Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

rosbag2_py reader and writer #308

Merged
merged 55 commits into from
Aug 13, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
55 commits
Select commit Hold shift + click to select a range
f5de2f8
Initialize new package rosbag2_py
jacobperron Jan 4, 2020
2eb3e22
Proof-of-concept implementation using pybind11
jacobperron Jan 9, 2020
66dbd3c
pybind StorageOptions and ConverterOptions; linter fixes
mabelzhang Jan 16, 2020
acabf6a
return timestamp
mabelzhang Jan 16, 2020
e571154
simplify binding of structs
mabelzhang Jan 29, 2020
6deb1da
pybind TopicMetadata
mabelzhang Jan 29, 2020
68b6b46
namespace rosbag2 -> rosbag2_cpp
mabelzhang Mar 3, 2020
a0ce1d8
small fixes
mabelzhang Mar 11, 2020
b144bc3
Merge branch 'master' into rosbag2_py
mabelzhang Mar 11, 2020
31f245e
Merge remote-tracking branch 'upstream/master' into rosbag2_py
mabelzhang Mar 31, 2020
54799a9
initial pytests
mabelzhang Apr 3, 2020
c99d7f4
Merge remote-tracking branch 'upstream/master' into rosbag2_py
mabelzhang Apr 3, 2020
f8c4391
wrap Reader instead of SequentialReader
mabelzhang Apr 3, 2020
e9da5f6
small fixes for PR comments
mabelzhang Apr 3, 2020
d63eece
Merge remote-tracking branch 'upstream/master' into rosbag2_py
mabelzhang Apr 16, 2020
2aff04b
change workflow to autotest feature branch
mabelzhang Apr 30, 2020
668a988
revert workflow
mabelzhang Apr 30, 2020
8b3f3d7
Merge remote-tracking branch 'upstream/master'
mabelzhang May 13, 2020
5767a61
Merge remote-tracking branch 'upstream/master'
mabelzhang May 16, 2020
58b24c5
Merge remote-tracking branch 'upstream/master'
mabelzhang May 19, 2020
2da411b
Merge remote-tracking branch 'upstream/master'
mabelzhang May 21, 2020
7eed626
added writer and writer tests
klintan Jun 15, 2020
e9c9262
fix test path setup
mabelzhang Jun 16, 2020
449a939
fix and make more rigorous writer test
mabelzhang Jun 16, 2020
562d2dd
wrapper and test for topic filter
mabelzhang Jun 17, 2020
d261c63
linters. change pybind package
mabelzhang Jun 26, 2020
ab426d9
simplify verbose import
mabelzhang Jul 1, 2020
133e1a4
tidy up
mabelzhang Jul 16, 2020
edcf24a
Merge branch 'master' into rosbag2_py
mabelzhang Jul 17, 2020
ec64c99
Merge remote-tracking branch 'upstream/master' into rosbag2_py
mabelzhang Jul 21, 2020
08db02f
explicit subclasses of Reader and Writer
mabelzhang Jul 21, 2020
089306a
Use template specialization instead of inheritence
jacobperron Jul 22, 2020
1798096
Remove temporary variable
jacobperron Jul 22, 2020
363059b
Remove unused member variable
jacobperron Jul 22, 2020
9394844
Move to initializer list
jacobperron Jul 22, 2020
41973ea
Merge pull request #2 from jacobperron/template_refactor
mabelzhang Jul 22, 2020
54f6722
refactor into reader writer storage
mabelzhang Jul 22, 2020
b845790
cleanup includes
mabelzhang Jul 24, 2020
be62274
switch back to pybind11_vendor
mabelzhang Jul 25, 2020
295ee66
Packages dependency for CI
mabelzhang Jul 28, 2020
825250c
Merge remote-tracking branch 'upstream/master' into rosbag2_py
mabelzhang Jul 28, 2020
8f62f46
printout to debug CI test failure
mabelzhang Jul 28, 2020
ff11f99
use tempfile for writer test, add exec_depend
mabelzhang Jul 28, 2020
d86ebf4
remove exec_depend
mabelzhang Jul 28, 2020
9ee167e
Merge remote-tracking branch 'upstream/master' into rosbag2_py
mabelzhang Jul 29, 2020
76e3850
use pytest fixture tmp_path; add rosbag2_py to rosbag2
mabelzhang Jul 29, 2020
ab16d49
add makedirs back to see CI result
mabelzhang Jul 29, 2020
ebf3a01
fix import error
mabelzhang Jul 29, 2020
a6774c7
cleanup
mabelzhang Jul 29, 2020
020caa8
add modules explicitly for windows CI
mabelzhang Jul 29, 2020
0e551ff
cleanup
mabelzhang Jul 30, 2020
c9cd71e
try more <test_depend>s for mac test failure
mabelzhang Aug 1, 2020
0603d27
wrap structs with named arguments for Python keyword params
mabelzhang Aug 5, 2020
ddbbdf7
add pytest.ini
mabelzhang Aug 5, 2020
31a2551
add rosbag db3-shm and db3-wal files for macOS test
mabelzhang Aug 11, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions rosbag2/package.xml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
<exec_depend>rosbag2_compression</exec_depend>
<exec_depend>rosbag2_converter_default_plugins</exec_depend>
<exec_depend>rosbag2_cpp</exec_depend>
<exec_depend>rosbag2_py</exec_depend>
<exec_depend>rosbag2_storage</exec_depend>
<exec_depend>rosbag2_storage_default_plugins</exec_depend>
<exec_depend>rosbag2_transport</exec_depend>
Expand Down
88 changes: 88 additions & 0 deletions rosbag2_py/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
cmake_minimum_required(VERSION 3.5)
project(rosbag2_py)

