mujoco-py icon indicating copy to clipboard operation
mujoco-py copied to clipboard

Apply external forces to the model.

Open daichi-3110 opened this issue 5 years ago • 5 comments

Hello.

I want to apply external forces to the model. Is there a way to apply an external force to the model?

daichi-3110 avatar May 10 '20 03:05 daichi-3110

add actuator/motor

kevincheng3 avatar May 17 '20 15:05 kevincheng3

You can also set sim.data.xfrc_applied or sim.data.qfrc_applied xfrc_applied is (nbody, 6) 3D force and 3D torque qfrc_applied is (nv, 6) 3D force and 3D torque applied at generalized position

To set these variables you need to update the matrix values since they are not explicitly writeable: sim.data.xfrc_applied[:] = new_xfrc # Or something like that

I hope this helps

mfogelson avatar Mar 02 '21 17:03 mfogelson

For xfrc_applied where is the force applied?

Ie center of mass? or at some other position?

justinberi avatar Dec 01 '21 23:12 justinberi

Based on this, xfrc_applied is applied at the center of mass for the body.

efahnestock avatar Dec 03 '21 02:12 efahnestock

If you want to apply force on object in a short time, just add it to data->xfrc_applied, this work on next step only, xfrc_applied() will apply the force forever.

fcycq avatar Oct 23 '24 00:10 fcycq

For the force to impact the inertial state of the mass, or be realisable, it should last for at least 10ms (depends on your model - I'm talking about the Humanoid v4). model.opt.timestep is equal to 0.005 seconds which is really small. Alternatively, increase the magnitude of applied force. However, it's got to be more realistic - you don't want a really large force affecting a body for an extremely tiny duration. It really depends on your application.

Therefore, here's the summary of the solution:

  1. Define your force magnitude.
  2. Identify which body is affected by it.
  3. Define the duration of the external force application.
  4. Apply it using data.xfrc_applied
IMPULSE_TIME = 3.0    #seconds
IMPULSE_DURATION = 0.02 # 20ms
IMPULSE_FORCE = np.array([200, 0, 0])  # force in x-direction

body_id = mujoco.mj_name2id(model, mujoco.mjtObj.mjOBJ_BODY, b"torso")
...
while data.time < DURATION:

    if IMPULSE_TIME <= data.time < IMPULSE_TIME + IMPULSE_DURATION:
      data.xfrc_applied[body_id][:3] = IMPULSE_FORCE
    else:
      data.xfrc_applied[body_id][:3] = 0  # Reset force
...

Officially-Siddhant avatar Jun 03 '25 14:06 Officially-Siddhant