-
-
Save yfyf/0a5d98fe133dc87ad5573e1222b2eb93 to your computer and use it in GitHub Desktop.
#!/usr/bin/env python3 | |
# Adapted from: | |
# | |
# https://gist.github.com/mjcarroll/f620ef8d88efc3a03711259d6fc9a578 | |
# | |
# Original gist fixed to work with latest version of cartographer: | |
# | |
# [~/sensmetry/slam/cartographer:master]λ git describe --always | |
# bcd5486 | |
# [~/slam/cartographer_ros:master]λ git describe --always | |
# 1de03b3 | |
# | |
# Requirements: | |
# python3 | |
# protobuf==3.* | |
# | |
# Preprocessing: | |
# cd cartographer | |
# # rename directories starting with a number - python | |
# # can't import those in a straightforward way | |
# find . -name '[0-9]*' -type d -exec rename 's/2d/i2d/' {} \; | |
# find . -name '[0-9]*' -type d -exec rename 's/3d/i3d/' {} \; | |
# find . -iname '*.proto' -exec sed -i 's|/2d/|/i2d/|' {} \; | |
# find . -iname '*.proto' -exec sed -i 's|/3d/|/i3d/|' {} \; | |
# mkdir py_export | |
# protoc --python_out ./py_export -I . `find . -iname '*.proto'` | |
import struct | |
import gzip | |
import argparse | |
import cartographer.mapping | |
from cartographer.mapping.proto.serialization_pb2 import SerializationHeader, SerializedData | |
from cartographer.mapping.proto.pose_graph_pb2 import PoseGraph | |
class PbstreamFile: | |
def __init__(self, pbstream_filename): | |
self.pbstream_filename = pbstream_filename | |
self.pbstream_file = open(pbstream_filename, 'rb') | |
assert(self.is_valid()) | |
self.ser_data_by_type = {} | |
self.read_serialization_header() | |
while self.pbstream_file: | |
serdata = self.read_serialized_data() | |
if serdata: | |
serdata_type = serdata.WhichOneof('data') | |
data = getattr(serdata, serdata_type) | |
cur = self.ser_data_by_type.get(serdata_type, []) | |
cur.append(data) | |
self.ser_data_by_type[serdata_type] = cur | |
else: | |
break | |
def read_chunk(self): | |
sz = self.read_size() | |
if sz: | |
buf = self.pbstream_file.read(sz) | |
buf = gzip.decompress(buf) | |
return buf | |
def read_serialization_header(self): | |
buf = self.read_chunk() | |
if buf: | |
sh = SerializationHeader() | |
sh.ParseFromString(buf) | |
return sh | |
def read_serialized_data(self): | |
buf = self.read_chunk() | |
if buf: | |
sd = SerializedData() | |
sd.ParseFromString(buf) | |
return sd | |
def is_valid(self): | |
kMagic = [0x7b, 0x1d, 0x1f, 0x7b, 0x5b, 0xf5, 0x01, 0xdb] | |
self.pbstream_file.seek(0) | |
magic = self.pbstream_file.read(8) | |
return all([x == y for x, y in zip(kMagic[::-1], magic)]) | |
def read_size(self): | |
buf = self.pbstream_file.read(8) | |
if len(buf) < 8: | |
return 0 | |
return struct.unpack_from("<Q", buf)[0] | |
def pose_graph(self): | |
pose_graphs = self.ser_data_by_type['pose_graph'] | |
if pose_graphs: | |
if len(pose_graphs) > 1: | |
print("Warning: multiple pose graphs parsed in Serialized Data " | |
"but only one should be present. Returning the first one.") | |
return pose_graphs[0] | |
else: | |
return None | |
if __name__ == "__main__": | |
parser = argparse.ArgumentParser(description="Process and export live SLAM results") | |
parser.add_argument('pbstream_filename', type=str) | |
args = parser.parse_args() | |
pbf = PbstreamFile(args.pbstream_filename) | |
pg = pbf.pose_graph() | |
print(pg) |
Actually, not
it changes "serialized_pb", too
Need to be adapted.
This don't need anymore
from cartographer.mapping.proto.pose_graph_pb2 import PoseGraph
Hi @yfyf
Sorry for trouble, but I'm having problem with understanding of how this problem can be fixed and I hoped that you could know the answer.
I followed instruction you gave here and everything work fine on preparation stage but then I try to run this script I receive following error:
Traceback (most recent call last):
File "pbstreamreader.py", line 6, in
from cartographer.mapping.proto.serialization_pb2 import SerializationHeader, SerializedData
ModuleNotFoundError: No module named 'cartographer.mapping.proto.serialization_pb2'
For installation I used official guide and I'm trying to get trajectories from map my robot created, so I don't think that problem in cartographer itself. Appreciate any hints.
Thank you!
In my case, renaming files as
find . -iname '*.proto' -exec sed -i 's|/2d/|/i2d/|' {} \;
for some reason didn't work.So I changed last two commands to:
Might be helpful to others.