| 
  • If you are citizen of an European Union member nation, you may not use this service unless you are at least 16 years old.

  • You already know Dokkio is an AI-powered assistant to organize & manage your digital files & messages. Very soon, Dokkio will support Outlook as well as One Drive. Check it out today!

View
 

plexil-pdl

Page history last edited by PBworks 17 years, 8 months ago

PLEXIL In Apex

 

8/14/06

 

This document describes the translation of PLEXIL into PDL, the language

of Apex. It is based on the 9/28/05 PLEXIL specification paper, parts

of the most recent PLEXIL XML schema, and Apex 3.0.12. An example

translation is included at the end. Detailed semantics and

implemenation issues are not explored here -- this is an informal

presentation.

 

The translation is organized according to the section numbers in the

Plexil paper that cover the language syntax.

 

 

2.2. Node description

 

In general, a Plexil node becomes one or more procedure steps in PDL.

 

Node Attributes

 

Identifier

 

This becomes a step's tag in PDL. Example:

 

   NodeID: DriveToTarget 

 

becomes

 

   (step |DriveToTarget| ...)

 

NOTE: The vertical bars around DriveToTarget are an artifact of

interning this string to obtain a Lisp symbol. Some details regarding

the conversion of strings in Plexil to symbols in Lisp (where

needed), may need to be worked out.

 

Conditions

 

This include: StartCondition, EndCondition, PreCondition,

PostCondition, InvariantCondition, RepeatUntilCondition. Described

below in "2.4.4 Conditions".

 

Priority

 

This translates to the priority procedure clause, which has

the same semantics, though broader applicability. Plexil seems to use

it to resolve conflicts between actions (leaf nodes) that do

incompatible things such as assigning to the same variable at the same

time or sending incompatible commands to a device. Apex usage can be

seen as a generalization of this.

 

 

Variables

 

Described below in "2.3.3 Declared Local Variables".

 

Interface

 

Described below in "2.3.4 Interfaces".

 

Node Body

 

NodeList

 

The nodes in a node list are simply steps in a PDL procedure.

 

Command node

 

Described below in "2.4.3 Command".

 

Assignment node

 

Described below in "2.4.2 Assignment".

 

 

2.3.1 External States

 

World events and states can be obtained by Apex in two ways

 

  • lookup forms (described below in "2.4.1 Lookups")
  • commands (described below in "2.4.3 Command")

 

 

2.3.2 Internal Variables

 

An Apex task is the equivalent of an executing Plexil node. A task

has queryable internal state. With respect to the states given in the

Plexil document:

 

  node.state             -> (state <task>)
  node.state.Timepoint   -> obtainable via state history callouts
                         -> some states timepoints have direct accessors
  node.outcome           -> (outcome <task>)
  node.failureType       -> (failure-type <task>)

 

NOTE: A complete list of Plexil internal variables should be provided and

verified in Apex.

 

 

2.3.3 Declared Local Variables

 

PDL does not support variable declaration or static type checking. In

PDL, variables are created "on the fly" and are scoped to their

enclosing procedure. In translating PLEXIL to PDL, fortunately we can

assume that the source PLEXIL XML is validated (against the PLEXIL XML

Schema). Therefore, we can forego the "declaring" aspect of variable

declaration in PDL because we are assured there is no improper use of

variables in the code (e.g. assigning to an undeclared or in

variable).

 

Plexil variable declarations also include an initial value, and these

are simply supported as assignments in PDL.

 

2.3.4 Interfaces

 

The Plexil style interface declarations are not directly supported in

PDL. As stated in the previous section, if we assume the original

PLEXIL XML is validated, then we can forego interface declarations with

respect to their role in variable usage checking.

 

The two types of interface variables, in and in-out are

(vacuously) supported correctly within one PDL procedure.

 

Across PDL procedures, any in variables given to the called

procedure are passed through its index clause. It is TBD how to support

in-out variables given to the called procedure.

 

2.4.1 Lookups

 

Condition testing occurs in the context of one of the defined condition

types (see "2.4.4 Conditions") and can be either in the form of PDL

state variable query, or a callout to a Lisp function that obtains the

desired value. Examples of each, respectively:

 

  (start-condition (temperature burner_1 >= 212.0))

  (start-condition :callout (>= (get-temperature "burner_1") 212.0))

 

LookupOnChange (name, tolerance)

 

This will be handled by a Lisp function of the same name, which calls to

