Differences

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

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
Last revisionBoth sides next revision
tutorials:advanced:events [2016/04/04 09:07] gkazhoyatutorials:advanced:events [2018/04/04 09:19] – created gkazhoya
Line 1: Line 1:
-====== Events in CRAM ====== +This page migrated [[tutorials:intermediate:events|here]].
- +
-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. +
- +
-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_occasions_events'' ROS package. The actual event types are defined in ''cram_plan_occasions_events''. Event handlers are mostly defined in ''cram_bullet_reasoning_belief_state'' package or you can define your own handlers. +
- +
-In the nutshell, the protocol is pretty trivialthere is a generic function called ''cram-occasions-events:on-event'' which is supposed to be overloaded with new handlers and called to emit new events+
- +
-So, let's first load the plan knowledge system and switch to its corresponding Lisp package: +
- +
-<code lisp> +
-CL-USER> (ros-load:load-system "cram_plan_occasions_events" :cram-plan-occasions-events) +
-;; or ,r-l-s RET cram_plan_occasions_events RET RET +
-CL-USER> (in-package :cram-plan-occasions-events) +
-</code> +
- +
-Next, we define a custom event class that inherits from ''cram-occasions-events:event'' and has one data slot: +
- +
-<code lisp> +
-CPOE> (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> +
- +
-CPOE> (describe 'cat-appeared-event) +
-CRAM-PLAN-OCCASIONS-EVENTS::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 +
-</code> +
- +
-Now that we have our custom event type we define an event handler for it: +
- +
-<code lisp> +
-CPOE> (defmethod on-event ((event cat-appeared-event)) +
-        (format t "OMG! I just saw a ~a cat!~%" (cat-color event))) +
-</code> +
- +
-To trigger the event we simply call the ''cram-occasions-events:on-event'' method: +
- +
-<code lisp> +
-CPOE> (on-event (make-instance 'cat-appeared-event :cat-color "black")) +
-OMG! I just saw a black cat! +
-(NIL) +
-</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> +
-CPOE> (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}> +
- +
-CPOE> (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) +
- +
-CPOE> (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-occasions-events::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 unique qualifiers we can have new handlers for our 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]]). +
- +
- +
-====== Occasions and goals in CRAM ====== +
- +
-Here is a short demo of how to define your own goals. +
-First, we need to load the CRAM plan library into our REPL: +
- +
-<code lisp> +
-CL-USER> (ros-load:load-system "cram_plan_library" :cram-plan-library) +
-;; or ,r-l-s RET cram_plan_library RET RET +
-</code> +
- +
-Next we need to define how we achieve our custom occasion, and what the occasion mean, i.e. when does it hold: +
-<code lisp> +
-CL-USER> (cpl:def-goal (plan-lib:achieve (cat-said ?something)) +
-           (format t "cat said ~a~%" ?something)) +
-(#<FUNCTION (LAMBDA #) {100EF8837B}> NIL) +
-CL-USER> (cpl:top-level (plan-lib:achieve `(cat-said hello))) +
-WARNING: Trying to prove goal (CAT-SAID HELLO) with undefined functor CAT-SAID. +
-cat said HELLO +
-NIL +
- +
-CL-USER> (prolog:def-fact-group cat-facts () +
-           (prolog:<- (cat-said ?what-he-said) +
-             (prolog:not (prolog:equal ?what-he-said meao)) +
-             (prolog:fail)) +
-           (prolog:<- (cat-said meao))) +
-CL-USER> (prolog:prolog `(cat-said meao)) +
-(NIL . #S(CRAM-UTILITIES::LAZY-CONS-ELEM :GENERATOR #<CLOSURE # {1005C02C6B}>)) +
-CL-USER> (prolog:prolog `(cat-said hello)) +
-NIL +
-CL-USER> (cpl:top-level (plan-lib:achieve `(cat-said hello))) +
-cat said HELLO +
-NIL +
-CL-USER> (cpl:top-level (plan-lib:achieve `(cat-said meao))) +
-[(ACHIEVE PLAN-LIB) INFO] 1459760764.841: Occasion `(CAT-SAID MEAO)' already achieved. +
-NIL +
- +
-</code>+