Apply external forces to the model.
Hello.
I want to apply external forces to the model. Is there a way to apply an external force to the model?
add actuator/motor
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
For xfrc_applied where is the force applied?
Ie center of mass? or at some other position?
Based on this, xfrc_applied is applied at the center of mass for the body.
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.
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:
- Define your force magnitude.
- Identify which body is affected by it.
- Define the duration of the external force application.
- 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
...