Updates|TIER IV, Inc.

CallbackIsolatedExecutor hands-on: Direct Linux scheduling for ROS 2 callbacks

Written by TIER IV | 6 Oct 2026, 05:08:11

This tech blog features content from a ROSCon JP 2026 presentation by TIER IV engineer Atsushi Yano.

Overview

  1. ROS 2 callbacks are scheduled in a nested manner, by the middleware layer's Executor and the OS layer's scheduler. Standard Executors have a limitation. They do not support setting Linux scheduling attributes (policy, priority and affinity) for individual callbacks.
  2. CallbackIsolatedExecutor (CIE) solves this problem. It is a new Executor that creates a one-to-one correspondence between CallbackGroups and OS threads. Using CIE allows you to apply Linux scheduling attributes directly to ROS 2 callbacks.
  3. This article features a sample application to explain the process in six steps – from installing CIE to applying Linux scheduling. The ROSCon JP presentation was structured so attendees could apply these steps to their own ROS 2 applications the same day.
  4. Almost all major Autoware nodes use CIE. By configuring CIE and scheduling attributes, TIER IV's robotaxis achieved an approximately three- to fivefold improvement in measured worst-case response time.

The design details and performance evaluations of CIE are summarized in a paper accepted at RTAS 2025, a leading conference in the field of real-time systems. The paper is titled "Work in Progress: Middleware-Transparent Callback Enforcement in Commoditized Component-Oriented Real-time Systems." A preprint of the paper is available on arXiv and has also been published by the IEEE.

The implementation is available on GitHub, where you can also find documentation explaining the setup process.

The design and motivation behind CIE were presented at ROSCon JP 2025. This year's presentation assumed the audience had not seen last year's talk. We kept the design overview brief. Instead, we focused on a hands-on guide covering how to use CIE.

Background: Nested scheduling in ROS 2

First, a brief overview of the structure of a ROS 2 application, which consists of a collection of nodes that are functional units. Each node has multiple callbacks. These callbacks receive messages from the topics they subscribe to, execute processing, and publish messages to the next topic. This publish-subscribe relay creates multiple data flows across the entire system. Essentially, a ROS 2 application is a data flow made up of multiple callbacks.

Data flow consisting of multiple callbacks


When and on which CPU core this callback is executed is determined by two schedulers working in tandem.

  • Callback scheduler (middleware layer): This is the ROS 2 Executor. It selects callbacks that are ready to run and assigns them to OS threads under its management. It operates using a round-robin-style algorithm specific to ROS 2.
  • Thread scheduler (OS layer): An OS thread scheduler, such as the one in Linux. It determines when and on which core to run the threads assigned by the Executor.

Nested scheduling in ROS 2 applications


POSIX-compliant operating systems such as Linux allow you to set scheduling attributes (policy, priority and affinity) for each thread to control scheduler behavior. There are three typical policies. Affinity allows you to specify the CPU core on which the thread is scheduled.

Policy

Configurable attributes

Summary

EDF scheduler

(SCHED_DEADLINE)

runtime / period / deadline

Prioritizes the thread with the earliest deadline.

FIFO scheduler

(SCHED_FIFO)

priority (99 - 1)

Executes the highest-priority thread first. Uses FIFO when priorities are equal.

CFS (EEVDF from Linux kernel version 6.6)

(SCHED_OTHER)

nice (-20 - 19)

Allocates CPU time as evenly as possible across all threads. This is the default policy.


The problem is that, as long as you use the standard ROS 2 Executor, you cannot set these scheduling attributes on a per-callback basis, making it difficult to optimize scheduling. Because SingleThreadedExecutor assigns a single thread to handle multiple callbacks, you cannot apply independent settings to each callback. MultiThreadedExecutor randomly assigns callbacks to multiple threads within a thread pool, preventing specific settings from applying to specific callbacks. NB: the recently added EventsExecutor was implemented for a different purpose – such as reducing timer callback release latency – and does not resolve this issue. This structure is the root cause hindering scheduling optimization for ROS 2 applications. CIE solves this problem.


Limitations of standard ROS 2 Executor

Design and implementation of CallbackIsolatedExecutor

