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
tutorials:beginner:process_modules_2 [2017/07/18 15:04] – Added chapter about adding new motions and calling pms in parallel. cpotutorials:beginner:process_modules_2 [2020/09/03 10:34] (current) – [Writing a process module for the turtlesim] gkazhoya
Line 3: Line 3:
 **Description:** in this tutorial you will learn about CRAM process modules and write a simple one to move the turtlesim. **Description:** in this tutorial you will learn about CRAM process modules and write a simple one to move the turtlesim.
  
-**Previous Tutorial:** [[tutorials:beginner:designators|Creating action designators for the turtlesim]]\\ +**Previous Tutorial:** [[tutorials:beginner:motion_designators|Creating motion designators for the turtlesim]]\\ 
-**Next Tutorial:** [[tutorials:beginner:location_designators|Using location designators with the turtlesim]]+**Next Tutorial:** [[tutorials:beginner:assigning_actions_2|Automatically choosing a process module for a motion]]
  
 ===== Process modules: an overview ===== ===== Process modules: an overview =====
Line 26: Line 26:
 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 ''cram_process_modules'':+In your ''package.xml'' file you need to add a dependency on ''cram_process_modules'':
  
 <code> <code>
-  <build_depend>cram_process_modules</build_depend> +  <depend>cram_process_modules</depend>
- +
-  <run_depend>cram_process_modules</run_depend>+
 </code> </code>
  
Line 37: Line 35:
  
 <code lisp> <code lisp>
-(defsystem cram-beginner-tutorial +(defsystem cram-my-beginner-tutorial 
-  :depends-on (cram-language roslisp turtlesim-msg geometry_msgs-msg cl-transforms+  :depends-on (cram-language roslisp turtlesim-msg turtlesim-srv geometry_msgs-msg cl-transforms
                              cram-designators cram-prolog                              cram-designators cram-prolog
                              cram-process-modules cram-language-designator-support)                              cram-process-modules cram-language-designator-support)
Line 47: Line 45:
              (: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 "motion-designators" :depends-on ("package"))
              (:file "process-modules" :depends-on ("package"              (:file "process-modules" :depends-on ("package"
                                                    "control-turtlesim"                                                    "control-turtlesim"
                                                    "simple-plans"                                                    "simple-plans"
-                                                   "action-designators"))))))+                                                   "motion-designators"))))))
 </code> </code>
  
Line 80: Line 78:
 </code> </code>
  
-First, we use the ''cram-process-modules:def-process-module'' macro to define ''turtlesim-navigation'' as a process module taking one parameter (''motion-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 motion-designator)'' to the variables ''command'' and ''motion'' respectively. Note that the inference rules we defined previously provide a name for the kind of motion we have (currently, all are ''drive''), and a ''turtle-motion'' object. We run an ''ecase'' on the kind of goal (currently, we only have the drive case) and use ''send-vel-cmd'' to tell the lower level to move the turtle around, given these parameters we infer from designator resolution.+First, we use the ''cram-process-modules:def-process-module'' macro to define ''turtlesim-navigation'' as a process module taking one parameter (''motion-designator''). The process module then chooses which motion to perform depending on the command specified in the designator: ''destructuring-bind'' maps the results from ''(reference motion-designator)'' to the variables ''command'' and ''motion'' respectively. Note that the inference rules we defined previously provide a name for the kind of motion we have (currently, all are ''drive''), and a ''turtle-motion'' object. We run an ''ecase'' on the kind of goal (currently, we only have the drive case) and use ''send-vel-cmd'' to tell the lower level to move the turtle around, given these parameters we infer from designator resolution.
  
 Let's try this out. Make sure you have ''roscore'' and ''turtlesim_node'' running. In a terminal tab for each, Let's try this out. Make sure you have ''roscore'' and ''turtlesim_node'' running. In a terminal tab for each,
Line 116: Line 114:
 <code lisp> <code lisp>
 TUT> (drive 5 2) TUT> (drive 5 2)
