0. 简介

protobuf也叫protocol buffer是google 的一种数据交换的格式,它独立于语言,独立于平台。google 提供了多种语言的实现:java、c#、c++、go 和 python,每一种实现都包含了相应语言的编译器以及库文件。

由于它是一种二进制的格式,比使用 xml 、json进行数据交换快许多。可以把它用于分布式应用之间的数据通信或者异构环境下的数据交换。作为一种效率和兼容性都很优秀的二进制数据传输格式,可以用于诸如网络传输、配置文件、数据存储等诸多领域。

更多详情请看:https://developers.google.com/protocol-buffers/docs/overview

1. 基础语法

1 字段限制

required: 必须赋值的字符
optional: 可有可无的字段,可以使用[default = xxx]配置默认值
repeated: 可重复变长字段,类似数组

2 tag

每个字段都有独一无二的tag
tag 1-15是字节编码,16-2047使用2字节编码,所以1-15给频繁使用的字段

3 类型

在这里插入图片描述

系统默认值:
string默认为空字符串;
bool默认为false;
数值默认为0;
enum默认为第一个元素

4 解析与序列化

每个message都包含如下方法,用于解析和序列化,注意目标是字节形式,非文本。
bool SerializeToString(string* output) const: 将message序列化成二进制保存在output中,注意保存的是二进制,不是文本;仅仅是string作为容器。
bool ParseFromString(const string& data): 从给定的二进制数值中解析成message
bool SerializeToOstream(ostream* output) const: 序列化到ostream中
bool ParseFromIstream(istream* input): 从istream中解析出message

3. 讲解举例

建立.proto文件

syntax = "proto3";//指定版本信息,不指定会报错

message Person //message为关键字,作用为定义一种消息类型
{
    string name = 1;    //姓名
    int32 id = 2;       //id
    string email = 3;   //邮件
}

message AddressBook
{
    repeated Person people = 1;
}

字段API

一般我们会经常使用protoc来自动生成:

protoc -I=$SRC_DIR --cpp_out=$DST_DIR $SRC_DIR/addressbook.proto

其中protoc工具地址:protoc

而对于字段修饰符为repeated的字段生成的函数,则稍微有一些不同,如people字段,则编译器会为其产生如下的代码:

int people_size() const;
void clear_people();
const ::Person& people(int index) const;
::Person* mutable_people(int index);
::Person* add_people();
::google::protobuf::RepeatedPtrField< ::Person >* mutable_people();
const ::google::protobuf::RepeatedPtrField< ::Person >& people() const;

测试程序

void set_addressbook()
{
    AddressBook obj;

    Person *p1 = obj.add_people(); //新增加一个Person
    p1->set_name("mike");
    p1->set_id(1);
    p1->set_email("mike@qq.com");

    Person *p2 = obj.add_people(); //新增加一个Person
    p2->set_name("jiang");
    p2->set_id(2);
    p2->set_email("jiang@qq.com");

    Person *p3 = obj.add_people(); //新增加一个Person
    p3->set_name("abc");
    p3->set_id(3);
    p3->set_email("abc@qq.com");

    fstream output("pb.xxx", ios::out | ios::trunc | ios::binary);

    bool flag = obj.SerializeToOstream(&output);//序列化
    if (!flag)
    {
        cerr << "Failed to write file." << endl;
        return;
    }

    output.close();//关闭文件
}

void get_addressbook()
{
    AddressBook obj;
    fstream input("./pb.xxx", ios::in | ios::binary);
    obj.ParseFromIstream(&input);  //反序列化
    input.close(); //关闭文件

    for (int i = 0; i < obj.people_size(); i++)
    {
        const Person& person = obj.people(i);//取第i个people
        cout << "第" << i + 1 << "个信息\n";
        cout << "name = " << person.name() << endl;
        cout << "id = " << person.id() << endl;
        cout << "email = " << person.email() << endl << endl;
    }
}

运行结果:

在这里插入图片描述

4. Protobuf的地图格式说明

