Skip to content

Commit ae0c219

Browse files
author
Peter Vaiko
committed
fix: headland corner plow offset
The corner was created with the tool offset, which is calculated automatically but may be on the wrong side. Use the current course offset instead.
1 parent 6754007 commit ae0c219

4 files changed

Lines changed: 45 additions & 28 deletions

File tree

scripts/ai/strategies/AIDriveStrategyCombineCourse.lua

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1405,7 +1405,7 @@ function AIDriveStrategyCombineCourse:startTurn(ix)
14051405

14061406
self.turnContext = TurnContext(self.vehicle, self.course, ix, ix + 1, self.turnNodes, self:getWorkWidth(),
14071407
self.frontMarkerDistance, self.backMarkerDistance,
1408-
self:getTurnEndSideOffset(), self:getTurnEndForwardOffset())
1408+
self:getTurnEndSideOffset(self.course:isHeadlandTurnAtIx(ix + 1)), self:getTurnEndForwardOffset())
14091409

14101410
-- Combines drive special headland corner maneuvers, except potato and sugarbeet harvesters
14111411
if self.turnContext:isHeadlandCorner() then

scripts/ai/strategies/AIDriveStrategyFieldWorkCourse.lua

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -392,7 +392,7 @@ function AIDriveStrategyFieldWorkCourse:startTurn(ix)
392392
local fm, bm = self:getFrontAndBackMarkers()
393393
self.ppc:setShortLookaheadDistance()
394394
self.turnContext = TurnContext(self.vehicle, self.course, ix, ix + 1, self.turnNodes, self:getWorkWidth(), fm, bm,
395-
self:getTurnEndSideOffset(), self:getTurnEndForwardOffset())
395+
self:getTurnEndSideOffset(self.course:isHeadlandTurnAtIx(ix + 1)), self:getTurnEndForwardOffset())
396396
if AITurn.canMakeKTurn(self.vehicle, self.turnContext, self.workWidth, self:isTurnOnFieldActive()) then
397397
self.aiTurn = KTurn(self.vehicle, self, self.ppc, self.proximityController, self.turnContext, self.workWidth)
398398
else
@@ -488,7 +488,7 @@ function AIDriveStrategyFieldWorkCourse:startAlignmentTurn(fieldWorkCourse, star
488488
if alignmentCourse then
489489
local fm, bm = self:getFrontAndBackMarkers()
490490
self.turnContext = RowStartOrFinishContext(self.vehicle, fieldWorkCourse, startIx, startIx, self.turnNodes,
491-
self:getWorkWidth(), fm, bm, self:getTurnEndSideOffset(), self:getTurnEndForwardOffset())
491+
self:getWorkWidth(), fm, bm, self:getTurnEndSideOffset(false), self:getTurnEndForwardOffset())
492492
self.workStarter = StartRowOnly(self.vehicle, self, self.ppc, self.turnContext, alignmentCourse)
493493
self.state = self.states.DRIVING_TO_WORK_START_WAYPOINT
494494
self:startCourse(self.workStarter:getCourse(), 1)
@@ -542,7 +542,7 @@ function AIDriveStrategyFieldWorkCourse:startPathfindingToNextWaypoint(ix)
542542
self:debug('start pathfinding to waypoint %d', ix + 1)
543543
local fm, bm = self:getFrontAndBackMarkers()
544544
self.turnContext = RowStartOrFinishContext(self.vehicle, self.fieldWorkCourse, ix + 1, ix + 1,
545-
self.turnNodes, self:getWorkWidth(), fm, bm, self:getTurnEndSideOffset(), self:getTurnEndForwardOffset())
545+
self.turnNodes, self:getWorkWidth(), fm, bm, self:getTurnEndSideOffset(false), self:getTurnEndForwardOffset())
546546
local _, steeringLength = AIUtil.getSteeringParameters(self.vehicle)
547547
local targetNode, zOffset = self.turnContext:getTurnEndNodeAndOffsets(steeringLength)
548548
local context = PathfinderContext(self.vehicle):allowReverse(self:getAllowReversePathfinding())
@@ -605,7 +605,7 @@ function AIDriveStrategyFieldWorkCourse:startConnectingPath(ix)
605605
-- set up the turn context for the work starter to use when the pathfinding succeeds
606606
local fm, bm = self:getFrontAndBackMarkers()
607607
self.turnContext = RowStartOrFinishContext(self.vehicle, self.fieldWorkCourse, targetWaypointIx, targetWaypointIx,
608-
self.turnNodes, self:getWorkWidth(), fm, bm, self:getTurnEndSideOffset(), self:getTurnEndForwardOffset())
608+
self.turnNodes, self:getWorkWidth(), fm, bm, self:getTurnEndSideOffset(false), self:getTurnEndForwardOffset())
609609
local _, steeringLength = AIUtil.getSteeringParameters(self.vehicle)
610610
local targetNode, zOffset = self.turnContext:getTurnEndNodeAndOffsets(steeringLength)
611611
local context = PathfinderContext(self.vehicle):allowReverse(self:getAllowReversePathfinding())
@@ -670,7 +670,7 @@ end
670670
-----------------------------------------------------------------------------------------------------------------------
671671
--- Dynamic parameters (may change while driving)
672672
-----------------------------------------------------------------------------------------------------------------------
673-
function AIDriveStrategyFieldWorkCourse:getTurnEndSideOffset()
673+
function AIDriveStrategyFieldWorkCourse:getTurnEndSideOffset(isHeadlandTurn)
674674
return 0
675675
end
676676

