RoS_robag中的msg与protobufNode订阅topic中自定义msg

ROS与protobuf

ros python 第三方msg在ROS中,

如果你想要在Python节点中使用第三方包里的自定义消息类型(msg),

你需要确保这些msg类型已经被生成了对应的Python绑定。这通常涉及到两个步骤:
01.确保第三方包已经被安装。
02. 在你的
节点package中的CMakeLists.txt文件中添加find_package()调用来找到第三方包,
并将其msg目录添加到 catkin_package()的CATKIN_DEPENDS参数中。

	find_package(catkin REQUIRED COMPONENTS
        roscpp
        ...
        third_party_msgs  # 确保这个包已经被找到
      )
	
	03.代码
	  from third_party_msgs.msg import MyCustomMessage

自定义msg

自定义msg实现
 需求:创建自定义消息,该消息包含人的信息:姓名、身高、年龄等。

流程:
    按照固定格式创建 msg 文件
    编辑配置文件
    编译生成可以被 Python 或 C++ 调用的中间文件

 pakage.xml中添加如下的功能包依赖
    <build_depend>message_generation</build_depend>
    <exec_depend>message_runtime</exec_depend>
 编译msg
       catkin_make 
 验证msg
    查看是否生成和 package名称staff_msgs相同的目录,以及目录内是否生成对应的py文件。
	    Python 需要调用的中间文件(.../工作空间/devel/lib/python3/dist-packages/包名/msg)  
		 添加到$PYTHONPATH:
		C++ 是头文件 中间文件(.../工作空间/devel/include/包名/xxx.h)
     rosmsg show staff_msgs/staff
 调用msg	 

在ROS中使用Python订阅novatel_msgs/INSPVAX.msg主题的基本步骤如下:

确保novatel_msgs已正确安装在你的环境中。
 <run_depend>novatel_msgs</run_depend>

  创建一个Python节点,并在该节点中订阅INSPVAX消息。
  实现一个回调函数,该函数将在接收到消息时被调用。

以下是一个简单的Python脚本示例,该脚本在ROS中使用rospy库订阅novatel_msgs/INSPVAX消息:

#!/usr/bin/env python
import rospy
from novatel_msgs.msg import INSPVAX

bag格式