The core design of CallbackIsolatedExecutor (CIE) creates a permanent one-to-one correspondence between a CallbackGroup and an OS thread. Since each CallbackGroup is assigned a dedicated OS thread, configuring the scheduling attributes for that thread directly applies those settings to the callbacks. This eliminates the need to consider scheduling at the middleware layer and resolves the issue of nested scheduling.


Resolving nested scheduling with CallbackIsolatedExecutor


Scheduling attributes can be configured for the entire system with just one YAML file. The YAML template is automatically generated – the process is covered in the hands-on section below. Users simply need to fill in each property.

CIE YAML configuration file


The
Thread Configurator Node reads this YAML file and applies the settings to the CIE threads. The Thread Configurator Node uses system calls such as nice(2) , sched_setaffinity(2) , setpriority(2) , sched_setscheduler(2) to set the scheduling attributes for each thread.


Overview of how CIE works


For more information on CIE's design details and performance evaluations, please refer to the RTAS 2025 paper mentioned above.

Six-step guide to per-callback Linux scheduling

Using a sample application, I’ll walk through six steps: from installing CIE to applying Linux scheduling. Similar instructions are also available in the official documentation.

(Optional) Step 0 | Separating CallbackGroups

CIE assigns a thread to each CallbackGroup. Therefore, as a preparatory step, we recommend creating an independent CallbackGroup for any callback that requires strict scheduling control.


// Declare and pass a dedicated CallbackGroup for each callback.

group1_ = create_callback_group(rclcpp::CallbackGroupType::MutuallyExclusive);
group2_ = create_callback_group(rclcpp::CallbackGroupType::MutuallyExclusive);

timer_ = create_wall_timer(3000ms, std::bind(&SampleNode::timer_callback, this), group1_);

rclcpp::SubscriptionOptions options;
options.callback_group = group2_; // Specify the subscription via options.
subscription_ = create_subscription<std_msgs::msg::Int32>("topic_in", 1, cb, options);

Step 1 | Installation

CIE is an independent package and requires no modifications to rcl or rclcpp. It can be installed via apt from the ROS 2 build farm.


sudo apt install ros-$ROS_DISTRO-callback-isolated-executor

You can also install the sample application used in this guide.


sudo apt install ros-$ROS_DISTRO-cie-sample-application

CIE is also included in Agnocast, a ROS 2-compatible zero-copy middleware developed by TIER IV, and can be installed via the Agnocast package. Use this option if you want to use CIE and Agnocast together.

Step 2 | Replacing the Executor

For standalone nodes, modify the line that creates the Executor in the main function. This typically requires changing just one line.


+ #include "callback_isolated_executor/callback_isolated_executor.hpp"


- auto executor = std::make_shared<rclcpp::executors::SingleThreadedExecutor>();
+ auto executor = std::make_shared<CallbackIsolatedExecutor>();

For composable nodes, simply modify the component container in the launch file. You don't need to change a single line of code in the node.


- <node_container pkg="rclcpp_components"

-                 exec="component_container" name="sample_container">
+ <node_container pkg="callback_isolated_executor"
+                 exec="component_container_callback_isolated" name="sample_container">

Step 3 | Creating the YAML template

To create the YAML template, use CIE's prerun node. Launch the target application while the prerun node is running. The prerun node will automatically generate a YAML template file that lists all detected CallbackGroups.


# Terminal 1

ros2 run cie_thread_configurator prerun_node
# Once the target application has launched, exit with Ctrl+C

# Terminal 2
# Launch the target application

The generated template is in the format shown below. The CallbackGroup ID uses the format "node_name@callback_belonging_to_that_CallbackGroup," so you can tell at a glance which entry corresponds to which CallbackGroup. The scheduling attributes are populated with default values.


callback_groups:

- id: /sample_node@Subscription(/topic_in)
  affinity: ~
  policy: SCHED_OTHER
  nice: 0

- id: /sample_node@Timer(1333000000)
  affinity: ~
  policy: SCHED_OTHER
  nice: 0

- id: /sample_node@Timer(3000000000)
  affinity: ~
  policy: SCHED_OTHER
  nice: 0

Step 4 | Configuring scheduling attributes

