ROS与protobuf
博客园 https://www.cnblogs.com/
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
标签:文件,RoS,protobuf,proto,序列化,Apollo,robag,msg,ROS
From: https://www.cnblogs.com/ytwang/p/17865541.html