读写pbstream文件

保存文件

Node::SerializeState —— MapBuilder::SerializeState —— MapBuilder::SerializeState —— cartographer\io\internal\mapping_state_serialization.cc文件中的WritePbStream函数

实际是MapBuilderBridge::SerializeStateNode::HandleWriteState调用的也是这个函数。在最新版本里是bool MapBuilderBridge::SerializeState(const std::string& filename, const bool include_unfinished_submaps);

1
2
3
cartographer::io::ProtoStreamWriter writer(filename);
map_builder_->SerializeState(&writer);
return writer.Close();

然后是
1
2
3
4
5
6
void MapBuilder::SerializeState(bool include_unfinished_submaps,
io::ProtoStreamWriterInterface* const writer)
{
io::WritePbStream(*pose_graph_, all_trajectory_builder_options_, writer,
include_unfinished_submaps);
}

proto_stream.cc包含ProtoStreamWriterProtoStreamReader两个类,这里用的是类ProtoStreamWriter,在它的构造函数里以二进制方式,写入8个字节的魔术数以确定proto stream格式,

WritePbStream如下,这里的writer就是类ProtoStreamWriter

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
void WritePbStream(
const mapping::PoseGraph& pose_graph,
const std::vector<mapping::proto::TrajectoryBuilderOptionsWithSensorIds>&
trajectory_builder_options,
ProtoStreamWriterInterface* const writer, bool include_unfinished_submaps)
{
writer->WriteProto(CreateHeader());
writer->WriteProto(
SerializePoseGraph(pose_graph, include_unfinished_submaps));
writer->WriteProto(SerializeTrajectoryBuilderOptions(
trajectory_builder_options,
GetValidTrajectoryIds(pose_graph.GetTrajectoryStates())));

SerializeSubmaps(pose_graph.GetAllSubmapData(), include_unfinished_submaps,
writer);
SerializeTrajectoryNodes(pose_graph.GetTrajectoryNodes(), writer);
SerializeTrajectoryData(pose_graph.GetTrajectoryData(), writer);
SerializeImuData(pose_graph.GetImuData(), writer);
SerializeOdometryData(pose_graph.GetOdometryData(), writer);
SerializeFixedFramePoseData(pose_graph.GetFixedFramePoseData(), writer);
SerializeLandmarkNodes(pose_graph.GetLandmarkNodes(), writer);
}

保存的是子图、轨迹节点、轨迹数据、IMU数据、里程计、Landmark等等

ProtoStreamWriter保存数据时用到了common::FastGzipString函数,实质是boost::iostreams::gzip_compressor

读pbstream文件

这个就参考纯定位流程,Node::LoadState —— MapBuilderBridge::LoadState —— MapBuilder::LoadState

MapBuilderBridge::LoadState(const std::string& state_filename, bool load_frozen_state)使用ProtoStreamReader

1
2
cartographer::io::ProtoStreamReader stream(state_filename);
map_builder_->LoadState(&stream, load_frozen_state);

到了MapBuilder::LoadState,可以看出如果只是读pbstream文件,不需要实例化map_builder,除去加载数据到后端,把函数里的大部分内容提取出来即可,主要是类型io::ProtoStreamDeserializerproto::PoseGraph等等。

另外可以参考pbstream_main.cc