最新情報|株式会社ティアフォー

CallbackIsolatedExecutorハンズオン:今日から誰でもできるROS 2 CallbackへのLinuxスケジューリング直接適用

作成者: TIER IV|Oct 6, 2026, 5:08:25 AM

本記事は、ROSCon JP 2026にてティアフォーのエンジニアである矢野篤志が行った講演内容をまとめたものです。

講演の概要

  1. ROS 2のCallbackは、ミドルウェアレイヤーのExecutorとOSレイヤーのスケジューラーによって二重にスケジューリングされており、標準のExecutorではCallback単位でLinuxのScheduling Attributes(policy・priority・affinity)を設定できないという問題がありました。
  2. この問題を解消するのが、CallbackGroupとOSスレッドを一対一に対応させる新しいExecutorであるCallbackIsolatedExecutor(CIE)です。CIEを使うと、LinuxのScheduling AttributesをROS 2のCallbackへ直接適用できるようになります。
  3. メインコンテンツとして、サンプルアプリケーションを題材に、CIEのインストールからLinuxスケジューリング適用までの手順を6つのステップに分けてハンズオン形式で解説しました。聴講した方がその日のうちに自分のROS 2アプリケーションへ適用できることを目指した構成です。
  4. CIEはAutowareの主要なノードのほぼすべてに採用されており、ティアフォーのロボットタクシーでは、CIEとScheduling Attributesの設定によって、計測ベースで約3~5倍のWorst-Case Response Time改善が達成されています。

CIEの設計詳細や性能評価は、リアルタイム系トップカンファレンスであるRTAS 2025に採択された論文「Work in Progress: Middleware-Transparent Callback Enforcement in Commoditized Component-Oriented Real-time Systems」にまとめられています。論文のプレプリントはarXivで見ることができ、IEEEでも公開されています。

実装はGitHubで公開されており、導入手順を解説した公式ドキュメントも整備されています。

なお、CIEの設計と動機については、昨年のROSCon JP 2025でも発表しています。今回の講演は聴講した方が昨年の発表を見ていない前提で構成されており、設計の振り返りは短くまとめ、「CIEをどう使うか」というハンズオンに重点を置いています。

背景:ROS 2の二重スケジューリング

まず前提として、ROS 2アプリケーションの構造を簡単に説明します。ROS 2アプリケーションは、機能単位であるNodeの集合体として構成されます。各Nodeは複数のCallbackを持ち、CallbackはSubscribeしているTopicからメッセージを受け取って処理を実行し、次のTopicへメッセージをPublishします。このPublish/Subscribeのリレーによって、システム全体として複数のデータフローが形成されます。つまり、ROS 2アプリケーションの実体は「複数のCallbackで構成されるデータフロー」です。

複数のCallbackで構成されるデータフロー


このCallbackがいつ・どのCPUコアで実行されるかは、実は2つのスケジューラによって二重に決定されています。

  • Callback Scheduler(ミドルウェアレイヤー):ROS 2のExecutorです。実行可能になったCallbackを選び、自身が管理するOSスレッドに割り当てます。ROS 2特有のラウンドロビン的なアルゴリズムで動作します。
  • Thread Scheduler(OSレイヤー):LinuxなどのOSスケジューラーです。ExecutorがCallbackを割り当てたスレッドを、いつ・どのコアで実行するかを決定します。

ROS 2アプリケーションの二重スケジューリング


一方、LinuxをはじめとするPOSIX系OSには、スケジューラーの振る舞いを制御するために各スレッドに対してScheduling Attributes(Policy・Priority・Affinity)を設定できます。代表的なPolicyは次の3つです。AffinityはそのスレッドがスケジューリングされるCPUコアを設定できます。

Policy

設定できる属性

概要

EDFスケジューラ

(SCHED_DEADLINE)

runtime / period / deadline

最も早くdeadlineが来るスレッドを優先する。

FIFOスケジューラ

(SCHED_FIFO)

priority(99〜1)

priorityが最も高いスレッドを優先。priorityが同じならFIFO。

CFS(※Linux kernel version 6.6以降ではEEVDF)

(SCHED_OTHER)

nice(-20〜19)

すべてのスレッドへのCPU割り当て量をなるべく均等にする。デフォルトのPolicy。


