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
Last revisionBoth sides next revision
tutorials:beginner:motion_designators [2017/09/07 12:04] – [Adding a motion for moving] cpotutorials:beginner:motion_designators [2022/02/25 23:12] – [Creating motion designators for the TurtleSim] schimpf
Line 3: Line 3:
 **Description:** In this tutorial you will learn what designators are, and in particular, work with motion designators: you will learn how to define one and how to use it. **Description:** In this tutorial you will learn what designators are, and in particular, work with motion designators: you will learn how to define one and how to use it.
  
-**Previous Tutorial:** [[tutorials:beginner:simple_plans|Implementing simple plans to move a turtle]]\\ +**Previous Tutorial:** [[tutorials:beginner:cram_prolog|Using Prolog for reasoning]]\\ 
-**Next Tutorial:** [[tutorials:beginner:process_modules|Creating process modules]]+**Next Tutorial:** [[tutorials:beginner:process_modules_2|Creating process modules]] 
 + 
 +To run the code in the tutuorial the roscore and the turtlesim need to be started over the terminal: 
 +<code bash> 
 +$ roscore 
 +</code> 
 +<code bash> 
 +$ rosrun turtlesim turtlesim_node 
 +</code>
  
 ===== Designators: an overview ===== ===== Designators: an overview =====
Line 10: Line 18:
 From a user's point of view, a designator is a Common Lisp object that contains a sequence of key-value pairs representing a high-level, symbolic description of some aspect of robot's activity. The power and usefulness of the designator concept comes from the ability to infer concrete parameters when needed, based on user-specified rules, from the context in which the robot operates and the symbolic description in the designator. This is known as 'resolving' or '[de]referencing' a designator, and it returns an object containing the newly resolved values that can then be used by the robot to specify some task. From a user's point of view, a designator is a Common Lisp object that contains a sequence of key-value pairs representing a high-level, symbolic description of some aspect of robot's activity. The power and usefulness of the designator concept comes from the ability to infer concrete parameters when needed, based on user-specified rules, from the context in which the robot operates and the symbolic description in the designator. This is known as 'resolving' or '[de]referencing' a designator, and it returns an object containing the newly resolved values that can then be used by the robot to specify some task.
  
-Currently there are five types of designators defined in CRAM:+Currently there are the following types of designators defined in CRAM:
  
   * location designators: describe locations taking various constraints into account (for example, reachability, visibility etc)   * location designators: describe locations taking various constraints into account (for example, reachability, visibility etc)
Line 16: Line 24:
   * motion designators: describe a low-level motion that a robot should take and serve as input to [[tutorials:beginner:process_modules|process modules]]   * motion designators: describe a low-level motion that a robot should take and serve as input to [[tutorials:beginner:process_modules|process modules]]
   * action designators: describe an high-level action, which can't be done with a simple (single) motion   * action designators: describe an high-level action, which can't be done with a simple (single) motion
-  * human designators: describe a human actor in the scene 
  
 These types should cover most use cases in robotics, however, if needed, new designator types can be defined as subclasses of the ''designator'' class. These types should cover most use cases in robotics, however, if needed, new designator types can be defined as subclasses of the ''designator'' class.
Line 23: Line 30:
  
 <code lisp> <code lisp>
-(defparameter spy-location (desig:a location (to see) (object ?prime-minister)))+(defparameter *spy-location(desig:a location (to see) (object ?prime-minister)))
 </code> </code>
  
 (Do not add this code to your tutorial files, it is meant simply for illustration here.) (Do not add this code to your tutorial files, it is meant simply for illustration here.)
  
-This line of code creates a location designator (''spy-location'') which "knows" of the given object (''?prime-minister'', which we assume is an already defined object designator), and knows that its purpose is to see the object. We do not actually specify a location in terms of coordinates at this moment. When we do want to find a suitable set of coordinates for this location, we would call+This line of code creates a location designator (''*spy-location*'') which "knows" of the given object (''?prime-minister'', which we assume is an already defined object designator), and knows that its purpose is to see the object. We do not actually specify a location in terms of coordinates at this moment. When we do want to find a suitable set of coordinates for this location, we would call
  
 <code lisp> <code lisp>
