fix(marker): påfyldning finder selv læssestation m. varen og AD-markør (AD's automaticPickupTarget er slået fra); tom sæt = ikke færdig; 30 s backoff når sæt mangler

Review-fund 26/9 (CRITICAL): setAutomaticPickupTarget er no-op i AutoDrive (AutoDrive.automaticPickupTarget = false),
så LOAD-mode ville køre til F-markøren og hænge. (MEDIUM): ingen backoff ved manglende sæt.
This commit is contained in:
2026-09-26 00:13:01 +02:00
parent b1a65929a7
commit 944e61d1a8
3 changed files with 69 additions and 12 deletions
+13
View File
@@ -176,6 +176,19 @@ function ADCpBridge.getRefillFillType(vehicle)
return nil return nil
end end
-- Hvor meget af påfyldningsvaren sættet har tilbage (liter, alle fyldenheder med varen).
function ADCpBridge.getRefillLevel(vehicle, fillType)
local total = 0
for _, object in ipairs(collect(vehicle)) do
pcall(function()
for index, unit in ipairs(object.spec_fillUnit ~= nil and object.spec_fillUnit.fillUnits or {}) do
if unit.fillType == fillType then total = total + (object:getFillUnitFillLevel(index) or 0) end
end
end)
end
return total
end
-- Stop køretøjets AI-job (Courseplay/hjælper). -- Stop køretøjets AI-job (Courseplay/hjælper).
function ADCpBridge.stop(vehicle) function ADCpBridge.stop(vehicle)
pcall(function() pcall(function()
+49 -8
View File
@@ -13,6 +13,9 @@ ADFieldWork.COURSE_WAIT_MS = 180000
ADFieldWork.PLAYER_DRIVING_KMH = 3 ADFieldWork.PLAYER_DRIVING_KMH = 3
-- riven skal være udfoldet og i gang, før nedlægningsområdet måles -- riven skal være udfoldet og i gang, før nedlægningsområdet måles
ADFieldWork.WINDROW_MEASURE_MS = 10000 ADFieldWork.WINDROW_MEASURE_MS = 10000
-- mangler der sæt, prøves igen efter så lang tid (ikke hvert sekund over hele flåden)
ADFieldWork.NO_RIG_RETRY_MS = 30000
ADFieldWork.REFILL_ROLES = {seeder = true, fertilizer = true, limer = true, weeder = true}
local function log(...) ADFieldJobs.log(...) end local function log(...) ADFieldJobs.log(...) end
local function note(...) ADFieldJobs.note(...) end local function note(...) ADFieldJobs.note(...) end
@@ -298,7 +301,7 @@ function ADFieldWork.dispatch(adEnv, field, info, decision)
rigs = rig ~= nil and {rig} or nil rigs = rig ~= nil and {rig} or nil
end end
if rigs == nil then if rigs == nil then
note(field.id, {reason = {key = "spu_field_reason_" .. tostring(why), role = role, args = args}}) note(field.id, {reason = {key = "spu_field_reason_" .. tostring(why), role = role, args = args}, retryAt = now() + ADFieldWork.NO_RIG_RETRY_MS})
return return
end end
local count = #rigs local count = #rigs
@@ -340,19 +343,50 @@ local function prepareCollector(adEnv, field, info, assignment)
return true return true
end end
-- Påfyldning undervejs (såmaskine/sprøjte/spreder): AutoDrive LOAD med automatisk påfyldningsmål og -- Nærmeste påfyldning af varen: en læssestation gården har adgang til, med varen på lager, en AutoDrive-
-- hjælper = Courseplay. Når CP melder tom (onCpEmpty), kører AD til nærmeste påfyldning af varen, fylder -- markør ved triggeren og vej fra traktoren. (AutoDrives eget "automatiske påfyldningsmål" er slået fra i
-- op, kører tilbage til F-markøren og genstarter CP. Courseplay og AutoDrive er bygget til netop dette. -- AutoDrive — AutoDrive.automaticPickupTarget = false — så vi finder stedet selv, som silovalget.)
function ADFieldWork.findRefillMarker(adEnv, vehicle, fillType, x, z)
local farmId = vehicle:getOwnerFarmId()
local best, bestDistance = nil, math.huge
local ok = pcall(function()
for _, station in pairs(g_currentMission.storageSystem:getLoadingStations()) do
local supported = station.getAISupportedFillTypes ~= nil and station:getAISupportedFillTypes() or {}
if g_currentMission.accessHandler:canFarmAccess(farmId, station) and supported[fillType]
and (station:getFillLevel(fillType, farmId) or 0) > 0 then
local wayPointId = adEnv.ADTriggerManager:getMarkerAtStation(station, vehicle, 10)
local wayPoint = wayPointId ~= nil and wayPointId > 0 and adEnv.ADGraphManager:getWayPointById(wayPointId) or nil
if wayPoint ~= nil then
local distance = (wayPoint.x - x) ^ 2 + (wayPoint.z - z) ^ 2
if distance < bestDistance and ADUnloadWait.hasRouteTo(adEnv, vehicle, wayPointId) then
best, bestDistance = wayPointId, distance
end
end
end
end
end)
return ok and best or nil
end
-- Påfyldning undervejs (såmaskine/sprøjte/spreder): AutoDrive LOAD med hjælper = Courseplay. Når CP melder
-- tom (onCpEmpty), kører AD til påfyldningen (2. markør), fylder op, kører tilbage til F-markøren (1. markør)
-- og genstarter CP. Findes ingen påfyldning, stopper sættet når det er tomt ("tom for …", se finish).
local function prepareRefill(adEnv, field, info, assignment) local function prepareRefill(adEnv, field, info, assignment)
local vehicle = assignment.vehicle local vehicle = assignment.vehicle
local fillType = ADCpBridge.getRefillFillType(vehicle) local fillType = ADCpBridge.getRefillFillType(vehicle)
if fillType == nil then return end if fillType == nil then return end
assignment.refillFillType = fillType
local name = g_fillTypeManager ~= nil and g_fillTypeManager:getFillTypeNameByIndex(fillType) or tostring(fillType)
local refillId = ADFieldWork.findRefillMarker(adEnv, vehicle, fillType, info.x, info.z)
if refillId == nil then
log(field.id, "ingen påfyldning af %s med AutoDrive-markør fundet — '%s' stopper når den er tom", tostring(name), ADRuns.vehicleLabel(vehicle))
return
end
local module = stateModule(vehicle) local module = stateModule(vehicle)
local ok = pcall(function() local ok = pcall(function()
module:setMode(adEnv.AutoDrive.MODE_LOAD) module:setMode(adEnv.AutoDrive.MODE_LOAD)
module:setFirstMarkerByWayPointId(info.markerId) module:setFirstMarkerByWayPointId(info.markerId)
module:setSecondMarkerByWayPointId(info.markerId) module:setSecondMarkerByWayPointId(refillId)
module:setAutomaticPickupTarget(true)
module:setFillType(fillType) module:setFillType(fillType)
module:setStartHelper(true) module:setStartHelper(true)
module.usedHelper = helperCp(adEnv) module.usedHelper = helperCp(adEnv)
@@ -361,8 +395,8 @@ local function prepareRefill(adEnv, field, info, assignment)
end) end)
if ok then if ok then
assignment.adHandlesEnd = true assignment.adHandlesEnd = true
local name = g_fillTypeManager ~= nil and g_fillTypeManager:getFillTypeNameByIndex(fillType) or tostring(fillType) local marker = adEnv.ADGraphManager:getMapMarkerByWayPointId(refillId)
log(field.id, "'%s' fyldes op med %s af AutoDrive når den er tom", ADRuns.vehicleLabel(vehicle), tostring(name)) log(field.id, "'%s' fyldes op med %s ved %s af AutoDrive når den er tom", ADRuns.vehicleLabel(vehicle), tostring(name), tostring(marker ~= nil and marker.name or refillId))
end end
end end
@@ -493,6 +527,13 @@ end
-- Sættet er færdigt: rest til lager (læsse-/aflæsningsvogn), ellers parkering. -- Sættet er færdigt: rest til lager (læsse-/aflæsningsvogn), ellers parkering.
local function finishAssignment(adEnv, assignment) local function finishAssignment(adEnv, assignment)
local vehicle = assignment.vehicle local vehicle = assignment.vehicle
-- tom såmaskine/sprøjte der ikke blev fyldt op: arbejdet er IKKE færdigt — marken må ikke gå videre
if assignment.refillFillType ~= nil and ADCpBridge.getRefillLevel(vehicle, assignment.refillFillType) <= 0 then
local name = g_fillTypeManager ~= nil and g_fillTypeManager:getFillTypeNameByIndex(assignment.refillFillType) or "?"
ADFieldWork.release(assignment)
fail(assignment.fieldId, string.format("'%s' er tom for %s — fyld op, så fortsætter marken", ADRuns.vehicleLabel(vehicle), tostring(name)))
return
end
log(assignment.fieldId, "%s '%s' færdig", assignment.role, ADRuns.vehicleLabel(vehicle)) log(assignment.fieldId, "%s '%s' færdig", assignment.role, ADRuns.vehicleLabel(vehicle))
-- læssevogn/påfyldte sæt parkeres af AutoDrive selv (onCpFinished med parkering sat) -- læssevogn/påfyldte sæt parkeres af AutoDrive selv (onCpFinished med parkering sat)
local park = not assignment.adHandlesEnd and parkMarkerId(adEnv, vehicle) or nil local park = not assignment.adHandlesEnd and parkMarkerId(adEnv, vehicle) or nil
+7 -4
View File
@@ -94,9 +94,12 @@ Afgrøde "Samme som høstet", Tromle Ja. Kalk Ja.
- [ ] **5.3 Såning.** Såmaskinen sættes til afgrøden (`setSeedIndex`), og den rigtige afgrøde spirer. - [ ] **5.3 Såning.** Såmaskinen sættes til afgrøden (`setSeedIndex`), og den rigtige afgrøde spirer.
- [ ] **5.4 Ude af såperioden.** Afgrøde der ikke kan sås nu → status "<afgrøde> kan ikke sås i denne - [ ] **5.4 Ude af såperioden.** Afgrøde der ikke kan sås nu → status "<afgrøde> kan ikke sås i denne
periode", ingen udsendelse. periode", ingen udsendelse.
- [ ] **5.5 Tom for frø / påfyldning.** Såmaskine med lidt frø: når den er tom midt på marken, kører - [ ] **5.5 Tom for frø / påfyldning.** Såmaskine med lidt frø. Moden leder efter en læssestation med frø
AutoDrive selv til nærmeste frø-påfyldning, fylder op, kører tilbage, og Courseplay fortsætter. på lager og en AutoDrive-markør ved triggeren (fx en silo/big-bag-station med SEEDS).
Log: `… fyldes op med SEEDS af AutoDrive når den er tom`. (Kræver et sted AutoDrive kan læsse frø.) - Findes den: log `… fyldes op med SEEDS ved <markør> af AutoDrive når den er tom`. Når den er tom
midt på marken, kører AutoDrive derhen, fylder op, kører tilbage, og Courseplay fortsætter.
- Findes den ikke: log `ingen påfyldning af SEEDS med AutoDrive-markør fundet …`. Når den er tom:
rød besked `'…' er tom for SEEDS — fyld op, så fortsætter marken`, og marken går IKKE videre.
- [ ] **5.6 Bar mark alene.** Vælg en bar mark (stub/pløjet) → **Start nu** → kun klargøring/såning. - [ ] **5.6 Bar mark alene.** Vælg en bar mark (stub/pløjet) → **Start nu** → kun klargøring/såning.
## 6. Pleje mens afgrøden vokser ## 6. Pleje mens afgrøden vokser
@@ -141,5 +144,5 @@ Afgrøde "Samme som høstet", Tromle Ja. Kalk Ja.
| Combine-unloader | stationsvalg ud fra silovalget | `ingen aflæsningsstation Courseplay kan bruge` | | Combine-unloader | stationsvalg ud fra silovalget | `ingen aflæsningsstation Courseplay kan bruge` |
| Multi-tool | `multiTools` + `laneOffset` + `Course:setPosition` | Begge maskiner kører samme bane | | Multi-tool | `multiTools` + `laneOffset` + `Course:setPosition` | Begge maskiner kører samme bane |
| Sideriver | fortegn på forskydningen | Læssevognen kører ved siden af skåret | | Sideriver | fortegn på forskydningen | Læssevognen kører ved siden af skåret |
| Påfyldning | AutoDrive LOAD med automatisk påfyldningsmål | Sættet står stille når det er tomt | | Påfyldning | AutoDrive LOAD til den læssestation moden fandt (AutoDrives eget automatiske mål er slået fra i AutoDrive) | Sættet står ved påfyldningen og læsser ikke, eller kører ikke tilbage |
| Ukrudt | `weedSystem`-værdi ≥ 2 = tæt | Ukrudtsbehandling uden ukrudt, eller aldrig | | Ukrudt | `weedSystem`-værdi ≥ 2 = tæt | Ukrudtsbehandling uden ukrudt, eller aldrig |