箱庭ブリッジを最初に考えたのは、忘れもしない、
高瀬先生と細合さんと、
箱庭のブリッジ構想を検討していた時でした。
当時、Zenohにハマっていたこともあり、
「箱庭の通信層はZenohで統一できるんでは?」
っていう夢物語を語っていました。
ちなみに、このあたりの記事で、実証実験の広報してました(わすれてた)。
箱庭ブリッジは奥が深い。
あの当時は、とりあえず、箱庭のシミュレーションの世界をZenohを通して、ROSと繋げる。
その一点で技術開発していたなと、しみじみと思い返されます(若かった)。
あれから、思い返せば、もう2年も経つんですね。
いろんな箱庭ブリッジってのを作りました。
はい、Zenohですべてを統合する。
無理ゲーだとおわかりました。
箱庭が扱いたい技術領域は、
- ドローンのMAVLINK通信
- WebブラウザやゲームアプリでのWebsocket通信
- AR連携とか
- :
いろんなバリエーションがあるんです。
当然、その当時(2024年)は、Zenohが対応しきれていないプログラミング言語もあったし、
たとえば、UnityでZenoh動かすとかね。
そんなの、いちいちやってられない。
で、結局は、箱庭のデモ特化型の「箱庭ブリッジ」つくりました。
「まー、現実はそんなもんなんかなー」って
半分、遠い夕日を細い目で見ながら、
そんな気分で作っていました。
ちょっと俯瞰して眺めてみるタイミングがきました。
箱庭の開発やっているとですね、そういう、技術的な泥臭さを色々よこに置きながら、
あるとき、それらを、まるで、
「おもちゃ箱から、ガラガラとあさって、眺めるように」
そう、俯瞰して、みる時期っていうのが来るんですよね。
そして、箱庭エンドポイントの設計が終わったときに、
エンドポイントは
全ての通信プロトコルを包含している。
ZenohもWebSocketも、
ぜんぶ同じ枠組みに収まっている。
…ってことは。
そのエンドポイントを、
転送設定して、
左から右に流すだけ。
それだけなんじゃない?!
そう気づいちゃったんです。
箱庭ブリッジを再設計してみた。

これが、今の箱庭ブリッジの設計です。
箱庭ブリッジは、通信を行いません。
エンドポイントが持つ通信能力を前提に、
「どのPDUを、いつ、どこへ流すか」だけを定義します。
ここで、もうひとつ大きな気づきがありました。
PDU の転送は、必ずしも
「1 対 1」である必要はない、ということです。
あるエンドポイントから出た PDU を、
複数のエンドポイントへ同時に流す(fan-out)。
シミュレーションの世界では、これはむしろ自然な振る舞いでした。
そしてもうひとつ。
転送において本当に重要なのは、
通信プロトコルではなく、時間的な振る舞いでした。
- 更新された瞬間に即座に流す immediate
- 帯域や負荷を意識して間引く throttle
- 一定周期でまとめて流す ticker
箱庭ブリッジが扱うのは、
「どう送るか」ではなく、
「いつ、どう振る舞うか」。
fan-out と転送ポリシー。
この二つを明示的に切り出したことで、
箱庭ブリッジは、単なる通信の仲介ではなく、
PDU の時間的な流れを記述するコンポーネントになりました。
ちなみに。
そしてもうひとつ、大事な整理があります。
NAT 越えは、Zenoh の専売特許ではありません。
箱庭ブリッジの設計では、
通信はすべてエンドポイントが担当します。
つまり、
- TCP で TCP をつなぐ
- UDP から TCP へ(その逆もできる)
- WebSocket で外に出る
- 必要なら Zenoh を使う
どれも、同じ枠組みの中で成立します。
箱庭ブリッジが定義するのは、
通信経路ではなく、転送の関係性。
だから、
「NAT 越えが必要なら、その区間を エンドポイントで切り替えればいい」
それだけの話になります。
Zenoh が必要なのではなく、
“選べる”ことが重要だった。
実装してみた。
まだ、絶賛実装中ですが、箱庭ブリッジは、hakoniwa-pdu-bridge-core という名前に変えて、
以下のリポジトリで公開しています。
箱庭ブリッジって、要するに、
「PDU の転送」なんですよね。
だから、名前に pdu を入れました。
そして、最後に core を付けたのには、実は理由があります。
これは、
箱庭コンダクターへの布石でもあるからです。
箱庭ブリッジそれ自体は、
単体のツールではなく、
ライブラリとして使える形である必要がある。
そんな気づきが、ここでありました。
……この話を始めると長くなるので、
今回はここでは省略します。
あとねー。
さらに、箱庭PDUブリッジ(ここからネーミング変えます)は、箱庭PDUエンドポイントと同じように、jsonで設定できるようにしたんですよ。
{
"version": "2.0.0",
"time_source_type": "virtual",
"transferPolicies": {
"immediate_policy": { "type": "immediate" }
},
"nodes": [
{ "id": "node1" },
{ "id": "node2" }
],
"endpoints_config_path": "endpoints.json",
"wireLinks": [
{ "from": "epA_dst_wire", "to": "epB_src_wire" }
],
"pduKeyGroups": {
"pdu_group_pos": [
{ "id": "Drone.pos", "robot_name": "Drone", "pdu_name": "pos" }
]
},
"connections": [
{
"id": "node1_conn",
"nodeId": "node1",
"source": { "endpointId": "epA_src" },
"destinations": [ { "endpointId": "epA_dst_wire" } ],
"transferPdus": [ { "pduKeyGroupId": "pdu_group_pos", "policyId": "immediate_policy" } ]
},
{
"id": "node2_conn",
"nodeId": "node2",
"source": { "endpointId": "epB_src_wire" },
"destinations": [ { "endpointId": "epB_dst" } ],
"transferPdus": [ { "pduKeyGroupId": "pdu_group_pos", "policyId": "immediate_policy" } ]
}
]
}詳細は省略しますが、
既存の箱庭 PDU エンドポイントの JSON 設定を参照しつつ、
箱庭 PDU ブリッジでは、転送設定だけを記述する形にしています。
通信の定義はエンドポイントに任せ、
ブリッジは「どう流すか」だけを書く。
……この分離、
「イケてません?!」
つづく。

コメントを残す