# Default to C99
if(NOT CMAKE_C_STANDARD)
set(CMAKE_C_STANDARD 99)
endif()

# Default to C++14
if(NOT CMAKE_CXX_STANDARD)
set(CMAKE_CXX_STANDARD 14)
endif()

if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
add_compile_options(-Wall -Wextra -Wpedantic -Werror)
endif()

find_package(ament_cmake REQUIRED)
find_package(ament_cmake_ros REQUIRED)
find_package(pybind11 REQUIRED)
piraka9011 marked this conversation as resolved.
Show resolved Hide resolved
find_package(python_cmake_module REQUIRED)
find_package(rosbag2_compression REQUIRED)
find_package(rosbag2_cpp REQUIRED)
find_package(rosbag2_storage REQUIRED)

ament_python_install_package(${PROJECT_NAME})

pybind11_add_module(_reader SHARED
src/rosbag2_py/_reader.cpp
)
ament_target_dependencies(_reader PUBLIC
"rosbag2_compression"
"rosbag2_cpp"
)

pybind11_add_module(_storage SHARED
src/rosbag2_py/_storage.cpp
)
ament_target_dependencies(_storage PUBLIC
"rosbag2_cpp"
"rosbag2_storage"
)

pybind11_add_module(_writer SHARED
src/rosbag2_py/_writer.cpp
)
ament_target_dependencies(_writer PUBLIC
"rosbag2_compression"
"rosbag2_cpp"
)

# Install cython modules as sub-modules of the project
install(
TARGETS
_reader
_storage
_writer
DESTINATION "${PYTHON_INSTALL_DIR}/${PROJECT_NAME}"
)

if(BUILD_TESTING)
find_package(ament_lint_auto REQUIRED)
ament_lint_auto_find_test_dependencies()
find_package(ament_cmake_pytest REQUIRED)

set(_PYTHON_EXECUTABLE "${PYTHON_EXECUTABLE}")
if(WIN32 AND "${CMAKE_BUILD_TYPE}" STREQUAL "Debug")
set(_PYTHON_EXECUTABLE "${PYTHON_EXECUTABLE_DEBUG}")
endif()
set(pythonpath "${CMAKE_CURRENT_BINARY_DIR}/rosbag2_py;${CMAKE_CURRENT_SOURCE_DIR}")
if(NOT WIN32)
string(REPLACE ";" ":" pythonpath "${pythonpath}")
endif()
mabelzhang marked this conversation as resolved.
Show resolved Hide resolved
ament_add_pytest_test(test_sequential_reader_py "test/test_sequential_reader.py"
PYTHON_EXECUTABLE "${_PYTHON_EXECUTABLE}"
APPEND_ENV "PYTHONPATH=${pythonpath}"
APPEND_LIBRARY_DIRS "${_append_library_dirs}"
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/resources"
)
ament_add_pytest_test(test_sequential_writer_py "test/test_sequential_writer.py"
PYTHON_EXECUTABLE "${_PYTHON_EXECUTABLE}"
APPEND_ENV "PYTHONPATH=${pythonpath}"
APPEND_LIBRARY_DIRS "${_append_library_dirs}"
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/resources"
)
endif()

