feat(marker): halm efter høst — hakkes, samles op til silo eller presses til baller + ballesamler (CP BALE_FINDER); græsvalg også ved græs-mål
This commit is contained in:
@@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
ADCpBridge = {}
|
ADCpBridge = {}
|
||||||
|
|
||||||
ADCpBridge.SPECS = {"spec_mower", "spec_tedder", "spec_windrower", "spec_forageWagon", "spec_combine",
|
ADCpBridge.SPECS = {"spec_mower", "spec_tedder", "spec_windrower", "spec_forageWagon", "spec_combine", "spec_baler",
|
||||||
"spec_sowingMachine", "spec_cultivator", "spec_plow", "spec_roller", "spec_weeder", "spec_mulcher"}
|
"spec_sowingMachine", "spec_cultivator", "spec_plow", "spec_roller", "spec_weeder", "spec_mulcher"}
|
||||||
|
|
||||||
-- Sprøjtens/sprederens fyld -> rolle (tom sprøjte har ingen rolle; den kan ikke sendes ud).
|
-- Sprøjtens/sprederens fyld -> rolle (tom sprøjte har ingen rolle; den kan ikke sendes ud).
|
||||||
@@ -86,6 +86,10 @@ function ADCpBridge.getSpecs(vehicle)
|
|||||||
local ok, can = pcall(vehicle.getCanStartCpCombineUnloader, vehicle)
|
local ok, can = pcall(vehicle.getCanStartCpCombineUnloader, vehicle)
|
||||||
specs.canUnload = ok and can == true or nil
|
specs.canUnload = ok and can == true or nil
|
||||||
end
|
end
|
||||||
|
if vehicle.getCanStartCpBaleFinder ~= nil then
|
||||||
|
local ok, can = pcall(vehicle.getCanStartCpBaleFinder, vehicle)
|
||||||
|
specs.canBaleCollect = ok and can == true or nil
|
||||||
|
end
|
||||||
return specs
|
return specs
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -189,6 +193,58 @@ function ADCpBridge.getRefillLevel(vehicle, fillType)
|
|||||||
return total
|
return total
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Halmskår bag mejetærskeren (Courseplays køretøjsindstilling strawSwath: 1 = fra/hakkes, 2 = til).
|
||||||
|
function ADCpBridge.setStrawSwath(vehicle, on)
|
||||||
|
return (pcall(function() vehicle:getCpSettings().strawSwath:setValue(on and 2 or 1) end))
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Ballesamler: Courseplays BALE_FINDER_CP (ballevogn eller Universal Autoload) samler markens baller.
|
||||||
|
function ADCpBridge.startBaleFinder(vehicle, fieldX, fieldZ, onDone)
|
||||||
|
if AIJobType == nil or AIJobType.BALE_FINDER_CP == nil then
|
||||||
|
return nil, "Courseplay (BALE_FINDER_CP) findes ikke"
|
||||||
|
end
|
||||||
|
local farmId = vehicle:getOwnerFarmId()
|
||||||
|
local job = g_currentMission.aiJobTypeManager:createJob(AIJobType.BALE_FINDER_CP)
|
||||||
|
if job == nil then return nil, "kunne ikke oprette ballesamler-job" end
|
||||||
|
pcall(function() job:applyCurrentState(vehicle, g_currentMission, farmId, false, false) end)
|
||||||
|
local params = job.cpJobParameters
|
||||||
|
if params ~= nil and params.fieldPosition ~= nil then pcall(function() params.fieldPosition:setPosition(fieldX, fieldZ) end) end
|
||||||
|
if params ~= nil and params.startPosition ~= nil then
|
||||||
|
local vx, _, vz = getWorldTranslation(vehicle.rootNode)
|
||||||
|
pcall(function() params.startPosition:setPosition(vx, vz) end)
|
||||||
|
end
|
||||||
|
pcall(function() job:setValues() end)
|
||||||
|
local handle = {cancelled = false, fired = false, finished = false}
|
||||||
|
local function finish(success, reason)
|
||||||
|
if handle.finished then return end
|
||||||
|
handle.finished = true
|
||||||
|
if not handle.cancelled then onDone(success, reason) end
|
||||||
|
end
|
||||||
|
local function startJob()
|
||||||
|
if handle.cancelled then return end
|
||||||
|
local valid, err = job:validate(farmId)
|
||||||
|
if not valid then return finish(false, "Courseplay: " .. tostring(err)) end
|
||||||
|
g_currentMission.aiSystem:startJob(job, farmId)
|
||||||
|
finish(true)
|
||||||
|
end
|
||||||
|
handle.onBoundary = function(_, success, message)
|
||||||
|
if handle.fired then return end
|
||||||
|
handle.fired = true
|
||||||
|
if not success then return finish(false, "Courseplay fandt ikke markgrænsen: " .. tostring(message)) end
|
||||||
|
startJob()
|
||||||
|
end
|
||||||
|
if job.registerFieldBoundaryDetectionCallback ~= nil then
|
||||||
|
job:registerFieldBoundaryDetectionCallback(handle, handle.onBoundary)
|
||||||
|
end
|
||||||
|
local isValid, isRunning, message = job:detectFieldBoundary()
|
||||||
|
if isValid and not isRunning then
|
||||||
|
startJob()
|
||||||
|
elseif not isRunning then
|
||||||
|
return nil, "Courseplay: " .. tostring(message)
|
||||||
|
end
|
||||||
|
return handle
|
||||||
|
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()
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ ADFieldFleet = {}
|
|||||||
-- plov, ikke aflæsningsvogn). sprayRole kommer fra sprøjtens/sprederens fyld (gødning/kalk/ukrudt).
|
-- plov, ikke aflæsningsvogn). sprayRole kommer fra sprøjtens/sprederens fyld (gødning/kalk/ukrudt).
|
||||||
ADFieldFleet.ROLE_SPECS = {
|
ADFieldFleet.ROLE_SPECS = {
|
||||||
{role = "harvester", spec = "spec_combine"},
|
{role = "harvester", spec = "spec_combine"},
|
||||||
|
{role = "baler", spec = "spec_baler"},
|
||||||
{role = "collector", spec = "spec_forageWagon"},
|
{role = "collector", spec = "spec_forageWagon"},
|
||||||
{role = "rake", spec = "spec_windrower"},
|
{role = "rake", spec = "spec_windrower"},
|
||||||
{role = "tedder", spec = "spec_tedder"},
|
{role = "tedder", spec = "spec_tedder"},
|
||||||
@@ -19,6 +20,7 @@ ADFieldFleet.ROLE_SPECS = {
|
|||||||
{role = "mulcher", spec = "spec_mulcher"},
|
{role = "mulcher", spec = "spec_mulcher"},
|
||||||
{role = "cultivator", spec = "spec_cultivator"},
|
{role = "cultivator", spec = "spec_cultivator"},
|
||||||
{role = "plow", spec = "spec_plow"},
|
{role = "plow", spec = "spec_plow"},
|
||||||
|
{role = "baleCollector", spec = "canBaleCollect"},
|
||||||
{role = "unloader", spec = "canUnload"},
|
{role = "unloader", spec = "canUnload"},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ ADFieldModel.ROLES = {
|
|||||||
mowing = "mower", tedding = "tedder", raking = "rake", collecting = "collector",
|
mowing = "mower", tedding = "tedder", raking = "rake", collecting = "collector",
|
||||||
harvesting = "harvester", mulching = "mulcher", liming = "limer", plowing = "plow",
|
harvesting = "harvester", mulching = "mulcher", liming = "limer", plowing = "plow",
|
||||||
cultivating = "cultivator", sowing = "seeder", rolling = "roller", weeding = "weeder",
|
cultivating = "cultivator", sowing = "seeder", rolling = "roller", weeding = "weeder",
|
||||||
fertilizing = "fertilizer",
|
fertilizing = "fertilizer", strawCollecting = "collector", baling = "baler", baleCollecting = "baleCollector",
|
||||||
}
|
}
|
||||||
ADFieldModel.HELPERS = {harvesting = "unloader"}
|
ADFieldModel.HELPERS = {harvesting = "unloader"}
|
||||||
ADFieldModel.CARE_STAGES = {fertilizing = true, weeding = true, careLiming = true}
|
ADFieldModel.CARE_STAGES = {fertilizing = true, weeding = true, careLiming = true}
|
||||||
@@ -42,8 +42,11 @@ KNOWN_STAGES.careLiming = true
|
|||||||
local DEFAULT_PLAN = {
|
local DEFAULT_PLAN = {
|
||||||
mode = "manual", product = "auto", rake = false, rigs = 1, unloaders = 1,
|
mode = "manual", product = "auto", rake = false, rigs = 1, unloaders = 1,
|
||||||
mulch = false, lime = true, soil = "auto", sow = false, sowFruit = "", roll = false,
|
mulch = false, lime = true, soil = "auto", sow = false, sowFruit = "", roll = false,
|
||||||
fertilize = true, weed = true, targetFruit = "", prepAfterMow = false,
|
fertilize = true, weed = true, targetFruit = "", prepAfterMow = false, straw = "chop",
|
||||||
}
|
}
|
||||||
|
local STRAW_VALUES = {chop = true, collect = true, bale = true}
|
||||||
|
-- halm-trin efter høst (mejetærskeren lægger skår når halmen skal bruges)
|
||||||
|
local STRAW_STAGES = {collect = {"strawCollecting"}, bale = {"baling", "baleCollecting"}}
|
||||||
local SOIL_VALUES = {auto = true, cultivate = true, plow = true, none = true}
|
local SOIL_VALUES = {auto = true, cultivate = true, plow = true, none = true}
|
||||||
local PRODUCTS = {auto = true, silage = true, hay = true, harvest = true}
|
local PRODUCTS = {auto = true, silage = true, hay = true, harvest = true}
|
||||||
|
|
||||||
@@ -116,6 +119,7 @@ function ADFieldModel.workStages(plan, kind, needs)
|
|||||||
local product = ADFieldModel.product(plan, kind)
|
local product = ADFieldModel.product(plan, kind)
|
||||||
if product == "harvest" then
|
if product == "harvest" then
|
||||||
local stages = {"harvesting"}
|
local stages = {"harvesting"}
|
||||||
|
for _, stage in ipairs(STRAW_STAGES[plan.straw or "chop"] or {}) do table.insert(stages, stage) end
|
||||||
for _, stage in ipairs(ADFieldModel.prepStages(plan, needs)) do table.insert(stages, stage) end
|
for _, stage in ipairs(ADFieldModel.prepStages(plan, needs)) do table.insert(stages, stage) end
|
||||||
return stages
|
return stages
|
||||||
end
|
end
|
||||||
@@ -168,9 +172,10 @@ function ADFieldModel.shouldStartBare(field, kind, plantableNow)
|
|||||||
return plantableNow == true
|
return plantableNow == true
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Krævet bredde for et sæt: kun læssevognen uden riv skal dække slåmaskinens baner.
|
-- Krævet bredde for et sæt: kun læssevognen uden riv skal dække slåmaskinens baner (halmskår ligger i
|
||||||
|
-- høsterens spor — der er breddekravet ligegyldigt).
|
||||||
function ADFieldModel.requiredWidth(field, role)
|
function ADFieldModel.requiredWidth(field, role)
|
||||||
if role == "collector" and not field.plan.rake then
|
if role == "collector" and not field.plan.rake and field.stage ~= "strawCollecting" then
|
||||||
return field.mowWidth
|
return field.mowWidth
|
||||||
end
|
end
|
||||||
return nil
|
return nil
|
||||||
@@ -178,6 +183,8 @@ end
|
|||||||
|
|
||||||
-- Hvilket tidligere kursus sættet skal køre: læssevognen følger skårene; de andre laver deres eget.
|
-- Hvilket tidligere kursus sættet skal køre: læssevognen følger skårene; de andre laver deres eget.
|
||||||
function ADFieldModel.courseSource(field, role)
|
function ADFieldModel.courseSource(field, role)
|
||||||
|
-- halm: læssevogn og presser kører høsterens kursus (skåret ligger i mejetærskerens spor)
|
||||||
|
if field.stage == "strawCollecting" or role == "baler" then return "harvester" end
|
||||||
if role ~= "collector" then return nil end
|
if role ~= "collector" then return nil end
|
||||||
return field.plan.rake and "rake" or "mower"
|
return field.plan.rake and "rake" or "mower"
|
||||||
end
|
end
|
||||||
@@ -247,6 +254,7 @@ local function freshCycle(copy)
|
|||||||
copy.mowWidth = nil
|
copy.mowWidth = nil
|
||||||
copy.mowVehicleId = nil
|
copy.mowVehicleId = nil
|
||||||
copy.rakeVehicleId = nil
|
copy.rakeVehicleId = nil
|
||||||
|
copy.harvestVehicleId = nil
|
||||||
copy.windrowOffset = nil
|
copy.windrowOffset = nil
|
||||||
copy.careRuns = {}
|
copy.careRuns = {}
|
||||||
end
|
end
|
||||||
@@ -276,7 +284,7 @@ function ADFieldModel.advance(field, needs)
|
|||||||
local stages = ADFieldModel.workStages(field.plan, field.kind, needs)
|
local stages = ADFieldModel.workStages(field.plan, field.kind, needs)
|
||||||
copy.stage = "done"
|
copy.stage = "done"
|
||||||
local passed = false
|
local passed = false
|
||||||
local order = {"mowing", "tedding", "raking", "collecting", "harvesting", "mulching", "liming", "plowing", "cultivating", "sowing", "rolling"}
|
local order = {"mowing", "tedding", "raking", "collecting", "harvesting", "strawCollecting", "baling", "baleCollecting", "mulching", "liming", "plowing", "cultivating", "sowing", "rolling"}
|
||||||
local rank = {}
|
local rank = {}
|
||||||
for index, stage in ipairs(order) do rank[stage] = index end
|
for index, stage in ipairs(order) do rank[stage] = index end
|
||||||
for _, stage in ipairs(stages) do
|
for _, stage in ipairs(stages) do
|
||||||
@@ -303,7 +311,7 @@ end
|
|||||||
|
|
||||||
-- Vejrfølsomme trin: afgrøde og skår skal være tørre (høst, slåning, vending, rivning, hø-opsamling).
|
-- Vejrfølsomme trin: afgrøde og skår skal være tørre (høst, slåning, vending, rivning, hø-opsamling).
|
||||||
-- Jordbehandling, såning, pleje og ensilage-opsamling kan køre i regn.
|
-- Jordbehandling, såning, pleje og ensilage-opsamling kan køre i regn.
|
||||||
local WEATHER_STAGES = {harvesting = true, mowing = true, tedding = true, raking = true}
|
local WEATHER_STAGES = {harvesting = true, mowing = true, tedding = true, raking = true, strawCollecting = true, baling = true}
|
||||||
function ADFieldModel.isWeatherSensitive(stage, plan, kind)
|
function ADFieldModel.isWeatherSensitive(stage, plan, kind)
|
||||||
if WEATHER_STAGES[stage] then return true end
|
if WEATHER_STAGES[stage] then return true end
|
||||||
return stage == "collecting" and ADFieldModel.product(plan, kind or "mowable") == "hay"
|
return stage == "collecting" and ADFieldModel.product(plan, kind or "mowable") == "hay"
|
||||||
@@ -423,11 +431,12 @@ function ADFieldModel.toRecord(field)
|
|||||||
rigs = plan.rigs, unloaders = plan.unloaders, mulch = flag(plan.mulch), lime = flag(plan.lime),
|
rigs = plan.rigs, unloaders = plan.unloaders, mulch = flag(plan.mulch), lime = flag(plan.lime),
|
||||||
soil = plan.soil, sow = flag(plan.sow), sowFruit = plan.sowFruit or "", roll = flag(plan.roll),
|
soil = plan.soil, sow = flag(plan.sow), sowFruit = plan.sowFruit or "", roll = flag(plan.roll),
|
||||||
fertilize = flag(plan.fertilize), weed = flag(plan.weed),
|
fertilize = flag(plan.fertilize), weed = flag(plan.weed),
|
||||||
targetFruit = plan.targetFruit or "", prepAfterMow = flag(plan.prepAfterMow),
|
targetFruit = plan.targetFruit or "", prepAfterMow = flag(plan.prepAfterMow), straw = plan.straw or "chop",
|
||||||
kind = field.kind or "", lastFruit = field.lastFruit or "", care = table.concat(care, " "),
|
kind = field.kind or "", lastFruit = field.lastFruit or "", care = table.concat(care, " "),
|
||||||
mowWidth = field.mowWidth or 0,
|
mowWidth = field.mowWidth or 0,
|
||||||
mowVehicle = field.mowVehicleId or "",
|
mowVehicle = field.mowVehicleId or "",
|
||||||
rakeVehicle = field.rakeVehicleId or "",
|
rakeVehicle = field.rakeVehicleId or "",
|
||||||
|
harvestVehicle = field.harvestVehicleId or "",
|
||||||
windrowOffset = field.windrowOffset ~= nil and string.format("%.2f", field.windrowOffset) or "",
|
windrowOffset = field.windrowOffset ~= nil and string.format("%.2f", field.windrowOffset) or "",
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
@@ -462,12 +471,14 @@ function ADFieldModel.fromRecord(record)
|
|||||||
plan.weed = readFlag(record.weed, true)
|
plan.weed = readFlag(record.weed, true)
|
||||||
plan.targetFruit = record.targetFruit or ""
|
plan.targetFruit = record.targetFruit or ""
|
||||||
plan.prepAfterMow = readFlag(record.prepAfterMow, false)
|
plan.prepAfterMow = readFlag(record.prepAfterMow, false)
|
||||||
|
plan.straw = STRAW_VALUES[record.straw] and record.straw or "chop"
|
||||||
field.kind = readText(record.kind)
|
field.kind = readText(record.kind)
|
||||||
field.lastFruit = readText(record.lastFruit)
|
field.lastFruit = readText(record.lastFruit)
|
||||||
for stage, runs in string.gmatch(record.care or "", "(%w+)=(%d+)") do field.careRuns[stage] = tonumber(runs) end
|
for stage, runs in string.gmatch(record.care or "", "(%w+)=(%d+)") do field.careRuns[stage] = tonumber(runs) end
|
||||||
field.mowWidth = (record.mowWidth or 0) > 0 and record.mowWidth or nil
|
field.mowWidth = (record.mowWidth or 0) > 0 and record.mowWidth or nil
|
||||||
field.mowVehicleId = readText(record.mowVehicle)
|
field.mowVehicleId = readText(record.mowVehicle)
|
||||||
field.rakeVehicleId = readText(record.rakeVehicle)
|
field.rakeVehicleId = readText(record.rakeVehicle)
|
||||||
|
field.harvestVehicleId = readText(record.harvestVehicle)
|
||||||
field.windrowOffset = tonumber(record.windrowOffset)
|
field.windrowOffset = tonumber(record.windrowOffset)
|
||||||
return field
|
return field
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -11,8 +11,8 @@ ADFieldStorage.FIELD_TYPES = {
|
|||||||
id = "Int", stage = "String", mode = "String", product = "String", rake = "Int", store = "String",
|
id = "Int", stage = "String", mode = "String", product = "String", rake = "Int", store = "String",
|
||||||
rigs = "Int", unloaders = "Int", mulch = "Int", lime = "Int", soil = "String", sow = "Int",
|
rigs = "Int", unloaders = "Int", mulch = "Int", lime = "Int", soil = "String", sow = "Int",
|
||||||
sowFruit = "String", roll = "Int", fertilize = "Int", weed = "Int",
|
sowFruit = "String", roll = "Int", fertilize = "Int", weed = "Int",
|
||||||
kind = "String", lastFruit = "String", care = "String", targetFruit = "String", prepAfterMow = "Int",
|
kind = "String", lastFruit = "String", care = "String", targetFruit = "String", prepAfterMow = "Int", straw = "String",
|
||||||
mowWidth = "Float", mowVehicle = "String", rakeVehicle = "String", windrowOffset = "String",
|
mowWidth = "Float", mowVehicle = "String", rakeVehicle = "String", harvestVehicle = "String", windrowOffset = "String",
|
||||||
}
|
}
|
||||||
|
|
||||||
function ADFieldStorage.getPath()
|
function ADFieldStorage.getPath()
|
||||||
|
|||||||
@@ -166,6 +166,9 @@ end
|
|||||||
-- Hvilken vare markens trin fører til lager: skår (ensilage), tørskår (hø) eller høstet afgrøde.
|
-- Hvilken vare markens trin fører til lager: skår (ensilage), tørskår (hø) eller høstet afgrøde.
|
||||||
function ADFieldWork.storeFillType(field, info)
|
function ADFieldWork.storeFillType(field, info)
|
||||||
if field.stage == "harvesting" then return info.harvestFillType end
|
if field.stage == "harvesting" then return info.harvestFillType end
|
||||||
|
if field.stage == "strawCollecting" or field.stage == "baling" or field.stage == "baleCollecting" then
|
||||||
|
return g_fillTypeManager:getFillTypeIndexByName("STRAW")
|
||||||
|
end
|
||||||
local product = ADFieldModel.product(field.plan, field.kind or info.kind)
|
local product = ADFieldModel.product(field.plan, field.kind or info.kind)
|
||||||
return product == "hay" and info.hay or info.windrow
|
return product == "hay" and info.hay or info.windrow
|
||||||
end
|
end
|
||||||
@@ -202,11 +205,11 @@ local function coursesOf(fieldId)
|
|||||||
return ADFieldJobs.courses[fieldId]
|
return ADFieldJobs.courses[fieldId]
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Kurset et trin skal genbruge ("mower"/"rake"): gemt kopi, ellers maskinens nuværende kursus.
|
-- Kurset et trin skal genbruge ("mower"/"rake"/"harvester"): gemt kopi, ellers maskinens nuværende kursus.
|
||||||
local function sourceCourse(adEnv, field, source)
|
local function sourceCourse(adEnv, field, source)
|
||||||
local saved = coursesOf(field.id)[source]
|
local saved = coursesOf(field.id)[source]
|
||||||
if saved ~= nil then return saved end
|
if saved ~= nil then return saved end
|
||||||
local vehicleId = source == "rake" and field.rakeVehicleId or field.mowVehicleId
|
local vehicleId = source == "rake" and field.rakeVehicleId or source == "harvester" and field.harvestVehicleId or field.mowVehicleId
|
||||||
if vehicleId == nil then return nil end
|
if vehicleId == nil then return nil end
|
||||||
for _, vehicle in ipairs(ADRunsController.getFarmVehicles(adEnv)) do
|
for _, vehicle in ipairs(ADRunsController.getFarmVehicles(adEnv)) do
|
||||||
if ADRunsController.getVehicleId(vehicle) == vehicleId then return ADCpBridge.getCourse(vehicle) end
|
if ADRunsController.getVehicleId(vehicle) == vehicleId then return ADCpBridge.getCourse(vehicle) end
|
||||||
@@ -435,6 +438,51 @@ local function beginUnloader(adEnv, field, info, assignment)
|
|||||||
assignment.handle = handle
|
assignment.handle = handle
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Ballesamler: Courseplays ballefinder; fuld vogn tømmes af AutoDrive i nærmeste ballelager (palleskur der
|
||||||
|
-- tager halmballer), som læssevognen. Uden lager stopper den når den er fuld.
|
||||||
|
local function beginBaleCollector(adEnv, field, info, assignment)
|
||||||
|
local vehicle = assignment.vehicle
|
||||||
|
local farmId = vehicle:getOwnerFarmId()
|
||||||
|
local straw = g_fillTypeManager:getFillTypeIndexByName("STRAW")
|
||||||
|
local isReachable = function(markerId) return ADUnloadWait.hasRouteTo(adEnv, vehicle, markerId) end
|
||||||
|
local store = ADSources.findPalletStore(adEnv, vehicle, straw, nil, isReachable, farmId)
|
||||||
|
if store ~= nil then
|
||||||
|
pcall(function()
|
||||||
|
local module = stateModule(vehicle)
|
||||||
|
module:setMode(adEnv.AutoDrive.MODE_PICKUPANDDELIVER)
|
||||||
|
module:setFirstMarkerByWayPointId(info.markerId)
|
||||||
|
module:setSecondMarkerByWayPointId(store.wayPointId)
|
||||||
|
module:setStartHelper(true)
|
||||||
|
module.usedHelper = helperCp(adEnv)
|
||||||
|
enableParkAtJobFinished(vehicle)
|
||||||
|
module:raiseDirtyFlag()
|
||||||
|
end)
|
||||||
|
assignment.adHandlesEnd = true
|
||||||
|
log(field.id, "ballesamler '%s' kører fulde læs til %s", ADRuns.vehicleLabel(vehicle), tostring(store.name))
|
||||||
|
else
|
||||||
|
log(field.id, "intet ballelager med plads og vej fundet — ballesamleren stopper når den er fuld")
|
||||||
|
end
|
||||||
|
local point = info.points[1] or {x = info.x, z = info.z}
|
||||||
|
assignment.phase = "starting"
|
||||||
|
assignment.since = now()
|
||||||
|
local handle, err = ADCpBridge.startBaleFinder(vehicle, point.x, point.z, function(ok, reason)
|
||||||
|
if ok then
|
||||||
|
assignment.phase = "working"
|
||||||
|
assignment.since = now()
|
||||||
|
log(field.id, "Courseplay startet (ballesamler)")
|
||||||
|
else
|
||||||
|
ADFieldWork.release(assignment)
|
||||||
|
fail(field.id, "ballesamler: " .. tostring(reason))
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
if handle == nil then
|
||||||
|
ADFieldWork.release(assignment)
|
||||||
|
fail(field.id, "ballesamler: " .. tostring(err))
|
||||||
|
return
|
||||||
|
end
|
||||||
|
assignment.handle = handle
|
||||||
|
end
|
||||||
|
|
||||||
-- Multi-tool: følgere venter på lederens kursus for trinnet og kopierer det med deres bane.
|
-- Multi-tool: følgere venter på lederens kursus for trinnet og kopierer det med deres bane.
|
||||||
local function courseOptions(adEnv, field, assignment)
|
local function courseOptions(adEnv, field, assignment)
|
||||||
local source = ADFieldModel.courseSource(field, assignment.role)
|
local source = ADFieldModel.courseSource(field, assignment.role)
|
||||||
@@ -459,6 +507,12 @@ end
|
|||||||
local function beginWork(adEnv, field, info, assignment)
|
local function beginWork(adEnv, field, info, assignment)
|
||||||
local vehicle = assignment.vehicle
|
local vehicle = assignment.vehicle
|
||||||
if assignment.role == "unloader" then return beginUnloader(adEnv, field, info, assignment) end
|
if assignment.role == "unloader" then return beginUnloader(adEnv, field, info, assignment) end
|
||||||
|
if assignment.role == "baleCollector" then return beginBaleCollector(adEnv, field, info, assignment) end
|
||||||
|
-- høsteren: halmskår efter planen (hakkes = fra; samles op/presses = skår)
|
||||||
|
if assignment.role == "harvester" then
|
||||||
|
local keepStraw = field.plan.straw == "collect" or field.plan.straw == "bale"
|
||||||
|
ADCpBridge.setStrawSwath(vehicle, keepStraw)
|
||||||
|
end
|
||||||
local opts, source = courseOptions(adEnv, field, assignment)
|
local opts, source = courseOptions(adEnv, field, assignment)
|
||||||
if opts == nil then
|
if opts == nil then
|
||||||
-- følger uden lederens kursus endnu
|
-- følger uden lederens kursus endnu
|
||||||
@@ -504,6 +558,9 @@ local function beginWork(adEnv, field, info, assignment)
|
|||||||
elseif assignment.role == "rake" then
|
elseif assignment.role == "rake" then
|
||||||
note(field.id, {rakeVehicleId = assignment.vehicleId})
|
note(field.id, {rakeVehicleId = assignment.vehicleId})
|
||||||
rememberCourse(field, "rake", vehicle)
|
rememberCourse(field, "rake", vehicle)
|
||||||
|
elseif assignment.role == "harvester" then
|
||||||
|
note(field.id, {harvestVehicleId = assignment.vehicleId})
|
||||||
|
rememberCourse(field, "harvester", vehicle)
|
||||||
end
|
end
|
||||||
if assignment.leader and (assignment.groupSize or 1) > 1 then
|
if assignment.leader and (assignment.groupSize or 1) > 1 then
|
||||||
rememberCourse(field, field.stage, vehicle)
|
rememberCourse(field, field.stage, vehicle)
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ SmartPickupFrame.FIELD_ROW_KINDS = {
|
|||||||
fieldProduct = true, fieldMode = true, fieldRake = true, fieldStore = true, fleetVehicle = true,
|
fieldProduct = true, fieldMode = true, fieldRake = true, fieldStore = true, fleetVehicle = true,
|
||||||
fieldRigs = true, fieldUnloaders = true, fieldMulch = true, fieldLime = true, fieldSoil = true,
|
fieldRigs = true, fieldUnloaders = true, fieldMulch = true, fieldLime = true, fieldSoil = true,
|
||||||
fieldSow = true, fieldSowFruit = true, fieldRoll = true, fieldFertilize = true, fieldWeed = true,
|
fieldSow = true, fieldSowFruit = true, fieldRoll = true, fieldFertilize = true, fieldWeed = true,
|
||||||
fieldTarget = true, fleetMode = true,
|
fieldTarget = true, fleetMode = true, fieldStraw = true,
|
||||||
}
|
}
|
||||||
SmartPickupFrame.ROLE_KEYS = {
|
SmartPickupFrame.ROLE_KEYS = {
|
||||||
mower = "spu_field_role_mower", tedder = "spu_field_role_tedder", rake = "spu_field_role_rake",
|
mower = "spu_field_role_mower", tedder = "spu_field_role_tedder", rake = "spu_field_role_rake",
|
||||||
@@ -17,6 +17,7 @@ SmartPickupFrame.ROLE_KEYS = {
|
|||||||
mulcher = "spu_field_role_mulcher", limer = "spu_field_role_limer", plow = "spu_field_role_plow",
|
mulcher = "spu_field_role_mulcher", limer = "spu_field_role_limer", plow = "spu_field_role_plow",
|
||||||
cultivator = "spu_field_role_cultivator", seeder = "spu_field_role_seeder", roller = "spu_field_role_roller",
|
cultivator = "spu_field_role_cultivator", seeder = "spu_field_role_seeder", roller = "spu_field_role_roller",
|
||||||
weeder = "spu_field_role_weeder", fertilizer = "spu_field_role_fertilizer",
|
weeder = "spu_field_role_weeder", fertilizer = "spu_field_role_fertilizer",
|
||||||
|
baler = "spu_field_role_baler", baleCollector = "spu_field_role_baleCollector",
|
||||||
}
|
}
|
||||||
SmartPickupFrame.SOIL_VALUES = {"auto", "cultivate", "plow", "none"}
|
SmartPickupFrame.SOIL_VALUES = {"auto", "cultivate", "plow", "none"}
|
||||||
-- simple Ja/Nej-valg på planen: rækketype -> plan-felt
|
-- simple Ja/Nej-valg på planen: rækketype -> plan-felt
|
||||||
@@ -25,7 +26,8 @@ SmartPickupFrame.PLAN_TOGGLES = {
|
|||||||
fieldFertilize = "fertilize", fieldWeed = "weed",
|
fieldFertilize = "fertilize", fieldWeed = "weed",
|
||||||
}
|
}
|
||||||
-- valg med flere muligheder: rækketype -> plan-felt
|
-- valg med flere muligheder: rækketype -> plan-felt
|
||||||
SmartPickupFrame.PLAN_CHOICES = {fieldRigs = "rigs", fieldUnloaders = "unloaders", fieldSoil = "soil", fieldSowFruit = "sowFruit"}
|
SmartPickupFrame.PLAN_CHOICES = {fieldRigs = "rigs", fieldUnloaders = "unloaders", fieldSoil = "soil", fieldSowFruit = "sowFruit", fieldStraw = "straw"}
|
||||||
|
SmartPickupFrame.STRAW_VALUES = {"chop", "collect", "bale"}
|
||||||
|
|
||||||
-- ---- tekster ----
|
-- ---- tekster ----
|
||||||
|
|
||||||
@@ -200,14 +202,25 @@ function SmartPickupFrame:fillFieldDetail(adEnv, info)
|
|||||||
end
|
end
|
||||||
local rigTexts, rigValues = numberTexts(1, ADFieldModel.MAX_RIGS)
|
local rigTexts, rigValues = numberTexts(1, ADFieldModel.MAX_RIGS)
|
||||||
self:addChoiceRow("fieldRigs", i18n:getText("spu_field_rigs"), rigTexts, rigValues, plan.rigs or 1)
|
self:addChoiceRow("fieldRigs", i18n:getText("spu_field_rigs"), rigTexts, rigValues, plan.rigs or 1)
|
||||||
if info.kind == "mowable" then
|
-- græs-valgene (ensilage/hø, riv) også når målet er en slåafgrøde (fx græs på en kornmark)
|
||||||
|
local targetMowable = false
|
||||||
|
if hasTarget and ADFields ~= nil and g_fruitTypeManager ~= nil then
|
||||||
|
local targetFruit = g_fruitTypeManager:getFruitTypeByName(plan.targetFruit)
|
||||||
|
targetMowable = targetFruit ~= nil and ADFields.getMowable()[targetFruit.index] ~= nil
|
||||||
|
end
|
||||||
|
if info.kind == "mowable" or targetMowable then
|
||||||
local isHay = ADFieldModel.product(plan, "mowable") == "hay"
|
local isHay = ADFieldModel.product(plan, "mowable") == "hay"
|
||||||
self:addToggleRow("fieldProduct", i18n:getText("spu_field_plan"), {i18n:getText("spu_field_plan_silage"), i18n:getText("spu_field_plan_hay")}, isHay)
|
self:addToggleRow("fieldProduct", i18n:getText("spu_field_plan"), {i18n:getText("spu_field_plan_silage"), i18n:getText("spu_field_plan_hay")}, isHay)
|
||||||
self:addToggleRow("fieldRake", i18n:getText("spu_field_rake"), yesNo, plan.rake == true)
|
self:addToggleRow("fieldRake", i18n:getText("spu_field_rake"), yesNo, plan.rake == true)
|
||||||
else
|
end
|
||||||
|
-- klargøring: høst-/bare marker, og græsmarker der skal skifte til en anden mål-afgrøde
|
||||||
|
if info.kind ~= "mowable" or (hasTarget and info.fruitName ~= plan.targetFruit) then
|
||||||
if info.kind == "harvest" then
|
if info.kind == "harvest" then
|
||||||
local unloaderTexts, unloaderValues = numberTexts(1, ADFieldModel.MAX_UNLOADERS)
|
local unloaderTexts, unloaderValues = numberTexts(1, ADFieldModel.MAX_UNLOADERS)
|
||||||
self:addChoiceRow("fieldUnloaders", i18n:getText("spu_field_unloaders"), unloaderTexts, unloaderValues, plan.unloaders or 1)
|
self:addChoiceRow("fieldUnloaders", i18n:getText("spu_field_unloaders"), unloaderTexts, unloaderValues, plan.unloaders or 1)
|
||||||
|
local strawTexts = {}
|
||||||
|
for _, value in ipairs(SmartPickupFrame.STRAW_VALUES) do table.insert(strawTexts, i18n:getText("spu_field_straw_" .. value)) end
|
||||||
|
self:addChoiceRow("fieldStraw", i18n:getText("spu_field_straw"), strawTexts, SmartPickupFrame.STRAW_VALUES, plan.straw or "chop")
|
||||||
end
|
end
|
||||||
self:addTextRow(i18n:getText(info.kind == "harvest" and "spu_field_section_after" or "spu_field_section_prep"))
|
self:addTextRow(i18n:getText(info.kind == "harvest" and "spu_field_section_after" or "spu_field_section_prep"))
|
||||||
self:addToggleRow("fieldMulch", i18n:getText("spu_field_mulch"), yesNo, plan.mulch == true)
|
self:addToggleRow("fieldMulch", i18n:getText("spu_field_mulch"), yesNo, plan.mulch == true)
|
||||||
|
|||||||
@@ -160,6 +160,15 @@
|
|||||||
<text name="spu_field_target_switch" text="%s får lov at vokse færdig og høstes/slås; derefter klargøres og tilsås med %s"/>
|
<text name="spu_field_target_switch" text="%s får lov at vokse færdig og høstes/slås; derefter klargøres og tilsås med %s"/>
|
||||||
<text name="spu_field_waitSowing" text="venter på såtid for %s"/>
|
<text name="spu_field_waitSowing" text="venter på såtid for %s"/>
|
||||||
<text name="spu_field_fleetAll" text="Brug alle ledige maskiner (Nej = kun med flueben)"/>
|
<text name="spu_field_fleetAll" text="Brug alle ledige maskiner (Nej = kun med flueben)"/>
|
||||||
|
<text name="spu_field_role_baler" text="ballepresser"/>
|
||||||
|
<text name="spu_field_role_baleCollector" text="ballesamler"/>
|
||||||
|
<text name="spu_field_stage_strawCollecting" text="Halm samles"/>
|
||||||
|
<text name="spu_field_stage_baling" text="Presses"/>
|
||||||
|
<text name="spu_field_stage_baleCollecting" text="Baller samles"/>
|
||||||
|
<text name="spu_field_straw" text="Halm efter høst"/>
|
||||||
|
<text name="spu_field_straw_chop" text="Hakkes (spredes på marken)"/>
|
||||||
|
<text name="spu_field_straw_collect" text="Samles op til silo"/>
|
||||||
|
<text name="spu_field_straw_bale" text="Presses til baller og samles"/>
|
||||||
<text name="spu_button_start" text="Start run"/>
|
<text name="spu_button_start" text="Start run"/>
|
||||||
<text name="spu_button_stop" text="Stop run"/>
|
<text name="spu_button_stop" text="Stop run"/>
|
||||||
<text name="spu_button_new" text="Nyt run"/>
|
<text name="spu_button_new" text="Nyt run"/>
|
||||||
|
|||||||
@@ -160,6 +160,15 @@
|
|||||||
<text name="spu_field_target_switch" text="%s is left to finish growing and is harvested/mowed; then the field is prepared and sown with %s"/>
|
<text name="spu_field_target_switch" text="%s is left to finish growing and is harvested/mowed; then the field is prepared and sown with %s"/>
|
||||||
<text name="spu_field_waitSowing" text="waiting for sowing time for %s"/>
|
<text name="spu_field_waitSowing" text="waiting for sowing time for %s"/>
|
||||||
<text name="spu_field_fleetAll" text="Use all free machines (No = only ticked ones)"/>
|
<text name="spu_field_fleetAll" text="Use all free machines (No = only ticked ones)"/>
|
||||||
|
<text name="spu_field_role_baler" text="baler"/>
|
||||||
|
<text name="spu_field_role_baleCollector" text="bale collector"/>
|
||||||
|
<text name="spu_field_stage_strawCollecting" text="Collecting straw"/>
|
||||||
|
<text name="spu_field_stage_baling" text="Baling"/>
|
||||||
|
<text name="spu_field_stage_baleCollecting" text="Collecting bales"/>
|
||||||
|
<text name="spu_field_straw" text="Straw after harvest"/>
|
||||||
|
<text name="spu_field_straw_chop" text="Chopped (spread on the field)"/>
|
||||||
|
<text name="spu_field_straw_collect" text="Collected to a silo"/>
|
||||||
|
<text name="spu_field_straw_bale" text="Baled and collected"/>
|
||||||
<text name="spu_button_start" text="Start run"/>
|
<text name="spu_button_start" text="Start run"/>
|
||||||
<text name="spu_button_stop" text="Stop run"/>
|
<text name="spu_button_stop" text="Stop run"/>
|
||||||
<text name="spu_button_new" text="New run"/>
|
<text name="spu_button_new" text="New run"/>
|
||||||
|
|||||||
@@ -88,5 +88,11 @@ check("FL11 flueben: uden flueben ude", F.isEnabled("ticked", {}, "v1"), false)
|
|||||||
check("FL11 flueben: med flueben", F.isEnabled("ticked", {v1 = true}, "v1"), true)
|
check("FL11 flueben: med flueben", F.isEnabled("ticked", {v1 = true}, "v1"), true)
|
||||||
check("FL11 ukendt tilstand = alle", F.isEnabled(nil, {}, "v1"), true)
|
check("FL11 ukendt tilstand = alle", F.isEnabled(nil, {}, "v1"), true)
|
||||||
|
|
||||||
|
-- FL12: ballepresser og ballesamler (ballevogn/Universal Autoload som Courseplays ballesamler kan bruge)
|
||||||
|
check("FL12 ballepresser", F.roleFromSpecs({spec_baler = true}), "baler")
|
||||||
|
check("FL12 ballesamler", F.roleFromSpecs({canBaleCollect = true}), "baleCollector")
|
||||||
|
check("FL12 ballesamler før aflæsningsvogn", F.roleFromSpecs({canBaleCollect = true, canUnload = true}), "baleCollector")
|
||||||
|
check("FL12 høster før presser", F.roleFromSpecs({spec_combine = true, spec_baler = true}), "harvester")
|
||||||
|
|
||||||
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)
|
||||||
|
|||||||
@@ -270,5 +270,24 @@ check("M21 arbejdende mark beholder trin", M.setTarget(started, "CANOLA").stage,
|
|||||||
local cleared = M.setTarget(chosen, "")
|
local cleared = M.setTarget(chosen, "")
|
||||||
check("M21 mål fjernet", cleared.plan.targetFruit, ""); check("M21 tilbage til manuel", cleared.plan.mode, "manual")
|
check("M21 mål fjernet", cleared.plan.targetFruit, ""); check("M21 tilbage til manuel", cleared.plan.mode, "manual")
|
||||||
|
|
||||||
|
-- M22: halm efter høst — hakkes (standard), samles op, eller presses til baller og samles
|
||||||
|
local strawBase = {soil = "none", sow = false, lime = false}
|
||||||
|
check("M22 hakkes: kun høst", table.concat(M.workStages(strawBase, "harvest", {}), ","), "harvesting")
|
||||||
|
check("M22 samles op", table.concat(M.workStages(M.with(M.newField(1), {plan = {soil = "none", lime = false, straw = "collect"}}).plan, "harvest", {}), ","), "harvesting,strawCollecting")
|
||||||
|
check("M22 baller", table.concat(M.workStages(M.with(M.newField(1), {plan = {soil = "none", lime = false, straw = "bale"}}).plan, "harvest", {}), ","), "harvesting,baling,baleCollecting")
|
||||||
|
local baleChain = M.start(M.with(M.newField(2), {plan = {straw = "bale", soil = "cultivate", lime = false}}), "harvest", {})
|
||||||
|
check("M22 høst -> presses", M.advance(baleChain, {}).stage, "baling")
|
||||||
|
check("M22 presses -> baller samles", M.advance(M.advance(baleChain, {}), {}).stage, "baleCollecting")
|
||||||
|
check("M22 -> kultivér", M.advance(M.advance(M.advance(baleChain, {}), {}), {}).stage, "cultivating")
|
||||||
|
check("M22 roller", M.roleFor("baling") .. "," .. M.roleFor("baleCollecting") .. "," .. M.roleFor("strawCollecting"), "baler,baleCollector,collector")
|
||||||
|
check("M22 halm-læssevogn følger høsterens kursus", M.courseSource(M.with(M.newField(3), {stage = "strawCollecting"}), "collector"), "harvester")
|
||||||
|
check("M22 presser følger høsterens kursus", M.courseSource(M.with(M.newField(3), {stage = "baling"}), "baler"), "harvester")
|
||||||
|
check("M22 græs-læssevogn følger stadig slåkurset", M.courseSource(M.with(M.newField(3), {stage = "collecting"}), "collector"), "mower")
|
||||||
|
check("M22 halm-læssevogn uden breddekrav", M.requiredWidth(M.with(M.newField(3), {stage = "strawCollecting", mowWidth = 40}), "collector"), nil)
|
||||||
|
check("M22 presning vejrfølsom", M.isWeatherSensitive("baling", {}, "harvest"), true)
|
||||||
|
check("M22 ballesamling ikke vejrfølsom", M.isWeatherSensitive("baleCollecting", {}, "harvest"), false)
|
||||||
|
check("M22 gemmes", M.fromRecord(M.toRecord(M.with(M.newField(4), {plan = {straw = "bale"}}))).plan.straw, "bale")
|
||||||
|
check("M22 ukendt -> hakkes", M.fromRecord({id = 5, straw = "x"}).plan.straw, "chop")
|
||||||
|
|
||||||
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)
|
||||||
|
|||||||
Reference in New Issue
Block a user