feat: autoload-bil løsner stropperne 25 m før aflæsningsmålet (ladet passerer triggeren før markøren) (v1.12.11.0)

This commit is contained in:
2026-09-23 15:02:32 +02:00
parent a6e17d4f36
commit 0d1e82983a
3 changed files with 87 additions and 1 deletions
+53
View File
@@ -25,6 +25,10 @@ ADOutbound.NOTIFICATION_MS = 8000
-- spawnet, forkert farm, ...): kilden udelukkes for varen i EMPTY_SOURCE_TTL_MS og turen afsluttes. -- spawnet, forkert farm, ...): kilden udelukkes for varen i EMPTY_SOURCE_TTL_MS og turen afsluttes.
ADOutbound.EMPTY_SOURCE_MS = 30000 ADOutbound.EMPTY_SOURCE_MS = 30000
ADOutbound.EMPTY_SOURCE_TTL_MS = 300000 ADOutbound.EMPTY_SOURCE_TTL_MS = 300000
-- Autoload-bil på vej til aflæsning: stropperne løsnes så mange meter FØR markøren. Markøren står
-- hvor næsen stopper, og en lastbils lad har passeret salgstriggeren dér; AutoDrive løsner selv
-- først ved markøren ("AL unload = center"), hvilket er for sent for en lastbil.
ADOutbound.UNSTRAP_BEFORE_M = 25
-- køretøj -> {run, trip, sources, queue, visited, current, lastFill, noProgressMs, spawn, done} -- køretøj -> {run, trip, sources, queue, visited, current, lastFill, noProgressMs, spawn, done}
local trips = setmetatable({}, {__mode = "k"}) local trips = setmetatable({}, {__mode = "k"})
@@ -570,6 +574,43 @@ function ADOutbound.beforeLoadUpdate(adEnv, task, dt)
return false return false
end end
local function distanceToWayPoint(adEnv, vehicle, wayPointId)
local wayPoint = adEnv.ADGraphManager:getWayPointById(wayPointId)
if wayPoint == nil or vehicle.rootNode == nil then
return nil
end
local x, _, z = getWorldTranslation(vehicle.rootNode)
local dx, dz = wayPoint.x - x, wayPoint.z - z
return math.sqrt(dx * dx + dz * dz)
end
-- Aflæsningskørsel (UnloadAtDestinationTask.update): autoload-bil med tur -> stropper af
-- UNSTRAP_BEFORE_M før målet, én gang pr. tur. Ændrer aldrig opgaven (returnerer altid false).
function ADOutbound.beforeUnloadUpdate(adEnv, task, dt)
local vehicle = task.vehicle
local state = trips[vehicle]
if state == nil or state.unstrapped or task.destinationID ~= state.trip.targetWayPointId then
return false
end
local _, hasAutoload = getVehicleCapacity(adEnv, vehicle)
if not hasAutoload then
state.unstrapped = true
return false
end
local distance = distanceToWayPoint(adEnv, vehicle, task.destinationID)
if distance == nil or distance > ADOutbound.UNSTRAP_BEFORE_M then
return false
end
state.unstrapped = true
for _, unit in ipairs(task.trailers or {}) do
if unit.setAllTensionBeltsActive ~= nil then
pcall(unit.setAllTensionBeltsActive, unit, false, false)
end
end
Logging.info(ADOutbound.LOG_PREFIX .. "'%s': stropper løsnet %.0f m før %s", tostring(vehicle:getName()), distance, tostring(state.trip.targetName))
return false
end
-- true = opsamlingsrunden fortsætter til næste kilde (original finished springes over). -- true = opsamlingsrunden fortsætter til næste kilde (original finished springes over).
function ADOutbound.beforeLoadFinished(adEnv, task) function ADOutbound.beforeLoadFinished(adEnv, task)
local vehicle = task.vehicle local vehicle = task.vehicle
@@ -661,4 +702,16 @@ function ADOutbound.install(adEnv)
return originalFinished(self) return originalFinished(self)
end end
end end
local unloadTask = adEnv.UnloadAtDestinationTask
if unloadTask ~= nil and unloadTask.update ~= nil then
local originalUnloadUpdate = unloadTask.update
unloadTask.update = function(self, dt)
local okUnload, err = pcall(ADOutbound.beforeUnloadUpdate, adEnv, self, dt)
if not okUnload then
Logging.warning(ADOutbound.LOG_PREFIX .. "fejl ved strop-løsning, AutoDrive fortsætter selv: %s", tostring(err))
end
return originalUnloadUpdate(self, dt)
end
end
end end
+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.12.10.0</version> <version>1.12.11.0</version>
<title> <title>
<en>AD Smart Pickup</en> <en>AD Smart Pickup</en>
</title> </title>
+33
View File
@@ -72,6 +72,7 @@ local adEnv = {
AutoDriveMessageEvent = {sendMessageOrNotification = function(vehicle, kind, text, duration, ...) table.insert(notifications, {vehicle = vehicle, kind = kind, text = string.format(text, ...)}) end}, AutoDriveMessageEvent = {sendMessageOrNotification = function(vehicle, kind, text, duration, ...) table.insert(notifications, {vehicle = vehicle, kind = kind, text = string.format(text, ...)}) end},
ADMessagesManager = {messageTypes = {INFO = 1, WARN = 2, ERROR = 3}}, ADMessagesManager = {messageTypes = {INFO = 1, WARN = 2, ERROR = 3}},
LoadAtDestinationTask = {STATE_DRIVING = 2, update = function() end, finished = function(self) self.finishedCalls = (self.finishedCalls or 0) + 1 end}, LoadAtDestinationTask = {STATE_DRIVING = 2, update = function() end, finished = function(self) self.finishedCalls = (self.finishedCalls or 0) + 1 end},
UnloadAtDestinationTask = {STATE_DRIVING = 2, update = function() end},
} }
local function newVehicle(name, x, z, capacity, ual) local function newVehicle(name, x, z, capacity, ual)
@@ -438,6 +439,35 @@ check("O20 kapacitet ukendt for pallebil", input20.capacity, nil)
check("O20 har autoload", input20.hasAutoload, true) check("O20 har autoload", input20.hasAutoload, true)
check("O20 turen planlægges alligevel", ADOutboundPlanner.plan(input20) ~= nil, true) check("O20 turen planlægges alligevel", ADOutboundPlanner.plan(input20) ~= nil, true)
-- O21: autoload-bil på vej til aflæsning: stropperne løsnes UNSTRAP_BEFORE_M før målet (ladet passerer
-- triggeren før markøren), kun én gang pr. tur, og aldrig for tipvogne
local v21 = newVehicle("Dragon3", 0, 0, 1, true)
v21.carriable = {}
v21.trailers[1].setAllTensionBeltsActive = function(self, active) self.beltsActive = active end
runs[v21] = outboundRun(22, {3}, {{fillType = "STRAW_BASKET", policy = "sell"}})
sources[3].stored[BASKET] = 3
quotes["selling station"][BASKET] = {percent = 95, price = 1}
ADOutbound.choosePickup(adEnv, v21)
check("O21 tur mod salgssted", v21.ad.stateModule.secondMarkerId, 10)
local unloadTask21 = {vehicle = v21, destinationID = 10, trailers = v21.trailers}
v21.rootNode = {x = 200 - 40, z = 0} -- 40 m fra markør 10 (x=200)
ADOutbound.beforeUnloadUpdate(adEnv, unloadTask21, 16)
check("O21 40 m: stropper stadig på", v21.trailers[1].beltsActive, nil)
v21.rootNode = {x = 200 - 20, z = 0}
ADOutbound.beforeUnloadUpdate(adEnv, unloadTask21, 16)
check("O21 20 m: stropper løsnet", v21.trailers[1].beltsActive, false)
v21.trailers[1].beltsActive = nil
ADOutbound.beforeUnloadUpdate(adEnv, unloadTask21, 16)
check("O21 kun én gang", v21.trailers[1].beltsActive, nil)
local v21b = newVehicle("Tip", 0, 0, 20000)
v21b.trailers[1].setAllTensionBeltsActive = function(self, active) self.beltsActive = active end
runs[v21b] = outboundRun(23, {1}, {{fillType = "SUGAR", policy = "sell"}})
quotes["selling station"][SUGAR].percent = 92
ADOutbound.choosePickup(adEnv, v21b)
v21b.rootNode = {x = 195, z = 0}
ADOutbound.beforeUnloadUpdate(adEnv, {vehicle = v21b, destinationID = 10, trailers = v21b.trailers}, 16)
check("O21 tipvogn: ingen stropper", v21b.trailers[1].beltsActive, nil)
-- O10: install wrapper: fejl i hook stopper ikke AD -- O10: install wrapper: fejl i hook stopper ikke AD
local calls = {} local calls = {}
adEnv.LoadAtDestinationTask.update = function(self, dt) calls.update = (calls.update or 0) + 1 end adEnv.LoadAtDestinationTask.update = function(self, dt) calls.update = (calls.update or 0) + 1 end
@@ -448,6 +478,9 @@ adEnv.LoadAtDestinationTask.update(newTask(vX, 1), 16)
check("O10 original update kaldt", calls.update, 1) check("O10 original update kaldt", calls.update, 1)
adEnv.LoadAtDestinationTask.finished(newTask(vX, 1)) adEnv.LoadAtDestinationTask.finished(newTask(vX, 1))
check("O10 original finished kaldt", calls.finished, 1) check("O10 original finished kaldt", calls.finished, 1)
adEnv.UnloadAtDestinationTask.update = function(self, dt) calls.unload = (calls.unload or 0) + 1 end
ADOutbound.install(adEnv)
check("O10 unload-wrap ikke installeret dobbelt", adEnv.UnloadAtDestinationTask.update ~= nil, true)
print(failures == 0 and "\nALLE TESTS OK" or ("\n" .. failures .. " FEJL")) print(failures == 0 and "\nALLE TESTS OK" or ("\n" .. failures .. " FEJL"))
os.exit(failures == 0 and 0 or 1) os.exit(failures == 0 and 0 or 1)