
AIエージェント Codex で ドローン2
MuJoCo で シミュレーション
本記事にはアフィリエイト広告が含まれます。
前回はAIエージェント Codex を活用してドローンの学習を開始しました。
Codex先生のおかげで姿勢制御やゲームコントローラによる位置制御を数日で実現できてしまいました。
Codex先生にドローン制御コード生成いただく
しっかし操作が難しすぎ
AIの力でここまで動くようになったけど現実の壁が厚すぎるw#バイブコーディング #Codex #ドローン pic.twitter.com/AK5GMbcnL1— HomeMadeGarbage (@H0meMadeGarbage) May 23, 2026
しかし実機のコントローラ操作が非常に難しく、Codex先生に提案いただいたIMUフィルタや姿勢制御方式の評価をするまでに至りませんでした。
現状の実機の制御方式は以下の通りです。Codex先生 誠にありがとうございます。
・IMU (MPU6050) のフィルタ:Complementary Filter (相補フィルタ)
・Roll, Pitch 姿勢制御:PD制御
・Yaw 姿勢制御:P制御
いきなり実機はさすがに無謀だったと反省し、ここではMuJoCo によるシミュレーションでドローン制御の検証を行います。
目次
MuJoCo
この時点でMuJoCoでのドローンのシミュレーション方法について私自身はノーアイディアでした。
Codex先生に以下のようにお願いしました。
“コントローラで位置制御できるドローンシミュレーションを実現して”
すると、以下が生成されました。
バイブコーディングでドローン
Codex先生にMuJoCoドローンSim.環境を生成いただく
MuJoCoのアクチュエータって推力にもできるんだねロールピッチのPDで水平・移動制御
Sim.でも手動静止ホバリングはむずい。。#Codex pic.twitter.com/nSXxAWzhxM— HomeMadeGarbage (@H0meMadeGarbage) May 22, 2026
Codex先生ヤバすぎる。一発でコレ↑が生成されたのです。
ドローンモデルの MJCF(MuJoCo XML Format)と、ゲームコントローラによる制御用 Python コードが本当に一瞬で生成されました。
MuJoCo の motor アクチュエータは、プロペラの回転そのものを物理的に再現しなくてもモデルに対して指定方向の力やトルクを与えることができます。
今回生成されたシミュレーションでは、4つのモータそれぞれに付与した motor アクチュエータの推力をPD 制御で調整することで Roll、Pitch の姿勢制御と高さ維持を実現しています。Yaw については機体の Z 軸まわりにトルクを直接与える motor アクチュエータを用意し、こちらも PD 制御で旋回させています。
なるほど!ドローンの場合はこうやって MuJoCo でモデリングすればよいのですね。非常に勉強になりました。
プロペラを回して推力を得る物理モデリングをしているわけではないのでSim2Real には相当苦労しそうです。
しかしドローンの制御方式の比較検証には十分使えそうです。
このシミュレーションでよくわかったのは、センサなしで位置や高度を安定させるのは非常に難しいということです。ゲームコントローラで Roll、Pitch の目標角を変えて操作しているのですが、実機と同じように機体がフラフラと流れていきます。
特に高度センサは必須レベルだと感じました。後述しますが、シミュレーション上でも高さ情報を使わない場合はほぼ制御不能だったため、以降のシミュレーションでは高さセンサありの構成で実施します。
MJCF(MuJoCo XML Format)
ドローンのMuJoCoシミュレーション方法を理解することができましたので、実機に近いモデルを制作します。
プロペラガードやモータ固定具を設計した際のAutodesk Fusion モデルをもとにSim.モデルを作ります。
プロペラガードを含む機体やモータ、バッテリのSTLを出力して、プロパティで慣性モーメントを取得します。
Codex先生に各パーツのSTLファイルと慣性モーメント情報、そして実機で計測した重さを渡してMJCFを生成してもらいました。
これまた一瞬で生成されました。
パーツの慣性モーメントは実機の重さで換算して、推力用や旋回用のmotorアクチュエータもモータや機体にええ感じに付与してくださいました。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 |
<mujoco model="stl_quad_drone"> <compiler angle="degree" autolimits="true"/> <option timestep="0.002" gravity="0 0 -9.81" integrator="RK4"/> <visual> <global azimuth="135" elevation="-25"/> <scale forcewidth="0.04" contactwidth="0.03"/> </visual> <asset> <mesh name="body_mesh" file="assets/body.stl"/> <mesh name="bat_mesh" file="assets/bat.stl"/> <mesh name="M1_mesh" file="assets/M1.stl"/> <mesh name="M2_mesh" file="assets/M2.stl"/> <mesh name="M3_mesh" file="assets/M3.stl"/> <mesh name="M4_mesh" file="assets/M4.stl"/> <material name="body_mat" rgba="1 0 0 1"/> <material name="battery_mat" rgba="0.08 0.08 0.09 1"/> <material name="motor_mat" rgba="0.75 0.75 0.72 1"/> <material name="front_motor_mat" rgba="0.75 0.75 0.72 1"/> <material name="floor_mat" rgba="0.75 0.78 0.8 1"/> </asset> <worldbody> <light name="top" pos="0 0 5" dir="0 0 -1" diffuse="0.8 0.8 0.8"/> <geom name="floor" type="plane" size="5 5 0.1" material="floor_mat"/> <body name="drone" pos="0 0 0"> <freejoint name="root"/> <site name="yaw_torque_site" pos="0 0 0.025" size="0.006" rgba="1 0.4 0 1"/> <body name="body_part"> <inertial pos="-0.000011 -0.000004 0.025911" mass="0.046" fullinertia="8.9955812e-5 8.9153722e-5 1.7192981e-4 6.2424830e-10 -3.5914298e-9 -1.1726702e-9"/> <geom name="body_geom" type="mesh" mesh="body_mesh" material="body_mat"/> </body> <body name="battery"> <inertial pos="0 0 0.012" mass="0.015" diaginertia="4.6781602e-6 6.7985437e-7 4.9990287e-6"/> <geom name="battery_geom" type="mesh" mesh="bat_mesh" material="battery_mat"/> </body> <body name="M1_left_back"> <inertial pos="-0.045 -0.045 0.018" mass="0.005" diaginertia="1.8199230e-7 1.8199230e-7 3.0628008e-8"/> <geom name="M1_geom" type="mesh" mesh="M1_mesh" material="motor_mat"/> <site name="thrust_M1" pos="-0.045 -0.045 0.028" size="0.003" rgba="0 0.8 0.1 1"/> </body> <body name="M2_right_front"> <inertial pos="0.045 0.045 0.018" mass="0.005" diaginertia="1.8199230e-7 1.8199230e-7 3.0628008e-8"/> <geom name="M2_geom" type="mesh" mesh="M2_mesh" material="front_motor_mat"/> <site name="thrust_M2" pos="0.045 0.045 0.028" size="0.003" rgba="1 0 0 1"/> </body> <body name="M3_right_back"> <inertial pos="0.045 -0.045 0.018" mass="0.005" diaginertia="1.8199230e-7 1.8199230e-7 3.0628008e-8"/> <geom name="M3_geom" type="mesh" mesh="M3_mesh" material="motor_mat"/> <site name="thrust_M3" pos="0.045 -0.045 0.028" size="0.003" rgba="0 0.8 0.1 1"/> </body> <body name="M4_left_front"> <inertial pos="-0.045 0.045 0.018" mass="0.005" diaginertia="1.8199230e-7 1.8199230e-7 3.0628008e-8"/> <geom name="M4_geom" type="mesh" mesh="M4_mesh" material="front_motor_mat"/> <site name="thrust_M4" pos="-0.045 0.045 0.028" size="0.003" rgba="1 0 0 1"/> </body> </body> </worldbody> <actuator> <motor name="M1_thrust" site="thrust_M1" gear="0 0 1 0 0 0" ctrlrange="0 1"/> <motor name="M2_thrust" site="thrust_M2" gear="0 0 1 0 0 0" ctrlrange="0 1"/> <motor name="M3_thrust" site="thrust_M3" gear="0 0 1 0 0 0" ctrlrange="0 1"/> <motor name="M4_thrust" site="thrust_M4" gear="0 0 1 0 0 0" ctrlrange="0 1"/> <motor name="yaw_torque" site="yaw_torque_site" gear="0 0 0 0 0 1" ctrlrange="-0.03 0.03"/> </actuator> </mujoco> |
もう二度とMJCFファイルを手書きすることはないかな。
AIの恩恵を大いに受けています。先生本当にありがとうございます。
PD制御
Sim.モデルができたので実機同様の制御で飛行の検証を行います。
・Roll, Pitch 姿勢制御:PD制御
・Yaw 姿勢制御:P制御
・高度:PD制御 (実機は高度センサないけど便宜上)
バイブコーディングでドローン
実機同様にRoll/Pitch:PD制御、Yaw:P制御
便宜上 Sim.では高度もPD制御
Sim.でも位置流れるからIMUだけで飛行は結構無謀だったかもコチラで制御手法検討しますか
あ いや先生に教えてもらいましょう#Codex pic.twitter.com/MsCZpcuH53— HomeMadeGarbage (@H0meMadeGarbage) May 22, 2026
各ゲインはCodex先生に別途ゲイン探索コードを生成してもらって安定度評価により決定しました (以後の各制御のゲインも同様です)。
やはり水平位置制御はSim.上でも難しいですね。
PID制御
Roll, Pitch 姿勢制御をPDからPIDに変更してみます。
・Roll, Pitch 姿勢制御:PID制御
・Yaw 姿勢制御:P制御
・高度:PD制御 (実機は高度センサないけど便宜上)
バイブコーディングでドローン
Roll/PitchをPID制御に変更
Yaw:P制御
高度:PD制御 (実機はセンサないけど便宜上)各ゲインの最適探索もCodex先生に実施いただく
いいホバリングだ#Codex #MuJoCo pic.twitter.com/De6fsVGv9M— HomeMadeGarbage (@H0meMadeGarbage) May 22, 2026
ホバリング時の位置の流されが低減されたように感じます。
カスケード制御
モノの本にかいてあるカスケード制御を試してみます。
Roll/Pitch目標角→P制御 (アウターループ)→目標角速度→PID制御 (インナーループ)→モータ推力
・Yaw:P制御
・高度:PD制御 (実機はセンサないけど便宜上)
バイブコーディングでドローン
カスケード制御
Roll/Pitch目標角→P制御 (アウターループ)→目標角速度→PID制御 (インナーループ)→モータ推力Yaw:P制御
高度:PD制御 (実機はセンサないけど便宜上)なんとなく応答がいいような気がする
一晩でここまでこれた。先生ありがとう#Codex #MuJoCo pic.twitter.com/abrNlKtmy9— HomeMadeGarbage (@H0meMadeGarbage) May 22, 2026
ホバリング時の安定性やコントローラへの応答もいい印象です。
高さセンサ
これまでは高さセンサも模擬してPD制御して高度を保ってシミュレーションしてきました。
実機同様にセンサなしでジョイスティックでモータ推力を手動制御してみます (姿勢制御はカスケード)。
バイブコーディングでドローン
Codex先生が高さセンサなしの飛行は無謀であることを教えてくださりました。#Codex #MuJoCo pic.twitter.com/Vr8NGUhQM7
— HomeMadeGarbage (@H0meMadeGarbage) May 23, 2026
センサなしでの高さ維持が非常に難しいことを強く実感しました。
前回はかなり無謀なことをしていたようです。。
無知は恐ろしいですね。
おわりに
ここではAIエージェント Codexを活用してMuJoCoシミュレーションによるドローン制御方式の検証を実施しました。
しかし、ドローン制御方式の検証そのものよりもやはりAIエージェントの有用性に大きく感動しました。
感動ポイントと気づきをまとめて本ブログを閉じさせていただきます。
- ドローンSim.環境が一瞬で構築され、その手法も非常に勉強になった
- モデル MJCFも正確に生成された。私はもう二度と MJCFを手書きすることはないでしょう
- 高度センサなしでの飛行は無謀。位置センサもあれば尚いい