ament_package()
38 changes: 38 additions & 0 deletions rosbag2_py/package.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<?xml version="1.0"?>
<?xml-model href="http://download.ros.org/schema/package_format3.xsd" schematypens="http://www.w3.org/2001/XMLSchema"?>
<package format="3">
<name>rosbag2_py</name>
<version>0.2.4</version>
<description>Python API for rosbag2</description>
<maintainer email="jacob@openrobotics.org">Jacob Perron</maintainer>
piraka9011 marked this conversation as resolved.
Show resolved Hide resolved
<maintainer email="ros-tooling@googlegroups.com">ROS Tooling Working Group</maintainer>
<license>Apache License 2.0</license>

jacobperron marked this conversation as resolved.
Show resolved Hide resolved
<author email="mabel@openrobotics.org">Mabel Zhang</author>

<buildtool_depend>ament_cmake_ros</buildtool_depend>

<depend>pybind11_vendor</depend>
jacobperron marked this conversation as resolved.
Show resolved Hide resolved
<depend>python_cmake_module</depend>
<depend>rosbag2_compression</depend>
<depend>rosbag2_cpp</depend>
<depend>rosbag2_storage</depend>

<exec_depend>rpyutils</exec_depend>

<test_depend>ament_lint_auto</test_depend>
<test_depend>ament_lint_common</test_depend>
<test_depend>python3-pytest</test_depend>
<test_depend>rcl_interfaces</test_depend>
<test_depend>rclpy</test_depend>
<test_depend>rosbag2_converter_default_plugins</test_depend>
<test_depend>rosbag2_storage_default_plugins</test_depend>
<test_depend>rosbag2_storage</test_depend>
<test_depend>rosidl_runtime_py</test_depend>
<test_depend>rpyutils</test_depend>
<test_depend>std_msgs</test_depend>

<export>
<build_type>ament_cmake</build_type>
</export>
</package>
2 changes: 2 additions & 0 deletions rosbag2_py/pytest.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[pytest]
junit_family=xunit2
31 changes: 31 additions & 0 deletions rosbag2_py/resources/talker/metadata.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
rosbag2_bagfile_information:
version: 4
storage_identifier: sqlite3
relative_file_paths:
- talker.db3
duration:
nanoseconds: 4531096768
starting_time:
nanoseconds_since_epoch: 1585866235112411371
message_count: 20
topics_with_message_count:
- topic_metadata:
name: /topic
type: std_msgs/msg/String
serialization_format: cdr
offered_qos_profiles: "- history: 3\n depth: 0\n reliability: 1\n durability: 2\n deadline:\n sec: 2147483647\n nsec: 4294967295\n lifespan:\n sec: 2147483647\n nsec: 4294967295\n liveliness: 1\n liveliness_lease_duration:\n sec: 2147483647\n nsec: 4294967295\n avoid_ros_namespace_conventions: false"
message_count: 10
- topic_metadata:
name: /rosout
type: rcl_interfaces/msg/Log
serialization_format: cdr
offered_qos_profiles: "- history: 3\n depth: 0\n reliability: 1\n durability: 1\n deadline:\n sec: 2147483647\n nsec: 4294967295\n lifespan:\n sec: 10\n nsec: 0\n liveliness: 1\n liveliness_lease_duration:\n sec: 2147483647\n nsec: 4294967295\n avoid_ros_namespace_conventions: false"
message_count: 10
- topic_metadata:
name: /parameter_events
type: rcl_interfaces/msg/ParameterEvent
serialization_format: cdr
offered_qos_profiles: "- history: 3\n depth: 0\n reliability: 1\n durability: 2\n deadline:\n sec: 2147483647\n nsec: 4294967295\n lifespan:\n sec: 2147483647\n nsec: 4294967295\n liveliness: 1\n liveliness_lease_duration:\n sec: 2147483647\n nsec: 4294967295\n avoid_ros_namespace_conventions: false"
message_count: 0
compression_format: ""
compression_mode: ""
Binary file added rosbag2_py/resources/talker/talker.db3
Binary file not shown.
Binary file added rosbag2_py/resources/talker/talker.db3-shm
Binary file not shown.
Empty file.
42 changes: 42 additions & 0 deletions rosbag2_py/rosbag2_py/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# Copyright 2020 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.

from rpyutils import add_dll_directories_from_env

# Since Python 3.8, on Windows we should ensure DLL directories are explicitly added
# to the search path.
# See https://docs.python.org/3/whatsnew/3.8.html#bpo-36085-whatsnew
with add_dll_directories_from_env('PATH'):
from rosbag2_py._reader import \
SequentialCompressionReader, \
SequentialReader
from rosbag2_py._storage import \
ConverterOptions, \
StorageFilter, \
StorageOptions, \
TopicMetadata
from rosbag2_py._writer import \
SequentialCompressionWriter, \
SequentialWriter

