How to subscribe to a signal

713 views Asked by At

I am trying to subscribe to a signal but I don't get it how exactly it is done. I have read http://doc.aldebaran.com/2-4/dev/libqi/api/python/signal.html but still don't fully understand it. Here is a code where I am trying to wait for this signal ALBehaviorManager.behaviorStopped('some_behavior') and than invoke some callback:

service = session.service("ALBehaviorManager")

signal = qi.Signal(service.behaviorStopped('by_behavior'))

signal.connect(my_callback)

But get the following error message:

Traceback (most recent call last):
  File "C:/testing.py", line 24, in <module>
    signal = qi.Signal(service.behaviorStopped('by_behavior'))
Boost.Python.ArgumentError: Python argument types in
    Signal.__init__(Signal, NoneType)
did not match C++ signature:
    __init__(struct _object *, class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >)
    __init__(struct _object *)

EDITED

service = session.service("ALBehaviorManager")

signal = qi.Signal()

signal(service.behaviorStopped('my_behavior'), my_callback())

When I run this it does not wait for the signal, it just call my_callback

EDITED No.2

import qi
import sys


def on_behavior_stopped_callback(behavior_id):
    if behavior_id == "test_video_player-fdb9c9/behavior_1":
        print "Yeah"
    else:
        print "Noooooo"

if __name__ == '__main__':
    ip = "11.1.11.111"
    port = 9559

    session = qi.Session()
    try:
        session.connect("tcp://" + ip + ":" + str(port))
    except RuntimeError:
        print ("Can't connect to Naoqi at ip \"" + ip + "\" on port " + str(port))
        sys.exit(1)

    behavior_manager_service = session.service("ALBehaviorManager")

    behavior_stopped_signal = behavior_manager_service.behaviorStopped

    behavior_stopped_connection = behavior_stopped_signal.connect(on_behavior_stopped_callback)

Based on your response (@JLS) when I run this python script it does nothing. Currently on the robot this "test_video_player-fdb9c9/behavior_1" is running. I thought the python script will not finish immediately but it would have waited for a signal from the type "behaviorStopped" to be received and when it has been received to check if behavior_id == "test_video_player-fdb9c9/behavior_1" and than do what it is supposed to do depending on the condition.

EDITED No.3

Lets have this situation: I have one behavior named 'listener' which only purpose is any time when other behavior is stopped to log the name of the stopped behavior. One way to do it is to make an event, that sends info to this 'listener'. Ok. everything works fine, but what to do when an build-in behavior stops such as 'dialog_runner_dev'. I thought if anytime a behavior stops it sends a signal that can be caught by this ALBehaviorManager::behaviorStopped(std::string behaviorName).

My idea is to make a signal listener that works all the time. This signal listener to react when a behavior is stopped and then to continue listening for other behaviors.

1

There are 1 answers

2
JLS On

Using qi.Signal() creates a signal. I guess here you want to subscribe to an existing signal, it will then call a callback function that you connect to it:

behavior_manager_service = session.service("ALBehaviorManager")
behavior_stopped_signal = behavior_manager_service.behaviorStopped
behavior_stopped_connection = behavior_stopped_signal.connect(on_behavior_stopped_callback)

with the callback function defined somewhere:

def on_behavior_stopped_callback(behavior_id):
    if behavior_id == "some_app_uuid/some_behavior":
        do_something()

and at the end:

behavior_stopped_signal.disconnect(behavior_stopped_connection)

ADDENDUM:

if you need to block and wait for the signal to happen, a trick is to use a thread-safe variable that your can wait for, like a promise, assigned from the callback. A qi.Promise can only be set once, so if you need it to happen several times, use a Queue instead.

1: define the variables somewhere where they will be accessible for you main and your callback:

pAnswer = qi.Promise()
fAnswer = pAnswer.future()

2: where you want the script to block, use

answer = fAnswer.value()

3: in the callback function, set the value:

pAnswer.setValue(ans)