notes
Tools

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 P362.6e-4
M3508 P197.2e-4
GM60201.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"
  • これがないと制動時などに滑って挙動が非物理的

診断手順#

  1. 単位確認: ros2 topic echo motor0/target の値の桁で m/s か rad/s か判定
  2. wheel spin 目視: MuJoCo viewer で cmd_vel=一定を送り、wheel が想定方向に回るか
  3. feedback velocity: motor0/feedback velocity を見る. target と桁が違う (単位ずれ) or 逆符号 (axis ずれ) を発見
  4. chassis の跳ね: sim/ground_truth の z 座標を見る. cmd_vel 送信瞬間に z が跳ねるなら armature or contact 剛性
  5. base 進行: xy 方向に想定通り進むか. 進まない or 逆方向 → axis 符号 or 単位

参考#

最終更新:

On this page