Differences

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

Link to this comparison view

Both sides previous revisionPrevious revision
Next revisionBoth sides next revision
tutorials:beginner:failure_handling [2019/07/11 11:21] – [Appendix: Retry counters] gkazhoyatutorials:beginner:failure_handling [2019/07/16 11:32] – Rename plan ''move'' to ''navigate''. cpo
Line 4: Line 4:
  
 **Previous Tutorial:** [[tutorials:beginner:high_level_plans|Writing plans for the TurtleSim]] **Previous Tutorial:** [[tutorials:beginner:high_level_plans|Writing plans for the TurtleSim]]
 +**Next Tutorial:** [[tutorials:beginner:testing|Writing tests]]
  
 ===== Failure Handling in CRAM ===== ===== Failure Handling in CRAM =====
Line 100: Line 101:
 This defines the condition ''out-of-bounds-error'' which inherits from ''cpl:simple-plan-failure''. It's a good idea to base your own conditions on the ones provided by CRAM, so it's recognized as a plan-failure by CRAM. This defines the condition ''out-of-bounds-error'' which inherits from ''cpl:simple-plan-failure''. It's a good idea to base your own conditions on the ones provided by CRAM, so it's recognized as a plan-failure by CRAM.
  
-Let's signal this condition when moving outside of the bounds of the world. For this we will expand our ''move'' plan in ''high-level-plans.lisp'':+Let's signal this condition when moving outside of the bounds of the world. For this we will expand our ''navigate'' plan in ''high-level-plans.lisp'':
  
 <code lisp> <code lisp>
Line 106: Line 107:
 (defparameter *max-bound* 10.5) (defparameter *max-bound* 10.5)
  
