Differences

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

Link to this comparison view

Next revision
Previous revision
Next revisionBoth sides next revision
tutorials:advanced:events [2015/05/11 17:31] – created gkazhoyatutorials:advanced:events [2015/05/11 19:23] gkazhoya
Line 4: Line 4:
 CRAM has an event protocol that makes the above-mentioned very simple. CRAM has an event protocol that makes the above-mentioned very simple.
  
-The event callback mechanism is based on the notion of hooks of the [[doc/package/cram_utilities|cram_utitlities]] package from the CRAM core. +Code-wise, the event callback mechanism is based on the notion of hooks of the [[doc/package/cram_utilities|cram_utitlities]] package from the CRAM core. 
-The protocol itself is defined in the ``cram_plan_knowledge`` package. That is also the package where new types of events and their handlers should be defined. That's why we will work in that package.+The protocol itself is defined in the ''cram_plan_knowledge'' ROS package. That is also the package where new types of events and their handlers should be defined.
  
-First, load the plan knowledge system and switch to the corresponding Lisp package:+In the nutshell, the protocol is pretty trivial: there is a generic function called ''cram-plan-knowledge:on-event'' which is supposed to be overloaded with new handlers and called to emit new events. 
 + 
 +Solet's first load the plan knowledge system and switch to its corresponding Lisp package:
  
 <code lisp> <code lisp>
 CL-USER> (asdf:load-system :cram-plan-knowledge) ; or ,r-l-s RET cram_plan_knowledge RET RET CL-USER> (asdf:load-system :cram-plan-knowledge) ; or ,r-l-s RET cram_plan_knowledge RET RET
-CL-USER> (in-package :plan-knowledge)+CL-USER> (in-package :cram-plan-knowledge)
 </code> </code>
  
Line 48: Line 50:
 </code> </code>
  
-To trigger the event we simply call the ''cram-plan-knowledge:on-event'' function:+To trigger the event we simply call the ''cram-plan-knowledge:on-event'' method:
  
 <code lisp> <code lisp>
 PLAN-KNOWLEDGE> (on-event (make-instance 'cat-appeared-event :cat-color "black")) PLAN-KNOWLEDGE> (on-event (make-instance 'cat-appeared-event :cat-color "black"))
 OMG! I just saw a black cat! OMG! I just saw a black cat!
 +(NIL)
 </code> </code>
 +
 +Now, imagine that we would like to have multiple handlers for the same event.
 +E.g., in addition to screaming excitedly each time we see a cat, we would also like to count the number of cats seen so far:
 +
 +<code lisp>
 +PLAN-KNOWLEDGE> (let ((saw-cats 0))
 +                  (defmethod on-event cat-counter ((event cat-appeared-event))
 +                    (incf saw-cats)
 +                    (format t "number of cats seen so far: ~a~%" saw-cats)
 +                    saw-cats))
 +#<STANDARD-METHOD ON-EVENT CAT-COUNTER (CAT-APPEARED-EVENT) {100F5D3C43}>
 +
 +PLAN-KNOWLEDGE> (on-event (make-instance 'cat-appeared-event :cat-color "black"))
 +number of cats seen so far: 1
 +OMG! I just saw a black cat!
 +(1 NIL)
 +
 +PLAN-KNOWLEDGE> (on-event (make-instance 'cat-appeared-event :cat-color "black"))
 +number of cats seen so far: 2
 +OMG! I just saw a black cat!
 +(2 NIL)
 +</code>
 +
 +Let's break this down.
 +
 +  * We define a lexical variable ''saw-cats'' which will be our counter (if ''saw-cats'' confuses you read up on [[http://www.gigamonkeys.com/book/variables.html#lexical-variables-and-closures|closures]]).
 +  * Then we overload our ''on-event'' method while specifying ''cram-plan-knowledge::cat-counter'' as a method combination qualifier. The default method combination of generic function ''on-event'' is ''cram-utilities:hooks'' which simply combines the results of all the suitable methods into a list. That is clearly illustrated in the result of the last ''on-event'' call in the code snippet above: ''(2 NIL)'', where ''2'' is the result of the method qualified with ''cat-counter'' and ''NIL'' results from the ''format'' statement of the other method. Combining the results of all the suitable methods means that the qualifier itself (in our case ''cat-counter'') is of no importance. So, as long as we can come up with new qualifiers we can have new handlers for a particular event (if this paragraph is hard to understand look into the definition of ''cram-utilities:define-hook'' and read up more on [[http://www.lispworks.com/documentation/HyperSpec/Body/m_defi_4.htm|method combinations]]).