This is an old revision of the document!


Events in CRAM

This is a short tutorial to showcase how to trigger and handle custom-defined events. 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 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.

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.

So, first, load the plan knowledge system and switch to its corresponding Lisp package:

CL-USER> (asdf:load-system :cram-plan-knowledge) ; or ,r-l-s RET cram_plan_knowledge RET RET
CL-USER> (in-package :plan-knowledge)

Next, we define a custom event class that inherits from cram-plan-knowledge:event and has one data slot:

PLAN-KNOWLEDGE> (defclass cat-appeared-event (event)
                  ((color-of-cat
                    :initarg :cat-color :reader cat-color
                    :initform (error
                               'simple-error
                               :format-control "CAT-APPEARED-EVENT requires CAT-COLOR"))))
#<STANDARD-CLASS CAT-APPEARED-EVENT>
 
PLAN-KNOWLEDGE> (describe 'cat-appeared-event)
CRAM-PLAN-KNOWLEDGE::CAT-APPEARED-EVENT
  [symbol]
CAT-APPEARED-EVENT names the standard-class #<STANDARD-CLASS
                                              CAT-APPEARED-EVENT>:
  Direct superclasses: EVENT
  No subclasses.
  Not yet finalized.
  Direct slots:
    COLOR-OF-CAT
      Initargs: :CAT-COLOR
      Initform: (ERROR 'SIMPLE-ERROR :FORMAT-CONTROL
                       "CAT-APPEARED-EVENT requires CAT-COLOR")
      Readers: CAT-COLOR

Now that we have our custom event type we define an event handler for it:

PLAN-KNOWLEDGE> (defmethod on-event ((event cat-appeared-event))
                  (format t "OMG! I just saw a ~a cat!~%" (cat-color event)))

To trigger the event we simply call the cram-plan-knowledge:on-event function:

PLAN-KNOWLEDGE> (on-event (make-instance 'cat-appeared-event :cat-color "black"))
OMG! I just saw a black cat!

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:

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)))