Skip to content

Commit

Permalink
Merge pull request #2862 from Courseplay/ShovelImprovements
Browse files Browse the repository at this point in the history
Shovel loader and bunker silo mode improvements
  • Loading branch information
Tensuko committed Oct 18, 2023
2 parents 2f4e683 + f43252e commit 9e89d93
Show file tree
Hide file tree
Showing 35 changed files with 259 additions and 80 deletions.
8 changes: 8 additions & 0 deletions config/MasterTranslations.xml
Original file line number Diff line number Diff line change
Expand Up @@ -687,6 +687,14 @@
<Text language="de"><![CDATA[Arbeitsbreite. Wert: 0 - 50]]></Text>
<Text language="en"><![CDATA[Work width. Value: 0 - 50]]></Text>
</Translation>
<Translation name="CP_vehicle_setting_levelerHeightOffset_title">
<Text language="de"><![CDATA[Versatz Schildhöhe]]></Text>
<Text language="en"><![CDATA[Shield height offset]]></Text>
</Translation>
<Translation name="CP_vehicle_setting_levelerHeightOffset_tooltip">
<Text language="de"><![CDATA[Höhenversatz vom Schild zum Boden. Wert: 0 - 1]]></Text>
<Text language="en"><![CDATA[Offset of the shield form the ground. Value: 0 - 1]]></Text>
</Translation>
<Translation name="CP_vehicle_setting_loadingShovelHeightOffset_title">
<Text language="de"><![CDATA[Versatz Schaufelhöhe.]]></Text>
<Text language="en"><![CDATA[Shovel hight offset.]]></Text>
Expand Down
2 changes: 2 additions & 0 deletions config/VehicleSettingsSetup.xml
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,8 @@
<Setting classType="AIParameterSettingList" name="loadingShovelHeightOffset" min="-1" max="1" incremental="0.1" default="0" unit="2"
isVisible="isLoadingShovelOffsetSettingVisible" isDisabled="isLoadingShovelOffsetSettingDisabled"
onChangeCallback="onCpLoadingShovelOffsetSettingChanged" vehicleConfiguration="loadingShovelOffset"/>
<Setting classType="AIParameterSettingList" name="levelerHeightOffset" min="0" max="0.5" incremental="0.05" default="0" unit="2" precision="3"
isVisible="isLevelerHeightOffsetSettingVisible" isDisabled="isLevelerHeightOffsetSettingDisabled" />
</SettingSubTitle>

<SettingSubTitle title="combine" isVisible="areCombineSettingsVisible">
Expand Down
11 changes: 7 additions & 4 deletions scripts/CpSettingsUtil.lua
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,10 @@ CpSettingsUtil = {}
- isExpertModeOnly(bool): is the setting visible in the expert version?, default = false
- generateValuesFunction(string): dynamically adds value, when the setting is created.
- min (int): min value
- max (int): max value
- min (float): min value
- max (float): max value
- incremental (float): increment (optional), default "1"
- precision (float): optional rounding precision
- text(string): string to format the setting value with in the gui element.
- unit (int) : 1 == km/h, 2 == meters, 3 == ha (optional), 4 = percent (%), 5 = degrees (°)
Expand Down Expand Up @@ -89,9 +90,10 @@ function CpSettingsUtil.init()
schema:register(XMLValueType.BOOL, key.."#isExpertModeOnly", "Is enabled in simple mode?", false) -- optional

schema:register(XMLValueType.STRING, key .. "#generateValuesFunction", "Function to generate values.")
schema:register(XMLValueType.INT, key.."#min", "Setting min value")
schema:register(XMLValueType.INT, key.."#max", "Setting max value")
schema:register(XMLValueType.FLOAT, key.."#min", "Setting min value")
schema:register(XMLValueType.FLOAT, key.."#max", "Setting max value")
schema:register(XMLValueType.FLOAT, key.."#incremental", "Setting incremental", 1) -- optional
schema:register(XMLValueType.FLOAT, key.."#precision", "Setting precision", 2) -- optional
schema:register(XMLValueType.STRING, key.."#text", "Setting text") -- optional
schema:register(XMLValueType.INT, key .. "#unit", "Setting value unit (km/h, m ...)") --optional

Expand Down Expand Up @@ -205,6 +207,7 @@ function CpSettingsUtil.loadSettingsFromSetup(class, filePath)
settingParameters.min = xmlFile:getValue(baseKey.."#min")
settingParameters.max = xmlFile:getValue(baseKey.."#max")
settingParameters.incremental = MathUtil.round(xmlFile:getValue(baseKey.."#incremental"), 3)
settingParameters.precision = xmlFile:getValue(baseKey.."#precision", 2)
settingParameters.textStr = xmlFile:getValue(baseKey.."#text")
settingParameters.unit = xmlFile:getValue(baseKey.."#unit")

