# SoftBank Robotics documentation What's new in NAOqi 2.8?

# Reacting to a vision event: face detected

<< return to C++ examples

This section explains how to implement a module reacted to a complex event and how to retrieve the information stored in this event.

## Principle

This example follows the same principle as here Reacting to an event: bumper, but is based on an event generated by ALVideoDevice: FaceDetetected.

This time, the data put into the memory corresponding to the “FaceDetected” key is more complex than aboolean: it is an ALValue containing information about the detected face(s).

To retrieve this information, use a proxy to ALMemory, and retrieve the data stored in the corresponding key.

## Example: OnFaceDetection module

This example follows the same principle as here Reacting to an event: bumper, but is based on an event generated by ALVideoDevice: FaceDetetected. This time, the data put into the memory corresponding to the “FaceDetected” key is more complex than a boolean: it is an ALValue containing information about the detected face(s).

This example will make NAO say the number of faces it detects.

The whole example is available here: `onfacedetection.zip` Header: +++++++

`onfacedetection.h`

    /**
     *
     * This file was generated by Aldebaran Robotics ModuleGenerator
     */

    #ifndef ONFACEDETECTION_ONFACEDETECTION_H
    #define ONFACEDETECTION_ONFACEDETECTION_H

    #include <boost/shared_ptr.hpp>
    #include <alcommon/almodule.h>
    #include <string>

    #include <alproxies/almemoryproxy.h>
    #include <alproxies/altexttospeechproxy.h>

    #include <althread/almutex.h>

    namespace AL
    {
      class ALBroker;
    }

    class OnFaceDetection : public AL::ALModule
    {
      public:

        OnFaceDetection(boost::shared_ptr<AL::ALBroker> broker, const std::string& name);

        virtual ~OnFaceDetection();

        virtual void init();

        /**
        * Method called each time a face is detected.
        * Makes NAO say the number of detected faces.
        */
        void callback();

      private:
        /** Memory proxy for event subscription and data access. */
        AL::ALMemoryProxy fMemoryProxy;
        /** TTS proxy to make NAO talk. */
        AL::ALTextToSpeechProxy fTtsProxy;

        /** ALValue containing the information on detected faces. */
        AL::ALValue fFaces;
        /** Current count of detected faces. */
        unsigned int fFacesCount;
        /** Mutex to make the callback function thread-safe. */
        boost::shared_ptr<AL::ALMutex> fCallbackMutex;

    };

    #endif  // ONFACEDETECTION_ONFACEDETECTION_H

### Source file:

`onfacedetection.cpp`

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

    #include "onfacedetection.h"

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

    #include <qi/log.hpp>

    OnFaceDetection::OnFaceDetection(
      boost::shared_ptr<AL::ALBroker> broker,
      const std::string& name):
        AL::ALModule(broker, name),
        fMemoryProxy(getParentBroker()),
        fFaces(AL::ALValue()),
        fFacesCount(0),
        fCallbackMutex(AL::ALMutex::createALMutex())
    {
      setModuleDescription("This is an autogenerated module, this descriptio needs to be updated.");

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

    }

    OnFaceDetection::~OnFaceDetection() {}

    void OnFaceDetection::init() {
      try {
        /** See if there is any face already detected at initialization. */
        fFaces = fMemoryProxy.getData("FaceDetected");
        if (fFaces.getSize() < 2) {
          qiLogInfo("module.example") << "No face detected" << std::endl;
          fTtsProxy.say("No face detected");
        }
        /** Subscribe to the event FaceDetected, with appropriate callback function. */
        fMemoryProxy.subscribeToEvent("FaceDetected", "OnFaceDetection", "callback");
      }
      catch (const AL::ALError& e) {
        qiLogError("module.name") << e.what() << std::endl;
      }
    }

    void OnFaceDetection::callback() {
      /** Use a mutex to make it all thread safe. */
      AL::ALCriticalSection section(fCallbackMutex);
      try {
        /** Retrieve the data raised by the event. */
        fFaces = fMemoryProxy.getData("FaceDetected");
        /** Check that there are faces effectively detected. */
        if (fFaces.getSize() < 2 ) {
          if (fFacesCount != 0) {
            qiLogInfo("module.example") << "No face detected" << std::endl;
            fTtsProxy.say("No face detected.");
            fFacesCount = 0;
          }
          return;
        }
        /** Check the number of faces from the FaceInfo field, and check that it has
        * changed from the last event.*/
        if (fFaces[1].getSize() - 1 != fFacesCount) {
          qiLogInfo("module.name") << fFaces[1].getSize() - 1 << " face(s) detected." << std::endl;
          char buffer[50];
          sprintf(buffer, "%d faces detected.", fFaces[1].getSize() - 1);
          fTtsProxy.say(std::string(buffer));
          /** Update the current number of detected faces. */
          fFacesCount = fFaces[1].getSize() - 1;
        }
      }
      catch (const AL::ALError& e) {
        qiLogError("module.name") << e.what() << 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 "onfacedetection.h"

    #ifdef ONFACEDETECTION_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<OnFaceDetection>( pBroker, "OnFaceDetection" );

        return 0;
      }

      ALCALL int _closeModule()
      {
        return 0;
      }
    }

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

### CMakeLists.txt:

The CMakeLists.txt file is:

`CMakeLists.txt`

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

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

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

    if(ONFACEDETECTION_IS_REMOTE)
      add_definitions(" -DONFACEDETECTION_IS_REMOTE ")
      qi_create_bin(onfacedetection ${_srcs})
    else()
      qi_create_lib(onfacedetection SHARED ${_srcs} SUBFOLDER naoqi)
    endif()

    qi_use_lib(onfacedetection ALCOMMON ALPROXIES ALTHREAD)

Glossary Site map Index Support Contact Legal Notices