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

Commit

Permalink
Merge pull request #8 from Courseplay/master
Browse files Browse the repository at this point in the history
French translation update
  • Loading branch information
polosubtil authored Apr 30, 2020
2 parents 8bb8c41 + 7a2715b commit fa0bc1d
Show file tree
Hide file tree
Showing 60 changed files with 4,809 additions and 7,396 deletions.
217 changes: 193 additions & 24 deletions AIDriver.lua

Large diffs are not rendered by default.

76 changes: 68 additions & 8 deletions AITurn.lua
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ end

--- Stuff we need to do during the turn no matter what turn type we are using
function AITurn:turn()
if self.driver:holdInTurnManeuver(false) then
if self.driver:holdInTurnManeuver(false, self.turnContext:isHeadlandCorner()) then
-- tell driver to stop if unloading or whatever
self.driver:setSpeed(0)
end
Expand Down Expand Up @@ -150,6 +150,20 @@ function AITurn:setReverseSpeed()
self.driver:setSpeed(self.vehicle.cp.speeds.reverse)
end

function AITurn:isForwardOnly()
return false
end

function AITurn:isFinishingRow()
return self.state == self.states.FINISHING_ROW
end

function AITurn:isEndingTurn()
-- include the direction too because some turns go to the ENDING_TURN state very early, while still driving
-- perpendicular to the row. This way this returns true really only when we are about to end the turn
return self.state == self.states.ENDING_TURN and self.turnContext:isDirectionCloseToEndDirection(self.driver:getDirectionNode(), 15)
end

function AITurn:drive(dt)
local iAmDriving = true
self:setForwardSpeed()
Expand Down Expand Up @@ -188,7 +202,7 @@ function AITurn:finishRow(dt)
self:startTurn()
self:debug('Row finished, starting turn.')
end
if self.driver:holdInTurnManeuver(true) then
if self.driver:holdInTurnManeuver(true, self.turnContext:isHeadlandCorner()) then
-- tell driver to stop while straw swath is active
self.driver:setSpeed(0)
end
Expand Down Expand Up @@ -250,14 +264,14 @@ function KTurn:turn(dt)
self.driver:driveVehicleBySteeringAngle(dt, true, 0, self.turnContext:isLeftTurn(), self.driver:getSpeed())
if self.turnContext:isLateralDistanceGreater(dx, turnRadius * 1.05) then
-- no need to reverse from here, we can make the turn
self.endingTurnCourse = self.turnContext:createEndingTurnCourse2(self.vehicle)
self.endingTurnCourse = self.turnContext:createEndingTurnCourse(self.vehicle)
self:debug('K Turn: dx = %.1f, r = %.1f, no need to reverse.', dx, turnRadius)
endTurn()
else
-- reverse until we can make turn to the turn end point
self.vehicle:raiseAIEvent("onAITurnProgress", "onAIImplementTurnProgress", 50, self.turnContext:isLeftTurn())
self.state = self.states.REVERSE
self.endingTurnCourse = self.turnContext:createEndingTurnCourse2(self.vehicle)
self.endingTurnCourse = self.turnContext:createEndingTurnCourse(self.vehicle)
self:debug('K Turn: dx = %.1f, r = %.1f, reversing now.', dx, turnRadius)
end
end
Expand Down Expand Up @@ -290,7 +304,7 @@ function KTurn:turn(dt)
end

function KTurn:onBlocked()
if self.driver:holdInTurnManeuver(false) then
if self.driver:holdInTurnManeuver(false, self.turnContext:isHeadlandCorner()) then
-- not really blocked just waiting for the straw for example
return
end
Expand Down Expand Up @@ -448,6 +462,14 @@ function CourseTurn:startTurn()
end
end

function CourseTurn:isForwardOnly()
return self.turnCourse and self.turnCourse:isForwardOnly()
end

function CourseTurn:getCourse()
return self.turnCourse
end

function CourseTurn:turn()

AITurn.turn(self)
Expand Down Expand Up @@ -492,7 +514,6 @@ function CourseTurn:onWaypointChange(ix)
end
end