__all__ = [
'ConverterOptions',
'SequentialCompressionReader',
'SequentialCompressionWriter',
'SequentialReader',
'SequentialWriter',
'StorageFilter',
'StorageOptions',
'TopicMetadata',
]
120 changes: 120 additions & 0 deletions rosbag2_py/src/rosbag2_py/_reader.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
// Copyright 2020 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 <pybind11/pybind11.h>
#include <pybind11/stl.h>

#include <memory>
#include <string>
#include <vector>

#include "rosbag2_compression/sequential_compression_reader.hpp"
#include "rosbag2_cpp/converter_options.hpp"
#include "rosbag2_cpp/readers/sequential_reader.hpp"
#include "rosbag2_cpp/reader.hpp"
#include "rosbag2_cpp/storage_options.hpp"
#include "rosbag2_storage/storage_filter.hpp"
#include "rosbag2_storage/topic_metadata.hpp"

namespace rosbag2_py
{

template<typename T>
class Reader
{
public:
Reader()
: reader_(std::make_unique<rosbag2_cpp::Reader>(std::make_unique<T>()))
{
}

void open(
rosbag2_cpp::StorageOptions & storage_options,
rosbag2_cpp::ConverterOptions & converter_options)
{
reader_->open(storage_options, converter_options);
}

bool has_next()
{
return reader_->has_next();
}

/// Return a tuple containing the topic name, the serialized ROS message, and
/// the timestamp.
pybind11::tuple read_next()
{
const auto next = reader_->read_next();
rcutils_uint8_array_t rcutils_data = *next->serialized_data.get();
std::string serialized_data(rcutils_data.buffer,
rcutils_data.buffer + rcutils_data.buffer_length);
return pybind11::make_tuple(
next->topic_name, pybind11::bytes(serialized_data), next->time_stamp);
}

/// Return a mapping from topic name to topic type.
std::vector<rosbag2_storage::TopicMetadata> get_all_topics_and_types()
{
return reader_->get_all_topics_and_types();
}

void set_filter(const rosbag2_storage::StorageFilter & storage_filter)
{
return reader_->set_filter(storage_filter);
}

void reset_filter()
{
reader_->reset_filter();
}

protected:
std::unique_ptr<rosbag2_cpp::Reader> reader_;
};
} // namespace rosbag2_py

PYBIND11_MODULE(_reader, m) {
m.doc() = "Python wrapper of the rosbag2_cpp reader API";

pybind11::class_<rosbag2_py::Reader<rosbag2_cpp::readers::SequentialReader>>(
m, "SequentialReader")
.def(pybind11::init())
.def("open", &rosbag2_py::Reader<rosbag2_cpp::readers::SequentialReader>::open)
.def("read_next", &rosbag2_py::Reader<rosbag2_cpp::readers::SequentialReader>::read_next)
.def("has_next", &rosbag2_py::Reader<rosbag2_cpp::readers::SequentialReader>::has_next)
.def(
"get_all_topics_and_types",
&rosbag2_py::Reader<rosbag2_cpp::readers::SequentialReader>::get_all_topics_and_types)
.def("set_filter", &rosbag2_py::Reader<rosbag2_cpp::readers::SequentialReader>::set_filter)
.def("reset_filter", &rosbag2_py::Reader<rosbag2_cpp::readers::SequentialReader>::reset_filter);

pybind11::class_<rosbag2_py::Reader<rosbag2_compression::SequentialCompressionReader>>(
m, "SequentialCompressionReader")
.def(pybind11::init())
.def("open", &rosbag2_py::Reader<rosbag2_compression::SequentialCompressionReader>::open)
.def(
"read_next", &rosbag2_py::Reader<rosbag2_compression::SequentialCompressionReader>::read_next)
.def("has_next", &rosbag2_py::Reader<rosbag2_compression::SequentialCompressionReader>::has_next)
.def(
"get_all_topics_and_types",
&rosbag2_py::Reader<
rosbag2_compression::SequentialCompressionReader
>::get_all_topics_and_types)
.def(
"set_filter",
&rosbag2_py::Reader<rosbag2_compression::SequentialCompressionReader>::set_filter)
.def(
"reset_filter",
&rosbag2_py::Reader<rosbag2_compression::SequentialCompressionReader>::reset_filter);
}
Loading