Differences

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

Link to this comparison view

tutorials:advanced:plans [2015/05/11 19:06] (current)
gkazhoya created
Line 1: Line 1:
 +====== Writing Plans ======
  
 +==== with-policy ====
 +{{ :​doc:​with-policy.png?​nolink&​300|}}
 +
 +Policies can be used to define generic monitoring behavior that should run concurrently besides main functionality code. Such a policy might be monitoring
 +  * the position of an object inside a robot gripper to see whether it is moving out of the gripper (losing the object)
 +  * the position of an object in the real world, in order to keep the robot'​s head pointing towards it
 +  * the collision of a robot joint with objects in the real world
 +  * generic events that must definitely interrupt a certain piece of code, but are too specialized to be implemented directly in the monitored code itself
 +
 +A policy consists of multiple parts:
 +  * A name (to identify it)
 +  * A description string (to make its purpose clear)
 +  * A parameter list (which can be used to specialize a generic policy for a situation at hand, without generating a new policy every time the situation changes slightly)
 +  * Code blocks that need to be evaluated during monitoring
 +
 +=== Usage example ===
 +An example of how to define a policy is shown here. The policy accepts two custom parameters, one defining a maximum number and one a match number. During execution of the main ''​body''​ code (which is really just a loop with an output here), it checks a randomly generated number (ranging from ''​0''​ to ''​max-num''​) against the match number ''​match-num''​. If this is the case (and it will be, eventually),​ it interrupts (and ends) the main ''​body''​ code and executes the '':​recover''​ code, followed by the '':​clean-up''​ code (both just outputting something here).
 +
 +<code lisp>
 +(define-policy my-policy (max-num match-num)
 +  "This is an example policy."​
 +  (:init (format t "​Initializing policy~%"​)
 +         t)
 +  (:check (format t "​Checking if random number from 0
 +                     to ~a equals ~a~%" max-num match-num)
 +          (let ((rnd (random max-num)))
 +            (format t "Got number ~a~%" rnd)
 +            (cond ((eql rnd match-num)
 +                   ​(format t "​Match~%"​)
 +                   t)
 +                  (t (sleep 1)))))
 +  (:recover (format t "​Running recovery mechanisms~%"​))
 +  (:clean-up (format t "​Running clean-up~%"​)))
 +</​code>​
 +
 +The calling code for using the policy uses ''​with-named-policy''​ to refer to the name as specified while defining the policy. The second parameter is a list of parameter values for customizing the policy instance. The rest of the code should be pretty self explanatory.
 +<code lisp>
 +(top-level
 +  (with-named-policy '​my-policy (10 5)
 +    (loop do (format t "Main loop cycle.~%"​)
 +             ​(sleep 2))))
 +</​code>​
 +
 +=== Exception handling ===
 +When policies are used, multiple failures can be signalled. The most meaningful of those are
 +  * ''​policy-not-found'':​ Signalled when a named policy is used that was not defined before.
 +  * ''​policy-init-failed'':​ Signalled when initialization of a policy went wrong (i.e. '':​init''​ returned ''​nil''​).
 +  * ''​policy-check-condition-met'':​ The '':​check''​ condition of the policy returned a non-''​nil''​ value, '':​recover''​ was executed and the ''​body''​ code was interrupted before it could complete execution.
 +
 +If one wants to monitor the triggering of a policy'​s '':​check''​ condition, this can be achieved like this:
 +<code lisp>
 +(top-level
 +  (with-failure-handling
 +      ((policy-check-condition-met (f)
 +         ​(declare (ignore f))is available that the given
 +         ​(do-custom-handling-here)
 +         ​(retry))) ;; Or whatever seems appropriate in your use-case e.g. (return)
 +    (with-named-policy '​my-policy (10 5)
 +      (loop do (format t "Main loop cycle.~%"​)
 +               ​(sleep 2)))))
 +</​code>​
 +
 +=== Using multiple policies at once ===
 +When multiple policies are to be used (either a mix of different policies, or the same policy multiple times, each with different parameters),​ two helpful macros can be used: ''​with-policies''​ and ''​with-named-policies''​. Both of these take lists of policies, together with their respective instantiation parameters, as arguments.
 +
 +When policy instances by the names ''​my-policy-object''​ and ''​my-other-policy-object''​ should be used, the following code snippet reflects this behaviour. The policy ''​my-policy-object''​ takes two ''​int''​s as parameters, while ''​is available that the givenmy-other-policy-object''​ takes a string as an argument.
 +<code lisp>
 +(with-policies
 +    ((my-policy-object (3 1))
 +     ​(my-policy-object (100 4))
 +     ​(my-other-policy-object ("​Test"​)))
 +  (body-code))
 +</​code>​
 +In this example, the resulting code will be equivalent to the following:
 +<code lisp>
 +(with-policy my-policy-object (3 1)
 +  (with-policy my-policy-object (100 4)
 +    (with-policy my-other-policy-object ("​Test"​)
 +      (body-code))))
 +</​code>​
 +
 +The same princple applies to ''​with-named-policies'',​ with the only difference being that it does not take policy instances, but policy name symbols as parameters:
 +<code lisp>
 +(with-named-policies
 +    (('​my-policy (3 1))
 +     ​('​my-policy (100 4))
 +     ​('​my-other-policy ("​Test"​)))
 +  (body-code))
 +</​code>​
 +This results in the same behavior as:
 +<code lisp>
 +(with-named-policy '​my-policy (3 1)
 +  (with-named-policy '​my-policy (100 4)
 +    (with-named-policy '​my-other-policy ("​Test"​)
 +      (body-code))))
 +</​code>​
 +
 +=== Built-in Policies ===
 +== timeout-policy ==
 +When a piece of code only has a limited maximum amount of time for execution (and must be aborted after that duration), the ''​timeout-policy''​ comes in handy.
 +
 +Use it like this:
 +<code lisp>
 +(with-policy cpl:​timeout-policy (5.0) ; Timeout after 5.0 seconds (fractions may be used)
 +  (body-code-goes-here))
 +</​code>​
 +And for catching the check condition when the timeout actually happens:
 +<code lisp>
 +(with-failure-handling
 +    ((policy-check-condition-met (f)
 +      (declare (ignore f))
 +      (handle-error-here-and-maybe-retry)))
 +  (with-policy cpl:​timeout-policy (5.0)
 +    (body-code-goes-here)))
 +</​code>​
 +The ''​timeout-policy''​ stops the given ''​body''​ code after a given amount of time (in seconds) if it hasn't finished by then. This helps to add a ''​timeout''​ functionality to functions that do not inherently support a timeout mechanism (blocking function calls).