scripts/ai/strategies/AIDriveStrategyPlowCourse.lua

Lines changed: 36 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -50,15 +50,15 @@ function AIDriveStrategyPlowCourse:getDriveData(dt, vX, vY, vZ)
5050
--- we still need to check if the rotation
5151
--- is in correct direction, as the course generator directed.
5252
self:rotatePlows()
53-
self:debug("Needs to wait until the plow has finished rotating.")
54-
self.state = self.states.ROTATING_PLOW
55-
else
53+
self:debug("Needs to wait until the plow has finished rotating.")
54+
self.state = self.states.ROTATING_PLOW
55+
else
5656
--- The plow can not be rotated,
5757
--- so we check if the plow is unfolded
5858
--- and try again to rotate the plow in the correct direction.
5959
self:debug("Plows have to be unfolded first!")
60-
self.state = self.states.UNFOLDING_PLOW
61-
end
60+
self.state = self.states.UNFOLDING_PLOW
61+
end
6262
elseif self.state == self.states.ROTATING_PLOW then
6363
self:setMaxSpeed(0)
6464
if not self:isPlowRotating() then
@@ -70,13 +70,13 @@ function AIDriveStrategyPlowCourse:getDriveData(dt, vX, vY, vZ)
7070
end
7171
elseif self.state == self.states.UNFOLDING_PLOW then
7272
self:setMaxSpeed(0)
73-
if self:isPlowRotationAllowed() then
73+
if self:isPlowRotationAllowed() then
7474
--- The Unfolding has finished and
7575
--- we need to check if the rotation is correct.
7676
self:rotatePlows()
7777
self:debug("Plow was unfolded and rotation can begin")
78-
self.state = self.states.ROTATING_PLOW
79-
elseif self:getCanContinueWork() then
78+
self.state = self.states.ROTATING_PLOW
79+
elseif self:getCanContinueWork() then
8080
--- Unfolding has finished and no extra rotation is needed.
8181
self:updatePlowOffset()
8282
self:startWaitingForLower()
@@ -104,7 +104,7 @@ end
104104
--- Updates the X Offset based on the plows attached.
105105
function AIDriveStrategyPlowCourse:updatePlowOffset()
106106
local xOffset = 0
107-
for _, controller in pairs(self.controllers) do
107+
for _, controller in pairs(self.controllers) do
108108
if controller.getAutomaticXOffset then
109109
local autoOffset = controller:getAutomaticXOffset()
110110
if autoOffset == nil then
@@ -127,8 +127,8 @@ end
127127
--- Is a plow currently rotating?
128128
---@return boolean
129129
function AIDriveStrategyPlowCourse:isPlowRotating()
130-
for _, controller in pairs(self.controllers) do
131-
if controller.isRotationActive and controller:isRotationActive() then
130+
for _, controller in pairs(self.controllers) do
131+
if controller.isRotationActive and controller:isRotationActive() then
132132
return true
133133
end
134134
end
@@ -139,8 +139,8 @@ end
139139
---@return boolean
140140
function AIDriveStrategyPlowCourse:isPlowRotationAllowed()
141141
local allowed = true
142-
for _, controller in pairs(self.controllers) do
143-
if controller.getIsPlowRotationAllowed and not controller:getIsPlowRotationAllowed() then
142+
for _, controller in pairs(self.controllers) do
143+
if controller.getIsPlowRotationAllowed and not controller:getIsPlowRotationAllowed() then
144144
allowed = false
145145
end
146146
end
@@ -153,29 +153,45 @@ function AIDriveStrategyPlowCourse:rotatePlows()
153153
local ix = self.ppc:getCurrentWaypointIx()
154154
local plowShouldBeOnTheLeft = self.course:shouldPlowBeOnTheLeft(ix)
155155
for _, controller in pairs(self.controllers) do
156-
if controller.rotate then
156+
if controller.rotate then
157157
controller:rotate(plowShouldBeOnTheLeft)
158158
end
159159
end
160160
end
161161

