Skip to content
This repository has been archived by the owner on May 23, 2023. It is now read-only.

Commit

Permalink
6.03.00050 Bale improvements and initialization fixes
Browse files Browse the repository at this point in the history
- Vehicle initialization after load fixed for #6964 (also made
it more resilient)

Bale collector/wrapper improvements

- Enabled bale wrapper for Mode 7
- Look for bales once more before leaving for the unload course.

Bale unload fix for #6953

- When moving forward after unloading, use the position where we
actually unloaded the bales instead of the unload waypoint.
  • Loading branch information
pvaiko committed Mar 9, 2021
1 parent 7ec6dc4 commit 21ae33b
Show file tree
Hide file tree
Showing 25 changed files with 175 additions and 110 deletions.
58 changes: 47 additions & 11 deletions BaleCollectorAIDriver.lua
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ without a field course.
For unloading, it has the same behavior as the BaleLoaderAIDriver.
It also works with a bale wrapper, find and wrap all wrappable bales.
--]]

---@class BaleCollectorAIDriver : BaleLoaderAIDriver
Expand All @@ -33,7 +35,7 @@ BaleCollectorAIDriver.myStates = {
WAITING_FOR_PATHFINDER = {},
DRIVING_TO_NEXT_BALE = {},
APPROACHING_BALE = {},
PICKING_UP_BALE = {}
WORKING_ON_BALE = {}
}

function BaleCollectorAIDriver:init(vehicle)
Expand Down Expand Up @@ -69,6 +71,7 @@ function BaleCollectorAIDriver:setUpAndStart(startingPoint)
self:stop("NO_FIELD_SELECTED")
return
end
BaleWrapperAIDriver.initializeBaleWrapper(self)
self.bales = self:findBales(myField)
self:changeToFieldwork()
self:collectNextBale()
Expand Down Expand Up @@ -97,8 +100,15 @@ function BaleCollectorAIDriver:collectNextBale()
if #self.bales > 0 then
self:findPathToNextBale()
else
self:info('No bales found.')
if self:getFillLevel() > 0.1 then
self:info('No bales found, scan the field once more before leaving for the unload course.')
self.bales = self:findBales(self.vehicle.cp.settings.baleCollectionField:get())
if #self.bales > 0 then
self:info('Found more bales, collecting them')
self:findPathToNextBale()
return
end
self:info('There really is no more bales on the field')
if self.baleLoader and self:getFillLevel() > 0.1 then
self:changeToUnloadOrRefill()
self:startCourseWithPathfinding(self.unloadRefillCourse, 1)
else
Expand All @@ -113,7 +123,7 @@ function BaleCollectorAIDriver:findBales(fieldId)
self:debug('Finding bales on field %d...', fieldId or 0)
local balesFound = {}
for _, object in pairs(g_currentMission.nodeToObject) do
if BaleToCollect.isValidBale(object) then
if BaleToCollect.isValidBale(object, self.baleWrapper) then
local bale = BaleToCollect(object)
-- if the bale has a mountObject it is already on the loader so ignore it
if (not fieldId or fieldId == 0 or bale:getFieldId() == fieldId) and
Expand Down Expand Up @@ -224,8 +234,8 @@ function BaleCollectorAIDriver:onLastWaypoint()
if self.state == self.states.ON_FIELDWORK_COURSE and self.fieldworkState == self.states.WORKING then
if self.baleCollectingState == self.states.DRIVING_TO_NEXT_BALE then
self:debug('last waypoint while driving to next bale reached')
self:approachBale()
elseif self.baleCollectingState == self.states.PICKING_UP_BALE then
self:startApproachingBale()
elseif self.baleCollectingState == self.states.WORKING_ON_BALE then
self:debug('last waypoint on bale pickup reached, start collecting bales again')
self:collectNextBale()
elseif self.baleCollectingState == self.states.APPROACHING_BALE then
Expand All @@ -250,7 +260,7 @@ function BaleCollectorAIDriver:onEndCourse()
end
end

function BaleCollectorAIDriver:approachBale()
function BaleCollectorAIDriver:startApproachingBale()
self:debug('Approaching bale...')
self:startCourse(self:getStraightForwardCourse(20), 1)
self:setBaleCollectingState(self.states.APPROACHING_BALE)
Expand All @@ -269,18 +279,44 @@ function BaleCollectorAIDriver:work()
self:setSpeed(self.vehicle:getSpeedLimit())
elseif self.baleCollectingState == self.states.APPROACHING_BALE then
self:setSpeed(self:getWorkSpeed() / 2)
self:approachBale()
elseif self.baleCollectingState == self.states.WORKING_ON_BALE then
self:workOnBale()
self:setSpeed(0)
end
self:checkFillLevels()
end

