Paths

A path is a pseudo object, representing a succession of points with orientation in space. pseudo object, since it is built using merely dummies and a customization script that describes its functionality and behaviour.

[Simple path containing 4 control points]


Path objects can be added to the scene with [Menu bar --> Add --> Path]. A path is composed by control points that define its curve in space. Control points can be shifted, copy/pasted or deleted. A path's basic properties are accessed and adjusted via its user parameters (implemented via a user config callback function), in the scene hierarchy:

[User parameter icon]


A path can also automatically generate extruded shapes; this functionality is enabled via its user parameters, and the shape profile, color and other details can be adjusted in its customization script, which uses the API function sim.generateShapefromPath:

function path.shaping(path,pathIsClosed,upVector)
    -- following section generates a square extrusion shape:
    local section={0.02,-0.02,0.02,0.02,-0.02,0.02,-0.02,-0.02,0.02,-0.02}
    local color={0.7,0.9,0.9}
    local options=0
    if pathIsClosed then
        options=options|4
    end
    local shape=sim.generateShapeFromPath(path,section,options,upVector)
    sim.setShapeColor(shape,nil,sim.colorcomponent_ambient_diffuse,color)
    return shape
end

[Simple path generating an extruded square shape]


To generate an extruded circular shape, use following code to create the section data:

local section={}
local radius=0.02
local sides=32
local da=math.pi*2/sides
for i=0,sides-1,1 do
    section[2*i+1]=radius*math.cos(da*i)
    section[2*i+2]=radius*math.sin(da*i)
end
-- the section shoujld be closed (first and last points perfect overlap):
section[#section+1]=section[1]
section[#section+1]=section[2]

[Simple path generating an extruded circular shape]


Path data is stored inside of the path object, as custom object data. It can be accessed with:

-- control point data (each one has x,y,z,qx,qy,qz,qw (position and quaternion)):
local ctrlPts=sim.unpackDoubleTable(sim.readCustomDataBlock(pathHandle,'PATHCTRLPTS'))

-- path data (each one has x,y,z,qx,qy,qz,qw (position and quaternion)):
local pathData=sim.unpackDoubleTable(sim.readCustomDataBlock(pathHandle,'PATH'))

Various API functions related to paths are available, e.g. in order to have an object follow a path in position and orientation, one could use following script:

function sysCall_init()
    objectToFollowPath=sim.getObjectHandle(sim.handle_self)
    path=sim.getObjectHandle('Path')
    pathData=sim.unpackDoubleTable(sim.readCustomDataBlock(path,'PATH'))
    local m=Matrix(#pathData//7,7,pathData)
    pathPositions=m:slice(1,1,m:rows(),3):data()
    pathQuaternions=m:slice(1,4,m:rows(),7):data()
    pathLengths,totalLength=sim.getPathLengths(pathPositions,3)
    velocity=0.04 -- m/s
    posAlongPath=0
    previousSimulationTime=0
    corout=coroutine.create(coroutineMain)
end

function sysCall_actuation()
    if coroutine.status(corout)~='dead' then
        local ok,errorMsg=coroutine.resume(corout)
        if errorMsg then
            error(debug.traceback(corout,errorMsg),2)
        end
    end
end

function coroutineMain()
    sim.setThreadAutomaticSwitch(false)
    while true do
        local t=sim.getSimulationTime()
        posAlongPath=posAlongPath+velocity*(t-previousSimulationTime)
        posAlongPath=posAlongPath % totalLength
        local pos=sim.getPathInterpolatedConfig(pathPositions,pathLengths,posAlongPath)
        local quat=sim.getPathInterpolatedConfig(pathQuaternions,pathLengths,
                                                 posAlongPath,nil,{2,2,2,2})
        sim.setObjectPosition(objectToFollowPath,path,pos)
        sim.setObjectQuaternion(objectToFollowPath,path,quat)
        previousSimulationTime=t
        sim.switchThread()
    end
end