-(defun move (?v)+(defun navigate (?v)
   (flet ((out-of-bounds (pose)   (flet ((out-of-bounds (pose)
            (with-fields (x y)            (with-fields (x y)
Line 119: Line 120:
  
 At first this looks more complicated than it is. We have a ''flet'' to define a local function ''out-of-bounds'' to check if a poses position is out of bounds of the world. Normally you would react to a collision or something like that, but checking if the turtle has collided with the walls is outside of the scope of this tutorial. At first this looks more complicated than it is. We have a ''flet'' to define a local function ''out-of-bounds'' to check if a poses position is out of bounds of the world. Normally you would react to a collision or something like that, but checking if the turtle has collided with the walls is outside of the scope of this tutorial.
-We use this function to build a fluent network which is recalculated everytime ''*turtle-pose*'' changes. It's value will be T, as long as ''*turtle-pose*'' is outside the bounds. We pass this fluent into a ''whenever'' macro. As the name suggests this macro executes it's body whenever the value of the passed fluent is non-NIL. This happens in a loop, so we don't have to worry about it returning after signaling one error. In the body we use ''error'' to signal our defined condition.+We use this function to build a fluent network which is recalculated every time ''*turtle-pose*'' changes. It's value will be T, as long as ''*turtle-pose*'' is outside the bounds. We pass this fluent into a ''whenever'' macro. As the name suggests this macro executes it's body whenever the value of the passed fluent is non-NIL. This happens in a loop, so we don't have to worry about it returning after signaling one error. In the body we use ''error'' to signal our defined condition.
 Because ''whenever'' blocks it's thread until it returns, we have to perform our motion in a parallel thread. For this we use ''pursue'' instead of ''par'' because we want the parallel form to return after the plan is executed. ''par'' would never return, because not all of it's children forms return. ''pursue'' returns as soon as ''perform'' returns. Because ''whenever'' blocks it's thread until it returns, we have to perform our motion in a parallel thread. For this we use ''pursue'' instead of ''par'' because we want the parallel form to return after the plan is executed. ''par'' would never return, because not all of it's children forms return. ''pursue'' returns as soon as ''perform'' returns.
  
Line 127: Line 128:
 TUT> (top-level TUT> (top-level
     (with-process-modules-running (turtlesim-navigation turtlesim-pen-control)     (with-process-modules-running (turtlesim-navigation turtlesim-pen-control)
-      (move-without-pen '(4 8 0))+      (navigate-without-pen '(4 8 0))
       (exe:perform (an action (type drawing) (shape house)))))       (exe:perform (an action (type drawing) (shape house)))))
 [(TURTLE-PROCESS-MODULES) INFO] 1503583551.243: TurtleSim pen control invoked with motion designator `#<MOTION-DESIGNATOR ((TYPE [(TURTLE-PROCESS-MODULES) INFO] 1503583551.243: TurtleSim pen control invoked with motion designator `#<MOTION-DESIGNATOR ((TYPE
Line 149: Line 150:
 ==== Recovering from the failure ==== ==== Recovering from the failure ====
  
-Now that we can run into an error, we better handle it. Again, we have to expand our ''move'' plan and also define a function to implement some form of recovery strategy.+Now that we can run into an error, we better handle it. Again, we have to expand our ''navigate'' plan and also define a function to implement some form of recovery strategy.
  
 The strategy we are going to implement is as follows: The strategy we are going to implement is as follows:
Line 190: Line 191:
 (defparameter *max-bound* 10.5) (defparameter *max-bound* 10.5)
  
-(defun move (?v)+(defun navigate (?v)
   (flet ((out-of-bounds (pose)   (flet ((out-of-bounds (pose)
            (with-fields (x y)            (with-fields (x y)
Line 221: Line 222:
 </code> </code>
  
-Again, we expanded the ''move'' plan. And we added a helper plan to for recovering from being out of bounds.+Again, we expanded the ''navigate'' plan. And we added a helper plan to for recovering from being out of bounds.
 ''recover-from-oob'' rotates to the center, drives forward and when there's a goal, it rotates towards that. This is just to get inside the bounds again and to place the turtle in a position to be able to move again. ''recover-from-oob'' rotates to the center, drives forward and when there's a goal, it rotates towards that. This is just to get inside the bounds again and to place the turtle in a position to be able to move again.
  
Line 251: Line 252:
       (value *turtle-pose*)       (value *turtle-pose*)
     (exe:perform (an action (type drawing) (shape rectangle) (width 5) (height 4.5)))     (exe:perform (an action (type drawing) (shape rectangle) (width 5) (height 4.5)))
-    (move-without-pen (list (+ x 3) y 0))+    (navigate-without-pen (list (+ x 3) y 0))
     (exe:perform (an action (type drawing) (shape rectangle) (width 1) (height 2.5)))     (exe:perform (an action (type drawing) (shape rectangle) (width 1) (height 2.5)))
-    (move-without-pen (list (+ x 0.5) (+ y 2) 0))+    (navigate-without-pen (list (+ x 0.5) (+ y 2) 0))
     (exe:perform (an action (type drawing) (shape rectangle) (width 1) (height 1)))     (exe:perform (an action (type drawing) (shape rectangle) (width 1) (height 1)))
-    (move-without-pen (list x (+ y 4.5) 0))+    (navigate-without-pen (list x (+ y 4.5) 0))
     (exe:perform (an action (type drawing) (shape triangle) (base-width 5) (height 4)))))     (exe:perform (an action (type drawing) (shape triangle) (base-width 5) (height 4)))))
  
Line 261: Line 262:
   (mapcar   (mapcar
    (lambda (?v)    (lambda (?v)
-     (exe:perform (an action (type moving) (target ?v))))+     (exe:perform (an action (type navigating) (target ?v))))
    vertices))    vertices))
  
-(defun move-without-pen (?target)+(defun navigate-without-pen (?target)
   (exe:perform (a motion (type setting-pen) (off 1)))   (exe:perform (a motion (type setting-pen) (off 1)))
-  (exe:perform (an action (type moving) (target ?target)))+  (exe:perform (an action (type navigating) (target ?target)))
   (exe:perform (a motion (type setting-pen) (off 0))))   (exe:perform (a motion (type setting-pen) (off 0))))
  
Line 272: Line 273:
 (defparameter *max-bound* 10.5) (defparameter *max-bound* 10.5)
  
-(defun move (?v)+(defun navigate (?v)
   (flet ((out-of-bounds (pose)   (flet ((out-of-bounds (pose)
            (with-fields (x y)            (with-fields (x y)
Line 310: Line 311:
 TUT> (top-level TUT> (top-level
     (with-process-modules-running (turtlesim-navigation turtlesim-pen-control)     (with-process-modules-running (turtlesim-navigation turtlesim-pen-control)
-      (move-without-pen '(4 8 0))+      (navigate-without-pen '(4 8 0))
       (exe:perform (an action (type drawing) (shape house)))))       (exe:perform (an action (type drawing) (shape house)))))
 [(TURTLE-PROCESS-MODULES) INFO] 1503587291.932: TurtleSim pen control invoked with motion designator `#<MOTION-DESIGNATOR ((TYPE [(TURTLE-PROCESS-MODULES) INFO] 1503587291.932: TurtleSim pen control invoked with motion designator `#<MOTION-DESIGNATOR ((TYPE
Line 393: Line 394:
 </code> </code>
  
-The ''with-failure-handling'' is enclosed in the ''with-retry-counters'', which binds ''some-error-counter'' with a value of ''3''. Inside the handling case the recovery is wrapped by ''do-retry'' which decreases the ''some-error-counter'' each time a ''some-error-condition'' is handled. So if ''do-some-failure-prone-stuff'' can fail up to three times, but after a fourth fail the do-retry won't execute it's body and the ''some-error-condition'' won't be handled. +The ''with-failure-handling'' is enclosed in the ''with-retry-counters'', which binds ''some-error-counter'' with a value of ''3''. Inside the handling case the recovery is wrapped by ''do-retry'' which decreases the ''some-error-counter'' each time a ''some-error-condition'' is handled. So ''do-some-failure-prone-stuff'' can fail up to three times, but after a fourth fail the do-retry won't execute it's body and the ''some-error-condition'' won't be handled. 
  
 ---- ----