Skip to content

Commit

Permalink
Add convert verb (ros2#163)
Browse files Browse the repository at this point in the history
Signed-off-by: Marcel Zeilinger <marcel.zeilinger.fl@ait.ac.at>
  • Loading branch information
Marcel Zeilinger committed Mar 1, 2020
1 parent fafbe76 commit e7c7150
Show file tree
Hide file tree
Showing 8 changed files with 242 additions and 0 deletions.
71 changes: 71 additions & 0 deletions ros2bag/ros2bag/verb/convert.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
# Copyright 2018 Open Source Robotics Foundation, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import datetime
import os

from ros2bag.verb import VerbExtension


class ConvertVerb(VerbExtension):
"""ros2 bag convert."""

def add_arguments(self, parser, cli_name): # noqa: D102
parser.add_argument(
'bag_file', help='bag file to convert')
parser.add_argument(
'-o', '--output',
help='destination of the bagfile to create, \
defaults to a timestamped folder in the current directory')
parser.add_argument(
'-s', '--storage', default='sqlite3',
help='storage identifier to be used for the input bag, defaults to "sqlite3"')
parser.add_argument(
'--out-storage', default='sqlite3',
help='storage identifier to be used for the output bag, defaults to "sqlite3"')
parser.add_argument(
'-f', '--serialization-format', default='',
help='rmw serialization format in which the messages are saved, defaults to the'
' rmw currently in use')

def create_bag_directory(self, uri):
try:
os.makedirs(uri)
except OSError:
return "[ERROR] [ros2bag]: Could not create bag folder '{}'.".format(uri)

def main(self, *, args): # noqa: D102
bag_file = args.bag_file
if not os.path.exists(bag_file):
return "[ERROR] [ros2bag] bag file '{}' does not exist!".format(bag_file)

uri = args.output or datetime.datetime.now().strftime('rosbag2_%Y_%m_%d-%H_%M_%S')
self.create_bag_directory(uri)

# NOTE(hidmic): in merged install workspaces on Windows, Python entrypoint lookups
# combined with constrained environments (as imposed by colcon test)
# may result in DLL loading failures when attempting to import a C
# extension. Therefore, do not import rosbag2_transport at the module
# level but on demand, right before first use.
from rosbag2_transport import rosbag2_transport_py

rosbag2_transport_py.convert(
in_uri=bag_file,
in_storage_id=args.storage,
out_uri=uri,
out_storage_id=args.out_storage,
serialization_format=args.serialization_format)

if os.path.isdir(uri) and not os.listdir(uri):
os.rmdir(uri)
1 change: 1 addition & 0 deletions ros2bag/setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
'info = ros2bag.verb.info:InfoVerb',
'play = ros2bag.verb.play:PlayVerb',
'record = ros2bag.verb.record:RecordVerb',
'convert = ros2bag.verb.convert:ConvertVerb',
],
}
)
1 change: 1 addition & 0 deletions rosbag2_transport/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ find_package(rosbag2_cpp REQUIRED)
find_package(shared_queues_vendor REQUIRED)