--- When switching direction during a turn, especially when switching to reverse we want to make sure
--- that a towed implement is aligned with the reverse direction (already straight behind the tractor when
--- starting to reverse). Turn courses are generated with a very long alignment section to allow for this with
Expand Down Expand Up @@ -585,12 +606,51 @@ CombineCourseTurn = CpObject(CourseTurn)

---@param driver AIDriver
---@param turnContext TurnContext
function CombineCourseTurn:init(vehicle, driver, turnContext, fieldworkCourse)
CourseTurn.init(self, vehicle, driver, turnContext, fieldworkCourse,'CombineCourseTurn')
function CombineCourseTurn:init(vehicle, driver, turnContext, fieldworkCourse, name)
CourseTurn.init(self, vehicle, driver, turnContext, fieldworkCourse,name or 'CombineCourseTurn')
end

-- in a combine headland turn we want to raise the header after it reached the field edge (or headland edge on an inner
-- headland.
function CombineCourseTurn:getRaiseImplementNode()
return self.turnContext.lateWorkEndNode
end

--[[
Headland turn for combines on the outermost headland:
1. drive forward to the field edge or the headland path edge
2. start turning forward
3. reverse straight and then align with the direction after the
corner while reversing
4. forward to the turn start to continue on headland
]]
---@class CombinePocketHeadlandTurn : CombineCourseTurn
CombinePocketHeadlandTurn = CpObject(CombineCourseTurn)

---@param driver CombineAIDriver
---@param turnContext TurnContext
function CombinePocketHeadlandTurn:init(vehicle, driver, turnContext, fieldworkCourse)
CombineCourseTurn.init(self, vehicle, driver, turnContext, fieldworkCourse,'CombinePocketHeadlandTurn')
end

function CombinePocketHeadlandTurn:startTurn()
self.turnCourse = self.driver:createOuterHeadlandCornerCourse(self.turnContext)
if not self.turnCourse then
self:debug('Could not create pocket course, falling back to normal headland corner')
self:generateCalculatedTurn()
end
self.driver:startFieldworkCourseWithTemporaryCourse(self.turnCourse, self.turnContext.turnEndWpIx)
self.state = self.states.TURNING
end

--- When making a pocket we need to lower the header whenever driving forward
function CombinePocketHeadlandTurn:turn(dt)
AITurn.turn(self)
if self.driver.ppc:isReversing() then
self.driver:raiseImplements()
self.implementsLowered = nil
elseif not self.implementsLowered then
self.driver:lowerImplements()
self.implementsLowered = true
end
end
204 changes: 204 additions & 0 deletions BunkersiloManager.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,204 @@
---@class FieldManager
BunkerSiloManager = CpObject()

-- Constructor
function BunkerSiloManager:init()
print("BunkerSiloManager: init()")

end

g_bunkerSiloManager = BunkerSiloManager()


function BunkerSiloManager:createBunkerSiloMap(vehicle, Silo,width, height)
local sx,sz = Silo.bunkerSiloArea.sx,Silo.bunkerSiloArea.sz;
local wx,wz = Silo.bunkerSiloArea.wx,Silo.bunkerSiloArea.wz;
local hx,hz = Silo.bunkerSiloArea.hx,Silo.bunkerSiloArea.hz;
local sy = getTerrainHeightAtWorldPos(g_currentMission.terrainRootNode, sx, 1, sz);
local bunkerWidth = courseplay:distance(sx,sz, wx, wz)
local bunkerLength = courseplay:distance(sx,sz, hx, hz)
local startDistance = courseplay:distanceToPoint(vehicle, sx, sy, sz)
local endDistance = courseplay:distanceToPoint(vehicle, hx, sy, hz)
local widthDirX,widthDirY,widthDirZ,widthDistance = courseplay:getWorldDirection(sx,sy,sz, wx,sy,wz);
local heightDirX,heightDirY,heightDirZ,heightDistance = courseplay:getWorldDirection(sx,sy,sz, hx,sy,hz);

local widthCount = 0
if width then
widthCount =math.ceil(bunkerWidth/width)
else
widthCount =math.ceil(bunkerWidth/vehicle.cp.workWidth)
end

if vehicle.cp.mode10.leveling and courseplay:isEven(widthCount) then
widthCount = widthCount+1
end

local heightCount = math.ceil(bunkerLength/vehicle.cp.workWidth)
local unitWidth = bunkerWidth/widthCount
local unitHeigth = bunkerLength/heightCount
local heightLengthX = (Silo.bunkerSiloArea.hx-Silo.bunkerSiloArea.sx)/heightCount
local heightLengthZ = (Silo.bunkerSiloArea.hz-Silo.bunkerSiloArea.sz)/heightCount
local widthLengthX = (Silo.bunkerSiloArea.wx-Silo.bunkerSiloArea.sx)/widthCount
local widthLengthZ = (Silo.bunkerSiloArea.wz-Silo.bunkerSiloArea.sz)/widthCount
local getOffTheWall = 0.5;

local lastValidfillType = 0
local map = {}
for heightIndex = 1,heightCount do
map[heightIndex]={}
for widthIndex = 1,widthCount do
local newWx = sx + widthLengthX
local newWz = sz + widthLengthZ
local newHx = sx + heightLengthX
local newHz = sz + heightLengthZ

local wY = getTerrainHeightAtWorldPos(g_currentMission.terrainRootNode, newWx, 1, newWz);
local hY = getTerrainHeightAtWorldPos(g_currentMission.terrainRootNode, newHx, 1, newHz);
local fillType = DensityMapHeightUtil.getFillTypeAtLine(newWx, wY, newWz, newHx, hY, newHz, 5)
if lastValidfillType ~= fillType and fillType ~= 0 then
lastValidfillType = fillType
end
local newFillLevel = DensityMapHeightUtil.getFillLevelAtArea(fillType, sx, sz, newWx, newWz, newHx, newHz )
local bx = sx + (widthLengthX/2) + (heightLengthX/2)
local bz = sz + (widthLengthZ/2) + (heightLengthZ/2)
local offset = 0
if vehicle.cp.mode9TargetSilo and vehicle.cp.mode9TargetSilo.type and vehicle.cp.mode9TargetSilo.type == "heap" then
offset = unitWidth/2
else
if widthIndex == 1 then
offset = getOffTheWall+ (vehicle.cp.workWidth/2)
elseif widthIndex == widthCount then
offset = unitWidth- (getOffTheWall+ (vehicle.cp.workWidth/2))
else
offset = unitWidth/2
end
end
local cx,cz = sx +(widthDirX*offset)+(heightLengthX/2),sz +(widthDirZ*offset)+ (heightLengthZ/2)
if vehicle.cp.mode == courseplay.MODE_SHOVEL_FILL_AND_EMPTY and heightIndex == heightCount then
cx,cz = sx +(widthDirX*offset)+(heightLengthX),sz +(widthDirZ*offset)+ (heightLengthZ)
end
local unitArea = unitWidth*unitHeigth

map[heightIndex][widthIndex] ={
sx = sx;
sz = sz;
y = wY;
wx = newWx;
wz = newWz;
hx = newHx;
hz = newHz;
cx = cx;
cz = cz;
bx = bx;
bz = bz;
area = unitArea;
fillLevel = newFillLevel;
fillType = fillType;
bunkerLength = bunkerLength;
bunkerWidth = bunkerWidth;
}

sx = map[heightIndex][widthIndex].wx
sz = map[heightIndex][widthIndex].wz
end
sx = map[heightIndex][1].hx
sz = map[heightIndex][1].hz
end
if lastValidfillType > 0 then
courseplay:debug(('%s: Bunkersilo filled with %s(%i) will be devided in %d lines and %d columns'):format(nameNum(vehicle),g_fillTypeManager.indexToName[lastValidfillType], lastValidfillType, heightCount, widthCount), 10);
else
courseplay:debug(('%s: empty Bunkersilo will be devided in %d lines and %d columns'):format(nameNum(vehicle), heightCount, widthCount), 10);
end
--invert table
if endDistance < startDistance then
courseplay:debug(('%s: Bunkersilo will be approached from the back -> turn map'):format(nameNum(vehicle)), 10);
local newMap = {}
local lineCounter = #map
for lineIndex=1,lineCounter do
local newLineIndex = lineCounter+1-lineIndex;
--print(string.format("put line%s into line%s",tostring(lineIndex),tostring(newLineIndex)))
newMap[newLineIndex]={}
local columnCount = #map[lineIndex]
for columnIndex =1, columnCount do
--print(string.format(" put column%s into column%s",tostring(columnIndex),tostring(columnCount+1-columnIndex)))
newMap[newLineIndex][columnCount+1-columnIndex] = map[lineIndex][columnIndex]
end
end
map = newMap
end
return map
end

function BunkerSiloManager:getTargetBunkerSiloByPointOnCourse(course,forcedPoint)
local pointIndex = forcedPoint or 1 ;
local x,_,z = course:getWaypointPosition(pointIndex)
local tx,tz = x,z + 0.50
local p1x,p1z,p2x,p2z,p1y,p2y = 0,0,0,0,0,0
if g_currentMission.bunkerSilos ~= nil then
for _, bunker in pairs(g_currentMission.bunkerSilos) do
local x1,z1 = bunker.bunkerSiloArea.sx,bunker.bunkerSiloArea.sz
local x2,z2 = bunker.bunkerSiloArea.wx,bunker.bunkerSiloArea.wz
local x3,z3 = bunker.bunkerSiloArea.hx,bunker.bunkerSiloArea.hz
bunker.type = "silo"
if MathUtil.hasRectangleLineIntersection2D(x1,z1,x2-x1,z2-z1,x3-x1,z3-z1,x,z,tx-x,tz-z) then
return bunker
end
end
end
end

function BunkerSiloManager:getBestColumnToFill(siloMap)
local leastFillLevel = math.huge
local leastColumnIndex = 0
for columnIndex=2,#siloMap[1]-1 do
local currentFillLevel = 0
for lineIndex=1,#siloMap do
local fillUnit = siloMap[lineIndex][columnIndex]
currentFillLevel = currentFillLevel + fillUnit.fillLevel
--print(string.format("check:line %s, column %s fillLevel:%s",tostring(lineIndex),tostring(columnIndex),tostring(fillUnit.fillLevel)))
end
--print("column:"..tostring(columnIndex).." :"..tostring(currentFillLevel))
if currentFillLevel<leastFillLevel then
leastFillLevel = currentFillLevel
leastColumnIndex = columnIndex
end

end
return leastColumnIndex
end

function BunkerSiloManager:setOffsetsPerWayPoint(course,siloMap,bestColumn,ix)
local points = {}
local foundFirst = 0
for index=ix,course:getNumberOfWaypoints() do
if self:getTargetBunkerSiloByPointOnCourse(course,index)~= nil then
local closest,cx,cz = 0,0,0
local leastDistance = math.huge
for lineIndex=1,#siloMap do
local fillUnit= siloMap[lineIndex][bestColumn]
local x,z = fillUnit.cx,fillUnit.cz
local distance = course:getDistanceBetweenPointAndWaypoint(x,z, index)
if leastDistance > distance then
leastDistance = distance
closest = lineIndex
cx,cz = x,z
end
end
local y = getTerrainHeightAtWorldPos(g_currentMission.terrainRootNode, cx, 1, cz);
course.waypoints[index].x = cx
course.waypoints[index].z = cz
--local offsetX,_,offsetZ = course:worldToWaypointLocal(index, cx, y, cz)
points[index]= true
--print(string.format("set %s new",tostring(index)))
if foundFirst == 0 then
foundFirst = index
end
elseif foundFirst ~= 0 then
break
end
end

return foundFirst
end


Loading

0 comments on commit fa0bc1d

Please sign in to comment.