function BaleCollectorAIDriver:approachBale()
if self.baleLoader then
if self.baleLoader.spec_baleLoader.grabberMoveState then
self:debug('Start picking up bale')
self:setBaleCollectingState(self.states.PICKING_UP_BALE)
self:setBaleCollectingState(self.states.WORKING_ON_BALE)
end
elseif self.baleCollectingState == self.states.PICKING_UP_BALE then
self:setSpeed(0)
end
if self.baleWrapper then
BaleWrapperAIDriver.handleBaleWrapper(self)
if self.baleWrapper.spec_baleWrapper.baleWrapperState ~= BaleWrapper.STATE_NONE then
self:debug('Start wrapping bale')
self:setBaleCollectingState(self.states.WORKING_ON_BALE)
end
end
end

function BaleCollectorAIDriver:workOnBale()
if self.baleLoader then
if not self.baleLoader.spec_baleLoader.grabberMoveState then
self:debug('Bale picked up, moving on to the next')
self:collectNextBale()
end
end
self:checkFillLevels()
if self.baleWrapper then
BaleWrapperAIDriver.handleBaleWrapper(self)
if self.baleWrapper.spec_baleWrapper.baleWrapperState == BaleWrapper.STATE_NONE then
self:debug('Bale wrapped, moving on to the next')
self:collectNextBale()
end
end
end

function BaleCollectorAIDriver:calculateTightTurnOffset()
Expand Down
31 changes: 17 additions & 14 deletions BaleLoaderAIDriver.lua
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,6 @@ function BaleLoaderAIDriver:init(vehicle)
courseplay.debugVehicle(courseplay.DBG_AI_DRIVER,vehicle,'BaleLoaderAIDriver:init()')
UnloadableFieldworkAIDriver.init(self, vehicle)
self:initStates(BaleLoaderAIDriver.myStates)
self:initializeBaleLoader()
self.unloadDoneX, self.unloadDoneZ = 0, 0
end

Expand All @@ -71,21 +70,25 @@ end

function BaleLoaderAIDriver:initializeBaleLoader()
self.baleLoader = AIDriverUtil.getImplementWithSpecialization(self.vehicle, BaleLoader)
self:debug('baleloader %s', tostring(self.baleLoader))
-- Bale loaders have no AI markers (as they are not AIImplements according to Giants) so add a function here
-- to get the markers
self.baleLoader.getAIMarkers = function(object)
return UnloadableFieldworkAIDriver.getAIMarkersFromGrabberNode(object, object.spec_baleLoader)
end
if self.baleLoader then
self:debug('baleloader %s', tostring(self.baleLoader))
-- Bale loaders have no AI markers (as they are not AIImplements according to Giants) so add a function here
-- to get the markers
self.baleLoader.getAIMarkers = function(object)
return UnloadableFieldworkAIDriver.getAIMarkersFromGrabberNode(object, object.spec_baleLoader)
end

self.manualUnloadNode = WaypointNode(self.vehicle:getName() .. 'unloadNode')
if self.baleLoader.cp.realUnloadOrFillNode then
-- use that realUnloadOrFillNode for now as it includes the balerUnloadDistance config value
-- TODO: can we just use the back marker node here as well?
self.baleFinderProximitySensorPack = BackwardLookingProximitySensorPack(
self.vehicle, self.ppc, self.baleLoader.cp.realUnloadOrFillNode, 5, 1)
self.manualUnloadNode = WaypointNode(self.vehicle:getName() .. 'unloadNode')
if self.baleLoader.cp.realUnloadOrFillNode then
-- use that realUnloadOrFillNode for now as it includes the balerUnloadDistance config value
-- TODO: can we just use the back marker node here as well?
self.baleFinderProximitySensorPack = BackwardLookingProximitySensorPack(
self.vehicle, self.ppc, self.baleLoader.cp.realUnloadOrFillNode, 5, 1)
end
self:debug('Initialized, bale loader: %s', self.baleLoader:getName())
else
self:debug('Has now bale loader specialization')
end
self:debug('Initialized, bale loader: %s', self.baleLoader:getName())
end

---@return boolean true if unload took over the driving
Expand Down
16 changes: 14 additions & 2 deletions BaleToCollect.lua
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,21 @@ function BaleToCollect:init(baleObject)
end

