Skip to content

Commit fbb08d0

Browse files
Add bindings for LocalMessageDefinitionSource (#1697)
* Add bindings for LocalMessageDefinitionSource Signed-off-by: methylDragon <[email protected]> * Fix pyi interface definitions Signed-off-by: methylDragon <[email protected]> * Update rosbag2_py/src/rosbag2_py/_message_definitions.cpp Co-authored-by: Michael Orlov <[email protected]> Signed-off-by: methylDragon <[email protected]> --------- Signed-off-by: methylDragon <[email protected]> Co-authored-by: Michael Orlov <[email protected]>
1 parent 0f216c8 commit fbb08d0

7 files changed

+198
-0
lines changed

rosbag2_py/CMakeLists.txt

+14
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,13 @@ target_link_libraries(_compression_options PUBLIC
4848
rosbag2_compression::rosbag2_compression
4949
)
5050

51+
pybind11_add_module(_message_definitions SHARED
52+
src/rosbag2_py/_message_definitions.cpp
53+
)
54+
target_link_libraries(_message_definitions PUBLIC
55+
rosbag2_cpp::rosbag2_cpp
56+
)
57+
5158
pybind11_add_module(_reader SHARED
5259
src/rosbag2_py/_reader.cpp
5360
)
@@ -107,6 +114,7 @@ target_link_libraries(_reindexer PUBLIC
107114
install(
108115
TARGETS
109116
_compression_options
117+
_message_definitions
110118
_reader
111119
_storage
112120
_writer
@@ -120,6 +128,7 @@ if(BUILD_TESTING)
120128
find_package(ament_lint_auto REQUIRED)
121129
ament_lint_auto_find_test_dependencies()
122130
find_package(ament_cmake_pytest REQUIRED)
131+
find_package(rosbag2_test_msgdefs REQUIRED)
123132

124133
set(append_env_vars "PYTHONPATH=${CMAKE_CURRENT_SOURCE_DIR}")
125134
set(set_env_vars "ROSBAG2_PY_TEST_RESOURCES_DIR=${CMAKE_CURRENT_SOURCE_DIR}/test/resources")
@@ -169,6 +178,11 @@ if(BUILD_TESTING)
169178
APPEND_ENV "${append_env_vars}"
170179
ENV "${set_env_vars}"
171180
)
181+
ament_add_pytest_test(test_message_definitions_py
182+
"test/test_message_definitions.py"
183+
APPEND_ENV "${append_env_vars}"
184+
ENV "${set_env_vars}"
185+
)
172186
endif()
173187

174188
ament_package()

rosbag2_py/package.xml

+1
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
<test_depend>rosbag2_test_common</test_depend>
3737
<test_depend>rosidl_runtime_py</test_depend>
3838
<test_depend>std_msgs</test_depend>
39+
<test_depend>rosbag2_test_msgdefs</test_depend>
3940

4041
<export>
4142
<build_type>ament_cmake</build_type>

rosbag2_py/rosbag2_py/__init__.py

+4
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,9 @@
2424
compression_mode_from_string,
2525
compression_mode_to_string
2626
)
27+
from rosbag2_py._message_definitions import (
28+
LocalMessageDefinitionSource,
29+
)
2730
from rosbag2_py._reader import (
2831
SequentialCompressionReader,
2932
SequentialReader,
@@ -100,4 +103,5 @@
100103
'ServiceRequestsSource',
101104
'Recorder',
102105
'RecordOptions',
106+
'LocalMessageDefinitionSource',
103107
]

rosbag2_py/rosbag2_py/__init__.pyi

+1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
from rosbag2_py._compression_options import CompressionMode as CompressionMode, CompressionOptions as CompressionOptions, compression_mode_from_string as compression_mode_from_string, compression_mode_to_string as compression_mode_to_string
22
from rosbag2_py._info import Info as Info
3+
from rosbag2_py._message_definitions import LocalMessageDefinitionSource as LocalMessageDefinitionSource
34
from rosbag2_py._reader import SequentialCompressionReader as SequentialCompressionReader, SequentialReader as SequentialReader, get_registered_readers as get_registered_readers
45
from rosbag2_py._reindexer import Reindexer as Reindexer
56
from rosbag2_py._storage import BagMetadata as BagMetadata, ConverterOptions as ConverterOptions, FileInformation as FileInformation, MessageDefinition as MessageDefinition, MetadataIo as MetadataIo, ReadOrder as ReadOrder, ReadOrderSortBy as ReadOrderSortBy, StorageFilter as StorageFilter, StorageOptions as StorageOptions, TopicInformation as TopicInformation, TopicMetadata as TopicMetadata, get_default_storage_id as get_default_storage_id, to_rclcpp_qos_vector as to_rclcpp_qos_vector
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
from typing import Any
2+
3+
class LocalMessageDefinitionSource:
4+
def __init__(self) -> None: ...
5+
def get_full_text(self, *args, **kwargs) -> Any: ...
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
// Copyright 2024 Intrinsic Innovation LLC. All rights reserved.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
#include "rosbag2_cpp/message_definitions/local_message_definition_source.hpp"
16+
17+
#include "./pybind11.hpp"
18+
19+
PYBIND11_MODULE(_message_definitions, m) {
20+
m.doc() = "Python wrapper of the rosbag2_cpp message definitions API";
21+
22+
pybind11::class_<rosbag2_cpp::LocalMessageDefinitionSource>(
23+
m, "LocalMessageDefinitionSource")
24+
.def(pybind11::init<>())
25+
.def(
26+
"get_full_text", &rosbag2_cpp::LocalMessageDefinitionSource::get_full_text);
27+
}
+146
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
# Copyright 2024 Intrinsic Innovation LLC. All rights reserved.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
from rosbag2_py import LocalMessageDefinitionSource
16+
17+
18+
def test_local_message_definition_source_no_crash_on_bad_name():
19+
source = LocalMessageDefinitionSource()
20+
result = source.get_full_text('some_pkg')
21+
assert result.encoding == 'unknown'
22+
assert result.encoded_message_definition == ''
23+
assert result.topic_type == 'some_pkg'
24+
25+
26+
def test_local_message_definition_source_can_find_msg_deps():
27+
source = LocalMessageDefinitionSource()
28+
result = source.get_full_text('rosbag2_test_msgdefs/ComplexMsg')
29+
assert result.encoding == 'ros2msg'
30+
assert result.encoded_message_definition == (
31+
'rosbag2_test_msgdefs/BasicMsg b\n'
32+
'\n'
33+
'================================================================================\n'
34+
'MSG: rosbag2_test_msgdefs/BasicMsg\n'
35+
'float32 c\n'
36+
)
37+
38+
39+
def test_local_message_definition_source_can_find_srv_deps_in_msg():
40+
source = LocalMessageDefinitionSource()
41+
result = source.get_full_text('rosbag2_test_msgdefs/srv/ComplexSrvMsg')
42+
assert result.encoding == 'ros2msg'
43+
assert result.topic_type == 'rosbag2_test_msgdefs/srv/ComplexSrvMsg'
44+
assert result.encoded_message_definition == (
45+
'================================================================================\n'
46+
'SRV: rosbag2_test_msgdefs/srv/ComplexSrvMsg\n'
47+
'rosbag2_test_msgdefs/BasicMsg req\n'
48+
'---\n'
49+
'rosbag2_test_msgdefs/BasicMsg resp\n'
50+
'\n'
51+
'================================================================================\n'
52+
'MSG: rosbag2_test_msgdefs/BasicMsg\n'
53+
'float32 c\n'
54+
)
55+
56+
57+
def test_local_message_definition_source_can_find_srv_deps_in_idl():
58+
source = LocalMessageDefinitionSource()
59+
result = source.get_full_text('rosbag2_test_msgdefs/srv/ComplexSrvIdl')
60+
assert result.encoding == 'ros2idl'
61+
assert result.topic_type == 'rosbag2_test_msgdefs/srv/ComplexSrvIdl'
62+
assert result.encoded_message_definition == (
63+
'================================================================================\n'
64+
'SRV: rosbag2_test_msgdefs/srv/ComplexSrvIdl\n'
65+
'rosbag2_test_msgdefs/BasicIdl req\n'
66+
'---\n'
67+
'rosbag2_test_msgdefs/BasicIdl resp\n'
68+
'\n'
69+
'================================================================================\n'
70+
'MSG: rosbag2_test_msgdefs/BasicIdl\n'
71+
'\n'
72+
'================================================================================\n'
73+
'IDL: rosbag2_test_msgdefs/BasicIdl\n'
74+
'module rosbag2_test_msgdefs {\n'
75+
' module msg {\n'
76+
' struct BasicIdl {\n'
77+
' float x;\n'
78+
' };\n'
79+
' };\n'
80+
'};\n'
81+
)
82+
83+
84+
def test_local_message_definition_source_can_find_idl_deps():
85+
source = LocalMessageDefinitionSource()
86+
result = source.get_full_text('rosbag2_test_msgdefs/msg/ComplexIdl')
87+
assert result.encoding == 'ros2idl'
88+
assert result.topic_type == 'rosbag2_test_msgdefs/msg/ComplexIdl'
89+
assert result.encoded_message_definition == (
90+
'================================================================================\n'
91+
'IDL: rosbag2_test_msgdefs/msg/ComplexIdl\n'
92+
'#include "rosbag2_test_msgdefs/msg/BasicIdl.idl"\n'
93+
'\n'
94+
'module rosbag2_test_msgdefs {\n'
95+
' module msg {\n'
96+
' struct ComplexIdl {\n'
97+
' rosbag2_test_msgdefs::msg::BasicIdl a;\n'
98+
' };\n'
99+
' };\n'
100+
'};\n'
101+
'\n'
102+
'================================================================================\n'
103+
'IDL: rosbag2_test_msgdefs/msg/BasicIdl\n'
104+
'module rosbag2_test_msgdefs {\n'
105+
' module msg {\n'
106+
' struct BasicIdl {\n'
107+
' float x;\n'
108+
' };\n'
109+
' };\n'
110+
'};\n'
111+
)
112+
113+
114+
def test_local_message_definition_source_can_resolve_msg_with_idl_deps():
115+
source = LocalMessageDefinitionSource()
116+
result = source.get_full_text(
117+
'rosbag2_test_msgdefs/msg/ComplexMsgDependsOnIdl')
118+
assert result.encoding == 'ros2idl'
119+
assert result.topic_type == 'rosbag2_test_msgdefs/msg/ComplexMsgDependsOnIdl'
120+
assert result.encoded_message_definition == (
121+
'================================================================================\n'
122+
'IDL: rosbag2_test_msgdefs/msg/ComplexMsgDependsOnIdl\n'
123+
'// generated from rosidl_adapter/resource/msg.idl.em\n'
124+
'// with input from rosbag2_test_msgdefs/msg/ComplexMsgDependsOnIdl.msg\n'
125+
'// generated code does not contain a copyright notice\n'
126+
'\n'
127+
'#include "rosbag2_test_msgdefs/msg/BasicIdl.idl"\n'
128+
'\n'
129+
'module rosbag2_test_msgdefs {\n'
130+
' module msg {\n'
131+
' struct ComplexMsgDependsOnIdl {\n'
132+
' rosbag2_test_msgdefs::msg::BasicIdl a;\n'
133+
' };\n'
134+
' };\n'
135+
'};\n'
136+
'\n'
137+
'================================================================================\n'
138+
'IDL: rosbag2_test_msgdefs/msg/BasicIdl\n'
139+
'module rosbag2_test_msgdefs {\n'
140+
' module msg {\n'
141+
' struct BasicIdl {\n'
142+
' float x;\n'
143+
' };\n'
144+
' };\n'
145+
'};\n'
146+
)

0 commit comments

Comments
 (0)