Business

ROS 2 Lyrical Luth: What's New in the 2026 LTS, from EventsCBGExecutor to rosbag2

The Kopik team7 min read

Lyrical Luth, the twelfth ROS 2 distribution, reached general availability on 22 May 2026. It is a long-term support (LTS) release, maintained until May 2031. For most teams the change that matters most is the new Callback Group Events Executor (EventsCBGExecutor) in rclcpp. The release notes measure it at 10% to 15% less CPU than the single- and multi-threaded executors. Around it sit asyncio support in rclpy, zero-copy buffers for uint8[] fields, much better rosbag2 tooling and a fresh platform baseline.

This briefing is written for technical leads at robotics firms, system integrators and university groups deciding when to adopt the new LTS. Figures and names come from the Lyrical release notes, timeline and supported-platforms pages, all of which are indexed in the ROS 2 documentation base.

Five changes that matter in production

1. A cheaper executor

The EventsCBGExecutor replaces wait-set polling with a first-in, first-out events queue. Entities enqueue an event only when they become ready. It builds on the earlier experimental EventsExecutor but adds multithreading and support for multiple time sources, including sim time. The concept page says it can serve as a drop-in replacement for the MultiThreadedExecutor. Adopt it with rclcpp::executors::EventsCBGExecutor in code, or with component_container --executor-type events-cbg for composed systems. One caveat is documented: the events queue currently has no size limit, so an overloaded process can accumulate ready entities without bound.

2. Zero-copy uint8[] fields

In C++, every uint8[] field now has the type rosidl::Buffer<uint8_t> rather than std::vector<uint8_t>. With a suitable rosidl::BufferBackend, images and other byte arrays can travel between nodes without copying them out of, say, GPU memory. The feature is available to publishers and subscribers using rmw_fastrtps_cpp or rmw_zenoh_cpp. Code that relied on the old vector type needs reviewing.

3. Observable, controllable recording

rosbag2 now publishes per-topic message-loss events on events/rosbag2_messages_lost. It offers services to start and stop recording remotely, supports circular recording via --max-bag-files, and gives split files self-describing names. A Python API (rosbag2_py.Recorder and rosbag2_py.Player) replaces the old blocking command-line style helpers.

4. Logging and tracing you can switch at run time

The RCL_LOGGING_IMPLEMENTATION environment variable selects the logging backend without rebuilding rcl. The options are rcl_logging_spdlog (the default), rcl_logging_noop or a custom implementation. Setting TRACETOOLS_RUNTIME_DISABLE=1 stops the tracer from loading. Snapshot-mode tracing keeps a rolling in-memory history that is written to disk only when a snapshot is taken, which the notes describe as a “flight recorder” mode.

5. Robot description improvements

URDF version 1.2 adds quaternions, capsule geometry, and acceleration, deceleration and jerk limits. robot_state_publisher can subscribe to robot_description when use_robot_description_topic is set to true, so that another framework can publish the description. A generic resource_retriever_service lets any node load meshes over the network.

What developers will notice day to day

  • rclpy AsyncNode: runs an asyncio event loop, lets callbacks await service calls and sleeps, and, according to the notes, uses significantly less CPU than the default SingleThreadedExecutor.
  • YAML type tags in parameter files, such as !!str true or !!float 10, to stop rcl guessing the wrong type.
  • Range checks on integer and double arrays declared with a ParameterDescriptor.
  • Launch files: per-message log levels and new string-join and path-join substitutions in XML and YAML.
  • CLI: ros2 param get <param name> across all nodes, ros2 service info --verbose with QoS details, ros2 topic bw /tf /joint_states or --all, and ros2 doctor --report now covering actions, services and environment variables.
  • Build: a new CMake target ament_cmake_ros_core::ament_ros_defaults sets C and C++ versions, and ament_python_install_package() may now be called several times with the same package name.
  • fish shell: source /opt/ros/lyrical/setup.fish.

The new platform and toolchain baseline

Lyrical moves the Tier 1 Linux target to Ubuntu Resolute (26.04), on amd64 and arm64. Windows 11 with VS2022 is Tier 1 on amd64 and RHEL 10 is Tier 2. Ubuntu Noble (24.04) and Debian Trixie are Tier 3 with early end-of-life dates (2029-06-01 and 2028-08-09), and any Tier 3 platform means building from source. The minimum language requirements are C++20, C17 and Python 3.12 to 3.14.

Selected versions at first release on Ubuntu Resolute (from the supported-platforms page)

ComponentVersion
CMake4.2.3
Python3.14.3
Qt6.10.2
OpenCV4.10.0
GazeboJetty (package from OSRF or the community)
Fast-DDS / Cyclone DDS / Zenoh3.6.x / 11.0.x / 1.8.0
Connext DDS7.7.0

