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 #7532 from Courseplay/MP_fixes
Browse files Browse the repository at this point in the history
Div MP Changes
  • Loading branch information
schwiti6190 authored Oct 7, 2021
2 parents 19da405 + 7966625 commit 2e9766a
Show file tree
Hide file tree
Showing 30 changed files with 729 additions and 588 deletions.
8 changes: 5 additions & 3 deletions AIDriver.lua
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ function AIDriver:init(vehicle)
end
self.aiDriverData = vehicle.cp.aiDriverData
self:debug('creating AIDriver')
self.maxDrivingVectorLength = self.vehicle.cp.turnDiameter
self.maxDrivingVectorLength = self.vehicle.cp.settings.turnDiameter:get()
---@type PurePursuitController
self.ppc = PurePursuitController(self.vehicle)
self.vehicle.cp.ppc = self.ppc
Expand All @@ -177,6 +177,7 @@ function AIDriver:init(vehicle)
self.activeMsgReferences = {}

self.settings = self.vehicle.cp.settings
self.courseGeneratorSettings = self.vehicle.cp.courseGeneratorSettings
-- make sure all vehicle settings are valid for this mode
if self.settings then
self:debug('Validating current settings...')
Expand Down Expand Up @@ -969,7 +970,7 @@ end
---@param course Course
function AIDriver:isAlignmentCourseNeeded(course, ix)
local d = course:getDistanceBetweenVehicleAndWaypoint(self.vehicle, ix)
return d > self.vehicle.cp.turnDiameter
return d > self.settings.turnDiameter:get()
end

