Broker —经济人,Proxy—代理,Module—模块,method—方法。
这四个可以说是构成naoqi框架的主要内容,直接进行分析,主要的参考资料就是官方文档。
Broker,
直译为经纪人,主要完成两项任务
1,提供字典服务,能够查找该broker下的Module及Method。
2,提供网络连接,使得模块中方法能够被外部模块调用。
在大多数情况下,你不需要考虑broker,可以视作透明的,将允许你像调用local module(本地模块)一样对 remote module(远程模块)进行调用。
Proxy
作为module的代理存在,在对module访问其内部method的时候,总是通过proxy来进行操作的。
有两种思路来创建一个proxy:
1,直接使用module的名字。
AL::ALProxy proxy = AL::ALProxy(<modulename>);
在这种情况下,必须要求你运行的代码与你将要生成的module在同一个broker中。
2,使用 module 名字,及broker的ip、port。
AL::ALProxy proxy = AL::ALProxy(<modulename>, <ip_adress>, <port_number>);
在这种情况下,module一定是位于你指定ip的broker中。
也就是说,必须保证 明确module所在的位置,如果位于同一个broker中,则不需要指明,如果位于不同的broker中,则需要明确broker的ip-addr,prot-number。
在实际应用中可能会用到
AL::ALProxy proxy = AL::ALProxy(boost::shared_ptr<AL::ALBroker> broker);
这里可以参考文档中C++ API 中的 alcommon -> Proxy的构造函数,需要注意的是里面的modulename参数,往往在进行初始化的时候将ALProxy替换为具体的Proxy,不需要再特别给出该参数值。
同样分析最后一行实际应用用的案例,其实是调用了 ALProxy (boost::shared_ptr< ALBroker > pBroker, const std::string &pModuleName, int pProxyMask=0, int timeout=0) 构造函数,同样省略modulename。
Module
Module可以看做是简单的类库中的类,当类库在autoload.init中加载的时候,会自动实例化module类,(调用构造函数,及init()方法)。
在module类的构造函数(继承自ALModule)中你可以绑定方法。这将会向其broker广告method名字及其方法,这样该这些方法就可以被其他module调用了。
Module 分为两类,local module,remote module:
Local module,将会被编译成一个库文件,只能在robot内部调用,执行效率较高。是指相对于同一个broker中的module而言的。由于都在一个broker中,module之间的调用不必通过网络,所以更加迅速,
Remote module,将会被编译成一个可执行文件,并且可以在机器人外部运行。Rmote module 可以方便的使用和调试,但是运行速度慢效率低。是相对于位于不同的broker中的module而言的。Remote module之间的通信必须是通过网络进行的,一个remote module 需要借由broker来与另一broker中的module进行通信。网络通信是通过SOAP协议进行的。
两个不同broker中的module(换句话说两者相对是 remote module)此时存在两种通讯方式,broker-broker,proxy-broker。
Broker-broker:双向通道,两侧所有的module均可互联。建立这种连接,在启动module的时候要指定main broker的ip、port。因为你在建立broker连接的时候就已经指定ip、port,所以在之后进行module调用的时候不需要再指明,直接利用名字进行proxy的创建。
Proxy-broker:单向通道,proxy所代理的module可以访问另一侧所有的module,反之则不可以。你需要在你的module内部创建一个proxy,同时指定想要连接的broker的ip、port。
案例分析:
现有NAO(IP:192.168.169.4),PC(IP:192.168.168.2)实现多组方式通讯。
方案一:不制作module,直接C++编程实现对NAO内部API的调用,具体是实现获取nao当前视觉内容,并显示。
程序执行界面:
在启动时将直接指定nao IP地址,也就是naoqi broker所在的IP地址。这里将显示nao的视觉信息:
调用关键代码:
/** Create a proxy to ALVideoDevice on the robot.*/ ALVideoDeviceProxy camProxy(robotIp, 9559);
这里便是直接指定远程broker的IP,Port,然后生成代理,而后可调用相应module,不再多说。
方案二:制作远程module,通过调用远程module中的方法实现特定的功能,这里我实现了一个VisionModule,并实现了与机器人视觉相关的部分内容。
启动remote module界面如下:
这里可以看出VisionModule监听的端口为:192.168.169.2:54012,可以看出是在PC端运行的。同时建立了与NAO(192.168.169.4:9559)的连接。
利用test函数对该remote module进行测试,尝试调用几个参数设定函数,测试界面如下:
client端:
module端:
这里test程序中生成的proxy同样指定为nao的IP地址,代码如下:
boost::shared_ptr<AL::ALProxy> testProxy = boost::shared_ptr<AL::ALProxy>(new AL::ALProxy("VisionModule", robotIP, port));
查看文档我找到这样一句话,
Brokers can be connected to each other to form a tree where each broker has parent broker until the base of the tree.
意思就是多个broker可以互联并形成树结构,而每一个新生成的broker都有一个父broker直至树的根节点。我便作此假设,remote module所生成的broker其实是naoqi broker的一个 子broker。
在程序中又可以应用这样的语句来创建proxy:ALVideoDeviceProxy camProxy(getParentBroker()); 从另一个方面印证了上述观点。
作为父broker理应能够得到子broker中的全部信息(这句话有待推敲,并没有找到确凿的证据说明这一点,只是通过naoqi framework的 自省机制(introspection)推断得来)。
这样我便得到了这样的结论,naoqi broker 作为 test application 与 vision module (remote module) 的中介存在,在test看来,vision module 也不过是 naoqi broker 中的一个 module,并不需要知道它是remote module 还是 local module。(中间还是有些内容是模糊的)
方案三:生成local module,并上传至nao中,等待调用,这里的编译及上传部分不再细述,看一下最终的效果:
这里是上传并加载成功后,在nao web页面显示的内容。这样的module就可以像naoqi自带的module一样进行调用了,尝试在 choregraphe中进行简单调用,如下:
就像普通local module一样进行调用,不需要多做解释了。
以上就是我对naoqi framework的一点总结,更多的是在实际使用中的效果展示,而原理性的内容,主要是参考官方文档,分析的并不是透彻和清楚,^_^