Set the scheduling attributes for each CallbackGroup in the generated template. Specify the configuration for CFS, FIFO scheduler and EDF scheduler as shown below. Configuration guidelines are covered in the next section.


callback_groups:

# CFS Example: Set nice value and CPU affinity
 - id: xxxxx
   affinity: [0,1]
   policy: SCHED_OTHER
   nice: -10

# FIFO scheduler example: Set real-time priority
 - id: yyyyy
   affinity: [2,3]
   policy: SCHED_FIFO
   priority: 50

# EDF scheduler example: Set runtime / deadline / period (unit: ns)
 - id: zzzzz
   affinity: [0,1]
   policy: SCHED_DEADLINE
   runtime: 10000000
   deadline: 10000000
   period: 20000000

Step 5 | Granting permissions to Thread Configurator

For the Thread Configurator to set scheduling attributes for threads in other processes, you must configure the CAP_SYS_NICE capability. There are two methods to do this.

Method 1: Define Thread Configurator as a systemd service and grant CAP_SYS_NICE. This is the easiest approach.


# thread_configurator.service

[Service]
ExecStart=ros2 run cie_thread_configurator thread_configurator_node
AmbientCapabilities=CAP_SYS_NICE

Method 2: This involves executing setcap on the binary. As noted in the official documentation, this requires extra effort because LD_LIBRARY_PATH is disabled for security reasons.


sudo setcap cap_sys_nice+ep \

$(ros2 pkg prefix cie_thread_configurator)/lib/cie_thread_configurator/thread_configurator_node

Only this single Thread Configurator process requires special permissions. The main application requires no permissions at all. This provides a security advantage by minimizing the scope of permissions.

Step 6 | Launching Thread Configurator and the application

Launch the target ROS 2 application while the Thread Configurator node with the loaded YAML file is running. The scheduling settings are automatically applied.


# Terminal 1 (Not required if defined as a systemd service)
ros2 run cie_thread_configurator thread_configurator_node --ros-args -p config_file:=<your yaml>

# Terminal 2
# Launch the target application

With these six steps, Linux scheduling per callback is ready to run. Replacing the Executor is the only required change to the application code.

How to configure scheduling attributes

CIE enables configuration of scheduling attributes per callback, but how should they actually be set? To address this, the system requirements have to be clarified. Most robotics applications are real-time systems required to produce output within a specified time frame. Autonomous driving systems in particular are hard real-time systems where human lives are at stake. Therefore, a key requirement for autonomous driving systems is to satisfy all time constraints within limited computing resources.

While this problem is not easy to solve, a real-time scheduling research community exists to address this exact challenge. Decades of research assets exist from international conferences such as RTSS, ECRTS and RTAS, and we can utilize these resources. In fact, real-time scheduling research targeting ROS 2 systems alone has produced a vast number of papers, starting with work by Casini et al. (ECRTS 2019). These cover Executor modifications, scheduling attribute assignment algorithms and end-to-end timing analysis. Many of these methods directly analyze the standard ROS 2 Executor – and by extension, nested scheduling.

  • D. Casini, T. Blaß, I. Lütkebohle and B. B. Brandenburg, “Response-Time Analysis of ROS 2 Processing Chains Under Reservation-Based Scheduling,” 2019 31st Euromicro Conference on Real-Time Systems (ECRTS)
  • H. Choi, Y. Xiang and H. Kim, "PiCAS: New Design of Priority-Driven Chain-Aware Scheduling for ROS2," 2021 IEEE 27th Real-Time and Embedded Technology and Applications Symposium (RTAS)
  • H. Sobhani, H. Choi and H. Kim, "Timing Analysis and Priority-driven Enhancements of ROS 2 Multi-threaded Executors," 2023 IEEE 29th Real-Time and Embedded Technology and Applications Symposium (RTAS)
  • H. Teper, M. Günzel, N. Ueter, G. von der Brüggen and J. -J. Chen, "End-To-End Timing Analysis in ROS2," 2022 IEEE Real-Time Systems Symposium (RTSS)