162+
--- Do we have at least one plow that can be rotated?
163+
---@return boolean
164+
function AIDriveStrategyPlowCourse:haveRotatablePlow()
165+
for _, controller in pairs(self.controllers) do
166+
if controller.isRotatablePlow and controller:isRotatablePlow() then
167+
return true
168+
end
169+
end
170+
return false
171+
end
172+
162173
-----------------------------------------------------------------------------------------------------------------------
163174
--- Dynamic parameters (may change while driving)
164175
-----------------------------------------------------------------------------------------------------------------------
165-
function AIDriveStrategyPlowCourse:getTurnEndSideOffset()
166-
if self:isWorking() then
176+
function AIDriveStrategyPlowCourse:getTurnEndSideOffset(isHeadlandTurn)
177+
-- on headland turns we do not rotate the plow, and since the course already has the offset, nothing to do,
178+
-- the context will calculate with the offset of the course already, no additional side offset is needed
179+
if self:isWorking() and not isHeadlandTurn and self:haveRotatablePlow() then
167180
self:updatePlowOffset()
168-
-- need the double tool offset as the turn end still has the current offset, after the rotation it'll be
169-
-- on the other side, (one toolOffsetX would put it to 0 only)
181+
-- need the double tool offset as the turn end waypoint still has the current offset, but after rotating,
182+
-- the plow will be on the other side, (one toolOffsetX would put it to 0 only)
183+
self:debug('Setting turn end side offset to %.2f for the plow', 2 * self.aiOffsetX)
170184
return 2 * self.aiOffsetX
171185
else
186+
self:debug('No turn end side offset, working: %s, headland turn %s, have rotatable plow %s ',
187+
tostring(self:isWorking()), tostring(isHeadlandTurn), tostring(self:haveRotatablePlow()))
172188
return 0
173189
end
174190
end
175191

176192
function AIDriveStrategyPlowCourse:updateFieldworkOffset(course)
177-
--- Ignore the tool offset setting.
178-
course:setOffset((self.aiOffsetX or 0), (self.aiOffsetZ or 0))
193+
--- Ignore the tool offset setting.
194+
course:setOffset((self.aiOffsetX or 0), (self.aiOffsetZ or 0))
179195
end
180196

181197
--- When we return from a turn, the offset is reverted and should immediately set, not waiting

scripts/ai/turns/TurnContext.lua

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ function TurnContext:init(vehicle, course, turnStartIx, turnEndIx, turnNodes, wo
8989

9090
self.dx, _, self.dz = localToLocal(self.turnEndWpNode.node, self.workEndNode, 0, 0, 0)
9191
self.leftTurn = self.dx > 0
92+
self.cornerOffsetX, _ = course:getOffset()
9293
self.plowShouldBeOnTheLeft = course:shouldPlowBeOnTheLeft(self.turnEndWpIx)
9394
self:debug('start ix = %d, back marker = %.1f, front marker = %.1f',
9495
turnStartIx, self.backMarkerDistance, self.frontMarkerDistance)
@@ -364,8 +365,8 @@ function TurnContext:createCorner(vehicle, r)
364365
local endAngleDeg = self:getAverageEndAngleDeg()
365366
CpUtil.debugVehicle(CpDebug.DBG_TURN, vehicle, 'start angle: %.1f, end angle: %.1f (from %.1f and %.1f)', self.beforeTurnStartWp.angle,
366367
endAngleDeg, self.turnEndWp.angle, self.afterTurnEndWp.angle)
367-
return Corner(vehicle, self.beforeTurnStartWp.angle, self.turnStartWp, endAngleDeg, self.turnEndWp, r,
368-
vehicle:getCpSettings().toolOffsetX:getValue())
368+
-- use the course X offset as that's the best indication of the current, actual offset X the vehicle is using
369+
return Corner(vehicle, self.beforeTurnStartWp.angle, self.turnStartWp, endAngleDeg, self.turnEndWp, r, self.cornerOffsetX)
369370
end
370371

371372

0 commit comments

Comments
 (0)