Expand Down
19 changes: 5 additions & 14 deletions scripts/ai/AIDriveStrategyBunkerSilo.lua
Original file line number Diff line number Diff line change
Expand Up @@ -47,16 +47,11 @@ function AIDriveStrategyBunkerSilo.new(customMt)
AIDriveStrategyCourse.initStates(self, AIDriveStrategyBunkerSilo.myStates)
self.state = self.states.DRIVING_TO_SILO

-- course offsets dynamically set by the AI and added to all tool and other offsets
self.aiOffsetX, self.aiOffsetZ = 0, 0
self.debugChannel = CpDebug.DBG_SILO
---@type ImplementController[]
self.controllers = {}
self.silo = nil
self.siloController = nil
self.drivingForwardsIntoSilo = true
self.turnNode = CpUtil.createNode("turnNode", 0, 0, 0)


self.isStuckTimer = Timer.new(self.isStuckMs)
self.driveIntoSiloAttempts = 0
Expand Down Expand Up @@ -177,7 +172,7 @@ function AIDriveStrategyBunkerSilo:setAllStaticParameters()
else
self:startDrivingTemporaryOutOfSilo()
end
elseif self.siloController:hasNearbyUnloader() and self:isDrivingToParkPositionAllowed() then
elseif self.state == self.states.DRIVING_INTO_SILO and self.siloController:hasNearbyUnloader() and self:isDrivingToParkPositionAllowed() then
self:debug("Found an unloader nearby and is stuck, so immediately leave the silo.")
self:startDrivingOutOfSilo()
end
Expand Down Expand Up @@ -292,15 +287,11 @@ end
function AIDriveStrategyBunkerSilo:update(dt)
AIDriveStrategyBunkerSilo:superClass().update(self, dt)
self:updateImplementControllers(dt)

if CpDebug:isChannelActive(self.debugChannel, self.vehicle) then
if self.course then
-- TODO_22 check user setting
if self.course:isTemporary() then
self.course:draw()
elseif self.ppc:getCourse():isTemporary() then
self.ppc:getCourse():draw()
end
if self.course and self.course:isTemporary() then
self.course:draw()
elseif self.ppc:getCourse():isTemporary() then
self.ppc:getCourse():draw()
end
if self.siloEndDetectionMarker ~= nil then
DebugUtil.drawDebugNode(self.siloEndDetectionMarker, "siloEndDetectionMarker", false, 1)
Expand Down
12 changes: 8 additions & 4 deletions scripts/ai/AIDriveStrategyShovelSiloLoader.lua
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@ function AIDriveStrategyShovelSiloLoader:setAllStaticParameters()
Markers.setMarkerNodes(self.vehicle)
self.frontMarkerNode, self.backMarkerNode, self.frontMarkerDistance, self.backMarkerDistance =
Markers.getMarkerNodes(self.vehicle)
self.siloEndProximitySensor = SingleForwardLookingProximitySensorPack(self.vehicle, self.shovelController:getShovelNode(), 5, 1)
self.siloEndProximitySensor = SingleForwardLookingProximitySensorPack(self.vehicle, self.shovelController:getShovelNode(), 1, 1)
self.heapNode = CpUtil.createNode("heapNode", 0, 0, 0, nil)
self.lastTrailerSearch = 0
self.isStuckTimer = Timer.new(self.isStuckMs)
Expand Down Expand Up @@ -275,9 +275,13 @@ function AIDriveStrategyShovelSiloLoader:getDriveData(dt, vX, vY, vZ)
self.isStuckTimer:startIfNotRunning()
end
local _, _, closestObject = self.siloEndProximitySensor:getClosestObjectDistanceAndRootVehicle()
local isEndReached, maxSpeed = self.siloController:isEndReached(self.shovelController:getShovelNode(), 0)
if self.silo:isTheSameSilo(closestObject) or isEndReached then
self:debug("End wall detected or bunker silo end is reached.")
local isEndReached, maxSpeed = self.siloController:isEndReached(self.shovelController:getShovelNode(), 2)
self:setMaxSpeed(maxSpeed)
if isEndReached then
self:debug("End of the silo or heap was detected.")
self:startDrivingOutOfSilo()
elseif self.silo:isTheSameSilo(closestObject) and self.silo:isNodeInSilo(self.shovelController:getShovelNode()) then
self:debug("End wall of the silo was detected.")
self:startDrivingOutOfSilo()
end
if self.shovelController:isFull() then
Expand Down
18 changes: 12 additions & 6 deletions scripts/ai/controllers/LevelerController.lua
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,13 @@ function LevelerController:getDriveData()
return nil, nil, nil, maxSpeed
end