問題は、ROS 2標準のExecutorを使う限り、このScheduling AttributesをCallback単位で設定できず、スケジューリングによる最適化が困難であることです。SingleThreadedExecutorは1つのスレッドが複数のCallbackを担当するため、Callbackごとに独立した設定を与えられません。MultiThreadedExecutorはスレッドプール内の複数のスレッドがCallbackへランダムに割り当てられるため、特定のCallbackに特定の設定を効かせることができません(※最近追加されたEventsExecutorはTimer Callbackのリリース遅延を減らすといった別の目的で実装されており、この問題を解決するものではありません)。この構造こそが、ROS 2アプリケーションに対するスケジューリング最適化を阻んできた要因です。CIEはこの問題を解決します。


ROS 2標準Executorの問題点

CallbackIsolatedExecutorの設計と実装

CIEの設計の核は、CallbackGroupとOSスレッドの間に永続的な一対一対応を構築することです。各CallbackGroupに専用のOSスレッドが与えられるため、そのスレッドにScheduling Attributesを設定すれば、それはそのままCallbackに対する設定になります。ミドルウェアレイヤーのスケジューリングを考慮する必要がなくなり、二重スケジューリングが解消されます。


CallbackIsolatedExecutorによる二重スケジューリングの解決


Scheduling Attributesの設定は、システム全体で1つのYAMLファイルを書くだけで完了します。YAMLフォーマットは自動生成され、ユーザは各プロパティを埋めるだけで済みます。生成方法は後述のハンズオンで説明します。

CIEの設定YAMLファイル


このYAMLファイルを読み込み、CIEのスレッド群へ実際に設定を反映するのがThread Configurator Nodeです。Thread Configurator Nodeは、nice(2)、sched_setaffinity(2)、setpriority(2)、sched_setscheduler(2)といったシステムコールを用いて、各スレッドのScheduling Attributesを設定します。


CIEの仕組みの全体像


CIEの設計詳細や性能評価に興味のある方は、前述の
RTAS 2025論文を参照してください。

ハンズオン:6ステップで始めるCallback単位のLinuxスケジューリング

ここからが本記事のメインです。サンプルアプリケーションを使って、CIEのインストールからLinuxスケジューリング適用までを6つのステップで説明します。同等の説明は公式ドキュメントにも記載されています。

(Optional)Step 0 | CallbackGroupの分離

CIEはCallbackGroup毎にスレッドを割り当てます。そのため、事前準備として、厳密にスケジューリングを制御したいCallbackには、独立したCallbackGroupの作成を推奨します。


// Callbackごとに専用の CallbackGroup を宣言して渡す

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_; // Subscription は options 経由で指定
subscription_ = create_subscription<std_msgs::msg::Int32>("topic_in", 1, cb, options);

Step 1 | インストール

CIEは独立したパッケージであり、rclやrclcppへの変更は一切不要です。ROS 2ビルドファームからaptでインストールできます。


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

本ハンズオンで使用するサンプルアプリケーションもインストールできます。


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

なお、CIEはティアフォーが開発しているROS 2互換のゼロコピーミドルウェアであるAgnocastにも同梱されており、Agnocastパッケージ経由でも導入できます。CIEとAgnocastを併用したい方はこちらをご利用ください。

Step 2 | Executorの差し替え

Standalone Nodeの場合は、main関数内のExecutor生成行を書き換えます。通常は1行の変更で済みます。


+ #include "callback_isolated_executor/callback_isolated_executor.hpp"


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

Composable Nodeの場合は、Launchファイルのcomponent containerを書き換えるだけです。ノードに対するコードの変更は0行です。


- <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 | YAMLテンプレートの作成

YAMLテンプレートの作成にはCIEのprerun nodeを使用します。prerun nodeを起動した状態で対象アプリケーションを起動すると、prerun nodeが検出したすべてのCallbackGroupを列挙したYAMLテンプレートファイルが自動生成されます。


# Terminal 1

ros2 run cie_thread_configurator prerun_node
# 対象アプリケーションの起動が完了したらctrl+cで終了

# Terminal 2
# 対象のアプリケーションを起動する

