Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
Next revisionBoth sides next revision
tutorials:beginner:process_modules [2016/01/22 16:20] – [Process modules: an overview] gkazhoyatutorials:beginner:process_modules [2016/01/25 10:30] – [A process module for the turtlesim] gkazhoya
Line 30: Line 30:
  
 ===== Writing a process module for the turtlesim ===== ===== Writing a process module for the turtlesim =====
 +
 +For this tutorial we will use the [[http://wiki.ros.org/actionlib_lisp/Tutorials/actionlibBasicUsage|ActionLib]] turtlesim server for having a turtle draw a shape.
  
 Once again, some new dependencies must be declared in the tutorial files you've been working on.  Once again, some new dependencies must be declared in the tutorial files you've been working on. 
  
-In your package.xml file you need to add build and runtime dependencies on actionlib_lisp, turtle_actionlib, and cram_process_modules:+In your ''package.xml'' file you need to add build and runtime dependencies on ''actionlib_lisp''''actionlib_msgs''''turtle_actionlib'' and ''cram_process_modules'':
  
 <code> <code>
   <build_depend>actionlib_lisp</build_depend>   <build_depend>actionlib_lisp</build_depend>
 +  <build_depend>actionlib_msgs</build_depend>
   <build_depend>turtle_actionlib</build_depend>   <build_depend>turtle_actionlib</build_depend>
   <build_depend>cram_process_modules</build_depend>   <build_depend>cram_process_modules</build_depend>
  
-  <run_depend>cram_process_modules</run_depend> 
   <run_depend>actionlib_lisp</run_depend>   <run_depend>actionlib_lisp</run_depend>
 +  <run_depend>actionlib_msgs</run_depend>
   <run_depend>turtle_actionlib</run_depend>   <run_depend>turtle_actionlib</run_depend>
 +  <run_depend>cram_process_modules</run_depend>
 </code> </code>
  
-Similarly, in your .asd file you should add cram-language-designator-support, actionlib, actionlib_tutorials-msg, process-modules, turtle_actionlib-msg to the :depends-on list. Let's also create two new source files in the src folder of your tutorial, call them turtle-action-client.lisp and process-modules.lisp, and add them to your *.asd file which should now look like this:+Similarly, in your ''.asd'' file you should add ''actionlib''''actionlib_msgs-msg''''turtle_actionlib-msg'', ''cram-process-modules'' and ''cram-language-designator-support'' to the '':depends-on'' list. Let's also create two new source files in the ''src'' directory of your tutorial, call them ''turtle-action-client.lisp'' and ''process-modules.lisp'', and add them to your ''*.asd'' filewhich should now look like this:
  
 <code lisp> <code lisp>
 (defsystem cram-beginner-tutorial (defsystem cram-beginner-tutorial
-  :depends-on (roslisp cram-language turtlesim-msg cl-transforms geometry_msgs-msg designators cram-reasoning  +  :depends-on (cram-language roslisp turtlesim-msg geometry_msgs-msg cl-transforms 
-                 cram-language-designator-support actionlib actionlib_tutorials-msg process-modules turtle_actionlib-msg)+                             cram-designators cram-prolog 
 +                             actionlib actionlib_msgs-msg turtle_actionlib-msg 
 +                             cram-process-modules cram-language-designator-support)
   :components   :components
   ((:module "src"   ((:module "src"
             :components             :components
             ((:file "package")             ((:file "package")
-             (:file "control-turtlesim" :depends-on  ("package")) +             (:file "control-turtlesim" :depends-on ("package")) 
-             (:file "simple-plans" :depends-on  ("package" "control-turtlesim")) +             (:file "simple-plans" :depends-on ("package" "control-turtlesim")) 
-             (:file "action-designators" :depends-on  ("package")) +             (:file "action-designators" :depends-on ("package")) 
-             (:file "turtle-action-client" :depends-on  ("package")) +             (:file "turtle-action-client" :depends-on ("package")) 
-             (:file "process-modules" :depends-on  ("package" "control-turtlesim" "simple-plans" "action-designators" "turtle-action-client"))))))+             (:file "process-modules" :depends-on ("package" 
 +                                                   "control-turtlesim" 
 +                                                   "simple-plans" 
 +                                                   "action-designators" 
 +                                                   "turtle-action-client"))))))
 </code> </code>
 +
 +Finally, let's also add '':cram-process-modules'' to the use list of our Lisp package for convenience:
 +<code lisp>
 +  (:use :cpl :roslisp :cl-transforms :cram-designators :cram-process-modules)
 +</code>
 +
  
 ==== A process module for the turtlesim ==== ==== A process module for the turtlesim ====
  
-We first need to connect to the turtlesim as a client for an action that will have the turtle draw a shape. To do this, append the following to your turtle-action-client.lisp file+We first need to connect to the turtlesim action server with an ActionLib client. To do this, append the following to your ''turtle-action-client.lisp'':
  
 <code lisp> <code lisp>
Line 89: Line 105:
 </code> </code>
  
-The above code simply declares a variable *navp-client* which we can then initialize with a pointer to our ROS action client and retrieve this pointer later with the init-action-client and get-action-client functions, respectively.+The above code simply declares a variable ''*navp-client*'' which we can then initialize with a pointer to our ROS action client and retrieve this pointer later with the ''init-action-client'' and ''get-action-client functions'', respectively.
  
-We'll need a way to tell the action client to move along a shape (which is specified by a number of edges and a radius), so append this to process-modules.lisp:+We will need an action goal for our action client that should represent a shape (which is specified by a number of edges and a radius), so append this to the ''turtle-action-client.lisp'':
  
 <code lisp> <code lisp>
Line 116: Line 132:
 In the above code we define a simple function to convert an edge and radius pair of values into a goal for the action client, and a function that will call said action client, with some error handling built in (for example, if the function is called without an action client being defined, it will (re)initialize one and retry). In the above code we define a simple function to convert an edge and radius pair of values into a goal for the action client, and a function that will call said action client, with some error handling built in (for example, if the function is called without an action client being defined, it will (re)initialize one and retry).
  
-Now that the lower level of controlling the turtlesim is taken care of, it's finally time to look at process modules and their interface to the higher levels. Append the following to process-modules.lisp:+Now that the lower level of controlling the turtlesim is taken care of, it's finally time to look at process modules and their interface to the higher levels. Append the following to your ''process-modules.lisp'' file:
  
 <code lisp> <code lisp>
 (in-package :tut) (in-package :tut)
  
-(cram-process-modules:def-process-module turtle-actuators (action-designator)+(def-process-module turtle-actuators (action-designator)
   (roslisp:ros-info (turtle-process-modules)   (roslisp:ros-info (turtle-process-modules)
                     "Turtle navigation invoked with action designator `~a'."                     "Turtle navigation invoked with action designator `~a'."
                     action-designator)                     action-designator)
-  (destructuring-bind (cmd action-goal) (reference action-designator) +  (destructuring-bind (command action-goal) (reference action-designator) 
-    (ecase cmd +    (ecase command 
-      (shape +      (draw-shape 
-         (call-shape-action +       (call-shape-action 
-          :edges (turtle-shape-edges action-goal) +        :edges (turtle-shape-edges action-goal) 
-          :radius (turtle-shape-radius action-goal)))))) +        :radius (turtle-shape-radius action-goal))))))
  
 (defmacro with-turtle-process-modules (&body body) (defmacro with-turtle-process-modules (&body body)
-  `(cpm:with-process-modules-running+  `(with-process-modules-running
        (turtle-actuators)        (turtle-actuators)
      ,@body))      ,@body))
 </code> </code>
  
-First, we use the cram-process-modules:def-process-module macro to define turtle-actuators as a process module taking one parameter (action-designator). The other lines in the def-process-module are comprise the code for turtle-actuators. +First, we use the ''cram-process-modules:def-process-module'' macro to define ''turtle-actuators'' as a process module taking one parameter (''action-designator''). The process module then chooses which action to perform depending on the command specified in the designator: ''destructuring-bind'' maps the results from ''(reference action-designator)'' to the variables ''command'' and ''action-goal'' respectively. Note that the inference rules we defined previously provide a name for the kind of action goal we have (currently, all are ''draw-shape''), and a ''turtle-shape'' object. We run an ''ecase'' on the kind of goal (currently, we only have the shape case) and use ''call-shape-action'' to tell the lower level to move the turtle around, given these parameters we infer from designator resolution.
- +
-destructuring-bind will map the results from (reference action-designator) to the variables cmd and action-goal respectively. Note that the inference rules we defined previously provide a name for the kind of action goal we have (currently, all are "shape"), and a turtle-shape object. We run an ecase on the kind of goal (currently, we only have the shape case) and use the call-shape-action to tell the lower level to move the turtle around, given these parameters we infer from designator resolution.+
  
-The with-turtle-process-modules macro is a macro we define for convenience. It allows us to set up a context in which to run commands, knowing that the turtle process modules are all running concurrently. Right now we only have one defined, turtle-actuators. When we will have several, we will add them to the list we pass to cpm:with-process-modules-running. Note that the cpm:with-process-modules-running macro (and therefore with-turtle-process-modules too) needs to be run inside a top-level macro. We will see this below.+The ''with-turtle-process-modules'' macro is a macro we define for convenience. It allows us to set up a context in which to run commands, knowing that the turtle process modules are all running concurrently. Right now we only have one defined, turtle-actuators. When we will have several, we will add them to the list we pass to cpm:with-process-modules-running. Note that the cpm:with-process-modules-running macro (and therefore with-turtle-process-modules too) needs to be run inside a top-level macro. We will see this below.
  
 Let's try this out. Make sure you have roscore, turtlesim, and turtle_actionlib running. In a terminal tab for each, Let's try this out. Make sure you have roscore, turtlesim, and turtle_actionlib running. In a terminal tab for each,