Skip to content

Commit 6754007

Browse files
author
Peter Vaiko
committed
refactor: plow rotation logic unified
1 parent ed603ef commit 6754007

6 files changed

Lines changed: 47 additions & 42 deletions

File tree

scripts/Course.lua

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -635,6 +635,29 @@ function Course:isNextTurnLeft(ix)
635635
end
636636
end
637637

638+
--- Should the plow be rotated to the left at the waypoint ix?
639+
--- On the headland just check which side was worked last, on the center, check the direction of the next turn
640+
--- as at the first pass both sides are unworked and need some other indication on which side the plow should be
641+
function Course:shouldPlowBeOnTheLeft(ix)
642+
local plowShouldBeOnTheLeft
643+
if self:isOnHeadland(ix) then
644+
local clockwise = self:isOnClockwiseHeadland(ix)
645+
plowShouldBeOnTheLeft = not clockwise
646+
CpUtil.debugVehicle(CpDebug.DBG_TURN, self.vehicle, 'On a headland (clockwise %s), plow should be on the left %s', tostring(clockwise), tostring(plowShouldBeOnTheLeft))
647+
else
648+
local isNextTurnLeft = self:isNextTurnLeft(ix)
649+
if isNextTurnLeft == nil then
650+
-- don't know if left or right, so just use the last worked side
651+
plowShouldBeOnTheLeft = self:isLeftSideWorked(ix)
652+
CpUtil.debugVehicle(CpDebug.DBG_TURN, self.vehicle, 'On the center, next turn direction unknown, plow should be on the left %s', tostring(plowShouldBeOnTheLeft))
653+
else
654+
plowShouldBeOnTheLeft = not isNextTurnLeft
655+
CpUtil.debugVehicle(CpDebug.DBG_TURN, self.vehicle, 'On the center, plow should be on the left %s', tostring(plowShouldBeOnTheLeft))
656+
end
657+
end
658+
return plowShouldBeOnTheLeft
659+
end
660+
638661
function Course:getIxRollover(ix)
639662
if ix > #self.waypoints then
640663
return ix - #self.waypoints
@@ -1455,7 +1478,7 @@ end
14551478
local function calculateYRot(waypoints, i)
14561479
local x1, z1 = waypoints[i].x, waypoints[i].z
14571480
local x2, z2 = waypoints[i + 1].x, waypoints[i + 1].z
1458-
if (x1 - x2) == 0 and (z1 - z2) == 0 then
1481+
if (x1 - x2) == 0 and (z1 - z2) == 0 then
14591482
-- Divide by zero fix ..
14601483
return 0
14611484
end
@@ -1810,13 +1833,13 @@ function Course.MultiVehicleData.createFromStream(stream, nVehicles)
18101833
end
18111834

18121835
function Course.MultiVehicleData.getAllowedPositions(nMultiToolVehicles)
1813-
if nMultiToolVehicles == 2 then
1836+
if nMultiToolVehicles == 2 then
18141837
return {-1,1}
1815-
elseif nMultiToolVehicles == 3 then
1838+
elseif nMultiToolVehicles == 3 then
18161839
return {-1,0,1}
1817-
elseif nMultiToolVehicles == 4 then
1840+
elseif nMultiToolVehicles == 4 then
18181841
return {-2,-1,1,2}
1819-
elseif nMultiToolVehicles == 5 then
1842+
elseif nMultiToolVehicles == 5 then
18201843
return {-2,-1,0,1,2}
18211844
end
18221845
return {0}

scripts/ai/controllers/PlowController.lua

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ function PlowController:init(vehicle, implement)
1212
-- the plow was not rotated into the working position before lowering. If that's the case, onLowering will
1313
-- rotate it but it needs to know which direction to lower, which, however is not known at that point
1414
-- anymore
15-
self.lastTurnIsLeftTurn = CpTemporaryObject()
15+
self.lastPlowSide = CpTemporaryObject()
1616
end
1717

1818

