cartographer-project / cartographer

Cartographer is a system that provides real-time simultaneous localization and mapping (SLAM) in 2D and 3D across multiple platforms and sensor configurations.
Apache License 2.0
7.03k stars 2.24k forks source link

pbstream good() check #1861

Closed DavidBrandes closed 2 years ago

DavidBrandes commented 2 years ago

Hey everybody,

with the intention to alter the trajectory manually by myself (i.e. rotate it) I would like to create my own pbstream writer in python. However I am having issues with writing the output stream. I narrowed the problem down to how the new stream is written and saved in python. In the code example below I am trying to simply read an input pbstream and write it to a new output pbstream, so no (de)compression or (de)serialization is happening for now.

import struct

class ProtoStream:
    def __init__(self, input_pbstream_file, output_pbstream_file, header_size=8):
        self.header_size = header_size
        self.input_pbstream = open(input_pbstream_file, 'rb')
        self.output_pbstream = open(output_pbstream_file, 'wb')

    def copy(self):
        # read header
        self.input_pbstream.seek(self.header_size)
        header = self.read_message()

        # write header
        self.output_pbstream.seek(self.header_size)
        self.write_message(header)

        while True:
            # read other messages
            msg = self.read_message()

            if msg is None:
                break

            else:
                # write other messages
                self.write_message(msg)

        self.input_pbstream.close()

    def read_message(self):
        buf = self.input_pbstream.read(self.header_size)
        if len(buf) < self.header_size:
            return None

        else:
            size = struct.unpack_from("<Q", buf)[0]
            msg = self.input_pbstream.read(size)

            return msg

    def write_message(self, msg):
        self.output_pbstream.write(struct.pack('<Q', len(msg)))
        self.output_pbstream.write(msg)

input_pbstream_file = '/home/david/Desktop/proto/files/data.pbstream'
output_pbstream_file = '/home/david/Desktop/proto/files/new_data.pbstream'

PS = ProtoStream(input_pbstream_file, output_pbstream_file)
PS.copy()

The new pbstream is created with equal size to that of the input, however when I try to use it with Cartographer, I am getting the error message: 'protostream.cc:75 Check failed: in.good() Failed to open proto stream'. So I assume the problem lies somewhere in how the stream is written with python.

Does anyone know what exactly is triggering the good() check to fail and how to avoid it?

DavidBrandes commented 2 years ago

I could figure it out, if I leave out the seek() in both the writing and reading it now works. In particular if I use b'\xdb\x01\xf5[{\x1f\x1d{' as the header, Cartographer now accepts it