2017-08-30 24 views
2

我想订阅一个信号,但我不明白它是如何完成的。 我已阅读http://doc.aldebaran.com/2-4/dev/libqi/api/python/signal.html,但仍未完全理解它。这里就是我想等待这个信号ALBehaviorManager.behaviorStopped('some_behavior')比调用一些回调代码:如何订阅信号

service = session.service("ALBehaviorManager") 

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

signal.connect(my_callback) 

但收到以下错误信息:

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()) 

当我运行它时,它不会等待信号,它只是调用my_callback

EDITED二号

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) 

根据您的回应(@JLS)当我运行这个python脚本就什么都不做。当前在机器人上,此"test_video_player-fdb9c9/behavior_1"正在运行。我认为python脚本不会立即完成,但它会等待来自类型“behaviorStopped”的信号被接收,并且在收到它时检查if behavior_id == "test_video_player-fdb9c9/behavior_1"并根据条件做它应该做的事情。

EDITED三

让我们有这样的情况:我有一个名为“听众”一个行为,唯一的目的就是当其他行为停止记录停止行为的名称的任何时间。一种做法是制作一个事件,将信息发送给这个“听众”。好。一切正常,但当内建行为停止时如何做,如'dialog_runner_dev'。我想如果任何时候行为停止,它会发送一个可以被这个ALBehaviorManager::behaviorStopped(std::string behaviorName)捕获的信号。

我的想法是让信号监听器一直工作。该信号监听器在行为停止时作出反应,然后继续监听其他行为。

+1

您的信号是否安装在行为'my_behavior'中?如果是的话,那么它可能是有道理的:你的程序在信号(无阻塞)之后没有任何事情要做,所以请在你接收回调之前(但你不应该因为你终止了...)。尝试添加一段时间1或一个time.wait之后的信号方法,试图看到变化...祝你好运... –

+0

@Alexandre Mazel这是问题,行为是从基本频道 - 'run_dialog_dev'。它负责运行所有的对话框,并根据机器人是否正在与人交谈来开启和关闭。所以我试图找到一种方法来知道它何时停止。也许和什么时候开始。 –

+0

您还可以使用ALBehaviorManager知道行为何时启动和停止:您可以询问正在运行的行为列表,并且每次安装/启动/启动行为时都会注册一些事件跟踪。 cf API:http://doc.aldebaran.com/2-1/naoqi/core/albehaviormanager-api.html –

回答

2

使用qi.Signal()创建信号。我想在这里要订阅到现有的信号,它就会叫你连接到它的回调函数:

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

与回调函数某处定义:

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

,并在结束:

behavior_stopped_signal.disconnect(behavior_stopped_connection) 

附录:

如果您需要阻止并等待信号发生,一个技巧就是使用可以等待的线程安全变量,如从回调中分配的承诺。 A qi.Promise只能设置一次,所以如果您需要多次执行此操作,请改为使用Queue

1:某处定义变量,他们会为你主,你的回调访问:

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

2:您希望脚本块,使用

answer = fAnswer.value() 

3:回调函数,设置值:

pAnswer.setValue(ans) 
+0

请参考EDITED No.2 –

+0

好的,我也添加了答案!订阅仅将回调连接到信号,而不是等待该信号被提出。如果您想等待,您可以使用期货或其他线程安全系统,例如队列。期货只能设置一次。 – JLS