the external system (details of communication TBD) to register for

notifications of change in the given variable's value, to the specified

tolerance.

 

LookupWithFrequency (name, frequency)

 

This translates into a step that sets up a repeating poll to the

external world using lookup-now, described next.

 

This type of lookup is special, because PDL currently lacks a mechanism

to invoke repeated polls inside monitors. While the other two

lookup types can be invoked within a step monitor, this one requires

that the polling/requesting of world state, and the subsequent testing

of this information in a condition (via state variable lookup), must be

done separately. A canonical example is seen in the sample translation

in this document.

 

LookupNow (name)

 

A Lisp function lookup-now obtains the given variable's value in the

external world (details TBD).

 

Another way to look up world state is possible, through a Command with

a return value. See the note and example in "2.4.3 Command".

 

 

2.4.2 Assignment

 

An assignment in PLEXIL:

 

  Assignment: <variable> = <value>;

 

becomes in PDL a step of the following form:

 

  (step [tag] :blocking-callout <value> => ?<variable>)

 

Note that the PLEXIL variable name has a '?' prepended when it becomes a

PDL variable. The form following :blocking-callout is

evaluated in Lisp, after any PDL variables withing the form are

evaluated by Apex. So for example, the following boolean conjunction

assignment in PLEXIL:

 

  Assignment: ready = charged AND warm;

 

becomes

 

  (step :blocking-callout (and ?warm ?charged) => ?ready)

 

2.4.3 Command

 

The functional layer is invoked by the Lisp function

 

  (command name arg1 arg2 ...)

 

which is invoked in a procedure step, in one of two ways. If the

command returns a value, the function will be called synchronously

(blocking). Example:

 

  (step :blocking-callout (command "read_temperature" "stove1")
        :returnval ?stove1-temp)

 

If no return value, it is called asychronously:

 

  (step :non-blocking-callout (command "start_rover"))

 

Note that the return value form of commands is one way to look up

external states. Example:

 

  (step s1 :blocking-callout (command "read_temperature" "stove1")
           :returnval ?stove1-temp)
  (step s2 :non-blocking-callout ("turn_up_stove1")
           :start-condition (:in-order
                              ?s1
                              :callout (< ?stove1-temp 200)))

 

2.4.4 Conditions

 

All Plexil conditions have a corresponding PDL step level and/or

procedure level clause. Let C be the specified condition.

 

