dora-rs: これがAI時代のロボティクスミドルウェアだ!
こんにちは、渡辺貴史です。
最近西海岸ではdora-rsというミドルウェアが流行っていると聞き、早速すこし真面目に触ってみました。すでに2.5k starがついています。
さっそく、自分のロボットのシステムをdora-rsで換装して遊んでみました。
いいぞ!!! と思った。もっと流行らせたいし育てたい。
ROSが「移動ロボットの(アルゴリズムベースの)スタンダードを作ったミドルウェア」であるとするならば、次には「AI x ロボティクスを前提にしたミドルウェア」の出現が期待されると、私は思っています。dora-rsは、そのひとつの候補になりうるのではという思いです。
雑な所感としては2つのことを思いました。
-
環境構築めっちゃ楽 ∴ MLモデルのインテグが楽: 各ノードの環境要件は「dora-rsが入っていること」だけ。お好きな環境に
uv add dora-rs
あるいはcargo add dora-rs
すれば終わり。conda環境を要求してくるMLモデルを試したいときも、それぞれ環境構築が可能です - Vibeコーディング(AIコーディング)に向いている: データフロー指向がもたらす強い粗結合性によって、コンテクスト長を抑えた分散的なプロジェクト構成を育てます。
色々なことに気づいたので、「dora-rsはなぜ生まれたのか?」「ROSとどう違うの?」という軸で所感を書いてみようと思います。気になっている人の一助になったら幸いです。
pixi派閥もあると思いますが、一旦それは無視しています。
dora-rsとは何をするものか?
ROS同様、ノード(プロセス)間の通信を行うためのミドルウェアです。
本質的にはそれ以上でもそれ以下でもありません。
実際にはハードウェアドライバとの接続やビジュアライザなどの周辺OSS資産の話もありますが、それは最後に少し書きます。
公式の売りポイント
GitHubのREADMEにある売りはこれ。
10-17x faster than ros2.
やはり流行りのblazing fastで、MaturinでバインドしたRust実装のpythonライブラリがrclpy(CycloneDDS, 共有メモリ)と比べて10-17倍速いという比較です。
C++で共有メモリを使う場合は差がないという結果が出ています。
なぜdora-rsが生まれたのか (推測)
AI x Roboticsの流行の上で、ROSにはいくつか問題があると思っています。
私が思う、ROSがある中でわざわざdora-rsが生まれた理由をまとめてみました。
諸説あるのはわかります、どうか落ち着いて…
C++が中心にあるせいで、Pythonは足を引っ張られている
MLの資産はやはりpythonで使うことになるのが現状です。製品向けにC++やRustで最適化を行うことはあっても、研究開発やプロトタイピングでpythonを使わない手はないでしょう。基本的に。
そんな状況の中、ROSの辛いポイントはエコシステムの古さです。ROSがというか、C++が悪いんですよね。PythonはPyPIで頒布しuvで管理、Rustはcrate.ioで頒布しCargo管理するというデファクトが育っている中、C++はgitから入手するかaptで入手するかという状況を脱しきれていません。
このC++の状況に引っ張られた結果、エコシステム全体をaptで構成することになり、システムのpythonを使うという状況が生まれています。pythonの依存もpython3-xxxxをインストールして使うので、更新がとても遅いという問題があります。(Ubuntu 24.04なのにpydanticなんてまだバージョン1.10.14だし…)
どのみちpythonで書いているのなら、依存はPyPIだけで完結してほしい。
これが大きな特徴の1つです。ミドルウェアの機能をごくシンプルに保つことでこれを実現します。
そのかわり、色々なことを諦めます。
その諦めが、逆にひとつのスタイルになっているところもあり、それも面白さの一つです。
CUDAメモリのプロセス間共有
複数のAIモデルに同じ画像をインプットする場合に、CUDAに転送したあとの画像のテンソルを共有できれば効率化が狙えます。とくにリアルタイムな処理を行っているロボティクス領域では、転送時間も重要なファクターです。
CPUメモリ上ではゼロコピーでも、それぞれのAIモデルでCUDAに転送していては無駄があります。
私はまだ使えていないのですが、重要な機能になってきそうです。
ROSと何が違うのか
言葉遣いがおかしいかったらすみません。
トピック指向ではなく、データフロー指向
doraの名前は Dataflow-Oriented Robotic Architecture から来ているらしく、その名のとおりデータフロー指向です。
各ノードは明示的な Input/Output のポートを持ち、これらを結ぶ通信を dataflow.yml に事前宣言します。実行時はこの事前配線されたグラフに沿って処理が流れます。
比較としてROSを特徴づけるなら、ROSはトピックベースのPub/Subであると言えます。
まず先にトピックが存在していて、そのトピックに参加するPublisherとSubscriberが事後的に集まってくる。参加したいと言ったタイミングで動的に通信路が作られます。
一方、doraではまずノードが存在して、InputとOutputを持っています。このI/Oを持つノードをつなぐ通信路を事前にdataflow.ymlで記述します。
つまり、ある種実行時点でコンパイル済みの通信路になっている、みたいなイメージです。
dora の名称は “Dataflow-Oriented Robotic Architecture” に由来し、データフロー指向です。ノードは明示的な Input/Output ポートを持ち、これらを結ぶ通信を dataflow.yml に事前宣言します。実行時はこの事前配線されたグラフに沿って処理が流れます。
対して ROS(ROS 1/2)は 動的な topic-based Pub/Sub が中核です。トピック(名前+型=“名前付きチャネル”)を基準に、Publisher/Subscriber は参加した時点で自動発見・接続され、通信路は実行時に必要に応じて確立されます。
まとめると、dora=宣言的に固定したグラフ配線、ROS=名前付きトピックを介した動的接続という設計の違いがあります。
実際にはdoraではデーモンがあって、pub/subの配信自体はこのデーモン経由で、大量のデータの受け渡しはこのデーモン経由のメッセージに共有メモリの情報を乗せるという構成になっています。
実行はdora run dataflow.yaml ≒ 引数のないroslaunch
実行はdora run dataflow.yaml
のようにします。
roslaunchに似ていて、違いはifやvariable展開はなく、すべて実際の値が埋まっていることを期待するします。
私は、このyamlを自動生成するソフトを自分で書きました。(そのうち公開してみようと思います。)
なので私の環境では、オプションを変えたい場合などに
$ ./build_dataflow.sh --robot sim --camera dummy --policy ACT
などとしてdataflow.yamlを生成し、実行は
$ ./run.sh
のようにしています。これを億劫に感じる方もいるかもしれませんね。
includeの機能がないので、ここをエコシステム化しないと、複数のノードからなるシステムをOSSで配信する場合には問題になるかもしれません。
型はない
- Apache Arrowのスキーマ情報自体は存在しますが、rosのようにメッセージ配信時点で宣言時のmd5sumと一致するかどうかのチェックなどは存在しません。
- 私はpython同士は共通のpydanticスキーマをライブラリとして持っておいて、各nodeのパッケージでこれをインストールしてvalidationしています。バージョニングなどを適切に行えば、問題はないように感じます。
ロボットフレームワークとして、ぶっちゃけどうか?
環境構築が楽!MLを試すのにもいいぞ!!
話題のMLモデルを試したい!と思っても、環境構築が面倒だからいいや、となるケースはままあると思います。ML系だとcondaを前提にしているものも結構あるし、ライブラリ間の衝突も少なくありません。
しかし、「dora-rsが提供するのは通信機能だけ」というシンプルな思想と勇気ある諦めにより、PyPIあるいはcrate.ioからdora-rsのライブラリをインストールさえできれば、ノードの環境構築を終えることができます。venvの登場以降当たり前のものとなってきた分離された仮想環境の思想を、そのまま活かすことができます。
Vibe Coding / Agentic Codingに嬉しい「小さいサイズと明確な役割」
データフロー指向では、「InputとOutputを決める」「その間をつなぐ役割を担うノードを作る」という明確で簡潔な目標のもとでノードを作ることが強く意識されます。さらにこのノードの役割を最小化しようという気持ちを持つことで、非常によい分散システムが構成できそうです。
これはROSも同様ではあるのだけど、「こういう機能を実装するから、あのトピックからも情報を引っ張ってこなきゃ」というふうに開発が進んで、分散システムのはずがいつの間にかノードが肥大化しがちです。
ある種通信のフローを定義するのが面倒であるが故に、「このノードはこのI/Oを繋ぐこの役割を持つものである」という明確な意思を持った開発がしやすいフレームワークであるように思います。
こうなっていると、AIが破綻せずにコーディングしやすくなります。
実際、私も2つくらい作ってみました。
-
dora-rsで流れてくる映像フレームをWebRTCで配信する: https://github.com/dieu-detruit/dora-gst-webrtc-sink
- これ結構便利だと思います。シグナリングサーバーも兼ねてます。
-
GStreamerのテスト映像を配信する: https://github.com/dieu-detruit/dora-gst-test-source
機械学習界隈はいまだにcondaで資産を作っていることが多く(本当に勘弁して欲しいのですが)、これらの資産を試す上でも、PyPIのみに依存しdora-rsの通信にだけ則れば良いと言うのは良い話です。
懸念
- まだ(特に日本では)あんまり流行っていないのが懸念です。ハードウェアとのインテグなどは流行らないとなかなか進まない部分もあるので、こうやって記事を書くなどして流行らせていきたい所存です。
- req-repはTODOにはあるようですが、現状はpub/subしかないので、レスポンスを待ちたいケースでは自前でこの構造を実装する必要があります。
最後に
流行らせたい!みんな小さなプロジェクトからでいいので一回使ってみてください!
Discussion