🙂

C言語で物理を操る!Mujoco x Unity x 箱庭をMacで試してみた話

2025/01/26に公開

これは何?

C言語エンジニアが、初めてMujocoに触れてみた話です。

https://mujoco.org/

きっかけ

先日、箱庭の情報交換会で、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プロジェクトの設定には少し時間がかかりました。しかし、このチュートリアルを参考にすると、初心者でもすぐに環境を整えられると思います。

今回の試行では、ざっくり以下のような流れでした。

  1. 公式サイトの最新リリースから、Mac用の dmg ファイルをダウンロード。
  2. 必要なツール類をインストール
brew install cmake
brew install gcc
brew install glfw
  1. cmakeプロジェクトを作成
  2. 箱庭と接続してUnityで動作チェック

箱庭で広がる可能性:MujocoとUnityの連携活用

箱庭は、複数のシミュレータやデジタルツイン環境を統合し、シームレスに連携させるためのプラットフォームです。Mujocoのような物理エンジンを簡単に統合でき、UnityやROS2を活用してシミュレーション結果をリアルタイムで可視化できます。

C++で開発されており、C言語のAPIも用意されているため、Mujoco(C++)との相性が非常に良いです。

箱庭を使うことで、例えば以下のようなシナリオで活用できます:

  • 複数台のドローンを協調して動作させるシミュレーション。
  • ロボットアームの精密な動きを物理エンジンで検証し、Unityで視覚的に確認する。
  • デジタルツイン環境で、現実世界と仮想空間をリアルタイムで同期する。
  • これらを、MujocoやUnityと組み合わせることで、効率的かつ直感的に構築できます。

ちなみに、ドローンシミュレーションと連携して、こんな遊び方もできます。

https://hakoniwa-lab.net/2025/01/24/blog-tech-new-drone/

Mujoco x Unityのリアルタイム連携した物理シミュレーションのデモ

こちらがそのデモ動画です。

https://www.youtube.com/watch?v=lDNgaeUfLqM

この動画では、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と箱庭の組み合わせは、物理シミュレーションの可能性を大きく広げるものでした。実際に使ってみて、この技術が持つポテンシャルに感動しました。

なお、箱庭を活用した情報やシミュレーションの事例については、こちらのブログでも詳しく紹介しています。興味がある方はぜひご覧ください。
https://hakoniwa-lab.net/information/

Discussion