-[(TURTLE-PROCESS-MODULES) INFO] 1499958119.336: TurtleSim navigation invoked with motion designator `#<MOTION-DESIGNATOR ((TYPE +[(TURTLE-PROCESS-MODULES) INFO] 1562698751.679: TurtleSim navigation invoked with motion designator `#<MOTION 
-                                                                           DRIVING) +    (TYPE DRIVING) 
-                                                                          (SPEED +    (SPEED 5) 
-                                                                           5) +    (ANGLE 2)>'.
-                                                                          (ANGLE +
-                                                                           2)) {1006979703}>'.+
 1 1
 </code> </code>
Line 134: Line 130:
 So to make this decision, we need to think about resources on the robot (eg. arms or the base of the robot). So to make this decision, we need to think about resources on the robot (eg. arms or the base of the robot).
  
-Our ''turtlesim-navigation'' is for the (abstract) resource 'driving' of the turtle. We now want to add the motions for setting the pen. Since this doesn't use the same resources as the navigation process module, we should add it as a new one.+Our ''turtlesim-navigation'' is for the (abstract) resource 'driving' of the turtle. We now want to add the motions for moving and for setting the pen. Former uses the same resource as the navigation process module, so we should add it to the existing process module. The latter however doesn't, so we should add it as a new process module.
  
-Append this to your ''process-modules.lisp'' file.+To add the move motion to the existing process module, we add a new case to the ''ecase''. It should look like this: 
 + 
 +<code lisp> 
 +(def-process-module turtlesim-navigation (motion-designator) 
 +  (roslisp:ros-info (turtle-process-modules) 
 +                    "TurtleSim navigation invoked with motion designator `~a'." 
 +                    motion-designator) 
 +  (destructuring-bind (command motion) (reference motion-designator) 
 +    (ecase command 
 +      (drive 
 +         (send-vel-cmd 
 +          (turtle-motion-speed motion) 
 +          (turtle-motion-angle motion))) 
 +      (move 
 +       (move-to motion))))) 
 +</code> 
 + 
 +Since ''move-to'' takes a 3d-vector as a parameter we only have to pass ''motion'' to it. 
 + 
 + 
 +To add the new process module, append this to your ''process-modules.lisp'' file.
  
 <code lisp> <code lisp>
Line 159: Line 175:
 ==== Executing process modules in parallel ==== ==== Executing process modules in parallel ====
  
