6.2K Views
April 10, 24
スライド概要
この資料では、Unityを箱庭アセットとして利用するための情報を整理しています。
- ロボットを動かすためのUnityの構造
- 箱庭があると何が嬉しくなるのか
- 箱庭が提供する機能(フレームワーク)
- 箱庭でのロボット設計・実装方法
TOPPERS/箱庭WG活動でUnityやらAthrillやらmROSやら触ってます。 最近は仕事の関係でWeb系の技術に注力しつつ、箱庭への転用を模索しています。 2023年8月1日:合同会社箱庭ラボに移動しました
箱庭(Hakoniwa) Unity 合同会社箱庭ラボ 森崇
はじめに • この資料では、Unityを箱庭アセットとして利⽤するための情報を整理してい ます。 ロボットを動かすためのUnityの構造 • 箱庭があると何が嬉しくなるのか • 箱庭が提供する機能(フレームワーク) • 箱庭でのロボット設計・実装⽅法 • 2
ロボットを動かすためのUnityの構造 • Unity上でロボットを動かすには以下の3レベルがあります 1. UnityのRigidBodyやArticulationBodyをアタッチしてロボットを動かす 2. UnityのC#スクリプトでロボットを制御する 3. Unity外のプログラム(Python/C++⾔語など)で、Unity上のロボットを制御する • 外部プログラムの実⾏環境 ︓OS上のプロセス、マイコンシミュレータ上のRTOSタスク等 • 外部プログラムとの通信⽅式︓共有メモリ、MQTT、UDP/TCP、、、 レベル1 RigidBody 等 レベル2 RigidBody 等 Unityの C#スクリプト レベル3 RigidBody 等 Unityの C#スクリプト 通信スタック プログラムの実⾏環境 通信⽅式 通信スタック
箱庭があると何が嬉しくなるのか • レベル3向けの共通機能の作成が不要になる︕ Unity上のロボット ロボット制御プログラム プログラムの 実⾏環境 Unityの C#スクリプト RigidBody等 共通機能 箱庭API(C#) (TOPPERS/箱庭) Unity向け箱庭 シミュレーション実⾏ タイミング制御 箱庭 通信スタック 通信⽅式 (UDP/MQTT/共有メモリ…) 箱庭API(様々なプログラミング⾔語) 箱庭 通信スタック C++版 箱庭コア機能
箱庭が提供する機能(フレームワーク) 箱庭ロボット Read/Write Callback 箱庭ロボット 箱庭ロボット 箱庭ロボット 箱庭コンフィグ ジェネレータ 箱庭コンフィグ ファイル (json) 箱庭コンフィグ ローダー Unityエディタ 箱庭ランタイム 機能 箱庭PDU API 箱庭通信機能 Unityランタイム [凡例] 箱庭PDU ファイル⽣成 箱庭PDU 定義ファイル (json/offset) ユーザが作成する 成果物 外部ファイル 箱庭が提供する機能 (フレームワーク) 箱庭が提供する 外部ツール Unityの機能
箱庭Unity側のアーキテクチャと内部設計(1/2) 箱庭コンフィグ ローダー 箱庭ランタイム機能 <<Unity>> MonoBehaviour AssetConfigLoader 箱庭コンフィグファイル (json) 箱庭PDU API <<User>> 箱庭ロボット実装 WorldController <<interface>> ISimulationController HakoAsset SimulationController HakoRpcAsset SimulationController <<interface>> IInsideAssetController <<interface>> IPduReader/Writer
箱庭Unity側のアーキテクチャと内部設計(2/2) <<User>> 箱庭ロボット実装 Reader/Writer Connector <<interface>> IPduReader/Writer Reader/Writer Channel RawPduReader/Writer PDUデータ RawPduReader/Writer Convertor 箱庭PDU定義ファイル (json/offset) HakoAsset SimulationController PduChannel Connector <<interface>> IIOReader/Writer ShmReader/Writer Pdu HakoMqtt PDU通信プロトコル 箱庭コンフィグ ローダー RpcReader/Writer 箱庭コンフィグファイル (json)
箱庭Unityアセットのランタイム機能 • コントロールフロー • 全体的な処理の流れ • 箱庭ロボット内部の流れ • 実装イメージ • レーザスキャナ • カメラセンサ • 差動モーター • ロボット
箱庭Unityアセットの全体的な処理の流れ Unity処理 コール バック 箱庭共通処理 (WorldController) 箱庭内のロボット処理 (コールバック関数) Start() Initialize() FixedUpdate() アクチュエータ⽤ データ受信 アクチュエータ⽤ データ(PDU) DoActuation() ロボット処理実⾏ IInsideAssetController CopySensing DataToPdu() センサ データ送信 センサデータ(PDU)
箱庭ロボットの内部処理 • RobotPartsRootがアクチュエータ/センサ部品群を統括し、処理実⾏する • 各種アクチュエータ/センサはインタフェース化されているため、RobotPartsRootは再利⽤可能 • 箱庭部品として、アクチュエータ/センサのプロトタイプ実装クラスを⽤意している IRobotPartsController(インタフェース) 【役割】 アクチュエータの制御コントローラ⽤のインタフェース 【インタフェース仕様】 DoControl()関数実装では、PDUデータを取得し、 アクチュエータ指⽰値を関係するアクチュエータに伝達する IRobotPartsMotor(インタフェース) 【役割】 モーター制御⽤のインタフェース 【インタフェース仕様】 SetTargetVeolcity()関数実装では、指⽰値に 従って、モーターの物理挙動を実現する IRobotPartsMotor IRobotPartsController SetTargetVelocity() IInsideAssetController インタフェース実装 【役割】 すべてのセンサ/アクチュエータ の処理を実⾏する親⽟ 【補⾜】 ロボット組み⽴て時には、 本Unityスクリプトを必ず アタッチしないといけない RobotPartsRoot DoActuation() CopySensing DataToPdu() DoControl() IRobotPartsPincherFinger IRobotPartsSensor UpdateSensor Values() IRobotPartsSensor(インタフェース) 【役割】 センサ⽤のインタフェース 【インタフェース仕様】 UpdateSensorValues()関数実装では、センシング 処理を実⾏し、取得したデータをPDUに保存する UpdateGrip() IRobotPartsActuator IRobotPartsActuator(インタフェース) 【役割】 アクチュエータ⽤の共通インタフェース
イベント関数インタフェース視点での全体像 IRobotPartsController IInsideAssetController IRobotParts RobotParts Root IRobotPartsSensor Unity向け箱庭 シミュレーション実⾏ タイミング制御 IRobotPartsTouchSensor IRobotPartsMotorSensor IRobotPartsActuator IRobotPartsMotor IRobotPartsPincherFinger [凡例] <<Unity>> FixedUpdate() インタフェース実装 インタフェース インタフェース継承 処理呼び出し インスタンス
インスタンス例 ロボットルート <<C#スクリプト>> RobotPartsRoot IRobotPartsSensor レーザスキャナ カメラセンサ <<C#スクリプト>> Laserscanner <<C#スクリプト>> CameraSensor IRobotPartsController <<C#スクリプト>> DifferentialMotorController 左モーター 右モーター <<C#スクリプト>> WheelMotor <<C#スクリプト>> WheelMotor IRobotPartsAcuator
RobotPartsRoot
IRobotPartsController︓ DifferentialMotorController
IRobotPartsActuator︓ WheelMotor
IRobotPartsSensor︓ Laserscanner
IRobotPartsSensor︓ CameraSensor
箱庭Unityアセットの通信機能 • PDU通信データの特徴 • PDU通信データのライフサイクル • PDU通信データの初期化 • PDU通信データの読み込み • PDU通信データの書き込み • PDU通信データのAPIクラス • Pdu/IPduReadOperation/IPduWriteOperation/IPduReader/IPduWriter • サンプル実装
PDU通信データの特徴 • C#クラスとして、キー・バリューで任意のデータ型を管理できます • 階層構造の構造体や配列などROS IDLで定義できる全ての型表現が可能です • jsonファイルで定義されたPDUデータを⼊⼒して、Pduクラスをインスタンス化します • ⾃分でPDUデータのクラスを作成する必要はありません PDUデータは、箱庭のPDUアクセスAPIでアクセスできます • 受信⽤のPDUデータ • • 箱庭ランタイム機能が⾃動的にデータ受信してバッファリングします • 受信タイミングは、全てのロボットのシミュレーション実⾏直前に、⼀括バッファリングします • 送信⽤のPDUデータ • 箱庭ランタイム機能が⾃動的にデータ送信します • 送信タイミングは、全てのロボットのセンシングデータを書き込みした後に⼀括送信します
PDU通信データのライフサイクル 箱庭コンフィグ ファイル (json) 箱庭PDU 定義ファイル (json/offset) 箱庭共通処理 (WorldController) Start() 箱庭内のロボット処理 (コールバック関数) インスタンス化 FixedUpdate() アクチュエータ⽤ データ受信 DoActuation() 受信Pdu インスタンス ロボット処理実⾏ センサ データ送信 送信Pdu インスタンス CopySensing DataToPdu()
PDU通信データのAPIクラス Pdu IPduReader IPduWriter <<interface>> IPduReadOperation <<interface>> IPduWriteOperation Dictionary Dictionary Dictionary Dictionary 構造体メンバ毎に キー・バーリュー形式で 任意のデータを管理
サンプル実装(初期化処理) IPduReader/Writerは、箱庭が⾃動的にローディング済みなので、 ロボットの初期化処理で、そのインスタンスを取得するだけでOK。 ⼿順は、以下の3ステップ。 ■IPduReader/Writerを取得するための親⽟オブジェクト(pdu_io)を取得 ■IPduReaderの取得⽅法(Pduの名前を指定して取得) ■IPduWriterの取得⽅法(Pduの名前を指定して取得)
サンプル実装(I/O) IPduReader/Writerを使⽤して、PDUデータの読み書きをする ■IPduReaderでのPDUデータ読み込み
サンプル実装(I/O) IPduReader/Writerを使⽤して、PDUデータの読み書きをする ■IPduWriterでのPDUデータ書き込み
箱庭Unityアセットのコンフィグ機能 • コンフィグファイルの種類と役割 • コンフィグファイルの⽣成⽅法 • コンフィグに関するインタフェースの実装 • ロボットの配置とスクリプトの割り当て • コンフィグファイルの⽣成
コンフィグファイルの種類と役割 • core_config.json • 通信ポートの定義 • 箱庭通信⽤のPDUデータ定義 • ロボットとPDUデータの関係定義 • hakoniwa_path.json • 外部コンポーネントとの連携するためのファイルパスを定義 • custom.json • ロボットのI/O⽅法 • 各I/Oで使うデータと型 • LoginRobot.json (現状未使⽤) • ロボットの位置情報
コンフィグファイルの⽣成⽅法(1/3) • コンフィグに関するインタフェースの実装 • ロボットのルートスクリプトでは、以下の2種類のインタフェースを実装してください。 • IRobotPartsConfig • GetRoboPartsConfig() • 実装例 • IRobotParts • getRosConfig() • 上記関数は、GetRoboPartsConfig()の戻り値から⾃動計算可能ですが、 • 現時点では、まだその辺りの整理が仕切れていません…。 • 実装例 • 本実装内容が、core_config.json と custom.json に反映されます。
コンフィグファイルの⽣成⽅法(2/3) • ロボットの配置とスクリプトの割り当て 1. ロボットは必ず prefab 化してください 2. ロボットには、HakoAssetRootというタグを割り当ててください 3. ロボットには、RoboPartsSettingsとRobotPartsRootスクリプトを割り当ててください 必ずOnをチェック してください 4. ロボットは必ずヒエラルキービューのHakoniwa/Robot配下に配置してください
コンフィグファイルの⽣成⽅法(3/3) • コンフィグファイルの⽣成 • 全ての設定が完了したら、必ず、コンフィグファイルを⽣成してください。 • Generate • 本番⽤ • GenerateDebug • テスト⽤
箱庭でのロボット設計・実装⽅法 • 箱庭でのロボット設計内容 • テスト向けシーン • デバッグ⽅法 • エラーハンドリングとロギング
箱庭でのロボット設計内容 • 箱庭を利⽤する上で必要な設計検討項⽬は以下のとおりです。 • 通信データの検討 • 作成するロボットのPDUデータの種類とデータ型 • 対象PDUデータを標準のROSデータ型で対応するか新規作成するかの検討も必要 • 対象PDUデータの通信⽅式(推奨︓共有メモリ⽅式) • 共有メモリ、UDP通信、MQTT通信から選択する • 送信対象となるPDUデータの送信周期 • ロボット物理挙動の再現⽅法検討 • 箱庭のサンプル実装が参考になると思います。 • Unityでのロセンサ/アクチュエータの実装⽅式検討 • 箱庭のサンプル実装が参考になると思います。
32 テスト向けシーン • ロボットの構造が複雑になる場合、Unity単体でテストする⽅が効率的です • 箱庭には、テスト向けシーンがあります。 • Workシーンです。ここで、GenerateDebugしてシミュレーションすることで簡単にお試しできます。 • PDUデータの通信は、Unity内のメモリで送受信できます。 • ロボットのテストドライバを作成することで、基本的な機能確認が可能になります。 • 参照
33 テスト向けシーンでの動作チェック https://www.youtube.com/watch?v=dlz-60bH4x8
34 デバッグ⽅法 • ロボットのデバッグ⽅法として⼀番単純なやり⽅は、 • Unityのデバッグログ出⼒をすることです。 • 例︓UnityのDebug APIをそのまま利⽤できます。
35 エラーハンドリングとロギング • エラーハンドリング • 基本的にはロボット側のエラーチェックをお願いします。 • 問題ある場合は、解析に必要な情報をログ出⼒してください。 • 復旧不可能な場合は、例外をスローしてください。 • ロギング • 箱庭側で単純なロガーを⽤意しています。 • SimpleLogger • 実装例︓SimpleLogger.Get().Log(Level.ERROR, e); • ログファイル︓ • hakonwia_core.logがUnityプロジェクト直下に⾃動的に出⼒されます。