myosuite
myosuite copied to clipboard
Muscle Fatigue doesn't work for most model
I started debugging this issue. Either I don't understand what's going on, or there is something really wrong with our implementation. I'd need more information about our Fatigue model to understand what is being implemented. Let me articulate what I have found so far
- Issue seems to be with the way self.f_load is being calculated
- f_load seems to depend on actuator_moment whose size is (nu x nv)
- The implementation seems to be checking for nv==1 as a special case here. This conceptually seems wrong. Why would ndof = 1 be any different than many dof?
- The implementation further goes on to only look at the first DoF for all its calculations and ignores all others. This seems seriously off.
My guess is that -- it was implemented for a single muscle single dof system and it has never been tested with a system with higher dof. -- I also think that the arm and hand fatigue results are wrong -- I also think the implementation has a massive memory leak. We keep appending f_load to the buffer throughout the existence of the env. The size of the buffer keys growing. We either need a cyclic buffer here, or f_load needs to be cleaned with at reset.
The fatigue works in isolation in a code example:
import mujoco
import mujoco.viewer as viewer
import os
import numpy as np
import time
curr_dir = os.path.dirname(os.path.abspath(__file__))
model_path = os.path.join(curr_dir, 'myolegs_v0.56(mj237).mjb')
mj_model = mujoco.MjModel.from_xml_path(model_path)
mj_data = mujoco.MjData(mj_model)
window = viewer.launch_passive(mj_model, mj_data)
# mj_model.actuator('connection_muscle').gainprm[2] = 2000
for i in range(10000):
mj_data.ctrl[:] = 1.0
if i > 300:
for i in range(mj_model.na):
mj_model.actuator(i).gainprm[2] = 0
mj_model.actuator(i).biasprm[2] = 0
mujoco.mj_step(mj_model, mj_data)
time.sleep(0.01)
window.sync()
print(mj_data.actuator_force)
so it's something inside myosuite somewhere
I tried it both on the sim and the env. The results seem sensible. I'm attaching my snippets below. Let me know if I'm missing something.
check for fatigue using sim
import mujoco
import mujoco.viewer as viewer
import os
import numpy as np
import time
curr_dir = os.path.dirname(os.path.abspath(__file__))
model_path = os.path.join(curr_dir, '../simhive/myo_sim/leg/myolegs_v0.56(mj237).mjb')
mj_model = mujoco.MjModel.from_binary_path(model_path)
mj_data = mujoco.MjData(mj_model)
window = viewer.launch_passive(mj_model, mj_data)
for i in range(200):
mj_data.ctrl[:] = 1.0
if i > 100:
for j in range(mj_model.na):
mj_model.actuator(j).gainprm[2] = 0
mj_model.actuator(j).biasprm[2] = 0
mujoco.mj_step(mj_model, mj_data)
time.sleep(0.01)
window.sync()
print(f"frame={i}, act_force={mj_data.actuator_force}")
check for fatigue using env
import myosuite
import gym
import time
env = gym.make('myoLegWalk-v0')
env.reset()
env.mj_render()
for i in range(200):
act = env.action_space.sample()
if i > 100:
for j in range(env.sim.model.na):
env.sim.model.actuator(j).gainprm[2] = 0
env.sim.model.actuator(j).biasprm[2] = 0
env.step(act)
time.sleep(0.01)
print(f"frame={i}, act_force={env.sim.data.actuator_force}")
Is this issue still relevant? IIRC we pushed a different fatigue model?
let's close this once we merge the new fatigue model in main