function LevelerController:getTargetTerrainHeight()
local x, y, z = getWorldTranslation(self.levelerNode)
local terrainHeight = getTerrainHeightAtWorldPos(g_currentMission.terrainRootNode, x, y, z)
--- Applies the setting offset, so the leveler is not directly on the ground.
return terrainHeight + self.settings.levelerHeightOffset:getValue()
end

--- Used when a wheel loader or a snowcat is used.
--- Finds the correct cylindered axis.
function LevelerController:setupCylinderedHeight()
Expand Down Expand Up @@ -87,7 +94,7 @@ end
--- Used when a wheel loader or a snowcat is used.
function LevelerController:updateCylinderedHeight(dt)
local x, y, z = getWorldTranslation(self.levelerNode)
local terrainHeight = getTerrainHeightAtWorldPos(g_currentMission.terrainRootNode, x, y, z)
local terrainHeight = self:getTargetTerrainHeight()
local nx, ny, nz = localToWorld(self.levelerNode, 0, 0, 1)
local nTerrainHeight = getTerrainHeightAtWorldPos(g_currentMission.terrainRootNode, nx, ny, nz)
local targetHeight = self:getTargetShieldHeight()
Expand All @@ -112,13 +119,13 @@ function LevelerController:setCylinderedLevelerRotation(dt, offsetDeg)
local _, dy, _ = localToWorld(self.levelerTool.node, 0, 0, 0)
local dx, _, dz = localToWorld(self.levelerNode, 0, 0, 0)
local _, ny, _ = worldToLocal(self.levelerTool.node, dx, dy, dz)
self:debug("dist: %.2f, ny: %.2f", dist, ny)
-- self:debug("dist: %.2f, ny: %.2f", dist, ny)
local targetRot = math.asin(ny/dist) + math.rad(offsetDeg)
if ny > 0 then
targetRot = -math.asin(-ny/dist) + math.rad(offsetDeg)
end
self:debug("curRot: %.2f, targetRot: %.2f, offset: %.2f, rotMin: %.2f, rotMax: %.2f",
angle, targetRot, math.rad(offsetDeg), self.levelerTool.rotMin, self.levelerTool.rotMax)
-- self:debug("curRot: %.2f, targetRot: %.2f, offset: %.2f, rotMin: %.2f, rotMax: %.2f",
-- angle, targetRot, math.rad(offsetDeg), self.levelerTool.rotMin, self.levelerTool.rotMax)

return ImplementUtil.moveMovingToolToRotation(self.levelerToolVehicle, self.levelerTool, dt,
MathUtil.clamp(angle - targetRot, self.levelerTool.rotMin, self.levelerTool.rotMax))
Expand Down Expand Up @@ -149,7 +156,7 @@ function LevelerController:updateHeight(dt)
local jointDesc = spec.jointDesc
if self.driveStrategy:isLevelerLoweringAllowed() then
local x, y, z = getWorldTranslation(self.levelerNode)
local terrainHeight = getTerrainHeightAtWorldPos(g_currentMission.terrainRootNode, x, y, z)
local terrainHeight = self:getTargetTerrainHeight()
---target height of leveling, fill up is 0 by default
local targetHeight = self:getTargetShieldHeight()

Expand Down Expand Up @@ -225,7 +232,6 @@ end
function LevelerController:updateShieldHeightOffset()
--- A small reduction to the offset, as the shield should be lifted after a only a bit silage.
local smallOffsetReduction = 0.3

--self.shieldHeightOffset = MathUtil.clamp(-self.levelerSpec.lastForce/self.levelerSpec.maxForce - smallOffsetReduction, 0, 1)
end

Expand Down
28 changes: 16 additions & 12 deletions scripts/ai/parameters/AIParameterSettingList.lua
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@ function AIParameterSettingList:init(data, vehicle, class)
--- so we generate a series of float values and texts here.
self.data.values = {}
self.data.texts = {}
AIParameterSettingList.generateValues(self, self.data.values, self.data.texts, data.min, data.max, data.incremental, data.unit)
AIParameterSettingList.generateValues(self, self.data.values, self.data.texts,
data.min, data.max, data.incremental, data.unit, data.precision)
--- Same as above, make sure the values are copied.
self.values = table.copy(self.data.values)
if self.data.texts ~= nil then
Expand Down Expand Up @@ -73,27 +74,28 @@ function AIParameterSettingList:init(data, vehicle, class)

end

function AIParameterSettingList.getSpeedText(value)
function AIParameterSettingList.getSpeedText(value, precision)
return string.format("%.1f %s", g_i18n:getSpeed(value), g_i18n:getSpeedMeasuringUnit())
end