-To demonstrate how process modules work when called in parallel, we will make a little adjustment to the code of ''turtlesim-navigation'': +To demonstrate how process modules work when called in parallel, we will call the same process module twiceYou can execute the following in the REPL:
- +
-<code lisp> +
-(def-process-module turtlesim-navigation (motion-designator) +
-  (roslisp:ros-info (turtle-process-modules) +
-                    "TurtleSim navigation invoked with motion designator `~a'.+
-                    motion-designator) +
-  (destructuring-bind (command motion) (reference motion-designator) +
-    (ecase command +
-      (drive +
-       (dotimes (i 10) +
-         (send-vel-cmd +
-          (turtle-motion-speed motion) +
-          (turtle-motion-angle motion)) +
-         (sleep 1)))))) +
-</code> +
- +
-Instead of just sending a single command, we send ten commands over the course of ten seconds. This way the process module will be occupied while executing a drive designator. Without this, all executions would be instantaneous and we wouldn't see any queueing. +
-But this change is only temporary for the sake of this demonstration. +
- +
-After the change you can execute the following in your REPL and look at the TurtleSim.+
  
 <code lisp> <code lisp>
 TUT> (top-level TUT> (top-level
     (with-process-modules-running (turtlesim-navigation turtlesim-pen-control)     (with-process-modules-running (turtlesim-navigation turtlesim-pen-control)
-      (let ((trajectory (desig:a motion (type driving) (speed 1) (angle 1))) +      (let ((goal (desig:a motion (type moving) (goal (0)))) 
-            (trajectory2 (desig:a motion (type driving) (speed 1) (angle 2))))+            (trajectory (desig:a motion (type driving) (speed 3) (angle 8))))
         (cpl:par         (cpl:par
-          (pm-execute 'turtlesim-navigation trajectory+          (pm-execute 'turtlesim-navigation goal
-          (pm-execute 'turtlesim-navigation trajectory2))))) +          (pm-execute 'turtlesim-navigation trajectory))))) 
- +[(TURTLE-PROCESS-MODULES) INFO] 1500997686.711: TurtleSim navigation invoked with motion designator `#<MOTION-DESIGNATOR ((TYPE 
-[(TURTLE-PROCESS-MODULES) INFO] 1500389140.365: TurtleSim navigation invoked with motion designator `#<MOTION-DESIGNATOR ((TYPE +                                                                           MOVING
-                                                                           DRIVING+                                                                          (GOAL 
-                                                                          (SPEED +                                                                           (9 1 
-                                                                           1) +                                                                            0))) {1006DBC893}>'.
-                                                                          (ANGLE +
-                                                                           1)) {100680BC83}>'.+
 WARNING: WARNING:
    Process module #<TURTLESIM-NAVIGATION    Process module #<TURTLESIM-NAVIGATION
-                    {1006E78283}> already processing input. Waiting for it to become free. +                    {10074C0293}> already processing input. Waiting for it to become free. 
-[(TURTLE-PROCESS-MODULES) INFO] 1500389150.382: TurtleSim navigation invoked with motion designator `#<MOTION-DESIGNATOR ((TYPE+[(TURTLE-PROCESS-MODULES) INFO] 1500997690.065: TurtleSim navigation invoked with motion designator `#<MOTION-DESIGNATOR ((TYPE
                                                                            DRIVING)                                                                            DRIVING)
                                                                           (SPEED                                                                           (SPEED
-                                                                           1)+                                                                           3)
                                                                           (ANGLE                                                                           (ANGLE
-                                                                           2)) {100680C063}>'+                                                                           8)) {1006DBCC73}>'
-NIL+T
 </code> </code>
  
-Here we use the ''par'' macro to call the same process module twice in parallel. When looking at the turtle we see, that it first drives in a circle and then switches to drive in smaller circle after roughly ten seconds. So the two designators were not executed in parallel because they were executed with the same process module. Also a warning gets printed stating, that the program waits for the process module to be free before executing the next designator.+Here we use the ''par'' macro to call the same process module twice in parallel. When looking at the turtle we see, that it first moves to the bottom-right corner and then drives in a circle for second. So the two designators were not executed in parallel because they were executed with the same process module. Also a warning gets printed stating, that the program waits for the process module to be free before executing the next designator.
  
 If we use two different process modules, they can in fact be called in parallel: If we use two different process modules, they can in fact be called in parallel:
Line 215: Line 209:
 TUT> (top-level TUT> (top-level
     (with-process-modules-running (turtlesim-navigation turtlesim-pen-control)     (with-process-modules-running (turtlesim-navigation turtlesim-pen-control)
-      (let ((trajectory (desig:a motion (type driving) (speed 1) (angle 0.5))))+      (let ((goal (desig:a motion (type moving) (goal (9 9 0)))))
         (cpl:par         (cpl:par
-          (pm-execute 'turtlesim-navigation trajectory)+          (pm-execute 'turtlesim-navigation goal)
           (dotimes (i 10)           (dotimes (i 10)
             (pm-execute 'turtlesim-pen-control             (pm-execute 'turtlesim-pen-control
Line 223: Line 217:
                             (?g (random 255))                             (?g (random 255))
                             (?b (random 255))                             (?b (random 255))
-                            (?width (random 5)))+                            (?width (+ 3 (random 5))))
                       (desig:a motion (type setting-pen) (r ?r) (g ?g) (b ?b) (width ?width))))                       (desig:a motion (type setting-pen) (r ?r) (g ?g) (b ?b) (width ?width))))
-            (sleep 1)))))) +            (sleep 0.5)))))) 
-[(TURTLE-PROCESS-MODULES) INFO] 1500389629.839: TurtleSim navigation invoked with motion designator `#<MOTION-DESIGNATOR ((TYPE +[(TURTLE-PROCESS-MODULES) INFO] 1500997786.329: TurtleSim navigation invoked with motion designator `#<MOTION-DESIGNATOR ((TYPE 
-                                                                           DRIVING+                                                                           MOVING
-                                                                          (SPEED +                                                                          (GOAL 
-                                                                           1) +                                                                           (9 9 
-                                                                          (ANGLE +                                                                            0))) {1005164AC3}>'
-                                                                           0.5)) {1004D7BD43}>'+[(TURTLE-PROCESS-MODULES) INFO] 1500997786.347: TurtleSim pen control invoked with motion designator `#<MOTION-DESIGNATOR ((TYPE
-[(TURTLE-PROCESS-MODULES) INFO] 1500389629.855: TurtleSim pen control invoked with motion designator `#<MOTION-DESIGNATOR ((TYPE+
                                                                             SETTING-PEN)                                                                             SETTING-PEN)
                                                                            (R                                                                            (R
-                                                                            225)+                                                                            220)
                                                                            (G                                                                            (G
-                                                                            228)+                                                                            115)
                                                                            (B                                                                            (B
-                                                                            156)+                                                                            14)
                                                                            (WIDTH                                                                            (WIDTH
-                                                                            0)) {1005BA0363}>'+                                                                            7)) {10072183E3}>'
 +                                                                            
 [ ... ] [ ... ]
- +                                                                             
-[(TURTLE-PROCESS-MODULES) INFO] 1500389639.067: TurtleSim pen control invoked with motion designator `#<MOTION-DESIGNATOR ((TYPE+[(TURTLE-PROCESS-MODULES) INFO] 1500997791.126: TurtleSim pen control invoked with motion designator `#<MOTION-DESIGNATOR ((TYPE
                                                                             SETTING-PEN)                                                                             SETTING-PEN)
                                                                            (R                                                                            (R
-                                                                            77)+                                                                            225)
                                                                            (G                                                                            (G
-                                                                            137)+                                                                            228)
                                                                            (B                                                                            (B
-                                                                            51)+                                                                            156)
                                                                            (WIDTH                                                                            (WIDTH
-                                                                            3)) {1008E58DD3}>'+                                                                            3)) {1002B903C3}>'
-NIL+T
 </code> </code>
  
