Home » ROS与C++入门教程 » ROS与C++入门教程-消息-序列化和适配类型

ROS与C++入门教程-消息-序列化和适配类型

ROS与C++入门教程-消息-序列化和适配类型

说明:

  • 介绍序列化和适配类型
  • 在C Turtle版本增加

序列化到内存

  • 使用ros::serialization::serialize()函数,roscpp的消息能非常容易地序列化到内存。
  • 示例:
namespace ser = ros::serialization;

std_msgs::UInt32 my_value;
my_value.data = 5;

uint32_t serial_size = ros::serialization::serializationLength(my_value);
boost::shared_array<uint8_t> buffer(new uint8_t[serial_size]);

ser::OStream stream(buffer.get(), serial_size);
ser::serialize(stream, my_value);

从内存中反序列

  • 从内存中反序列,也很容易:
namespace ser = ros::serialization;

std_msgs::UInt32 my_value;

uint32_t serial_size = ros::serialization::serializationLength(my_value);
boost::shared_array<uint8_t> buffer(new uint8_t[serial_size]);

// Fill buffer with a serialized UInt32
ser::IStream stream(buffer.get(), serial_size);
ser::deserialize(stream, my_value);
  • 在最新ROS,上面代码会显示deprecation warning,替换最后一行为:
ros::serialization::Serializer<std_msgs::UInt32>::read(stream, my_value);

适配C++类型

  • 在ROS 1.1,roscpp使用了基于模板的序列化系统。
  • 它能适应外部类型,能在ROS的订阅和发布中使用。
  • 它通过一套专门的特性类,以及一个专门的序列化类来实现。

Trait Specialization

Serializer Specialization

  • 为了定义类型的序列化,你必需定义ros::serialization::Serializer类的specialization
  • 示例代码:
template<typename T>
struct Serializer
{
  template<typename Stream>
  inline static void write(Stream& stream, typename boost::call_traits<T>::param_type t);
  template<typename Stream>
  inline static void read(Stream& stream, typename boost::call_traits<T>::reference t);
  inline static uint32_t serializedLength(typename boost::call_traits<T>::param_type t);
};
  • 定义all-in-one序列处理器
template<typename T>
struct Serializer
{
  template<typename Stream, typename M>
  inline static void allInOne(Stream& stream, M t);
  ROS_DECLARE_ALLINONE_SERIALIZER;
};
  • 注意,如果你使用一个all-in-one序列处理器,不允许你其他函数,除了stream.next()。
  • 任何需要更复杂的行为应使用独立的3-function版本。

适配自定义Vector3

#include <ros/message_traits.h>
#include <ros/serialization.h>

struct MyVector3
{
  double x;
  double y;
  double z;
};
// compile-time assert that sizeof(MyVector3) == serializationLength(x) + serializationLength(y) + serializationLength(z)
ROS_STATIC_ASSERT(sizeof(MyVector3) == 24);

namespace ros
{
namespace message_traits
{
// This type is fixed-size (24-bytes)
template<> struct IsFixedSize<MyVector3> : public TrueType {};
// This type is memcpyable
template<> struct IsSimple<MyVector3> : public TrueType {};

template<>
struct MD5Sum<MyVector3>
{
  static const char* value()
  {
    // Ensure that if the definition of geometry_msgs/Vector3 changes we have a compile error here.
    ROS_STATIC_ASSERT(MD5Sum<geometry_msgs::Vector3>::static_value1 == 0x4a842b65f413084dULL);
    ROS_STATIC_ASSERT(MD5Sum<geometry_msgs::Vector3>::static_value2 == 0xc2b10fb484ea7f17ULL);
    return MD5Sum<geometry_msgs::Vector3>::value();
  }

  static const char* value(const MyVector3& m)
  {
    return MD5Sum<geometry_msgs::Vector3>::value(m);
  }
};

template<>
struct DataType<MyVector3>
{
  static const char* value()
  {
    return DataType<geometry_msgs::Vector3>::value();
  }

  static const char* value(const MyVector3& m)
  {
    return DataType<geometry_msgs::Vector3>::value(m);
  }
};

template<>
struct Definition<MyVector3>
{
  static const char* value()
  {
    return Definition<geometry_msgs::Vector3>::value();
  }

  static const char* value(const MyVector3& m)
  {
    return Definition<geometry_msgs::Vector3>::value(m);
  }
};
} // namespace message_traits

namespace serialization
{
template<>
struct Serializer<MyVector3>
{
  template<typename Stream, typename T>
  inline static void allInOne(Stream& stream, T t)
  {
    stream.next(t.x);
    stream.next(t.y);
    stream.next(t.z);
  }

  ROS_DECLARE_ALLINONE_SERIALIZER;
};
} // namespace serialization
} // namespace ros
  • 替换成使用3-function序列处理:
namespace ros
{
namespace serialization
{

template<>
struct Serializer<MyVector3>
{
  template<typename Stream>
  inline static void write(Stream& stream, const MyVector3& t)
  {
    stream.next(t.x);
    stream.next(t.y);
    stream.next(t.z);
  }

  template<typename Stream>
  inline static void read(Stream& stream, MyVector3& t)
  {
    stream.next(t.x);
    stream.next(t.y);
    stream.next(t.z);
  }

  inline static uint32_t serializedLength(const MyVector3& t)
  {
    uint32_t size = 0;
    size += serializationLength(t.x);
    size += serializationLength(t.y);
    size += serializationLength(t.z);
    return size;
  }
};

} // namespace serialization
} // namespace ros

纠错,疑问,交流: 请进入讨论区点击加入Q群

获取最新文章: 扫一扫右上角的二维码加入“创客智造”公众号


标签: ROS与C++入门教程