If you use these converted MuJoCo models in your research, please cite "Converting Biomechanical Models from OpenSim to MuJoCo", as well as the original models. The converted models, and the original ones, are available for academic and other non-commercial use (check the references given in table below for licenses of original models).
Disclaimer: I started writing this code when I was still learning MuJoCo and OpenSim, and therefore the code logic is subpar at some places and could use a little update.
- Doesn't work with OpenSim 4.0 (or later) models
- PathPoint names must have the same prefix and a running index, which defines the order of tendon path. For instance, in MoBL_ARMS model musculo-tendon unit DELT2 has PathPoints {"DELT2-P1", "default", "DELT2-P3", "DELT2-P4"}, and thus the PathPoint named "default" should be changed to "DELT2-P2". This problem occurs because the XML parser we're using scrambles the order of individual PathPoints in certain situations. There is a pull request to fix this behaviour, but it hasn't been merged yet (and the pull request is from 2016 so chances are it won't be merged).
- For some of the converted models the convex hulls around meshes/geometries are too close to each other and they collide. A possible remedy is to disable contacts in the converted model (although then there's a risk of physically impossible trajectories).
- The order in which TransformAxis are processed for custom joints is likely to be incorrect, although it works for the models presented here. If a converted model doesn't look like the original OpenSim model, then this might be the problem.
- PointActuator and TorqueActuator are ignored; WrappingObjects are ignored; there probably are other other OpenSim model specifications that I haven't encountered yet and are ignored as well
- The worldbody is assumed to be called ground in an OpenSim model
Easiest way to run the converter is to use conda to create the environment from conda_env.yml, activate the environment, and then run O2MConverter.py script
> conda env create --name O2MConverter --file=conda_env.yml
> conda activate O2MConverter
> python O2MConverter.py opensim_model_file.osim /location/where/converted/model/will/be/saved /location/where/geometry/files/are
-
Use conda to create the environment from conda_env_for_testing.yml. Note that this installs MuJoCo, and you must have set the environment variable MUJOCO_PY_MJKEY_PATH (pointing to your MuJoCo license file) prior to creating the environment.
-
Convert the OpenSim model as instructed above, but this time input true as fourth argument to O2MConverter.py. This disables contacts in the MuJoCo model since they are disabled in OpenSim forward simulations also.
-
Create a new template in tests/envs.py using the EnvTemplate class. Note that you need an OpenSim forward dynamics setup XML file (you can just copy and modify an existing one from models/opensim/[any_model]) and also an initial states file (this one's more tricky to create, easiest just to run forward dynamics simulation in OpenSim and use the output file with states). Also modify the function get(model_name) in tests/envs.py to return this new env.
-
Run script tests/generate_controls.py using the model name you specified in the previous step for the get function as input argument. This creates a hundred muscle excitation sets in a folder specified by the EnvTemplate object.
-
Run script tests/run_opensim_simulations.py (using the model name as input argument) to run the OpenSim simulations with the generated muscle excitation sets
-
Run script tests/optimize_mujoco_parameters.py (using the model name as input argument) to optimize the converted model parameters. The parameters will be saved in a file specified by the EnvTemplate object.
The optimized parameters are saved in tests/[model_name]/output/data.pckl, or in a file specified by the EnvTemplate object if you created & optimized a new model. Use function load_data(args) from Utils.py to load the optimized parameters, and function set_parameters(args) to set the models into a mujoco_py.PyMjModel model (see function run_mujoco_simulations(args) in tests/process_test_runs.py for an example).