生成されるテンプレートは次のような形式です。CallbackGroupのidは「ノード名@そのCallbackGroupに属すCallback」という形式で決定されるため、どのエントリーがどのCallbackGroupに対応するのか一目で分かります。Scheduling Attributesにはデフォルト値が入っています。


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 | Scheduling Attributesの設定

生成されたテンプレートの各CallbackGroupに対して、Scheduling Attributesを設定します。CFS・FIFOスケジューラ・EDFスケジューラのそれぞれで、次のように記述します。どのような値を設定すべきかの考え方については、次章「Scheduling Attributesをどう設定するか」で説明します。


callback_groups:

# CFS の例: nice 値と CPU アフィニティを設定
 - id: xxxxx
   affinity: [0,1]
   policy: SCHED_OTHER
   nice: -10

# FIFO スケジューラの例: リアルタイム優先度を設定
 - id: yyyyy
   affinity: [2,3]
   policy: SCHED_FIFO
   priority: 50

# EDF スケジューラの例: runtime / deadline / period を設定 (単位: ns)
 - id: zzzzz
   affinity: [0,1]
   policy: SCHED_DEADLINE
   runtime: 10000000
   deadline: 10000000
   period: 20000000

Step 5 | Thread Configuratorに権限を付与する

Thread Configuratorプロセスから他のプロセスのスレッドのScheduling Attributesを設定するためには、CAP_SYS_NICEというCapabilityを設定する必要があります。方法は2つあります。

方法1: Thread Configuratorをsystemd serviceとして定義し、CAP_SYS_NICEを付与する方法です。これが最も簡単です。


# thread_configurator.service

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

方法2:バイナリにsetcapを実行する方法です。公式ドキュメントにある通り、セキュリティ上の理由で LD_LIBRARY_PATH が無効化されてしまうため、少し手間がかかります。


sudo setcap cap_sys_nice+ep \

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

特別な権限が必要になるのはこのThread Configuratorという1プロセスのみで、アプリケーション本体には一切権限が要りません。権限範囲を最小化できるという、セキュリティ面の利点があります。

Step 6 | Thread Configuratorとアプリケーションの起動

YAMLファイルを読み込んだThread Configuratorノードが立ち上がった状態で、対象のROS 2アプリケーションを起動すると、自動でスケジューリング設定が反映されます。


# Terminal 1 (systemd serviceとして定義している場合は不要)
ros2 run cie_thread_configurator thread_configurator_node --ros-args -p config_file:=<your yaml>

# Terminal 2
# 対象のアプリケーションを起動する

以上の6ステップで、Callback単位のLinuxスケジューリングが動き始めます。アプリケーションコードの変更は、Executorの差し替えだけです。

Scheduling Attributesをどう設定するか

CIEによってCallback単位でScheduling Attributesが設定可能になりましたが、どのように設定すれば良いのでしょうか?この問いを考える際にはシステムに求められる要件を明確にする必要があります。ほとんどのロボットアプリケーションは、決められた時間内に出力することが求められるリアルタイムシステムです。中でも自動運転システムは、人命に関わるハードリアルタイムシステムです。したがって、限られたコンピューティングリソースの中で全ての時間制約を満たすことが自動運転システムにおける要件です。

この問題は簡単に解けるものでは無いですが、心強いことに、まさにこの問題を扱っているリアルタイムスケジューリングの研究コミュニティが存在します。RTSS・ECRTS・RTASといった国際会議を中心に、数十年にわたる研究資産が蓄積されており、これを活用できます。実際に、ROS 2システムを対象としたリアルタイムスケジューリング研究だけでも、Casiniらによる研究(ECRTS '19)を皮切りに、Executorの改造・Scheduling Attributes割り当てアルゴリズム・エンドツーエンドのタイミング解析など、多くの論文が発表され続けています。これらの多くの手法はROS 2標準Executor、すなわち二重スケジューリングをそのまま解析対象としています。

  • 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)

また、CallbackをVertex・Topic通信をEdgeとみなすと、ROS 2システムはDirected Acyclic Graph(DAG)としてモデル化できます。DAGに対するリアルタイムスケジューリングは2010年頃から現在まで盛んに研究されており、日夜最適なアルゴリズムの探求が進められています。

  • 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)