Protobuf3 请参阅 Google 官方文档

Protobuf 的仓库地址为 https://github.com/protocolbuffers/protobuf

syntax = "proto3";
package rbk.protocol;
import "google/protobuf/wrappers.proto";
import "message_header.proto";

message Message_MapProperty {

    string key = 1;  // 属性名
    string type = 2; // 属性值的类型, 这里 type 一定是 string, bool, int(int32), uint(uint32), int64, uint64, float, double, bytes,json(如果为json时则取string_value)
    bytes value = 3; // 属性值 (已废弃, for backward compatibility)
      oneof oneof_value { // 属性值
      string string_value = 4;
      bool bool_value = 5;
      int32 int32_value = 6;
      uint32 uint32_value = 7;
      int64 int64_value = 8;
      uint64 uint64_value = 9;
      float float_value = 10;
      double double_value = 11;
      bytes bytes_value = 12;
    }

}

// 普通点

message Message_MapPos {
    double x = 1;
    double y = 2;
}

// 反光板点

message Message_MapRSSIPos {
    double x = 1;
    double y = 2;
}

message Message_ReflectorPos {
  string type = 1;
  double width = 2;
  double x = 3;
  double y = 4;
}



message Message_LiveRefPos {
  repeated Message_ReflectorPos ref_pos = 1;
}

message Message_tagPos{
  uint32 tag_value = 1;
  double x = 2 ;
  double y = 3;
  double angle =4 ;
  bool is_DMT_detected = 5;
}

// 普通线

message Message_MapLine {
    Message_MapPos start_pos = 1; // 线的起始点
    Message_MapPos end_pos = 2;  // 线的终止点
}

// 地图元数据

message Message_MapHeader {
    string map_type = 1;   // type of map: 2D-map or 3D-map
    string map_name = 2;  // name of map: the map file name
    Message_MapPos min_pos = 3; // 地图中 x,y 最小值, 该点不一定存在, 只是指示包含增长地图的矩形的左下点
    Message_MapPos max_pos = 4; // 地图中 x,y 最大值, 该点不一定存在, 只是指示包含增长地图的矩形的右上点
    double resolution = 5; // 分辨率 (m), 一般为 0.02 或 0.05
    string version = 8; // 地图的格式的版本号, 目前只支持 1.0.x
}

// 暂时无用,用户不必关注该条目

message Message_MapAttribute {
    string description = 1; // description of the this class
    uint32 color_pen = 2;
    uint32 color_brush = 3;
    uint32 color_font = 4;
}

// 高级点
message Message_AdvancedPoint {
    string class_name = 1;   // 高级点的类型, 目前只有 LocationMark(普通站点), ChargePoint(充电点), ParkPoint(停靠点), ActionPoint(动作点), TransferLocation(运输点), WorkLocation(工作点)
    string instance_name = 2; // 唯一标识名
    Message_MapPos pos = 3;  // 点
    double dir = 4;      // 方向
    repeated Message_MapProperty property = 5; // 高级点的属性
    bool ignore_dir = 6;         // 是否忽略方向
    bytes desc = 8;           // 描述
    Message_MapAttribute attribute = 10; // 暂时无用
}

// 高级线

message Message_AdvancedLine {
    string class_name = 1;  // 高级线的类型, 目前只有 ForbiddenLine
    string instance_name = 2; // 唯一标识名
    Message_MapLine line = 3; // 线
    repeated Message_MapProperty property = 4; // 高级线的属性
    bytes desc = 8;           // 描述
    Message_MapAttribute attribute = 10; // 暂时无用
}



