ROS-I simple_message 源码分析:Messag
MessageHandler类定义了消息处理的接口:当接收到消息后的回调处理函数。
namespace industrial
{
namespace message_handler
{
class MessageHandler
{
public:
MessageHandler();
~MessageHandler();
bool callback(industrial::simple_message::SimpleMessage & in);
int getMsgType()
{
return this->msg_type_;
}
;
protected:
industrial::smpl_msg_connection::SmplMsgConnection*getConnection()
{
return this->connection_;
}
;
bool init(int msg_type, industrial::smpl_msg_connection::SmplMsgConnection* connection);
private:
industrial::smpl_msg_connection::SmplMsgConnection* connection_;
int msg_type_;
virtual bool internalCB(industrial::simple_message::SimpleMessage & in)=0;
bool validateMsg(industrial::simple_message::SimpleMessage & in);
void setConnection(industrial::smpl_msg_connection::SmplMsgConnection* connection)
{
this->connection_ = connection;
}
;
void setMsgType(int msg_type)
{
this->msg_type_ = msg_type;
}
;
};
} //namespace message_handler
} //namespace industrial
使用的时候,首先需要调用init
方法来配置消息类型和使用的连接。当接收到消息后,callback
回调函数将会执行,它首先会检查消息的有效性,即将收到的消息类型与配置的消息类型做对比看是否一致,如果一致,则调用internalCB
来执行具体的消息处理,这个具体的处理则是由子类实现的,我们以ping message为例来分析一个具体的实现。
首先看一下PingMessage的代码:
namespace industrial
{
namespace ping_message
{
class PingMessage : public industrial::typed_message::TypedMessage
{
public:
PingMessage(void);
~PingMessage(void);
bool init(industrial::simple_message::SimpleMessage & msg);
void init();
bool toTopic(industrial::simple_message::SimpleMessage & msg)
{
return false;
}
// Overrides - SimpleSerialize
bool load(industrial::byte_array::ByteArray *buffer){return true;}
bool unload(industrial::byte_array::ByteArray *buffer){return true;}
unsigned int byteLength(){return 0;}
};
}
}
这个类同我们之前看到的RobotStatusMessage类是类似的,都继承自TypedMessage。
bool init(industrial::simple_message::SimpleMessage & msg);
用于尝试从一个SimpleMessage中得到ping message。如果传进来的msg类型不是PING类型,则或返回失败。而从ping message创建SimpleMessage是通过基类TypedMessage中的toRequest或toReply实现的:
virtual bool toRequest(industrial::simple_message::SimpleMessage & msg)
{
industrial::byte_array::ByteArray data;
data.load(*this);
return msg.init(this->getMessageType(),
industrial::simple_message::CommTypes::SERVICE_REQUEST,
industrial::simple_message::ReplyTypes::INVALID, data);
}
virtual bool toReply(industrial::simple_message::SimpleMessage & msg,
industrial::simple_message::ReplyType reply)
{
industrial::byte_array::ByteArray data;
data.load(*this);
return msg.init(this->getMessageType(),
industrial::simple_message::CommTypes::SERVICE_REPLY,
reply, data);
}
接下来我们看一下继承自MessageHandler的PingHandler:
namespace industrial
{
namespace ping_handler
{
class PingHandler : public industrial::message_handler::MessageHandler
{
public:
bool init(industrial::smpl_msg_connection::SmplMsgConnection* connection);
bool init(int msg_type, industrial::smpl_msg_connection::SmplMsgConnection* connection)
{ return MessageHandler::init(msg_type, connection);};
private:
bool internalCB(industrial::simple_message::SimpleMessage & in);
};
}//ping_handler
}//industrial
顾名思义,ping 消息被用于测试通信是否正常,而PingHandler则是用于处理ping message的类,定义了如何响应(回复)ping message。
bool PingHandler::internalCB(industrial::simple_message::SimpleMessage & in)
{
bool rtn = false;
PingMessage ping;
SimpleMessage msg;
if (ping.init(in))
{
if (ping.toReply(msg, ReplyTypes::SUCCESS))
{
if(this->getConnection()->sendMsg(msg))
{
LOG_INFO("Ping return sent");
rtn = true;
}
else
{
LOG_ERROR("Failed to send ping return");
rtn = false;
}
}
else
{
LOG_ERROR("Failed to generate ping reply message");
rtn = false;
}
}
else
{
LOG_ERROR("Failed to initialize ping message");
rtn = false;
}
return rtn;
}
首先创建PingMessage类型的临时变量ping,再调用ping.init(in)
检查到来的消息是否是ping message,再调用ping.toReply(msg, ReplyTypes::SUCCESS)
创建msg消息,最后调用sendMsg(msg)
发送回复消息。
这里提一下另一个重载的init,当然也可以直接写在第一个init当中,
bool init(int msg_type, industrial::smpl_msg_connection::SmplMsgConnection* connection)
{ return MessageHandler::init(msg_type, connection);};
这个方法里调用了基类MessageHandler的init方法,用于初始化PingHandler基类成员中的数据:connection_和msg_type_
PingHandler只是一个简单的示例,后面会分析一个具体的机器人中是怎么写message handler的。