Использование многопоточности в роботе Nao

Я пытаюсь что-то сделать с API-интерфейсом обнаружения красных шаров Nao. Я хочу сделать все шаг за шагом. Я написал callbackMutex каждый в начале обратных вызовов. Я отписываю событие в обратном вызове в операторе if.

Функции работают, но иногда выдает ошибку «ИНФО: Достигнут предел потока» или ошибку события отмены подписки.

Нао всегда видит красный шар, но создает много нитей (я думаю). Как я могу использовать только один поток?

Пишу на С++.

Я подписываюсь так:

memory.subscribeToEvent("redBallDetected", "moduleName", "fuctionName");

затем, когда Нао видит мяч, вызывается эта функция.

void moduleName::functionName()
{
ALCriticalSection section(callbackMutex);
//create some proxies and declare some variables

try
{
//do movements
}
catch(const ALError& e) {
        qiLogError("module.name") << e.what() << std::endl;
      }
}

Я использую setWalkTargetVelocity для обхода робота и проверки оператора if, если он идет или останавливается. Я ничего не использовал, чтобы запустить или остановить поток.


person user3126199    schedule 29.05.2014    source источник
comment
Можете ли вы показать нам код, который вызывает вашу ошибку?   -  person aglasser    schedule 30.05.2014
comment
Я не знаю, какие строки вызывают эту ошибку, но я добавляю некоторые коды.   -  person user3126199    schedule 31.05.2014


Ответы (2)


Вот хитрости:

  • Вы должны убедиться, что вы никогда не застреваете слишком долго в своем обратном вызове, поэтому вызов метода асинхронного обхода - это хорошо.

  • Метод ходьбы требует времени, его не следует вызывать слишком часто: минимум ~400 мс.

  • при поступлении обратного вызова не ждите завершения предыдущего обратного вызова, просто уходите, так как в следующий раз будет получена более свежая информация. Я имею в виду, что предыдущая информация не представляет интереса при получении новой, так что не застревайте.

person Alexandre Mazel    schedule 02.06.2014
comment
Спасибо за ответ. Как я могу оставить предыдущий обратный вызов. Я просто подписываюсь на это. Когда Нао видит мяч, он автоматически выполняет обратный вызов. Мяч всегда в поле зрения, так что я могу сделать? Есть API-интерфейс менеджера ресурсов, но я не понял, как его использовать. Не хватает примера. - person user3126199; 04.06.2014
comment
Какой метод мне следует использовать, и есть ли какой-либо способ выпуска прокси-сервера Redball после обновления информации? - person user3126199; 07.06.2014
comment
Просто уничтожьте свой объект. - person Alexandre Mazel; 26.09.2014

Вы можете использовать qi::Strand для постановки вызовов в очередь, чтобы не создавать дополнительные потоки. В сочетании с современной подпиской на события ALMemory это выглядит так:

qi::Strand strand; // Store the strand anywhere, but keep it alive.
qi::AnyObject redBallSubscriber; // You must also keep alive this object to keep the subscription
redBallSubscriber = memory.subscriber("redBallDetected");
redBallSubscriber.connect("signal", strand.schedulerFor([]
{
  // The strand guarantees only one thread will enter this function
  // at a time, you don't need to use a mutex here.
  try
  {
    //do movements
  }
  catch(const std::exception& e) {
    qiLogError("module.name") << e.what();
  }
}));

Примечание: если лямбда не работает, попробуйте обернуть ее в boost::function.

person Victor Paléologue    schedule 18.08.2017