@@ -115,38 +115,38 @@ end
115115
-- TODO: this whole magic hack would not be necessary if we moved the actual lowering into onTurnEndProgress()
116116
function PlowController:onLowering()
117117
-- if we just turned (that is, not starting to work)
118-
local lastTurnIsLeftTurn = self.lastTurnIsLeftTurn:get()
119-
if lastTurnIsLeftTurn ~= nil and
118+
local lastPlowSide = self.lastPlowSide:get()
119+
if lastPlowSide ~= nil and
120120
self:isRotatablePlow() and not self:isFullyRotated() and not self:isRotationActive() then
121-
self:debug('Lowering, rotating plow to working position (last turn is left %s).', lastTurnIsLeftTurn)
121+
self:debug('Lowering, rotating plow to working position (plow in last turn was left %s).', lastPlowSide)
122122
-- rotation direction depends on the direction of the last turn
123-
self.implement:setRotationMax(lastTurnIsLeftTurn)
123+
self.implement:setRotationMax(lastPlowSide)
124124
end
125125
end
126126

127127
--- This is called in every loop when we approach the start of the row, the location where
128-
--- the plow must be lowered. Currently AIDriveStrategyFieldworkCourse takes care of the lowering,
128+
--- the plow must be lowered. Currently the WorkStarter takes care of the lowering,
129129
--- here we only make sure that the plow is rotated to the work position (from the center position)
130130
--- in time.
131131
---@param workStartNode number node where the work starts as calculated by TurnContext
132132
---@param reversing boolean driving in reverse now
133133
---@param shouldLower boolean the implement should be lowered as we are close to the work start (this
134134
--- should most likely be calculated here in the controller, but for now, we get it from an argument
135-
---@param isLeftTurn boolean is this a left turn?
136-
function PlowController:onTurnEndProgress(workStartNode, reversing, shouldLower, isLeftTurn)
137-
self.lastTurnIsLeftTurn:set(isLeftTurn or false, 2000)
135+
---@param shouldBeOnTheLeft boolean should the plow be turned to the left to be in the good position after the turn?
136+
function PlowController:onTurnEndProgress(workStartNode, reversing, shouldLower, shouldBeOnTheLeft)
137+
self.lastPlowSide:set(shouldBeOnTheLeft or false, 2000)
138138
if self:isRotatablePlow() and not self:isFullyRotated() and not self:isRotationActive() then
139139
-- more or less aligned with the first waypoint of the row, start rotating to working position
140140
if CpMathUtil.isSameDirection(self.implement.rootNode, workStartNode, 30) or shouldLower then
141141
if self.towed then
142142
-- let towed plows remain in the center position while reversing to the start of the row
143143
if not reversing then
144144
self:debug('Rotating towed plow to working position.')
145-
self.implement:setRotationMax(isLeftTurn)
145+
self.implement:setRotationMax(shouldBeOnTheLeft)
146146
end
147147
else
148148
self:debug('Rotating hitch-mounted plow to working position.')
149-
self.implement:setRotationMax(isLeftTurn)
149+
self.implement:setRotationMax(shouldBeOnTheLeft)
150150
end
151151
end
152152
end

scripts/ai/strategies/AIDriveStrategyPlowCourse.lua

Lines changed: 1 addition & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -150,25 +150,8 @@ end
150150
--- Initial plow rotation based on the ridge marker side selection by the course generator.
151151
function AIDriveStrategyPlowCourse:rotatePlows()
152152
self:debug('Starting work: check if plow needs to be turned.')
153-
-- on the headland just check which side was worked last, on the center, check the direction of the next turn
154-
-- as at the first pass both sides are unworked and need some other indication on which side the plow should be
155153
local ix = self.ppc:getCurrentWaypointIx()
156-
local plowShouldBeOnTheLeft
157-
if self.course:isOnHeadland(ix) then
158-
local clockwise = self.course:isOnClockwiseHeadland(ix)
159-
plowShouldBeOnTheLeft = not clockwise
160-
self:debug('On a headland (clockwise %s), plow should be on the left %s', tostring(clockwise), tostring(plowShouldBeOnTheLeft))
161-
else
162-
local isNextTurnLeft = self.course:isNextTurnLeft(ix)
163-
if isNextTurnLeft == nil then
164-
-- don't know if left or right, so just use the last worked side
165-
plowShouldBeOnTheLeft = self.course:isLeftSideWorked(ix)
166-
self:debug('On the center, next turn direction unknown, plow should be on the left %s', tostring(plowShouldBeOnTheLeft))
167-
else
168-
plowShouldBeOnTheLeft = not isNextTurnLeft
169-
self:debug('On the center, plow should be on the left %s', tostring(plowShouldBeOnTheLeft))
170-
end
171-
end
154+
local plowShouldBeOnTheLeft = self.course:shouldPlowBeOnTheLeft(ix)
172155
for _, controller in pairs(self.controllers) do
173156
if controller.rotate then
174157
controller:rotate(plowShouldBeOnTheLeft)

scripts/ai/turns/AITurn.lua

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1000,8 +1000,6 @@ function StartRowOnly:getDriveData()
10001000
TurnManeuver.LOWER_IMPLEMENT_AT_TURN_END) then
10011001
self.state = self.states.APPROACHING_ROW
10021002
self:debug('Approaching row')
1003-
self.driveStrategy:raiseControllerEvent(AIDriveStrategyCourse.onTurnEndProgressEvent,
1004-
self:getLowerImplementNode(), self.ppc:isReversing(), true, not self.turnContext:isNextTurnLeft())
10051003
end
10061004
elseif self.state == self.states.APPROACHING_ROW then
10071005
self.workStartHandler:lowerImplementsAsNeeded(self:getLowerImplementNode(), self.ppc:isReversing())

