Cyber RT解析与实践
第二章:Cyber RT通信机制解析与实践
Cyber RT解析与实践
- Cyber RT解析与实践
- 一、Cyber RT 通讯机制简介
- 1. 话题
- 2. 服务
- 3. 参数
- 二、数据通信基础Protobuf
- 1. Protobuf 简介
- 2. Protobuf 创建
- 3. Protobuf 编译
- 4. Protobuf 案例实战
- 三、Cyber RT 话题通信实践案例
- 1. Listener 和 Talker通讯原理
- 2. 通信实现流程讲解
- 3. 编写C++话题通信实现
- 4. 运行与测试
- 5. 编写Python话题通信实现(小练习)
- 6. 运行与测试
- 总结
一、Cyber RT 通讯机制简介
1. 话题
我们想要⼀直获取⻋的速度,该需求不需要向发送⽅返回什么消息,也不需要发送⽅对消息进⾏进⼀步处理。所以我们选择了Listener-Talker通信⽅式实现该功能。
Listener-Talker通信⼀⽅主动送消息,⼀⽅被动接收。如图2-1所示,Listener-Talker通信⾸先创建了两个Node,分别是Talker Node和 Listener Node。每个Node实例化Writer类和Reader类对Channel进⾏消息的读写。Writer和Reader通过Topic连接,对同⼀块共享内存(Channel)进⾏读写处理。在这⾥,Talker Node 为了实现其“诉说”的功能,选择实例化Writer,通过Writer来对Channel进⾏消息写操
作。⽽istener Node为了实现其“聆听”功能,选择实例化reader类,通过Reader来对channel进⾏读操作。在这⾥,通信中⽤的的数据格式的定义car message 定义在car.proto中。该通信⽅式适合于持续性通信的应⽤场景,⽐如雷达信号,摄像头图像信息这类数据的传输。
2. 服务
我们想要获得⼩⻋的详细信息,⽐如⻋牌这些,但是⼜不需要⼀直获得该信息,想要在需要知道这些信息的时候请求⼀下就好,于是考虑⽤Server- Client通信实现该功能。如图2-1所示,Server-Client通信可以在客户端发出消息请求时,服务端才进⾏请求回应,并将客户端所需的数据返回给客户端。该通信模式适合临时的消息传输,适⽤于不需要持续性发送数据的场景。其传输的数据定义依然在对应的proto⽂件中。
3. 参数
有⼀些参数⽐如该⻋的最⾼限速,最多乘客以及是否⾃动驾驶等需要被各个模块所使⽤,⽐如是否⾃动驾驶这个参数可能同时影响这很多模块,也可能被很多模块运⾏时所更改。我们希望有⼀个类似于“全局变量”的⽅式来存储这些参数,并定义⼀些⾃定义参数来进⾏使⽤。Cyber中设计了全局参数服务器来实现这个功能,其通信依然基于RTPS协议,如图2-8所示。该通信⽅式服务端和客户端都可以设置参数和更改参数。
二、数据通信基础Protobuf
1. Protobuf 简介
Protobuf是Google公司开发的一种跨语言和平台的序列化数据结构的方式,是一个灵活的、高效的用于序列化数据的协议,与XML和JSON格式相比,Protobuf更小、更快、更便捷。
Protobuf是跨语言的,并且自带一个编译器(protoc),只需要用protoc进行编译,就可以编译成Java、Python、C++、C#、Go等多种语言代码,然后可以直接使用,不需要再写其它代码,自带有解析的代码。只需要将要被序列化的结构化数据定义一次(在.proto文件定义),便可以使用特别生成的源代码(使用protobuf提供的生成工具)轻松的使用不同的数据流完成对结构数据的读写操作。甚至可以更新.proto文件中对数据结构的定义而不会破坏依赖旧格式编译出来的程序。
其优点如下:
- 性能效率高:序列化后字节占用空间比XML少3-10倍,序列化的时间效率比XML快20-100倍。
- 使用便捷便捷:将对结构化数据的操作封装成一个类,便于使用。
- 兼容性高:通信两方使用同一数据协议,当有一方修改了数据结构,不会影响另一方的使用。
- 跨语言:支持Java,C++,Python、Go、Ruby等多种语言。
2. Protobuf 创建
为了方便讲解,使用cyber/examples/proto/examples.proto
文件来讲解,syntax
表示使用Protobuf的版本,目前Protobuf支持proto3,但在Apollo中使用的是proto2;package 表示该文件的路径;每一个message都表示一种数据结构,message后面跟的是数据结构名字,括号里的字段定义格式为:字段规则 数据类型 字段名称 字段编号。
字段规则主要有三种:
- required:调用时必须提供该字段的值,否则该消息被视为“未初始化”,官方不建议使用,当把字段规则改为其他规则会存在兼容性问题。
- optional:该字段的值可以设置也可以不设置,会根据数据类型生成一个默认的值。
- repeated:类似于动态数组,可以存储多个同类型的数据。
# examples.proto
syntax = "proto2";
package apollo.cyber.examples.proto;
message SamplesTest1 {
optional string class_name = 1;
optional string case_name = 2;
};
message Chatter {
optional uint64 timestamp = 1;
optional uint64 lidar_timestamp = 2;
optional uint64 seq = 3;
optional bytes content = 4;
};
message Driver {
optional string content = 1;
optional uint64 msg_id = 2;
optional uint64 timestamp = 3;
};
3. Protobuf 编译
Protobuf的编译要分为两个步骤,首先要根据.proto文件生成proto库,然后再根据生产的proto库生成C++相关的源文件。这个源文件是C++语言自动编写的,可以被C++程序自动识别。每一个message会被解析生一个类,里面的字段就相当于这个类的属性。在源文件中也会根据属性生成额外的成员,如获取和设置属性的函数。
package(default_visibility = ["//visibility:public"])
#1、生成proto库
proto_library(
name = "examples_proto",
srcs = ["examples.proto"],
)
#2、生成源文件
cc_proto_library(
name = "examples_cc_proto",
deps = [
":examples_proto",
],
)
4. Protobuf 案例实战
目的:使用Protobuf来定义数据格式,在main程序中设置数据值并输出。
流程:1、创建目录并编写相关文件;2、编译执行。
内容如下:
创建test功能包结构:
test
|-- test_proto
|-- BUILD
|-- car.cc
|-- proto
|-- BUILD
|-- car_msg.proto
各个结构内容如下:
三、Cyber RT 话题通信实践案例
1. Listener 和 Talker通讯原理
2. 通信实现流程讲解
3. 编写C++话题通信实现
4. 运行与测试
5. 编写Python话题通信实现(小练习)
6. 运行与测试
总结
以上就是今天要讲的内容,本文仅仅简单介绍了apollo talker and listener 的使用,而apollo 提供了大量能使我们快速便捷地处理数据的函数和方法。