Skip to content

Commit

Permalink
Merge pull request #1122 from Courseplay/OrchardDriver
Browse files Browse the repository at this point in the history
Orchard driver
  • Loading branch information
Tensuko committed Mar 23, 2022
2 parents 7346b84 + 27e84fd commit 092c4ba
Show file tree
Hide file tree
Showing 26 changed files with 842 additions and 59 deletions.
6 changes: 5 additions & 1 deletion Courseplay.lua
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,9 @@ function Courseplay:update(dt)
end

function Courseplay:draw()
if not g_gui:getIsGuiVisible() then
g_vineScanner:draw()
end
g_devHelper:draw()
CpDebug:draw()
if not g_gui:getIsGuiVisible() then
Expand Down Expand Up @@ -218,7 +221,8 @@ function Courseplay:load()
g_assignedCoursesManager:registerXmlSchema()

--- Register additional AI messages.
AIMessageErrorIsFull.register()
AIMessageErrorIsFull.register()
g_vineScanner:setup()
end

------------------------------------------------------------------------------------------------------------------------
Expand Down
24 changes: 22 additions & 2 deletions config/VehicleConfigurations.xml
Original file line number Diff line number Diff line change
Expand Up @@ -90,9 +90,21 @@ You can define the following custom settings:
<!--[GIANTS]-->

<!-- Harvesters -->

<!--vehicles\newHolland-->
<Vehicle name="braud9070L.xml"
raiseLate="true"
lowerEarly="true"
turnRadius="5"
/>
<Vehicle name="braud9090X.xml"
raiseLate="true"
lowerEarly="true"
turnRadius="5"
/>
<!-- Implements -->

<!-- Agromasz POV 5XL -->
<!--\vehicles\agromasz-->
<Vehicle name="pov5xl.xml"
raiseLate="true"
lowerEarly="true"
Expand All @@ -102,7 +114,7 @@ You can define the following custom settings:
toolOffsetX="-2.7"
turnRadius="15"
/>
<!--\Vehicles\amazone-->
<!--\vehicles\amazone-->
<Vehicle name="citan15001C.xml"
implementWheelAlwaysOnGround = "true"
/>
Expand Down Expand Up @@ -210,8 +222,16 @@ You can define the following custom settings:
<Vehicle name="agrisemCultiplowPlatinum8m.xml"
turnRadius = "7"
/>
<!--\vehicles\proviti-->
<Vehicle name="mp122Ocea.xml"
toolOffsetX="-1.2"
raiseLate="true"
lowerEarly="true"
turnRadius="5"
/>

<!--Tractors-->

<!--\vehicles\stara-->
<Vehicle name="imperador3.xml"
ignoreCollisionBoxesWhenFolded="true"
Expand Down
26 changes: 26 additions & 0 deletions config/VineCourseGeneratorSettingsSetup.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<?xml version="1.0" encoding="UTF-8"?>


<!--
All the course generator settings can be setup here.
For documentation look up the CpSettingUtil.lua.
-->