The documentation describes these versions as a low watermark. They are captured at first release and not updated as dependencies move on.

What the new executor does not change

It is worth setting expectations with your team. The EventsCBGExecutor changes how ready work is found and queued. It does not change the concurrency rules you have already written into your nodes. The executors page explains that, with more than one thread, actual parallelism still depends on callback groups. A mutually exclusive group never runs its callbacks in parallel, a reentrant group may, and callbacks in different groups may always run in parallel. The same page lists long-standing limits of the classic executors for real-time work, including mixed scheduling semantics, possible priority inversion and no explicit control over callback order. Where strict determinism is needed, it points to alternatives such as the rclcpp WaitSet and the rclc Executor.

Support windows: Lyrical against the alternatives

  • Kilted Kaiju: released 23 May 2025, end-of-life December 2026.
  • Humble Hawksbill: end-of-life May 2027.
  • Jazzy Jalisco: end-of-life May 2029.
  • Lyrical Luth: end-of-life May 2031.
  • Makoa Mata-mata: planned for May 2027, a regular release supported until December 2028.

Waiting for Makoa therefore buys newer features but a much shorter support window than Lyrical. Teams on Kilted have the least time, with roughly three months of support left from the date of this article (October 2026) to December 2026. The documentation also warns that nodes are not guaranteed to communicate across distributions, so a mixed Kilted and Lyrical estate is not a supported configuration.

Recording features worth enabling on day one

For robots deployed on customer sites, the rosbag2 changes may save more engineering time than the executor. The release notes show a circular recording set-up: ros2 bag record --all --max-bag-size 100000000 --max-bag-files 5 keeps at most five split files of about 100 MB each, and deletes the oldest as new ones are created. Split files follow the pattern {counter}_{prefix}_{timestamp}.{extension}. The timestamp uses local time in the format YYYY_MM_DD-HH_MM_SS, so bags pulled off a robot can be put in order without guesswork. To catch data loss early, record with --stats_max_publishing_rate 10 and run ros2 topic echo /events/rosbag2_messages_lost. If all is well, it prints nothing.

A suggested adoption sequence

  1. Build a Lyrical reference machine on Ubuntu 26.04 and run your test suite unchanged, to surface API breaks such as the rosidl::Buffer type change.
  2. Move CMake files away from the deprecated ament_target_dependencies() and onto target_link_libraries() with modern targets.
  3. Measure CPU with the EventsCBGExecutor on representative nodes before making it the default.
  4. Enable rosbag2 loss statistics and circular recording on pilot robots.
  5. Schedule the fleet cut-over system by system, keeping one RMW implementation throughout, as the documentation recommends.

Evaluating the executor on your own nodes

The 10% to 15% figure compares the EventsCBGExecutor with the single- and multi-threaded executors. Your own saving will depend on your callbacks, so measure it. ros2_tracing, now with snapshot and dual-session modes, is one way to compare before and after.

Brief yourself from the release notes

Kopik's ROS 2 base indexes the release notes of every distribution alongside the Lyrical concepts, tutorials and how-to guides. Ask “When does Kilted Kaiju reach end-of-life, and is that before or after the current Lyrical Luth LTS?” and the answer comes with its source.

If your team builds internal tools on top of documentation, the base is also available through the developer API.

Frequently asked questions

What is the headline feature of ROS 2 Lyrical Luth?

For rclcpp users, it is the Callback Group Events Executor (EventsCBGExecutor), which the release notes say uses 10% to 15% less CPU than the single- and multi-threaded executors and adds multithreading and multiple time sources.

How long is Lyrical Luth supported?

Until May 2031. The release timeline says it will then stop receiving updates, including security updates.

Does Lyrical Luth support Ubuntu 24.04?

Only at Tier 3, with an early end-of-life on 2029-06-01, which means building from source. The Tier 1 Ubuntu platform is Resolute (26.04).

Can I use the EventsCBGExecutor with composable nodes?

Yes. Start the container with ros2 run rclcpp_components component_container --executor-type events-cbg, and set the number of threads with the thread_num parameter.

What minimum C++ and Python versions does Lyrical need?

The supported-platforms page lists C++20, C17 and Python 3.12 to 3.14 as minimum language requirements.

Should I wait for Makoa Mata-mata instead of adopting Lyrical?

Makoa is planned for May 2027 as a regular release supported until December 2028, whereas Lyrical is supported until May 2031. If you value a long support window, Lyrical is the documented LTS option.

Get the Kopik newsletter

New knowledge bases, RAG guides and product news. One email every week or two, unsubscribe in one click.

By subscribing you agree to receive our newsletter. We never share your address.