Automatically choosing a process module for a motion

Description: in previous tutorials we called a process module explicitly via cram-process-modules:pm-execute, and fed them appropriate action designators. However, it is sometimes useful to reason about what process module to use to handle a given designator. To illustrate the CRAM infrastructure that allows this, we provide a very simple example here.

Previous Tutorial: Creating process modules
Next Tutorial: Using location designators with the TurtleSim

Setting up fact groups to select a process module

First let's create a new file selecting-process-modules.lisp and add it to our *.asd file. We also need to add cram-executive as a dependency to our system. It should now look like this:

(defsystem cram-beginner-tutorial
  :depends-on (cram-language roslisp turtlesim-msg geometry_msgs-msg cl-transforms
                             cram-designators cram-prolog
                             cram-process-modules cram-language-designator-support
                             cram-executive)
  :components
  ((:module "src"
            :components
            ((:file "package")
             (:file "control-turtlesim" :depends-on ("package"))
             (:file "simple-plans" :depends-on ("package" "control-turtlesim"))
             (:file "motion-designators" :depends-on ("package"))
             (:file "turtle-action-client" :depends-on ("package"))
             (:file "process-modules" :depends-on ("package"
                                                   "control-turtlesim"
                                                   "simple-plans"
                                                   "motion-designators"
                                                   "turtle-action-client"))
             (:file "selecting-process-modules" :depends-on ("package"
                                                             "motion-designators"
                                                             "process-modules"))))))

We only need to add a couple of Prolog rules to implement automatic process module choosing, append this to selecting-process-modules.lisp:

(in-package :tut)
 
(def-fact-group available-turtle-process-modules (available-process-module
                                                  matching-process-module)
  (<- (available-process-module turtlesim-navigation))
  (<- (available-process-module turtlesim-pen-control))
 
  (<- (matching-process-module ?desig turtlesim-navigation)
    (desig-prop ?desig (:type :driving)))
  (<- (matching-process-module ?desig turtlesim-navigation)
    (desig-prop ?desig (:type :moving)))
  (<- (matching-process-module ?desig turtlesim-pen-control)
    (desig-prop ?desig (:type :setting-pen))))

The available-turtle-process-modules fact group extends the predicates cram-process-modules:matching-process-module and cram-process-modules:available-process-module.

The first two facts say that we have two process modules available for automatically matching them to designators (this is used for switching process modules for simulating and executing on the real robot in parallel), in our case no conditions need to be true for this fact to hold, our process modules are always available. matching-process-module predicates match designators with specific properties (in our case (:type :moving), (:type :driving) or (:type :setting-pen)) to corresponding process modules names. See previous tutorials to find how these motion designators are resolved and how their corresponding process modules use them.

For convenience, let's add one more function to selecting-process-modules.lisp:

(defun perform-some-motion (motion-desig)
  (top-level
    (with-process-modules-running (turtlesim-navigation turtlesim-pen-control)
      (cram-executive:perform motion-desig))))

This function is mostly similar to previous ones we used to call process modules; the difference is that rather than calling pm-execute with a process module and an motion designator, we call cram-executive:perform with a motion designator and allow the system to decide what process module to use. In our case the decision is very simple, just a matter of matching type to appropriate consumer; more complex inferences are possible for real systems.

Running motion designators

Let's load our code in roslisp_repl. Make sure you have roscore and turtlesim in terminals in the background (see a previous tutorial for the exact commands). Also make sure you call start-ros-node and (init-ros-turtle “turtle1”) before executing the commands below.

With that, let's first make a couple of designators for test, so type this in REPL's command line:

TUT> (defparameter fast-circle (desig:a motion (type driving) (speed 10) (angle 7)))
FAST-CIRCLE
TUT> (defparameter goal (desig:a motion (type moving) (goal (1 9 0))))
GOAL
TUT> (defparameter pen-off (desig:a motion (type setting-pen) (off 1)))
PEN-OFF

With these designators defined, see what happens if you try to execute them. For example,

TUT> (perform-some-motion fast-circle)
[(TURTLE-PROCESS-MODULES) INFO] 1501142699.638: TurtleSim navigation invoked with motion designator `#<MOTION-DESIGNATOR ((TYPE
                                                                           DRIVING)
                                                                          (SPEED
                                                                           10)
                                                                          (ANGLE
                                                                           7)) {1009D756C3}>'.
1

The turtle should have driven in a circle.

Let's see if it will move to the top-left corner:

(perform-some-motion goal)
[(TURTLE-PROCESS-MODULES) INFO] 1501142702.867: TurtleSim navigation invoked with motion designator `#<MOTION-DESIGNATOR ((TYPE
                                                                           MOVING)
                                                                          (GOAL
                                                                           (1 9
                                                                            0))) {10068602D3}>'.
T

You can also perform pen-off and then one of the others to see that the turtle doesn't leave a trace anymore.

 (perform-some-motion pen-off)
[(TURTLE-PROCESS-MODULES) INFO] 1504786623.566: TurtleSim pen control invoked with motion designator `#<MOTION-DESIGNATOR ((TYPE
                                                                            SETTING-PEN)
                                                                           (OFF
                                                                            1)) {1002BB26A3}>'.
[TURTLESIM-SRV:SETPEN-RESPONSE]
TUT> (perform-some-motion fast-circle)
[(TURTLE-PROCESS-MODULES) INFO] 1504786630.845: TurtleSim navigation invoked with motion designator `#<MOTION-DESIGNATOR ((TYPE
                                                                           DRIVING)
                                                                          (SPEED
                                                                           10)
                                                                          (ANGLE
                                                                           7)) {1002BB2CD3}>'.
1

You can turn the pen back on with this:

(perform-some-motion (desig:a motion (type setting-pen) (off 0)))
[(TURTLE-PROCESS-MODULES) INFO] 1504786654.744: TurtleSim pen control invoked with motion designator `#<MOTION-DESIGNATOR ((TYPE
                                                                            SETTING-PEN)
                                                                           (OFF
                                                                            0)) {1002D6D763}>'.
[TURTLESIM-SRV:SETPEN-RESPONSE]

Next

Let's have a look at location designators and other ways to move the turtle, as well as have some more practice with designator resolution and process modules …

Using location designators with the TurtleSim