add_library(${PROJECT_NAME} SHARED
src/rosbag2_transport/converter.cpp
src/rosbag2_transport/player.cpp
src/rosbag2_transport/formatter.cpp
src/rosbag2_transport/generic_publisher.cpp
Expand Down
12 changes: 12 additions & 0 deletions rosbag2_transport/include/rosbag2_transport/rosbag2_transport.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,18 @@ class Rosbag2Transport
ROSBAG2_TRANSPORT_PUBLIC
void play(const StorageOptions & storage_options, const PlayOptions & play_options);

/**
* Convert a bagfile from one storage to another.
*
* \param input_storage_options Options regarding the input storage (e.g. input bag file name)
* \param output_storage_options Options regarding the output storage (e.g. bag file name)
*/
ROSBAG2_TRANSPORT_PUBLIC
void convert(
const StorageOptions & input_storage_options,
const StorageOptions & output_storage_options,
std::string output_serialization_format);

/**
* Print the bag info contained in the metadata yaml file.
*
Expand Down
40 changes: 40 additions & 0 deletions rosbag2_transport/src/rosbag2_transport/converter.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// Copyright 2018 Open Source Robotics Foundation, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "converter.hpp"

#include "rosbag2_cpp/reader.hpp"
#include "rosbag2_cpp/writer.hpp"
#include "rosbag2_transport/logging.hpp"

namespace rosbag2_transport
{
Converter::Converter(
std::shared_ptr<rosbag2_cpp::Reader> reader,
std::shared_ptr<rosbag2_cpp::Writer> writer)
: reader_(std::move(reader)), writer_(std::move(writer)) {}

void Converter::convert(std::string serialization_format)
{
for (auto topic : reader_->get_all_topics_and_types()) {
topic.serialization_format = serialization_format;
writer_->create_topic(topic);
}
while (reader_->has_next()) {
auto msg = reader_->read_next();
writer_->write(msg);
}
}

} // namespace rosbag2_transport
56 changes: 56 additions & 0 deletions rosbag2_transport/src/rosbag2_transport/converter.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
// Copyright 2018 Open Source Robotics Foundation, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#ifndef ROSBAG2_TRANSPORT__CONVERTER_HPP_
#define ROSBAG2_TRANSPORT__CONVERTER_HPP_

#include <future>
#include <memory>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <utility>
#include <vector>

#include "rosbag2_cpp/types.hpp"
#include "rosbag2_cpp/reader.hpp"
#include "rosbag2_cpp/writer.hpp"
#include "rosbag2_transport/storage_options.hpp"

namespace rosbag2
{
class Writer;
class Reader;
}

namespace rosbag2_transport
{

class Converter
{
public:
explicit Converter(
std::shared_ptr<rosbag2_cpp::Reader> reader,
std::shared_ptr<rosbag2_cpp::Writer> writer);

void convert(std::string serialization_format);

private:
std::shared_ptr<rosbag2_cpp::Reader> reader_;
std::shared_ptr<rosbag2_cpp::Writer> writer_;
};

} // namespace rosbag2_transport

#endif // ROSBAG2_TRANSPORT__CONVERTER_HPP_
19 changes: 19 additions & 0 deletions rosbag2_transport/src/rosbag2_transport/rosbag2_transport.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@

#include "rosbag2_transport/logging.hpp"

#include "converter.hpp"
#include "formatter.hpp"
#include "player.hpp"
#include "recorder.hpp"
Expand Down Expand Up @@ -104,6 +105,24 @@ void Rosbag2Transport::play(
}
}

void Rosbag2Transport::convert(
const StorageOptions & input_storage_options,
const StorageOptions & output_storage_options,
std::string output_serialization_format)
{
try {
reader_->open(input_storage_options, {"", output_serialization_format});
writer_->open(
output_storage_options,
{output_serialization_format, output_serialization_format});

Converter converter(reader_, writer_);
converter.convert(output_serialization_format);
} catch (std::runtime_error & e) {
ROSBAG2_TRANSPORT_LOG_ERROR("Failed to convert: %s", e.what());
}
}

void Rosbag2Transport::print_bag_info(const std::string & uri, const std::string & storage_id)
{
rosbag2_storage::BagMetadata metadata;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,43 @@ rosbag2_transport_info(PyObject * Py_UNUSED(self), PyObject * args, PyObject * k
Py_RETURN_NONE;
}

static PyObject *
rosbag2_transport_convert(PyObject * Py_UNUSED(self), PyObject * args, PyObject * kwargs)
{
rosbag2_transport::StorageOptions in_options{};
rosbag2_transport::StorageOptions out_options{};
static const char * kwlist[] = {"in_uri", "in_storage_id", "out_uri", "out_storage_id", "serialization_format", nullptr};

char * in_uri;
char * in_storage_id;
char * out_uri;
char * out_storage_id;
char * serialization_format;
if (!PyArg_ParseTupleAndKeywords(
args, kwargs, "sssss", const_cast<char **>(kwlist), &in_uri, &in_storage_id,
&out_uri,
&out_storage_id,
&serialization_format))
{
return nullptr;
}

in_options.uri = std::string(in_uri);
in_options.storage_id = std::string(in_storage_id);

out_options.uri = std::string(out_uri);
out_options.storage_id = std::string(out_storage_id);

std::string rmw_serialization_format = std::string(serialization_format).empty() ?
rmw_get_serialization_format() :
serialization_format;

rosbag2_transport::Rosbag2Transport transport;
transport.convert(in_options, out_options, rmw_serialization_format);

Py_RETURN_NONE;
}

/// Define the public methods of this module
#if __GNUC__ >= 8
# pragma GCC diagnostic push
Expand All @@ -238,6 +275,11 @@ static PyMethodDef rosbag2_transport_methods[] = {
"info", reinterpret_cast<PyCFunction>(rosbag2_transport_info), METH_VARARGS | METH_KEYWORDS,
"Print bag info"
},
{
"convert", reinterpret_cast<PyCFunction>(rosbag2_transport_convert),
METH_VARARGS | METH_KEYWORDS,
"Convert bag storage"
},
{nullptr, nullptr, 0, nullptr} /* sentinel */
};
#if __GNUC__ >= 8
Expand Down

0 comments on commit e7c7150

Please sign in to comment.