C言語で物理を操る!Mujoco x Unity x 箱庭をMacで試してみた話
これは何?
C言語エンジニアが、初めてMujocoに触れてみた話です。
きっかけ
先日、箱庭の情報交換会で、Genesisの話題になりまして、内部でMujocoという物理エンジンが動いているらしい、さらにMujocoはオープンソース、ということで、早速、調べてみようと思い立ちました。
ChatGPTを活用!Mujocoのインストールと初めてのプログラム
mujocoのライブラリをmacでインストールする方法を教えて、C++でプログラミングしたい
そうすると、細々としたインストール手順を教えてくれて、サンプルプログラムが表示されました。
#include <mujoco/mujoco.h>
#include <iostream>
int main() {
// MuJoCoライブラリのバージョンを表示
std::cout << "MuJoCo Version: " << mj_version() << std::endl;
// モデルとデータの作成
mjModel* m = nullptr; // MuJoCoモデル
mjData* d = nullptr; // シミュレーションデータ
// 終了処理
mj_deleteData(d);
mj_deleteModel(m);
return 0;
}
mujocoのライブラリは、モデル(mjModel)とシミュレーションデータ(mjData)を分離して、この2つをベースに、様々な関数を呼び出して操作を行える設計になっているようです。
- mjModel: システムの定数的な物理プロパティ(例: 質量、形状、関節のパラメータなど)を保持。
- mjData: シミュレーション中の動的な状態(例: 位置、速度、力の情報)や、中間計算結果を保持。
MujocoをMacで初体験!C言語で物理シミュレーションを操る
ガチャガチャやって、2時間くらいで動かせるようになりました。公式サイトからのダウンロードやツールのインストールはスムーズでしたが、CMakeプロジェクトの設定には少し時間がかかりました。しかし、このチュートリアルを参考にすると、初心者でもすぐに環境を整えられると思います。
今回の試行では、ざっくり以下のような流れでした。
- 公式サイトの最新リリースから、Mac用の dmg ファイルをダウンロード。
- 必要なツール類をインストール
brew install cmake
brew install gcc
brew install glfw
- cmakeプロジェクトを作成
- 箱庭と接続してUnityで動作チェック
箱庭で広がる可能性:MujocoとUnityの連携活用
箱庭は、複数のシミュレータやデジタルツイン環境を統合し、シームレスに連携させるためのプラットフォームです。Mujocoのような物理エンジンを簡単に統合でき、UnityやROS2を活用してシミュレーション結果をリアルタイムで可視化できます。
C++で開発されており、C言語のAPIも用意されているため、Mujoco(C++)との相性が非常に良いです。
箱庭を使うことで、例えば以下のようなシナリオで活用できます:
- 複数台のドローンを協調して動作させるシミュレーション。
- ロボットアームの精密な動きを物理エンジンで検証し、Unityで視覚的に確認する。
- デジタルツイン環境で、現実世界と仮想空間をリアルタイムで同期する。
- これらを、MujocoやUnityと組み合わせることで、効率的かつ直感的に構築できます。
ちなみに、ドローンシミュレーションと連携して、こんな遊び方もできます。
Mujoco x Unityのリアルタイム連携した物理シミュレーションのデモ
こちらがそのデモ動画です。
この動画では、Mujocoでシミュレーションされたキューブの自由落下が、Unity上でリアルタイムにビジュアライズされる様子を確認できます。特に注目してほしいのは、Mujocoで計算された物理データが、箱庭を介してUnityに瞬時に反映されている点です。
この仕組みを使えば、複雑なシミュレーションも簡単に可視化でき、現実世界とのギャップを埋める可能性が広がります。
箱庭とMujocoの連携プログラムはこんな感じです。
static int my_on_simulation_step(hako_asset_context_t* context)
{
(void)context;
// Mujocoで1ステップ分のシミュレーションを実行
mj_step(mujoco_model, mujoco_data);
std::cout << "Time: " << mujoco_data->time
<< ", Height: " << mujoco_data->qpos[2] << std::endl;
// キューブの位置情報と姿勢を取得
double qw = mujoco_data->qpos[3];
double qx = mujoco_data->qpos[4];
double qy = mujoco_data->qpos[5];
double qz = mujoco_data->qpos[6];
// 姿勢をオイラー角に変換
double roll, pitch, yaw;
quaternionToEuler(qw, qx, qy, qz, roll, pitch, yaw);
// 位置と姿勢データを箱庭に書き込み
HakoCpp_Twist twist;
twist.linear.x = mujoco_data->qpos[0];
twist.linear.y = mujoco_data->qpos[1];
twist.linear.z = mujoco_data->qpos[2];
twist.angular.x = roll;
twist.angular.y = pitch;
twist.angular.z = yaw;
// PDUへのデータ書き込み処理
Hako_Twist* raw_data;
auto _ret = hako_convert_cpp2pdu_Twist(twist, &raw_data);
if (hako_asset_pdu_write(robot_name, channel_id, (const char*)hako_get_top_ptr_pdu(raw_data), static_cast<size_t>(pdu_size)) != 0) {
std::cerr << "Failed to write PDU." << std::endl;
}
hako_destroy_pdu(raw_data);
return 0;
}
こちらで一般公開しています。箱庭のコールバック関数(my_on_simulation_step)にて、Mujocoのシミュレーションを1ステップ進めて、キューブの位置と姿勢情報を取得して、箱庭に書き込みするだけです。
感想
Mujocoを使うことで、物理シミュレーションの軽快さやリアルさを体感しましたが、特に印象的だったのは「API設計の扱いやすさ」と「シンプルなインストールプロセス」です。普段C言語を使っている私にとって、モデルとデータの明確な分離は非常に直感的で、初めて使ったにも関わらずすぐに動かせた点に驚きました。
今後は、Mujocoと箱庭を使って、より複雑なシミュレーションにも挑戦してみたいと思います。例えば、複数のドローンが協調動作する場面や、産業用ロボットが複数のタスクを並行して処理するシミュレーションなどです。また、箱庭を使えば、これらのシミュレーションを分散環境で効率的に動かすことができ、現実の設計プロセスを大きく加速できる可能性を感じています。
最後に
Mujocoと箱庭の組み合わせは、物理シミュレーションの可能性を大きく広げるものでした。実際に使ってみて、この技術が持つポテンシャルに感動しました。
なお、箱庭を活用した情報やシミュレーションの事例については、こちらのブログでも詳しく紹介しています。興味がある方はぜひご覧ください。
Discussion