|
mola_bridge_ros2 package from mola repomola mola_bridge_ros2 mola_demos mola_input_lidar_bin_dataset mola_input_rawlog mola_input_rosbag2 mola_input_video mola_kernel mola_launcher mola_metric_maps mola_msgs mola_pose_list mola_relocalization mola_traj_tools mola_viz mola_viz_imgui mola_yaml |
ROS Distro
|
Package Summary
| Version | 3.2.0 |
| License | BSD-3-Clause |
| Build type | AMENT_CMAKE |
| Use | RECOMMENDED |
Repository Summary
| Checkout URI | https://github.com/MOLAorg/mola.git |
| VCS Type | git |
| VCS Version | develop |
| Last Updated | 2026-09-04 |
| Dev Status | DEVELOPED |
| Released | RELEASED |
| Contributing |
Help Wanted (-)
Good First Issues (-) Pull Requests to Review (-) |
Package Description
Additional Links
Maintainers
- Jose-Luis Blanco-Claraco
Authors
mola_bridge_ros2
RawDataSource acting as a bidirectional bridge between ROS2 and MOLA modules.
Can be used to:
- ROS2->MOLA: Interface a real sensor using a ROS driver node and run SLAM with it. See
mola_lidar_odometrydemos. - MOLA->ROS2: Expose a dataset as ROS2 topics, from any of the datasets supported by MOLA. Example: kitti
- ROS2<->MOLA: Run SLAM on a live sensor stream, then send back the reconstructed map and trajectory to ROS for further processing or visualization in RViz. See
mola_lidar_odometrydemos.
If you want to run SLAM on a rosbag, the module mola_input_rosbag2 provides
a more convenient interface, e.g. allows fast-forwarding or skipping parts of a bag.
Building this module requires ROS 2 to be installed, and its setup.bash
activation script being sourced before invoking CMake to configure and build MOLA.
See package docs for instructions and options to install ROS prerequisites.
Provided MOLA modules:
-
BridgeROS2, type RawDataSourceBase.
Build and install
Refer to the root MOLA repository.
Docs and examples
See this package page in the documentation.
License
This package is released under the BSD 3-clause license.
Changelog for package mola_bridge_ros2
3.2.0 (2026-08-21)
- Merge pull request #198 from Zeal-Robotics/fix/bridge_ros2-tf-buffer-staleness fix(bridge_ros2): keep the TF buffer current under bridge executor load
- fix(bridge_ros2): give the TF listener its own spin thread The listener was constructed with spin_thread=false, against tf2's own default, on the grounds that the bridge already spins rosNode_ and a second spinner would be redundant. That holds only while the bridge executor keeps up with /tf, and makes buffer freshness a function of everything else the node is handling --sensor callbacks, timers, map publishing. When it does not keep up, the failure is silent: lookups still succeed, they just answer from a buffer that is behind, and the resulting poses look plausible. With spin_thread=true the /tf and /tf_static subscriptions move to a callback group and executor the listener owns, so ingestion is independent of the bridge executor's load. No new sharing is introduced. The buffer is already read from other threads --publishLocalizationTf() from the localization source's thread, transform_tree() from whichever module calls it -- and tf2::BufferCore serialises readers and writers on a single mutex. The listener's group is created with automatically_add_to_executor_with_node=false, so add_node() does not adopt it and no second executor can dispatch those subscriptions. Its destructor cancels and joins its thread, and it is declared after tf_buffer_ and rosNode_, so that happens while both are still alive.
- fix(bridge_ros2): drain the ROS queues instead of one message per topic The ROS thread polls [spin_some()]{.title-ref} on a 10 ms sleep. That loop replaced a blocking [rclcpp::spin()]{.title-ref} so the destructor could stop the thread via [shouldExit_]{.title-ref}, and the sleep was only ever there to keep the flag poll from busy-waiting. But [spin_some()]{.title-ref} collects the ready set once and executes each ready entity at most once per call, so the pair caps every subscription at roughly one message per 10 ms and puts a 10 ms floor under handling anything. Any topic arriving faster than ~100 Hz therefore keeps its subscription queue permanently full, and every message the node sees is stale by the whole queue depth. [/tf]{.title-ref} is the worst case: it aggregates every broadcaster on the graph, so on a robot publishing a few hundred transforms/s the listener's KeepLast(100) queue leaves the TF buffer several hundred ms behind. The visible symptom is REP-105 composition falling back to the stale odom transform with "extrapolation into the future" while the odom broadcaster is publishing on time and a normally-spun listener on the same graph reads it as current. A 200 Hz IMU on the same node loses half its samples the same way. [spin_once(timeout)]{.title-ref} blocks until there is work while still bounding how long [shouldExit_]{.title-ref} goes unchecked, and [spin_all()]{.title-ref} then drains whatever else is ready. Both are needed: [spin_some()]{.title-ref} and [spin_all()]{.title-ref} each call [wait_for_work(0ms)]{.title-ref}, so [spin_all()]{.title-ref} alone returns immediately when idle and would busy-wait. With work pending [spin_once()]{.title-ref} returns at once, so no iteration sleeps while a queue is non-empty. Cost is that the two bounds stack: worst case for observing [shouldExit_]{.title-ref} goes from 10 ms to 20 ms. Measured with two TF listeners on the same [/tf]{.title-ref}, one per spin strategy: draining fully leaves the buffer 12.6 ms behind the broadcaster, taking one message per 10 ms tick leaves it 358 ms behind. A blocking [spin()]{.title-ref} cancelled via [executor.cancel()]{.title-ref} would remove the poll loop altogether and is the better end state, but [cancel()]{.title-ref} racing the [spinning.exchange(true)]{.title-ref} in [spin()]{.title-ref} means the destructor has to retry until the thread joins. That is left as a separate change.
- Merge remote-tracking branch 'origin/feat/map-frame-gauge-change' into feat/map-frame-gauge-change
- Merge branch 'develop' into feat/map-frame-gauge-change
- Contributors: Jose Luis Blanco-Claraco, Robin Van Cauwenbergh
3.1.1 (2026-08-10)
- fix build in ros rolling (newer gcc)
- fix format
- mola_bridge_ros2: use tf2_ros .hpp headers instead of deprecated .h Avoids #warning deprecation spam on newer ROS2 distros while building unchanged from Humble to Rolling.
- Contributors: Jose Luis Blanco Claraco, Jose Luis Blanco-Claraco
3.1.0 (2026-08-06)
- Add mola::TransformTreeSource: expose the /tf tree to other MOLA modules (#188) * Add mola::TransformTreeSource: expose the /tf tree to other modules New mola_kernel interface letting a data source publish its tree of coordinate frames, so consumers (e.g. a LiDAR-odometry viewer) can draw a robot's joints as it moves. transform_tree(root) returns the subtree below 'root' with poses already resolved against it. The filtering is done in the source, which is what owns the transform buffer, so a consumer never receives nor walks unrelated subtrees. The interface carries no ROS/tf2 type, keeping mola_kernel ROS-independent. Implemented by Rosbag1Dataset (separate repo), Rosbag2Dataset and BridgeROS2. No locking is added around the subtree walk: tf2::BufferCore guards its own internals, which is also what lets BridgeROS2's TransformListener feed the buffer from its own thread.
File truncated at 100 lines see the full file
Package Dependencies
System Dependencies
Dependant Packages
Launch files
Messages
Services
Plugins
Recent questions tagged mola_bridge_ros2 at Robotics Stack Exchange
|
mola_bridge_ros2 package from mola repomola mola_bridge_ros2 mola_demos mola_input_lidar_bin_dataset mola_input_rawlog mola_input_rosbag2 mola_input_video mola_kernel mola_launcher mola_metric_maps mola_msgs mola_pose_list mola_relocalization mola_traj_tools mola_viz mola_viz_imgui mola_yaml |
ROS Distro
|
Package Summary
| Version | 3.2.0 |
| License | BSD-3-Clause |
| Build type | AMENT_CMAKE |
| Use | RECOMMENDED |
Repository Summary
| Checkout URI | https://github.com/MOLAorg/mola.git |
| VCS Type | git |
| VCS Version | develop |
| Last Updated | 2026-09-04 |
| Dev Status | DEVELOPED |
| Released | RELEASED |
| Contributing |
Help Wanted (-)
Good First Issues (-) Pull Requests to Review (-) |
Package Description
Additional Links
Maintainers
- Jose-Luis Blanco-Claraco
Authors
mola_bridge_ros2
RawDataSource acting as a bidirectional bridge between ROS2 and MOLA modules.
Can be used to:
- ROS2->MOLA: Interface a real sensor using a ROS driver node and run SLAM with it. See
mola_lidar_odometrydemos. - MOLA->ROS2: Expose a dataset as ROS2 topics, from any of the datasets supported by MOLA. Example: kitti
- ROS2<->MOLA: Run SLAM on a live sensor stream, then send back the reconstructed map and trajectory to ROS for further processing or visualization in RViz. See
mola_lidar_odometrydemos.
If you want to run SLAM on a rosbag, the module mola_input_rosbag2 provides
a more convenient interface, e.g. allows fast-forwarding or skipping parts of a bag.
Building this module requires ROS 2 to be installed, and its setup.bash
activation script being sourced before invoking CMake to configure and build MOLA.
See package docs for instructions and options to install ROS prerequisites.
Provided MOLA modules:
-
BridgeROS2, type RawDataSourceBase.
Build and install
Refer to the root MOLA repository.
Docs and examples
See this package page in the documentation.
License
This package is released under the BSD 3-clause license.
Changelog for package mola_bridge_ros2
3.2.0 (2026-08-21)
- Merge pull request #198 from Zeal-Robotics/fix/bridge_ros2-tf-buffer-staleness fix(bridge_ros2): keep the TF buffer current under bridge executor load
- fix(bridge_ros2): give the TF listener its own spin thread The listener was constructed with spin_thread=false, against tf2's own default, on the grounds that the bridge already spins rosNode_ and a second spinner would be redundant. That holds only while the bridge executor keeps up with /tf, and makes buffer freshness a function of everything else the node is handling --sensor callbacks, timers, map publishing. When it does not keep up, the failure is silent: lookups still succeed, they just answer from a buffer that is behind, and the resulting poses look plausible. With spin_thread=true the /tf and /tf_static subscriptions move to a callback group and executor the listener owns, so ingestion is independent of the bridge executor's load. No new sharing is introduced. The buffer is already read from other threads --publishLocalizationTf() from the localization source's thread, transform_tree() from whichever module calls it -- and tf2::BufferCore serialises readers and writers on a single mutex. The listener's group is created with automatically_add_to_executor_with_node=false, so add_node() does not adopt it and no second executor can dispatch those subscriptions. Its destructor cancels and joins its thread, and it is declared after tf_buffer_ and rosNode_, so that happens while both are still alive.
- fix(bridge_ros2): drain the ROS queues instead of one message per topic The ROS thread polls [spin_some()]{.title-ref} on a 10 ms sleep. That loop replaced a blocking [rclcpp::spin()]{.title-ref} so the destructor could stop the thread via [shouldExit_]{.title-ref}, and the sleep was only ever there to keep the flag poll from busy-waiting. But [spin_some()]{.title-ref} collects the ready set once and executes each ready entity at most once per call, so the pair caps every subscription at roughly one message per 10 ms and puts a 10 ms floor under handling anything. Any topic arriving faster than ~100 Hz therefore keeps its subscription queue permanently full, and every message the node sees is stale by the whole queue depth. [/tf]{.title-ref} is the worst case: it aggregates every broadcaster on the graph, so on a robot publishing a few hundred transforms/s the listener's KeepLast(100) queue leaves the TF buffer several hundred ms behind. The visible symptom is REP-105 composition falling back to the stale odom transform with "extrapolation into the future" while the odom broadcaster is publishing on time and a normally-spun listener on the same graph reads it as current. A 200 Hz IMU on the same node loses half its samples the same way. [spin_once(timeout)]{.title-ref} blocks until there is work while still bounding how long [shouldExit_]{.title-ref} goes unchecked, and [spin_all()]{.title-ref} then drains whatever else is ready. Both are needed: [spin_some()]{.title-ref} and [spin_all()]{.title-ref} each call [wait_for_work(0ms)]{.title-ref}, so [spin_all()]{.title-ref} alone returns immediately when idle and would busy-wait. With work pending [spin_once()]{.title-ref} returns at once, so no iteration sleeps while a queue is non-empty. Cost is that the two bounds stack: worst case for observing [shouldExit_]{.title-ref} goes from 10 ms to 20 ms. Measured with two TF listeners on the same [/tf]{.title-ref}, one per spin strategy: draining fully leaves the buffer 12.6 ms behind the broadcaster, taking one message per 10 ms tick leaves it 358 ms behind. A blocking [spin()]{.title-ref} cancelled via [executor.cancel()]{.title-ref} would remove the poll loop altogether and is the better end state, but [cancel()]{.title-ref} racing the [spinning.exchange(true)]{.title-ref} in [spin()]{.title-ref} means the destructor has to retry until the thread joins. That is left as a separate change.
- Merge remote-tracking branch 'origin/feat/map-frame-gauge-change' into feat/map-frame-gauge-change
- Merge branch 'develop' into feat/map-frame-gauge-change
- Contributors: Jose Luis Blanco-Claraco, Robin Van Cauwenbergh
3.1.1 (2026-08-10)
- fix build in ros rolling (newer gcc)
- fix format
- mola_bridge_ros2: use tf2_ros .hpp headers instead of deprecated .h Avoids #warning deprecation spam on newer ROS2 distros while building unchanged from Humble to Rolling.
- Contributors: Jose Luis Blanco Claraco, Jose Luis Blanco-Claraco
3.1.0 (2026-08-06)
- Add mola::TransformTreeSource: expose the /tf tree to other MOLA modules (#188) * Add mola::TransformTreeSource: expose the /tf tree to other modules New mola_kernel interface letting a data source publish its tree of coordinate frames, so consumers (e.g. a LiDAR-odometry viewer) can draw a robot's joints as it moves. transform_tree(root) returns the subtree below 'root' with poses already resolved against it. The filtering is done in the source, which is what owns the transform buffer, so a consumer never receives nor walks unrelated subtrees. The interface carries no ROS/tf2 type, keeping mola_kernel ROS-independent. Implemented by Rosbag1Dataset (separate repo), Rosbag2Dataset and BridgeROS2. No locking is added around the subtree walk: tf2::BufferCore guards its own internals, which is also what lets BridgeROS2's TransformListener feed the buffer from its own thread.
File truncated at 100 lines see the full file
Package Dependencies
System Dependencies
Dependant Packages
Launch files
Messages
Services
Plugins
Recent questions tagged mola_bridge_ros2 at Robotics Stack Exchange
|
mola_bridge_ros2 package from mola repomola mola_bridge_ros2 mola_demos mola_input_lidar_bin_dataset mola_input_rawlog mola_input_rosbag2 mola_input_video mola_kernel mola_launcher mola_metric_maps mola_msgs mola_pose_list mola_relocalization mola_traj_tools mola_viz mola_viz_imgui mola_yaml |
ROS Distro
|
Package Summary
| Version | 3.2.0 |
| License | BSD-3-Clause |
| Build type | AMENT_CMAKE |
| Use | RECOMMENDED |
Repository Summary
| Checkout URI | https://github.com/MOLAorg/mola.git |
| VCS Type | git |
| VCS Version | develop |
| Last Updated | 2026-09-04 |
| Dev Status | DEVELOPED |
| Released | RELEASED |
| Contributing |
Help Wanted (-)
Good First Issues (-) Pull Requests to Review (-) |
Package Description
Additional Links
Maintainers
- Jose-Luis Blanco-Claraco
Authors
mola_bridge_ros2
RawDataSource acting as a bidirectional bridge between ROS2 and MOLA modules.
Can be used to:
- ROS2->MOLA: Interface a real sensor using a ROS driver node and run SLAM with it. See
mola_lidar_odometrydemos. - MOLA->ROS2: Expose a dataset as ROS2 topics, from any of the datasets supported by MOLA. Example: kitti
- ROS2<->MOLA: Run SLAM on a live sensor stream, then send back the reconstructed map and trajectory to ROS for further processing or visualization in RViz. See
mola_lidar_odometrydemos.
If you want to run SLAM on a rosbag, the module mola_input_rosbag2 provides
a more convenient interface, e.g. allows fast-forwarding or skipping parts of a bag.
Building this module requires ROS 2 to be installed, and its setup.bash
activation script being sourced before invoking CMake to configure and build MOLA.
See package docs for instructions and options to install ROS prerequisites.
Provided MOLA modules:
-
BridgeROS2, type RawDataSourceBase.
Build and install
Refer to the root MOLA repository.
Docs and examples
See this package page in the documentation.
License
This package is released under the BSD 3-clause license.
Changelog for package mola_bridge_ros2
3.2.0 (2026-08-21)
- Merge pull request #198 from Zeal-Robotics/fix/bridge_ros2-tf-buffer-staleness fix(bridge_ros2): keep the TF buffer current under bridge executor load
- fix(bridge_ros2): give the TF listener its own spin thread The listener was constructed with spin_thread=false, against tf2's own default, on the grounds that the bridge already spins rosNode_ and a second spinner would be redundant. That holds only while the bridge executor keeps up with /tf, and makes buffer freshness a function of everything else the node is handling --sensor callbacks, timers, map publishing. When it does not keep up, the failure is silent: lookups still succeed, they just answer from a buffer that is behind, and the resulting poses look plausible. With spin_thread=true the /tf and /tf_static subscriptions move to a callback group and executor the listener owns, so ingestion is independent of the bridge executor's load. No new sharing is introduced. The buffer is already read from other threads --publishLocalizationTf() from the localization source's thread, transform_tree() from whichever module calls it -- and tf2::BufferCore serialises readers and writers on a single mutex. The listener's group is created with automatically_add_to_executor_with_node=false, so add_node() does not adopt it and no second executor can dispatch those subscriptions. Its destructor cancels and joins its thread, and it is declared after tf_buffer_ and rosNode_, so that happens while both are still alive.
- fix(bridge_ros2): drain the ROS queues instead of one message per topic The ROS thread polls [spin_some()]{.title-ref} on a 10 ms sleep. That loop replaced a blocking [rclcpp::spin()]{.title-ref} so the destructor could stop the thread via [shouldExit_]{.title-ref}, and the sleep was only ever there to keep the flag poll from busy-waiting. But [spin_some()]{.title-ref} collects the ready set once and executes each ready entity at most once per call, so the pair caps every subscription at roughly one message per 10 ms and puts a 10 ms floor under handling anything. Any topic arriving faster than ~100 Hz therefore keeps its subscription queue permanently full, and every message the node sees is stale by the whole queue depth. [/tf]{.title-ref} is the worst case: it aggregates every broadcaster on the graph, so on a robot publishing a few hundred transforms/s the listener's KeepLast(100) queue leaves the TF buffer several hundred ms behind. The visible symptom is REP-105 composition falling back to the stale odom transform with "extrapolation into the future" while the odom broadcaster is publishing on time and a normally-spun listener on the same graph reads it as current. A 200 Hz IMU on the same node loses half its samples the same way. [spin_once(timeout)]{.title-ref} blocks until there is work while still bounding how long [shouldExit_]{.title-ref} goes unchecked, and [spin_all()]{.title-ref} then drains whatever else is ready. Both are needed: [spin_some()]{.title-ref} and [spin_all()]{.title-ref} each call [wait_for_work(0ms)]{.title-ref}, so [spin_all()]{.title-ref} alone returns immediately when idle and would busy-wait. With work pending [spin_once()]{.title-ref} returns at once, so no iteration sleeps while a queue is non-empty. Cost is that the two bounds stack: worst case for observing [shouldExit_]{.title-ref} goes from 10 ms to 20 ms. Measured with two TF listeners on the same [/tf]{.title-ref}, one per spin strategy: draining fully leaves the buffer 12.6 ms behind the broadcaster, taking one message per 10 ms tick leaves it 358 ms behind. A blocking [spin()]{.title-ref} cancelled via [executor.cancel()]{.title-ref} would remove the poll loop altogether and is the better end state, but [cancel()]{.title-ref} racing the [spinning.exchange(true)]{.title-ref} in [spin()]{.title-ref} means the destructor has to retry until the thread joins. That is left as a separate change.
- Merge remote-tracking branch 'origin/feat/map-frame-gauge-change' into feat/map-frame-gauge-change
- Merge branch 'develop' into feat/map-frame-gauge-change
- Contributors: Jose Luis Blanco-Claraco, Robin Van Cauwenbergh
3.1.1 (2026-08-10)
- fix build in ros rolling (newer gcc)
- fix format
- mola_bridge_ros2: use tf2_ros .hpp headers instead of deprecated .h Avoids #warning deprecation spam on newer ROS2 distros while building unchanged from Humble to Rolling.
- Contributors: Jose Luis Blanco Claraco, Jose Luis Blanco-Claraco
3.1.0 (2026-08-06)
- Add mola::TransformTreeSource: expose the /tf tree to other MOLA modules (#188) * Add mola::TransformTreeSource: expose the /tf tree to other modules New mola_kernel interface letting a data source publish its tree of coordinate frames, so consumers (e.g. a LiDAR-odometry viewer) can draw a robot's joints as it moves. transform_tree(root) returns the subtree below 'root' with poses already resolved against it. The filtering is done in the source, which is what owns the transform buffer, so a consumer never receives nor walks unrelated subtrees. The interface carries no ROS/tf2 type, keeping mola_kernel ROS-independent. Implemented by Rosbag1Dataset (separate repo), Rosbag2Dataset and BridgeROS2. No locking is added around the subtree walk: tf2::BufferCore guards its own internals, which is also what lets BridgeROS2's TransformListener feed the buffer from its own thread.
File truncated at 100 lines see the full file
Package Dependencies
System Dependencies
Dependant Packages
Launch files
Messages
Services
Plugins
Recent questions tagged mola_bridge_ros2 at Robotics Stack Exchange
|
mola_bridge_ros2 package from mola repomola mola_bridge_ros2 mola_demos mola_input_lidar_bin_dataset mola_input_rawlog mola_input_rosbag2 mola_input_video mola_kernel mola_launcher mola_metric_maps mola_msgs mola_pose_list mola_relocalization mola_traj_tools mola_viz mola_viz_imgui mola_yaml |
ROS Distro
|
Package Summary
| Version | 3.2.0 |
| License | BSD-3-Clause |
| Build type | AMENT_CMAKE |
| Use | RECOMMENDED |
Repository Summary
| Checkout URI | https://github.com/MOLAorg/mola.git |
| VCS Type | git |
| VCS Version | develop |
| Last Updated | 2026-09-04 |
| Dev Status | DEVELOPED |
| Released | RELEASED |
| Contributing |
Help Wanted (-)
Good First Issues (-) Pull Requests to Review (-) |
Package Description
Additional Links
Maintainers
- Jose-Luis Blanco-Claraco
Authors
mola_bridge_ros2
RawDataSource acting as a bidirectional bridge between ROS2 and MOLA modules.
Can be used to:
- ROS2->MOLA: Interface a real sensor using a ROS driver node and run SLAM with it. See
mola_lidar_odometrydemos. - MOLA->ROS2: Expose a dataset as ROS2 topics, from any of the datasets supported by MOLA. Example: kitti
- ROS2<->MOLA: Run SLAM on a live sensor stream, then send back the reconstructed map and trajectory to ROS for further processing or visualization in RViz. See
mola_lidar_odometrydemos.
If you want to run SLAM on a rosbag, the module mola_input_rosbag2 provides
a more convenient interface, e.g. allows fast-forwarding or skipping parts of a bag.
Building this module requires ROS 2 to be installed, and its setup.bash
activation script being sourced before invoking CMake to configure and build MOLA.
See package docs for instructions and options to install ROS prerequisites.
Provided MOLA modules:
-
BridgeROS2, type RawDataSourceBase.
Build and install
Refer to the root MOLA repository.
Docs and examples
See this package page in the documentation.
License
This package is released under the BSD 3-clause license.
Changelog for package mola_bridge_ros2
3.2.0 (2026-08-21)
- Merge pull request #198 from Zeal-Robotics/fix/bridge_ros2-tf-buffer-staleness fix(bridge_ros2): keep the TF buffer current under bridge executor load
- fix(bridge_ros2): give the TF listener its own spin thread The listener was constructed with spin_thread=false, against tf2's own default, on the grounds that the bridge already spins rosNode_ and a second spinner would be redundant. That holds only while the bridge executor keeps up with /tf, and makes buffer freshness a function of everything else the node is handling --sensor callbacks, timers, map publishing. When it does not keep up, the failure is silent: lookups still succeed, they just answer from a buffer that is behind, and the resulting poses look plausible. With spin_thread=true the /tf and /tf_static subscriptions move to a callback group and executor the listener owns, so ingestion is independent of the bridge executor's load. No new sharing is introduced. The buffer is already read from other threads --publishLocalizationTf() from the localization source's thread, transform_tree() from whichever module calls it -- and tf2::BufferCore serialises readers and writers on a single mutex. The listener's group is created with automatically_add_to_executor_with_node=false, so add_node() does not adopt it and no second executor can dispatch those subscriptions. Its destructor cancels and joins its thread, and it is declared after tf_buffer_ and rosNode_, so that happens while both are still alive.
- fix(bridge_ros2): drain the ROS queues instead of one message per topic The ROS thread polls [spin_some()]{.title-ref} on a 10 ms sleep. That loop replaced a blocking [rclcpp::spin()]{.title-ref} so the destructor could stop the thread via [shouldExit_]{.title-ref}, and the sleep was only ever there to keep the flag poll from busy-waiting. But [spin_some()]{.title-ref} collects the ready set once and executes each ready entity at most once per call, so the pair caps every subscription at roughly one message per 10 ms and puts a 10 ms floor under handling anything. Any topic arriving faster than ~100 Hz therefore keeps its subscription queue permanently full, and every message the node sees is stale by the whole queue depth. [/tf]{.title-ref} is the worst case: it aggregates every broadcaster on the graph, so on a robot publishing a few hundred transforms/s the listener's KeepLast(100) queue leaves the TF buffer several hundred ms behind. The visible symptom is REP-105 composition falling back to the stale odom transform with "extrapolation into the future" while the odom broadcaster is publishing on time and a normally-spun listener on the same graph reads it as current. A 200 Hz IMU on the same node loses half its samples the same way. [spin_once(timeout)]{.title-ref} blocks until there is work while still bounding how long [shouldExit_]{.title-ref} goes unchecked, and [spin_all()]{.title-ref} then drains whatever else is ready. Both are needed: [spin_some()]{.title-ref} and [spin_all()]{.title-ref} each call [wait_for_work(0ms)]{.title-ref}, so [spin_all()]{.title-ref} alone returns immediately when idle and would busy-wait. With work pending [spin_once()]{.title-ref} returns at once, so no iteration sleeps while a queue is non-empty. Cost is that the two bounds stack: worst case for observing [shouldExit_]{.title-ref} goes from 10 ms to 20 ms. Measured with two TF listeners on the same [/tf]{.title-ref}, one per spin strategy: draining fully leaves the buffer 12.6 ms behind the broadcaster, taking one message per 10 ms tick leaves it 358 ms behind. A blocking [spin()]{.title-ref} cancelled via [executor.cancel()]{.title-ref} would remove the poll loop altogether and is the better end state, but [cancel()]{.title-ref} racing the [spinning.exchange(true)]{.title-ref} in [spin()]{.title-ref} means the destructor has to retry until the thread joins. That is left as a separate change.
- Merge remote-tracking branch 'origin/feat/map-frame-gauge-change' into feat/map-frame-gauge-change
- Merge branch 'develop' into feat/map-frame-gauge-change
- Contributors: Jose Luis Blanco-Claraco, Robin Van Cauwenbergh
3.1.1 (2026-08-10)
- fix build in ros rolling (newer gcc)
- fix format
- mola_bridge_ros2: use tf2_ros .hpp headers instead of deprecated .h Avoids #warning deprecation spam on newer ROS2 distros while building unchanged from Humble to Rolling.
- Contributors: Jose Luis Blanco Claraco, Jose Luis Blanco-Claraco
3.1.0 (2026-08-06)
- Add mola::TransformTreeSource: expose the /tf tree to other MOLA modules (#188) * Add mola::TransformTreeSource: expose the /tf tree to other modules New mola_kernel interface letting a data source publish its tree of coordinate frames, so consumers (e.g. a LiDAR-odometry viewer) can draw a robot's joints as it moves. transform_tree(root) returns the subtree below 'root' with poses already resolved against it. The filtering is done in the source, which is what owns the transform buffer, so a consumer never receives nor walks unrelated subtrees. The interface carries no ROS/tf2 type, keeping mola_kernel ROS-independent. Implemented by Rosbag1Dataset (separate repo), Rosbag2Dataset and BridgeROS2. No locking is added around the subtree walk: tf2::BufferCore guards its own internals, which is also what lets BridgeROS2's TransformListener feed the buffer from its own thread.
File truncated at 100 lines see the full file
Package Dependencies
System Dependencies
Dependant Packages
Launch files
Messages
Services
Plugins
Recent questions tagged mola_bridge_ros2 at Robotics Stack Exchange
|
mola_bridge_ros2 package from mola repomola mola_bridge_ros2 mola_demos mola_input_lidar_bin_dataset mola_input_rawlog mola_input_rosbag2 mola_input_video mola_kernel mola_launcher mola_metric_maps mola_msgs mola_pose_list mola_relocalization mola_traj_tools mola_viz mola_viz_imgui mola_yaml |
ROS Distro
|
Package Summary
| Version | 3.2.0 |
| License | BSD-3-Clause |
| Build type | AMENT_CMAKE |
| Use | RECOMMENDED |
Repository Summary
| Checkout URI | https://github.com/MOLAorg/mola.git |
| VCS Type | git |
| VCS Version | develop |
| Last Updated | 2026-09-04 |
| Dev Status | DEVELOPED |
| Released | RELEASED |
| Contributing |
Help Wanted (-)
Good First Issues (-) Pull Requests to Review (-) |
Package Description
Additional Links
Maintainers
- Jose-Luis Blanco-Claraco
Authors
mola_bridge_ros2
RawDataSource acting as a bidirectional bridge between ROS2 and MOLA modules.
Can be used to:
- ROS2->MOLA: Interface a real sensor using a ROS driver node and run SLAM with it. See
mola_lidar_odometrydemos. - MOLA->ROS2: Expose a dataset as ROS2 topics, from any of the datasets supported by MOLA. Example: kitti
- ROS2<->MOLA: Run SLAM on a live sensor stream, then send back the reconstructed map and trajectory to ROS for further processing or visualization in RViz. See
mola_lidar_odometrydemos.
If you want to run SLAM on a rosbag, the module mola_input_rosbag2 provides
a more convenient interface, e.g. allows fast-forwarding or skipping parts of a bag.
Building this module requires ROS 2 to be installed, and its setup.bash
activation script being sourced before invoking CMake to configure and build MOLA.
See package docs for instructions and options to install ROS prerequisites.
Provided MOLA modules:
-
BridgeROS2, type RawDataSourceBase.
Build and install
Refer to the root MOLA repository.
Docs and examples
See this package page in the documentation.
License
This package is released under the BSD 3-clause license.
Changelog for package mola_bridge_ros2
3.2.0 (2026-08-21)
- Merge pull request #198 from Zeal-Robotics/fix/bridge_ros2-tf-buffer-staleness fix(bridge_ros2): keep the TF buffer current under bridge executor load
- fix(bridge_ros2): give the TF listener its own spin thread The listener was constructed with spin_thread=false, against tf2's own default, on the grounds that the bridge already spins rosNode_ and a second spinner would be redundant. That holds only while the bridge executor keeps up with /tf, and makes buffer freshness a function of everything else the node is handling --sensor callbacks, timers, map publishing. When it does not keep up, the failure is silent: lookups still succeed, they just answer from a buffer that is behind, and the resulting poses look plausible. With spin_thread=true the /tf and /tf_static subscriptions move to a callback group and executor the listener owns, so ingestion is independent of the bridge executor's load. No new sharing is introduced. The buffer is already read from other threads --publishLocalizationTf() from the localization source's thread, transform_tree() from whichever module calls it -- and tf2::BufferCore serialises readers and writers on a single mutex. The listener's group is created with automatically_add_to_executor_with_node=false, so add_node() does not adopt it and no second executor can dispatch those subscriptions. Its destructor cancels and joins its thread, and it is declared after tf_buffer_ and rosNode_, so that happens while both are still alive.
- fix(bridge_ros2): drain the ROS queues instead of one message per topic The ROS thread polls [spin_some()]{.title-ref} on a 10 ms sleep. That loop replaced a blocking [rclcpp::spin()]{.title-ref} so the destructor could stop the thread via [shouldExit_]{.title-ref}, and the sleep was only ever there to keep the flag poll from busy-waiting. But [spin_some()]{.title-ref} collects the ready set once and executes each ready entity at most once per call, so the pair caps every subscription at roughly one message per 10 ms and puts a 10 ms floor under handling anything. Any topic arriving faster than ~100 Hz therefore keeps its subscription queue permanently full, and every message the node sees is stale by the whole queue depth. [/tf]{.title-ref} is the worst case: it aggregates every broadcaster on the graph, so on a robot publishing a few hundred transforms/s the listener's KeepLast(100) queue leaves the TF buffer several hundred ms behind. The visible symptom is REP-105 composition falling back to the stale odom transform with "extrapolation into the future" while the odom broadcaster is publishing on time and a normally-spun listener on the same graph reads it as current. A 200 Hz IMU on the same node loses half its samples the same way. [spin_once(timeout)]{.title-ref} blocks until there is work while still bounding how long [shouldExit_]{.title-ref} goes unchecked, and [spin_all()]{.title-ref} then drains whatever else is ready. Both are needed: [spin_some()]{.title-ref} and [spin_all()]{.title-ref} each call [wait_for_work(0ms)]{.title-ref}, so [spin_all()]{.title-ref} alone returns immediately when idle and would busy-wait. With work pending [spin_once()]{.title-ref} returns at once, so no iteration sleeps while a queue is non-empty. Cost is that the two bounds stack: worst case for observing [shouldExit_]{.title-ref} goes from 10 ms to 20 ms. Measured with two TF listeners on the same [/tf]{.title-ref}, one per spin strategy: draining fully leaves the buffer 12.6 ms behind the broadcaster, taking one message per 10 ms tick leaves it 358 ms behind. A blocking [spin()]{.title-ref} cancelled via [executor.cancel()]{.title-ref} would remove the poll loop altogether and is the better end state, but [cancel()]{.title-ref} racing the [spinning.exchange(true)]{.title-ref} in [spin()]{.title-ref} means the destructor has to retry until the thread joins. That is left as a separate change.
- Merge remote-tracking branch 'origin/feat/map-frame-gauge-change' into feat/map-frame-gauge-change
- Merge branch 'develop' into feat/map-frame-gauge-change
- Contributors: Jose Luis Blanco-Claraco, Robin Van Cauwenbergh
3.1.1 (2026-08-10)
- fix build in ros rolling (newer gcc)
- fix format
- mola_bridge_ros2: use tf2_ros .hpp headers instead of deprecated .h Avoids #warning deprecation spam on newer ROS2 distros while building unchanged from Humble to Rolling.
- Contributors: Jose Luis Blanco Claraco, Jose Luis Blanco-Claraco
3.1.0 (2026-08-06)
- Add mola::TransformTreeSource: expose the /tf tree to other MOLA modules (#188) * Add mola::TransformTreeSource: expose the /tf tree to other modules New mola_kernel interface letting a data source publish its tree of coordinate frames, so consumers (e.g. a LiDAR-odometry viewer) can draw a robot's joints as it moves. transform_tree(root) returns the subtree below 'root' with poses already resolved against it. The filtering is done in the source, which is what owns the transform buffer, so a consumer never receives nor walks unrelated subtrees. The interface carries no ROS/tf2 type, keeping mola_kernel ROS-independent. Implemented by Rosbag1Dataset (separate repo), Rosbag2Dataset and BridgeROS2. No locking is added around the subtree walk: tf2::BufferCore guards its own internals, which is also what lets BridgeROS2's TransformListener feed the buffer from its own thread.
File truncated at 100 lines see the full file
Package Dependencies
System Dependencies
Dependant Packages
Launch files
Messages
Services
Plugins
Recent questions tagged mola_bridge_ros2 at Robotics Stack Exchange
|
mola_bridge_ros2 package from mola repomola mola_bridge_ros2 mola_demos mola_input_lidar_bin_dataset mola_input_rawlog mola_input_rosbag2 mola_input_video mola_kernel mola_launcher mola_metric_maps mola_msgs mola_pose_list mola_relocalization mola_traj_tools mola_viz mola_viz_imgui mola_yaml |
ROS Distro
|
Package Summary
| Version | 3.2.0 |
| License | BSD-3-Clause |
| Build type | AMENT_CMAKE |
| Use | RECOMMENDED |
Repository Summary
| Checkout URI | https://github.com/MOLAorg/mola.git |
| VCS Type | git |
| VCS Version | develop |
| Last Updated | 2026-09-04 |
| Dev Status | DEVELOPED |
| Released | RELEASED |
| Contributing |
Help Wanted (-)
Good First Issues (-) Pull Requests to Review (-) |
Package Description
Additional Links
Maintainers
- Jose-Luis Blanco-Claraco
Authors
mola_bridge_ros2
RawDataSource acting as a bidirectional bridge between ROS2 and MOLA modules.
Can be used to:
- ROS2->MOLA: Interface a real sensor using a ROS driver node and run SLAM with it. See
mola_lidar_odometrydemos. - MOLA->ROS2: Expose a dataset as ROS2 topics, from any of the datasets supported by MOLA. Example: kitti
- ROS2<->MOLA: Run SLAM on a live sensor stream, then send back the reconstructed map and trajectory to ROS for further processing or visualization in RViz. See
mola_lidar_odometrydemos.
If you want to run SLAM on a rosbag, the module mola_input_rosbag2 provides
a more convenient interface, e.g. allows fast-forwarding or skipping parts of a bag.
Building this module requires ROS 2 to be installed, and its setup.bash
activation script being sourced before invoking CMake to configure and build MOLA.
See package docs for instructions and options to install ROS prerequisites.
Provided MOLA modules:
-
BridgeROS2, type RawDataSourceBase.
Build and install
Refer to the root MOLA repository.
Docs and examples
See this package page in the documentation.
License
This package is released under the BSD 3-clause license.
Changelog for package mola_bridge_ros2
3.2.0 (2026-08-21)
- Merge pull request #198 from Zeal-Robotics/fix/bridge_ros2-tf-buffer-staleness fix(bridge_ros2): keep the TF buffer current under bridge executor load
- fix(bridge_ros2): give the TF listener its own spin thread The listener was constructed with spin_thread=false, against tf2's own default, on the grounds that the bridge already spins rosNode_ and a second spinner would be redundant. That holds only while the bridge executor keeps up with /tf, and makes buffer freshness a function of everything else the node is handling --sensor callbacks, timers, map publishing. When it does not keep up, the failure is silent: lookups still succeed, they just answer from a buffer that is behind, and the resulting poses look plausible. With spin_thread=true the /tf and /tf_static subscriptions move to a callback group and executor the listener owns, so ingestion is independent of the bridge executor's load. No new sharing is introduced. The buffer is already read from other threads --publishLocalizationTf() from the localization source's thread, transform_tree() from whichever module calls it -- and tf2::BufferCore serialises readers and writers on a single mutex. The listener's group is created with automatically_add_to_executor_with_node=false, so add_node() does not adopt it and no second executor can dispatch those subscriptions. Its destructor cancels and joins its thread, and it is declared after tf_buffer_ and rosNode_, so that happens while both are still alive.
- fix(bridge_ros2): drain the ROS queues instead of one message per topic The ROS thread polls [spin_some()]{.title-ref} on a 10 ms sleep. That loop replaced a blocking [rclcpp::spin()]{.title-ref} so the destructor could stop the thread via [shouldExit_]{.title-ref}, and the sleep was only ever there to keep the flag poll from busy-waiting. But [spin_some()]{.title-ref} collects the ready set once and executes each ready entity at most once per call, so the pair caps every subscription at roughly one message per 10 ms and puts a 10 ms floor under handling anything. Any topic arriving faster than ~100 Hz therefore keeps its subscription queue permanently full, and every message the node sees is stale by the whole queue depth. [/tf]{.title-ref} is the worst case: it aggregates every broadcaster on the graph, so on a robot publishing a few hundred transforms/s the listener's KeepLast(100) queue leaves the TF buffer several hundred ms behind. The visible symptom is REP-105 composition falling back to the stale odom transform with "extrapolation into the future" while the odom broadcaster is publishing on time and a normally-spun listener on the same graph reads it as current. A 200 Hz IMU on the same node loses half its samples the same way. [spin_once(timeout)]{.title-ref} blocks until there is work while still bounding how long [shouldExit_]{.title-ref} goes unchecked, and [spin_all()]{.title-ref} then drains whatever else is ready. Both are needed: [spin_some()]{.title-ref} and [spin_all()]{.title-ref} each call [wait_for_work(0ms)]{.title-ref}, so [spin_all()]{.title-ref} alone returns immediately when idle and would busy-wait. With work pending [spin_once()]{.title-ref} returns at once, so no iteration sleeps while a queue is non-empty. Cost is that the two bounds stack: worst case for observing [shouldExit_]{.title-ref} goes from 10 ms to 20 ms. Measured with two TF listeners on the same [/tf]{.title-ref}, one per spin strategy: draining fully leaves the buffer 12.6 ms behind the broadcaster, taking one message per 10 ms tick leaves it 358 ms behind. A blocking [spin()]{.title-ref} cancelled via [executor.cancel()]{.title-ref} would remove the poll loop altogether and is the better end state, but [cancel()]{.title-ref} racing the [spinning.exchange(true)]{.title-ref} in [spin()]{.title-ref} means the destructor has to retry until the thread joins. That is left as a separate change.
- Merge remote-tracking branch 'origin/feat/map-frame-gauge-change' into feat/map-frame-gauge-change
- Merge branch 'develop' into feat/map-frame-gauge-change
- Contributors: Jose Luis Blanco-Claraco, Robin Van Cauwenbergh
3.1.1 (2026-08-10)
- fix build in ros rolling (newer gcc)
- fix format
- mola_bridge_ros2: use tf2_ros .hpp headers instead of deprecated .h Avoids #warning deprecation spam on newer ROS2 distros while building unchanged from Humble to Rolling.
- Contributors: Jose Luis Blanco Claraco, Jose Luis Blanco-Claraco
3.1.0 (2026-08-06)
- Add mola::TransformTreeSource: expose the /tf tree to other MOLA modules (#188) * Add mola::TransformTreeSource: expose the /tf tree to other modules New mola_kernel interface letting a data source publish its tree of coordinate frames, so consumers (e.g. a LiDAR-odometry viewer) can draw a robot's joints as it moves. transform_tree(root) returns the subtree below 'root' with poses already resolved against it. The filtering is done in the source, which is what owns the transform buffer, so a consumer never receives nor walks unrelated subtrees. The interface carries no ROS/tf2 type, keeping mola_kernel ROS-independent. Implemented by Rosbag1Dataset (separate repo), Rosbag2Dataset and BridgeROS2. No locking is added around the subtree walk: tf2::BufferCore guards its own internals, which is also what lets BridgeROS2's TransformListener feed the buffer from its own thread.
File truncated at 100 lines see the full file
Package Dependencies
System Dependencies
Dependant Packages
Launch files
Messages
Services
Plugins
Recent questions tagged mola_bridge_ros2 at Robotics Stack Exchange
|
mola_bridge_ros2 package from mola repomola mola_bridge_ros2 mola_demos mola_input_lidar_bin_dataset mola_input_rawlog mola_input_rosbag2 mola_input_video mola_kernel mola_launcher mola_metric_maps mola_msgs mola_pose_list mola_relocalization mola_traj_tools mola_viz mola_viz_imgui mola_yaml |
ROS Distro
|
Package Summary
| Version | 3.2.0 |
| License | BSD-3-Clause |
| Build type | AMENT_CMAKE |
| Use | RECOMMENDED |
Repository Summary
| Checkout URI | https://github.com/MOLAorg/mola.git |
| VCS Type | git |
| VCS Version | develop |
| Last Updated | 2026-09-04 |
| Dev Status | DEVELOPED |
| Released | RELEASED |
| Contributing |
Help Wanted (-)
Good First Issues (-) Pull Requests to Review (-) |
Package Description
Additional Links
Maintainers
- Jose-Luis Blanco-Claraco
Authors
mola_bridge_ros2
RawDataSource acting as a bidirectional bridge between ROS2 and MOLA modules.
Can be used to:
- ROS2->MOLA: Interface a real sensor using a ROS driver node and run SLAM with it. See
mola_lidar_odometrydemos. - MOLA->ROS2: Expose a dataset as ROS2 topics, from any of the datasets supported by MOLA. Example: kitti
- ROS2<->MOLA: Run SLAM on a live sensor stream, then send back the reconstructed map and trajectory to ROS for further processing or visualization in RViz. See
mola_lidar_odometrydemos.
If you want to run SLAM on a rosbag, the module mola_input_rosbag2 provides
a more convenient interface, e.g. allows fast-forwarding or skipping parts of a bag.
Building this module requires ROS 2 to be installed, and its setup.bash
activation script being sourced before invoking CMake to configure and build MOLA.
See package docs for instructions and options to install ROS prerequisites.
Provided MOLA modules:
-
BridgeROS2, type RawDataSourceBase.
Build and install
Refer to the root MOLA repository.
Docs and examples
See this package page in the documentation.
License
This package is released under the BSD 3-clause license.
Changelog for package mola_bridge_ros2
3.2.0 (2026-08-21)
- Merge pull request #198 from Zeal-Robotics/fix/bridge_ros2-tf-buffer-staleness fix(bridge_ros2): keep the TF buffer current under bridge executor load
- fix(bridge_ros2): give the TF listener its own spin thread The listener was constructed with spin_thread=false, against tf2's own default, on the grounds that the bridge already spins rosNode_ and a second spinner would be redundant. That holds only while the bridge executor keeps up with /tf, and makes buffer freshness a function of everything else the node is handling --sensor callbacks, timers, map publishing. When it does not keep up, the failure is silent: lookups still succeed, they just answer from a buffer that is behind, and the resulting poses look plausible. With spin_thread=true the /tf and /tf_static subscriptions move to a callback group and executor the listener owns, so ingestion is independent of the bridge executor's load. No new sharing is introduced. The buffer is already read from other threads --publishLocalizationTf() from the localization source's thread, transform_tree() from whichever module calls it -- and tf2::BufferCore serialises readers and writers on a single mutex. The listener's group is created with automatically_add_to_executor_with_node=false, so add_node() does not adopt it and no second executor can dispatch those subscriptions. Its destructor cancels and joins its thread, and it is declared after tf_buffer_ and rosNode_, so that happens while both are still alive.
- fix(bridge_ros2): drain the ROS queues instead of one message per topic The ROS thread polls [spin_some()]{.title-ref} on a 10 ms sleep. That loop replaced a blocking [rclcpp::spin()]{.title-ref} so the destructor could stop the thread via [shouldExit_]{.title-ref}, and the sleep was only ever there to keep the flag poll from busy-waiting. But [spin_some()]{.title-ref} collects the ready set once and executes each ready entity at most once per call, so the pair caps every subscription at roughly one message per 10 ms and puts a 10 ms floor under handling anything. Any topic arriving faster than ~100 Hz therefore keeps its subscription queue permanently full, and every message the node sees is stale by the whole queue depth. [/tf]{.title-ref} is the worst case: it aggregates every broadcaster on the graph, so on a robot publishing a few hundred transforms/s the listener's KeepLast(100) queue leaves the TF buffer several hundred ms behind. The visible symptom is REP-105 composition falling back to the stale odom transform with "extrapolation into the future" while the odom broadcaster is publishing on time and a normally-spun listener on the same graph reads it as current. A 200 Hz IMU on the same node loses half its samples the same way. [spin_once(timeout)]{.title-ref} blocks until there is work while still bounding how long [shouldExit_]{.title-ref} goes unchecked, and [spin_all()]{.title-ref} then drains whatever else is ready. Both are needed: [spin_some()]{.title-ref} and [spin_all()]{.title-ref} each call [wait_for_work(0ms)]{.title-ref}, so [spin_all()]{.title-ref} alone returns immediately when idle and would busy-wait. With work pending [spin_once()]{.title-ref} returns at once, so no iteration sleeps while a queue is non-empty. Cost is that the two bounds stack: worst case for observing [shouldExit_]{.title-ref} goes from 10 ms to 20 ms. Measured with two TF listeners on the same [/tf]{.title-ref}, one per spin strategy: draining fully leaves the buffer 12.6 ms behind the broadcaster, taking one message per 10 ms tick leaves it 358 ms behind. A blocking [spin()]{.title-ref} cancelled via [executor.cancel()]{.title-ref} would remove the poll loop altogether and is the better end state, but [cancel()]{.title-ref} racing the [spinning.exchange(true)]{.title-ref} in [spin()]{.title-ref} means the destructor has to retry until the thread joins. That is left as a separate change.
- Merge remote-tracking branch 'origin/feat/map-frame-gauge-change' into feat/map-frame-gauge-change
- Merge branch 'develop' into feat/map-frame-gauge-change
- Contributors: Jose Luis Blanco-Claraco, Robin Van Cauwenbergh
3.1.1 (2026-08-10)
- fix build in ros rolling (newer gcc)
- fix format
- mola_bridge_ros2: use tf2_ros .hpp headers instead of deprecated .h Avoids #warning deprecation spam on newer ROS2 distros while building unchanged from Humble to Rolling.
- Contributors: Jose Luis Blanco Claraco, Jose Luis Blanco-Claraco
3.1.0 (2026-08-06)
- Add mola::TransformTreeSource: expose the /tf tree to other MOLA modules (#188) * Add mola::TransformTreeSource: expose the /tf tree to other modules New mola_kernel interface letting a data source publish its tree of coordinate frames, so consumers (e.g. a LiDAR-odometry viewer) can draw a robot's joints as it moves. transform_tree(root) returns the subtree below 'root' with poses already resolved against it. The filtering is done in the source, which is what owns the transform buffer, so a consumer never receives nor walks unrelated subtrees. The interface carries no ROS/tf2 type, keeping mola_kernel ROS-independent. Implemented by Rosbag1Dataset (separate repo), Rosbag2Dataset and BridgeROS2. No locking is added around the subtree walk: tf2::BufferCore guards its own internals, which is also what lets BridgeROS2's TransformListener feed the buffer from its own thread.
File truncated at 100 lines see the full file
Package Dependencies
System Dependencies
Dependant Packages
Launch files
Messages
Services
Plugins
Recent questions tagged mola_bridge_ros2 at Robotics Stack Exchange
|
mola_bridge_ros2 package from mola repomola mola_bridge_ros2 mola_demos mola_input_lidar_bin_dataset mola_input_rawlog mola_input_rosbag2 mola_input_video mola_kernel mola_launcher mola_metric_maps mola_msgs mola_pose_list mola_relocalization mola_traj_tools mola_viz mola_viz_imgui mola_yaml |
ROS Distro
|
Package Summary
| Version | 3.2.0 |
| License | BSD-3-Clause |
| Build type | AMENT_CMAKE |
| Use | RECOMMENDED |
Repository Summary
| Checkout URI | https://github.com/MOLAorg/mola.git |
| VCS Type | git |
| VCS Version | develop |
| Last Updated | 2026-09-04 |
| Dev Status | DEVELOPED |
| Released | RELEASED |
| Contributing |
Help Wanted (-)
Good First Issues (-) Pull Requests to Review (-) |
Package Description
Additional Links
Maintainers
- Jose-Luis Blanco-Claraco
Authors
mola_bridge_ros2
RawDataSource acting as a bidirectional bridge between ROS2 and MOLA modules.
Can be used to:
- ROS2->MOLA: Interface a real sensor using a ROS driver node and run SLAM with it. See
mola_lidar_odometrydemos. - MOLA->ROS2: Expose a dataset as ROS2 topics, from any of the datasets supported by MOLA. Example: kitti
- ROS2<->MOLA: Run SLAM on a live sensor stream, then send back the reconstructed map and trajectory to ROS for further processing or visualization in RViz. See
mola_lidar_odometrydemos.
If you want to run SLAM on a rosbag, the module mola_input_rosbag2 provides
a more convenient interface, e.g. allows fast-forwarding or skipping parts of a bag.
Building this module requires ROS 2 to be installed, and its setup.bash
activation script being sourced before invoking CMake to configure and build MOLA.
See package docs for instructions and options to install ROS prerequisites.
Provided MOLA modules:
-
BridgeROS2, type RawDataSourceBase.
Build and install
Refer to the root MOLA repository.
Docs and examples
See this package page in the documentation.
License
This package is released under the BSD 3-clause license.
Changelog for package mola_bridge_ros2
3.2.0 (2026-08-21)
- Merge pull request #198 from Zeal-Robotics/fix/bridge_ros2-tf-buffer-staleness fix(bridge_ros2): keep the TF buffer current under bridge executor load
- fix(bridge_ros2): give the TF listener its own spin thread The listener was constructed with spin_thread=false, against tf2's own default, on the grounds that the bridge already spins rosNode_ and a second spinner would be redundant. That holds only while the bridge executor keeps up with /tf, and makes buffer freshness a function of everything else the node is handling --sensor callbacks, timers, map publishing. When it does not keep up, the failure is silent: lookups still succeed, they just answer from a buffer that is behind, and the resulting poses look plausible. With spin_thread=true the /tf and /tf_static subscriptions move to a callback group and executor the listener owns, so ingestion is independent of the bridge executor's load. No new sharing is introduced. The buffer is already read from other threads --publishLocalizationTf() from the localization source's thread, transform_tree() from whichever module calls it -- and tf2::BufferCore serialises readers and writers on a single mutex. The listener's group is created with automatically_add_to_executor_with_node=false, so add_node() does not adopt it and no second executor can dispatch those subscriptions. Its destructor cancels and joins its thread, and it is declared after tf_buffer_ and rosNode_, so that happens while both are still alive.
- fix(bridge_ros2): drain the ROS queues instead of one message per topic The ROS thread polls [spin_some()]{.title-ref} on a 10 ms sleep. That loop replaced a blocking [rclcpp::spin()]{.title-ref} so the destructor could stop the thread via [shouldExit_]{.title-ref}, and the sleep was only ever there to keep the flag poll from busy-waiting. But [spin_some()]{.title-ref} collects the ready set once and executes each ready entity at most once per call, so the pair caps every subscription at roughly one message per 10 ms and puts a 10 ms floor under handling anything. Any topic arriving faster than ~100 Hz therefore keeps its subscription queue permanently full, and every message the node sees is stale by the whole queue depth. [/tf]{.title-ref} is the worst case: it aggregates every broadcaster on the graph, so on a robot publishing a few hundred transforms/s the listener's KeepLast(100) queue leaves the TF buffer several hundred ms behind. The visible symptom is REP-105 composition falling back to the stale odom transform with "extrapolation into the future" while the odom broadcaster is publishing on time and a normally-spun listener on the same graph reads it as current. A 200 Hz IMU on the same node loses half its samples the same way. [spin_once(timeout)]{.title-ref} blocks until there is work while still bounding how long [shouldExit_]{.title-ref} goes unchecked, and [spin_all()]{.title-ref} then drains whatever else is ready. Both are needed: [spin_some()]{.title-ref} and [spin_all()]{.title-ref} each call [wait_for_work(0ms)]{.title-ref}, so [spin_all()]{.title-ref} alone returns immediately when idle and would busy-wait. With work pending [spin_once()]{.title-ref} returns at once, so no iteration sleeps while a queue is non-empty. Cost is that the two bounds stack: worst case for observing [shouldExit_]{.title-ref} goes from 10 ms to 20 ms. Measured with two TF listeners on the same [/tf]{.title-ref}, one per spin strategy: draining fully leaves the buffer 12.6 ms behind the broadcaster, taking one message per 10 ms tick leaves it 358 ms behind. A blocking [spin()]{.title-ref} cancelled via [executor.cancel()]{.title-ref} would remove the poll loop altogether and is the better end state, but [cancel()]{.title-ref} racing the [spinning.exchange(true)]{.title-ref} in [spin()]{.title-ref} means the destructor has to retry until the thread joins. That is left as a separate change.
- Merge remote-tracking branch 'origin/feat/map-frame-gauge-change' into feat/map-frame-gauge-change
- Merge branch 'develop' into feat/map-frame-gauge-change
- Contributors: Jose Luis Blanco-Claraco, Robin Van Cauwenbergh
3.1.1 (2026-08-10)
- fix build in ros rolling (newer gcc)
- fix format
- mola_bridge_ros2: use tf2_ros .hpp headers instead of deprecated .h Avoids #warning deprecation spam on newer ROS2 distros while building unchanged from Humble to Rolling.
- Contributors: Jose Luis Blanco Claraco, Jose Luis Blanco-Claraco
3.1.0 (2026-08-06)
- Add mola::TransformTreeSource: expose the /tf tree to other MOLA modules (#188) * Add mola::TransformTreeSource: expose the /tf tree to other modules New mola_kernel interface letting a data source publish its tree of coordinate frames, so consumers (e.g. a LiDAR-odometry viewer) can draw a robot's joints as it moves. transform_tree(root) returns the subtree below 'root' with poses already resolved against it. The filtering is done in the source, which is what owns the transform buffer, so a consumer never receives nor walks unrelated subtrees. The interface carries no ROS/tf2 type, keeping mola_kernel ROS-independent. Implemented by Rosbag1Dataset (separate repo), Rosbag2Dataset and BridgeROS2. No locking is added around the subtree walk: tf2::BufferCore guards its own internals, which is also what lets BridgeROS2's TransformListener feed the buffer from its own thread.
File truncated at 100 lines see the full file
Package Dependencies
System Dependencies
Dependant Packages
Launch files
Messages
Services
Plugins
Recent questions tagged mola_bridge_ros2 at Robotics Stack Exchange
|
mola_bridge_ros2 package from mola repomola mola_bridge_ros2 mola_demos mola_input_lidar_bin_dataset mola_input_rawlog mola_input_rosbag2 mola_input_video mola_kernel mola_launcher mola_metric_maps mola_msgs mola_pose_list mola_relocalization mola_traj_tools mola_viz mola_viz_imgui mola_yaml |
ROS Distro
|
Package Summary
| Version | 3.2.0 |
| License | BSD-3-Clause |
| Build type | AMENT_CMAKE |
| Use | RECOMMENDED |
Repository Summary
| Checkout URI | https://github.com/MOLAorg/mola.git |
| VCS Type | git |
| VCS Version | develop |
| Last Updated | 2026-09-04 |
| Dev Status | DEVELOPED |
| Released | RELEASED |
| Contributing |
Help Wanted (-)
Good First Issues (-) Pull Requests to Review (-) |
Package Description
Additional Links
Maintainers
- Jose-Luis Blanco-Claraco
Authors
mola_bridge_ros2
RawDataSource acting as a bidirectional bridge between ROS2 and MOLA modules.
Can be used to:
- ROS2->MOLA: Interface a real sensor using a ROS driver node and run SLAM with it. See
mola_lidar_odometrydemos. - MOLA->ROS2: Expose a dataset as ROS2 topics, from any of the datasets supported by MOLA. Example: kitti
- ROS2<->MOLA: Run SLAM on a live sensor stream, then send back the reconstructed map and trajectory to ROS for further processing or visualization in RViz. See
mola_lidar_odometrydemos.
If you want to run SLAM on a rosbag, the module mola_input_rosbag2 provides
a more convenient interface, e.g. allows fast-forwarding or skipping parts of a bag.
Building this module requires ROS 2 to be installed, and its setup.bash
activation script being sourced before invoking CMake to configure and build MOLA.
See package docs for instructions and options to install ROS prerequisites.
Provided MOLA modules:
-
BridgeROS2, type RawDataSourceBase.
Build and install
Refer to the root MOLA repository.
Docs and examples
See this package page in the documentation.
License
This package is released under the BSD 3-clause license.
Changelog for package mola_bridge_ros2
3.2.0 (2026-08-21)
- Merge pull request #198 from Zeal-Robotics/fix/bridge_ros2-tf-buffer-staleness fix(bridge_ros2): keep the TF buffer current under bridge executor load
- fix(bridge_ros2): give the TF listener its own spin thread The listener was constructed with spin_thread=false, against tf2's own default, on the grounds that the bridge already spins rosNode_ and a second spinner would be redundant. That holds only while the bridge executor keeps up with /tf, and makes buffer freshness a function of everything else the node is handling --sensor callbacks, timers, map publishing. When it does not keep up, the failure is silent: lookups still succeed, they just answer from a buffer that is behind, and the resulting poses look plausible. With spin_thread=true the /tf and /tf_static subscriptions move to a callback group and executor the listener owns, so ingestion is independent of the bridge executor's load. No new sharing is introduced. The buffer is already read from other threads --publishLocalizationTf() from the localization source's thread, transform_tree() from whichever module calls it -- and tf2::BufferCore serialises readers and writers on a single mutex. The listener's group is created with automatically_add_to_executor_with_node=false, so add_node() does not adopt it and no second executor can dispatch those subscriptions. Its destructor cancels and joins its thread, and it is declared after tf_buffer_ and rosNode_, so that happens while both are still alive.
- fix(bridge_ros2): drain the ROS queues instead of one message per topic The ROS thread polls [spin_some()]{.title-ref} on a 10 ms sleep. That loop replaced a blocking [rclcpp::spin()]{.title-ref} so the destructor could stop the thread via [shouldExit_]{.title-ref}, and the sleep was only ever there to keep the flag poll from busy-waiting. But [spin_some()]{.title-ref} collects the ready set once and executes each ready entity at most once per call, so the pair caps every subscription at roughly one message per 10 ms and puts a 10 ms floor under handling anything. Any topic arriving faster than ~100 Hz therefore keeps its subscription queue permanently full, and every message the node sees is stale by the whole queue depth. [/tf]{.title-ref} is the worst case: it aggregates every broadcaster on the graph, so on a robot publishing a few hundred transforms/s the listener's KeepLast(100) queue leaves the TF buffer several hundred ms behind. The visible symptom is REP-105 composition falling back to the stale odom transform with "extrapolation into the future" while the odom broadcaster is publishing on time and a normally-spun listener on the same graph reads it as current. A 200 Hz IMU on the same node loses half its samples the same way. [spin_once(timeout)]{.title-ref} blocks until there is work while still bounding how long [shouldExit_]{.title-ref} goes unchecked, and [spin_all()]{.title-ref} then drains whatever else is ready. Both are needed: [spin_some()]{.title-ref} and [spin_all()]{.title-ref} each call [wait_for_work(0ms)]{.title-ref}, so [spin_all()]{.title-ref} alone returns immediately when idle and would busy-wait. With work pending [spin_once()]{.title-ref} returns at once, so no iteration sleeps while a queue is non-empty. Cost is that the two bounds stack: worst case for observing [shouldExit_]{.title-ref} goes from 10 ms to 20 ms. Measured with two TF listeners on the same [/tf]{.title-ref}, one per spin strategy: draining fully leaves the buffer 12.6 ms behind the broadcaster, taking one message per 10 ms tick leaves it 358 ms behind. A blocking [spin()]{.title-ref} cancelled via [executor.cancel()]{.title-ref} would remove the poll loop altogether and is the better end state, but [cancel()]{.title-ref} racing the [spinning.exchange(true)]{.title-ref} in [spin()]{.title-ref} means the destructor has to retry until the thread joins. That is left as a separate change.
- Merge remote-tracking branch 'origin/feat/map-frame-gauge-change' into feat/map-frame-gauge-change
- Merge branch 'develop' into feat/map-frame-gauge-change
- Contributors: Jose Luis Blanco-Claraco, Robin Van Cauwenbergh
3.1.1 (2026-08-10)
- fix build in ros rolling (newer gcc)
- fix format
- mola_bridge_ros2: use tf2_ros .hpp headers instead of deprecated .h Avoids #warning deprecation spam on newer ROS2 distros while building unchanged from Humble to Rolling.
- Contributors: Jose Luis Blanco Claraco, Jose Luis Blanco-Claraco
3.1.0 (2026-08-06)
- Add mola::TransformTreeSource: expose the /tf tree to other MOLA modules (#188) * Add mola::TransformTreeSource: expose the /tf tree to other modules New mola_kernel interface letting a data source publish its tree of coordinate frames, so consumers (e.g. a LiDAR-odometry viewer) can draw a robot's joints as it moves. transform_tree(root) returns the subtree below 'root' with poses already resolved against it. The filtering is done in the source, which is what owns the transform buffer, so a consumer never receives nor walks unrelated subtrees. The interface carries no ROS/tf2 type, keeping mola_kernel ROS-independent. Implemented by Rosbag1Dataset (separate repo), Rosbag2Dataset and BridgeROS2. No locking is added around the subtree walk: tf2::BufferCore guards its own internals, which is also what lets BridgeROS2's TransformListener feed the buffer from its own thread.
File truncated at 100 lines see the full file
Package Dependencies
System Dependencies
Dependant Packages
Launch files
Messages
Services
Plugins
Recent questions tagged mola_bridge_ros2 at Robotics Stack Exchange
|
mola_bridge_ros2 package from mola repomola mola_bridge_ros2 mola_demos mola_input_lidar_bin_dataset mola_input_rawlog mola_input_rosbag2 mola_input_video mola_kernel mola_launcher mola_metric_maps mola_msgs mola_pose_list mola_relocalization mola_traj_tools mola_viz mola_viz_imgui mola_yaml |
ROS Distro
|
Package Summary
| Version | 3.2.0 |
| License | BSD-3-Clause |
| Build type | AMENT_CMAKE |
| Use | RECOMMENDED |
Repository Summary
| Checkout URI | https://github.com/MOLAorg/mola.git |
| VCS Type | git |
| VCS Version | develop |
| Last Updated | 2026-09-04 |
| Dev Status | DEVELOPED |
| Released | RELEASED |
| Contributing |
Help Wanted (-)
Good First Issues (-) Pull Requests to Review (-) |
Package Description
Additional Links
Maintainers
- Jose-Luis Blanco-Claraco
Authors
mola_bridge_ros2
RawDataSource acting as a bidirectional bridge between ROS2 and MOLA modules.
Can be used to:
- ROS2->MOLA: Interface a real sensor using a ROS driver node and run SLAM with it. See
mola_lidar_odometrydemos. - MOLA->ROS2: Expose a dataset as ROS2 topics, from any of the datasets supported by MOLA. Example: kitti
- ROS2<->MOLA: Run SLAM on a live sensor stream, then send back the reconstructed map and trajectory to ROS for further processing or visualization in RViz. See
mola_lidar_odometrydemos.
If you want to run SLAM on a rosbag, the module mola_input_rosbag2 provides
a more convenient interface, e.g. allows fast-forwarding or skipping parts of a bag.
Building this module requires ROS 2 to be installed, and its setup.bash
activation script being sourced before invoking CMake to configure and build MOLA.
See package docs for instructions and options to install ROS prerequisites.
Provided MOLA modules:
-
BridgeROS2, type RawDataSourceBase.
Build and install
Refer to the root MOLA repository.
Docs and examples
See this package page in the documentation.
License
This package is released under the BSD 3-clause license.
Changelog for package mola_bridge_ros2
3.2.0 (2026-08-21)
- Merge pull request #198 from Zeal-Robotics/fix/bridge_ros2-tf-buffer-staleness fix(bridge_ros2): keep the TF buffer current under bridge executor load
- fix(bridge_ros2): give the TF listener its own spin thread The listener was constructed with spin_thread=false, against tf2's own default, on the grounds that the bridge already spins rosNode_ and a second spinner would be redundant. That holds only while the bridge executor keeps up with /tf, and makes buffer freshness a function of everything else the node is handling --sensor callbacks, timers, map publishing. When it does not keep up, the failure is silent: lookups still succeed, they just answer from a buffer that is behind, and the resulting poses look plausible. With spin_thread=true the /tf and /tf_static subscriptions move to a callback group and executor the listener owns, so ingestion is independent of the bridge executor's load. No new sharing is introduced. The buffer is already read from other threads --publishLocalizationTf() from the localization source's thread, transform_tree() from whichever module calls it -- and tf2::BufferCore serialises readers and writers on a single mutex. The listener's group is created with automatically_add_to_executor_with_node=false, so add_node() does not adopt it and no second executor can dispatch those subscriptions. Its destructor cancels and joins its thread, and it is declared after tf_buffer_ and rosNode_, so that happens while both are still alive.
- fix(bridge_ros2): drain the ROS queues instead of one message per topic The ROS thread polls [spin_some()]{.title-ref} on a 10 ms sleep. That loop replaced a blocking [rclcpp::spin()]{.title-ref} so the destructor could stop the thread via [shouldExit_]{.title-ref}, and the sleep was only ever there to keep the flag poll from busy-waiting. But [spin_some()]{.title-ref} collects the ready set once and executes each ready entity at most once per call, so the pair caps every subscription at roughly one message per 10 ms and puts a 10 ms floor under handling anything. Any topic arriving faster than ~100 Hz therefore keeps its subscription queue permanently full, and every message the node sees is stale by the whole queue depth. [/tf]{.title-ref} is the worst case: it aggregates every broadcaster on the graph, so on a robot publishing a few hundred transforms/s the listener's KeepLast(100) queue leaves the TF buffer several hundred ms behind. The visible symptom is REP-105 composition falling back to the stale odom transform with "extrapolation into the future" while the odom broadcaster is publishing on time and a normally-spun listener on the same graph reads it as current. A 200 Hz IMU on the same node loses half its samples the same way. [spin_once(timeout)]{.title-ref} blocks until there is work while still bounding how long [shouldExit_]{.title-ref} goes unchecked, and [spin_all()]{.title-ref} then drains whatever else is ready. Both are needed: [spin_some()]{.title-ref} and [spin_all()]{.title-ref} each call [wait_for_work(0ms)]{.title-ref}, so [spin_all()]{.title-ref} alone returns immediately when idle and would busy-wait. With work pending [spin_once()]{.title-ref} returns at once, so no iteration sleeps while a queue is non-empty. Cost is that the two bounds stack: worst case for observing [shouldExit_]{.title-ref} goes from 10 ms to 20 ms. Measured with two TF listeners on the same [/tf]{.title-ref}, one per spin strategy: draining fully leaves the buffer 12.6 ms behind the broadcaster, taking one message per 10 ms tick leaves it 358 ms behind. A blocking [spin()]{.title-ref} cancelled via [executor.cancel()]{.title-ref} would remove the poll loop altogether and is the better end state, but [cancel()]{.title-ref} racing the [spinning.exchange(true)]{.title-ref} in [spin()]{.title-ref} means the destructor has to retry until the thread joins. That is left as a separate change.
- Merge remote-tracking branch 'origin/feat/map-frame-gauge-change' into feat/map-frame-gauge-change
- Merge branch 'develop' into feat/map-frame-gauge-change
- Contributors: Jose Luis Blanco-Claraco, Robin Van Cauwenbergh
3.1.1 (2026-08-10)
- fix build in ros rolling (newer gcc)
- fix format
- mola_bridge_ros2: use tf2_ros .hpp headers instead of deprecated .h Avoids #warning deprecation spam on newer ROS2 distros while building unchanged from Humble to Rolling.
- Contributors: Jose Luis Blanco Claraco, Jose Luis Blanco-Claraco
3.1.0 (2026-08-06)
- Add mola::TransformTreeSource: expose the /tf tree to other MOLA modules (#188) * Add mola::TransformTreeSource: expose the /tf tree to other modules New mola_kernel interface letting a data source publish its tree of coordinate frames, so consumers (e.g. a LiDAR-odometry viewer) can draw a robot's joints as it moves. transform_tree(root) returns the subtree below 'root' with poses already resolved against it. The filtering is done in the source, which is what owns the transform buffer, so a consumer never receives nor walks unrelated subtrees. The interface carries no ROS/tf2 type, keeping mola_kernel ROS-independent. Implemented by Rosbag1Dataset (separate repo), Rosbag2Dataset and BridgeROS2. No locking is added around the subtree walk: tf2::BufferCore guards its own internals, which is also what lets BridgeROS2's TransformListener feed the buffer from its own thread.
File truncated at 100 lines see the full file
Package Dependencies
System Dependencies
Dependant Packages
Launch files
Messages
Services
Plugins
Recent questions tagged mola_bridge_ros2 at Robotics Stack Exchange
|
mola_bridge_ros2 package from mola repomola mola_bridge_ros2 mola_demos mola_input_lidar_bin_dataset mola_input_rawlog mola_input_rosbag2 mola_input_video mola_kernel mola_launcher mola_metric_maps mola_msgs mola_pose_list mola_relocalization mola_traj_tools mola_viz mola_viz_imgui mola_yaml |
ROS Distro
|
Package Summary
| Version | 3.2.0 |
| License | BSD-3-Clause |
| Build type | AMENT_CMAKE |
| Use | RECOMMENDED |
Repository Summary
| Checkout URI | https://github.com/MOLAorg/mola.git |
| VCS Type | git |
| VCS Version | develop |
| Last Updated | 2026-09-04 |
| Dev Status | DEVELOPED |
| Released | RELEASED |
| Contributing |
Help Wanted (-)
Good First Issues (-) Pull Requests to Review (-) |
Package Description
Additional Links
Maintainers
- Jose-Luis Blanco-Claraco
Authors
mola_bridge_ros2
RawDataSource acting as a bidirectional bridge between ROS2 and MOLA modules.
Can be used to:
- ROS2->MOLA: Interface a real sensor using a ROS driver node and run SLAM with it. See
mola_lidar_odometrydemos. - MOLA->ROS2: Expose a dataset as ROS2 topics, from any of the datasets supported by MOLA. Example: kitti
- ROS2<->MOLA: Run SLAM on a live sensor stream, then send back the reconstructed map and trajectory to ROS for further processing or visualization in RViz. See
mola_lidar_odometrydemos.
If you want to run SLAM on a rosbag, the module mola_input_rosbag2 provides
a more convenient interface, e.g. allows fast-forwarding or skipping parts of a bag.
Building this module requires ROS 2 to be installed, and its setup.bash
activation script being sourced before invoking CMake to configure and build MOLA.
See package docs for instructions and options to install ROS prerequisites.
Provided MOLA modules:
-
BridgeROS2, type RawDataSourceBase.
Build and install
Refer to the root MOLA repository.
Docs and examples
See this package page in the documentation.
License
This package is released under the BSD 3-clause license.
Changelog for package mola_bridge_ros2
3.2.0 (2026-08-21)
- Merge pull request #198 from Zeal-Robotics/fix/bridge_ros2-tf-buffer-staleness fix(bridge_ros2): keep the TF buffer current under bridge executor load
- fix(bridge_ros2): give the TF listener its own spin thread The listener was constructed with spin_thread=false, against tf2's own default, on the grounds that the bridge already spins rosNode_ and a second spinner would be redundant. That holds only while the bridge executor keeps up with /tf, and makes buffer freshness a function of everything else the node is handling --sensor callbacks, timers, map publishing. When it does not keep up, the failure is silent: lookups still succeed, they just answer from a buffer that is behind, and the resulting poses look plausible. With spin_thread=true the /tf and /tf_static subscriptions move to a callback group and executor the listener owns, so ingestion is independent of the bridge executor's load. No new sharing is introduced. The buffer is already read from other threads --publishLocalizationTf() from the localization source's thread, transform_tree() from whichever module calls it -- and tf2::BufferCore serialises readers and writers on a single mutex. The listener's group is created with automatically_add_to_executor_with_node=false, so add_node() does not adopt it and no second executor can dispatch those subscriptions. Its destructor cancels and joins its thread, and it is declared after tf_buffer_ and rosNode_, so that happens while both are still alive.
- fix(bridge_ros2): drain the ROS queues instead of one message per topic The ROS thread polls [spin_some()]{.title-ref} on a 10 ms sleep. That loop replaced a blocking [rclcpp::spin()]{.title-ref} so the destructor could stop the thread via [shouldExit_]{.title-ref}, and the sleep was only ever there to keep the flag poll from busy-waiting. But [spin_some()]{.title-ref} collects the ready set once and executes each ready entity at most once per call, so the pair caps every subscription at roughly one message per 10 ms and puts a 10 ms floor under handling anything. Any topic arriving faster than ~100 Hz therefore keeps its subscription queue permanently full, and every message the node sees is stale by the whole queue depth. [/tf]{.title-ref} is the worst case: it aggregates every broadcaster on the graph, so on a robot publishing a few hundred transforms/s the listener's KeepLast(100) queue leaves the TF buffer several hundred ms behind. The visible symptom is REP-105 composition falling back to the stale odom transform with "extrapolation into the future" while the odom broadcaster is publishing on time and a normally-spun listener on the same graph reads it as current. A 200 Hz IMU on the same node loses half its samples the same way. [spin_once(timeout)]{.title-ref} blocks until there is work while still bounding how long [shouldExit_]{.title-ref} goes unchecked, and [spin_all()]{.title-ref} then drains whatever else is ready. Both are needed: [spin_some()]{.title-ref} and [spin_all()]{.title-ref} each call [wait_for_work(0ms)]{.title-ref}, so [spin_all()]{.title-ref} alone returns immediately when idle and would busy-wait. With work pending [spin_once()]{.title-ref} returns at once, so no iteration sleeps while a queue is non-empty. Cost is that the two bounds stack: worst case for observing [shouldExit_]{.title-ref} goes from 10 ms to 20 ms. Measured with two TF listeners on the same [/tf]{.title-ref}, one per spin strategy: draining fully leaves the buffer 12.6 ms behind the broadcaster, taking one message per 10 ms tick leaves it 358 ms behind. A blocking [spin()]{.title-ref} cancelled via [executor.cancel()]{.title-ref} would remove the poll loop altogether and is the better end state, but [cancel()]{.title-ref} racing the [spinning.exchange(true)]{.title-ref} in [spin()]{.title-ref} means the destructor has to retry until the thread joins. That is left as a separate change.
- Merge remote-tracking branch 'origin/feat/map-frame-gauge-change' into feat/map-frame-gauge-change
- Merge branch 'develop' into feat/map-frame-gauge-change
- Contributors: Jose Luis Blanco-Claraco, Robin Van Cauwenbergh
3.1.1 (2026-08-10)
- fix build in ros rolling (newer gcc)
- fix format
- mola_bridge_ros2: use tf2_ros .hpp headers instead of deprecated .h Avoids #warning deprecation spam on newer ROS2 distros while building unchanged from Humble to Rolling.
- Contributors: Jose Luis Blanco Claraco, Jose Luis Blanco-Claraco
3.1.0 (2026-08-06)
- Add mola::TransformTreeSource: expose the /tf tree to other MOLA modules (#188) * Add mola::TransformTreeSource: expose the /tf tree to other modules New mola_kernel interface letting a data source publish its tree of coordinate frames, so consumers (e.g. a LiDAR-odometry viewer) can draw a robot's joints as it moves. transform_tree(root) returns the subtree below 'root' with poses already resolved against it. The filtering is done in the source, which is what owns the transform buffer, so a consumer never receives nor walks unrelated subtrees. The interface carries no ROS/tf2 type, keeping mola_kernel ROS-independent. Implemented by Rosbag1Dataset (separate repo), Rosbag2Dataset and BridgeROS2. No locking is added around the subtree walk: tf2::BufferCore guards its own internals, which is also what lets BridgeROS2's TransformListener feed the buffer from its own thread.
File truncated at 100 lines see the full file
Package Dependencies
System Dependencies
Dependant Packages
Launch files
Messages
Services
Plugins
Recent questions tagged mola_bridge_ros2 at Robotics Stack Exchange
|
mola_bridge_ros2 package from mola repomola mola_bridge_ros2 mola_demos mola_input_lidar_bin_dataset mola_input_rawlog mola_input_rosbag2 mola_input_video mola_kernel mola_launcher mola_metric_maps mola_msgs mola_pose_list mola_relocalization mola_traj_tools mola_viz mola_viz_imgui mola_yaml |
ROS Distro
|
Package Summary
| Version | 3.2.0 |
| License | BSD-3-Clause |
| Build type | AMENT_CMAKE |
| Use | RECOMMENDED |
Repository Summary
| Checkout URI | https://github.com/MOLAorg/mola.git |
| VCS Type | git |
| VCS Version | develop |
| Last Updated | 2026-09-04 |
| Dev Status | DEVELOPED |
| Released | RELEASED |
| Contributing |
Help Wanted (-)
Good First Issues (-) Pull Requests to Review (-) |
Package Description
Additional Links
Maintainers
- Jose-Luis Blanco-Claraco
Authors
mola_bridge_ros2
RawDataSource acting as a bidirectional bridge between ROS2 and MOLA modules.
Can be used to:
- ROS2->MOLA: Interface a real sensor using a ROS driver node and run SLAM with it. See
mola_lidar_odometrydemos. - MOLA->ROS2: Expose a dataset as ROS2 topics, from any of the datasets supported by MOLA. Example: kitti
- ROS2<->MOLA: Run SLAM on a live sensor stream, then send back the reconstructed map and trajectory to ROS for further processing or visualization in RViz. See
mola_lidar_odometrydemos.
If you want to run SLAM on a rosbag, the module mola_input_rosbag2 provides
a more convenient interface, e.g. allows fast-forwarding or skipping parts of a bag.
Building this module requires ROS 2 to be installed, and its setup.bash
activation script being sourced before invoking CMake to configure and build MOLA.
See package docs for instructions and options to install ROS prerequisites.
Provided MOLA modules:
-
BridgeROS2, type RawDataSourceBase.
Build and install
Refer to the root MOLA repository.
Docs and examples
See this package page in the documentation.
License
This package is released under the BSD 3-clause license.
Changelog for package mola_bridge_ros2
3.2.0 (2026-08-21)
- Merge pull request #198 from Zeal-Robotics/fix/bridge_ros2-tf-buffer-staleness fix(bridge_ros2): keep the TF buffer current under bridge executor load
- fix(bridge_ros2): give the TF listener its own spin thread The listener was constructed with spin_thread=false, against tf2's own default, on the grounds that the bridge already spins rosNode_ and a second spinner would be redundant. That holds only while the bridge executor keeps up with /tf, and makes buffer freshness a function of everything else the node is handling --sensor callbacks, timers, map publishing. When it does not keep up, the failure is silent: lookups still succeed, they just answer from a buffer that is behind, and the resulting poses look plausible. With spin_thread=true the /tf and /tf_static subscriptions move to a callback group and executor the listener owns, so ingestion is independent of the bridge executor's load. No new sharing is introduced. The buffer is already read from other threads --publishLocalizationTf() from the localization source's thread, transform_tree() from whichever module calls it -- and tf2::BufferCore serialises readers and writers on a single mutex. The listener's group is created with automatically_add_to_executor_with_node=false, so add_node() does not adopt it and no second executor can dispatch those subscriptions. Its destructor cancels and joins its thread, and it is declared after tf_buffer_ and rosNode_, so that happens while both are still alive.
- fix(bridge_ros2): drain the ROS queues instead of one message per topic The ROS thread polls [spin_some()]{.title-ref} on a 10 ms sleep. That loop replaced a blocking [rclcpp::spin()]{.title-ref} so the destructor could stop the thread via [shouldExit_]{.title-ref}, and the sleep was only ever there to keep the flag poll from busy-waiting. But [spin_some()]{.title-ref} collects the ready set once and executes each ready entity at most once per call, so the pair caps every subscription at roughly one message per 10 ms and puts a 10 ms floor under handling anything. Any topic arriving faster than ~100 Hz therefore keeps its subscription queue permanently full, and every message the node sees is stale by the whole queue depth. [/tf]{.title-ref} is the worst case: it aggregates every broadcaster on the graph, so on a robot publishing a few hundred transforms/s the listener's KeepLast(100) queue leaves the TF buffer several hundred ms behind. The visible symptom is REP-105 composition falling back to the stale odom transform with "extrapolation into the future" while the odom broadcaster is publishing on time and a normally-spun listener on the same graph reads it as current. A 200 Hz IMU on the same node loses half its samples the same way. [spin_once(timeout)]{.title-ref} blocks until there is work while still bounding how long [shouldExit_]{.title-ref} goes unchecked, and [spin_all()]{.title-ref} then drains whatever else is ready. Both are needed: [spin_some()]{.title-ref} and [spin_all()]{.title-ref} each call [wait_for_work(0ms)]{.title-ref}, so [spin_all()]{.title-ref} alone returns immediately when idle and would busy-wait. With work pending [spin_once()]{.title-ref} returns at once, so no iteration sleeps while a queue is non-empty. Cost is that the two bounds stack: worst case for observing [shouldExit_]{.title-ref} goes from 10 ms to 20 ms. Measured with two TF listeners on the same [/tf]{.title-ref}, one per spin strategy: draining fully leaves the buffer 12.6 ms behind the broadcaster, taking one message per 10 ms tick leaves it 358 ms behind. A blocking [spin()]{.title-ref} cancelled via [executor.cancel()]{.title-ref} would remove the poll loop altogether and is the better end state, but [cancel()]{.title-ref} racing the [spinning.exchange(true)]{.title-ref} in [spin()]{.title-ref} means the destructor has to retry until the thread joins. That is left as a separate change.
- Merge remote-tracking branch 'origin/feat/map-frame-gauge-change' into feat/map-frame-gauge-change
- Merge branch 'develop' into feat/map-frame-gauge-change
- Contributors: Jose Luis Blanco-Claraco, Robin Van Cauwenbergh
3.1.1 (2026-08-10)
- fix build in ros rolling (newer gcc)
- fix format
- mola_bridge_ros2: use tf2_ros .hpp headers instead of deprecated .h Avoids #warning deprecation spam on newer ROS2 distros while building unchanged from Humble to Rolling.
- Contributors: Jose Luis Blanco Claraco, Jose Luis Blanco-Claraco
3.1.0 (2026-08-06)
- Add mola::TransformTreeSource: expose the /tf tree to other MOLA modules (#188) * Add mola::TransformTreeSource: expose the /tf tree to other modules New mola_kernel interface letting a data source publish its tree of coordinate frames, so consumers (e.g. a LiDAR-odometry viewer) can draw a robot's joints as it moves. transform_tree(root) returns the subtree below 'root' with poses already resolved against it. The filtering is done in the source, which is what owns the transform buffer, so a consumer never receives nor walks unrelated subtrees. The interface carries no ROS/tf2 type, keeping mola_kernel ROS-independent. Implemented by Rosbag1Dataset (separate repo), Rosbag2Dataset and BridgeROS2. No locking is added around the subtree walk: tf2::BufferCore guards its own internals, which is also what lets BridgeROS2's TransformListener feed the buffer from its own thread.
File truncated at 100 lines see the full file
Package Dependencies
System Dependencies
Dependant Packages
Launch files
Messages
Services
Plugins
Recent questions tagged mola_bridge_ros2 at Robotics Stack Exchange
|
mola_bridge_ros2 package from mola repomola mola_bridge_ros2 mola_demos mola_input_lidar_bin_dataset mola_input_rawlog mola_input_rosbag2 mola_input_video mola_kernel mola_launcher mola_metric_maps mola_msgs mola_pose_list mola_relocalization mola_traj_tools mola_viz mola_viz_imgui mola_yaml |
ROS Distro
|
Package Summary
| Version | 3.2.0 |
| License | BSD-3-Clause |
| Build type | AMENT_CMAKE |
| Use | RECOMMENDED |
Repository Summary
| Checkout URI | https://github.com/MOLAorg/mola.git |
| VCS Type | git |
| VCS Version | develop |
| Last Updated | 2026-09-04 |
| Dev Status | DEVELOPED |
| Released | RELEASED |
| Contributing |
Help Wanted (-)
Good First Issues (-) Pull Requests to Review (-) |
Package Description
Additional Links
Maintainers
- Jose-Luis Blanco-Claraco
Authors
mola_bridge_ros2
RawDataSource acting as a bidirectional bridge between ROS2 and MOLA modules.
Can be used to:
- ROS2->MOLA: Interface a real sensor using a ROS driver node and run SLAM with it. See
mola_lidar_odometrydemos. - MOLA->ROS2: Expose a dataset as ROS2 topics, from any of the datasets supported by MOLA. Example: kitti
- ROS2<->MOLA: Run SLAM on a live sensor stream, then send back the reconstructed map and trajectory to ROS for further processing or visualization in RViz. See
mola_lidar_odometrydemos.
If you want to run SLAM on a rosbag, the module mola_input_rosbag2 provides
a more convenient interface, e.g. allows fast-forwarding or skipping parts of a bag.
Building this module requires ROS 2 to be installed, and its setup.bash
activation script being sourced before invoking CMake to configure and build MOLA.
See package docs for instructions and options to install ROS prerequisites.
Provided MOLA modules:
-
BridgeROS2, type RawDataSourceBase.
Build and install
Refer to the root MOLA repository.
Docs and examples
See this package page in the documentation.
License
This package is released under the BSD 3-clause license.
Changelog for package mola_bridge_ros2
3.2.0 (2026-08-21)
- Merge pull request #198 from Zeal-Robotics/fix/bridge_ros2-tf-buffer-staleness fix(bridge_ros2): keep the TF buffer current under bridge executor load
- fix(bridge_ros2): give the TF listener its own spin thread The listener was constructed with spin_thread=false, against tf2's own default, on the grounds that the bridge already spins rosNode_ and a second spinner would be redundant. That holds only while the bridge executor keeps up with /tf, and makes buffer freshness a function of everything else the node is handling --sensor callbacks, timers, map publishing. When it does not keep up, the failure is silent: lookups still succeed, they just answer from a buffer that is behind, and the resulting poses look plausible. With spin_thread=true the /tf and /tf_static subscriptions move to a callback group and executor the listener owns, so ingestion is independent of the bridge executor's load. No new sharing is introduced. The buffer is already read from other threads --publishLocalizationTf() from the localization source's thread, transform_tree() from whichever module calls it -- and tf2::BufferCore serialises readers and writers on a single mutex. The listener's group is created with automatically_add_to_executor_with_node=false, so add_node() does not adopt it and no second executor can dispatch those subscriptions. Its destructor cancels and joins its thread, and it is declared after tf_buffer_ and rosNode_, so that happens while both are still alive.
- fix(bridge_ros2): drain the ROS queues instead of one message per topic The ROS thread polls [spin_some()]{.title-ref} on a 10 ms sleep. That loop replaced a blocking [rclcpp::spin()]{.title-ref} so the destructor could stop the thread via [shouldExit_]{.title-ref}, and the sleep was only ever there to keep the flag poll from busy-waiting. But [spin_some()]{.title-ref} collects the ready set once and executes each ready entity at most once per call, so the pair caps every subscription at roughly one message per 10 ms and puts a 10 ms floor under handling anything. Any topic arriving faster than ~100 Hz therefore keeps its subscription queue permanently full, and every message the node sees is stale by the whole queue depth. [/tf]{.title-ref} is the worst case: it aggregates every broadcaster on the graph, so on a robot publishing a few hundred transforms/s the listener's KeepLast(100) queue leaves the TF buffer several hundred ms behind. The visible symptom is REP-105 composition falling back to the stale odom transform with "extrapolation into the future" while the odom broadcaster is publishing on time and a normally-spun listener on the same graph reads it as current. A 200 Hz IMU on the same node loses half its samples the same way. [spin_once(timeout)]{.title-ref} blocks until there is work while still bounding how long [shouldExit_]{.title-ref} goes unchecked, and [spin_all()]{.title-ref} then drains whatever else is ready. Both are needed: [spin_some()]{.title-ref} and [spin_all()]{.title-ref} each call [wait_for_work(0ms)]{.title-ref}, so [spin_all()]{.title-ref} alone returns immediately when idle and would busy-wait. With work pending [spin_once()]{.title-ref} returns at once, so no iteration sleeps while a queue is non-empty. Cost is that the two bounds stack: worst case for observing [shouldExit_]{.title-ref} goes from 10 ms to 20 ms. Measured with two TF listeners on the same [/tf]{.title-ref}, one per spin strategy: draining fully leaves the buffer 12.6 ms behind the broadcaster, taking one message per 10 ms tick leaves it 358 ms behind. A blocking [spin()]{.title-ref} cancelled via [executor.cancel()]{.title-ref} would remove the poll loop altogether and is the better end state, but [cancel()]{.title-ref} racing the [spinning.exchange(true)]{.title-ref} in [spin()]{.title-ref} means the destructor has to retry until the thread joins. That is left as a separate change.
- Merge remote-tracking branch 'origin/feat/map-frame-gauge-change' into feat/map-frame-gauge-change
- Merge branch 'develop' into feat/map-frame-gauge-change
- Contributors: Jose Luis Blanco-Claraco, Robin Van Cauwenbergh
3.1.1 (2026-08-10)
- fix build in ros rolling (newer gcc)
- fix format
- mola_bridge_ros2: use tf2_ros .hpp headers instead of deprecated .h Avoids #warning deprecation spam on newer ROS2 distros while building unchanged from Humble to Rolling.
- Contributors: Jose Luis Blanco Claraco, Jose Luis Blanco-Claraco
3.1.0 (2026-08-06)
- Add mola::TransformTreeSource: expose the /tf tree to other MOLA modules (#188) * Add mola::TransformTreeSource: expose the /tf tree to other modules New mola_kernel interface letting a data source publish its tree of coordinate frames, so consumers (e.g. a LiDAR-odometry viewer) can draw a robot's joints as it moves. transform_tree(root) returns the subtree below 'root' with poses already resolved against it. The filtering is done in the source, which is what owns the transform buffer, so a consumer never receives nor walks unrelated subtrees. The interface carries no ROS/tf2 type, keeping mola_kernel ROS-independent. Implemented by Rosbag1Dataset (separate repo), Rosbag2Dataset and BridgeROS2. No locking is added around the subtree walk: tf2::BufferCore guards its own internals, which is also what lets BridgeROS2's TransformListener feed the buffer from its own thread.
File truncated at 100 lines see the full file
Package Dependencies
System Dependencies
Dependant Packages
| Name | Deps |
|---|---|
| mola | |
| mola_lidar_odometry |
Launch files
Messages
Services
Plugins
Recent questions tagged mola_bridge_ros2 at Robotics Stack Exchange
|
mola_bridge_ros2 package from mola repomola mola_bridge_ros2 mola_demos mola_input_lidar_bin_dataset mola_input_rawlog mola_input_rosbag2 mola_input_video mola_kernel mola_launcher mola_metric_maps mola_msgs mola_pose_list mola_relocalization mola_traj_tools mola_viz mola_viz_imgui mola_yaml |
ROS Distro
|
Package Summary
| Version | 3.2.0 |
| License | BSD-3-Clause |
| Build type | AMENT_CMAKE |
| Use | RECOMMENDED |
Repository Summary
| Checkout URI | https://github.com/MOLAorg/mola.git |
| VCS Type | git |
| VCS Version | develop |
| Last Updated | 2026-09-04 |
| Dev Status | DEVELOPED |
| Released | RELEASED |
| Contributing |
Help Wanted (-)
Good First Issues (-) Pull Requests to Review (-) |
Package Description
Additional Links
Maintainers
- Jose-Luis Blanco-Claraco
Authors
mola_bridge_ros2
RawDataSource acting as a bidirectional bridge between ROS2 and MOLA modules.
Can be used to:
- ROS2->MOLA: Interface a real sensor using a ROS driver node and run SLAM with it. See
mola_lidar_odometrydemos. - MOLA->ROS2: Expose a dataset as ROS2 topics, from any of the datasets supported by MOLA. Example: kitti
- ROS2<->MOLA: Run SLAM on a live sensor stream, then send back the reconstructed map and trajectory to ROS for further processing or visualization in RViz. See
mola_lidar_odometrydemos.
If you want to run SLAM on a rosbag, the module mola_input_rosbag2 provides
a more convenient interface, e.g. allows fast-forwarding or skipping parts of a bag.
Building this module requires ROS 2 to be installed, and its setup.bash
activation script being sourced before invoking CMake to configure and build MOLA.
See package docs for instructions and options to install ROS prerequisites.
Provided MOLA modules:
-
BridgeROS2, type RawDataSourceBase.
Build and install
Refer to the root MOLA repository.
Docs and examples
See this package page in the documentation.
License
This package is released under the BSD 3-clause license.
Changelog for package mola_bridge_ros2
3.2.0 (2026-08-21)
- Merge pull request #198 from Zeal-Robotics/fix/bridge_ros2-tf-buffer-staleness fix(bridge_ros2): keep the TF buffer current under bridge executor load
- fix(bridge_ros2): give the TF listener its own spin thread The listener was constructed with spin_thread=false, against tf2's own default, on the grounds that the bridge already spins rosNode_ and a second spinner would be redundant. That holds only while the bridge executor keeps up with /tf, and makes buffer freshness a function of everything else the node is handling --sensor callbacks, timers, map publishing. When it does not keep up, the failure is silent: lookups still succeed, they just answer from a buffer that is behind, and the resulting poses look plausible. With spin_thread=true the /tf and /tf_static subscriptions move to a callback group and executor the listener owns, so ingestion is independent of the bridge executor's load. No new sharing is introduced. The buffer is already read from other threads --publishLocalizationTf() from the localization source's thread, transform_tree() from whichever module calls it -- and tf2::BufferCore serialises readers and writers on a single mutex. The listener's group is created with automatically_add_to_executor_with_node=false, so add_node() does not adopt it and no second executor can dispatch those subscriptions. Its destructor cancels and joins its thread, and it is declared after tf_buffer_ and rosNode_, so that happens while both are still alive.
- fix(bridge_ros2): drain the ROS queues instead of one message per topic The ROS thread polls [spin_some()]{.title-ref} on a 10 ms sleep. That loop replaced a blocking [rclcpp::spin()]{.title-ref} so the destructor could stop the thread via [shouldExit_]{.title-ref}, and the sleep was only ever there to keep the flag poll from busy-waiting. But [spin_some()]{.title-ref} collects the ready set once and executes each ready entity at most once per call, so the pair caps every subscription at roughly one message per 10 ms and puts a 10 ms floor under handling anything. Any topic arriving faster than ~100 Hz therefore keeps its subscription queue permanently full, and every message the node sees is stale by the whole queue depth. [/tf]{.title-ref} is the worst case: it aggregates every broadcaster on the graph, so on a robot publishing a few hundred transforms/s the listener's KeepLast(100) queue leaves the TF buffer several hundred ms behind. The visible symptom is REP-105 composition falling back to the stale odom transform with "extrapolation into the future" while the odom broadcaster is publishing on time and a normally-spun listener on the same graph reads it as current. A 200 Hz IMU on the same node loses half its samples the same way. [spin_once(timeout)]{.title-ref} blocks until there is work while still bounding how long [shouldExit_]{.title-ref} goes unchecked, and [spin_all()]{.title-ref} then drains whatever else is ready. Both are needed: [spin_some()]{.title-ref} and [spin_all()]{.title-ref} each call [wait_for_work(0ms)]{.title-ref}, so [spin_all()]{.title-ref} alone returns immediately when idle and would busy-wait. With work pending [spin_once()]{.title-ref} returns at once, so no iteration sleeps while a queue is non-empty. Cost is that the two bounds stack: worst case for observing [shouldExit_]{.title-ref} goes from 10 ms to 20 ms. Measured with two TF listeners on the same [/tf]{.title-ref}, one per spin strategy: draining fully leaves the buffer 12.6 ms behind the broadcaster, taking one message per 10 ms tick leaves it 358 ms behind. A blocking [spin()]{.title-ref} cancelled via [executor.cancel()]{.title-ref} would remove the poll loop altogether and is the better end state, but [cancel()]{.title-ref} racing the [spinning.exchange(true)]{.title-ref} in [spin()]{.title-ref} means the destructor has to retry until the thread joins. That is left as a separate change.
- Merge remote-tracking branch 'origin/feat/map-frame-gauge-change' into feat/map-frame-gauge-change
- Merge branch 'develop' into feat/map-frame-gauge-change
- Contributors: Jose Luis Blanco-Claraco, Robin Van Cauwenbergh
3.1.1 (2026-08-10)
- fix build in ros rolling (newer gcc)
- fix format
- mola_bridge_ros2: use tf2_ros .hpp headers instead of deprecated .h Avoids #warning deprecation spam on newer ROS2 distros while building unchanged from Humble to Rolling.
- Contributors: Jose Luis Blanco Claraco, Jose Luis Blanco-Claraco
3.1.0 (2026-08-06)
- Add mola::TransformTreeSource: expose the /tf tree to other MOLA modules (#188) * Add mola::TransformTreeSource: expose the /tf tree to other modules New mola_kernel interface letting a data source publish its tree of coordinate frames, so consumers (e.g. a LiDAR-odometry viewer) can draw a robot's joints as it moves. transform_tree(root) returns the subtree below 'root' with poses already resolved against it. The filtering is done in the source, which is what owns the transform buffer, so a consumer never receives nor walks unrelated subtrees. The interface carries no ROS/tf2 type, keeping mola_kernel ROS-independent. Implemented by Rosbag1Dataset (separate repo), Rosbag2Dataset and BridgeROS2. No locking is added around the subtree walk: tf2::BufferCore guards its own internals, which is also what lets BridgeROS2's TransformListener feed the buffer from its own thread.
File truncated at 100 lines see the full file
Package Dependencies
System Dependencies
Dependant Packages
Launch files
Messages
Services
Plugins
Recent questions tagged mola_bridge_ros2 at Robotics Stack Exchange
|
mola_bridge_ros2 package from mola repomola mola_bridge_ros2 mola_demos mola_input_lidar_bin_dataset mola_input_rawlog mola_input_rosbag2 mola_input_video mola_kernel mola_launcher mola_metric_maps mola_msgs mola_pose_list mola_relocalization mola_traj_tools mola_viz mola_viz_imgui mola_yaml |
ROS Distro
|
Package Summary
| Version | 3.2.0 |
| License | BSD-3-Clause |
| Build type | AMENT_CMAKE |
| Use | RECOMMENDED |
Repository Summary
| Checkout URI | https://github.com/MOLAorg/mola.git |
| VCS Type | git |
| VCS Version | develop |
| Last Updated | 2026-09-04 |
| Dev Status | DEVELOPED |
| Released | RELEASED |
| Contributing |
Help Wanted (-)
Good First Issues (-) Pull Requests to Review (-) |
Package Description
Additional Links
Maintainers
- Jose-Luis Blanco-Claraco
Authors
mola_bridge_ros2
RawDataSource acting as a bidirectional bridge between ROS2 and MOLA modules.
Can be used to:
- ROS2->MOLA: Interface a real sensor using a ROS driver node and run SLAM with it. See
mola_lidar_odometrydemos. - MOLA->ROS2: Expose a dataset as ROS2 topics, from any of the datasets supported by MOLA. Example: kitti
- ROS2<->MOLA: Run SLAM on a live sensor stream, then send back the reconstructed map and trajectory to ROS for further processing or visualization in RViz. See
mola_lidar_odometrydemos.
If you want to run SLAM on a rosbag, the module mola_input_rosbag2 provides
a more convenient interface, e.g. allows fast-forwarding or skipping parts of a bag.
Building this module requires ROS 2 to be installed, and its setup.bash
activation script being sourced before invoking CMake to configure and build MOLA.
See package docs for instructions and options to install ROS prerequisites.
Provided MOLA modules:
-
BridgeROS2, type RawDataSourceBase.
Build and install
Refer to the root MOLA repository.
Docs and examples
See this package page in the documentation.
License
This package is released under the BSD 3-clause license.
Changelog for package mola_bridge_ros2
3.2.0 (2026-08-21)
- Merge pull request #198 from Zeal-Robotics/fix/bridge_ros2-tf-buffer-staleness fix(bridge_ros2): keep the TF buffer current under bridge executor load
- fix(bridge_ros2): give the TF listener its own spin thread The listener was constructed with spin_thread=false, against tf2's own default, on the grounds that the bridge already spins rosNode_ and a second spinner would be redundant. That holds only while the bridge executor keeps up with /tf, and makes buffer freshness a function of everything else the node is handling --sensor callbacks, timers, map publishing. When it does not keep up, the failure is silent: lookups still succeed, they just answer from a buffer that is behind, and the resulting poses look plausible. With spin_thread=true the /tf and /tf_static subscriptions move to a callback group and executor the listener owns, so ingestion is independent of the bridge executor's load. No new sharing is introduced. The buffer is already read from other threads --publishLocalizationTf() from the localization source's thread, transform_tree() from whichever module calls it -- and tf2::BufferCore serialises readers and writers on a single mutex. The listener's group is created with automatically_add_to_executor_with_node=false, so add_node() does not adopt it and no second executor can dispatch those subscriptions. Its destructor cancels and joins its thread, and it is declared after tf_buffer_ and rosNode_, so that happens while both are still alive.
- fix(bridge_ros2): drain the ROS queues instead of one message per topic The ROS thread polls [spin_some()]{.title-ref} on a 10 ms sleep. That loop replaced a blocking [rclcpp::spin()]{.title-ref} so the destructor could stop the thread via [shouldExit_]{.title-ref}, and the sleep was only ever there to keep the flag poll from busy-waiting. But [spin_some()]{.title-ref} collects the ready set once and executes each ready entity at most once per call, so the pair caps every subscription at roughly one message per 10 ms and puts a 10 ms floor under handling anything. Any topic arriving faster than ~100 Hz therefore keeps its subscription queue permanently full, and every message the node sees is stale by the whole queue depth. [/tf]{.title-ref} is the worst case: it aggregates every broadcaster on the graph, so on a robot publishing a few hundred transforms/s the listener's KeepLast(100) queue leaves the TF buffer several hundred ms behind. The visible symptom is REP-105 composition falling back to the stale odom transform with "extrapolation into the future" while the odom broadcaster is publishing on time and a normally-spun listener on the same graph reads it as current. A 200 Hz IMU on the same node loses half its samples the same way. [spin_once(timeout)]{.title-ref} blocks until there is work while still bounding how long [shouldExit_]{.title-ref} goes unchecked, and [spin_all()]{.title-ref} then drains whatever else is ready. Both are needed: [spin_some()]{.title-ref} and [spin_all()]{.title-ref} each call [wait_for_work(0ms)]{.title-ref}, so [spin_all()]{.title-ref} alone returns immediately when idle and would busy-wait. With work pending [spin_once()]{.title-ref} returns at once, so no iteration sleeps while a queue is non-empty. Cost is that the two bounds stack: worst case for observing [shouldExit_]{.title-ref} goes from 10 ms to 20 ms. Measured with two TF listeners on the same [/tf]{.title-ref}, one per spin strategy: draining fully leaves the buffer 12.6 ms behind the broadcaster, taking one message per 10 ms tick leaves it 358 ms behind. A blocking [spin()]{.title-ref} cancelled via [executor.cancel()]{.title-ref} would remove the poll loop altogether and is the better end state, but [cancel()]{.title-ref} racing the [spinning.exchange(true)]{.title-ref} in [spin()]{.title-ref} means the destructor has to retry until the thread joins. That is left as a separate change.
- Merge remote-tracking branch 'origin/feat/map-frame-gauge-change' into feat/map-frame-gauge-change
- Merge branch 'develop' into feat/map-frame-gauge-change
- Contributors: Jose Luis Blanco-Claraco, Robin Van Cauwenbergh
3.1.1 (2026-08-10)
- fix build in ros rolling (newer gcc)
- fix format
- mola_bridge_ros2: use tf2_ros .hpp headers instead of deprecated .h Avoids #warning deprecation spam on newer ROS2 distros while building unchanged from Humble to Rolling.
- Contributors: Jose Luis Blanco Claraco, Jose Luis Blanco-Claraco
3.1.0 (2026-08-06)
- Add mola::TransformTreeSource: expose the /tf tree to other MOLA modules (#188) * Add mola::TransformTreeSource: expose the /tf tree to other modules New mola_kernel interface letting a data source publish its tree of coordinate frames, so consumers (e.g. a LiDAR-odometry viewer) can draw a robot's joints as it moves. transform_tree(root) returns the subtree below 'root' with poses already resolved against it. The filtering is done in the source, which is what owns the transform buffer, so a consumer never receives nor walks unrelated subtrees. The interface carries no ROS/tf2 type, keeping mola_kernel ROS-independent. Implemented by Rosbag1Dataset (separate repo), Rosbag2Dataset and BridgeROS2. No locking is added around the subtree walk: tf2::BufferCore guards its own internals, which is also what lets BridgeROS2's TransformListener feed the buffer from its own thread.
File truncated at 100 lines see the full file
Package Dependencies
System Dependencies
Dependant Packages
Launch files
Messages
Services
Plugins
Recent questions tagged mola_bridge_ros2 at Robotics Stack Exchange
|
mola_bridge_ros2 package from mola repomola mola_bridge_ros2 mola_demos mola_input_lidar_bin_dataset mola_input_rawlog mola_input_rosbag2 mola_input_video mola_kernel mola_launcher mola_metric_maps mola_msgs mola_pose_list mola_relocalization mola_traj_tools mola_viz mola_viz_imgui mola_yaml |
ROS Distro
|
Package Summary
| Version | 3.2.0 |
| License | BSD-3-Clause |
| Build type | AMENT_CMAKE |
| Use | RECOMMENDED |
Repository Summary
| Checkout URI | https://github.com/MOLAorg/mola.git |
| VCS Type | git |
| VCS Version | develop |
| Last Updated | 2026-09-04 |
| Dev Status | DEVELOPED |
| Released | RELEASED |
| Contributing |
Help Wanted (-)
Good First Issues (-) Pull Requests to Review (-) |
Package Description
Additional Links
Maintainers
- Jose-Luis Blanco-Claraco
Authors
mola_bridge_ros2
RawDataSource acting as a bidirectional bridge between ROS2 and MOLA modules.
Can be used to:
- ROS2->MOLA: Interface a real sensor using a ROS driver node and run SLAM with it. See
mola_lidar_odometrydemos. - MOLA->ROS2: Expose a dataset as ROS2 topics, from any of the datasets supported by MOLA. Example: kitti
- ROS2<->MOLA: Run SLAM on a live sensor stream, then send back the reconstructed map and trajectory to ROS for further processing or visualization in RViz. See
mola_lidar_odometrydemos.
If you want to run SLAM on a rosbag, the module mola_input_rosbag2 provides
a more convenient interface, e.g. allows fast-forwarding or skipping parts of a bag.
Building this module requires ROS 2 to be installed, and its setup.bash
activation script being sourced before invoking CMake to configure and build MOLA.
See package docs for instructions and options to install ROS prerequisites.
Provided MOLA modules:
-
BridgeROS2, type RawDataSourceBase.
Build and install
Refer to the root MOLA repository.
Docs and examples
See this package page in the documentation.
License
This package is released under the BSD 3-clause license.
Changelog for package mola_bridge_ros2
3.2.0 (2026-08-21)
- Merge pull request #198 from Zeal-Robotics/fix/bridge_ros2-tf-buffer-staleness fix(bridge_ros2): keep the TF buffer current under bridge executor load
- fix(bridge_ros2): give the TF listener its own spin thread The listener was constructed with spin_thread=false, against tf2's own default, on the grounds that the bridge already spins rosNode_ and a second spinner would be redundant. That holds only while the bridge executor keeps up with /tf, and makes buffer freshness a function of everything else the node is handling --sensor callbacks, timers, map publishing. When it does not keep up, the failure is silent: lookups still succeed, they just answer from a buffer that is behind, and the resulting poses look plausible. With spin_thread=true the /tf and /tf_static subscriptions move to a callback group and executor the listener owns, so ingestion is independent of the bridge executor's load. No new sharing is introduced. The buffer is already read from other threads --publishLocalizationTf() from the localization source's thread, transform_tree() from whichever module calls it -- and tf2::BufferCore serialises readers and writers on a single mutex. The listener's group is created with automatically_add_to_executor_with_node=false, so add_node() does not adopt it and no second executor can dispatch those subscriptions. Its destructor cancels and joins its thread, and it is declared after tf_buffer_ and rosNode_, so that happens while both are still alive.
- fix(bridge_ros2): drain the ROS queues instead of one message per topic The ROS thread polls [spin_some()]{.title-ref} on a 10 ms sleep. That loop replaced a blocking [rclcpp::spin()]{.title-ref} so the destructor could stop the thread via [shouldExit_]{.title-ref}, and the sleep was only ever there to keep the flag poll from busy-waiting. But [spin_some()]{.title-ref} collects the ready set once and executes each ready entity at most once per call, so the pair caps every subscription at roughly one message per 10 ms and puts a 10 ms floor under handling anything. Any topic arriving faster than ~100 Hz therefore keeps its subscription queue permanently full, and every message the node sees is stale by the whole queue depth. [/tf]{.title-ref} is the worst case: it aggregates every broadcaster on the graph, so on a robot publishing a few hundred transforms/s the listener's KeepLast(100) queue leaves the TF buffer several hundred ms behind. The visible symptom is REP-105 composition falling back to the stale odom transform with "extrapolation into the future" while the odom broadcaster is publishing on time and a normally-spun listener on the same graph reads it as current. A 200 Hz IMU on the same node loses half its samples the same way. [spin_once(timeout)]{.title-ref} blocks until there is work while still bounding how long [shouldExit_]{.title-ref} goes unchecked, and [spin_all()]{.title-ref} then drains whatever else is ready. Both are needed: [spin_some()]{.title-ref} and [spin_all()]{.title-ref} each call [wait_for_work(0ms)]{.title-ref}, so [spin_all()]{.title-ref} alone returns immediately when idle and would busy-wait. With work pending [spin_once()]{.title-ref} returns at once, so no iteration sleeps while a queue is non-empty. Cost is that the two bounds stack: worst case for observing [shouldExit_]{.title-ref} goes from 10 ms to 20 ms. Measured with two TF listeners on the same [/tf]{.title-ref}, one per spin strategy: draining fully leaves the buffer 12.6 ms behind the broadcaster, taking one message per 10 ms tick leaves it 358 ms behind. A blocking [spin()]{.title-ref} cancelled via [executor.cancel()]{.title-ref} would remove the poll loop altogether and is the better end state, but [cancel()]{.title-ref} racing the [spinning.exchange(true)]{.title-ref} in [spin()]{.title-ref} means the destructor has to retry until the thread joins. That is left as a separate change.
- Merge remote-tracking branch 'origin/feat/map-frame-gauge-change' into feat/map-frame-gauge-change
- Merge branch 'develop' into feat/map-frame-gauge-change
- Contributors: Jose Luis Blanco-Claraco, Robin Van Cauwenbergh
3.1.1 (2026-08-10)
- fix build in ros rolling (newer gcc)
- fix format
- mola_bridge_ros2: use tf2_ros .hpp headers instead of deprecated .h Avoids #warning deprecation spam on newer ROS2 distros while building unchanged from Humble to Rolling.
- Contributors: Jose Luis Blanco Claraco, Jose Luis Blanco-Claraco
3.1.0 (2026-08-06)
- Add mola::TransformTreeSource: expose the /tf tree to other MOLA modules (#188) * Add mola::TransformTreeSource: expose the /tf tree to other modules New mola_kernel interface letting a data source publish its tree of coordinate frames, so consumers (e.g. a LiDAR-odometry viewer) can draw a robot's joints as it moves. transform_tree(root) returns the subtree below 'root' with poses already resolved against it. The filtering is done in the source, which is what owns the transform buffer, so a consumer never receives nor walks unrelated subtrees. The interface carries no ROS/tf2 type, keeping mola_kernel ROS-independent. Implemented by Rosbag1Dataset (separate repo), Rosbag2Dataset and BridgeROS2. No locking is added around the subtree walk: tf2::BufferCore guards its own internals, which is also what lets BridgeROS2's TransformListener feed the buffer from its own thread.
File truncated at 100 lines see the full file
Package Dependencies
System Dependencies
Dependant Packages
Launch files
Messages
Services
Plugins
Recent questions tagged mola_bridge_ros2 at Robotics Stack Exchange
|
mola_bridge_ros2 package from mola repomola mola_bridge_ros2 mola_demos mola_input_lidar_bin_dataset mola_input_rawlog mola_input_rosbag2 mola_input_video mola_kernel mola_launcher mola_metric_maps mola_msgs mola_pose_list mola_relocalization mola_traj_tools mola_viz mola_viz_imgui mola_yaml |
ROS Distro
|
Package Summary
| Version | 3.2.0 |
| License | BSD-3-Clause |
| Build type | AMENT_CMAKE |
| Use | RECOMMENDED |
Repository Summary
| Checkout URI | https://github.com/MOLAorg/mola.git |
| VCS Type | git |
| VCS Version | develop |
| Last Updated | 2026-09-04 |
| Dev Status | DEVELOPED |
| Released | RELEASED |
| Contributing |
Help Wanted (-)
Good First Issues (-) Pull Requests to Review (-) |
Package Description
Additional Links
Maintainers
- Jose-Luis Blanco-Claraco
Authors
mola_bridge_ros2
RawDataSource acting as a bidirectional bridge between ROS2 and MOLA modules.
Can be used to:
- ROS2->MOLA: Interface a real sensor using a ROS driver node and run SLAM with it. See
mola_lidar_odometrydemos. - MOLA->ROS2: Expose a dataset as ROS2 topics, from any of the datasets supported by MOLA. Example: kitti
- ROS2<->MOLA: Run SLAM on a live sensor stream, then send back the reconstructed map and trajectory to ROS for further processing or visualization in RViz. See
mola_lidar_odometrydemos.
If you want to run SLAM on a rosbag, the module mola_input_rosbag2 provides
a more convenient interface, e.g. allows fast-forwarding or skipping parts of a bag.
Building this module requires ROS 2 to be installed, and its setup.bash
activation script being sourced before invoking CMake to configure and build MOLA.
See package docs for instructions and options to install ROS prerequisites.
Provided MOLA modules:
-
BridgeROS2, type RawDataSourceBase.
Build and install
Refer to the root MOLA repository.
Docs and examples
See this package page in the documentation.
License
This package is released under the BSD 3-clause license.
Changelog for package mola_bridge_ros2
3.2.0 (2026-08-21)
- Merge pull request #198 from Zeal-Robotics/fix/bridge_ros2-tf-buffer-staleness fix(bridge_ros2): keep the TF buffer current under bridge executor load
- fix(bridge_ros2): give the TF listener its own spin thread The listener was constructed with spin_thread=false, against tf2's own default, on the grounds that the bridge already spins rosNode_ and a second spinner would be redundant. That holds only while the bridge executor keeps up with /tf, and makes buffer freshness a function of everything else the node is handling --sensor callbacks, timers, map publishing. When it does not keep up, the failure is silent: lookups still succeed, they just answer from a buffer that is behind, and the resulting poses look plausible. With spin_thread=true the /tf and /tf_static subscriptions move to a callback group and executor the listener owns, so ingestion is independent of the bridge executor's load. No new sharing is introduced. The buffer is already read from other threads --publishLocalizationTf() from the localization source's thread, transform_tree() from whichever module calls it -- and tf2::BufferCore serialises readers and writers on a single mutex. The listener's group is created with automatically_add_to_executor_with_node=false, so add_node() does not adopt it and no second executor can dispatch those subscriptions. Its destructor cancels and joins its thread, and it is declared after tf_buffer_ and rosNode_, so that happens while both are still alive.
- fix(bridge_ros2): drain the ROS queues instead of one message per topic The ROS thread polls [spin_some()]{.title-ref} on a 10 ms sleep. That loop replaced a blocking [rclcpp::spin()]{.title-ref} so the destructor could stop the thread via [shouldExit_]{.title-ref}, and the sleep was only ever there to keep the flag poll from busy-waiting. But [spin_some()]{.title-ref} collects the ready set once and executes each ready entity at most once per call, so the pair caps every subscription at roughly one message per 10 ms and puts a 10 ms floor under handling anything. Any topic arriving faster than ~100 Hz therefore keeps its subscription queue permanently full, and every message the node sees is stale by the whole queue depth. [/tf]{.title-ref} is the worst case: it aggregates every broadcaster on the graph, so on a robot publishing a few hundred transforms/s the listener's KeepLast(100) queue leaves the TF buffer several hundred ms behind. The visible symptom is REP-105 composition falling back to the stale odom transform with "extrapolation into the future" while the odom broadcaster is publishing on time and a normally-spun listener on the same graph reads it as current. A 200 Hz IMU on the same node loses half its samples the same way. [spin_once(timeout)]{.title-ref} blocks until there is work while still bounding how long [shouldExit_]{.title-ref} goes unchecked, and [spin_all()]{.title-ref} then drains whatever else is ready. Both are needed: [spin_some()]{.title-ref} and [spin_all()]{.title-ref} each call [wait_for_work(0ms)]{.title-ref}, so [spin_all()]{.title-ref} alone returns immediately when idle and would busy-wait. With work pending [spin_once()]{.title-ref} returns at once, so no iteration sleeps while a queue is non-empty. Cost is that the two bounds stack: worst case for observing [shouldExit_]{.title-ref} goes from 10 ms to 20 ms. Measured with two TF listeners on the same [/tf]{.title-ref}, one per spin strategy: draining fully leaves the buffer 12.6 ms behind the broadcaster, taking one message per 10 ms tick leaves it 358 ms behind. A blocking [spin()]{.title-ref} cancelled via [executor.cancel()]{.title-ref} would remove the poll loop altogether and is the better end state, but [cancel()]{.title-ref} racing the [spinning.exchange(true)]{.title-ref} in [spin()]{.title-ref} means the destructor has to retry until the thread joins. That is left as a separate change.
- Merge remote-tracking branch 'origin/feat/map-frame-gauge-change' into feat/map-frame-gauge-change
- Merge branch 'develop' into feat/map-frame-gauge-change
- Contributors: Jose Luis Blanco-Claraco, Robin Van Cauwenbergh
3.1.1 (2026-08-10)
- fix build in ros rolling (newer gcc)
- fix format
- mola_bridge_ros2: use tf2_ros .hpp headers instead of deprecated .h Avoids #warning deprecation spam on newer ROS2 distros while building unchanged from Humble to Rolling.
- Contributors: Jose Luis Blanco Claraco, Jose Luis Blanco-Claraco
3.1.0 (2026-08-06)
- Add mola::TransformTreeSource: expose the /tf tree to other MOLA modules (#188) * Add mola::TransformTreeSource: expose the /tf tree to other modules New mola_kernel interface letting a data source publish its tree of coordinate frames, so consumers (e.g. a LiDAR-odometry viewer) can draw a robot's joints as it moves. transform_tree(root) returns the subtree below 'root' with poses already resolved against it. The filtering is done in the source, which is what owns the transform buffer, so a consumer never receives nor walks unrelated subtrees. The interface carries no ROS/tf2 type, keeping mola_kernel ROS-independent. Implemented by Rosbag1Dataset (separate repo), Rosbag2Dataset and BridgeROS2. No locking is added around the subtree walk: tf2::BufferCore guards its own internals, which is also what lets BridgeROS2's TransformListener feed the buffer from its own thread.
File truncated at 100 lines see the full file
Package Dependencies
System Dependencies
Dependant Packages
Launch files
Messages
Services
Plugins
Recent questions tagged mola_bridge_ros2 at Robotics Stack Exchange
|
mola_bridge_ros2 package from mola repomola mola_bridge_ros2 mola_demos mola_input_lidar_bin_dataset mola_input_rawlog mola_input_rosbag2 mola_input_video mola_kernel mola_launcher mola_metric_maps mola_msgs mola_pose_list mola_relocalization mola_traj_tools mola_viz mola_viz_imgui mola_yaml |
ROS Distro
|
Package Summary
| Version | 3.2.0 |
| License | BSD-3-Clause |
| Build type | AMENT_CMAKE |
| Use | RECOMMENDED |
Repository Summary
| Checkout URI | https://github.com/MOLAorg/mola.git |
| VCS Type | git |
| VCS Version | develop |
| Last Updated | 2026-09-04 |
| Dev Status | DEVELOPED |
| Released | RELEASED |
| Contributing |
Help Wanted (-)
Good First Issues (-) Pull Requests to Review (-) |
Package Description
Additional Links
Maintainers
- Jose-Luis Blanco-Claraco
Authors
mola_bridge_ros2
RawDataSource acting as a bidirectional bridge between ROS2 and MOLA modules.
Can be used to:
- ROS2->MOLA: Interface a real sensor using a ROS driver node and run SLAM with it. See
mola_lidar_odometrydemos. - MOLA->ROS2: Expose a dataset as ROS2 topics, from any of the datasets supported by MOLA. Example: kitti
- ROS2<->MOLA: Run SLAM on a live sensor stream, then send back the reconstructed map and trajectory to ROS for further processing or visualization in RViz. See
mola_lidar_odometrydemos.
If you want to run SLAM on a rosbag, the module mola_input_rosbag2 provides
a more convenient interface, e.g. allows fast-forwarding or skipping parts of a bag.
Building this module requires ROS 2 to be installed, and its setup.bash
activation script being sourced before invoking CMake to configure and build MOLA.
See package docs for instructions and options to install ROS prerequisites.
Provided MOLA modules:
-
BridgeROS2, type RawDataSourceBase.
Build and install
Refer to the root MOLA repository.
Docs and examples
See this package page in the documentation.
License
This package is released under the BSD 3-clause license.
Changelog for package mola_bridge_ros2
3.2.0 (2026-08-21)
- Merge pull request #198 from Zeal-Robotics/fix/bridge_ros2-tf-buffer-staleness fix(bridge_ros2): keep the TF buffer current under bridge executor load
- fix(bridge_ros2): give the TF listener its own spin thread The listener was constructed with spin_thread=false, against tf2's own default, on the grounds that the bridge already spins rosNode_ and a second spinner would be redundant. That holds only while the bridge executor keeps up with /tf, and makes buffer freshness a function of everything else the node is handling --sensor callbacks, timers, map publishing. When it does not keep up, the failure is silent: lookups still succeed, they just answer from a buffer that is behind, and the resulting poses look plausible. With spin_thread=true the /tf and /tf_static subscriptions move to a callback group and executor the listener owns, so ingestion is independent of the bridge executor's load. No new sharing is introduced. The buffer is already read from other threads --publishLocalizationTf() from the localization source's thread, transform_tree() from whichever module calls it -- and tf2::BufferCore serialises readers and writers on a single mutex. The listener's group is created with automatically_add_to_executor_with_node=false, so add_node() does not adopt it and no second executor can dispatch those subscriptions. Its destructor cancels and joins its thread, and it is declared after tf_buffer_ and rosNode_, so that happens while both are still alive.
- fix(bridge_ros2): drain the ROS queues instead of one message per topic The ROS thread polls [spin_some()]{.title-ref} on a 10 ms sleep. That loop replaced a blocking [rclcpp::spin()]{.title-ref} so the destructor could stop the thread via [shouldExit_]{.title-ref}, and the sleep was only ever there to keep the flag poll from busy-waiting. But [spin_some()]{.title-ref} collects the ready set once and executes each ready entity at most once per call, so the pair caps every subscription at roughly one message per 10 ms and puts a 10 ms floor under handling anything. Any topic arriving faster than ~100 Hz therefore keeps its subscription queue permanently full, and every message the node sees is stale by the whole queue depth. [/tf]{.title-ref} is the worst case: it aggregates every broadcaster on the graph, so on a robot publishing a few hundred transforms/s the listener's KeepLast(100) queue leaves the TF buffer several hundred ms behind. The visible symptom is REP-105 composition falling back to the stale odom transform with "extrapolation into the future" while the odom broadcaster is publishing on time and a normally-spun listener on the same graph reads it as current. A 200 Hz IMU on the same node loses half its samples the same way. [spin_once(timeout)]{.title-ref} blocks until there is work while still bounding how long [shouldExit_]{.title-ref} goes unchecked, and [spin_all()]{.title-ref} then drains whatever else is ready. Both are needed: [spin_some()]{.title-ref} and [spin_all()]{.title-ref} each call [wait_for_work(0ms)]{.title-ref}, so [spin_all()]{.title-ref} alone returns immediately when idle and would busy-wait. With work pending [spin_once()]{.title-ref} returns at once, so no iteration sleeps while a queue is non-empty. Cost is that the two bounds stack: worst case for observing [shouldExit_]{.title-ref} goes from 10 ms to 20 ms. Measured with two TF listeners on the same [/tf]{.title-ref}, one per spin strategy: draining fully leaves the buffer 12.6 ms behind the broadcaster, taking one message per 10 ms tick leaves it 358 ms behind. A blocking [spin()]{.title-ref} cancelled via [executor.cancel()]{.title-ref} would remove the poll loop altogether and is the better end state, but [cancel()]{.title-ref} racing the [spinning.exchange(true)]{.title-ref} in [spin()]{.title-ref} means the destructor has to retry until the thread joins. That is left as a separate change.
- Merge remote-tracking branch 'origin/feat/map-frame-gauge-change' into feat/map-frame-gauge-change
- Merge branch 'develop' into feat/map-frame-gauge-change
- Contributors: Jose Luis Blanco-Claraco, Robin Van Cauwenbergh
3.1.1 (2026-08-10)
- fix build in ros rolling (newer gcc)
- fix format
- mola_bridge_ros2: use tf2_ros .hpp headers instead of deprecated .h Avoids #warning deprecation spam on newer ROS2 distros while building unchanged from Humble to Rolling.
- Contributors: Jose Luis Blanco Claraco, Jose Luis Blanco-Claraco
3.1.0 (2026-08-06)
- Add mola::TransformTreeSource: expose the /tf tree to other MOLA modules (#188) * Add mola::TransformTreeSource: expose the /tf tree to other modules New mola_kernel interface letting a data source publish its tree of coordinate frames, so consumers (e.g. a LiDAR-odometry viewer) can draw a robot's joints as it moves. transform_tree(root) returns the subtree below 'root' with poses already resolved against it. The filtering is done in the source, which is what owns the transform buffer, so a consumer never receives nor walks unrelated subtrees. The interface carries no ROS/tf2 type, keeping mola_kernel ROS-independent. Implemented by Rosbag1Dataset (separate repo), Rosbag2Dataset and BridgeROS2. No locking is added around the subtree walk: tf2::BufferCore guards its own internals, which is also what lets BridgeROS2's TransformListener feed the buffer from its own thread.
File truncated at 100 lines see the full file
Package Dependencies
System Dependencies
Dependant Packages
Launch files
Messages
Services
Plugins
Recent questions tagged mola_bridge_ros2 at Robotics Stack Exchange
|
mola_bridge_ros2 package from mola repomola mola_bridge_ros2 mola_demos mola_input_lidar_bin_dataset mola_input_rawlog mola_input_rosbag2 mola_input_video mola_kernel mola_launcher mola_metric_maps mola_msgs mola_pose_list mola_relocalization mola_traj_tools mola_viz mola_viz_imgui mola_yaml |
ROS Distro
|
Package Summary
| Version | 3.2.0 |
| License | BSD-3-Clause |
| Build type | AMENT_CMAKE |
| Use | RECOMMENDED |
Repository Summary
| Checkout URI | https://github.com/MOLAorg/mola.git |
| VCS Type | git |
| VCS Version | develop |
| Last Updated | 2026-09-04 |
| Dev Status | DEVELOPED |
| Released | RELEASED |
| Contributing |
Help Wanted (-)
Good First Issues (-) Pull Requests to Review (-) |
Package Description
Additional Links
Maintainers
- Jose-Luis Blanco-Claraco
Authors
mola_bridge_ros2
RawDataSource acting as a bidirectional bridge between ROS2 and MOLA modules.
Can be used to:
- ROS2->MOLA: Interface a real sensor using a ROS driver node and run SLAM with it. See
mola_lidar_odometrydemos. - MOLA->ROS2: Expose a dataset as ROS2 topics, from any of the datasets supported by MOLA. Example: kitti
- ROS2<->MOLA: Run SLAM on a live sensor stream, then send back the reconstructed map and trajectory to ROS for further processing or visualization in RViz. See
mola_lidar_odometrydemos.
If you want to run SLAM on a rosbag, the module mola_input_rosbag2 provides
a more convenient interface, e.g. allows fast-forwarding or skipping parts of a bag.
Building this module requires ROS 2 to be installed, and its setup.bash
activation script being sourced before invoking CMake to configure and build MOLA.
See package docs for instructions and options to install ROS prerequisites.
Provided MOLA modules:
-
BridgeROS2, type RawDataSourceBase.
Build and install
Refer to the root MOLA repository.
Docs and examples
See this package page in the documentation.
License
This package is released under the BSD 3-clause license.
Changelog for package mola_bridge_ros2
3.2.0 (2026-08-21)
- Merge pull request #198 from Zeal-Robotics/fix/bridge_ros2-tf-buffer-staleness fix(bridge_ros2): keep the TF buffer current under bridge executor load
- fix(bridge_ros2): give the TF listener its own spin thread The listener was constructed with spin_thread=false, against tf2's own default, on the grounds that the bridge already spins rosNode_ and a second spinner would be redundant. That holds only while the bridge executor keeps up with /tf, and makes buffer freshness a function of everything else the node is handling --sensor callbacks, timers, map publishing. When it does not keep up, the failure is silent: lookups still succeed, they just answer from a buffer that is behind, and the resulting poses look plausible. With spin_thread=true the /tf and /tf_static subscriptions move to a callback group and executor the listener owns, so ingestion is independent of the bridge executor's load. No new sharing is introduced. The buffer is already read from other threads --publishLocalizationTf() from the localization source's thread, transform_tree() from whichever module calls it -- and tf2::BufferCore serialises readers and writers on a single mutex. The listener's group is created with automatically_add_to_executor_with_node=false, so add_node() does not adopt it and no second executor can dispatch those subscriptions. Its destructor cancels and joins its thread, and it is declared after tf_buffer_ and rosNode_, so that happens while both are still alive.
- fix(bridge_ros2): drain the ROS queues instead of one message per topic The ROS thread polls [spin_some()]{.title-ref} on a 10 ms sleep. That loop replaced a blocking [rclcpp::spin()]{.title-ref} so the destructor could stop the thread via [shouldExit_]{.title-ref}, and the sleep was only ever there to keep the flag poll from busy-waiting. But [spin_some()]{.title-ref} collects the ready set once and executes each ready entity at most once per call, so the pair caps every subscription at roughly one message per 10 ms and puts a 10 ms floor under handling anything. Any topic arriving faster than ~100 Hz therefore keeps its subscription queue permanently full, and every message the node sees is stale by the whole queue depth. [/tf]{.title-ref} is the worst case: it aggregates every broadcaster on the graph, so on a robot publishing a few hundred transforms/s the listener's KeepLast(100) queue leaves the TF buffer several hundred ms behind. The visible symptom is REP-105 composition falling back to the stale odom transform with "extrapolation into the future" while the odom broadcaster is publishing on time and a normally-spun listener on the same graph reads it as current. A 200 Hz IMU on the same node loses half its samples the same way. [spin_once(timeout)]{.title-ref} blocks until there is work while still bounding how long [shouldExit_]{.title-ref} goes unchecked, and [spin_all()]{.title-ref} then drains whatever else is ready. Both are needed: [spin_some()]{.title-ref} and [spin_all()]{.title-ref} each call [wait_for_work(0ms)]{.title-ref}, so [spin_all()]{.title-ref} alone returns immediately when idle and would busy-wait. With work pending [spin_once()]{.title-ref} returns at once, so no iteration sleeps while a queue is non-empty. Cost is that the two bounds stack: worst case for observing [shouldExit_]{.title-ref} goes from 10 ms to 20 ms. Measured with two TF listeners on the same [/tf]{.title-ref}, one per spin strategy: draining fully leaves the buffer 12.6 ms behind the broadcaster, taking one message per 10 ms tick leaves it 358 ms behind. A blocking [spin()]{.title-ref} cancelled via [executor.cancel()]{.title-ref} would remove the poll loop altogether and is the better end state, but [cancel()]{.title-ref} racing the [spinning.exchange(true)]{.title-ref} in [spin()]{.title-ref} means the destructor has to retry until the thread joins. That is left as a separate change.
- Merge remote-tracking branch 'origin/feat/map-frame-gauge-change' into feat/map-frame-gauge-change
- Merge branch 'develop' into feat/map-frame-gauge-change
- Contributors: Jose Luis Blanco-Claraco, Robin Van Cauwenbergh
3.1.1 (2026-08-10)
- fix build in ros rolling (newer gcc)
- fix format
- mola_bridge_ros2: use tf2_ros .hpp headers instead of deprecated .h Avoids #warning deprecation spam on newer ROS2 distros while building unchanged from Humble to Rolling.
- Contributors: Jose Luis Blanco Claraco, Jose Luis Blanco-Claraco
3.1.0 (2026-08-06)
- Add mola::TransformTreeSource: expose the /tf tree to other MOLA modules (#188) * Add mola::TransformTreeSource: expose the /tf tree to other modules New mola_kernel interface letting a data source publish its tree of coordinate frames, so consumers (e.g. a LiDAR-odometry viewer) can draw a robot's joints as it moves. transform_tree(root) returns the subtree below 'root' with poses already resolved against it. The filtering is done in the source, which is what owns the transform buffer, so a consumer never receives nor walks unrelated subtrees. The interface carries no ROS/tf2 type, keeping mola_kernel ROS-independent. Implemented by Rosbag1Dataset (separate repo), Rosbag2Dataset and BridgeROS2. No locking is added around the subtree walk: tf2::BufferCore guards its own internals, which is also what lets BridgeROS2's TransformListener feed the buffer from its own thread.
File truncated at 100 lines see the full file
Package Dependencies
System Dependencies
Dependant Packages
Launch files
Messages
Services
Plugins
Recent questions tagged mola_bridge_ros2 at Robotics Stack Exchange
|
mola_bridge_ros2 package from mola repomola mola_bridge_ros2 mola_demos mola_input_lidar_bin_dataset mola_input_rawlog mola_input_rosbag2 mola_input_video mola_kernel mola_launcher mola_metric_maps mola_msgs mola_pose_list mola_relocalization mola_traj_tools mola_viz mola_viz_imgui mola_yaml |
ROS Distro
|
Package Summary
| Version | 3.2.0 |
| License | BSD-3-Clause |
| Build type | AMENT_CMAKE |
| Use | RECOMMENDED |
Repository Summary
| Checkout URI | https://github.com/MOLAorg/mola.git |
| VCS Type | git |
| VCS Version | develop |
| Last Updated | 2026-09-04 |
| Dev Status | DEVELOPED |
| Released | RELEASED |
| Contributing |
Help Wanted (-)
Good First Issues (-) Pull Requests to Review (-) |
Package Description
Additional Links
Maintainers
- Jose-Luis Blanco-Claraco
Authors
mola_bridge_ros2
RawDataSource acting as a bidirectional bridge between ROS2 and MOLA modules.
Can be used to:
- ROS2->MOLA: Interface a real sensor using a ROS driver node and run SLAM with it. See
mola_lidar_odometrydemos. - MOLA->ROS2: Expose a dataset as ROS2 topics, from any of the datasets supported by MOLA. Example: kitti
- ROS2<->MOLA: Run SLAM on a live sensor stream, then send back the reconstructed map and trajectory to ROS for further processing or visualization in RViz. See
mola_lidar_odometrydemos.
If you want to run SLAM on a rosbag, the module mola_input_rosbag2 provides
a more convenient interface, e.g. allows fast-forwarding or skipping parts of a bag.
Building this module requires ROS 2 to be installed, and its setup.bash
activation script being sourced before invoking CMake to configure and build MOLA.
See package docs for instructions and options to install ROS prerequisites.
Provided MOLA modules:
-
BridgeROS2, type RawDataSourceBase.
Build and install
Refer to the root MOLA repository.
Docs and examples
See this package page in the documentation.
License
This package is released under the BSD 3-clause license.
Changelog for package mola_bridge_ros2
3.2.0 (2026-08-21)
- Merge pull request #198 from Zeal-Robotics/fix/bridge_ros2-tf-buffer-staleness fix(bridge_ros2): keep the TF buffer current under bridge executor load
- fix(bridge_ros2): give the TF listener its own spin thread The listener was constructed with spin_thread=false, against tf2's own default, on the grounds that the bridge already spins rosNode_ and a second spinner would be redundant. That holds only while the bridge executor keeps up with /tf, and makes buffer freshness a function of everything else the node is handling --sensor callbacks, timers, map publishing. When it does not keep up, the failure is silent: lookups still succeed, they just answer from a buffer that is behind, and the resulting poses look plausible. With spin_thread=true the /tf and /tf_static subscriptions move to a callback group and executor the listener owns, so ingestion is independent of the bridge executor's load. No new sharing is introduced. The buffer is already read from other threads --publishLocalizationTf() from the localization source's thread, transform_tree() from whichever module calls it -- and tf2::BufferCore serialises readers and writers on a single mutex. The listener's group is created with automatically_add_to_executor_with_node=false, so add_node() does not adopt it and no second executor can dispatch those subscriptions. Its destructor cancels and joins its thread, and it is declared after tf_buffer_ and rosNode_, so that happens while both are still alive.
- fix(bridge_ros2): drain the ROS queues instead of one message per topic The ROS thread polls [spin_some()]{.title-ref} on a 10 ms sleep. That loop replaced a blocking [rclcpp::spin()]{.title-ref} so the destructor could stop the thread via [shouldExit_]{.title-ref}, and the sleep was only ever there to keep the flag poll from busy-waiting. But [spin_some()]{.title-ref} collects the ready set once and executes each ready entity at most once per call, so the pair caps every subscription at roughly one message per 10 ms and puts a 10 ms floor under handling anything. Any topic arriving faster than ~100 Hz therefore keeps its subscription queue permanently full, and every message the node sees is stale by the whole queue depth. [/tf]{.title-ref} is the worst case: it aggregates every broadcaster on the graph, so on a robot publishing a few hundred transforms/s the listener's KeepLast(100) queue leaves the TF buffer several hundred ms behind. The visible symptom is REP-105 composition falling back to the stale odom transform with "extrapolation into the future" while the odom broadcaster is publishing on time and a normally-spun listener on the same graph reads it as current. A 200 Hz IMU on the same node loses half its samples the same way. [spin_once(timeout)]{.title-ref} blocks until there is work while still bounding how long [shouldExit_]{.title-ref} goes unchecked, and [spin_all()]{.title-ref} then drains whatever else is ready. Both are needed: [spin_some()]{.title-ref} and [spin_all()]{.title-ref} each call [wait_for_work(0ms)]{.title-ref}, so [spin_all()]{.title-ref} alone returns immediately when idle and would busy-wait. With work pending [spin_once()]{.title-ref} returns at once, so no iteration sleeps while a queue is non-empty. Cost is that the two bounds stack: worst case for observing [shouldExit_]{.title-ref} goes from 10 ms to 20 ms. Measured with two TF listeners on the same [/tf]{.title-ref}, one per spin strategy: draining fully leaves the buffer 12.6 ms behind the broadcaster, taking one message per 10 ms tick leaves it 358 ms behind. A blocking [spin()]{.title-ref} cancelled via [executor.cancel()]{.title-ref} would remove the poll loop altogether and is the better end state, but [cancel()]{.title-ref} racing the [spinning.exchange(true)]{.title-ref} in [spin()]{.title-ref} means the destructor has to retry until the thread joins. That is left as a separate change.
- Merge remote-tracking branch 'origin/feat/map-frame-gauge-change' into feat/map-frame-gauge-change
- Merge branch 'develop' into feat/map-frame-gauge-change
- Contributors: Jose Luis Blanco-Claraco, Robin Van Cauwenbergh
3.1.1 (2026-08-10)
- fix build in ros rolling (newer gcc)
- fix format
- mola_bridge_ros2: use tf2_ros .hpp headers instead of deprecated .h Avoids #warning deprecation spam on newer ROS2 distros while building unchanged from Humble to Rolling.
- Contributors: Jose Luis Blanco Claraco, Jose Luis Blanco-Claraco
3.1.0 (2026-08-06)
- Add mola::TransformTreeSource: expose the /tf tree to other MOLA modules (#188) * Add mola::TransformTreeSource: expose the /tf tree to other modules New mola_kernel interface letting a data source publish its tree of coordinate frames, so consumers (e.g. a LiDAR-odometry viewer) can draw a robot's joints as it moves. transform_tree(root) returns the subtree below 'root' with poses already resolved against it. The filtering is done in the source, which is what owns the transform buffer, so a consumer never receives nor walks unrelated subtrees. The interface carries no ROS/tf2 type, keeping mola_kernel ROS-independent. Implemented by Rosbag1Dataset (separate repo), Rosbag2Dataset and BridgeROS2. No locking is added around the subtree walk: tf2::BufferCore guards its own internals, which is also what lets BridgeROS2's TransformListener feed the buffer from its own thread.
File truncated at 100 lines see the full file