Gate conditions

 

  StartCondition C     -> (start-condition C')
  EndCondition C       -> (end-condition C')
  InvariantCondition C -> (invariant-condition C')

 

Check conditions

 

  Precondition C         -> (precondition C')
  Postcondition C        -> (postcondition C')
  RepeatUntilCondition C -> (repeat-until-condition C')

 

where C' is the conversion of C into its corresponding PDL form.

 

 

Summary

 

In principle, the current Apex (3.0.12) supports the 9/28/05 description

of PLEXIL. This document needs revision to include newer PLEXIL

features, and the Apex system may require corresponding enhancements.

NOTE: support for in-out interface variables across procedures is

still be worked out.

 

Example

 

Here is a translation of the simple rover example given on page 5 of

the Plexil paper. Significant lines have been numbered.

 


Node: {                                                 0
 NodeID: DriveToTarget;                                 1
  Boolean drive_done, timeout;                          2

 NodeList: {                                            3

  Command: rover_drive(10);                             4

  When                                                  5
  AbsoluteTimeWithin:{10, POSITIVE_INFINITY}            6
  Sequence:{                                            7
    Command: rover_stop();                              8
    Assign: timeout=true;                               9
  }                                                    

  When                                                 10
  LookupWithFrequency{target_in_view,10}==true;        11 
  Sequence:{                                           12
    Command: rover_stop();                             13
    Assign: drive_done=true;                           14
  }                                                    

  When timeout==true                                   15
    Command: take_navcam();                            16

  When drive_done==true                                17
    Command: take_pancam();                            18

  Node:{                                               
    NodeID: Heater;                                    
    StartCondition: LookupOnChange{temperature}<0;     19
    EndCondition: LookupOnChange{temperature}>=10;     20
    RepeatUntilCondition: false;                       21
    Command: turn_on_heater();                         22
    }        
  }
}

 

 

In PDL, along with supporting functions:

 


;; 0: A top level node becomes a PDL procedure
;;
(procedure  

  ;; 1: Obtained this procedure's index by "interning" the Node's name.
  ;; (Interning is a process of obtaining a Lisp symbol from a string).
  ;;
  (index (|DriveToTarget|))

  ;; 2: Initial values (required according to schema) were missing in
  ;; the example, so assuming False (nil in Lisp).  Declarations are
  ;; simply translated into assignments of initial values.

  (step :blocking-callout nil => ?drive-done)
  (step :blocking-callout nil => ?timeout)

  ;; 3: In general, a NodeList becomes a set of steps.  This particular
  ;; example does not require introducing additional procedures.

  ;; 4: Invoke the system command "rover_drive" with argument 10 in a
  ;; non-blocking fashion.
  ;;
  (step s1 :non-blocking-callout (command "rover_drive" 10))

  ;; 5: Expansion of the WHEN sugar translates into several steps that
  ;; are sequentially constained.

  ;; 6-8: AbsoluteTimeWithin becomes a timestamp monitor.  This becomes
  ;; the start condition for a step that does the rover_stop command.
  ;;
  (step s2 :non-blocking-callout (command "rover_stop")
    (start-condition (:timestamp (>= 10))))

  ;; 9: Standard idiom for assignment.  This step is constrained to
  ;; follow the previous one.
  ;;
  (step s3 :blocking-callout t => ?timeout
           (start-condition ?s2))

  ;; 10: Analogous to the WHEN in line 5.

  ;; 11: LookupWithFrequency requires a separate initial step for setup.
  ;; Here, we call a to-be-implemented domain interface function
  ;; LOOKUP-NOW that reads a variable's value in the external world.
  ;; (NOTE: Not sure if this should actually be non-blocking).  This
  ;; step is repeated every 100ms (assuming 10 in the Plexil means 10
  ;; times per second), and repeats until we get a true assignment.
  ;;
  (step c1 :non-blocking-callout (lookup-now "target_in_view")
           :returnval ?target-in-view
           (repeating :min-interval p100ms
                      :until (:callout (<?target-in-view>))))

  ;; 11-13
  (step s4 :non-blocking-callout (command "rover_stop")
    (start-condition (and ?c1 (:callout ?target-in-view))))

  ;; 14
  (step s5 :blocking-callout t => ?drive-done
    (start-condition ?s4))

  ;; 15-16
  (step s6 :non-blocking-callout (command "take_navcam")
    (start-condition (and ?s3 (:callout ?timeout))))

  ;; 17-18
  (step s7 :non-blocking-callout (command "take_pancam")
    (start-condition (and ?s5 (:callout ?drive-done))))

  ;; 19-20: Assuming 0.0 is the default tolerance, this step calls a
  ;; to-be-implemented function that registers with the external world a
  ;; request for notifications of change in temperature (which will be
  ;; sent as cogevents to Apex).  It returns a unique ID used in the
  ;; subsequent steps to monitor for the right notifications.
  ;;  
  (step c2 :blocking-callout
           (lookup-on-change "temperature" 0.0)
           :returnval ?temperature-watch)


  ;; 19-22: Assuming the Plexil was in error, and really wanted to say:
  ;; "turn the heater on whenever temp falls below 0, and turn it off
  ;; whenever it's >= 10".  The temperature is passed in the
  ;; ?temperature variable via the lookup-on-change registration in the
  ;; previous step.

  (step s8 :non-blocking-callout (command "turn_on_heater")
     (start-condition (:in-order ?c2
                                 (changed <?temperature-watch> ?temperature)
                                 (:callout (< ?temperature 0))))
     (repeating :enabled nil))

  (step s9 :non-blocking-callout (command "turn_off_heater")
     (start-condition (:in-order ?c2
                                 (changed <?temperature-watch> ?temperature)
                                 (:callout (> ?temperature 10))))
     (repeating :enabled nil))

  ;; Assuming this end condition (we've taken a picture), not specified
  ;; in Plexil example
  ;;
  (end (when (:or ?s6 ?s7))))


;;; To-be-implemented support functions:

;;; A system call to invoke the given command
(defun command (name &rest args) ...)        ; string * any -> ()

;;; Gets the value of the given var from the external world.
(defun lookup-now (var) ...)   ; string -> any

;;; Registers in the external world for notifications of change in
;;; value of the given variable.  Returns a unique id as means for
;;; identifying these notifications.
;;;
(defun lookup-on-change (var tolerance) ...)  ; string * number -> int

Comments (0)

You don't have permission to comment on this page.