一 Buzz控制器
Buzz控制器
Buzz继承实现了Argos中的控制器接口(如第一个案例中的buzz_controller_footbot控制器)。当启动Argos模拟器时,会自动执行Buzz控制器的初始化方法,该方法主要获取传感器数据,读取bytecode字节码文件和debug调试文件,并将bytecode字节码文件交给BVM模块解析处理。Buzz控制器的ControlStep方法主要用于按步执行(执行频率可以在.argos文件中配置),分为四个过程:
1)processInMsg: 从sensors中读取传感器数据,更新邻居节点信息,处理接收到的消息;
2)updateSensors: 更新传感器数据,如位置、电量;
3)function_call: 调用用户定义的step方法;
4)processOutMsgs: 通过actuator发送outmsg队列中的消息,消息格式: robotid | 消息体长度 | 消息内容
二 BVM模块
Buzz虚拟机主要用于在机器人平台上执行通过Buzz语言生成的bytecode字节码文件。BVM模块会解析bytecode字节码文件,存储其中的相关指令和用户定义的方法,以及内部模块的一些方法(如neighbors/swarm/vstig/math/strings/obj等)。BVM还提供了方法调用堆栈、全局变量表、局部变量表、输入输出消息队列等。
如上图,BVM从"Sensor data"读取接收到的消息,放入到inmsgs消息队列,并根据消息类型分发给相应的功能模块(swarm/neighbor/vstig),这些模块会解析并处理消息,处理消息时会用到BVM中的堆栈、解释器等,然后将要发送的消息放入到outmsgs消息队列,通过"Actuator data"发送出去。
三 neighbor模块
邻居节点数据存储:<robotid, [distance, azimuth, elevation]>
数据来源
节点每step都会向邻居节点广播一条消息,消息内容为本节点的robotid,如果有outmsgs队列中有要发送的数据,则合并发送。
邻居节点收到该消息后,检测与消息发送者的distance,并更新上面的数据存储。
方法
1)listen(侦听):BVM模块将用户定义的回调方法注册到vm->listeners字段中,当每step中processInMsgsc处理接收到消息时,如果消息类型为BROADCAST,则从vm->listeners中查询对应的回调方法,并调用执行。
思考:vm->listeners为字典结构<key, func>,是不是不能多个同一话题的侦听?
2)broadcast(广播):消息类型为BROADCAST,消息放入到vm->outmsgs队列中,每step都会将队列中的消息发送出去。
3)ignore(取消):从vm->listeners回调函数列表中删除回调函数。
4)map(坐标变换):函数作为参数,该函数用于对邻居节点的数据进行转换,并返回新的邻居节点数据结构。
5)reduce(缩减):函数作为参数,该函数用于对邻居节点数据进行左折叠/累积/缩小操作,函数最后计算出一个值。
四 swarm模块
数据存储:
vm->swarms字典:<swarmid, 0/1>,存储本节点知道的群列表;
vm->swarmmembers字典:<robotid, [age,swarmed_list]>,存储本节点所有邻居节点所属的群列表
方法
1)create(创建群):本节点BVM将swarmid保存到vm->swarms字典中,数据结构为<swarmid, 0/1>,后者表示本机器人是否属于该群。也可以从已有的群中创建新群:intersection(交集)/union(并集)/difference(差集)。
2)join(加群):本节点BVM将vm->swarms字典中的标志为1,并发送消息<robotid, swarmid>,消息类型SWARM_JOIN。邻居节点收到消息后,将节点与群关系存储到vm->swarmmembers字典中,数据结构为<robotid, [age,swarmed_list]>。另外一种加群方法为select,不同的是:select 是有条件加群,join 是无条件加群。
3)leave(离群):本节点BVM将vm->swarms字典中的标志为0,并发送消息<robotid, swarmid>,消息类型SWARM_LEAVE。邻居节点收到消息后,更新vm->swarmmembers字典中的节点与群关系。另外一种离群方法为unselect,不同的是:unselect 是有条件离群,leave 是无条件离群。
4)in(查询):若判断本节点是否属于某个群,则从本节点vm->swarms字典中的查询标志是否为1;若判断邻居节点是否属于某个群,则从本节点的vm->swarmmembers字典中查询。
5)exec(执行):属于该群的所有节点执行某个方法。
思考:如果一个节点属于多个群,那么在exec执行任务时,如何处理?
BVM对群的自动管理过程(如节点宕机时,如何主动判断节点离群?)
1)BVM每步都会调用一次update方法,该方法会检查vm->swarmmembers字典中的邻居节点的age是否超过限制(默认50),如果超龄,则从字典中删除该节点的记录。
2)BVM每10步发送一次SWARM_LIST消息,消息格式<robotid, swarmid_list>。邻居节点收到该消息后,更新本节点BVM中的vm->swarmmembers字典,并将发送者的age置为0。(age表示从上次更新到当前时间的经历的步数)
五 vstig模块
主要用于整个群内的数据共享。
数据存储 vm->vstigs :<vstigid, <key, [value,timestamp,robotid]>
方法
1)put (写):当节点向共识写新的数据时,本地BVM先更新本地共识数据,然后,将<vstigid,key,value,timestamp,robotid>消息放入vm->outmsgs队列,消息类型为VSTIG_PUT。邻居节点收到该消息后,检查消息的timestamp,如果timestamp比当前存储的key的时间新,则数据有效并转发;如果同样的timestamp但不同的robotid说明出现了冲突,会调用用户设置的onconglict方法(默认使用robotid大的数据有效),解决冲突后会调用用户设置的onconflictlost方法。
2)get(读):当节点从共识读取数据时,如果本地有该key,则BVM会返回该key对应的数据;然后,BVM将<vstigid,key…>消息放入vm->outmsgs队列,消息类型为VSTIG_QUERY。邻居节点收到该消息后,会查询自己的共识数据,如果本地的数据较新,则会向发送者回复较新的数据,消息类型为VSTIG_PUT;如果本地的数据较旧,BVM则会更新该条数据,并广播给所有邻居节点。该机制允许机器人断开重连后自动更新数据。