0

I installed the NAOqi C++ SDK on my MAC and I tried out some examples from the SDK. HelloWorld-Example worked fine but with the OnFaceDetection-Example I'll get an Error/Warning with qi.eventloop after the NAO detect my face.

Narongsones-MacBook-Pro:bin Narongsone$ ./onfacedetection --pip 192.168.1.138
[I] 1295 core.common.toolsmain: ..::: starting onfacedetection :::..

[I] 1295 core.common.toolsmain: Connecting to 192.168.1.138:9559...

[I] 1295 qimessaging.session: Session listener created on tcp://0.0.0.0:0
[I] 1295 qimessaging.transportserver: TransportServer will listen on:    tcp://192.168.1.136:64881
[I] 1295 qimessaging.transportserver: TransportServer will listen on: tcp://127.0.0.1:64881
[I] 1295 core.common.toolsmain: Connection with 192.168.1.138:9559 established

[I] 1295 module.example: No face detected

[I] 1295 core.common.toolsmain: onfacedetection is ready... Press CTRL^C to quit

[I] 3843 module.name: 1 face(s) detected.

[I] 4355 qi.eventloop: eventloop: Spawning more threads (5)

[I] 4355 qi.eventloop: eventloop: Spawning more threads (6)

[I] 4355 qi.eventloop: eventloop: Spawning more threads (7)

[I] 4355 qi.eventloop: eventloop: Spawning more threads (8)

[I] 4355 qi.eventloop: eventloop: Spawning more threads (9)

[I] 4355 qi.eventloop: eventloop: Spawning more threads (10)

Please, help me if you have any idea about what the problem is. Thank you!

My callback function:

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;
  }
}
noudels
  • 11
  • 3
  • usually this kind of error arrive when you're creating new threads and never exiting them. So have a look at what you do in the callback and check you're exiting it after a while... good luck – Alexandre Mazel Oct 18 '18 at 12:33
  • @AlexandreMazel I edited my post and added my callback function. I don't know yet, how I can fix it. Can you give me some tips? – noudels Oct 19 '18 at 02:05
  • I think the error is the facedetection is running at 10fps and for any callback you call an action of speaking taking like 2 seconds. So you're stacking a huge thread of waiting "tts.say" calls. My advice is to speak only when stats change and prevent speaking too much. Like if time.time() - self.lastTimeSpoken > 5.0 then self.lastTimeSpoken = time.time() and speak. – Alexandre Mazel Oct 23 '18 at 15:13
  • @AlexandreMazel that's the issue. I comment the "tts.say" calls out, and the error doesn't appear anymore. So where should I put the code if time.time()... in? – noudels Oct 25 '18 at 01:09
  • change the tts.say by the code above – Alexandre Mazel Oct 26 '18 at 11:56

2 Answers2

0

As mentionned by @AlexandreMazel, this error is simply explaining you that the system is creating too many new threads as the function is called very often (up to 10x/s) but takes a few seconds to execute as there is a speech in it.

You might want to have a flag or a non-blocking mutex to prevent the function to be run several times.

JLS
  • 968
  • 5
  • 12
  • Thanks for the answer. But what is a flag? And how can I add a non-blocking mutex in my code? Any examples for it? – noudels Oct 25 '18 at 01:11
  • a flag is just a global boolean "is_running" that you set to True at the beginning of your method and set to False at the end of your method. That way you can test and not run things twice at the same time : "if is_running: return" – JLS Oct 27 '18 at 19:02
0

About changing the tts.say, here's an example:

change the tts.say by a method handling all text commands

tts.say(txt)

becomes:

if time.time() - self.lastSaidTime > 5.0 or txt != self.lastSaidText:
    self.lastSaidTime = time.time()
    self.lastSaidText = txt
    tts.say(txt)
Alexandre Mazel
  • 2,462
  • 20
  • 26