By treating callbacks as vertices and topic communications as edges, a ROS 2 system can be modeled as a directed acyclic graph (DAG). Real-time scheduling for DAGs has been actively researched since around 2010. Researchers continue working to find optimal algorithms.

  • J. Li, J. J. Chen, K. Agrawal, C. Lu, C. Gill and A. Saifullah, "Analysis of Federated and Global Scheduling for Parallel Real-Time Tasks," 2014 26th Euromicro Conference on Real-Time Systems (ECRTS)
  • S. Zhao, X. Dai, I. Bate, A. Burns and W. Chang, "DAG Scheduling and Analysis on Multiprocessor Systems: Exploitation of Parallelism and Dependency," 2020 IEEE Real-Time Systems Symposium (RTSS)
  • H. Takahashi, A. Yano, and T. Azumi, “Probabilistic Schedulability Analysis for Mixed-Criticality DAG Tasks on Multiprocessors,” 2026 38th European Conference on Real-Time Systems (ECRTS)

Until now, these research findings rarely reached deployed ROS 2 systems. Analysis methods built on the assumption of nested scheduling are overly complex to be routinely applied. Meanwhile, theoretical DAG scheduling algorithms do not assume nested scheduling. By structurally eliminating nested scheduling, CIE enables you to directly apply established theory for independently OS-scheduled task groups to ROS 2 callbacks. In short, CIE serves as a bridge connecting the ROS community and the real-time scheduling research community. Once you find a scheduling algorithm from existing research assets that fits your system requirements, you simply set the scheduling attributes based on that approach.

Autoware adoption and track record

In Autoware, open-source software for autonomous driving pioneered by TIER IV, almost all key nodes have been replaced with CIE (Autoware GitHub Discussion). We plan to replace the Executors across all nodes with CIE in the future.

Here, we present the results of applying CIE to TIER IV’s robotaxi and optimizing the scheduling attributes of five bottleneck DAGs: Top LiDAR Preprocessing, Localization, Perception, Planning and Control. For priority assignment, we referenced this paper and adopted a strategy of assigning higher priorities to callbacks belonging to longer paths. This ensures the critical path of the DAG is processed as fast as possible.

DAGs in Autoware


The graphic below shows the response time improvement (from the release of the source vertex to the completion of the tail vertex) across the five DAGs compared to running the default Linux scheduler (CFS) without custom tuning (gray line). These measurements were captured while driving the robotaxi on public roads in Odaiba. The horizontal axis represents elapsed time in seconds.

Comparison between default configuration and CIE optimization


As a result, measured worst-case response times showed an approximate 3- to 5-fold improvement, and jitter was also reduced. For systems that must run heavy workloads on limited computing resources, such as autonomous driving platforms, optimized scheduling can deliver significant performance improvements.

Wrap-up

  • CIE enables per-callback OS scheduling.
  • An active research community focuses on optimal OS scheduling, allowing us to utilize extensive research assets.
  • CIE is already applied across most of Autoware, and we plan to apply it to all nodes in the future.
  • By using CIE and configuring scheduling attributes, TIER IV robotaxis achieved a measured 3- to 5-fold improvement in worst-case response time.

It takes only six steps to get from installation to applying schedules. If you have a ROS 2 application facing response time or jitter challenges, give it a try.

Acknowledgments

This work is based on results obtained from the New Energy and Industrial Technology Development Organization (NEDO) Green Innovation Fund Project “Development of In-vehicle Computing and Simulation Technology for Energy Saving in Electric Vehicles” (JPNP21027).

Atsushi Yano | System Platform Development Department

Atsushi heads the Real-Time Group at TIER IV, working on R&D for OS and middleware to maximize the real-time performance of autonomous driving systems. He is concurrently enrolled in a doctoral program at Saitama University’s Azumi Laboratory, researching real-time scheduling theory for autonomous driving systems.

TIER IV is always on the lookout for passionate individuals to join our journey. If you share our vision of making autonomous driving accessible to all, get in touch.

We’re currently hiring for the following positions:

Visit our careers page to view all job openings.

If you’re unsure which roles fit your experience, or if the current job openings don’t quite match your preferences, you can register your interest here. We’ll contact you when a suitable role becomes available and arrange an informal interview.

Inquiries

  • Media: pr@tier4.jp
  • Business: sales@tier4.jp

Social media

X (Japan/Global) | LinkedIn | Facebook | Instagram | YouTube

More