Rule based scripts: Difference between revisions

From Rsewiki
No edit summary
No edit summary
Line 78: Line 78:
  </rule>
  </rule>


====<rule as a function>====
====Rule as a function====
   
   
A rule may have optional parameters, that can be used if the rule is called from another rules (as a procedure or function, that do not return a value), i.e.:
A rule may have optional parameters, that can be used if the rule is called from another rules (as a procedure or function, that do not return a value), i.e.:

Revision as of 15:52, 2 November 2008

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, and at the same time accept that a large number of the robot tasks are better described by a sequential language.

This implementation attempts to cover this gab.

Language

An example rule definition file could look like this:

<?xml version="1.0" ?>
<rule name="CrossRoad">
   <init>
       odoPose.tripB = 0
       nearRoad = false // define local variable
       <rule 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
       </rule>
       <rule 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
       </rule>
       <rule 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>
       </rule>
   </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>
</rule>

A number of these rules can be active simultaneously, and can be total independent. I.e.one can control the robot arm while another controls the navigation.

Language keywords

Rule

A rule statement must be formed as a XML block structure, as shown below

<rule name="foo" run="true">
   statements
</rule>
<rule name="bar" if="rule_condition">
   statements
</rule>

Rules comes in two flavors, rules and inactive rules. A (active) rule must have a rule condition in an if="" attribute like the plan "bar" above. A rule without the if="" attribute is inactive until called, or made active by a "enable" statement. If it is a top-level rule, then it can be made active when loaded by a run="true" attribute. The run="true" attribute will make it run once

The rule may have a description, like

<rule name="foo" run="true">
   <description>
   This is the descriptive text of "foo", it may have any length, and is intended as an on-line available description of the rule.
   It is optional and recommended only for top-level rules.
   </description>
   statements
</rule>

Rule as a function

A rule may have optional parameters, that can be used if the rule is called from another rules (as a procedure or function, that do not return a value), i.e.:

<rule name="foo">
   <parameters x="0.28" y="0" th="pi"/>
   statements
</rule>
<rule name="bar">
   foo()
   foo(1.5, 0.0, pi/2)
</rule>

Here the rule "bar" uses the "foo" rule as function, first by using the default values, and after this with new values replacing the default values in "foo". The parameters in "foo" works like local variables in the "foo" plan. A rule may be called recursively, and each call will have its own set of local variables. There is a limit to the number nested calls.

<Local variables>

A rule may define local variables and sub-rules, like

<rule name="foo">
   <init>
      x = 88;
      x2 = sqr(x)
      <rule name="bar" if="x < 22")
         print("x is now " x)
      </rule>
   </init>
   statements
</rule>

Here x and x2 are newly established local variables The rule "bar" is active as long as the plan "foo" is active.

<Global variables>

A rule may create and use global variables, e.g.

<rule name="foo" if="utmpose.posey < 1000">
   <init>
      global.equatorWarning = false;
   </init>
   global.equatorWarning = true;
</rule>

This rule is triggered by the Northing in the utmPose module, "utmpose.posey" is here a global variable. The rule defined a new global variable "global.equatorWarning", this must start with the keyword "global", and is then available for all other rules (in all scopes).

Enable/Disable

This will make a rule active - if not already, or stop or prohibit a plan from getting active, e.g.

enable foo

Will make the rule "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 the condition is satisfied. if the rule has no rule condition, it will run once only.

If the rule 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 rule is waiting at a control statement, then this will be interrupted, and any post-lines will be executed, before the rule is disabled. If the rule is not a rule and is not waiting at a control statement, then the statement will have no effect. A called rule will not be affected by the 'disable rulename' statement

A rule can disable itself with the statement:

disable

(a rule can not enable itself)

Language definition

The language definition is:

Rules

ruleBlock ::= ruleOpenTag ruleBody ruleCloseTag

ruleOpenTag ::= '<rule' 'name=' ruleName [runAttribute] [ruleCondition] [evaluateOrder]'>\n'

ruleName ::= '"' symbol '"'

runAttribute ::= 'run' ['="true"' | '="false"']

ruleCondition ::= 'if="' expression '"' (this expression may be split into more lines)

evaluateOrder ::= 'order="' number '"' (number in range 0..100 is recommended)

ruleCloseTag ::= '</rule>\n'

ruleBody ::= [parameters] [description] [ruleInitBlock] ruleMainBlock [rulePostBlock]

parameters ::= '<parameters ' [symbol '="' [paramDefaultValue] '"']* '/>\n'

paramDefaultValue ::= constantValue

description ::= '<description>\n' xmlText '</description>\n'

xmlText ::= any 7-bit characters except '\0', '&' and '<', the last two should be coded as & and <

ruleInitBlock ::= '<init>\n' [declarationStatement]* '</init>\n'

declarationStatement ::= ruleBlock | executableStatement

ruleMainBlock ::= [statement]*

rulePostBlock ::= '<post>\n' [statement]* '</post>\n'

Statements

statement ::= executableStatement | controlStatement

executableStatement ::= assignment | procedureCall | blockStatement | breakStatement | enableStatement | ifStatement | loopStatement | 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'

loopStatement ::= forStatement | whileStatement

forStatement ::= 'for (' assignment ';' expression ';' assignment ')' [remark] '\n' statement [remark] '\n'

whileStatement ::= 'while (' expression ')' [remark] '\n' statement [remark] '\n'

emptyStatement ::= [remark] '\n'

remark ::= ('#' | ';' | '//') xmlText except '\n'