前言
我们常常需要机器人进行整体地协作,即在队伍间交互一些信息。BHuman提供了这一功能。
由于采用UDP协议传播,所以发送的消息所有机器人都可以接收。
正文
representation以及对应的module
representations中的TeamData包含了所有接收的信息,BHumanMessageOutputGenerator包含了所有要发送的信息。可能因为这两个数据流格式差不多,所以统一交给module里的TeamMessageHandler处理.
可以看到TeamMessageHandler有对应的重载的update
void update(TeamData& teamData) override;
void update(BHumanMessageOutputGenerator& outputGenerator) override;
此外,所有要发送的representation都需要继承“BHumanMessageParticle”,
以BallModel为例,定义形如:
STREAMABLE(BallModel, COMMA public BHumanMessageParticle<idBallModel>{
void operator>>(BHumanMessage& m) const override;
void operator<<(const BHumanMessage& m) override;
// Just see here, forget the following
...
}
除了 BallModel,这样的representation还有:
(RobotPose);
(ObstacleModel);
(BehaviorStatus);
(Whistle);
(TeamBehaviorStatus);
(SideConfidence);
(FieldCoverage);
(RobotHealth);
(TeamTalk);
消息格式
传输的消息的主体由以下四部分构成(在…/…/Src/Representations/Communication/BHumanMessage.h中定义)
(BSPLStandardMessage) theBSPLStandardMessage,
(MixedTeamHeader) theMixedTeamHeader,
(BHumanStandardMessage) theBHumanStandardMessage,
(BHumanArbitraryMessage) theBHumanArbitraryMessage,
前三者表示一些基本的信息,比如队伍号、是否摔倒等。它们有固定的格式。最后一个表示任意长度和格式的信息。
感兴趣的可以查查每个具体包含哪些信息。
发送
…/…/Src/Modules/Communication/TeamMessageHandler/TeamMessageHandler.cpp 中可以看到writeMessage函数把所有有关的数据(包括theRobotInfo,BallModel等)交付给BHumanMessageOutputGenerator
接收
…/…/Src/Representations/Communication/TeamData.cpp 中可以看到handleMessage把接收到的原始数据还原成具体的renpresentation格式。
总结
传送自定义的数据
TeamData包含的信息虽然大部分情况下够用了,但有时候我们想发送和接收别的representation,这时候就要:
1、检查representation是否继承了BHumanMessageParticle,若无,请改写。
2、
…/…/Src/Representations/Communication/TeamData.h 中添加对应的声明:
(YourMessage) theYourMessage
3、
…/…/Src/Representations/Communication/TeamData.cpp 中的handleMessage 函数添加对应的代码:
HANDLE_PARTICLE(YourMessage);
4、
…/…/Src/Modules/Communication/TeamMessageHandler/TeamMessageHandler.cpp 中的parseMessageIntoBMate函数添加对应的代码:
RECEIVE_PARTICLE(YourMessage);
5、
…/…/Src/Modules/Communication/TeamMessageHandler/TeamMessageHandler.cpp 中的 generateMessage 函数添加对应的代码:
SEND_PARTICLE(YourMessage);
越重要的信息放在越靠前的位置,因为尾部信息有概率丢失。
当然不要忘了在有关的文件Require(YourMessage),不再赘述。