// 高级曲线(用于连接两个高级点)
message Message_AdvancedCurve {
    string class_name = 1;  // 高级曲线的类型, 目前只有 BezierPath(三阶贝塞尔曲线),ArcPath(圆弧),StraightPath(直线) 三种
    string instance_name = 2; // 唯一标识名
    Message_AdvancedPoint start_pos = 3; // 曲线起始点(是某个高级点,一定是地图中出现过的某个高级点)
    Message_AdvancedPoint end_pos = 4;  // 曲线终止点(是某个高级点,一定是地图中出现过的某个高级点)
    Message_MapPos control_pos1 = 5;   // 曲线控制点1(BezierPath 的第一个控制点,或 ArcPath 的唯一控制点,StraightPath 无控制点)
    Message_MapPos control_pos2 = 6;   // 曲线控制点2(BezierPath 的第二个控制点)
    repeated Message_MapProperty property = 7; // 高级曲线的属性
    bytes desc = 8;            // 描述
    Message_MapPos control_pos3 = 9;    // 曲线控制点3(暂时无用)
    repeated Message_Device devices = 12; // 暂时无用
    Message_MapAttribute attribute = 15;  // 暂时无用
}



// 高级区域
message Message_AdvancedArea {
    string class_name = 1;  // 高级区域的类型,目前只有 AdvancedArea(高级属性区域),ReflectorArea(反光板区域),DOArea(DO控制区域),DIArea(DI控制区域)
    string instance_name = 2; // 唯一标识名
    repeated Message_MapPos pos_group = 3; // 区域边界线
    double dir = 4;            // 方向
    repeated Message_MapProperty property = 5; // 高级区域的属性
    bytes desc = 8;            // 描述
    repeated Message_Device devices = 10; // 暂时无用
    Message_MapAttribute attribute = 15;  // 暂时无用
}

// 暂时无用,用户不必关注该条目

message Message_VirtualLineList {
  repeated Message_MapLine virtual_map_line = 1;
}

// 暂时无用,用户不必关注该条目

message Message_LaserDevice {
    uint32 id = 1;
    repeated Message_MapPos laser_margin_pos = 2;
}



// 暂时无用,用户不必关注该条目

message Message_Device {
    string model_name = 1;
    repeated Message_LaserDevice laser_devices = 5;
    repeated double ultrasonic_dist = 6;
    repeated double fallingdown_dist = 7;
}

// 暂时无用,用户不必关注该条目

message Message_PatrolRouteStation {
    string id = 1;
}

// 暂时无用,用户不必关注该条目

message Message_PatrolRoute {
    string name = 1;
    repeated Message_PatrolRouteStation station_list = 2;
    google.protobuf.DoubleValue max_speed = 4;
    google.protobuf.DoubleValue max_acc = 5;
    google.protobuf.DoubleValue max_rot = 6;
    google.protobuf.DoubleValue max_rot_acc = 7;
    bytes desc = 8;
    google.protobuf.DoubleValue max_dec = 9;
    google.protobuf.DoubleValue max_rot_dec = 10;
}



// 地图

message Message_Map {
    string map_directory = 1;   // 暂时无用
    Message_MapHeader header = 2; // 元数据,用户无需关注
    repeated Message_MapPos normal_pos_list = 3; // 普通点数组
    repeated Message_MapLine normal_line_list = 4; // 普通线数组
    repeated Message_AdvancedPoint advanced_point_list = 6; // 高级点数组
    repeated Message_AdvancedLine advanced_line_list = 7; // 高级线数组
    repeated Message_AdvancedCurve advanced_curve_list = 8; // 高级曲线数组
    repeated Message_AdvancedArea advanced_area_list = 9; // 高级区域数组
    repeated Message_PatrolRoute patrol_route_list = 10;  // 暂时无用
    repeated Message_MapRSSIPos rssi_pos_list = 11;     // 反光板点数组
    repeated Message_ReflectorPos reflector_pos_list = 12;
    repeated Message_tagPos tag_pos_list = 13;
}

5. 参考链接

https://blog.csdn.net/K346K346/article/details/51754431

https://www.jianshu.com/p/6a6dbff2b5cd

https://docs.seer-group.com/public/technical-support/master/zh/excursus/smap-format.html

https://blog.csdn.net/qq_39534332/article/details/105237131

https://blog.csdn.net/ziliwangmoe/article/details/94481529

https://blog.csdn.net/tennysonsky/article/details/73921025