-(reference spy-location)+(reference *spy-location*)
 </code> </code>
  
Line 40: Line 47:
 ===== Using motion designators ===== ===== Using motion designators =====
  
-First, you will need to add a few more dependencies to the tutorial package files you created previously. To ''package.xml'', add build and run dependencies on ''cram_prolog'' and ''cram_designators'':+First, you will need to add a few more dependencies to the tutorial package files you created previously. To ''package.xml'', add dependencies on ''cram_prolog'' and ''cram_designators'', but this time only with '<depend>:
  
 <code> <code>
-  <build_depend>cram_prolog</build_depend+  <depend>cram_prolog</depend
-  <build_depend>cram_designators</build_depend> +  <depend>cram_designators</depend>
- +
-  <run_depend>cram_prolog</run_depend> +
-  <run_depend>cram_designators</run_depend>+
 </code> </code>
  
-In your ''cram-beginner-tutorial.asd'' file, on the '':depends-on'' line, add dependencies to ''cram-designators'' and ''cram-prolog''. Let's also create a new source file for the code in this tutorial (under ''src'' directory), call it ''motion-designators.lisp''. We will need to add the file to the '':components'' of the ''src'' module in your ''cram-beginner-tutorial.asd'', which should now look something like this:+In your ''cram-my-beginner-tutorial.asd'' file, on the '':depends-on'' line, add dependencies to ''cram-designators'' and ''cram-prolog''. Let's also create a new source file for the code in this tutorial (under ''src'' directory), call it ''motion-designators.lisp''. It can be empty for now. We will need to add the file to the '':components'' of the ''src'' module in your ''cram-my-beginner-tutorial.asd'', which should now look something like this:
  
 <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)
   :components   :components
Line 68: Line 73:
  
 <code lisp> <code lisp>
-(defpackage :cram-beginner-tutorial+(defpackage :cram-my-beginner-tutorial
   (:nicknames :tut)   (:nicknames :tut)
   (:use :cpl :roslisp :cl-transforms :cram-designators)   (:use :cpl :roslisp :cl-transforms :cram-designators)
Line 74: Line 79:
 </code> </code>
  
-Now, reload the tutorial in ''roslisp_repl'' (which also loads the newly added dependencies).+Now, reload the tutorial in ''roslisp_repl'' (which also loads the newly added dependencies)
 + 
 +<code lisp> 
 +PROLOG> (ros-load:load-system "cram_my_beginner_tutorial" :cram-my-beginner-tutorial) 
 +PROLOG> (in-package :tut) 
 +</code>
  
 ==== Creating a motion designator ==== ==== Creating a motion designator ====
Line 81: Line 91:
  
 <code lisp> <code lisp>
-TUT> (defparameter my-desig (desig:a motion (type driving) (speed 1.5))) +TUT> (defparameter *my-desig(desig:a motion (type driving) (speed 1.5))) 
-MY-DESIG +*MY-DESIG* 
-TUT> (desig-prop-value my-desig :speed)+TUT> (desig-prop-value *my-desig:speed)
 1.5 1.5
 </code> </code>
 +
 +We call the variable ''*my-desig*'' with asterisks as this is the common convention in Common Lisp for naming global variables.
  
 We use the ''a'' macro to create designators. Internally it uses the ''make-designator'' function to create a designator of the specified type. The macro allows us to write cleaner code for designator creation. We use the ''a'' macro to create designators. Internally it uses the ''make-designator'' function to create a designator of the specified type. The macro allows us to write cleaner code for designator creation.
Line 92: Line 104:
  
 <code lisp> <code lisp>
-TUT> (reference my-desig)+TUT> (reference *my-desig*)
 Cannot resolve motion designator #<MOTION-DESIGNATOR ((TYPE Cannot resolve motion designator #<MOTION-DESIGNATOR ((TYPE
                                                        DRIVING)                                                        DRIVING)