function AIDriver:startTurn(ix)
Expand Down Expand Up @@ -1557,7 +1558,8 @@ function AIDriver:startCourseWithPathfinding(course, ix, zOffset, fieldNum, alwa
local d = course:getDistanceBetweenVehicleAndWaypoint(self.vehicle, ix)
-- always enforce a minimum distance needed for pathfinding, otherwise we'll end up with vehicles making
-- a circle just to end up 50 cm to the left or right...
local pathfindingRange = alwaysUsePathfinding and self.vehicle.cp.turnDiameter or (3 * self.vehicle.cp.turnDiameter)
local turnDiameter = self.settings.turnDiameter:get()
local pathfindingRange = alwaysUsePathfinding and turnDiameter or (3 * turnDiameter)
if not alwaysUsePathfinding and d < pathfindingRange then
self:debug('Too close to target (%.1fm), will not perform pathfinding', d)
return self:startCourseWithAlignment(course, ix)
Expand Down
9 changes: 6 additions & 3 deletions AIDriverUtil.lua
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,8 @@ function AIDriverUtil.calculateTightTurnOffset(vehicle, course, previousOffset,
-- limit the radius we are trying to follow to the vehicle's turn radius.
-- TODO: there's some potential here as the towed implement can move on a radius less than the vehicle's
-- turn radius so this limit may be too pessimistic
r = math.max(r, vehicle.cp.turnDiameter / 2)
local turnDiameter = vehicle.cp.settings.turnDiameter:get()
r = math.max(r, turnDiameter / 2)

local towBarLength = AIDriverUtil.getTowBarLength(vehicle)

Expand Down Expand Up @@ -173,8 +174,10 @@ function AIDriverUtil.getTurningRadius(vehicle)
radius = g_vehicleConfigurations:get(vehicle, 'turnRadius')
courseplay.debugVehicle(courseplay.DBG_IMPLEMENTS, vehicle, ' turnRadius set from configfile to %.1f', radius)
end
if vehicle.cp.turnDiameterAutoMode == false and vehicle.cp.turnDiameter ~= nil then
radius = vehicle.cp.turnDiameter / 2

local turnDiameterSetting = vehicle.cp.settings.turnDiameter
if not turnDiameterSetting:isAutomaticActive() then
radius = turnDiameterSetting:get() / 2
courseplay.debugVehicle(courseplay.DBG_IMPLEMENTS, vehicle, ' turnRadius manually set to %.1f', radius)
end

Expand Down
15 changes: 9 additions & 6 deletions AITurn.lua
Original file line number Diff line number Diff line change
Expand Up @@ -112,9 +112,10 @@ function AITurn.canMakeKTurn(vehicle, turnContext)
courseplay.debugVehicle(AITurn.debugChannel, vehicle, 'Headland turn, let turn.lua drive for now.')
return false
end
if vehicle.cp.turnDiameter <= math.abs(turnContext.dx) then
local turnDiameter = vehicle.cp.settings.turnDiameter:get()
if turnDiameter <= math.abs(turnContext.dx) then
courseplay.debugVehicle(AITurn.debugChannel, vehicle, 'wide turn with no reversing (turn diameter = %.1f, dx = %.1f, let turn.lua do that for now.',
vehicle.cp.turnDiameter, math.abs(turnContext.dx))
turnDiameter, math.abs(turnContext.dx))
return true
end
if not AIVehicleUtil.getAttachedImplementsAllowTurnBackward(vehicle) then
Expand Down Expand Up @@ -248,8 +249,8 @@ function KTurn:turn(dt)
end

AITurn.turn(self)

local turnRadius = self.vehicle.cp.turnDiameter / 2
local turnDiameter = self.vehicle.cp.settings.turnDiameter:get()
local turnRadius = turnDiameter / 2
if self.state == self.states.FORWARD then
local dx, _, dz = self.turnContext:getLocalPositionFromTurnEnd(self.driver:getDirectionNode())
self:setForwardSpeed()
Expand Down Expand Up @@ -337,7 +338,8 @@ function CombineHeadlandTurn:init(vehicle, driver, turnContext)
self:addState('FORWARD')
self:addState('REVERSE_STRAIGHT')
self:addState('REVERSE_ARC')
self.turnRadius = self.vehicle.cp.turnDiameter / 2
local turnDiameter = self.vehicle.cp.settings.turnDiameter:get()
self.turnRadius = turnDiameter / 2
self.cornerAngleToTurn = turnContext:getCornerAngleToTurn()
self.angleToTurnInReverse = math.abs(self.cornerAngleToTurn / 2)
self.dxToStartReverseTurn = self.turnRadius - math.abs(self.turnRadius - self.turnRadius * math.cos(self.cornerAngleToTurn))
Expand Down Expand Up @@ -630,7 +632,8 @@ end
---@param turnContext TurnContext
function CombinePocketHeadlandTurn:generatePocketHeadlandTurn(turnContext)
local cornerWaypoints = {}
local turnRadius = self.vehicle.cp.turnDiameter / 2
local turnDiameter = self.vehicle.cp.settings.turnDiameter:get()
local turnRadius = turnDiameter / 2
-- this is how far we have to cut into the next headland (the position where the header will be after the turn)
local offset = math.min(turnRadius + turnContext.frontMarkerDistance, self.vehicle.cp.workWidth)
local corner = turnContext:createCorner(self.vehicle, turnRadius)
Expand Down
2 changes: 1 addition & 1 deletion BaleCollectorAIDriver.lua
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ function BaleCollectorAIDriver:findClosestBale(bales)
if bale:isStillValid() then
local _, _, _, d = bale:getPositionInfoFromNode(AIDriverUtil.getDirectionNode(self.vehicle))
self:debug('%d. bale (%d, %s) in %.1f m', i, bale:getId(), bale:getBaleObject(), d)
if d < self.vehicle.cp.turnDiameter * 2 then
if d < self.settings.turnDiameter:get() * 2 then
-- if it is really close, check the length of the Dubins path
-- as we may need to drive a loop first to get to it
d = self:getDubinsPathLengthToBale(bale)
Expand Down
2 changes: 1 addition & 1 deletion CombineAIDriver.lua
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ function CombineAIDriver:init(vehicle)
self.pullBackRightSideOffset = math.abs(self.pipeOffsetX) - self.vehicle.cp.workWidth / 2 + 5
self.pullBackRightSideOffset = self.pipeOnLeftSide and self.pullBackRightSideOffset or -self.pullBackRightSideOffset
-- should be at pullBackRightSideOffset to the right or left at pullBackDistanceStart
self.pullBackDistanceStart = self.vehicle.cp.turnDiameter --* 0.7
self.pullBackDistanceStart = self.settings.turnDiameter:get() --* 0.7
-- and back up another bit
self.pullBackDistanceEnd = self.pullBackDistanceStart + 5
-- when making a pocket, how far to back up before changing to forward
Expand Down
4 changes: 2 additions & 2 deletions CombineUnloadAIDriver.lua
Original file line number Diff line number Diff line change
Expand Up @@ -446,7 +446,7 @@ function CombineUnloadAIDriver:driveOnField(dt)
elseif self.onFieldState == self.states.MOVE_BACK_FULL then
local _, dx, dz = self:getDistanceFromCombine(self.combineJustUnloaded)
-- drive back way further if we are behind a chopper to have room
local dDriveBack = math.abs(dx) < 3 and 0.75 * self.vehicle.cp.turnDiameter or -10
local dDriveBack = math.abs(dx) < 3 and 0.75 * self.settings.turnDiameter:get() or -10
if dz > dDriveBack then
self:startUnloadCourse()
end
Expand Down Expand Up @@ -1496,7 +1496,7 @@ function CombineUnloadAIDriver:startPathfindingToTurnEnd(xOffset, zOffset)
local turnEndNode, startOffset, goalOffset = self.turnContext:getTurnEndNodeAndOffsets(self.vehicle)
-- ignore combine for pathfinding, it is moving anyway and our turn functions make sure we won't hit it
self.pathfinder, done, path, goalNodeInvalid = PathfinderUtil.findPathForTurn(self.vehicle, startOffset, turnEndNode, goalOffset,
self.vehicle.cp.turnDiameter / 2, self:getAllowReversePathfinding(), self.followCourse, {self.combineToUnload})
self.settings.turnDiameter:get() / 2, self:getAllowReversePathfinding(), self.followCourse, {self.combineToUnload})
if done then
return self:onPathfindingDoneToTurnEnd(path, goalNodeInvalid)
else
Expand Down
2 changes: 1 addition & 1 deletion DevHelper.lua
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,7 @@ function DevHelper:startPathfinding()
if self.vehicle and self.vehicle.cp.driver and self.vehicle.cp.driver.fieldworkCourse then
self:debug('Starting pathfinding for turn between %s and %s', tostring(self.start), tostring(self.goal))
self.pathfinder, done, path = PathfinderUtil.findPathForTurn(self.vehicle, 0, self.goalNode, 0,
1.05 * self.vehicle.cp.turnDiameter / 2, false, self.vehicle.cp.driver.fieldworkCourse)
1.05 * self.vehicle.cp.settings.turnDiameter:get() / 2, false, self.vehicle.cp.driver.fieldworkCourse)
else
self:debug('Starting pathfinding (no reverse) between %s and %s, field %d',
tostring(self.start), tostring(self.goal), self.fieldNumForPathfinding or 0)
Expand Down
60 changes: 0 additions & 60 deletions Events/GlobalSettingsEvent.lua

