Here
From Rsewiki
Drivebase.rule code
<?xml version="1.0" ?>
<rule name="initDrive" run="true">
<init>
global.drive.mapDest[2] = 0.0 # destination in map coordinates
global.drive.utmDest[2] = 0.0 # destination in UTM coordinates
global.drive.odoDest[2] = 0.0 # destination in ODO coordinates
global.drive.lastMapDest[2] = 0.0 # last destination in map coordinates
global.drive.lastUtmDest[2] = 0.0 # last destination in UTM coordinates
global.drive.lastOdoDest[2] = 0.0 # last destination in ODO coordinates
global.drive.refCoord = -1 # 0=odo, 1=UTM, 2=map
global.drive.newDest = 0
global.drive.pause = false
global.drive.waitHere = true # waits in a state with low RPM
global.drive.gettingClose = false
global.drive.skipDestination = false
global.drive.compasHeading = false # heading in compas degrees if true (else math)
global.drive.radians = true # heading in radians if true, else in degrees (math heading only)
global.drive.continueDist = 1 # continues when closer than this from next node
global.drive.holdLine = true # try hold line from last waypoint, else go direct
global.drive.engineRPM= 1900;
global.mission.name= 'none'
global.mission.leg= 0
odoPose.tripTimeB= 0
odoPose.tripB= 0
global.drive.distToTgt = 0
global.drive.fromPose[2] = 0.0 # last used source pose
print("------------ rule drivebase version 2.747")
</init>
</rule>
<rule name="drive" if="true">
<description>
Main drive rules
</description>
<init>
# define drive local variables
destUpdated = false
dest[2] = 0
odoDest[2] = 0
destOK = false
relPose[2] = 0
tripStart = now()
lastManDist = 100.0 # target distance at last plan
holdLineDist = 11 # aiming pose position when holding line
lastOdoDest[2] = 0
newDest = false
renewDrive = false
#distToTgt = 0
#fromPose[2] = 0
#
#define rule to update map target in odometry coordinates
<rule name="updateMap" if="global.drive.refCoord == 2 and
global.drive.newDest">
relPose = mapToPose(mapPose.pose, global.drive.mapDest)
odoDest = poseToMap(odoPose.pose, relPose)
relPose = mapToPose(mapPose.pose, global.drive.lastMapDest)
lastOdoDest = poseToMap(odoPose.pose, relPose)
newDest = true
</rule>
#
#define rule to update utm target in odometry coordinates
<rule name="updateUtm" if="global.drive.refCoord == 1 and
global.drive.newDest">
relPose = mapToPose(utmPose.pose, global.drive.utmDest)
odoDest = poseToMap(odoPose.pose, relPose)
relPose = mapToPose(utmPose.pose, global.drive.lastUtmDest)
lastOdoDest = poseToMap(odoPose.pose, relPose)
newDest = true
</rule>
#
#define rule to use destination odometry coordinates
<rule name="updateOdo" if="global.drive.refCoord == 0 and
global.drive.newDest">
lastOdoDest = odoDest
odoDest = global.drive.odoDest
global.drive.newDest = false;
newDest = true
</rule>
#
# should destination be used directly, or are we following a line
<rule name="aim4dest" if="newDest and not global.drive.holdLine">
# use of next destination is OK
dest = odoDest;
destOK = true
lastManDist = 100
newDest = false;
# print("aim4dest direct dest " dest)
</rule>
#
# should destination be used directly, or are we following a line
<rule name="aim4line" if="global.drive.holdLine and
(newDest or lastManDist < holdLineDist)">
# use of next destination is not OK
<init>
dtgt = 0
srcDist = 0
</init>
dest = odoDest;
dtgt = dist2d(dest, odoPose.pose)
if (dtgt > holdLineDist + 500) # disabled
<block>
# use a shorter distance than the real destination
srcDist = holdLineDist + 5 + dist2d(lastOdoDest, odoPose.pose)
dest = poseOnLine(lastOdoDest, odoDest, srcDist)
# print("aim4line target " dtgt "m, new dest " dest)
</block>
# else
# print("aim4line target " dtgt "m, direct dest " dest)
destOK = true
if (newDest)
lastManDist = 100
newDest = false;
</rule>
#
# stop the robot for a pause
<rule name="stopAndWait" if="smrctl.directWait or
global.drive.pause or
global.drive.waitHere">
print("Stopping ...")
odoPose.tripB = 0
odoPose.tripTimeB = 0
smr.send("flushcmds")
smr.do('setvar "hakoenginespeed" 800')
if (global.drive.waitHere and destOK and odopose.vel > 0.3)
<block>
# drive towards the destination and stop
smr.do("drive " dest[0] " " dest[1] " " dest[2] ' "rad" @v0.2 : ($targetdist < 0.0) | ($odovelocity < 0.3)')
</block>
smr.send("idle")
print("StopAndWait: stopped at pose " odopose.pose)
wait() : not if()
print("StopAndWait: resume after pause")
smr.do('setvar "hakoenginespeed" ' global.drive.engineRPM)
</rule>
#
# test if robot is close to destination
<rule name="closeTest" if="destOK">
<init>
ds = 0
rel[2] = 1 # target relative pose x,y,h
</init>
# get destination relative to current pose
rel = mapToPose(odoPose.pose, odoDest)
ds = rulestate.sampletime * smr.speed + 0.1 + global.drive.continueDist
# close if x is less that a sample distance, and total distance is small too
global.drive.gettingClose = ds > rel[0] and (3.0 > hypot(rel[1], rel[0]) or abs(rel[0]) > abs(rel[1]))
destOK = not global.drive.gettingClose
</rule>
#
<rule name="replayRenewDrive" if="not renewDrive">
# renew drive command if driven more than 1 meter
# should only be needed in replay mode wih no live MRC to event trigger this renewal
<init>
d = 0.0
</init>
d = dist2d(global.drive.fromPose, odoPose.pose)
renewDrive = d > 1
if (renewDrive)
print("Rule::replayRenewDrive: Driven 1m, so forced renewal of drive command")
</rule>
# advance a further distance
<rule name="advance" if="destOK and
lastManDist > smrctl.manPlanDist and
not global.drive.pause and
smr.connected">
odoPose.tripB = 0
odoPose.tripTimeB = 0
global.drive.fromPose = odoPose.pose
renewDrive = false
print("Drive advance from " odopose.pose " towards " dest " (leg " global.mission.leg ")")
tripStart = now()
lastManDist = dist2d(dest, odoPose.pose)
drivePos.odo(dest[0], dest[1], dest[2]) : renewDrive or not destOK or global.drive.pause or not smr.connected
print("Drive advance ended leg at odo pose " odopose.pose " (leg " global.mission.leg ")")
</rule>
#
</init>
# stay alert here
wait() : false
</rule>
<rule name="driveUTM">
<parameters x="0" y="0" h="0" />
global.drive.lastUtmDest = global.drive.utmDest
global.drive.utmDest[0] = x
global.drive.utmDest[1] = y
if (global.drive.compasHeading == true)
global.drive.utmDest[2] = limittopi((90 - h) * pi / 180.0)
else
if (global.drive.radians)
global.drive.utmDest[2] = h
else
global.drive.utmDest[2] = limittopi(h * pi / 180.0)
global.drive.refCoord = 1
global.drive.gettingClose = false
global.drive.skipDestination = false
global.drive.waitHere = false;
global.mission.leg = global.mission.leg + 1
print("Leg " global.mission.leg " UTM target pose: x:" x ", y:" y ", h:" h)
global.drive.newDest = true
wait() : global.drive.gettingClose or global.drive.skipDestination
<post>
global.drive.newDest = false
#global.drive.holdLine=false
</post>
</rule>
<rule name="driveMap">
<parameters x="0" y="0" h="0" />
global.drive.lastMapDest = global.drive.mapDest
global.drive.mapDest[0] = x
global.drive.mapDest[1] = y
if (global.drive.compasHeading)
global.drive.mapDest[2] = limittopi((90 - h) * pi / 180.0)
else
if (global.drive.radians)
global.drive.mapDest[2] = h
else
global.drive.mapDest[2] = limittopi(h * pi / 180.0)
global.drive.refCoord = 2
global.drive.gettingClose = false
global.drive.skipDestination = false
global.drive.waitHere = false;
global.mission.leg = global.mission.leg + 1
print("Leg " global.mission.leg " map target pose: x:" x ", y:" y ", h:" h)
global.drive.newDest = true
wait() : global.drive.gettingClose or global.drive.skipDestination
<post>
global.drive.newDest = false
#global.drive.holdLine=false
</post>
</rule>
<rule name="driveNode">
<parameters node="" hdg="0"/> <init> nextNode[2] = 0.0; </init> nextNode[0] = mapbase.node(node, 'x') nextNode[1] = mapbase.node(node, 'y') nextNode[2] = mapbase.node(node, 'th') + hdg driveMap(nextNode[0], nextNode[1], nextNode[2])
</rule>
<rule name="driveOdo">
<parameters x="0" y="0" h="0" />
global.drive.lastOdoDest = global.drive.odoDest
global.drive.odoDest[0] = x
global.drive.odoDest[1] = y
if (global.drive.compasHeading)
global.drive.odoDest[2] = limittopi((90 - h) * pi / 180.0)
else
if (global.drive.radians)
global.drive.odoDest[2] = h
else
global.drive.odoDest[2] = limittopi(h * pi / 180.0)
global.drive.refCoord = 0
global.drive.gettingClose = false
global.drive.skipDestination = false
global.drive.waitHere = false;
global.mission.leg = global.mission.leg + 1
print("Leg " global.mission.leg " odo target pose: x:" x ", y:" y ", h:" h)
global.drive.newDest = true
wait() : global.drive.gettingClose or global.drive.skipDestination
<post>
print("driveodo continues, as gettingClose=" global.drive.gettingClose ", and skip=" global.drive.skipDestination)
global.drive.newDest = false
#global.drive.holdLine=false
</post>
</rule>
<rule name="driveWait">
# stop and wait are language keywords
# stop here for some seconds
<parameters stoptime="1.0"/>
print("********** stop and wait for " stoptime " sec")
global.drive.waitHere = true;
wait(stoptime) : false
print("********** resumes drive")
</rule>
<rule name="missionStart">
<parameters missionName="'noname'"/>
global.mission.name=missionName
global.mission.leg=0
odoPose.tripTimeB= 0
odoPose.tripB= 0
print("Mission " global.mission.name " started.")
</rule>
<rule name="missionEnd">
global.drive.waitHere=true
wait(2) : false
print("Mission " global.mission.name " stopped after " global.mission.leg " legs.")
print("Mission took " odoPose.tripTimeB " and drove " odoPose.tripB "m.")
</rule>