これまで、こうした研究成果はデプロイされたROS 2システムにほとんど届いていませんでした。二重スケジューリングを前提に構築された解析手法は、実務者が日常的に適用するには過度に複雑であり、理論的なDAGスケジューリングアルゴリズムは二重スケジューリングを前提としていないためです。CIEは二重スケジューリングを構造的に取り除くため、独立してOSスケジューリングされるタスク群について確立されてきた理論を、ROS 2のCallbackへ直接適用できるようになります。つまり、CIEは、ROSコミュニティとリアルタイムスケジューリング研究コミュニティをつなぐ架け橋です。既存の研究資産からあなたのシステムの要件に沿うスケジューリングアルゴリズムを見つけたら、そのアイデア通りにScheduling Attributesを設定するだけで良いのです。

Autowareでの採用状況・実績

ティアフォーが開発を主導する自動運転用オープンソースソフトウェアのAutowareにおいて、主要なノードのほぼすべてがCIEに置き換わっており(Autoware GitHub Discussion)、今後すべてのノードのExecutorをCIEに置き換える予定です。

実際にティアフォーのロボットタクシーにCIEを適用したうえで、ボトルネックである5つのDAG(Top LiDAR Preprocessing・Localization・Perception・Planning・Control)のScheduling Attributesを最適化した結果を紹介します。優先度割り当てはこの論文を参考に、「より長いパスに属するCallbackほど高い優先度を割り当てる」という戦略を取りました。これによってDAGのクリティカルパスを最速で処理することができます。

Autowareを構成するDAG


以下は、デフォルトのLinuxスケジューラであるCFSを特別な調整なしで実行した場合(灰色線)と比較して、5つのDAGのResponse Time(先頭Vertexのリリース〜末尾Vertexの終了)がどれだけ改善したかを示したものです。ロボットタクシーをお台場の公道で走行させた際の計測結果であり、横軸は経過時間(秒)です。

デフォルトとCIEによる最適化後の比較


結果として、最悪時のレスポンスタイムは計測ベースで約3~5倍改善され、ジッタも軽減されました。自動運転システムのように、限られたコンピューティングリソースで高負荷な処理をする必要があるシステムでは、スケジューリングによる性能改善が期待できます。

まとめ

  • CIEにより、Callback単位のOSスケジューリングが可能になりました。
  • 最適なOSスケジューリングを扱う研究コミュニティが存在し、その豊富な研究資産が活用できます。
  • CIEはAutowareの大部分に既に適用されており、今後すべてのノードに適用される予定です。
  • CIEとScheduling Attributesの設定によって、ティアフォーのロボットタクシーにおいては、計測ベースで3~5倍のWorst-Case Response Time改善が達成されています。

インストールからスケジューリング適用までは本記事で紹介した6ステップだけです。応答時間やジッタに課題を抱えているROS 2アプリケーションをお持ちの方は、ぜひ今日から試してみてください。

謝辞

この成果は、国立研究開発法人新エネルギー・産業技術総合開発機構(NEDO)の助成事業 グリーンイノベーション基金事業 / 電動車等省エネ化のための車載コンピューティング・シミュレーション技術の開発(JPNP21027)の結果得られたものです。

Atsushi Yano | システムプラットフォーム開発部

株式会社ティアフォーシステムプラットフォーム開発部リアルタイムグループリーダー。自動運転システムのリアルタイム性能を最大化するOS/ミドルウェアの研究開発に従事。埼玉大学 安積研究室 社会人博士課程に在籍し、自動運転システム向けリアルタイムスケジューリング理論を研究。

ティアフォーでは、「自動運転の民主化」というビジョンに共感を持ち、自らそれを実現する意欲に満ち溢れた新しい仲間を募集しています。

募集中の職種

その他にも多くの職種で採用をしています。詳細は、ティアフォーの「求人ページ」をご覧ください。

「どの職種で自分の経験を活かせるかが分からない」「希望する職種が見つからない」などの場合は、ぜひ「キャリア登録」をお願いします。

お問い合わせ先

  • メディア取材やイベント登壇のご依頼:pr@tier4.jp
  • ビジネスや協業のご相談:sales@tier4.jp

ソーシャルメディア

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

関連リンク