6.2K Views
April 10, 24
スライド概要
この資料では、箱庭アセット間の通信データであるPDUの情報を整理しています。
- 箱庭のPDU(Protocol Data Unity)とは何か
- 箱庭の通信プロトコル・アーキテクチャ
- 箱庭アセットと箱庭PDUチャネルについて
- 箱庭PDUデータの作成方法
- 箱庭PDUデータの組み込み方法
箱庭アセットAPI
箱庭アセットUnity
- 箱庭PDUデータのアクセス方法
箱庭アセットAPI
箱庭アセットUnity
TOPPERS/箱庭WG活動でUnityやらAthrillやらmROSやら触ってます。 最近は仕事の関係でWeb系の技術に注力しつつ、箱庭への転用を模索しています。 2023年8月1日:合同会社箱庭ラボに移動しました
箱庭(Hakoniwa) PDU 合同会社箱庭ラボ CTO 森崇
はじめに • この資料では、箱庭アセット間の通信データであるPDUの情報を整理してい ます。 • 箱庭のPDU(Protocol Data Unit)とは何か • 箱庭の通信プロトコル・アーキテクチャ • 箱庭のPDUデータをプログラムで使うには • 箱庭アセットと箱庭PDUチャネルについて • 箱庭PDUデータの作成方法 2
箱庭のPDUとは何か • 箱庭のPDU(Protocol Data Unit)は、箱庭アセットが互いに通信するためのデータ単位です。 • PDUデータ型の定義: ROS IDL (Interface Definition Language) というインターフェース記述言語 • PDUデータは、様々な通信プロトコルを介してデータ交換されます。 • UDP, MQTT, ROS, Zenoh, 共有メモリ 3
箱庭の通信プロトコル・アーキテクチャ(1/4) • UDP通信 4
箱庭の通信プロトコル・アーキテクチャ(2/4) • MQTT通信 5
箱庭の通信プロトコル・アーキテクチャ(3/4) • ROS通信 6
箱庭の通信プロトコル・アーキテクチャ(3/4) • 共有メモリ 7
箱庭PDUデータをプログラムで使うには • 箱庭PDUデータをプログラムで使うには • データ(位置・速度など)をネットワーク用に変換する必要があります。 • まずは、「一般的な通信プログラムの流れ」を理解し、 • 次に、「箱庭PDUの場合の流れ」を理解します。 • そして、「一般的な通信プログラム vs 箱庭PDU」の比較をして理解を深めます。 • 最後に、「箱庭PDUの変換ライブラリとテンプレート」を紹介します。 8
一般的な通信プログラムの流れ • 通信フレームワーク側でプログラムデータ型をバイナリ変換してくれる アプリケーションプログラム プログラムデータ型 アプリケーションプログラム プログラムデータ型 アプリケーション 処理 アプリケーション 処理 通信API 通信API バイナリデータ バイナリ変換処理 (encode) バイナリデータ バイナリ変換処理 (decode) 通信フレームワーク 通信フレームワーク 転送API 転送API トランスポート層/ネットワーク層/データリンク層 トランスポート層/ネットワーク層/データリンク層 9
箱庭PDUの場合の流れ • アプリケーション側でプログラムデータ型をバイナリ変換します アプリケーションプログラム プログラムデータ型 アプリケーションプログラム プログラムデータ型 アプリケーション 処理 バイナリデータ バイナリ変換処理 (encode) アプリケーション 処理 バイナリデータ バイナリ変換処理 (decode) 転送API 転送API トランスポート層/ネットワーク層/データリンク層 トランスポート層/ネットワーク層/データリンク層 10
一般的な通信プログラム vs 箱庭PDU の比較 • 一般的な通信はFW任せ、箱庭PDUはアプリ主導 項目 一般的な通信プログラム 箱庭PDU バイナリ変換処理の場所 通信フレームワークが自動で実施 (アプリ側は意識する必要なし) アプリケーション側がバイナリ変換APIを使って実施 (アプリ側は意識する必要あり) データ型の定義 通信FW依存のデータ型を利用する 箱庭PDUのデータ型(ROS IDL) 通信層構造 アプリ → 通信API → 通信FW → 転送API → ネットワーク層 アプリ → PDU変換処理 → 転送API → ネットワーク層 API表面積 プログラム言語毎に通信APIが増える構造 (通信API内処理+バイナリ変換) プログラム言語毎にバイナリ変換APIが増える構造 (バイナリ変換のみ) 他プログラミング言語への 移植コスト ノード層・型バインディング・ミドル層など 広範囲改修 言語毎のバイナリ変換テンプレートの新規作成のみ 利点 FW内で閉じた最適化・通信の透明化 多言語対応が用意、API表面積を最小化すること で移植コストを低減できる 11
箱庭PDUの変換ライブラリとテンプレート • 箱庭PDU向けのデータ型/バイナリ変換ライブラリはテンプレートで自動生成! 通信記述形式 (ROS IDL) Python C# C++ データ型 テンプレート データ型 テンプレート データ型 テンプレート バイナリ変換 テンプレート バイナリ変換 テンプレート バイナリ変換 テンプレート ROS msgファイル ・・・ 箱庭PDU変換ツール Python C# C++ データ型 データ型 データ型 バイナリ変換 ライブラリ バイナリ変換 ライブラリ バイナリ変換 ライブラリ ・・・ 12
箱庭アセットと箱庭PDUチャネルについて • 箱庭アセットをPDUデータI/Oの観点で分類すると以下の2種類に分かれます • プラントモデル • 制御モデル • プラントモデルは、複数のロボットを持つことができます(制御側も同様) • ロボットは、複数のPDUデータに対してI/O発行できます • 各ロボットから見たときのPDUデータの識別IDをチャネルと呼びます • なのでPDUチャネルの識別は以下の2つの情報が必要となります • プラントモデルのロボット名 • チャネルID プラントモデル ロボットA チャネルID チャネルID 0 0 PDUデータA-1 1 0 ロボットB 1 PDUデータA-2 PDUデータB-1 PDUデータB-2 1 制御モデル 制御A 0 1 ロボットAのPDUデータ A-2にアクセスするには、 (“ロボットA”, “1” ) でアクセスする 制御B ロボットBのPDUデータ B-2にアクセスするには、 (“ロボットB”, “1” ) でアクセスする 13
箱庭アセットと箱庭PDUチャネルについて • UnityとPythonの箱庭アセットが箱庭コア機能を通して通信している様子(共有メモリ方式) 箱庭アセット(Unityの場合) 箱庭アセット (Pythonの場合) センサ1 0:センシングデータ1 0 センサ2 1:センシングデータ2 1 モータ 2:モータ指示値 2 ロボット PDU 0 1 2 0 1 2 0 1 2 箱庭コア機能 2 1 0 PDUデータ 14
箱庭PDUデータの作成方法 • 以下の手順で箱庭PDUデータを作成します。 • 0. 箱庭PDUデータを作成するリポジトリをクローンする • https://github.com/toppers/hakoniwa-ros2pdu • インストール手順およびPDUデータ生成方法は上記を参照ください。 • 1. 箱庭PDUデータの型を決める • 2-(a). ROS標準の通信データに存在している場合 • 対象の定義ファイル(.msg)から箱庭のPDUデータ定義ファイル群を生成する • 2-(b). ROS標準の通信データに存在していない場合 • ROS IDLで、定義ファイル(.msg)を作成する • 対象の定義ファイル(.msg)から箱庭のPDUデータ定義ファイル群を生成する • 3. 生成した箱庭PDUデータ/バイナリ変換ライブラリを取得する 15
生成される箱庭PDUデータの内訳 • 生成される場所: • hakoniwa-ros2pdu/pdu • 3種類のファイルが生成されます。 • json: • json形式の定義ファイル(Unityで利用) • offset: • offset定義ファイル(PDUバイナリデータのエンコーダ/デコーダで利用) • types: • C言語のデータ型およびROSデータ型への変換定義ファイル(.h, .hpp) • C言語のデータ型定義ファイル :pdu_ctype_<PDUデータ名>.h • ROSデータ型への変換定義ファイル:pdu_ctype_conv_<PDUデータ名>. hpp • python/csharp • python/C#のデータ型およびROSデータ型への変換定義ファイル群 • 上記ファイルは、以下のディレクトリ構成で生成されます。 • <ROSのパッケージ名>/<メッセージ名> 16
箱庭PDUデータの構造 ROS IDLのデータをC言語の構造体 (例:Point) Meta Data offset 型 内容 0 uint32 Magic番号(0x12345678) 4 uint32 バージョン番号(現在は1) 8 uint32 BaseDataの開始位置(=24) 12 uint32 HeapDataの開始位置(BaseDataの末尾) 16 uint32 全体サイズ(Meta + Base + Heap) 20 - パディング Base Data 可変長配列データを格納する領域 (例:CompressedImage) uint8 data[] Heap Data 17
箱庭PDUのプリミティブデータ型定義 ROS データ型 箱庭PDU データ型 C言語データ型(stdint.h) (pdu_primitive_ctypes.h) 備考 int8 Hako_int8 int8_t ー uint8 Hako_uint8 uint8_t ー byte Hako_byte uint8_t ー char Hako_char uint8_t ー int16 Hako_int16 int16_t ー uint16 Hako_uint16 uint16_t ー int32 Hako_int32 int32_t ー uint32 Hako_uint32 uint32_t ー int64 Hako_int64 int64_t ー uint64 Hako_uint64 uint64_t ー float32 Hako_float32 float ー float64 Hako_float64 double ー bool Hako_bool int ー string Hako_cstring #define HAKO_STRING_SIZE 128 typedef struct { char data[HAKO_STRING_SIZE]; } Hako_cstring; 現時点では、文字列データは128バイト固定です。 18
箱庭PDUのBase Data領域の構造 • ROS IDLで定義したデータ型を、「箱庭PDUのプリミティブデータ型定義」 に従って、C言語の構造体に変換します。 • 可変長配列については、ヒープ領域への参照データを保持します。 Heap Data 1..* Primitive Data型 ヒープ領域の オフセット位置 可変長配列の長さ (データサイズではない) BaseData型 0..* 可変長配列 のメタデータ int _data_len 可変長配列 データの実体を格納 data[] int _data_off 19
箱庭PDUのHeap Data領域の構造 • Heap Data領域は、可変長配列データを格納します。 • 可変長配列データのプリミティブデータ型 • Primitive Data型 • 構造体データ型 • 構造体データ型の中にさらに可変長配列データがある場合は、 再帰的な構造になる(下図)。 1..* 可変長配列 構造体データ に可変長配列 がある場合 0..* Heap Data プリミティブデータ型 uint8 data[] Primitive Data型 構造体データ型 CompressedImage data[] 可変長配列 のメタデータ プリミティブデータ型 uint8 data[] int _data_len プリミティブデータ型 uint8 data[] int _data_off 20
箱庭PDUデータの組み込み方法 • TODO:最新のAPIに対応した内容で作り直す予定。。 21
箱庭PDUデータのアクセス方法 • TODO:最新のAPIに対応した内容で作り直す予定。。 22