美文网首页
ROS-I simple_message 源码分析:Messag

ROS-I simple_message 源码分析:Messag

作者: play_robot | 来源:发表于2019-03-21 10:39 被阅读0次

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的。

相关文章

网友评论

      本文标题:ROS-I simple_message 源码分析:Messag

      本文链接:https://www.haomeiwen.com/subject/cjofvqtx.html