Creating events

<< return to C++ examples

This section explains how to create events. Event creation works only for local modules.

Event creation principle

Some events already exist in Aldebaran modules. For example, an event is raised each time a face is detected (see Reacting to a vision event: face detected). You might want to create your own events, to be able to use callback methods.

Event creation and raising goes through ALMemory. Once a module has declared an event, all modules which subscribe to that event will be notified when the value of the event changes.

To declare an event, use a proxy to ALMemory:

AL::ALMemoryProxy memProxy = AL::ALMemoryProxy(getBroker())
memProxy.declareEvent("EventName")

Every time you raise the event, use the following line:

memProxy.raiseEvent("EventName", eventValue)

The event value can be any basic type.

Note

This feature is only possible for a local module, since the modules are looking directly into the memory of the robot.

Example: Events module

This section presents an example module. It is generating an event called “ExampleEvent”, and subscribing to it to display a message everytime the event is generated.

The whole example is available here: events.zip

Source file:

events.cpp

/**
 *
 * Version : $Id$
 * This file was generated by Aldebaran Robotics ModuleGenerator
 */

#include "events.h"

#include <alvalue/alvalue.h>
#include <alcommon/alproxy.h>
#include <alcommon/albroker.h>

#include <qi/log.hpp>


Events::Events(
  boost::shared_ptr<AL::ALBroker> broker,
  const std::string& name):
      AL::ALModule(broker, name),
      fMemoryProxy(getParentBroker())
{
  setModuleDescription("");


  functionName("callback", getName(), "");
  BIND_METHOD(Events::callback);

}

Events::~Events() {
  fMemoryProxy.unsubscribeToEvent("ExampleEvent", "Events");
  fMemoryProxy.unsubscribeToMicroEvent("ExampleMicroEvent", "Events");
}

void Events::init() {
  try {
    //Allow ALMemory to start the Events module when someone subscribe to ExampleEvent
    //This module should inherit from ALExtractor
    //It's not necessary to call this function when you dont want the autostart feature.
    //fMemoryProxy.declareEvent("ExampleEvent", "Events");

    fMemoryProxy.subscribeToEvent("ExampleEvent", "Events", "userDataToIdentifyEvent", "callback");
    fMemoryProxy.subscribeToMicroEvent("ExampleMicroEvent", "Events", "AnotherUserDataToIdentifyEvent", "callback");

    //generate a simple event for the test
    generateEvent(42.0);
    generateMicroEvent(42.0);
  }
  catch (const AL::ALError& e) {
    qiLogError("module.example") << e.what() << std::endl;
  }

}

void Events::generateEvent(const float& value) {
  /** Raise an event with its value (here a float, but could be something else.*/
  fMemoryProxy.raiseEvent("ExampleEvent", value);
}

void Events::generateMicroEvent(const float& value) {
  /** Raise an event with its value (here a float, but could be something else.*/
  fMemoryProxy.raiseMicroEvent("ExampleMicroEvent", value);
}

void Events::callback(const std::string &key, const AL::ALValue &value, const AL::ALValue &msg) {
  qiLogInfo("module.example") << "Callback:" << key << std::endl;
  qiLogInfo("module.example") << "Value   :" << value << std::endl;
  qiLogInfo("module.example") << "Msg     :" << msg << std::endl;
}

Main:

main.cpp

/**
 * @author
 *
 * \section Description
 * This file was generated by Aldebaran Robotics ModuleGenerator
 */

#include <signal.h>
#include <boost/shared_ptr.hpp>
#include <alcommon/albroker.h>
#include <alcommon/almodule.h>
#include <alcommon/albrokermanager.h>
#include <alcommon/altoolsmain.h>

#include "events.h"


#ifdef EVENTS_IS_REMOTE
# define ALCALL
#else
# ifdef _WIN32
#  define ALCALL __declspec(dllexport)
# else
#  define ALCALL
# endif
#endif

extern "C"
{
  ALCALL int _createModule(boost::shared_ptr<AL::ALBroker> pBroker)
  {
    // init broker with the main broker instance
    // from the parent executable
    AL::ALBrokerManager::setInstance(pBroker->fBrokerManager.lock());
    AL::ALBrokerManager::getInstance()->addBroker(pBroker);
      AL::ALModule::createModule<Events>( pBroker, "Events" );

    return 0;
  }

  ALCALL int _closeModule()
  {
    return 0;
  }
}

#ifdef EVENTS_IS_REMOTE
  int main(int argc, char *argv[])
  {
    // pointer to createModule
    TMainType sig;
    sig = &_createModule;
    // call main
    ALTools::mainFunction("events", argc, argv, sig);
  }
#endif

CMakeLists.txt:

CMakeLists.txt

cmake_minimum_required(VERSION 2.8)
project(events)
find_package(qibuild)

option(EVENTS_IS_REMOTE
  "module is compiled as a remote module (ON or OFF)"
  ON)

set(_srcs
  main.cpp
  events.h
  events.cpp
)


if(EVENTS_IS_REMOTE)
  add_definitions(" -DEVENTS_IS_REMOTE")
  qi_create_bin(events ${_srcs})
else()
  qi_create_lib(events SHARED ${_srcs} SUBFOLDER naoqi)
endif()


qi_use_lib(events ALCOMMON ALPROXIES)