function AIParameterSettingList.getDistanceText(value)
function AIParameterSettingList.getDistanceText(value, precision)
precision = precision or 1
if g_Courseplay.globalSettings and g_Courseplay.globalSettings.distanceUnit:getValue() == g_Courseplay.globalSettings.IMPERIAL_UNIT then
return string.format("%.1f %s", value*AIParameterSettingList.FOOT_FACTOR, g_i18n:getText("CP_unit_foot"))
end
return string.format("%.1f %s", value, g_i18n:getText("CP_unit_meter"))
return string.format("%.".. tostring(precision) .. "f %s", value, g_i18n:getText("CP_unit_meter"))
end

function AIParameterSettingList.getAreaText(value)
function AIParameterSettingList.getAreaText(value, precision)
return g_i18n:formatArea(value, 1, true)
end

AIParameterSettingList.UNITS_TEXTS = {
AIParameterSettingList.getSpeedText, --- km/h
AIParameterSettingList.getDistanceText, --- m
AIParameterSettingList.getAreaText, --- ha/arcs
function (value) return string.format("%d", value) .. "%" end, --- percent
function (value) return string.format("%d", value) .. "°" end --- degrees
function (value, precision) return string.format("%d", value) .. "%" end, --- percent
function (value, precision) return string.format("%d", value) .. "°" end --- degrees
}

AIParameterSettingList.UNITS_CONVERSION = {
Expand All @@ -113,12 +115,13 @@ AIParameterSettingList.INPUT_VALUE_THRESHOLD = 2
---@param max number
---@param inc number
---@param unit number
function AIParameterSettingList:generateValues(values, texts, min, max, inc, unit)
function AIParameterSettingList:generateValues(values, texts, min, max, inc, unit, precision)
inc = inc or 1
precision = precision or 2
for i=min, max, inc do
table.insert(values, i)
local value = MathUtil.round(i, 2)
local text = unit and AIParameterSettingList.UNITS_TEXTS[unit] and AIParameterSettingList.UNITS_TEXTS[unit](value) or tostring(value)
local value = MathUtil.round(i, precision)
local text = unit and AIParameterSettingList.UNITS_TEXTS[unit] and AIParameterSettingList.UNITS_TEXTS[unit](value, precision - 1) or tostring(value)
table.insert(texts, text)
end
end
Expand Down Expand Up @@ -233,12 +236,13 @@ end
--- For all units that are not an SI unit ...
function AIParameterSettingList:validateTexts()
local unit = self.data.unit
local precision = self.data.precision or 2
if unit then
local unitStrFunc = AIParameterSettingList.UNITS_TEXTS[unit]
local fixedTexts = {}
for ix, value in ipairs(self.values) do
local value = MathUtil.round(value, 2)
local text = unitStrFunc(value)
local value = MathUtil.round(value, precision)
local text = unitStrFunc(value, precision - 1)
fixedTexts[ix] = text
end
self.texts = fixedTexts
Expand Down
11 changes: 10 additions & 1 deletion scripts/gui/hud/CpBunkerSiloWorkerHudPage.lua
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@ function CpBunkerSiloWorkerHudPageElement:setupElements(baseHud, vehicle, lines,
}
self.driveDirectionBtn:setCallback(callback, callback)

--- Leveler height offset.
self.levelerHeightOffsetBtn = baseHud:addLineTextButton(self, 4, CpBaseHud.defaultFontSize,
vehicle:getCpSettings().levelerHeightOffset)

--- Waiting at park position
local x, y = unpack(lines[1].left)
local xRight,_ = unpack(lines[1].right)
Expand Down Expand Up @@ -78,7 +82,12 @@ function CpBunkerSiloWorkerHudPageElement:updateContent(vehicle, status)
local driveDirection = vehicle:getCpBunkerSiloWorkerJobParameters().drivingForwardsIntoSilo
self.driveDirectionBtn:setTextDetails(driveDirection:getTitle(), driveDirection:getString())
self.driveDirectionBtn:setVisible(driveDirection:getIsVisible())
self.driveDirectionBtn:setDisabled(driveDirection:getIsDisabled())
self.driveDirectionBtn:setDisabled(not driveDirection:getIsVisible())

local heightOffset = vehicle:getCpSettings().levelerHeightOffset
self.levelerHeightOffsetBtn:setTextDetails(heightOffset:getTitle(), heightOffset:getString())
self.levelerHeightOffsetBtn:setVisible(heightOffset:getIsVisible())
self.levelerHeightOffsetBtn:setDisabled(heightOffset:getIsDisabled())

local waitAt = vehicle:getCpBunkerSiloWorkerJobParameters().waitAtParkPosition
self.waitAtBtn:setTextDetails(waitAt:getTitle(), waitAt:getString())
Expand Down
Loading

0 comments on commit 9e89d93

Please sign in to comment.