Both sides previous revisionPrevious revisionNext revision | Previous revisionNext revisionBoth sides next revision |
tutorials:advanced:events [2015/05/11 18:00] – gkazhoya | tutorials:advanced:events [2015/05/11 19:23] – gkazhoya |
---|
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'' ROS package. That is also the package where new types of events and their handlers should be defined. | 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. |
| |
Basically, 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. | 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. |
| |
So, first, load the plan knowledge system and switch to its corresponding Lisp package: | So, let'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> |
| |
</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. | Now, imagine that we would like to have multiple handlers for the same event. |
E.g., in addition to screaming excited each time we see a cat, we would also like to count the number of cats seen so far: | 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> | <code lisp> |
(defmethod on-event cat-counter ((event cat-appeared-event)) | (defmethod on-event cat-counter ((event cat-appeared-event)) |
(incf saw-cats) | (incf saw-cats) |
(format t "number of cats seen so far: ~a~%" 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> | </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]]). |