Line 103: Line 115:
  
 ==== Defining inference rules for designators ==== ==== Defining inference rules for designators ====
 +
 +The function ''reference'' uses the CRAM Prolog engine to ground a motion designator into specific motion parameters.
 +CRAM Prolog engine is a Prolog interpreter / compiler implemented as a domain-specific language within Lisp.
 +To learn more about CRAM Prolog look at the [[cram_prolog|Using Prolog for reasoning]] tutorial.
 +To ''reference'' a motion designator, ''motion-grounding'' Prolog rule is being called on the given designator and the rule binds a tuple of command and specific motion parameters to its second argument.
  
 Append the following to your ''motion-designators.lisp'' file: Append the following to your ''motion-designators.lisp'' file:
Line 114: Line 131:
   angle)   angle)
  
-(def-fact-group turtle-motion-designators (motion-desig)+(def-fact-group turtle-motion-designators (motion-grounding)
   ;; for each kind of motion, check for and extract the necessary info   ;; for each kind of motion, check for and extract the necessary info
  
   ;; drive and turn   ;; drive and turn
-  (<- (desig:motion-desig ?desig (drive ?motion))+  (<- (desig:motion-grounding ?desig (drive ?motion))
     (desig-prop ?desig (:type :driving))     (desig-prop ?desig (:type :driving))
     (desig-prop ?desig (:speed ?speed))     (desig-prop ?desig (:speed ?speed))
Line 125: Line 142:
      
   ;; drive   ;; drive
-  (<- (desig:motion-desig ?desig (drive ?motion))+  (<- (desig:motion-grounding ?desig (drive ?motion))
     (desig-prop ?desig (:type :driving))     (desig-prop ?desig (:type :driving))
     (desig-prop ?desig (:speed ?speed))     (desig-prop ?desig (:speed ?speed))
Line 131: Line 148:
  
   ;; turn   ;; turn
-  (<- (desig:motion-desig ?desig (drive ?motion))+  (<- (desig:motion-grounding ?desig (drive ?motion))
     (desig-prop ?desig (:type :driving))     (desig-prop ?desig (:type :driving))
     (desig-prop ?desig (:angle ?angle))     (desig-prop ?desig (:angle ?angle))
Line 140: Line 157:
 Let's see what this code does. The defstruct declares a structure type to hold values resulting from the inference. It's an instantiation of our motion in a space of (possibly) continuous parameters, which we deduce from a symbolic description of the designator via rules given in the def-fact-group. Let's see what this code does. The defstruct declares a structure type to hold values resulting from the inference. It's an instantiation of our motion in a space of (possibly) continuous parameters, which we deduce from a symbolic description of the designator via rules given in the def-fact-group.
  
-As for the inference rules themselves, these are Prolog code embedded in Lisp, for it is Prolog that powers the inference behind designator resolution. To learn more about CRAM Prolog look at the [[cram_prolog|Using Prolog for reasoning]] tutorial. The ''def-fact-group'' is a collection of several rules, each of similar structure, so it helps to look at one of them in more detail:+As for the inference rules themselves, these are Prolog code embedded in Lisp, for it is Prolog that powers the inference behind designator resolution. The ''def-fact-group'' is a collection of several rules, each of similar structure, so it helps to look at one of them in more detail:
  
 <code lisp> <code lisp>
-  (<- (desig:motion-desig ?desig (drive ?motion))+  (<- (desig:motion-grounding ?desig (drive ?motion))
     (desig-prop ?desig (:type :driving))     (desig-prop ?desig (:type :driving))
     (desig-prop ?desig (:speed ?speed))     (desig-prop ?desig (:speed ?speed))
Line 153: Line 170:
  
 <code lisp> <code lisp>
-  (<- (desig:motion-desig ?desig (drive ?motion))+  (<- (desig:motion-grounding ?desig (drive ?motion))
 </code> </code>
  
Line 169: Line 186:
 For the example rule we've selected, Prolog looks at the designator and asks "does it contain a key-value pair that is ''(:type :driving)''?" (so no variables here except the designator itself). Assuming this is true, it then asks "does it contain a key-value pair that is ''(speed <some variable value>)''?". This last question has the effect of extracting the value of the speed parameter that we created the designator with and making it available to Prolog. This is done again to extract the value of the angle parameter. Lastly it uses ''lisp-fun'' to call a lisp function and store it's result in a variable available to Prolog. In this case it calls ''make-turtle-motion'', which is the default function to instantiate our previously defined struct ''turtle-motion''. It then stores the struct in ''?motion''. For the example rule we've selected, Prolog looks at the designator and asks "does it contain a key-value pair that is ''(:type :driving)''?" (so no variables here except the designator itself). Assuming this is true, it then asks "does it contain a key-value pair that is ''(speed <some variable value>)''?". This last question has the effect of extracting the value of the speed parameter that we created the designator with and making it available to Prolog. This is done again to extract the value of the angle parameter. Lastly it uses ''lisp-fun'' to call a lisp function and store it's result in a variable available to Prolog. In this case it calls ''make-turtle-motion'', which is the default function to instantiate our previously defined struct ''turtle-motion''. It then stores the struct in ''?motion''.
  
-If all of the above body rules are true (or can be executed sucessfully) then the head is itself evaluated, and what it does is glue the newly created ''?motion'', the object containing the concrete values, to the designator ''?desig''. Or in more concrete terms, it defines what the value of the ''motion-desig'' predicate is if applied to ''?desig'', and that value is a list containing the instruction ''drive'' and the value of ''?motion''.+If all of the above body rules are true (or can be executed sucessfully) then the head is itself evaluated, and what it does is glue the newly created ''?motion'', the object containing the concrete values, to the designator ''?desig''. Or in more concrete terms, it defines what the value of the ''motion-grounding'' predicate is if applied to ''?desig'', and that value is a list containing the instruction ''drive'' and the value of ''?motion''.
  
 If in any step of the inference Prolog stumbles upon ''false'' (or ''NIL'') it exists the current search branch and continues searching somewhere else. If in any step of the inference Prolog stumbles upon ''false'' (or ''NIL'') it exists the current search branch and continues searching somewhere else.
Line 180: Line 197:
  
 <code lisp> <code lisp>
-TUT> (defparameter my-desig2 (desig:a motion (type driving) (speed 1.5) (angle 2))) +TUT> (defparameter *my-desig2(desig:a motion (type driving) (speed 1.5) (angle 2))) 
-MY-DESIG2 +*MY-DESIG2 
-TUT> (reference my-desig2)+TUT> (reference *my-desig2*)
 (DRIVE #S(TURTLE-MOTION :SPEED 1.5 :ANGLE 2)) (DRIVE #S(TURTLE-MOTION :SPEED 1.5 :ANGLE 2))
 </code> </code>
Line 191: Line 208:
 ==== Adding a motion for moving ==== ==== Adding a motion for moving ====
  
-In the previous tutorial we added a simple plan to move to a location. This is a low level motion, so we should a rule for it to our fact-group ''turtle-motion-designators'':+In the previous tutorial we added a simple plan to move to a location. This is a low level motion, so we should add a rule for it to our fact-group ''turtle-motion-designators'':
  
 <code lisp> <code lisp>
-(def-fact-group turtle-motion-designators (motion-desig)+(def-fact-group turtle-motion-designators (motion-grounding)
   ;; for each kind of motion, check for and extract the necessary info   ;; for each kind of motion, check for and extract the necessary info
      
   ;; drive and turn   ;; drive and turn
-  (<- (desig:motion-desig ?desig (drive ?motion))+  (<- (desig:motion-grounding ?desig (drive ?motion))
     (desig-prop ?desig (:type :driving))     (desig-prop ?desig (:type :driving))
     (desig-prop ?desig (:speed ?speed))     (desig-prop ?desig (:speed ?speed))
Line 205: Line 222:
      
   ;; drive   ;; drive
-  (<- (desig:motion-desig ?desig (drive ?motion))+  (<- (desig:motion-grounding ?desig (drive ?motion))
     (desig-prop ?desig (:type :driving))     (desig-prop ?desig (:type :driving))
     (desig-prop ?desig (:speed ?speed))     (desig-prop ?desig (:speed ?speed))
Line 211: Line 228:
  
   ;; turn   ;; turn
-  (<- (desig:motion-desig ?desig (drive ?motion))+  (<- (desig:motion-grounding ?desig (drive ?motion))
     (desig-prop ?desig (:type :driving))     (desig-prop ?desig (:type :driving))
     (desig-prop ?desig (:angle ?angle))     (desig-prop ?desig (:angle ?angle))
Line 217: Line 234:
      
   ;; move   ;; move
-  (<- (desig:motion-desig ?desig (move ?motion))+  (<- (desig:motion-grounding ?desig (move ?motion))
     (desig-prop ?desig (:type :moving))     (desig-prop ?desig (:type :moving))
     (desig-prop ?desig (:goal ?goal))     (desig-prop ?desig (:goal ?goal))
Line 227: Line 244:
 <code lisp> <code lisp>
 TUT> (desig:a motion (type moving) (goal (1 1 0))) TUT> (desig:a motion (type moving) (goal (1 1 0)))
-#<MOTION-DESIGNATOR ((:TYPE :MOVING) (:GOAL (1 1 0))) {10042C61F3}>+#<MOTION 
 +    (TYPE MOVING) 
 +    (GOAL (1 1 0))>
 </code> </code>
  
Line 244: Line 263:
   (off 0))   (off 0))
  
-(def-fact-group turtle-pen-motion-designators (motion-desig)+(def-fact-group turtle-pen-motion-designators (motion-grounding)
   ;; for each kind of pen motion, check for and extract the necessary info   ;; for each kind of pen motion, check for and extract the necessary info
  
   ;; change color, width and on/off status   ;; change color, width and on/off status
-  (<- (desig:motion-desig ?desig (set-pen ?motion))+  (<- (desig:motion-grounding ?desig (set-pen ?motion))
     (desig-prop ?desig (:type :setting-pen))     (desig-prop ?desig (:type :setting-pen))
     (desig-prop ?desig (:r ?r))     (desig-prop ?desig (:r ?r))
Line 258: Line 277:
  
   ;; change color and width (implicates setting the pen to 'on')   ;; change color and width (implicates setting the pen to 'on')
-  (<- (desig:motion-desig ?desig (set-pen ?motion))+  (<- (desig:motion-grounding ?desig (set-pen ?motion))
     (desig-prop ?desig (:type :setting-pen))     (desig-prop ?desig (:type :setting-pen))
     (desig-prop ?desig (:r ?r))     (desig-prop ?desig (:r ?r))
Line 267: Line 286:
  
   ;; change on/off status (if set to 'on' the pen will have a default color and width)   ;; change on/off status (if set to 'on' the pen will have a default color and width)
-  (<- (desig:motion-desig ?desig (set-pen ?motion))+  (<- (desig:motion-grounding ?desig (set-pen ?motion))
     (desig-prop ?desig (:type :setting-pen))     (desig-prop ?desig (:type :setting-pen))
     (desig-prop ?desig (:off ?off))     (desig-prop ?desig (:off ?off))
Line 280: Line 299:
  
 <code lisp> <code lisp>
-TUT> (defparameter my-desig3 (desig:a motion (type setting-pen) (r 100) (g 150) (b 0) (width 5))) +TUT> (defparameter *my-desig3(desig:a motion (type setting-pen) (r 100) (g 150) (b 0) (width 5))) 
-MY-DESIG3 +*MY-DESIG3* 
-TUT> (reference my-desig3)+TUT> (reference *my-desig3*)
 (SET-PEN #S(PEN-MOTION :R 100 :G 150 :B 0 :WIDTH 5 :OFF 0)) (SET-PEN #S(PEN-MOTION :R 100 :G 150 :B 0 :WIDTH 5 :OFF 0))
 </code> </code>
Line 294: Line 313:
 Now that we know how to handle designators, we need to have the robot act on them in some way. CRAM process modules allow us to do just that ... Now that we know how to handle designators, we need to have the robot act on them in some way. CRAM process modules allow us to do just that ...
  
-[[tutorials:beginner:process_modules|Creating process modules]]+[[tutorials:beginner:process_modules_2|Creating process modules]]