protobuf
Protobuf的数据结构定义的语法,以及如何编译proto文件,以及相关的主要读写proto文件结构中的API
说明:
读bin文件API 是bin文件二进制形式,
Prototxt文件 是prototxt形式.ProtoBuf数据保存的一种形式,主要是以txt形式.最主要的功能是可视化,
步骤
Define message formats in a .proto file.
Use the protocol buffer compiler.
Use the C++ protocol buffer API to write and read messages.
语法
syntax = "proto3" 表示使用proto3版本,默认使用proto2版本。
optional 表示当前字段可选,非必填。
string name = 1 每个字段需要有一个唯一的号码,必须大于0。
enum 表示枚举类型。
repeated 表示可重复,
message 可以嵌套
protobuf 的一大特点就是通过 “代码生成” 数据结构类的方式来序列化、反序列化二进制数据
protobuf 使用方式
01.手动调用 protoc 来编译文件,然后引入自己的项目。
02.使用 CMake 提供的 find_package 脚本找到 protobuf,得到一些变量。
03.使用 CMake 下载指定版本 protobuf,源码编译 protobuf,然后用编译生成的 protoc 来编译。
C++
代码示例
#include <vector>
#include <iostream>
#include <ros/types.h>
#include <std_msgs/String.h>
#include <rosbag/view.h>
#include <rosbag/bag.h>
#include "test.pb.h"
#define foreach BOOST_FOREACH
#include <boost/foreach.hpp>
using namespace std;
int main(){
rosbag::Bag bag;
bag.open("/data/test/test.bag", rosbag::bagmode::Read);
std::vector<std::string> topics; //设置需要遍历的topic
topics.push_back(std::string("/test/sensor/test_person"));
rosbag::View view(bag, rosbag::TopicQuery(topics));;
//rosbag::View view_all(view); //读取全部topic如果全读,第二个参数不写,如下
PersonObstacle Person;
foreach(rosbag::MessageInstance const m, view)
{
//此处为消息头文件中的ConstPtr
std_msgs::String::ConstPtr s = m.instantiate<std_msgs::String>();
if (s != NULL){
std::cout << "the null message"<<std::endl;
std::cout << Person.ParseFromString(s->data) <<std::endl;
std::cout << Person.id() <<std::endl;
std::cout << Person.mstatus()<<std::endl;
std::cout << Person.mstatus_Name<<std::endl;
}
else{
std::cout << "the message"<<std::endl;
}
}
bag.close();
return 0;
}
CMakeLists.txt
cmake_minimum_required(VERSION 3.0.2)
project(parseBag)
find_package(catkin REQUIRED COMPONENTS
rosbag
roscpp
rospy
std_msgs
)
set(CMAKE_CXX_FLAGS "-std=c++17 -pthread")
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR})
#Find required protobuf package
find_package(Protobuf REQUIRED)
if(PROTOBUF_FOUND)
message(STATUS "protobuf library found")
else()
message(FATAL_ERROR "protobuf library is needed but cant be found")
endif()
include_directories(
${Protobuf_INCLUDE_DIRS}
${CMAKE_CURRENT_BINARY_DIR}/..
)
message(STATUS "protobuf library includ: ${Protobuf_INCLUDE_DIRS}")
#Find required opncv package
set(OpenCV2_DIR /usr/share/OpenCV)
find_package(OpenCV REQUIRED)
include_directories(
${OpenCV_INCLUDE_DIRS}
${OpenCV_INCLUDE_DIRS}/opencv2
)
link_libraries( ${OpenCV_LIBS})
###########
## Build ##
###########
include_directories(
./include
${catkin_INCLUDE_DIRS}
${OpenCV_INCLUDE_DIRS}
)
add_executable(${PROJECT_NAME}_node ./src/bagParse.cpp ./include/test.pb.cc ./include/test2.pb.cc )
target_link_libraries(${PROJECT_NAME}_node
${catkin_LIBRARIES} ${PROTOBUF_LIBRARIES}
)
C++调试
未声明的引用是头文件引入错误,
未定义的引用是函数的实现没有引入。
python3
1.安装和使用:
1.安装protobuf ,安装完成后 protoc --version,如果将输出版本号
2.2.python安装protobuf,直接通过pip安装 pip3 install protobuf
3.根据协议生成python文件 protocol -I= --python_out
--python_out --python3_out
4.引入脚本,使用api
2.报错原因:
01.(unicode error) 'utf-8' codec can't d --Python版本问题
02.locale问题
3.说明
python2
SerializeToString(): serializes the message and returns it as a string. Note that the bytes are binary, not text; we only use the str type as a convenient container.
ParseFromString(data)
python3
序列化的时候,pyhont3 使用 protobuf3 的接口变了。
encode_to_bytes 替换了 SerializeToString
parse_from_bytes 替换了 ParseFromString
说明
ParseFromString是一种方法-它不返回任何内容,而是填充self已解析的内容
参考:
在 CMake 项目中使用 protobuf https://www.cnblogs.com/zzk0/p/15583430.html
rosbag遍历数据出错:(unicode error) 'utf-8' codec can't d https://www.apude.com/blog/15289.html
https://developers.google.com/protocol-buffers/docs/pythontutorial
【ROS】读写rosbag(c++) https://blog.csdn.net/yfy1127yfy/article/details/124345222
ROS(melodic)创建工作空间,功能包(Ubuntu18.04)https://blog.csdn.net/weixin_44858747/article/details/109479414
标签:std,ROS,解析,protobuf,INCLUDE,package,include,rosbag
From: https://www.cnblogs.com/ytwang/p/16911968.html