fix(markarbejde): maskiner over 60 m fra AD-vejnettet sendes ikke ud (AutoDrive 'Could not calculate path'); ingen genforsøg når AD stopper uden at flytte sig (v1.33.2.0)

This commit is contained in:
2026-09-26 22:00:45 +02:00
parent f9d875fc3e
commit 6a835b9efb
2 changed files with 53 additions and 2 deletions
+52 -1
View File
@@ -17,6 +17,11 @@ ADFieldWork.WINDROW_MEASURE_MS = 10000
ADFieldWork.NO_RIG_RETRY_MS = 30000 ADFieldWork.NO_RIG_RETRY_MS = 30000
-- AutoDrive der stopper før markøren startes igen så mange gange, før turen opgives -- AutoDrive der stopper før markøren startes igen så mange gange, før turen opgives
ADFieldWork.DRIVE_RETRIES = 2 ADFieldWork.DRIVE_RETRIES = 2
-- længere fra AD-vejnettet end dette kan AutoDrive ikke finde en rute ("Could not calculate path", in-game 26/9:
-- kultivatoren stod 666 m fra nærmeste waypoint); sådan en maskine sendes ikke ud
ADFieldWork.MAX_OFF_NETWORK = 60
-- flyttede køretøjet sig mindre end dette før AD stoppede, fandt AD ingen rute — ingen genforsøg
ADFieldWork.NO_MOVE_DISTANCE = 5
ADFieldWork.REFILL_ROLES = {seeder = true, fertilizer = true, limer = true, weeder = true} ADFieldWork.REFILL_ROLES = {seeder = true, fertilizer = true, limer = true, weeder = true}
local function log(...) ADFieldJobs.log(...) end local function log(...) ADFieldJobs.log(...) end
@@ -263,6 +268,29 @@ local function fail(fieldId, text)
end end
-- Hvad et sæt skal kunne ud over rollen (afgrøde, frø, ukrudtets størrelse). -- Hvad et sæt skal kunne ud over rollen (afgrøde, frø, ukrudtets størrelse).
-- Afstand fra (x, z) til nærmeste AD-waypoint (nil hvis vejnettet ikke kan læses).
function ADFieldWork.distanceToNetwork(adEnv, x, z)
-- gemmes 30 s pr. 10 m-celle (15.000 waypoints pr. opslag)
if ADCacheGet ~= nil then
local key = string.format("%d:%d", math.floor(x / 10), math.floor(z / 10))
return ADCacheGet("networkDistance", key, 30000, function() return ADFieldWork.distanceToNetworkUncached(adEnv, x, z) end)
end
return ADFieldWork.distanceToNetworkUncached(adEnv, x, z)
end
function ADFieldWork.distanceToNetworkUncached(adEnv, x, z)
local ok, best = pcall(function()
local wayPoints = adEnv.ADGraphManager:getWayPoints()
local bestD = math.huge
for _, wp in pairs(wayPoints or {}) do
local d = (wp.x - x) ^ 2 + (wp.z - z) ^ 2
if d < bestD then bestD = d end
end
return math.sqrt(bestD)
end)
return ok and best ~= math.huge and best or nil
end
local function acceptFor(field, info, role) local function acceptFor(field, info, role)
if role == "harvester" then if role == "harvester" then
local fruit = info.fruitIndex local fruit = info.fruitIndex
@@ -329,7 +357,18 @@ function ADFieldWork.dispatch(adEnv, field, info, decision)
for fieldId, other in pairs(ADFieldJobs.state.fields) do rigIdsByField[fieldId] = other.plan ~= nil and other.plan.rigIds or nil end for fieldId, other in pairs(ADFieldJobs.state.fields) do rigIdsByField[fieldId] = other.plan ~= nil and other.plan.rigIds or nil end
local candidates = ADFieldFleet.filterDedicated(ADFieldWork.getRigs(adEnv), field.id, role, rigIdsByField) local candidates = ADFieldFleet.filterDedicated(ADFieldWork.getRigs(adEnv), field.id, role, rigIdsByField)
local required = ADFieldModel.requiredWidth(field, role) local required = ADFieldModel.requiredWidth(field, role)
local accept = acceptFor(field, info, role) local roleAccept = acceptFor(field, info, role)
-- kun maskiner AutoDrive kan køre fra: tæt på vejnettet
local offNetwork = {}
local accept = function(candidate)
if roleAccept ~= nil and not roleAccept(candidate) then return false end
local d = candidate.x ~= nil and ADFieldWork.distanceToNetwork(adEnv, candidate.x, candidate.z) or nil
if d ~= nil and d > ADFieldWork.MAX_OFF_NETWORK then
table.insert(offNetwork, string.format("'%s' %.0f m", tostring(candidate.label), d))
return false
end
return true
end
local rigs, why, args local rigs, why, args
if (decision.count or 1) > 1 then if (decision.count or 1) > 1 then
rigs, why, args = ADFieldFleet.pickMany(candidates, role, decision.count, info.x, info.z, required, accept) rigs, why, args = ADFieldFleet.pickMany(candidates, role, decision.count, info.x, info.z, required, accept)
@@ -339,6 +378,12 @@ 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
if #offNetwork > 0 and (why == "cannotDo" or why == "noRig") then
-- de eneste med rollen står uden for AD-vejnettet
note(field.id, {reason = {text = string.format("ingen %s kan køre til %s — står for langt fra AutoDrive-vejnettet (%s)",
tostring(role), tostring(info.markerName), table.concat(offNetwork, ", "))}, retryAt = now() + ADFieldWork.NO_RIG_RETRY_MS})
return
end
note(field.id, {reason = {key = "spu_field_reason_" .. tostring(why), role = role, args = args}, retryAt = now() + ADFieldWork.NO_RIG_RETRY_MS}) 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
@@ -357,6 +402,7 @@ function ADFieldWork.dispatch(adEnv, field, info, decision)
fail(field.id, string.format("'%s' er tom for %s og der er ingen påfyldning med AutoDrive-markør — fyld den op", rig.label, fillTypeName(refill.fillType))) fail(field.id, string.format("'%s' er tom for %s og der er ingen påfyldning med AutoDrive-markør — fyld den op", rig.label, fillTypeName(refill.fillType)))
return return
end end
assignment.startX, assignment.startZ = rig.x, rig.z
ADFieldJobs.state.assignments[rig.id] = assignment ADFieldJobs.state.assignments[rig.id] = assignment
if refill ~= nil and refill.empty then if refill ~= nil and refill.empty then
-- AutoDrive LOAD: påfyldningen (2. markør), fyld op, videre til F-markøren (1.) — så Courseplay -- AutoDrive LOAD: påfyldningen (2. markør), fyld op, videre til F-markøren (1.) — så Courseplay
@@ -784,6 +830,11 @@ function ADFieldWork.follow(adEnv, assignment)
local distance = wayPoint ~= nil and math.sqrt((wayPoint.x - x) ^ 2 + (wayPoint.z - z) ^ 2) or math.huge local distance = wayPoint ~= nil and math.sqrt((wayPoint.x - x) ^ 2 + (wayPoint.z - z) ^ 2) or math.huge
if distance <= ADFieldWork.ARRIVE_DISTANCE then if distance <= ADFieldWork.ARRIVE_DISTANCE then
beginWork(adEnv, field, info, assignment) beginWork(adEnv, field, info, assignment)
elseif assignment.startX ~= nil and math.sqrt((x - assignment.startX) ^ 2 + (z - assignment.startZ) ^ 2) < ADFieldWork.NO_MOVE_DISTANCE
and (assignment.driveRetries or 0) >= 1 then
-- AD startede og stoppede uden at flytte sig (to gange): ingen rute — genforsøg hjælper ikke
ADFieldWork.release(assignment)
fail(assignment.fieldId, string.format("AutoDrive fandt ingen rute fra '%s' til %s — står den uden for vejnettet?", ADRuns.vehicleLabel(vehicle), tostring(info ~= nil and info.markerName or "?")))
elseif assignment.drive ~= nil and (assignment.driveRetries or 0) < ADFieldWork.DRIVE_RETRIES then elseif assignment.drive ~= nil and (assignment.driveRetries or 0) < ADFieldWork.DRIVE_RETRIES then
-- AutoDrive stoppede undervejs (spilleren byggede, trafik, ...): kør videre i stedet for at opgive -- AutoDrive stoppede undervejs (spilleren byggede, trafik, ...): kør videre i stedet for at opgive
assignment.driveRetries = (assignment.driveRetries or 0) + 1 assignment.driveRetries = (assignment.driveRetries or 0) + 1
+1 -1
View File
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8" standalone="no"?> <?xml version="1.0" encoding="utf-8" standalone="no"?>
<modDesc descVersion="107"> <modDesc descVersion="107">
<author>masterdraco</author> <author>masterdraco</author>
<version>1.33.1.0</version> <version>1.33.2.0</version>
<title> <title>
<en>AD Smart Pickup</en> <en>AD Smart Pickup</en>
</title> </title>