This file was deleted.

141 changes: 141 additions & 0 deletions Events/SettingEvent.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
--- This event is used to synchronize Setting changes on run time.
--- Every setting event requires:
--- - a container name (parentName)
--- - a setting name
--- - an event index for the setting
--- - the value
---
SettingEvent = {}
local SettingEvent_mt = Class(SettingEvent, Event)

InitEventClass(SettingEvent, "SettingEvent")

function SettingEvent:emptyNew()
local self = Event:new(SettingEvent_mt)
self.className = "SettingEvent"
return self
end

--- Creates a new Event
---@param vehicle table
---@param setting Setting
---@param eventData table
---@param value any
function SettingEvent:new(vehicle,setting,eventData,value)
self.vehicle = vehicle
self.value = value
self.parentName,self.name,self.eventIx,self.writeFunc = self.decodeEventData(setting,eventData)
self.debug("SettingEvent:new()")
return self
end

--- Reads the serialized data on the receiving end of the event.
function SettingEvent:readStream(streamId, connection) -- wird aufgerufen wenn mich ein Event erreicht
self.vehicle = nil
if streamReadBool(streamId) then
self.vehicle = NetworkUtil.getObject(streamReadInt32(streamId))
self.debugVehicle(self.vehicle,"Vehicle setting")
else
self.debug("Global setting")
end

