Skip to content

Commit 1bfe305

Browse files
roncapatfujitatomoyaMichaelOrlov
authored
Update documentation about recorder and player creation via composition (#1510)
* Initial composition documentation Signed-off-by: Patrick Roncagliolo <[email protected]> * Update python snippet Signed-off-by: Patrick Roncagliolo <[email protected]> * Update README.md Co-authored-by: Tomoya Fujita <[email protected]> Signed-off-by: Patrick Roncagliolo <[email protected]> * Update README.md Co-authored-by: Tomoya Fujita <[email protected]> Signed-off-by: Patrick Roncagliolo <[email protected]> * Update README.md Co-authored-by: Michael Orlov <[email protected]> Signed-off-by: Patrick Roncagliolo <[email protected]> * Add parameters example for composition Signed-off-by: Patrick Roncagliolo <[email protected]> * Update README.md Co-authored-by: Michael Orlov <[email protected]> Signed-off-by: Patrick Roncagliolo <[email protected]> * Update README.md Co-authored-by: Michael Orlov <[email protected]> Signed-off-by: Patrick Roncagliolo <[email protected]> * Update README.md Co-authored-by: Michael Orlov <[email protected]> Signed-off-by: Patrick Roncagliolo <[email protected]> * Update README.md Signed-off-by: Patrick Roncagliolo <[email protected]> --------- Signed-off-by: Patrick Roncagliolo <[email protected]> Co-authored-by: Tomoya Fujita <[email protected]> Co-authored-by: Michael Orlov <[email protected]>
1 parent 29a8415 commit 1bfe305

File tree

1 file changed

+119
-0
lines changed

1 file changed

+119
-0
lines changed

README.md

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,9 @@ These verbs are available for `ros2 bag`:
3838

3939
For up-to-date information on the available options for each, use `ros2 bag <verb> --help`.
4040

41+
Moreover, `rosbag2_transport::Player` and `rosbag2_transport::Recorder` components can be instantiated in `rclcpp` component containers, which makes possible to use intra-process communication for greater efficiency.
42+
See [composition](#using-with-composition) section for details.
43+
4144
### Recording data
4245

4346
In order to record all topics currently available in the system:
@@ -345,6 +348,122 @@ For example, if we named the above XML launch script, `record_all.launch.xml`:
345348
$ ros2 launch record_all.launch.xml
346349
```
347350

351+
You can also invoke the `play` and `record` functionalities provided by `rosbag2_transport` package as nodes.
352+
The advantage to use this invocation strategy is that the Python layer handling the `ros2 bag` CLI is completely skipped.
353+
354+
```python
355+
import launch
356+
357+
def generate_launch_description():
358+
return launch.LaunchDescription([
359+
launch.actions.Node(
360+
package='rosbag2_transport',
361+
executable='player',
362+
name='player',
363+
output="screen",
364+
parameters=["/path/to/params.yaml"],
365+
)
366+
])
367+
```
368+
369+
## Using with composition
370+
371+
Play and record are fundamental tasks of `rosbag2`. However, playing or recording data at high rates may have limitations (e.g. spurious packet drops) due to one of the following:
372+
- low network bandwith
373+
- high CPU load
374+
- slow mass memory
375+
- ROS 2 middleware serialization/deserialization delays & overhead
376+
377+
ROS 2 C++ nodes can benefit from intra-process communication to partially or completely bypass network transport of messages between two nodes.
378+
379+
Multiple _components_ can be _composed_, either [statically](https://docs.ros.org/en/rolling/Tutorials/Intermediate/Composition.html#compile-time-composition-using-ros-services) or [dynamically](https://docs.ros.org/en/rolling/Tutorials/Intermediate/Composition.html#run-time-composition-using-ros-services-with-a-publisher-and-subscriber): all the composed component will share the same address space because they will be loaded in a single process.
380+
381+
A prerequirement is for each C++ node to be [_composable_](https://docs.ros.org/en/rolling/Concepts/Intermediate/About-Composition.html?highlight=composition) and to follow the [guidelines](https://docs.ros.org/en/rolling/Tutorials/Demos/Intra-Process-Communication.html?highlight=intra) for efficient publishing & subscription.
382+
383+
With the above requirements met, the user can:
384+
- compose multiple nodes together
385+
- explicitly enable intra-process communication
386+
387+
Whenever a publisher and a subscriber on the same topic belong to the same _composed_ process, and intra-process is enabled for both, `rclcpp` completely bypasses RMW layer and below transport layer (i.e. DDS). Instead, messages are shared via process memory and *potentially* never copied. Some exception hold, so please have a look to the [IPC guidelines](https://docs.ros.org/en/rolling/Tutorials/Demos/Intra-Process-Communication.html?highlight=intra).
388+
389+
Here is an example of Python launchfile composition. Notice that composable container components do not expect YAML files to be directly passed to them: parameters have to be "dumped" out from the YAML file (if you have one). A suggestion of possible implementation is offered as a starting point.
390+
391+
```python
392+
import launch
393+
import launch_ros
394+
import yaml
395+
396+
'''
397+
Used to load parameters for composable nodes from a standard param file
398+
'''
399+
def dump_params(param_file_path, node_name):
400+
with open(param_file_path, 'r') as file:
401+
return [yaml.safe_load(file)[node_name]['ros__parameters']]
402+
403+
def generate_launch_description():
404+
return launch.LaunchDescription([
405+
launch.actions.ComposableNodeContainer(
406+
name='composable_container',
407+
package='rclcpp_components',
408+
executable='component_container',
409+
composable_node_descriptions=[
410+
launch_ros.descriptions.ComposableNode(
411+
package='rosbag2_transport',
412+
plugin='rosbag2_transport::Player',
413+
name='player',
414+
parameters=dump_params("/path/to/params.yaml", "player"),
415+
extra_arguments=[{'use_intra_process_comms': True}]
416+
),
417+
# your other components here
418+
]
419+
)
420+
])
421+
}
422+
```
423+
424+
Here's an example YAML configuration for both composable player and recorder:
425+
```yaml
426+
recorder:
427+
ros__parameters:
428+
use_sim_time: false
429+
record:
430+
all: true
431+
is_discovery_disabled: false
432+
topic_polling_interval:
433+
sec: 0
434+
nsec: 10000000
435+
include_hidden_topics: true
436+
ignore_leaf_topics: false
437+
start_paused: false
438+
439+
storage:
440+
uri: "/path/to/destination/folder"
441+
storage_id: "sqlite3"
442+
max_cache_size: 20000000
443+
```
444+
and
445+
```yaml
446+
player:
447+
ros__parameters:
448+
play:
449+
read_ahead_queue_size: 1000
450+
node_prefix: ""
451+
rate: 1.0
452+
loop: false
453+
# Negative timestamps will make the playback to not stop.
454+
playback_duration:
455+
sec: -1
456+
nsec: 00000000
457+
start_paused: false
458+
459+
storage:
460+
uri: "path/to/rosbag/file"
461+
storage_id: "mcap"
462+
storage_config_uri: ""
463+
```
464+
465+
For a full list of available parameters, you can refer to [`player`](rosbag2_transport/test/resources/player_node_params.yaml) and [`recorder`](rosbag2_transport/test/resources/recorder_node_params.yaml) configurations from the `test` folder of `rosbag2_transport`.
466+
348467
## Storage format plugin architecture
349468

350469
Looking at the output of the `ros2 bag info` command, we can see a field `Storage id:`.

0 commit comments

Comments
 (0)