GE Lua Documentation

Press F to search!

optimizePath

Definition


-- @/lua/ge/map.lua:3105



local function optimizePath(path, s, useRawPos)
  --[[ Inputs:
    path: a sequence of navigraph waypoint names ('strings')

    Optional:
    s = {
      segDistSplitLim = nil, -- Optional: will generate new nodes between path nodes that guarantee the maximum distance between any two nodes does not exceed segDistSplitLim meters
      fixPathNodes = nil, -- Do not dispace trajectory nodes that are path nodes (will only displace the generated intermediate nodes)
      fixEndpoints = nil, -- Value: boolean/nil. End points of path will not be displaced
      evolvePathNormals = nil, -- Value: boolean/nil. normal vectors of path nodes will be recalculated on each iteration (might affect stability, when road width limits are reached)
      evolveMidNormals = nil, -- Value: boolean/nil. normal vectors of generated nodes (nodes not belonging to the original path) will be recalculated on each iteration (might affect stability, when road width limits are reached)
      evolveEndNormals = false, -- Value: boolean/nil. normal vectors of path end nodes will be recalculated on each iteration (might affect stability, when road width limits are reached)
      hta = 0.5, -- maximum displacement on each optimization cycle (meters). Higher values means faster convergence but posibly lower stability
      fRange = 1, -- number of nodes before and after node i onto which reaction forces from node i will be applied (a value of 1 will only apply reaction forces to the immediate neighboors of a node)
      forceMag = 'curvature', -- Values: 'curvature' or 'angle' -- whether the force on each node will scale with the angle between the incident edges on that node or with the curvature calculated for that node
      forceScale = nil, -- Values: 'normalize' or nil
      forceMultiplier = 1, -- default: 1. A multiplier to forceMag.
      iterations = 120, -- number of optimizations cycles. -- TODO: At this point this is just a guess.
      distFromEdge = 1 -- Distance limit from road edge (m)
      dispLimFromCenterAbs = nil -- Displacement limit from road centerline (m)
      dispLimFromCenterRel = nil -- Displacement limit from road centerline in units relative to the road half width (radius) at that point
      logData = nil, -- If not nil, bending energy data will be logged to a csv file. If a string, it will be used as the file name.
      logTrajectory = nil, -- If not nil, trajectory data will be logged to a csv file. If a string, it will be used as the file name.
      s.tolFactor = nil -- (Typ. Val 0.001) Optimization will terminate if the relative difference between the previous and current iteration bending energy is less than tolFactor
                        -- The bending energy is calculated as the squared sum of node curvatures
    }
    useRawPos: boolean/nil. If true, the path is expected to be a list of {pos = vec3, radius = number} tuples. If false, the path is expected to be a list of navigraph waypoint names ('strings')
  --]]

  if not path[2] then return end

  useRawPos = useRawPos or false

  s.hta = s.hta or 0.1
  s.fRange = s.fRange or 1
  s.forceMag = s.forceMag or 'angle'
  s.forceMultiplier = s.forceMultiplier or 2
  s.iterations = s.iterations or 120
  s.distFromEdge = s.distFromEdge or 1
  s.tolFactor = s.tolFactor or 0

  local dataToCSV
  local trajectoryToCSV2
  if s.logData then
    dataToCSV = require('csvlib').newCSV("Iteration (i)", "energy (1/m^2)")
  end
  if s.logTrajectory then
    trajectoryToCSV2 = require('csvlib').newCSV("posX", "posY", "posZ", "radius")
  end

  --timeprobe()
  local trajectory = createTrajectory(path, s, useRawPos)

  if dataToCSV then
    dataToCSV:add(0, trajectory.energy)
  end

  for i = 1, s.iterations do
    curvatureFlow(trajectory, s)

    if dataToCSV then
      dataToCSV:add(i, trajectory.energy)
    end

    if trajectory.converged then
     break
    end
  end
  --timeprobe()

  if trajectoryToCSV2 then
    for i = 1, #trajectory do
      trajectoryToCSV2:add(trajectory[i].pos.x, trajectory[i].pos.y, trajectory[i].pos.z, trajectory[i].halfWidth)
    end
  end

  if dataToCSV then
    dataToCSV:write(type(s.logData) == 'string' and s.logData or nil)
  end

  if trajectoryToCSV2 then
    trajectoryToCSV2:write(type(s.logTrajectory) == 'string' and s.logTrajectory or nil)
  end

  return trajectory
end

Callers

@/lua/ge/extensions/gameplay/rally/geometry.lua

  local trajectory = map.optimizePath(path, settings) -- will run the optimization off-line
  --map.debugDrawTrajectory(trajectory)