self.parentName = streamReadString(streamId)
self.name = streamReadString(streamId)
self.eventIx = streamReadUInt8(streamId)

self.setting,self.eventData = self.encodeEventData(self.vehicle,self.parentName,self.name,self.eventIx)

if self.eventData.readFunc then
self.value = self.eventData.readFunc(streamId)
end

self.debug("SettingEvent:readStream()")
self.debug("Parent name: %s, Setting name: %s, value: %s, eventIx: %d",self.parentName, self.name, tostring(self.value),self.eventIx)

self:run(connection);
end

--- Writes the serialized data from the sender.
function SettingEvent:writeStream(streamId, connection) -- Wird aufgrufen wenn ich ein event verschicke (merke: reihenfolge der Daten muss mit der bei readStream uebereinstimmen
self.debug("SettingEvent:writeStream()")
if self.vehicle ~= nil then
self.debugVehicle(self.vehicle,"Vehicle setting")
streamWriteBool(streamId, true)
streamWriteInt32(streamId, NetworkUtil.getObjectId(self.vehicle))
else
self.debug("Global setting")
streamWriteBool(streamId, false)
end
self.debug("Parent name: %s, Setting name: %s, value: %s, eventIx: %d",self.parentName, self.name, tostring(self.value),self.eventIx)
streamWriteString(streamId, self.parentName)
streamWriteString(streamId, self.name)
streamWriteUInt8(streamId,self.eventIx)
if self.writeFunc then
self.writeFunc(streamId, self.value)
end
end

--- Runs the event on the receiving end of the event.
function SettingEvent:run(connection) -- wir fuehren das empfangene event aus
self.debug("SettingEvent:run()")
self.eventData.eventFunc(self.setting,self.value)

--- If the receiver was the client make sure every clients gets also updated.
if not connection:getIsServer() then
self.debug("Send SettingEvent to clients")
g_server:broadcastEvent(SettingEvent:new(self.vehicle,self.setting,self.eventData,self.value), nil, connection, self.vehicle)
end;
end

--- Sends an Event either:
--- - from the server to all clients or
--- - from the client to the server
---@param vehicle table
---@param setting Setting
---@param eventData table an event registers on the setting
---@param value any
function SettingEvent.sendEvent(vehicle,setting,eventData,value)
if g_server ~= nil then
SettingEvent.debug("Send SettingEvent to clients")
SettingEvent.debug("Setting name: %s",setting:getName())
g_server:broadcastEvent(SettingEvent:new(vehicle,setting,eventData,value), nil, nil, vehicle)
else
SettingEvent.debug("Send SettingEvent to server")
SettingEvent.debug("Setting name: %s",setting:getName())
g_client:getServerConnection():sendEvent(SettingEvent:new(vehicle,setting,eventData,value))
end;
end

function SettingEvent.debug(...)
courseplay.debugFormat(courseplay.DBG_MULTIPLAYER,...)
end

function SettingEvent.debugVehicle(vehicle,...)
courseplay.debugVehicle(courseplay.DBG_MULTIPLAYER,vehicle,...)
end

--- Gets all relevant values from the setting event to send the event.
---@param setting Setting
---@param eventData table
function SettingEvent.decodeEventData(setting,eventData)
local parentName = setting:getParentName()
local settingName = setting:getName()
local eventIx = eventData.ix
local writeFunc = eventData.writeFunc
return parentName,settingName,eventIx,writeFunc
end

--- Gets the setting and event back from all received values.
---@param vehicle table
---@param parentName table Name of the setting container
---@param settingName string Name of the setting
---@param eventIx number Event number received
function SettingEvent.encodeEventData(vehicle,parentName,settingName,eventIx)
local setting
if vehicle then
setting = vehicle.cp[parentName][settingName]
else
setting = courseplay.globalSettings[parentName][settingName]
end
return setting,setting:getEvent(eventIx)
end
Loading

0 comments on commit 2e9766a

Please sign in to comment.