MuJoCo で車輪ロボが爆発する 5 つの典型原因
車輪ロボの MuJoCo モデルが跳ねる・暴れる・進まないときに疑う 5 原因 (単位不整合・armature・actuator 種別・axis 符号・接触剛性) と対処
要点
車輪付きロボが MuJoCo 上で 跳ねる・暴れる・進まない のは以下 5 原因の重なりがほとんど。単位不整合と armature 抜けの 2 つだけで大抵爆発する。
1. 単位不整合 (m/s vs rad/s) ← 最頻出
上位コントローラが返す target と actuator が受ける ctrl の単位が違うと 10-100 倍のスケールずれ。
典型: 3 輪オムニ / mecanum で
- コントローラ formula:
v = vy·cos(θ) − vx·sin(θ) + R_base·wz→ wheel 接触点線速度 [m/s] - MJCF
<dcmotor input="velocity">: joint 角速度 [rad/s] を期待
変換は omega_wheel = v_contact / r_wheel. wheel 半径 5cm なら 20 倍必要。
確認: ros2 topic echo /motor0/target で m/s の値 (0.5-2 くらい) が出るなら m/s。rad/s なら 10-50 くらいの値のはず。
対処: どちらかで変換
- コントローラ側で div (formula を改修)
- 中間 adapter node で div
- MJCF
<motor gear="20">を使う (<velocity gear>は意味が逆なので不可)
2. Armature (反射慣性) 未設定
<joint armature> を入れないと wheel の「見かけ慣性」が実質ゼロ扱い. 目標速度に瞬時到達 → 立ち上がり瞬間トルクが物理的でない大きさに → 跳ねる。
対処: モータ rotor 慣性 × 減速比² を joint に。
| モータ | armature = J_rotor × N² |
|---|---|
| M2006 P36 | 2.6e-4 |
| M3508 P19 | 7.2e-4 |
| GM6020 | 1.5e-4 |
<joint name="wheel0_joint" armature="2.6e-4" damping="0.02"/>3. Actuator 種別が hack (<velocity> の乱用)
<velocity kv> は force = kv × (ctrl − v) の単純比例制御. 電気モデル無し.
- 立ち上がり時に瞬間的な巨大トルク → 反作用でロボ跳ねる
- forcerange でクリップされても armature 無しだと角加速度は無限大
対処: 実機モータ種別に対応する物理 actuator を使う.
<dcmotor name="motor0" joint="wheel0_joint"
class="fibril_sim_hw_robomaster_m2006_p36_nominal"
saturation="2.25 0 0" input="velocity"
controller="0.136 0.036 0 0 0 24"/>resistance,motorconst(Kt Ke),inductanceが電気ダイナミクスを担うsaturationで電流上限controllerで内部 PI (kp=0.136, ki=0.036, umax=24V)
4. Wheel joint axis の符号ミス
コントローラ formula は「wheel 正回転 → chassis 進行方向」を仮定。MJCF <joint axis> の向きと合わないと 3 輪 (or 4 輪) の力が 打ち消し合う + 残差で跳ねる。
確認: MuJoCo viewer で cmd_vel = 純 X を送って各 wheel の回転方向を目視. 全部同じ方向 (前進なら全部 rolling forward) になっているか。
対処: <joint axis> の符号を反転 or <motor gear="-20"> で actuator 側を反転.
5. 接触剛性 default で車輪との相性悪い
solref="0.02 1" (default) は剛体接触向け. 車輪 × 硬い床の立ち上がり瞬間力を吸収しきれず bounce。
対処: 車輪 geom だけ柔らかく.
<geom name="wheel0_tyre" type="cylinder" size="0.05 0.015"
friction="1.0 0.05 0.0001"
solref="0.04 1.2"
solimp="0.9 0.95 0.001"/>二次的な原因
Omni wheel の side friction が低すぎて滑る
friction="1.0 0.05 0.0001"の side=0.05 は roller の slip 表現- side が 0.01 以下だと横方向の力に抵抗ゼロ → 押されて滑る
- 逆に side=0.5 だと omni ではなく普通のホイールになる
Timestep が粗い
- default 0.002 (500Hz) は高速回転 wheel には荒い
- rc26 は 0.001 (1kHz). 車輪 20 rad/s なら 1 step で 0.02 rad = 1.15° 回る
- 不安定なら 0.001, 更に不安定なら 0.0005
noslip_iterations 未設定
- 車輪の no-slip 制約を追加反復で強化
- rc26 は
noslip_iterations="15" - これがないと制動時などに滑って挙動が非物理的
診断手順
- 単位確認:
ros2 topic echo motor0/targetの値の桁で m/s か rad/s か判定 - wheel spin 目視: MuJoCo viewer で cmd_vel=一定を送り、wheel が想定方向に回るか
- feedback velocity:
motor0/feedback velocityを見る. target と桁が違う (単位ずれ) or 逆符号 (axis ずれ) を発見 - chassis の跳ね:
sim/ground_truthの z 座標を見る. cmd_vel 送信瞬間に z が跳ねるなら armature or contact 剛性 - base 進行: xy 方向に想定通り進むか. 進まない or 逆方向 → axis 符号 or 単位
参考
- rc26 の r1.xml (working example): fibril_sim_models の actuator_presets.xml と組み合わせ
- 関連: MuJoCo 物理設定の 5 階層
- 関連: MuJoCo パラメータを機体構造から推算する
- 関連: MuJoCo でオムニ/メカナムの横滑りを表現する — 回転は動くが並進で自転する場合