根据Apollo学习protobuf
上图引至Protobuf学习
参考文档:
Protobuffer简介
Protobuf是Protocol Buffers的简称,它是Google公司开发的一种数据描述语言,用于描述一种轻便高效的结构化数据存储格式,并于2008年对外开源。Protobuf可以用于结构化数据串行化,或者说序列化。它的设计非常适用于在网络通讯中的数据载体,很适合做数据存储或 RPC 数据交换格式,它序列化出来的数据量少再加上以 K-V 的方式来存储数据,对消息的版本兼容性非常强,可用于通讯协议、数据存储等领域的语言无关、平台无关、可扩展的序列化结构数据格式。开发者可以通过Protobuf附带的工具生成代码并实现将结构化数据序列化的功能。
Protobuf中最基本的数据单元是message。在message中可以嵌套message或其它的基础数据类型的成员。
定义Message
首先看一个简单apollo中的例子,比如说你定义一个车辆参数,车辆参数主要用于定义不同的车辆,以及可选的一些参数。在.proto文件中定义如下:
syntax = "proto2";
package apollo.common;
import "modules/common/proto/header.proto";
import "modules/common/proto/geometry.proto";
message Transform {
optional bytes source_frame = 1; // Also known as "frame_id."
optional bytes target_frame = 2; // Also known as "child_frame_id."
// Position of target in the source frame.
optional Point3D translation = 3;
// Activate rotation from the source frame to the target frame.
optional Quaternion rotation = 4;
}
message Extrinsics {
repeated Transform tansforms = 1;
}
// Vehicle parameters shared among several modules.
// By default, all are measured with the SI units (meters, meters per second,
// etc.).
enum VehicleBrand {
LINCOLN_MKZ = 0;
GEM = 1;
LEXUS = 2;
TRANSIT = 3;
GE3 = 4;
WEY = 5;
ZHONGYUN = 6;
CH = 7;
}
message VehicleID {
optional string vin = 1;
optional string plate = 2;
optional string other_unique_id = 3;
}
message LatencyParam {
// latency parameters, in second (s)
optional double dead_time = 1;
optional double rise_time = 2;
optional double peak_time = 3;
optional double settling_time = 4;
}
message VehicleParam {
optional VehicleBrand brand = 1;
// Car center point is car reference point, i.e., center of rear axle.
optional VehicleID vehicle_id = 2;
optional double front_edge_to_center = 3 [default = nan];
optional double back_edge_to_center = 4 [default = nan];
optional double left_edge_to_center = 5 [default = nan];
optional double right_edge_to_center = 6 [default = nan];
optional double length = 7 [default = nan];
optional double width = 8 [default = nan];
optional double height = 9 [default = nan];
optional double min_turn_radius = 10 [default = nan];
optional double max_acceleration = 11 [default = nan];
optional double max_deceleration = 12 [default = nan];
// The following items are used to compute trajectory constraints in
// planning/control/canbus,
// vehicle max steer angle
optional double max_steer_angle = 13 [default = nan];
// vehicle max steer rate; how fast can the steering wheel turn.
optional double max_steer_angle_rate = 14 [default = nan];
// vehicle min steer rate;
optional double min_steer_angle_rate = 15 [default = nan];
// ratio between the turn of steering wheel and the turn of wheels
optional double steer_ratio = 16 [default = nan];
// the distance between the front and back wheels
optional double wheel_base = 17 [default = nan];
// Tire effective rolling radius (vertical distance between the wheel center
// and the ground).
optional double wheel_rolling_radius = 18 [default = nan];
// minimum differentiable vehicle speed, in m/s
optional float max_abs_speed_when_stopped = 19 [default = nan];
// minimum value get from chassis.brake, in percentage
optional double brake_deadzone = 20 [default = nan];
// minimum value get from chassis.throttle, in percentage
optional double throttle_deadzone = 21 [default = nan];
// vehicle latency parameters
optional LatencyParam steering_latency_param = 22;
optional LatencyParam throttle_latency_param = 23;
optional LatencyParam brake_latency_param = 24;
}
message VehicleConfig {
optional apollo.common.Header header = 1;
optional VehicleParam vehicle_param = 2;
optional Extrinsics extrinsics = 3;
}
.proto文件的第一行指定了使用proto2语法。如果省略protocol buffer编译器默认使用proto2语法。他必须是文件中非空非注释行的第一行。VehicleBrand定义中指定了一个枚举字段,字段包含两对键值对(name/value键值对),可选的定义了几个字段,每个字段都会有名称和类型。
其中apollo中默认的车辆是MKZ ,因此在测试用例里也都是用mkz,具体启动车辆时可设置具体选择哪个车辆的驱动。
设置车辆的语句如下:
class LincolnVehicleFactoryTest : public ::testing::Test {
public:
virtual void SetUp() {
VehicleParameter parameter;
parameter.set_brand(apollo::common::LINCOLN_MKZ);
lincoln_factory_.SetVehicleParameter(parameter);
}
这个例程中就完成了参数的定义到使用的过程。
parameter是类VehicleParameter的一个对象,set是成员函数。
另外需要说明的是,protobuf会根据我们的定义自动生成类代码,键值对的存在只是他内部使用,我们只需要按照他的要求进行定义即可。
有几个疑问待解:
1. 如何让程序自动去解析protobuf文件
apollo已经集成好了protobuf的解析器,编写好文件后,编译apollo代码,自动生成protobuf的头文件,然后根据头文件去写代码即可。
以ch.proto为例,程序编译之后会在
/home/ch/.cache/bazel/_bazel_ch/540135163923dd7d5820f3ee4b306b32/execroot/apollo/bazel-out/local-dbg/genfiles/modules/canbus/proto/ch.pb.h
ch.pb.h就是自动生成的代码.
2. 如何让程序自动去解析protobuf文件
参考文档:
https://www.cnblogs.com/orangeform/archive/2013/01/04/2842533.html
https://www.cnblogs.com/DswCnblog/p/6703660.html
https://blog.csdn.net/u014696921/article/details/52200010