-Here we call our modified ''turtlesim-navigation'' and in parallel call our other process module to change the pen color and width every second. When looking at the turtle we can see it driving a wide circle while randomly changing its pen.+Here we call the navigation process module to move the turtle to the upper right corner and our other process module to change the pen color and width twice every second. When looking at the turtle we can see it moving to the upper right corner while randomly changing its pen.
  
 As stated above this behaviour is to ensure that a single resource on a robot isn't used by multiple functions at once, while not hindering the parallel execution of independent resources. But keep in mind, that this is only true for the low-level motions. If a robots arms should grasp something and its base is moved, the grasping might fail, although these motions are not necessarily controlled by the same process module. As stated above this behaviour is to ensure that a single resource on a robot isn't used by multiple functions at once, while not hindering the parallel execution of independent resources. But keep in mind, that this is only true for the low-level motions. If a robots arms should grasp something and its base is moved, the grasping might fail, although these motions are not necessarily controlled by the same process module.
Line 264: Line 257:
  
 == Next == == Next ==
 +So far we called process modules directly. Sometimes it's better to let the system decide on its own … 
  
-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 ... +[[tutorials:beginner:assigning_actions_2|Automatically choosing a process module for a motion]]
- +
-[[tutorials:beginner:location_designators|Using location designators with the turtlesim]]+