scripts/ai/turns/TurnContext.lua

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -89,7 +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.nextTurnLeft = course:isNextTurnLeft(turnEndIx)
92+
self.plowShouldBeOnTheLeft = course:shouldPlowBeOnTheLeft(self.turnEndWpIx)
9393
self:debug('start ix = %d, back marker = %.1f, front marker = %.1f',
9494
turnStartIx, self.backMarkerDistance, self.frontMarkerDistance)
9595
end
@@ -238,10 +238,6 @@ function TurnContext:getHeadlandAngle()
238238
return math.abs(CpMathUtil.getDeltaAngle(math.rad(self.turnEndWp.angle), math.rad(self.turnStartWp.angle)))
239239
end
240240

241-
function TurnContext:isNextTurnLeft()
242-
return self.nextTurnLeft
243-
end
244-
245241
function TurnContext:isHeadlandCorner()
246242
-- in headland turns there's no significant direction change at the turn start waypoint, as the turn end waypoint
247243
-- marks the actual corner. In a non-headland turn (usually 180) there is about 90 degrees direction change at
@@ -282,6 +278,11 @@ function TurnContext:isLeftTurn()
282278
end
283279
end
284280

281+
--- Should the plow be rotated to the left after the turn?
282+
function TurnContext:shouldPlowBeOnTheLeft()
283+
return self.plowShouldBeOnTheLeft
284+
end
285+
285286
---@return number offset of the turn end in meters forward (>0) or back (<0)
286287
function TurnContext:getTurnEndForwardOffset()
287288
return self.dz

scripts/ai/turns/WorkStartHandler.lua

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ function WorkStartHandler:lowerImplementsAsNeeded(workStartNode, reversing)
5858
-- this must be called before the implement is lowered, for instance to rotate the plow before lowering it.
5959
-- ideally, this should all be in the PlowController since it is internal to the plow.
6060
self.driveStrategy:raiseControllerEvent(AIDriveStrategyCourse.onTurnEndProgressEvent,
61-
workStartNode, reversing, shouldLowerThis, self.turnContext:isLeftTurn())
61+
workStartNode, reversing, shouldLowerThis, self.turnContext:shouldPlowBeOnTheLeft())
6262
if reversing then
6363
dz = math.max(dz, thisDz)
6464
allShouldBeLowered = allShouldBeLowered and shouldLowerThis

0 commit comments

Comments
 (0)