<Settings prefixText="CP_vehicle_vineCourseGeneratorSetting_" autoUpdateGui="true">
<SettingSubTitle title="basic">
<Setting classType="AIParameterSettingList" name="vineCenterOffset" default = "0">
<Values>
<Value name="VINE_CENTER_OFFSET_LEFT">-1</Value>
<Value name="VINE_CENTER_OFFSET_CENTER">0</Value>
<Value name="VINE_CENTER_OFFSET_RIGHT">1</Value>
</Values>
<Texts>
<Text>left</Text>
<Text>center</Text>
<Text>right</Text>
</Texts>
</Setting>
<Setting classType="AIParameterSettingList" name="vineMultiTools" min="1" max="5" default="1"/>
<Setting classType="AIParameterSettingList" name="vineRowsToSkip" min="0" max="1" default="0"/>
</SettingSubTitle>
</Settings>
3 changes: 3 additions & 0 deletions modDesc.xml
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ Funktionen:
<sourceFile filename="scripts/field/CustomField.lua"/>
<sourceFile filename="scripts/field/CustomFieldManager.lua"/>
<sourceFile filename="scripts/field/FieldScanner.lua"/>
<sourceFile filename="scripts/field/VineScanner.lua"/>
<sourceFile filename="scripts/pathfinder/BinaryHeap.lua"/>
<sourceFile filename="scripts/pathfinder/State3D.lua"/>
<sourceFile filename="scripts/pathfinder/AnalyticSolution.lua"/>
Expand All @@ -97,6 +98,7 @@ Funktionen:
<sourceFile filename="scripts/ai/AIDriveStrategyCombineCourse.lua"/>
<sourceFile filename="scripts/ai/AIDriveStrategyPlowCourse.lua"/>
<sourceFile filename="scripts/ai/AIDriveStrategyFindBales.lua"/>
<sourceFile filename="scripts/ai/AIDriveStrategyVineFieldWorkCourse.lua"/>
<sourceFile filename="scripts/ai/AIMessages.lua"/>
<sourceFile filename="scripts/ai/Markers.lua"/>
<sourceFile filename="scripts/ai/ProximitySensor.lua"/>
Expand All @@ -116,6 +118,7 @@ Funktionen:
<sourceFile filename="scripts/ai/controllers/StonePickerController.lua"/>
<sourceFile filename="scripts/ai/controllers/CombineController.lua"/>
<sourceFile filename="scripts/ai/controllers/MotorController.lua"/>
<sourceFile filename="scripts/ai/controllers/VineCutterController.lua"/>
<sourceFile filename="scripts/ai/BaleToCollect.lua"/>
<sourceFile filename="scripts/ai/FillLevelManager.lua"/>
<sourceFile filename="scripts/ai/InfoTextsManager.lua"/>
Expand Down
2 changes: 1 addition & 1 deletion scripts/ai/AIDriveStrategyCombineCourse.lua
Original file line number Diff line number Diff line change
Expand Up @@ -1110,7 +1110,7 @@ function AIDriveStrategyCombineCourse:startTurn(ix)
elseif self.course:isOnConnectingTrack(ix) then
self:debug('Headland turn but this a connecting track, use normal turn maneuvers.')
AIDriveStrategyCombineCourse.superClass().startTurn(self, ix)
elseif self.course:isOnOutermostHeadland(ix) and self.settings.turnOnField:getValue() then
elseif self.course:isOnOutermostHeadland(ix) and self:isTurnOnFieldActive() then
self:debug('Creating a pocket in the corner so the combine stays on the field during the turn')
self.aiTurn = CombinePocketHeadlandTurn(self.vehicle, self, self.ppc, self.turnContext,
self.course, self:getWorkWidth())
Expand Down
7 changes: 7 additions & 0 deletions scripts/ai/AIDriveStrategyDriveToFieldWorkStart.lua
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,9 @@ function AIDriveStrategyDriveToFieldWorkStart:start(course, startIx, jobParamete
self.vehicle:prepareForAIDriving()
self:startCourseWithPathfinding(course, startIx)
end
--- Saves the course start position, so it can be given to the job instance.
local x, _, z = course:getWaypointPosition(startIx)
self.startPosition = {x = x, z = z}
end

function AIDriveStrategyDriveToFieldWorkStart:update()
Expand All @@ -94,6 +97,10 @@ function AIDriveStrategyDriveToFieldWorkStart:isWorkStartReached()
return self.state == self.states.WORK_START_REACHED
end

function AIDriveStrategyDriveToFieldWorkStart:getStartPosition()
return self.startPosition
end

function AIDriveStrategyDriveToFieldWorkStart:getDriveData(dt, vX, vY, vZ)
local moveForwards = not self.ppc:isReversing()
local gx, gz
Expand Down
7 changes: 6 additions & 1 deletion scripts/ai/AIDriveStrategyFieldWorkCourse.lua
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,7 @@ function AIDriveStrategyFieldWorkCourse:initializeImplementControllers(vehicle)
self:addImplementController(vehicle, CombineController, Combine, defaultDisabledStates)

self:addImplementController(vehicle, MotorController, Motorized, {})
self:addImplementController(vehicle, VineCutterController, VineCutter, defaultDisabledStates)
end

function AIDriveStrategyFieldWorkCourse:lowerImplements()
Expand Down Expand Up @@ -441,7 +442,7 @@ function AIDriveStrategyFieldWorkCourse:startTurn(ix)
self.ppc:setShortLookaheadDistance()
self.turnContext = TurnContext(self.course, ix, ix + 1, self.turnNodes, self:getWorkWidth(), fm, bm,
self:getTurnEndSideOffset(), self:getTurnEndForwardOffset())
if AITurn.canMakeKTurn(self.vehicle, self.turnContext, self.workWidth) then
if AITurn.canMakeKTurn(self.vehicle, self.turnContext, self.workWidth, self:isTurnOnFieldActive()) then
self.aiTurn = KTurn(self.vehicle, self, self.ppc, self.turnContext, self.workWidth)
else
self.aiTurn = CourseTurn(self.vehicle, self, self.ppc, self.turnContext, self.course, self.workWidth)
Expand Down Expand Up @@ -612,6 +613,10 @@ function AIDriveStrategyFieldWorkCourse:updateCpStatus(status)
end
end

function AIDriveStrategyFieldWorkCourse:isTurnOnFieldActive()
return self.settings.turnOnField:getValue()
end

-----------------------------------------------------------------------------------------------------------------------
--- Convoy management
-----------------------------------------------------------------------------------------------------------------------
Expand Down
42 changes: 42 additions & 0 deletions scripts/ai/AIDriveStrategyVineFieldWorkCourse.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
--[[
This file is part of Courseplay (https://github.com/Courseplay/Courseplay_FS22)
Copyright (C) 2021 Peter Vaiko
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Drive strategy for driving a vine field work course
]]--

---@class AIDriveStrategyVineFieldWorkCourse : AIDriveStrategyFieldWorkCourse
AIDriveStrategyVineFieldWorkCourse = {}
local AIDriveStrategyVineFieldWorkCourse_mt = Class(AIDriveStrategyVineFieldWorkCourse, AIDriveStrategyFieldWorkCourse)

function AIDriveStrategyVineFieldWorkCourse.new(customMt)
if customMt == nil then
customMt = AIDriveStrategyVineFieldWorkCourse_mt
end
local self = AIDriveStrategyFieldWorkCourse.new(customMt)

return self
end

function AIDriveStrategyVineFieldWorkCourse:setAIVehicle(...)
AIDriveStrategyVineFieldWorkCourse:superClass().setAIVehicle(self, ...)
end

--- Always disables turn on field.
function AIDriveStrategyVineFieldWorkCourse:isTurnOnFieldActive()
return false
end
12 changes: 9 additions & 3 deletions scripts/ai/Markers.lua
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ local function setBackMarkerNode(vehicle, measuredBackDistance)
debugText, backMarkerOffset, dBetweenRootAndReverserNode)
else
referenceNode = vehicle.rootNode
backMarkerOffset = - vehicle.sizeLength / 2 + vehicle.lengthOffset
backMarkerOffset = - vehicle.size.length / 2 + vehicle.size.lengthOffset
CpUtil.debugVehicle(CpDebug.DBG_IMPLEMENTS,'Using the vehicle\'s root node for the rear proximity sensor, %d m from root node', backMarkerOffset)
end

Expand Down Expand Up @@ -74,10 +74,16 @@ function Markers.setMarkerNodes(vehicle, measuredBackDistance)
end

function Markers.getFrontMarkerNode(vehicle)
return g_vehicleMarkers[vehicle] and g_vehicleMarkers[vehicle].frontMarkerNode
if not g_vehicleMarkers[vehicle] or not g_vehicleMarkers[vehicle].frontMarkerNode then
setFrontMarkerNode(vehicle)
end
return g_vehicleMarkers[vehicle].frontMarkerNode
end

function Markers.getBackMarkerNode(vehicle)
return g_vehicleMarkers[vehicle] and g_vehicleMarkers[vehicle].backMarkerNode
if not g_vehicleMarkers[vehicle] or not g_vehicleMarkers[vehicle].backMarkerNode then
setBackMarkerNode(vehicle)
end
return g_vehicleMarkers[vehicle].backMarkerNode
end

4 changes: 2 additions & 2 deletions scripts/ai/WorkWidthUtil.lua
Original file line number Diff line number Diff line change
Expand Up @@ -130,9 +130,9 @@ function WorkWidthUtil.getAIMarkers(object, logPrefix, suppressLog)
aiLeftMarker, aiRightMarker, aiBackMarker = WorkWidthUtil.getAIMarkersFromWorkAreas(object)
if not aiLeftMarker or not aiRightMarker or not aiLeftMarker then
if not suppressLog then
WorkWidthUtil.debug(object, logPrefix, 'has no work areas, giving up')
WorkWidthUtil.debug(object, logPrefix, 'has no work areas, giving up, will use front/back markers')
end
return nil, nil, nil
return Markers.getFrontMarkerNode(object), Markers.getFrontMarkerNode(object), Markers.getBackMarkerNode(object)
else
if not suppressLog then WorkWidthUtil.debug(object, logPrefix, 'AI markers from work area set') end
return aiLeftMarker, aiRightMarker, aiBackMarker
Expand Down
31 changes: 31 additions & 0 deletions scripts/ai/controllers/VineCutterController.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
--- Makes sure the vine harvester is stop, once it's full.
--- The vine harvester isn't using the combine drive strategy, as there is some bug.
---@class VineCutterController : ImplementController
VineCutterController = CpObject(ImplementController)

function VineCutterController:init(vehicle, vineCutter)
ImplementController.init(self, vehicle, vineCutter)
self.vineCutterSpec = vineCutter.spec_vineCutter
self.combine = AIUtil.getAllChildVehiclesWithSpecialization(vehicle, Combine)[1]
self.combineSpec = self.combine.spec_combine
end

function VineCutterController:getIsFull()
return self.combine:getFillUnitFreeCapacity(self.combineSpec.fillUnitIndex) <= 0
end

function VineCutterController:update()
if self:getIsFull() then
self.vehicle:stopCurrentAIJob(AIMessageErrorIsFull.new())
end
end

--- Waits while it's full or unloading finished.
function VineCutterController:getDriveData()
local maxSpeed
if self:getIsFull() then
maxSpeed = 0
end

return nil, nil, nil, maxSpeed
end
47 changes: 43 additions & 4 deletions scripts/ai/jobs/CpAIJobFieldWork.lua
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ function CpAIJobFieldWork.new(isServer, customMt)

self.lastPositionX, self.lastPositionZ = math.huge, math.huge
self.hasValidPosition = false

self.foundVines = nil
self.selectedFieldPlot = FieldPlot(g_currentMission.inGameMenu.ingameMap)
self.selectedFieldPlot:setVisible(false)
return self
Expand Down Expand Up @@ -80,12 +80,18 @@ function CpAIJobFieldWork:validateFieldSetup(isValid, errorMessage)

-- everything else is valid, now find the field
local tx, tz = self.fieldPositionParameter:getPosition()

self.hasValidPosition = false
self.foundVines = nil
local isCustomField
self.fieldPolygon, isCustomField = CpFieldUtil.getFieldPolygonAtWorldPosition(tx, tz)

if self.fieldPolygon then
self.hasValidPosition = true
self.foundVines = g_vineScanner:findVineNodesInField(self.fieldPolygon, tx, tz, self.customField~=nil)
if self.foundVines then
self.fieldPolygon = g_vineScanner:getCourseGeneratorVertices(0, tx, tz)
end

self.selectedFieldPlot:setWaypoints(self.fieldPolygon)
self.selectedFieldPlot:setVisible(true)
self.selectedFieldPlot:setBrightColor(true)
Expand Down Expand Up @@ -169,7 +175,24 @@ function CpAIJobFieldWork:onClickGenerateFieldWorkCourse()
local vehicle = self.vehicleParameter:getVehicle()
local settings = vehicle:getCourseGeneratorSettings()
local tx, tz = self.fieldPositionParameter:getPosition()
local status, ok, course = CourseGeneratorInterface.generate(self.fieldPolygon,
local status, ok, course
if self.foundVines then
local vineSettings = vehicle:getCpVineSettings()
local vertices, width, startingPoint, rowAngleDeg = g_vineScanner:getCourseGeneratorVertices(
vineSettings.vineCenterOffset:getValue(),
tx, tz
)
status, ok, course = CourseGeneratorInterface.generateVineCourse(vertices,
startingPoint,
width,
AIUtil.getTurningRadius(vehicle),
rowAngleDeg,
vineSettings.vineRowsToSkip:getValue(),
vineSettings.vineMultiTools:getValue()
)
else

status, ok, course = CourseGeneratorInterface.generate(self.fieldPolygon,
{x = tx, z = tz},
settings.isClockwise:getValue(),
settings.workWidth:getValue(),
Expand All @@ -182,12 +205,14 @@ function CpAIJobFieldWork:onClickGenerateFieldWorkCourse()
settings.rowDirection:getValue(),
settings.manualRowAngleDeg:getValue(),
settings.rowsToSkip:getValue(),
false,
settings.rowsPerLand:getValue(),
settings.islandBypassMode:getValue(),
settings.fieldMargin:getValue(),
settings.multiTools:getValue(),
self:isPipeOnLeftSide(vehicle)
)
)
end
CpUtil.debugFormat(CpDebug.DBG_COURSES, 'Course generator returned status %s, ok %s, course %s', status, ok, course)
if not status then
g_gui:showInfoDialog({
Expand Down Expand Up @@ -229,4 +254,18 @@ function CpAIJobFieldWork:stop(aiMessage)
if vehicle and vehicle.spec_aiFieldWorker.isActive then
vehicle.spec_aiFieldWorker.isActive = false
end
end

function CpAIJobFieldWork:getCourseGeneratorSettings()
local vehicle = self:getVehicle()
if self.foundVines then
return vehicle, vehicle:getCpVineSettingsTable(), CpCourseGeneratorSettings.getVineSettingSetup(vehicle)
end
return vehicle, vehicle:getCourseGeneratorSettingsTable(), CpCourseGeneratorSettings.getSettingSetup(vehicle)
end

function CpAIJobFieldWork:setStartPosition(startPosition)
if self.fieldWorkTask then
self.fieldWorkTask:setStartPosition(startPosition)
end
end
3 changes: 2 additions & 1 deletion scripts/ai/tasks/CpAITaskDriveTo.lua
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ function CpAITaskDriveTo:stop()
AITask.stop(self)
end

function CpAITaskDriveTo:onTargetReached()
function CpAITaskDriveTo:onTargetReached(startPosition)
self.isFinished = true
self.job:setStartPosition(startPosition)
end
Loading

0 comments on commit 092c4ba

Please sign in to comment.