Mission monitor sequencer
Introduction
This plug-in implements a a language that is a mixture of a rule-based and a sequential based language. The idea is that a number of situations need permanent - or semi permanent - monitoring to get a good situation awareness for the root, and at the same time a large number of the robot tasks are better described by a sequential language.
This implementation attempts to cover this gab.
Language
An example function could look like this:
<?xml version="1.0" ?> <plan name="CrossRoad"> <init> odoPose.tripB = 0 nearRoad = false // define local variable <plan name="maxOdoDist" if="odoPose.tripB > 250"> // this is a rule to moditor distance traveled since trip-counter were reset print("Driven too far on odo " odoPose.tripB "m") // print message break CrossRoad // failed to cross road - could trigger a relocalization </plan> <plan name="closeToRoad" if="hypot(utmPose.poseY - 6174307, utmPose.poseX - 707873) < 15" > // this is a rule that monitors the distance to an UTM point print("Cose to road slowing down) // print message smr.speed=0.5 // set the desired maximum speed in mrc interface module nearRoad = true // set flag disable // disable this rule </plan> <plan name="turn"> <parameter angle="pi" dist=1.0/> // this is a plan <commands to="smr.send"> # construct commands to MRC using the smr.send command 'drive @v ' smr.speed ' : ($drivendist > ' dist ')' 'turn ' angle 'drive : ($drivendist > ' dist ')' </commands> </plan> </init> print("started") roaddrive.right(0.75) : nearRoad // follow road 75cm from edge until near road // more stuff missing here to detect traffic etc. ... turn() // turn back - using a call to a plan success=true <post> print("finsihed crossRoad - success=" success) </post> </plan>
A number of these plans can be started (enabled) simultaniously, an can in principle be total independant. I.e.one can control the robot arm while another controls the navigation.
Language keywords
Enable/Disable
This will make a plan active - if not already, or stop or prohibit a plan from getting active, e.g.
enable foo
Will make the plan "foo" active, that is start running the code as if it was a rule. If there is a rule condition, then the code will not run until this is satisfied.
If the plan is active already, either it is an active rule or the plan is waiting at a control statement, the statement will have no effect.
The disable command:
disable foo
Will disable the plan "foo", if the plan is a rule, then the rule condition will no longer be evaluated. If the plan is waiting at a control statement, then this will be interrupted, and any post-lines will be executed, before the plan is disabled. If the plan is not a rule and is not waiting at a control statement, then the statement will have no effect.
A rule can disable itself with the statement:
disable
(a plan can not enable itself)
Language definition
The language definition is:
Plan
planBlock ::= planOpenTag planBody planCloseTag
planOpenTag ::= '<plan' 'name=' planName [runAttribute] [ruleCondition] '>\n'
planName ::= '"' symbol '"'
runAttribute ::= 'run="default"' (there may come more values later)
ruleCondition ::= 'if="' expression '"' (this expression may be split into more lines)
planCloseTag ::= '</plan>\n'
planBody ::= [parameters] [description] [planInitBlock] planMainBlock [planPostBlock]
parameters ::= '<parameters ' [symbol '="' [paramDefaultValue] '"']* '/>\n'
paramDefaultValue ::= constantValue
description ::= '<description>\n' xmlText '</description>\n'
xmlText ::= any 7-bit characters except '\0', '&' and '<', the last two must be coded as & and <
planInitBlock ::= '<init>\n' [declarationStatement]* '</init>\n'
declarationStatement ::= planBlock | executableStatement
planMainBlock ::= [statement]*
planPostBlock ::= '<post>\n' [statement]* '</post>\n'
Statements
statement ::= executableStatement | controlStatement
executableStatement ::= assignment | procedureCall | blockStatement | breakStatement | enableStatement | ifStatement | emptyStatement
controlStatement ::= proceureCall ':' expression [remark] '\n'
assignment ::= [symbol.]* symbol '=' expression [remark] '\n'
procedureCall ::= [symbol.]* symbol '(' [expression [',' expression]* ')' [remark] '\n'
blockStatement ::= '<block>\n' [statement]* '</block>\n'
breakStatement ::= ('break' [symbol] | 'continue' ) [remark] '\n'
enableStatement ::= ('enable' | 'disable') [symbol] [remark] '\n'
ifStatement ::= 'if (' expression ')' [remark] '\n' statement [remark] '\n' [elseStatement]
elseStatement ::= 'else' [remark] '\n' statement [remark] '\n'
emptyStatement ::= [remark] '\n'
remark ::= ('#' | ';' | '//') xmlText except '\n'