--- Call this before attempting to construct a BaleToCollect to check the validity of the object
function BaleToCollect.isValidBale(object)
---@param baleWrapper table bale wrapper, if exists
function BaleToCollect.isValidBale(object, baleWrapper)
-- nodeId is sometimes 0, causing issues for the BaleToCollect constructor
return object.isa and object:isa(Bale) and object.nodeId and entityExists(object.nodeId)
if object.isa and object:isa(Bale) and object.nodeId and entityExists(object.nodeId) then
if baleWrapper then
-- if there is a bale wrapper, the bale must be wrappable and the wrapper does not want to skip this fill type
-- (and yes, this is another typo in Giants code
local wrappedBaleType = baleWrapper:getWrapperBaleType(object)
courseplay.debugFormat(courseplay.DBG_MODE_7, ' bale %d wrapping state: %d, wrapped bale type: %s',
object.id, tostring(object.wrappingState), tostring(wrappedBaleType))
return wrappedBaleType and object.wrappingState < 0.99
else
return true
end
end
end

function BaleToCollect:getFieldId()
Expand Down
58 changes: 32 additions & 26 deletions BaleWrapperAIDriver.lua
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ end
function BaleWrapperAIDriver:initializeBaleWrapper()
self.baleWrapper = AIDriverUtil.getAIImplementWithSpecialization(self.vehicle, BaleWrapper)

if not self.baler then
if not self.baler and self.baleWrapper then
-- Bale wrappers which aren't balers have no AI markers as they have no pick up so add a function here
-- to get the markers
self.baleWrapper.getAIMarkers = function(object)
Expand All @@ -47,31 +47,37 @@ end
function BaleWrapperAIDriver:driveFieldwork(dt)
-- Don't drop the bale in the turn or on temporary alignment or connecting tracks
if self:isHandlingAllowed() then
-- stop while wrapping only if we don't have a baler. If we do we should continue driving and working
-- on the next bale, the baler code will take care about stopping if we need to
if self.baleWrapper.spec_baleWrapper.baleWrapperState ~= BaleWrapper.STATE_NONE and not self.baler then
self:setSpeed(0)
end
-- Yes, Giants has a typo in the state
if self.baleWrapper.spec_baleWrapper.baleWrapperState == BaleWrapper.STATE_WRAPPER_FINSIHED then
-- inserts unload threshold after lowering the implement, useful after e.g. transition from connecting track to fieldwork
if self.fieldworkState == self.states.WAITING_FOR_LOWER then
local unloadThreshold = 2500 --delay in msecs, 2.5 secs seems to work well
loweringDropTime = self.vehicle.timer + unloadThreshold
elseif loweringDropTime == nil then
loweringDropTime = 0
end
-- inserts unload threshold after turn so bales don't drop on headlands
if self.turnStartedAt and self.realTurnDurationMs then
local unloadThreshold = 4000 --delay in msecs, 4 secs seems to work well
turnDropTime = self.turnStartedAt + self.realTurnDurationMs + unloadThreshold
else
turnDropTime = 0 --avoids problems in case of condition variables not existing / empty e.g. before the first turn
end
if self.vehicle.timer > math.max(loweringDropTime,turnDropTime) then --chooses the bigger delay
self.baleWrapper:doStateChange(BaleWrapper.CHANGE_WRAPPER_START_DROP_BALE)
end
end
self:handleBaleWrapper()
end
return BalerAIDriver.driveFieldwork(self, dt)
end


function BaleWrapperAIDriver:handleBaleWrapper()
-- stop while wrapping only if we don't have a baler. If we do we should continue driving and working
-- on the next bale, the baler code will take care about stopping if we need to
if self.baleWrapper.spec_baleWrapper.baleWrapperState ~= BaleWrapper.STATE_NONE and not self.baler then
self:setSpeed(0)
end
-- Yes, Giants has a typo in the state
if self.baleWrapper.spec_baleWrapper.baleWrapperState == BaleWrapper.STATE_WRAPPER_FINSIHED then
local loweringDropTime, turnDropTime
-- inserts unload threshold after lowering the implement, useful after e.g. transition from connecting track to fieldwork
if self.fieldworkState == self.states.WAITING_FOR_LOWER then
local unloadThreshold = 2500 --delay in msecs, 2.5 secs seems to work well
loweringDropTime = self.vehicle.timer + unloadThreshold
elseif loweringDropTime == nil then
loweringDropTime = 0
end
-- inserts unload threshold after turn so bales don't drop on headlands
if self.turnStartedAt and self.realTurnDurationMs then
local unloadThreshold = 4000 --delay in msecs, 4 secs seems to work well
turnDropTime = self.turnStartedAt + self.realTurnDurationMs + unloadThreshold
else
turnDropTime = 0 --avoids problems in case of condition variables not existing / empty e.g. before the first turn
end
if self.vehicle.timer > math.max(loweringDropTime,turnDropTime) then --chooses the bigger delay
self.baleWrapper:doStateChange(BaleWrapper.CHANGE_WRAPPER_START_DROP_BALE)
end
end
end
7 changes: 5 additions & 2 deletions Waypoint.lua
Original file line number Diff line number Diff line change
Expand Up @@ -1050,17 +1050,20 @@ end
---@param dx number direction to extend
---@param dz number direction to extend
function Course:extend(length, dx, dz)
self:print()
local lastWp = self.waypoints[#self.waypoints]
local len = self.waypoints[#self.waypoints - 1].dToNext
dx, dz = dx or lastWp.dx / len, dz or lastWp.dz / len
dx, dz = dx or lastWp.dx, dz or lastWp.dz
print(dx, dz)
local wpDistance = 2
for _ = wpDistance, math.max(length, wpDistance), wpDistance do
for i = wpDistance, math.max(length, wpDistance), wpDistance do
lastWp = self.waypoints[#self.waypoints]
local x = lastWp.x + dx * wpDistance
local z = lastWp.z + dz * wpDistance
self:appendWaypoint({x = x, z = z})
end
self:enrichWaypointData()
self:print()
end

--- Create a new (straight) temporary course based on a node
Expand Down
6 changes: 0 additions & 6 deletions base.lua
Original file line number Diff line number Diff line change
Expand Up @@ -370,12 +370,6 @@ function courseplay:onLoad(savegame)
};
};

-- WOOD CUTTING: increase max cut length
if CpManager.isDeveloper then
self.cutLengthMax = 15;
self.cutLengthStep = 1;
end;

self.cp.mouseCursorActive = false;

-- 2D course
Expand Down
3 changes: 3 additions & 0 deletions config/ValidModeSetup.xml
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,9 @@
<Setup>
<Specialization name="spec_baleLoader"/>
</Setup>
<Setup>
<Specialization name="spec_baleWrapper"/>
</Setup>
</AllowedSetups>
<DisallowedSetups>
<Setup>
Expand Down
8 changes: 4 additions & 4 deletions hud.lua
Original file line number Diff line number Diff line change
Expand Up @@ -231,8 +231,8 @@ function courseplay.hud:setup()
[courseplay.MODE_SEED_FERTILIZE] = { 220, 72, 252,40 };
[courseplay.MODE_TRANSPORT] = { 4,108, 36,76 };
[courseplay.MODE_FIELDWORK] = { 40,108, 72,76 };
[courseplay.MODE_BALE_COLLECTOR] = { 76,108, 108,76 };
[courseplay.MODE_FIELD_SUPPLY] = { 112,108, 144,76 };
[courseplay.MODE_BALE_COLLECTOR] = { 76,108, 108,76 };
[courseplay.MODE_FIELD_SUPPLY] = { 112,108, 144,76 };
[courseplay.MODE_SHOVEL_FILL_AND_EMPTY] = { 148,108, 180,76 };
[courseplay.MODE_BUNKERSILO_COMPACTER] = { 219,431, 251,399 };
};
Expand Down Expand Up @@ -323,8 +323,8 @@ function courseplay.hud:setup()
[courseplay.MODE_SEED_FERTILIZE] = { 40,144, 72,112 };
[courseplay.MODE_TRANSPORT] = { 76,144, 108,112 };
[courseplay.MODE_FIELDWORK] = { 112,144, 144,112 };
[courseplay.MODE_BALE_COLLECTOR] = { 148,144, 180,112 };
[courseplay.MODE_FIELD_SUPPLY] = { 184,144, 216,112 };
[courseplay.MODE_BALE_COLLECTOR] = { 148,144, 180,112 };
[courseplay.MODE_FIELD_SUPPLY] = { 184,144, 216,112 };
[courseplay.MODE_SHOVEL_FILL_AND_EMPTY] = { 220,144, 252,112 };
[courseplay.MODE_BUNKERSILO_COMPACTER] = { 219,394, 251,362 };
};
Expand Down
2 changes: 1 addition & 1 deletion modDesc.xml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8" standalone="no" ?>
<modDesc descVersion="47">
<version>6.03.00049</version>
<version>6.03.00050</version>
<author><![CDATA[Courseplay.devTeam]]></author>
<title><!-- en=English de=German fr=French es=Spanish ru=Russian pl=Polish it=Italian br=Brazilian-Portuguese cs=Chinese(Simplified) ct=Chinese(Traditional) cz=Czech nl=Netherlands hu=Hungary jp=Japanese kr=Korean pt=Portuguese ro=Romanian tr=Turkish -->
<en>CoursePlay SIX</en>
Expand Down
Loading

0 comments on commit 21ae33b

Please sign in to comment.