bag包就是为了录制消息,而消息的保存和读取就涉及到一个广义上的问题序列化和反序列化
 Bag包的第一行是人眼可以识别的版本号,后面紧跟着的是一系列记录序列
  #ROSBAG V2.0
  <record 1><record 2>....<record N>
 <record 1> 
    record由header和data组成,以及header_len和data_len
	
	Headers
	 每个记录头包含一系列 name=value 字段,格式如下
	  <field1_len><field1_name>=<field1_value>
	  <field2_len><field2_name>=<field2_value>...<fieldN_len><fieldN_name>=<fieldN_value>

	   field_name  字段名称可以包含任何可打印的 ASCII 字符 (0x20 - 0x7e),但 =(0x3d) 除外。
       field_value 字段值可以包含任何数据(包括嵌入空值、换行符等的二进制数据
	   信息头必须包含Op码字段,也就是说上述field_name必须有一个字段为Op 。这个字段是为了区分 record的类型而准备的
	   
 record类型,一共有6种类型,下面我们逐个介绍。
   Bag header   主要存放bag包整体的信息,必须是第一个record。
   Chunk        主要的数据结构,可以被压缩,可以理解为把N个消息打包为一个块(Chunk),方便索引节省空间。
   Connection   块的结构之一,存放信息的格式信息,有了消息的格式,才能解析消息。
   Message data 块的结构之一,消息序列化之后以2进制存储,通过Connection获取消息格式后进行反序列化。
   Index data   索引数据,因为一个块比较大,索引消息在块中的位置,方便快速查找,缺点在于会占用额外的空间
   Chunk info   块的结构之一,主要描述块的信息,例如消息的起始和结束时间等。	   
 数据兼容,在原生ROS里面,
   开发者使用了一个trick:将Proto文件序列化成一个字符串信息放到Message信息里面,完成消息的向后兼容
 Apollo ROS这个方式有两个明显的缺点:
  1.它增加了一次数据序列化和反序列化。并把Proto序列化信息压到Message里面,增加了两次额外的数据Copy。
  2.如果想实时调试信息,通过Rostopic echo打印出来Message里面那个序列化的字母串,
     若是采用Wrapper的方式,则这个字符串信息在屏幕上就会是一堆乱码。

protobuf

[root@fedora ]# protoc --version
libprotoc 25.0
[root@fedora ]# python3
>>> import google.protobuf
>>> print(google.protobuf.__version__)
4.25.0

protobuf 下载地址

 https://github.com/protocolbuffers/protobuf/releases

 下载文件:
    protoc-25.1-linux-x86_64.zip  -- 选择了对应平台的包
	protobuf-25.1.zip
1. protoc-25.1-linux-x86_64.zip压后打开该目录的bin目录,复制路径到环境变量中


2.解压protobuf-23.1.zip文件,找到python目录,并在protobuf中的python目录打开cmd将下面三条命令敲入
  (pip的protobuf和下载的protobuf版本最好一致)–要在当前目录下的cmd噢
    pip install protobuf
    python setup.py build
    python setup.py install
	### 安装命令会将当前的 Python 应用安装到当前 Python 环境的 site-packages 目录下,这样其他程序就可以像导入标准库一样导入该应用的代码了。  

protobuf文件

### JSON 对应的 Python 对象是字典,而 protobuf 则是单独生成的对象
 基本类型
 复合类型
 // 包命名,确保包名不冲突,导入其他proto文件会用到
 package greeter;

protobuf执行生成命令

 搜索路径参数

   即-IPATH, –proto_path=PATH。它表示要在哪个路径下搜索.proto文件,这个参数既可以用-I指定,也可以使用–proto_path=指定
  protoc --python_out=./ ./文件名.proto  
  
  # 点号表示当前路径,注意-I参数没有等于号
    $ protoc -I. --go_out=. proto/greeter/greeter.proto 
    
    $ protoc --proto_path=. --python_out=. proto/greeter/greeter.proto 
  
  在自定义的.proto文件中引入了外部的proto文件
     单一依赖--多重依赖-公共依赖--循环依赖
	 
    import指令时,应该特别注意文件路径引用的问题
    需要注意文件路径引用、命名空间冲突、协议版本等一系列问题	  
	cd 到import的中最上层的目录的同一级目录中

protobuf通过语言脚本设置接口要发送/接收的数据

利用 foo_pb2.py 文件定义发送的接口数据。 创建一个test_foo_pb2.py文件

 // 2.初始化ROS节点,这里是节点名
ros::init(argc,argv,"besproma_pub_node");

// 3.实例化 ROS 句柄
ros::NodeHandle nh;

 // 4.实例化发布者对象,参数是话题名,buffer大小
ros::Publisher pub = nh.advertise<std_msgs::String>("besproma_topic",10);

 . I will try to convert the proto buffer msg into std msg 
 then from subscriber end I will convert it back to protobuf.

百度Apollo ROS

控制器的类型,大致分为三类,分别是开环控制、前馈环控制和后馈环控制
 百度Apollo ROS
    Topic内部使用的数据格式是Message。
	Message是一系统简单的数据类型或者是一些自定义的复杂数据类型,所组装成的一个描述文件。
	Message是两个节点进行消息通信的抽象描述文件。这个描述文件提前定义好两个节点之间进行消息通信的基本数据类型
 大数据传输性能瓶颈 单中心的网络存在单点风险 数据格式缺乏后向兼容
  通信性能优化
     1.Apollo项目对于ROS第一个改造就是通过共享内存来减少数据拷贝,以提升通信性能
	    基于共享内存的通信方式下,每一条链路内存拷贝的次数只需要两次,三条链路只需要六次
	 2.Apollo ROS对ROS的改进第二部分去中心化网络拓扑
	  Nvidia Drive PX2板卡,它就包括两个系统:一个主系统,一个是冗余备份系统即容错系统
	  Apollo ROS 使用PTRS服务发现协议实现完全的P2P网络拓扑-它离开的时候,也会发送消息告诉所有的节点:现在这个节点要退出
     3.深度整合Protobuf功能,实现数据兼容性扩展
	   新增的字段我们可以使用Optional属性去描述。
	   如果下游它要去使用这个字段的话才需要去进行一定程度的适配。如果它的程序不使用这个新增的字段,就不需要做任何的修改。

ROS

ROS提供了三种节点之间通信的方式
  基于消息的订阅发布模型, MSG描述文件
  第二种就是ROS Service, SRV文件描述都有一个Request和Response方式 请求信息的消息格式和响应格式
  第三种Param	 Parameter service是一个全局的服务器,各个节点在进行参数设置和获取的时候可以通过Parameter service的方式轻易完成	   
    rosparam其它工具相比,有两个不同的地方:get和set。get是get某一个全局参数的值;set是设置某一个全局参数的值.
 ros msg 扩展性较差,即如果 msg 的字段发生变化,则程序前后版本不兼容
     google 的 protobuf 相对就是一个更好的选择。在拥有更好的扩展性的同时,还能给对数据进行压缩,减少 rosbag 的体积。	 

参考

 进阶无人驾驶—百度Apollo ROS介绍 https://blog.nowcoder.net/n/5238b7beb2bd4085a76828136cff901a	
 https://github.com/daohu527/bag_convert
 Rosbag转Apollo数据包  https://zhuanlan.zhihu.com/p/494917196
  一张图对比Rosbag和cyber record https://apollo.baidu.com/community/article/198
https://zhuanlan.zhihu.com/p/494474804  
 https://github.com/novatel/novatel_oem7_driver/tree/master/src/novatel_oem7_msgs/msg
 http://www.autolabor.com.cn/book/ROSTutorials/di-2-zhang-ros-jia-gou-she-ji/22hua-ti-tong-xin/214-hua-ti-tong-xin-zhi-zi-ding-yi-xiao-xi.html
 https://github.com/ros-drivers/novatel_span_driver/blob/master/novatel_span_driver/src/novatel_span_driver/publisher.py
posted @ 2023-11-29 18:13  辰令  阅读(363)  评论(0编辑  收藏  举报