feat(kobling): spuTrip kører en tur i flere trin — Connect kobler på, Afkobl kobler af, almindelige markører holder 10 s undervejs (v1.47.1.0)

This commit is contained in:
2026-09-28 17:15:49 +02:00
parent be043ac220
commit b57940a933
3 changed files with 97 additions and 37 deletions
+79 -32
View File
@@ -19,12 +19,13 @@ ADHitch.MARKER_PREFIXES = {
{prefix = "connect", action = "attach"},
{prefix = "kobl", action = "attach"},
}
ADHitch.TIMEOUT_REASON = {attach = "noAttachable", detach = "nothingToDetach"}
ADHitch.TIMEOUT_REASON = {attach = "noAttachable", detach = "nothingToDetach", arrive = "notArrived"}
ADHitch.ARRIVE_DISTANCE = 5 -- m fra markøren, AD standser traktoren tæt på waypointet
ADHitch.STILL_SPEED = 1 -- km/t
ADHitch.START_GRACE_MS = 3000 -- så længe må AD være om at komme i gang efter fetch/drop
ADHitch.ACT_TIMEOUT_MS = 8000 -- så længe forsøges kobling/afkobling efter ankomst
ADHitch.TICK_MS = 250
ADHitch.ROUTE_WAIT_MS = 10000 -- pause ved almindelige markører midt i en tur
-- ---- ren logik ----
@@ -52,12 +53,25 @@ function ADHitch.rearImplements(implements)
return rear
end
-- konsol-argumenter "Connect Bredal > Start" -> "Connect Bredal", "Start" (mål nil uden ">")
-- konsol-argumenter "Connect Bredal > Start > Afkobl Bredal > Start" -> {"Connect Bredal", "Start", ...}
function ADHitch.parseTrip(...)
local text = table.concat({...}, " ")
local first, second = text:match("^%s*(.-)%s*>%s*(.-)%s*$")
if first == nil then return (text:match("^%s*(.-)%s*$")), nil end
return first, second
local steps = {}
for part in (table.concat({...}, " ") .. ">"):gmatch("([^>]*)>") do
local name = part:match("^%s*(.-)%s*$")
if name ~= "" then table.insert(steps, name) end
end
return steps
end
-- markørnavn -> attach / detach / arrive (almindelig markør: bare køre dertil)
function ADHitch.stepAction(name)
return ADHitch.parseMarker(name) or "arrive"
end
-- pause efter et trin: ved almindelige markører undervejs holdes der, ikke efter sidste trin
function ADHitch.waitAfter(action, index, count)
if action == "arrive" and index < count then return ADHitch.ROUTE_WAIT_MS end
return 0
end
-- markers = {{name, id}} -> markøren med navnet (store/små bogstaver ligegyldigt)
@@ -203,19 +217,47 @@ function ADHitch.drop(adEnv, vehicle, markerId, onDone)
return start(adEnv, vehicle, markerId, "detach", onDone)
end
-- "Hent vogn og kør til": kør til Connect-markøren, kobl på, kør så med AD til målet.
function ADHitch.trip(adEnv, vehicle, connectId, destinationId, onDone)
return ADHitch.fetch(adEnv, vehicle, connectId, function(tractor, ok, detail)
if not ok then
if onDone ~= nil then onDone(tractor, false, detail) end
-- Tur: markørerne køres i rækkefølge. Connect = kobl på, Afkobl = kobl af, andre = kør dertil (og hold
-- ROUTE_WAIT_MS, hvis det ikke er sidste trin). Stopper ved første fejl. onDone(vehicle, ok, årsag) til sidst.
local waits = {} -- {vehicle, leftMs, continue}
function ADHitch.route(adEnv, vehicle, markerIds, onDone)
local function runStep(index)
if index > #markerIds then
Logging.info(ADHitch.LOG_PREFIX .. "'%s' er færdig med turen (%d trin)", vehicleName(vehicle), #markerIds)
if onDone ~= nil then pcall(onDone, vehicle, true) end
return
end
local destination = adEnv.ADGraphManager:getMapMarkerByWayPointId(destinationId)
ADFieldWork.startAd(adEnv, tractor, adEnv.AutoDrive.MODE_DRIVETO, destinationId)
Logging.info(ADHitch.LOG_PREFIX .. "'%s' kører med '%s' til '%s'", vehicleName(tractor), vehicleName(detail),
destination ~= nil and destination.name or tostring(destinationId))
if onDone ~= nil then onDone(tractor, true, detail) end
end)
local marker = adEnv.ADGraphManager:getMapMarkerByWayPointId(markerIds[index])
local action = ADHitch.stepAction(marker ~= nil and marker.name or nil)
start(adEnv, vehicle, markerIds[index], action, function(_, ok, detail)
if not ok then
Logging.warning(ADHitch.LOG_PREFIX .. "'%s' stopper turen ved trin %d", vehicleName(vehicle), index)
if onDone ~= nil then pcall(onDone, vehicle, false, detail) end
return
end
local waitMs = ADHitch.waitAfter(action, index, #markerIds)
if waitMs > 0 then
Logging.info(ADHitch.LOG_PREFIX .. "'%s' holder %d s ved '%s'", vehicleName(vehicle), waitMs / 1000,
marker ~= nil and marker.name or "?")
table.insert(waits, {vehicle = vehicle, leftMs = waitMs, continue = function() runStep(index + 1) end})
else
runStep(index + 1)
end
end)
end
runStep(1)
end
local function tickWaits(elapsed)
for i = #waits, 1, -1 do
local wait = waits[i]
wait.leftMs = wait.leftMs - elapsed
if wait.leftMs <= 0 then
table.remove(waits, i)
wait.continue()
end
end
end
-- Spilleren sender selv en traktor til en Connect-/Afkobl-markør med AD "Kør til": den kobles også.
@@ -231,8 +273,8 @@ local function watchManualTrips(adEnv)
end
end
local DONE_TEXT = {attach = "koblede '%s' på", detach = "koblede '%s' af"}
local FAIL_TEXT = {attach = "kunne ikke koble på", detach = "kunne ikke koble af"}
local DONE_TEXT = {attach = "koblede '%s' på", detach = "koblede '%s' af", arrive = "er fremme%s"}
local FAIL_TEXT = {attach = "kunne ikke koble på", detach = "kunne ikke koble af", arrive = "nåede ikke frem"}
local function finish(vehicle, job, ok, detail)
jobs[vehicle] = nil
@@ -246,7 +288,7 @@ local function finish(vehicle, job, ok, detail)
if job.onDone ~= nil then pcall(job.onDone, vehicle, ok, detail) end
end
local ACTIONS = {attach = ADHitch.tryAttach, detach = ADHitch.tryDetach}
local ACTIONS = {attach = ADHitch.tryAttach, detach = ADHitch.tryDetach, arrive = function() return true, "" end}
function ADHitch.tick(adEnv, dt)
if adEnv == nil or adEnv.ADGraphManager == nil then return end
@@ -254,8 +296,12 @@ function ADHitch.tick(adEnv, dt)
if tickTimer < ADHitch.TICK_MS then return end
local elapsed = tickTimer
tickTimer = 0
tickWaits(elapsed)
watchManualTrips(adEnv)
for vehicle, job in pairs(jobs) do
-- kopi: et færdigt trin starter næste trin (nyt job på samme maskine) midt i løkken
local current = {}
for vehicle, job in pairs(jobs) do current[vehicle] = job end
for vehicle, job in pairs(current) do
local succeeded, detail = false, nil
if job.state == "acting" then
succeeded, detail = ACTIONS[job.action](vehicle)
@@ -291,26 +337,27 @@ function ADHitch:consoleDetach()
return "spuDetach: intet koblet af (" .. tostring(detail) .. ")"
end
-- "spuTrip Connect Bredal > Start": maskinen spilleren sidder i henter vognen og kører til målet (spilleren
-- kan blive siddende; AD kører også med spilleren i førerhuset).
-- "spuTrip Connect Bredal > Start > Afkobl Bredal > Start": maskinen spilleren sidder i kører turen
-- (spilleren kan blive siddende; AD kører også med spilleren i førerhuset).
function ADHitch:consoleTrip(...)
local vehicle = currentVehicle()
if vehicle == nil then return "spuTrip: sæt dig i en traktor først" end
local adEnv = ADFieldSilos ~= nil and ADFieldSilos.adEnv or nil
if adEnv == nil then return "spuTrip: AutoDrive er ikke klar endnu" end
local connectName, destinationName = ADHitch.parseTrip(...)
local markers = adEnv.ADGraphManager:getMapMarkers()
local connect, destination = ADHitch.findMarker(markers, connectName), ADHitch.findMarker(markers, destinationName)
if connect == nil or ADHitch.parseMarker(connect.name) ~= "attach" then
return "spuTrip: ukendt Connect-markør '" .. tostring(connectName) .. "'"
local names = ADHitch.parseTrip(...)
if #names == 0 then return "spuTrip: brug fx spuTrip Connect Bredal > Start > Afkobl Bredal > Start" end
local markers, ids = adEnv.ADGraphManager:getMapMarkers(), {}
for _, name in ipairs(names) do
local marker = ADHitch.findMarker(markers, name)
if marker == nil then return "spuTrip: ukendt markør '" .. name .. "'" end
table.insert(ids, marker.id)
end
if destination == nil then return "spuTrip: ukendt mål '" .. tostring(destinationName) .. "' (brug: spuTrip Connect Bredal > Start)" end
ADHitch.trip(adEnv, vehicle, connect.id, destination.id)
return "spuTrip: " .. vehicleName(vehicle) .. " henter ved '" .. connect.name .. "' og kører til '" .. destination.name .. "'"
ADHitch.route(adEnv, vehicle, ids)
return "spuTrip: " .. vehicleName(vehicle) .. " kører " .. table.concat(names, " > ")
end
if addConsoleCommand ~= nil then
addConsoleCommand("spuConnect", "Kobler nærmeste redskab på den maskine du sidder i", "consoleConnect", ADHitch)
addConsoleCommand("spuTrip", "Hent vogn og kør: spuTrip Connect Bredal > Start", "consoleTrip", ADHitch)
addConsoleCommand("spuTrip", "Kør en tur: spuTrip Connect Bredal > Start > Afkobl Bredal > Start", "consoleTrip", ADHitch)
addConsoleCommand("spuDetach", "Kobler redskaberne bag den maskine du sidder i af", "consoleDetach", ADHitch)
end