├── .dockerignore
├── .github
└── ISSUE_TEMPLATE
│ └── bug_report.md
├── .gitignore
├── .travis.yml
├── Dockerfile
├── LICENSE.md
├── MANIFEST.in
├── Makefile
├── README.md
├── docs
├── .nojekyll
├── Makefile
├── _static
│ └── .gitkeep
├── _templates
│ └── .gitkeep
├── build
│ ├── doctrees
│ │ ├── environment.pickle
│ │ ├── index.doctree
│ │ ├── internals.doctree
│ │ └── reference.doctree
│ └── html
│ │ ├── .buildinfo
│ │ ├── _modules
│ │ ├── index.html
│ │ └── mujoco_py
│ │ │ ├── builder.html
│ │ │ └── mjviewer.html
│ │ ├── _sources
│ │ ├── index.rst.txt
│ │ ├── internals.rst.txt
│ │ └── reference.rst.txt
│ │ ├── _static
│ │ ├── ajax-loader.gif
│ │ ├── basic.css
│ │ ├── comment-bright.png
│ │ ├── comment-close.png
│ │ ├── comment.png
│ │ ├── css
│ │ │ ├── badge_only.css
│ │ │ └── theme.css
│ │ ├── doctools.js
│ │ ├── down-pressed.png
│ │ ├── down.png
│ │ ├── file.png
│ │ ├── fonts
│ │ │ ├── Inconsolata-Bold.ttf
│ │ │ ├── Inconsolata-Regular.ttf
│ │ │ ├── Lato-Bold.ttf
│ │ │ ├── Lato-Regular.ttf
│ │ │ ├── RobotoSlab-Bold.ttf
│ │ │ ├── RobotoSlab-Regular.ttf
│ │ │ ├── fontawesome-webfont.eot
│ │ │ ├── fontawesome-webfont.svg
│ │ │ ├── fontawesome-webfont.ttf
│ │ │ └── fontawesome-webfont.woff
│ │ ├── jquery-3.1.0.js
│ │ ├── jquery.js
│ │ ├── js
│ │ │ ├── modernizr.min.js
│ │ │ └── theme.js
│ │ ├── minus.png
│ │ ├── plus.png
│ │ ├── pygments.css
│ │ ├── searchtools.js
│ │ ├── underscore-1.3.1.js
│ │ ├── underscore.js
│ │ ├── up-pressed.png
│ │ ├── up.png
│ │ └── websupport.js
│ │ ├── genindex.html
│ │ ├── index.html
│ │ ├── internals.html
│ │ ├── objects.inv
│ │ ├── reference.html
│ │ ├── search.html
│ │ └── searchindex.js
├── conf.py
├── index.html
├── index.rst
├── internals.rst
└── reference.rst
├── examples
├── body_interaction.py
├── disco_fetch.py
├── internal_functions.py
├── markers_demo.py
├── mjvive.py
├── multigpu_rendering.py
├── render_callback.py
├── serialize_model.py
├── setting_state.py
├── substep_callback.py
└── tosser.py
├── mujoco_py
├── __init__.py
├── builder.py
├── cymj.pyx
├── generated
│ ├── README.md
│ ├── __init__.py
│ ├── const.py
│ └── wrappers.pxi
├── gl
│ ├── __init__.py
│ ├── dummyshim.c
│ ├── egl.h
│ ├── eglext.h
│ ├── eglplatform.h
│ ├── eglshim.c
│ ├── glshim.h
│ ├── khrplatform.h
│ └── osmesashim.c
├── mjbatchrenderer.pyx
├── mjpid.pyx
├── mjrendercontext.pyx
├── mjrenderpool.py
├── mjsim.pyx
├── mjsimstate.pyx
├── mjviewer.py
├── modder.py
├── opengl_context.pyx
├── pxd
│ ├── __init__.py
│ ├── mjdata.pxd
│ ├── mjmodel.pxd
│ ├── mjrender.pxd
│ ├── mjui.pxd
│ ├── mjvisualize.pxd
│ └── mujoco.pxd
├── test_imgs
│ ├── test_glfw_context.png
│ ├── test_materials.premod.png
│ ├── test_materials.props.png
│ ├── test_materials.rand_all.png
│ ├── test_multiple_sims.loop0_0.png
│ ├── test_multiple_sims.loop0_1.png
│ ├── test_multiple_sims.loop1_0.png
│ ├── test_multiple_sims.loop1_1.png
│ ├── test_multiple_sims.loop2_0.png
│ ├── test_multiple_sims.loop2_1.png
│ ├── test_render_pool.mp_test_cameras.0.png
│ ├── test_render_pool.mp_test_cameras.1.png
│ ├── test_render_pool.mp_test_rendering.0.png
│ ├── test_render_pool.mp_test_states.1.png
│ ├── test_render_pool.mp_test_states.2.png
│ ├── test_render_pool.mp_test_states.3.png
│ ├── test_render_pool.mp_test_states.4.png
│ ├── test_render_pool.mp_test_states.5.png
│ ├── test_rendering.camera1.narrow.png
│ ├── test_rendering.camera1.png
│ ├── test_rendering.freecam.depth-darwin.png
│ ├── test_rendering.freecam.depth.png
│ ├── test_rendering.freecam.png
│ ├── test_rendering_markers.camera1.png
│ ├── test_resetting.loop0_0.png
│ ├── test_resetting.loop0_1.png
│ ├── test_resetting.loop1_0.png
│ ├── test_resetting.loop1_1.png
│ ├── test_resetting.loop2_0.png
│ ├── test_resetting.loop2_1.png
│ ├── test_textures.premod.png
│ ├── test_textures.rand_all.png
│ ├── test_textures.rand_specific.png
│ ├── test_textures.rand_texrepeat.png
│ ├── test_textures.rgb.png
│ └── test_textures.variety.png
├── tests
│ ├── __init__.py
│ ├── include.xml
│ ├── test.xml
│ ├── test_composite.py
│ ├── test_cymj.py
│ ├── test_examples.py
│ ├── test_gen_wrappers.py
│ ├── test_modder.py
│ ├── test_opengl_context.py
│ ├── test_pid.py
│ ├── test_render_pool.py
│ ├── test_substep.py
│ ├── test_vfs.py
│ ├── test_viewer.py
│ └── utils.py
├── utils.py
└── version.py
├── pyproject.toml
├── requirements.dev.txt
├── requirements.txt
├── scripts
└── gen_wrappers.py
├── setup.py
├── vendor
├── 10_nvidia.json
├── Xdummy
└── Xdummy-entrypoint
└── xmls
├── claw.xml
├── door.xml
├── fetch
├── base_link_collision.stl
├── bellows_link_collision.stl
├── elbow_flex_link_collision.stl
├── estop_link.stl
├── forearm_roll_link_collision.stl
├── gripper_link.stl
├── head_pan_link_collision.stl
├── head_tilt_link_collision.stl
├── l_wheel_link_collision.stl
├── laser_link.stl
├── main.xml
├── r_wheel_link_collision.stl
├── shoulder_lift_link_collision.stl
├── shoulder_pan_link_collision.stl
├── torso_fixed_link.stl
├── torso_lift_link_collision.stl
├── upperarm_roll_link_collision.stl
├── wrist_flex_link_collision.stl
└── wrist_roll_link_collision.stl
├── juggler.xml
├── key.xml
├── shelf.xml
├── slider.xml
└── tosser.xml
/.dockerignore:
--------------------------------------------------------------------------------
1 | generated_cymj*
2 | _pyxbld*
3 | dist
4 | cache
5 | .idea/*
6 | *~
7 | .*~
8 | *#*#
9 | *.o
10 | *.dat
11 | *.prof
12 | *.lprof
13 | *.local
14 | .realsync
15 | .DS_Store
16 | **/*.egg-info
17 | .cache
18 | *.ckpt
19 | *.log
20 | .ipynb_checkpoints
21 | venv/
22 | .vimrc
23 | *.settings
24 | *.svn
25 | .project
26 | .pydevproject
27 | tags
28 | *sublime-project
29 | *sublime-workspace
30 | # Intermediate outputs
31 | __pycache__
32 | **/__pycache__
33 | *.pb.*
34 | *.pyc
35 | *.swp
36 | *.swo
37 | # generated data
38 | *.rdb
39 | *.db
40 | *.avi
41 | # mujoco outputs
42 | MUJOCO_LOG.TXT
43 | model.txt
44 | .window_data
45 | .idea/*.xml
46 | outputfile
47 | tmp*
48 | cymj.c
49 | **/.git
50 | **/*.so
51 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/bug_report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Bug report
3 | about: Create a report to help us improve
4 |
5 | ---
6 |
7 | **Describe the bug**
8 | A clear and concise description of what the bug is.
9 |
10 | **To Reproduce**
11 | Steps to reproduce the behavior.
12 |
13 | **Expected behavior**
14 | A clear and concise description of what you expected to happen.
15 |
16 | **Error Messages**
17 | Including more/longer error messages gives us more information to work with.
18 |
19 | **Desktop (please complete the following information):**
20 | - OS: [e.g. macOS 10.13.6]
21 | - Python Version [e.g. 3.6.6]
22 | - Mujoco Version [e.g. 1.50]
23 | - mujoco-py version [e.g. 1.50.1.59]
24 |
25 | **Environment**
26 | - output of: `echo $LD_LIBRARY_PATH`
27 | - output of: `echo $HOME`
28 | - output of: `echo $USER`
29 |
30 | **Additional context**
31 | Add any other context about the problem here.
32 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | mujoco-py-**
2 | mjkey.txt
3 | mujoco_py/generated/cymj*
4 | _pyxbld*
5 | dist
6 | cache
7 | .idea/*
8 | *~
9 | .*~
10 | *#*#
11 | *.o
12 | *.dat
13 | *.prof
14 | *.lprof
15 | *.local
16 | .realsync
17 | .DS_Store
18 | **/*.egg-info
19 | .cache
20 | *.ckpt
21 | *.log
22 | .ipynb_checkpoints
23 | venv/
24 | .vimrc
25 | *.settings
26 | *.svn
27 | .project
28 | .pydevproject
29 | tags
30 | *sublime-project
31 | *sublime-workspace
32 | # Intermediate outputs
33 | __pycache__
34 | **/__pycache__
35 | *.pb.*
36 | *.pyc
37 | *.swp
38 | *.swo
39 | # generated data
40 | *.rdb
41 | *.db
42 | *.avi
43 | # mujoco outputs
44 | MUJOCO_LOG.TXT
45 | model.txt
46 | .window_data
47 | .idea/*.xml
48 | outputfile
49 | tmp*
50 | cymj.c
51 | **/.git
52 | .eggs/
53 | *.so
54 | .python-version
55 | /build
56 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: generic
2 |
3 | before_install:
4 | - curl $MUJOCO_FOR_LINUX | tar -xz ./mjkey.txt
5 | - docker build -t image-under-test .
6 |
7 | script:
8 | - docker run --rm image-under-test
9 |
--------------------------------------------------------------------------------
/Dockerfile:
--------------------------------------------------------------------------------
1 | # We need the CUDA base dockerfile to enable GPU rendering
2 | # on hosts with GPUs.
3 | # The image below is a pinned version of nvidia/cuda:9.1-cudnn7-devel-ubuntu16.04 (from Jan 2018)
4 | # If updating the base image, be sure to test on GPU since it has broken in the past.
5 | FROM nvidia/cuda@sha256:4df157f2afde1cb6077a191104ab134ed4b2fd62927f27b69d788e8e79a45fa1
6 |
7 | RUN apt-get update -q \
8 | && DEBIAN_FRONTEND=noninteractive apt-get install -y \
9 | curl \
10 | git \
11 | libgl1-mesa-dev \
12 | libgl1-mesa-glx \
13 | libglew-dev \
14 | libosmesa6-dev \
15 | software-properties-common \
16 | net-tools \
17 | vim \
18 | virtualenv \
19 | wget \
20 | xpra \
21 | xserver-xorg-dev \
22 | && apt-get clean \
23 | && rm -rf /var/lib/apt/lists/*
24 |
25 | RUN DEBIAN_FRONTEND=noninteractive add-apt-repository --yes ppa:deadsnakes/ppa && apt-get update
26 | RUN DEBIAN_FRONTEND=noninteractive apt-get install --yes python3.6-dev python3.6 python3-pip
27 | RUN virtualenv --python=python3.6 env
28 |
29 | RUN rm /usr/bin/python
30 | RUN ln -s /env/bin/python3.6 /usr/bin/python
31 | RUN ln -s /env/bin/pip3.6 /usr/bin/pip
32 | RUN ln -s /env/bin/pytest /usr/bin/pytest
33 |
34 | RUN curl -o /usr/local/bin/patchelf https://s3-us-west-2.amazonaws.com/openai-sci-artifacts/manual-builds/patchelf_0.9_amd64.elf \
35 | && chmod +x /usr/local/bin/patchelf
36 |
37 | ENV LANG C.UTF-8
38 |
39 | RUN mkdir -p /root/.mujoco \
40 | && wget https://mujoco.org/download/mujoco210-linux-x86_64.tar.gz -O mujoco.tar.gz \
41 | && tar -xf mujoco.tar.gz -C /root/.mujoco \
42 | && rm mujoco.tar.gz
43 |
44 | ENV LD_LIBRARY_PATH /root/.mujoco/mujoco210/bin:${LD_LIBRARY_PATH}
45 | ENV LD_LIBRARY_PATH /usr/local/nvidia/lib64:${LD_LIBRARY_PATH}
46 |
47 | COPY vendor/Xdummy /usr/local/bin/Xdummy
48 | RUN chmod +x /usr/local/bin/Xdummy
49 |
50 | # Workaround for https://bugs.launchpad.net/ubuntu/+source/nvidia-graphics-drivers-375/+bug/1674677
51 | COPY ./vendor/10_nvidia.json /usr/share/glvnd/egl_vendor.d/10_nvidia.json
52 |
53 | WORKDIR /mujoco_py
54 | # Copy over just requirements.txt at first. That way, the Docker cache doesn't
55 | # expire until we actually change the requirements.
56 | COPY ./requirements.txt /mujoco_py/
57 | COPY ./requirements.dev.txt /mujoco_py/
58 | RUN pip install --no-cache-dir -r requirements.txt
59 | RUN pip install --no-cache-dir -r requirements.dev.txt
60 |
61 | # Delay moving in the entire code until the very end.
62 | ENTRYPOINT ["/mujoco_py/vendor/Xdummy-entrypoint"]
63 | CMD ["pytest"]
64 | COPY . /mujoco_py
65 | RUN python setup.py install
66 |
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | # mujoco-py
2 |
3 | The MIT License
4 |
5 | Copyright (c) 2017 OpenAI (http://openai.com)
6 |
7 | Permission is hereby granted, free of charge, to any person obtaining a copy
8 | of this software and associated documentation files (the "Software"), to deal
9 | in the Software without restriction, including without limitation the rights
10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | copies of the Software, and to permit persons to whom the Software is
12 | furnished to do so, subject to the following conditions:
13 |
14 | The above copyright notice and this permission notice shall be included in
15 | all copies or substantial portions of the Software.
16 |
17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 | THE SOFTWARE.
24 |
25 | # Mujoco models
26 | This work is derived from [MuJuCo models](http://www.mujoco.org/forum/index.php?resources/) used under the following license:
27 | ```
28 | This file is part of MuJoCo.
29 | Copyright 2009-2015 Roboti LLC.
30 | Mujoco :: Advanced physics simulation engine
31 | Source : www.roboti.us
32 | Version : 1.31
33 | Released : 23Apr16
34 | Author :: Vikash Kumar
35 | Contacts : kumar@roboti.us
36 | ```
37 |
--------------------------------------------------------------------------------
/MANIFEST.in:
--------------------------------------------------------------------------------
1 | include pyproject.toml
2 | include requirements.txt
3 | include requirements.dev.txt
4 | recursive-include mujoco_py *.h *.py *.pyx *.pxd *.pxi *.xml *.c
5 | include mujoco_py/gl/*.c
6 | include setup.py
7 | include mujoco_py/generated/cymj_*_linuxcpuextensionbuilder.so
8 | include mujoco_py/generated/cymj_*_linuxgpuextensionbuilder.so
9 | include xmls/*
10 |
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 | SHELL := /bin/bash
2 | .PHONY: all clean build test mount_shell shell upload check-env
3 |
4 | VERSION := `cd mujoco_py; python -c "from version import get_version;print(get_version())"; cd ..`
5 | PYTHON_VERSION := "36"
6 | DOCKER_NAME := quay.io/openai/mujoco_py:$(USER)_$(VERSION)
7 | DOCKER := $(shell type -p nvidia-docker || echo docker)
8 | UUID := $(shell uuidgen)
9 |
10 | all: test
11 |
12 | clean:
13 | rm -rf mujoco_py.egg-info
14 | rm -rf */__pycache__
15 | rm -rf */*/__pycache__
16 | rm -rf mujoco_py/generated/_pyxbld*
17 | rm -rf mujoco_py/generated/*.so
18 | rm -rf mujoco_py/generated/*.dll
19 | rm -rf mujoco_py/generated_cymj*
20 | rm -rf mujoco_py/cythonlock_*.pyc
21 | rm -rf mujoco_py/cymj.c
22 | rm -rf mujoco_py/__pycache__
23 | rm -rf dist
24 | rm -rf build
25 |
26 | build:
27 | docker build -t $(DOCKER_NAME) .
28 |
29 | push:
30 | docker push $(DOCKER_NAME)
31 |
32 | pull:
33 | docker pull $(DOCKER_NAME)
34 |
35 | test: build
36 | # run it interactive mode so we can abort with CTRL+C
37 | $(DOCKER) run --rm -i $(DOCKER_NAME) pytest
38 |
39 | test_gpu: build push
40 | $(eval NODE="$(shell cirrascale-cli reserve -g 1080ti -t 10m)")
41 | $(eval GPUS="$(shell echo $(NODE)| grep -oE '[^:]+f' | cut -c1-1 )")
42 | $(eval NODE="$(shell echo $(NODE)| grep -oE '[^=]+:' | sed 's/://')")
43 | ssh -t -o StrictHostKeyChecking=no $(NODE) 'docker pull $(DOCKER_NAME) && export GPUS=$(GPUS) && nvidia-docker run --rm -e GPUS -i $(DOCKER_NAME) pytest -m "not requires_glfw"'
44 |
45 | shell:
46 | $(DOCKER) run --rm -it $(DOCKER_NAME) /bin/bash
47 |
48 | mount:
49 | $(DOCKER) run -e GPUS -it -v `pwd`:/mujoco_py-dev $(DOCKER_NAME) /bin/bash -c "pip uninstall -y mujoco-py; rm -rf /mujoco_py; (cd /mujoco_py-dev; export PYTHONPATH='/mujoco_py-dev'; /bin/bash)"
50 |
51 | cirra:
52 | $(eval NODE="$(shell cirrascale-cli reserve)")
53 | $(eval GPUS="$(shell echo $(NODE)| grep -oE '[^:]+f' | cut -c1-1 )")
54 | $(eval NODE="$(shell echo $(NODE)| grep -oE '[^=]+:' | sed 's/://')")
55 | tmux new-session "while :; do rsync -e 'ssh -o StrictHostKeyChecking=no' --delete -rzai --out-format='%t %f %b' --chmod=Du+rwx --exclude='*extensionbuilder.so' --exclude='dist' --exclude='cymj.c' --exclude='_pyxbld_*' --exclude='__pycache__' --exclude='*.egg-info' --exclude='.cache' --exclude='.git' --exclude='*.pyc' --exclude='*.swp' --exclude='.idea' . $(NODE):~/mujoco_py/ ; sleep 1; done" \; \
56 | split-window "ssh -t -o StrictHostKeyChecking=no $(NODE) 'mkdir -p ~/mujoco_py && cd ~/mujoco_py && export GPUS=$(GPUS) && /bin/bash'; " \; select-layout 9ce0,204x51,0,0[204x4,0,0,32,204x46,0,5,33]
57 |
58 | # Requires to generate all *.so files. Call make generate_mac_so on mac;
59 | # Call make generate_cpu_so on mac or linux.
60 | #
61 | # Call make generate_gpu_so on linux with nvidia-docker. The easiest way is to get to cirrascale, and call: make cirra.
62 | # Then you have to copy back generated cymj_linuxgpuextensionbuilder.so file.
63 | #
64 | # Gather all *.so files.
65 | upload:
66 | # Commented out for now, binary distributions seem not to work very well
67 | # test -f ./mujoco_py/generated/cymj_$(VERSION)_$(PYTHON_VERSION)_linuxcpuextensionbuilder.so || exit -1
68 | # test -f ./mujoco_py/generated/cymj_$(VERSION)_$(PYTHON_VERSION)_linuxgpuextensionbuilder.so || exit -1
69 | rm -rf dist
70 | python setup.py sdist
71 | twine upload dist/*
72 |
73 | generate_gpu_so:
74 | rm -f ./mujoco_py/generated/cymj_*_linuxgpuextensionbuilder.so
75 | nvidia-docker run -it --name $(UUID) $(DOCKER_NAME) bash -c "make clean;python -c 'import mujoco_py'"
76 | nvidia-docker cp $(UUID):/mujoco_py/mujoco_py/generated/cymj_$(VERSION)_$(PYTHON_VERSION)_linuxgpuextensionbuilder.so mujoco_py/generated/
77 |
78 | generate_cpu_so:
79 | rm -f ./mujoco_py/generated/cymj_*_linuxcpuextensionbuilder.so
80 | docker run -it --name $(UUID) $(DOCKER_NAME) bash -c "make clean;python -c 'import mujoco_py'"
81 | docker cp $(UUID):/mujoco_py/mujoco_py/generated/cymj_$(VERSION)_$(PYTHON_VERSION)_linuxcpuextensionbuilder.so mujoco_py/generated/
82 |
83 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | **Status**: Deprecated
2 |
3 | ### `mujoco-py` does not support versions of MuJoCo after 2.1.0.
4 |
5 | ### New users should depend on the [official MuJoCo Python bindings](https://github.com/deepmind/mujoco/blob/main/python/README.md).
6 |
7 | # mujoco-py [](https://openai.github.io/mujoco-py/build/html/index.html) [](https://travis-ci.org/openai/mujoco-py)
8 |
9 | [MuJoCo](http://mujoco.org/) is a physics engine for detailed, efficient rigid body simulations with contacts.
10 | `mujoco-py` allows using MuJoCo from Python 3.
11 |
12 | This library has been updated to be compatible with MuJoCo version 2.1 released on 2021-10-18.
13 |
14 |
15 | ## Synopsis
16 |
17 | ### Requirements
18 |
19 | The following platforms are currently supported:
20 |
21 | - Linux with Python 3.6+. See [the `Dockerfile`](Dockerfile) for the canonical list of system dependencies.
22 | - OS X with Python 3.6+.
23 |
24 | The following platforms are DEPRECATED and unsupported:
25 |
26 | - Windows support has been DEPRECATED and removed in [2.0.2.0](https://github.com/openai/mujoco-py/releases/tag/v2.0.2.0a1). One known good past version is [1.50.1.68](https://github.com/openai/mujoco-py/blob/9ea9bb000d6b8551b99f9aa440862e0c7f7b4191/README.md#requirements).
27 | - Python 2 has been DEPRECATED and removed in [1.50.1.0](https://github.com/openai/mujoco-py/releases/tag/1.50.1.0). Python 2 users can stay on the [`0.5` branch](https://github.com/openai/mujoco-py/tree/0.5). The latest release there is [`0.5.7`](https://github.com/openai/mujoco-py/releases/tag/0.5.7) which can be installed with `pip install mujoco-py==0.5.7`.
28 |
29 | ### Install MuJoCo
30 |
31 | 1. Download the MuJoCo version 2.1 binaries for
32 | [Linux](https://mujoco.org/download/mujoco210-linux-x86_64.tar.gz) or
33 | [OSX](https://mujoco.org/download/mujoco210-macos-x86_64.tar.gz).
34 | 1. Extract the downloaded `mujoco210` directory into `~/.mujoco/mujoco210`.
35 |
36 | If you want to specify a nonstandard location for the package,
37 | use the env variable `MUJOCO_PY_MUJOCO_PATH`.
38 |
39 | ### Install and use `mujoco-py`
40 | To include `mujoco-py` in your own package, add it to your requirements like so:
41 | ```
42 | mujoco-py<2.2,>=2.1
43 | ```
44 | To play with `mujoco-py` interactively, follow these steps:
45 | ```
46 | $ pip3 install -U 'mujoco-py<2.2,>=2.1'
47 | $ python3
48 | import mujoco_py
49 | import os
50 | mj_path = mujoco_py.utils.discover_mujoco()
51 | xml_path = os.path.join(mj_path, 'model', 'humanoid.xml')
52 | model = mujoco_py.load_model_from_path(xml_path)
53 | sim = mujoco_py.MjSim(model)
54 |
55 | print(sim.data.qpos)
56 | # [0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
57 |
58 | sim.step()
59 | print(sim.data.qpos)
60 | # [-2.09531783e-19 2.72130735e-05 6.14480786e-22 -3.45474715e-06
61 | # 7.42993721e-06 -1.40711141e-04 -3.04253586e-04 -2.07559344e-04
62 | # 8.50646247e-05 -3.45474715e-06 7.42993721e-06 -1.40711141e-04
63 | # -3.04253586e-04 -2.07559344e-04 -8.50646247e-05 1.11317030e-04
64 | # -7.03465386e-05 -2.22862221e-05 -1.11317030e-04 7.03465386e-05
65 | # -2.22862221e-05]
66 | ```
67 |
68 | See the [full documentation](https://openai.github.io/mujoco-py/build/html/index.html) for advanced usage.
69 |
70 | ## Troubleshooting
71 |
72 | ### You're on MacOS and you see `clang: error: unsupported option '-fopenmp'`
73 |
74 | If this happend during installation or just running `python -c "import mujoco_py"` then the issue seems to be related to [this](https://github.com/velocyto-team/velocyto.R/issues/2#issuecomment-341165967) and the TL;DR is that for macOS the default compiler Apple clang LLVM does not support openmp. So you can try to install another clang/llvm installation. For example (requires [brew](https://brew.sh/)):
75 |
76 | ```bash
77 | brew install llvm
78 | brew install boost
79 | brew install hdf5
80 |
81 | # Add this to your .bashrc/.zshrc:
82 | export PATH="/usr/local/opt/llvm/bin:$PATH"
83 |
84 | export CC="/usr/local/opt/llvm/bin/clang"
85 | export CXX="/usr/local/opt/llvm/bin/clang++"
86 | export CXX11="/usr/local/opt/llvm/bin/clang++"
87 | export CXX14="/usr/local/opt/llvm/bin/clang++"
88 | export CXX17="/usr/local/opt/llvm/bin/clang++"
89 | export CXX1X="/usr/local/opt/llvm/bin/clang++"
90 |
91 | export LDFLAGS="-L/usr/local/opt/llvm/lib"
92 | export CPPFLAGS="-I/usr/local/opt/llvm/include"
93 | ```
94 |
95 | **Note:** Don't forget to source your `.bashrc/.zshrc` after editing it and try to install `mujoco-py` again:
96 |
97 | ```bash
98 | # Make sure your python environment is activated
99 | pip install -U 'mujoco-py<2.2,>=2.1'
100 | ```
101 |
102 | ### Missing GLFW
103 |
104 | A common error when installing is:
105 |
106 | raise ImportError("Failed to load GLFW3 shared library.")
107 |
108 | Which happens when the `glfw` python package fails to find a GLFW dynamic library.
109 |
110 | MuJoCo ships with its own copy of this library, which can be used during installation.
111 |
112 | Add the path to the mujoco bin directory to your dynamic loader:
113 |
114 | LD_LIBRARY_PATH=$HOME/.mujoco/mujoco210/bin pip install mujoco-py
115 |
116 | This is particularly useful on Ubuntu 14.04, which does not have a GLFW package.
117 |
118 |
119 | ### Ubuntu installtion troubleshooting
120 |
121 | Because `mujoco_py` has compiled native code that needs to be linked to a supplied MuJoCo binary, it's installation
122 | on linux can be more challenging than pure Python source packages.
123 |
124 | To install mujoco-py on Ubuntu, make sure you have the following libraries installed:
125 |
126 | sudo apt install libosmesa6-dev libgl1-mesa-glx libglfw3
127 |
128 | If you installed above libraries and you still see an error that `-lGL` cannot be found, most likely you need
129 | to create the symbolic link directly:
130 |
131 | sudo ln -s /usr/lib/x86_64-linux-gnu/libGL.so.1 /usr/lib/x86_64-linux-gnu/libGL.so
132 |
133 |
134 | ## Usage Examples
135 |
136 | A number of examples demonstrating some advanced features of `mujoco-py` can be found in [`examples/`](/./examples/). These include:
137 | - [`body_interaction.py`](./examples/body_interaction.py): shows interactions between colliding bodies
138 | - [`disco_fetch.py`](./examples/disco_fetch.py): shows how `TextureModder` can be used to randomize object textures
139 | - [`internal_functions.py`](./examples/internal_functions.py): shows how to call raw mujoco functions like `mjv_room2model`
140 | - [`markers_demo.py`](./examples/markers_demo.py): shows how to add visualization-only geoms to the viewer
141 | - [`serialize_model.py`](./examples/serialize_model.py): shows how to save and restore a model
142 | - [`setting_state.py`](./examples/setting_state.py): shows how to reset the simulation to a given state
143 | - [`tosser.py`](./examples/tosser.py): shows a simple actuated object sorting robot application
144 |
145 | See the [full documentation](https://openai.github.io/mujoco-py/build/html/index.html) for advanced usage.
146 |
147 | ## Development
148 |
149 | To run the provided unit and integrations tests:
150 |
151 | ```
152 | make test
153 | ```
154 |
155 | To test GPU-backed rendering, run:
156 |
157 | ```
158 | make test_gpu
159 | ```
160 |
161 | This is somewhat dependent on internal OpenAI infrastructure at the moment, but it should run if you change the `Makefile` parameters for your own setup.
162 |
163 | ## Changelog
164 |
165 | - 03/08/2018: We removed MjSimPool, because most of benefit one can get with multiple processes having single simulation.
166 |
167 | ## Credits
168 |
169 | `mujoco-py` is maintained by the OpenAI Robotics team. Contributors include:
170 |
171 | - Alex Ray
172 | - Bob McGrew
173 | - Jonas Schneider
174 | - Jonathan Ho
175 | - Peter Welinder
176 | - Wojciech Zaremba
177 | - Jerry Tworek
178 |
--------------------------------------------------------------------------------
/docs/.nojekyll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/openai/mujoco-py/a13903b82f1ab316815e63b3575526005b3b2ae1/docs/.nojekyll
--------------------------------------------------------------------------------
/docs/Makefile:
--------------------------------------------------------------------------------
1 | SPHINXOPTS =
2 | SPHINXBUILD = python -msphinx
3 | SPHINXPROJ = mujoco-py
4 | SOURCEDIR = .
5 | BUILDDIR = build
6 |
7 | .PHONY: all clean
8 |
9 | all:
10 | @$(SPHINXBUILD) -M html "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
11 |
12 | clean:
13 | @$(SPHINXBUILD) -M clean "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
14 |
--------------------------------------------------------------------------------
/docs/_static/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/openai/mujoco-py/a13903b82f1ab316815e63b3575526005b3b2ae1/docs/_static/.gitkeep
--------------------------------------------------------------------------------
/docs/_templates/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/openai/mujoco-py/a13903b82f1ab316815e63b3575526005b3b2ae1/docs/_templates/.gitkeep
--------------------------------------------------------------------------------
/docs/build/doctrees/environment.pickle:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/openai/mujoco-py/a13903b82f1ab316815e63b3575526005b3b2ae1/docs/build/doctrees/environment.pickle
--------------------------------------------------------------------------------
/docs/build/doctrees/index.doctree:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/openai/mujoco-py/a13903b82f1ab316815e63b3575526005b3b2ae1/docs/build/doctrees/index.doctree
--------------------------------------------------------------------------------
/docs/build/doctrees/internals.doctree:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/openai/mujoco-py/a13903b82f1ab316815e63b3575526005b3b2ae1/docs/build/doctrees/internals.doctree
--------------------------------------------------------------------------------
/docs/build/doctrees/reference.doctree:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/openai/mujoco-py/a13903b82f1ab316815e63b3575526005b3b2ae1/docs/build/doctrees/reference.doctree
--------------------------------------------------------------------------------
/docs/build/html/.buildinfo:
--------------------------------------------------------------------------------
1 | # Sphinx build info version 1
2 | # This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done.
3 | config: ed7df2c1f6fc81f1edc97343eaa55651
4 | tags: 645f666f9bcd5a90fca523b33c5a78b7
5 |
--------------------------------------------------------------------------------
/docs/build/html/_modules/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 | Overview: module code — mujoco-py 1.50.1.0 documentation
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 | mujoco-py
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 | Docs »
137 |
138 | Overview: module code
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
All modules for which code is available
156 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
180 |
181 |
182 |
183 |
184 |
185 |
186 |
187 |
188 |
189 |
190 |
191 |
192 |
202 |
203 |
204 |
205 |
206 |
207 |
208 |
209 |
210 |
211 |
212 |
213 |
214 |
215 |
220 |
221 |
222 |
223 |
--------------------------------------------------------------------------------
/docs/build/html/_sources/index.rst.txt:
--------------------------------------------------------------------------------
1 | =======================
2 | mujoco-py Documentation
3 | =======================
4 |
5 | .. toctree::
6 | reference
7 | internals
8 |
9 | `MuJoCo `_ is a physics engine for detailed, efficient rigid body simulations with contacts. ``mujoco-py`` allows using MuJoCo from Python 3.
10 |
11 | See the `README `_ for installation instructions and example usage.
12 |
13 | ``mujoco-py`` allows access to MuJoCo on a number of different levels of abstraction:
14 |
15 | - Directly from Cython (low-level): `Raw Cython declarations `_ are provided for using the MuJoCo C structs and functions directly in your own Cython code.
16 |
17 | - Using :ref:`pymjdata` (medium-level): These wrappers are lightweight Cython ``cdef`` classes that expose MuJuCo data to Python space. The data in the MuJoCo structs is exposed as NumPy arrays bound to Mujoco-allocated memory, so there is no copying overhead when accessing or modifying MuJoCo state from Python. For more information on how this works internally, see [this document](./doc/cython_wrappers.md).
18 |
19 | - Using :class:`mujoco_py.MjSim` (high-level): :class:`mujoco_py.MjSim` manages a stateful simulation similar to the `MujocoEnv `_ class found in `Gym `_
20 | .
21 |
--------------------------------------------------------------------------------
/docs/build/html/_sources/internals.rst.txt:
--------------------------------------------------------------------------------
1 | Internals
2 | =========
3 |
4 | .. _genwrapper:
5 |
6 | Autogenerated wrappers
7 | ----------------------
8 |
9 | The Cython struct wrappers are generated by ``scripts/gen_wrappers.py``. To illustrate how the wrappers work, let's consider a toy C structure and the corresponding generated Cython cdef class. Here's a stripped down version of ``mjData`` with a scalar member and a pointer (array) member::
10 |
11 | typedef struct _mjData {
12 | int ne;
13 | mjtNum* qpos; // (nq x 1)
14 | } mjData;
15 |
16 | Here's the corresponding generated Cython wrapper code::
17 |
18 | cdef class PyMjData(object):
19 | cdef mjData* ptr
20 | cdef mjModel* _model
21 | cdef np.ndarray _qpos
22 |
23 | cdef void _set(self, mjData* p, mjModel* model):
24 | self.ptr = p
25 | self._model = model
26 | self._qpos = _wrap_mjtNum_1d(p.qpos, model.nq)
27 |
28 | @property
29 | def ne(self): return self.ptr.ne
30 |
31 | @ne.setter
32 | def ne(self, int x): self.ptr.ne = x
33 |
34 | @property
35 | def qpos(self): return self._qpos
36 |
37 | cdef PyMjData WrapMjData(mjData* p, mjModel* model):
38 | cdef PyMjData o = PyMjData()
39 | o._set(p, model)
40 | return o
41 |
42 | ``PyMjData`` is the wrapper class for exposing the underlying Mujoco structure to Python; it doesn't perform any memory mangement. A user writing Cython code can create this wrapper using ``WrapMjData``. A ``mjModel`` pointer must be passed because the shape of a ``mjData`` member, namely ``qpos``, depends on ``model->nq``.
43 |
44 | Each field of ``mjData`` corresponds to some generated piece of code in ``PyMjData`` that depends on the type of that field. For example, ``ne`` is a scalar integer, so it gets exposed as a pair of getter and setter methods in ``PyMjData``. ``qpos`` is an array represented as a pointer to its first element, so it's wrapped with a NumPy array by ``_wrap_mjtNum_1d`` and is exposed with a getter for that NumPy array.
45 |
46 | The function ``_wrap_mjtNum_1d`` creates a Cython memoryview from the data pointer and converts it to a NumPy array pointing to the same memory::
47 |
48 | cdef inline np.ndarray _wrap_mjtNum_1d(mjtNum* a, int shape0):
49 | if shape0 == 0: return None
50 | cdef mjtNum[:] b = a
51 | return np.asarray(b)
52 |
53 | Similar functions for other types are also generated as required.
54 |
55 | Keep in mind that the only reason to use these autogenerated wrappers is to allow Python users of the Cython code to easily access Mujoco data (for instance the ``MjSim`` Cython class, found in ``cymj/cymj.pyx`). If you're writing Cython code and you don't need the user to access Mujoco data from Python, then there is no reason to use these wrappers.
56 |
--------------------------------------------------------------------------------
/docs/build/html/_static/ajax-loader.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/openai/mujoco-py/a13903b82f1ab316815e63b3575526005b3b2ae1/docs/build/html/_static/ajax-loader.gif
--------------------------------------------------------------------------------
/docs/build/html/_static/comment-bright.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/openai/mujoco-py/a13903b82f1ab316815e63b3575526005b3b2ae1/docs/build/html/_static/comment-bright.png
--------------------------------------------------------------------------------
/docs/build/html/_static/comment-close.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/openai/mujoco-py/a13903b82f1ab316815e63b3575526005b3b2ae1/docs/build/html/_static/comment-close.png
--------------------------------------------------------------------------------
/docs/build/html/_static/comment.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/openai/mujoco-py/a13903b82f1ab316815e63b3575526005b3b2ae1/docs/build/html/_static/comment.png
--------------------------------------------------------------------------------
/docs/build/html/_static/css/badge_only.css:
--------------------------------------------------------------------------------
1 | .fa:before{-webkit-font-smoothing:antialiased}.clearfix{*zoom:1}.clearfix:before,.clearfix:after{display:table;content:""}.clearfix:after{clear:both}@font-face{font-family:FontAwesome;font-weight:normal;font-style:normal;src:url("../font/fontawesome_webfont.eot");src:url("../font/fontawesome_webfont.eot?#iefix") format("embedded-opentype"),url("../font/fontawesome_webfont.woff") format("woff"),url("../font/fontawesome_webfont.ttf") format("truetype"),url("../font/fontawesome_webfont.svg#FontAwesome") format("svg")}.fa:before{display:inline-block;font-family:FontAwesome;font-style:normal;font-weight:normal;line-height:1;text-decoration:inherit}a .fa{display:inline-block;text-decoration:inherit}li .fa{display:inline-block}li .fa-large:before,li .fa-large:before{width:1.875em}ul.fas{list-style-type:none;margin-left:2em;text-indent:-0.8em}ul.fas li .fa{width:0.8em}ul.fas li .fa-large:before,ul.fas li .fa-large:before{vertical-align:baseline}.fa-book:before{content:""}.icon-book:before{content:""}.fa-caret-down:before{content:""}.icon-caret-down:before{content:""}.fa-caret-up:before{content:""}.icon-caret-up:before{content:""}.fa-caret-left:before{content:""}.icon-caret-left:before{content:""}.fa-caret-right:before{content:""}.icon-caret-right:before{content:""}.rst-versions{position:fixed;bottom:0;left:0;width:300px;color:#fcfcfc;background:#1f1d1d;border-top:solid 10px #343131;font-family:"Lato","proxima-nova","Helvetica Neue",Arial,sans-serif;z-index:400}.rst-versions a{color:#2980B9;text-decoration:none}.rst-versions .rst-badge-small{display:none}.rst-versions .rst-current-version{padding:12px;background-color:#272525;display:block;text-align:right;font-size:90%;cursor:pointer;color:#27AE60;*zoom:1}.rst-versions .rst-current-version:before,.rst-versions .rst-current-version:after{display:table;content:""}.rst-versions .rst-current-version:after{clear:both}.rst-versions .rst-current-version .fa{color:#fcfcfc}.rst-versions .rst-current-version .fa-book{float:left}.rst-versions .rst-current-version .icon-book{float:left}.rst-versions .rst-current-version.rst-out-of-date{background-color:#E74C3C;color:#fff}.rst-versions .rst-current-version.rst-active-old-version{background-color:#F1C40F;color:#000}.rst-versions.shift-up .rst-other-versions{display:block}.rst-versions .rst-other-versions{font-size:90%;padding:12px;color:gray;display:none}.rst-versions .rst-other-versions hr{display:block;height:1px;border:0;margin:20px 0;padding:0;border-top:solid 1px #413d3d}.rst-versions .rst-other-versions dd{display:inline-block;margin:0}.rst-versions .rst-other-versions dd a{display:inline-block;padding:6px;color:#fcfcfc}.rst-versions.rst-badge{width:auto;bottom:20px;right:20px;left:auto;border:none;max-width:300px}.rst-versions.rst-badge .icon-book{float:none}.rst-versions.rst-badge .fa-book{float:none}.rst-versions.rst-badge.shift-up .rst-current-version{text-align:right}.rst-versions.rst-badge.shift-up .rst-current-version .fa-book{float:left}.rst-versions.rst-badge.shift-up .rst-current-version .icon-book{float:left}.rst-versions.rst-badge .rst-current-version{width:auto;height:30px;line-height:30px;padding:0 6px;display:block;text-align:center}@media screen and (max-width: 768px){.rst-versions{width:85%;display:none}.rst-versions.shift{display:block}}
2 | /*# sourceMappingURL=badge_only.css.map */
3 |
--------------------------------------------------------------------------------
/docs/build/html/_static/down-pressed.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/openai/mujoco-py/a13903b82f1ab316815e63b3575526005b3b2ae1/docs/build/html/_static/down-pressed.png
--------------------------------------------------------------------------------
/docs/build/html/_static/down.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/openai/mujoco-py/a13903b82f1ab316815e63b3575526005b3b2ae1/docs/build/html/_static/down.png
--------------------------------------------------------------------------------
/docs/build/html/_static/file.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/openai/mujoco-py/a13903b82f1ab316815e63b3575526005b3b2ae1/docs/build/html/_static/file.png
--------------------------------------------------------------------------------
/docs/build/html/_static/fonts/Inconsolata-Bold.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/openai/mujoco-py/a13903b82f1ab316815e63b3575526005b3b2ae1/docs/build/html/_static/fonts/Inconsolata-Bold.ttf
--------------------------------------------------------------------------------
/docs/build/html/_static/fonts/Inconsolata-Regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/openai/mujoco-py/a13903b82f1ab316815e63b3575526005b3b2ae1/docs/build/html/_static/fonts/Inconsolata-Regular.ttf
--------------------------------------------------------------------------------
/docs/build/html/_static/fonts/Lato-Bold.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/openai/mujoco-py/a13903b82f1ab316815e63b3575526005b3b2ae1/docs/build/html/_static/fonts/Lato-Bold.ttf
--------------------------------------------------------------------------------
/docs/build/html/_static/fonts/Lato-Regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/openai/mujoco-py/a13903b82f1ab316815e63b3575526005b3b2ae1/docs/build/html/_static/fonts/Lato-Regular.ttf
--------------------------------------------------------------------------------
/docs/build/html/_static/fonts/RobotoSlab-Bold.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/openai/mujoco-py/a13903b82f1ab316815e63b3575526005b3b2ae1/docs/build/html/_static/fonts/RobotoSlab-Bold.ttf
--------------------------------------------------------------------------------
/docs/build/html/_static/fonts/RobotoSlab-Regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/openai/mujoco-py/a13903b82f1ab316815e63b3575526005b3b2ae1/docs/build/html/_static/fonts/RobotoSlab-Regular.ttf
--------------------------------------------------------------------------------
/docs/build/html/_static/fonts/fontawesome-webfont.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/openai/mujoco-py/a13903b82f1ab316815e63b3575526005b3b2ae1/docs/build/html/_static/fonts/fontawesome-webfont.eot
--------------------------------------------------------------------------------
/docs/build/html/_static/fonts/fontawesome-webfont.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/openai/mujoco-py/a13903b82f1ab316815e63b3575526005b3b2ae1/docs/build/html/_static/fonts/fontawesome-webfont.ttf
--------------------------------------------------------------------------------
/docs/build/html/_static/fonts/fontawesome-webfont.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/openai/mujoco-py/a13903b82f1ab316815e63b3575526005b3b2ae1/docs/build/html/_static/fonts/fontawesome-webfont.woff
--------------------------------------------------------------------------------
/docs/build/html/_static/js/theme.js:
--------------------------------------------------------------------------------
1 | require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o");
80 |
81 | // Add expand links to all parents of nested ul
82 | $('.wy-menu-vertical ul').not('.simple').siblings('a').each(function () {
83 | var link = $(this);
84 | expand = $(' ');
85 | expand.on('click', function (ev) {
86 | self.toggleCurrent(link);
87 | ev.stopPropagation();
88 | return false;
89 | });
90 | link.prepend(expand);
91 | });
92 | };
93 |
94 | nav.reset = function () {
95 | // Get anchor from URL and open up nested nav
96 | var anchor = encodeURI(window.location.hash);
97 | if (anchor) {
98 | try {
99 | var link = $('.wy-menu-vertical')
100 | .find('[href="' + anchor + '"]');
101 | // If we didn't find a link, it may be because we clicked on
102 | // something that is not in the sidebar (eg: when using
103 | // sphinxcontrib.httpdomain it generates headerlinks but those
104 | // aren't picked up and placed in the toctree). So let's find
105 | // the closest header in the document and try with that one.
106 | if (link.length === 0) {
107 | var doc_link = $('.document a[href="' + anchor + '"]');
108 | var closest_section = doc_link.closest('div.section');
109 | // Try again with the closest section entry.
110 | link = $('.wy-menu-vertical')
111 | .find('[href="#' + closest_section.attr("id") + '"]');
112 |
113 | }
114 | $('.wy-menu-vertical li.toctree-l1 li.current')
115 | .removeClass('current');
116 | link.closest('li.toctree-l2').addClass('current');
117 | link.closest('li.toctree-l3').addClass('current');
118 | link.closest('li.toctree-l4').addClass('current');
119 | }
120 | catch (err) {
121 | console.log("Error expanding nav for anchor", err);
122 | }
123 | }
124 | };
125 |
126 | nav.onScroll = function () {
127 | this.winScroll = false;
128 | var newWinPosition = this.win.scrollTop(),
129 | winBottom = newWinPosition + this.winHeight,
130 | navPosition = this.navBar.scrollTop(),
131 | newNavPosition = navPosition + (newWinPosition - this.winPosition);
132 | if (newWinPosition < 0 || winBottom > this.docHeight) {
133 | return;
134 | }
135 | this.navBar.scrollTop(newNavPosition);
136 | this.winPosition = newWinPosition;
137 | };
138 |
139 | nav.onResize = function () {
140 | this.winResize = false;
141 | this.winHeight = this.win.height();
142 | this.docHeight = $(document).height();
143 | };
144 |
145 | nav.hashChange = function () {
146 | this.linkScroll = true;
147 | this.win.one('hashchange', function () {
148 | this.linkScroll = false;
149 | });
150 | };
151 |
152 | nav.toggleCurrent = function (elem) {
153 | var parent_li = elem.closest('li');
154 | parent_li.siblings('li.current').removeClass('current');
155 | parent_li.siblings().find('li.current').removeClass('current');
156 | parent_li.find('> ul li.current').removeClass('current');
157 | parent_li.toggleClass('current');
158 | }
159 |
160 | return nav;
161 | };
162 |
163 | module.exports.ThemeNav = ThemeNav();
164 |
165 | if (typeof(window) != 'undefined') {
166 | window.SphinxRtdTheme = { StickyNav: module.exports.ThemeNav };
167 | }
168 |
169 | },{"jquery":"jquery"}]},{},["sphinx-rtd-theme"]);
170 |
--------------------------------------------------------------------------------
/docs/build/html/_static/minus.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/openai/mujoco-py/a13903b82f1ab316815e63b3575526005b3b2ae1/docs/build/html/_static/minus.png
--------------------------------------------------------------------------------
/docs/build/html/_static/plus.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/openai/mujoco-py/a13903b82f1ab316815e63b3575526005b3b2ae1/docs/build/html/_static/plus.png
--------------------------------------------------------------------------------
/docs/build/html/_static/pygments.css:
--------------------------------------------------------------------------------
1 | .highlight .hll { background-color: #ffffcc }
2 | .highlight { background: #eeffcc; }
3 | .highlight .c { color: #408090; font-style: italic } /* Comment */
4 | .highlight .err { border: 1px solid #FF0000 } /* Error */
5 | .highlight .k { color: #007020; font-weight: bold } /* Keyword */
6 | .highlight .o { color: #666666 } /* Operator */
7 | .highlight .ch { color: #408090; font-style: italic } /* Comment.Hashbang */
8 | .highlight .cm { color: #408090; font-style: italic } /* Comment.Multiline */
9 | .highlight .cp { color: #007020 } /* Comment.Preproc */
10 | .highlight .cpf { color: #408090; font-style: italic } /* Comment.PreprocFile */
11 | .highlight .c1 { color: #408090; font-style: italic } /* Comment.Single */
12 | .highlight .cs { color: #408090; background-color: #fff0f0 } /* Comment.Special */
13 | .highlight .gd { color: #A00000 } /* Generic.Deleted */
14 | .highlight .ge { font-style: italic } /* Generic.Emph */
15 | .highlight .gr { color: #FF0000 } /* Generic.Error */
16 | .highlight .gh { color: #000080; font-weight: bold } /* Generic.Heading */
17 | .highlight .gi { color: #00A000 } /* Generic.Inserted */
18 | .highlight .go { color: #333333 } /* Generic.Output */
19 | .highlight .gp { color: #c65d09; font-weight: bold } /* Generic.Prompt */
20 | .highlight .gs { font-weight: bold } /* Generic.Strong */
21 | .highlight .gu { color: #800080; font-weight: bold } /* Generic.Subheading */
22 | .highlight .gt { color: #0044DD } /* Generic.Traceback */
23 | .highlight .kc { color: #007020; font-weight: bold } /* Keyword.Constant */
24 | .highlight .kd { color: #007020; font-weight: bold } /* Keyword.Declaration */
25 | .highlight .kn { color: #007020; font-weight: bold } /* Keyword.Namespace */
26 | .highlight .kp { color: #007020 } /* Keyword.Pseudo */
27 | .highlight .kr { color: #007020; font-weight: bold } /* Keyword.Reserved */
28 | .highlight .kt { color: #902000 } /* Keyword.Type */
29 | .highlight .m { color: #208050 } /* Literal.Number */
30 | .highlight .s { color: #4070a0 } /* Literal.String */
31 | .highlight .na { color: #4070a0 } /* Name.Attribute */
32 | .highlight .nb { color: #007020 } /* Name.Builtin */
33 | .highlight .nc { color: #0e84b5; font-weight: bold } /* Name.Class */
34 | .highlight .no { color: #60add5 } /* Name.Constant */
35 | .highlight .nd { color: #555555; font-weight: bold } /* Name.Decorator */
36 | .highlight .ni { color: #d55537; font-weight: bold } /* Name.Entity */
37 | .highlight .ne { color: #007020 } /* Name.Exception */
38 | .highlight .nf { color: #06287e } /* Name.Function */
39 | .highlight .nl { color: #002070; font-weight: bold } /* Name.Label */
40 | .highlight .nn { color: #0e84b5; font-weight: bold } /* Name.Namespace */
41 | .highlight .nt { color: #062873; font-weight: bold } /* Name.Tag */
42 | .highlight .nv { color: #bb60d5 } /* Name.Variable */
43 | .highlight .ow { color: #007020; font-weight: bold } /* Operator.Word */
44 | .highlight .w { color: #bbbbbb } /* Text.Whitespace */
45 | .highlight .mb { color: #208050 } /* Literal.Number.Bin */
46 | .highlight .mf { color: #208050 } /* Literal.Number.Float */
47 | .highlight .mh { color: #208050 } /* Literal.Number.Hex */
48 | .highlight .mi { color: #208050 } /* Literal.Number.Integer */
49 | .highlight .mo { color: #208050 } /* Literal.Number.Oct */
50 | .highlight .sa { color: #4070a0 } /* Literal.String.Affix */
51 | .highlight .sb { color: #4070a0 } /* Literal.String.Backtick */
52 | .highlight .sc { color: #4070a0 } /* Literal.String.Char */
53 | .highlight .dl { color: #4070a0 } /* Literal.String.Delimiter */
54 | .highlight .sd { color: #4070a0; font-style: italic } /* Literal.String.Doc */
55 | .highlight .s2 { color: #4070a0 } /* Literal.String.Double */
56 | .highlight .se { color: #4070a0; font-weight: bold } /* Literal.String.Escape */
57 | .highlight .sh { color: #4070a0 } /* Literal.String.Heredoc */
58 | .highlight .si { color: #70a0d0; font-style: italic } /* Literal.String.Interpol */
59 | .highlight .sx { color: #c65d09 } /* Literal.String.Other */
60 | .highlight .sr { color: #235388 } /* Literal.String.Regex */
61 | .highlight .s1 { color: #4070a0 } /* Literal.String.Single */
62 | .highlight .ss { color: #517918 } /* Literal.String.Symbol */
63 | .highlight .bp { color: #007020 } /* Name.Builtin.Pseudo */
64 | .highlight .fm { color: #06287e } /* Name.Function.Magic */
65 | .highlight .vc { color: #bb60d5 } /* Name.Variable.Class */
66 | .highlight .vg { color: #bb60d5 } /* Name.Variable.Global */
67 | .highlight .vi { color: #bb60d5 } /* Name.Variable.Instance */
68 | .highlight .vm { color: #bb60d5 } /* Name.Variable.Magic */
69 | .highlight .il { color: #208050 } /* Literal.Number.Integer.Long */
--------------------------------------------------------------------------------
/docs/build/html/_static/up-pressed.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/openai/mujoco-py/a13903b82f1ab316815e63b3575526005b3b2ae1/docs/build/html/_static/up-pressed.png
--------------------------------------------------------------------------------
/docs/build/html/_static/up.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/openai/mujoco-py/a13903b82f1ab316815e63b3575526005b3b2ae1/docs/build/html/_static/up.png
--------------------------------------------------------------------------------
/docs/build/html/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 | mujoco-py Documentation — mujoco-py 1.50.1.0 documentation
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 | mujoco-py
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 | Docs »
138 |
139 | mujoco-py Documentation
140 |
141 |
142 |
143 |
144 |
145 | View page source
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
mujoco-py Documentation
160 |
175 |
MuJoCo is a physics engine for detailed, efficient rigid body simulations with contacts. mujoco-py
allows using MuJoCo from Python 3.
176 |
See the README for installation instructions and example usage.
177 |
mujoco-py
allows access to MuJoCo on a number of different levels of abstraction:
178 |
179 | Directly from Cython (low-level): Raw Cython declarations are provided for using the MuJoCo C structs and functions directly in your own Cython code.
180 | Using PyMjData: Time-dependent data (medium-level): These wrappers are lightweight Cython cdef
classes that expose MuJuCo data to Python space. The data in the MuJoCo structs is exposed as NumPy arrays bound to Mujoco-allocated memory, so there is no copying overhead when accessing or modifying MuJoCo state from Python. For more information on how this works internally, see [this document](./doc/cython_wrappers.md).
181 | Using mujoco_py.MjSim
(high-level): mujoco_py.MjSim
manages a stateful simulation similar to the MujocoEnv class found in Gym
182 |
183 |
.
184 |
185 |
186 |
187 |
188 |
189 |
190 |
191 |
192 |
213 |
214 |
215 |
216 |
217 |
218 |
219 |
220 |
221 |
222 |
223 |
224 |
225 |
235 |
236 |
237 |
238 |
239 |
240 |
241 |
242 |
243 |
244 |
245 |
246 |
247 |
248 |
253 |
254 |
255 |
256 |
--------------------------------------------------------------------------------
/docs/build/html/objects.inv:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/openai/mujoco-py/a13903b82f1ab316815e63b3575526005b3b2ae1/docs/build/html/objects.inv
--------------------------------------------------------------------------------
/docs/build/html/search.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 | Search — mujoco-py 1.50.1.0 documentation
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 | mujoco-py
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 | Docs »
137 |
138 | Search
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 | Please activate JavaScript to enable the search
157 | functionality.
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
186 |
187 |
188 |
189 |
190 |
191 |
192 |
193 |
194 |
195 |
196 |
197 |
198 |
208 |
209 |
210 |
211 |
212 |
213 |
214 |
215 |
216 |
217 |
218 |
219 |
220 |
221 |
222 |
227 |
228 |
231 |
232 |
233 |
234 |
235 |
236 |
237 |
--------------------------------------------------------------------------------
/docs/conf.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 | # -*- coding: utf-8 -*-
3 | #
4 | # mujoco-py documentation build configuration file, created by
5 | # sphinx-quickstart on Tue Jun 27 15:21:11 2017.
6 | #
7 | # This file is execfile()d with the current directory set to its
8 | # containing dir.
9 | #
10 | # Note that not all possible configuration values are present in this
11 | # autogenerated file.
12 | #
13 | # All configuration values have a default; values that are commented out
14 | # serve to show the default.
15 |
16 | # If extensions (or modules to document with autodoc) are in another directory,
17 | # add these directories to sys.path here. If the directory is relative to the
18 | # documentation root, use os.path.abspath to make it absolute, like shown here.
19 | #
20 | # import os
21 | # import sys
22 | # sys.path.insert(0, os.path.abspath('.'))
23 |
24 |
25 | # -- General configuration ------------------------------------------------
26 |
27 | # If your documentation needs a minimal Sphinx version, state it here.
28 | #
29 | # needs_sphinx = '1.0'
30 |
31 | # Add any Sphinx extension module names here, as strings. They can be
32 | # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
33 | # ones.
34 | extensions = ['sphinx.ext.autodoc',
35 | 'sphinx.ext.viewcode',
36 | 'numpydoc']
37 |
38 | # Add any paths that contain templates here, relative to this directory.
39 | templates_path = ['_templates']
40 |
41 | # The suffix(es) of source filenames.
42 | # You can specify multiple suffix as a list of string:
43 | #
44 | # source_suffix = ['.rst', '.md']
45 | source_suffix = '.rst'
46 |
47 | # The master toctree document.
48 | master_doc = 'index'
49 |
50 | # General information about the project.
51 | project = 'mujoco-py'
52 | copyright = '2017, OpenAI'
53 | author = 'OpenAI'
54 |
55 | # The version info for the project you're documenting, acts as replacement for
56 | # |version| and |release|, also used in various other places throughout the
57 | # built documents.
58 | #
59 | # The short X.Y version.
60 | import mujoco_py
61 | version = mujoco_py.__version__
62 | # The full version, including alpha/beta/rc tags.
63 | release = mujoco_py.__version__
64 |
65 | # The language for content autogenerated by Sphinx. Refer to documentation
66 | # for a list of supported languages.
67 | #
68 | # This is also used if you do content translation via gettext catalogs.
69 | # Usually you set "language" from the command line for these cases.
70 | language = None
71 |
72 | # List of patterns, relative to source directory, that match files and
73 | # directories to ignore when looking for source files.
74 | # This patterns also effect to html_static_path and html_extra_path
75 | exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']
76 |
77 | # The name of the Pygments (syntax highlighting) style to use.
78 | pygments_style = 'sphinx'
79 |
80 | # If true, `todo` and `todoList` produce output, else they produce nothing.
81 | todo_include_todos = False
82 |
83 |
84 | # -- Options for HTML output ----------------------------------------------
85 |
86 | # The theme to use for HTML and HTML Help pages. See the documentation for
87 | # a list of builtin themes.
88 | #
89 | html_theme = "sphinx_rtd_theme"
90 |
91 | # Theme options are theme-specific and customize the look and feel of a theme
92 | # further. For a list of options available for each theme, see the
93 | # documentation.
94 | #
95 | # html_theme_options = {}
96 |
97 | # Add any paths that contain custom static files (such as style sheets) here,
98 | # relative to this directory. They are copied after the builtin static files,
99 | # so a file named "default.css" will overwrite the builtin "default.css".
100 | html_static_path = ['_static']
101 |
102 |
103 | # -- Options for HTMLHelp output ------------------------------------------
104 |
105 | # Output file base name for HTML help builder.
106 | htmlhelp_basename = 'mujoco-pydoc'
107 |
108 |
109 | # -- Options for LaTeX output ---------------------------------------------
110 |
111 | latex_elements = {
112 | # The paper size ('letterpaper' or 'a4paper').
113 | #
114 | # 'papersize': 'letterpaper',
115 |
116 | # The font size ('10pt', '11pt' or '12pt').
117 | #
118 | # 'pointsize': '10pt',
119 |
120 | # Additional stuff for the LaTeX preamble.
121 | #
122 | # 'preamble': '',
123 |
124 | # Latex figure (float) alignment
125 | #
126 | # 'figure_align': 'htbp',
127 | }
128 |
129 | # Grouping the document tree into LaTeX files. List of tuples
130 | # (source start file, target name, title,
131 | # author, documentclass [howto, manual, or own class]).
132 | latex_documents = [
133 | (master_doc, 'mujoco-py.tex', 'mujoco-py Documentation',
134 | 'OpenAI', 'manual'),
135 | ]
136 |
137 |
138 | # -- Options for manual page output ---------------------------------------
139 |
140 | # One entry per manual page. List of tuples
141 | # (source start file, name, description, authors, manual section).
142 | man_pages = [
143 | (master_doc, 'mujoco-py', 'mujoco-py Documentation',
144 | [author], 1)
145 | ]
146 |
147 |
148 | # -- Options for Texinfo output -------------------------------------------
149 |
150 | # Grouping the document tree into Texinfo files. List of tuples
151 | # (source start file, target name, title, author,
152 | # dir menu entry, description, category)
153 | texinfo_documents = [
154 | (master_doc, 'mujoco-py', 'mujoco-py Documentation',
155 | author, 'mujoco-py', 'One line description of project.',
156 | 'Miscellaneous'),
157 | ]
158 |
--------------------------------------------------------------------------------
/docs/index.html:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/docs/index.rst:
--------------------------------------------------------------------------------
1 | =======================
2 | mujoco-py Documentation
3 | =======================
4 |
5 | .. toctree::
6 | reference
7 | internals
8 |
9 | `MuJoCo `_ is a physics engine for detailed, efficient rigid body simulations with contacts. ``mujoco-py`` allows using MuJoCo from Python 3.
10 |
11 | See the `README `_ for installation instructions and example usage.
12 |
13 | ``mujoco-py`` allows access to MuJoCo on a number of different levels of abstraction:
14 |
15 | - Directly from Cython (low-level): `Raw Cython declarations `_ are provided for using the MuJoCo C structs and functions directly in your own Cython code.
16 |
17 | - Using :ref:`pymjdata` (medium-level): These wrappers are lightweight Cython ``cdef`` classes that expose MuJuCo data to Python space. The data in the MuJoCo structs is exposed as NumPy arrays bound to Mujoco-allocated memory, so there is no copying overhead when accessing or modifying MuJoCo state from Python. For more information on how this works internally, see [this document](./doc/cython_wrappers.md).
18 |
19 | - Using :class:`mujoco_py.MjSim` (high-level): :class:`mujoco_py.MjSim` manages a stateful simulation similar to the `MujocoEnv `_ class found in `Gym `_
20 | .
21 |
--------------------------------------------------------------------------------
/docs/internals.rst:
--------------------------------------------------------------------------------
1 | Internals
2 | =========
3 |
4 | .. _genwrapper:
5 |
6 | Autogenerated wrappers
7 | ----------------------
8 |
9 | The Cython struct wrappers are generated by ``scripts/gen_wrappers.py``. To illustrate how the wrappers work, let's consider a toy C structure and the corresponding generated Cython cdef class. Here's a stripped down version of ``mjData`` with a scalar member and a pointer (array) member::
10 |
11 | typedef struct _mjData {
12 | int ne;
13 | mjtNum* qpos; // (nq x 1)
14 | } mjData;
15 |
16 | Here's the corresponding generated Cython wrapper code::
17 |
18 | cdef class PyMjData(object):
19 | cdef mjData* ptr
20 | cdef mjModel* _model
21 | cdef np.ndarray _qpos
22 |
23 | cdef void _set(self, mjData* p, mjModel* model):
24 | self.ptr = p
25 | self._model = model
26 | self._qpos = _wrap_mjtNum_1d(p.qpos, model.nq)
27 |
28 | @property
29 | def ne(self): return self.ptr.ne
30 |
31 | @ne.setter
32 | def ne(self, int x): self.ptr.ne = x
33 |
34 | @property
35 | def qpos(self): return self._qpos
36 |
37 | cdef PyMjData WrapMjData(mjData* p, mjModel* model):
38 | cdef PyMjData o = PyMjData()
39 | o._set(p, model)
40 | return o
41 |
42 | ``PyMjData`` is the wrapper class for exposing the underlying Mujoco structure to Python; it doesn't perform any memory mangement. A user writing Cython code can create this wrapper using ``WrapMjData``. A ``mjModel`` pointer must be passed because the shape of a ``mjData`` member, namely ``qpos``, depends on ``model->nq``.
43 |
44 | Each field of ``mjData`` corresponds to some generated piece of code in ``PyMjData`` that depends on the type of that field. For example, ``ne`` is a scalar integer, so it gets exposed as a pair of getter and setter methods in ``PyMjData``. ``qpos`` is an array represented as a pointer to its first element, so it's wrapped with a NumPy array by ``_wrap_mjtNum_1d`` and is exposed with a getter for that NumPy array.
45 |
46 | The function ``_wrap_mjtNum_1d`` creates a Cython memoryview from the data pointer and converts it to a NumPy array pointing to the same memory::
47 |
48 | cdef inline np.ndarray _wrap_mjtNum_1d(mjtNum* a, int shape0):
49 | if shape0 == 0: return None
50 | cdef mjtNum[:] b = a
51 | return np.asarray(b)
52 |
53 | Similar functions for other types are also generated as required.
54 |
55 | Keep in mind that the only reason to use these autogenerated wrappers is to allow Python users of the Cython code to easily access Mujoco data (for instance the ``MjSim`` Cython class, found in ``cymj/cymj.pyx`). If you're writing Cython code and you don't need the user to access Mujoco data from Python, then there is no reason to use these wrappers.
56 |
--------------------------------------------------------------------------------
/examples/body_interaction.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 | """
3 | Example of how bodies interact with each other. For a body to be able to
4 | move it needs to have joints. In this example, the "robot" is a red ball
5 | with X and Y slide joints (and a Z slide joint that isn't controlled).
6 | On the floor, there's a cylinder with X and Y slide joints, so it can
7 | be pushed around with the robot. There's also a box without joints. Since
8 | the box doesn't have joints, it's fixed and can't be pushed around.
9 | """
10 | from mujoco_py import load_model_from_xml, MjSim, MjViewer
11 | import math
12 | import os
13 |
14 | MODEL_XML = """
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 | """
48 |
49 | model = load_model_from_xml(MODEL_XML)
50 | sim = MjSim(model)
51 | viewer = MjViewer(sim)
52 | t = 0
53 | while True:
54 | sim.data.ctrl[0] = math.cos(t / 10.) * 0.01
55 | sim.data.ctrl[1] = math.sin(t / 10.) * 0.01
56 | t += 1
57 | sim.step()
58 | viewer.render()
59 | if t > 100 and os.getenv('TESTING') is not None:
60 | break
61 |
--------------------------------------------------------------------------------
/examples/disco_fetch.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 | """
3 | Displays robot fetch at a disco party.
4 | """
5 | from mujoco_py import load_model_from_path, MjSim, MjViewer
6 | from mujoco_py.modder import TextureModder
7 | import os
8 |
9 | model = load_model_from_path("xmls/fetch/main.xml")
10 | sim = MjSim(model)
11 |
12 | viewer = MjViewer(sim)
13 | modder = TextureModder(sim)
14 |
15 | t = 0
16 |
17 | while True:
18 | for name in sim.model.geom_names:
19 | modder.rand_all(name)
20 |
21 | viewer.render()
22 | t += 1
23 | if t > 100 and os.getenv('TESTING') is not None:
24 | break
25 |
--------------------------------------------------------------------------------
/examples/internal_functions.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 | """
3 | Shows how to access internal functions from MuJoCo.
4 | """
5 | from mujoco_py import load_model_from_xml, MjSim, functions
6 | import numpy as np
7 |
8 | MODEL_XML = """
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 | """
20 |
21 | model = load_model_from_xml(MODEL_XML)
22 | sim = MjSim(model)
23 |
24 | print("Nicely exposed function:\n")
25 | print(sim.model.get_xml())
26 |
27 | print("\nversus MuJoCo internals:\n\n")
28 |
29 | functions.mj_saveLastXML("/tmp/saved.xml", model, "", 0)
30 | with open("/tmp/saved.xml", "r") as f:
31 | print(f.read())
32 |
33 | sim.render(100, 100)
34 |
35 | modelpos = np.zeros(3)
36 | modelquat = np.zeros(4)
37 | roompos = np.ones(3)
38 | roomquat = np.array([1., 0., 1., 0.])
39 |
40 | functions.mjv_room2model(modelpos, modelquat, roompos,
41 | roomquat, sim.render_contexts[0].scn)
42 |
43 | print("\n\nAnother internal function, mjv_room2model:")
44 | print("modelpos = %s, modelquat = %s" % (str(modelpos), str(modelquat)))
45 |
46 |
47 | res = np.zeros(9)
48 | functions.mju_quat2Mat(res, roomquat)
49 | print("\n\nAnother internal function, mju_quat2Mat:\n%s" % res)
50 |
--------------------------------------------------------------------------------
/examples/markers_demo.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # demonstration of markers (visual-only geoms)
3 |
4 | import math
5 | import time
6 | import os
7 | import numpy as np
8 | from mujoco_py import load_model_from_xml, MjSim, MjViewer
9 |
10 | MODEL_XML = """
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 | """
25 |
26 | model = load_model_from_xml(MODEL_XML)
27 | sim = MjSim(model)
28 | viewer = MjViewer(sim)
29 | step = 0
30 | while True:
31 | t = time.time()
32 | x, y = math.cos(t), math.sin(t)
33 | viewer.add_marker(pos=np.array([x, y, 1]),
34 | label=str(t))
35 | viewer.render()
36 |
37 | step += 1
38 | if step > 100 and os.getenv('TESTING') is not None:
39 | break
40 |
--------------------------------------------------------------------------------
/examples/mjvive.py:
--------------------------------------------------------------------------------
1 | '''
2 | EXPERIMENTAL: Displays MuJoCo model in VR.
3 |
4 | Based on http://www.mujoco.org/book/source/mjvive.cpp
5 | No controller integration currently
6 |
7 | This example is a demonstration of a near-direct translation of an existing
8 | MuJoCo example (mjvive.cpp), showing how to use lower-level functionality
9 | in conjunction with Python.
10 |
11 | Known occasional issues with SteamVR (all-black textures seen),
12 | fixed by closing and re-opening.
13 |
14 | Requires HTC Vive, Windows, and OpenVR.
15 |
16 | Install openvr python module with:
17 | pip install openvr
18 | '''
19 |
20 |
21 | import math
22 | import os
23 | import glfw
24 | import openvr
25 | import numpy as np
26 | import OpenGL.GL as gl
27 | from mujoco_py import functions
28 | from mujoco_py.builder import mujoco_path
29 | from mujoco_py.cymj import (MjRenderContext, MjSim, load_model_from_xml,
30 | PyMjrRect, PyMjvCamera)
31 | from mujoco_py.generated.const import (CAT_ALL, FB_OFFSCREEN, FONT_BIG,
32 | GRID_BOTTOMLEFT, STEREO_SIDEBYSIDE)
33 |
34 |
35 | # Normally global variables aren't used like this in python,
36 | # but we want to be as close as possible to the original file.
37 | class HMD(): # anonymous object we can set fields on
38 | pass
39 |
40 |
41 | window = None
42 | sim = None
43 | ctx = None
44 | hmd = HMD()
45 |
46 |
47 | def initMuJoCo(filename, width2, height):
48 | ''' load model, init simulation and rendering '''
49 | global window, sim, ctx
50 | assert glfw.init(), 'Could not initialize GLFW'
51 | glfw.window_hint(glfw.SAMPLES, 0)
52 | glfw.window_hint(glfw.DOUBLEBUFFER, True)
53 | glfw.window_hint(glfw.RESIZABLE, 0)
54 | window = glfw.create_window(width2 // 4, height // 2, "mjvive.py", None, None)
55 | assert window, "Could not create GLFW window"
56 | glfw.make_context_current(window)
57 | glfw.swap_interval(0)
58 | # GLEW init required in C++, not in Python
59 | sim = MjSim(load_model_from_xml(open(filename).read()))
60 | sim.forward()
61 | sim.model.vis.global_.offwidth = width2
62 | sim.model.vis.global_.offheight = height
63 | sim.model.vis.quality.offsamples = 8
64 | ctx = MjRenderContext(sim)
65 | ctx.scn.enabletransform = 1
66 | ctx.scn.translate[1:3] = -0.5
67 | ctx.scn.rotate[0:2] = math.cos(-0.25 * math.pi), math.sin(-0.25 * math.pi)
68 | ctx.scn.scale = 1
69 | ctx.scn.stereo = STEREO_SIDEBYSIDE
70 |
71 |
72 | def v_initPre():
73 | ''' init vr before MuJoCo init '''
74 | global hmd
75 | hmd.system = openvr.init(openvr.VRApplication_Scene)
76 | hmd.roompos = np.zeros(3)
77 | hmd.roommat = np.eye(3)
78 | hmd.eyeoffset = np.zeros((2, 3))
79 | openvr.VRCompositor().setTrackingSpace(openvr.TrackingUniverseStanding)
80 | hmd.width, hmd.height = hmd.system.getRecommendedRenderTargetSize()
81 | for n in range(2):
82 | hmd.eyeoffset[n] = np.array(hmd.system.getEyeToHeadTransform(n).m)[0:3, 3]
83 |
84 |
85 | def v_initPost():
86 | ''' init vr after MuJoCo init '''
87 | global hmd
88 | for n in range(2):
89 | znear, zfar = 0.05, 50.0
90 | left, right, top, bottom = hmd.system.getProjectionRaw(n)
91 | ctx.scn.camera[n].frustum_bottom = -bottom * znear
92 | ctx.scn.camera[n].frustum_top = -top * znear
93 | ctx.scn.camera[n].frustum_center = 0.5 * (left + right) * znear
94 | ctx.scn.camera[n].frustum_near = znear
95 | ctx.scn.camera[n].frustum_far = zfar
96 | gl.glActiveTexture(gl.GL_TEXTURE2)
97 | hmd.idtex = gl.glGenTextures(1)
98 | gl.glBindTexture(gl.GL_TEXTURE_2D, hmd.idtex)
99 | gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MAG_FILTER, gl.GL_NEAREST)
100 | gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MIN_FILTER, gl.GL_NEAREST)
101 | gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_WRAP_S, gl.GL_CLAMP_TO_EDGE)
102 | gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_WRAP_T, gl.GL_CLAMP_TO_EDGE)
103 | gl.glTexImage2D(gl.GL_TEXTURE_2D, 0, gl.GL_RGBA8, 2 * hmd.width, hmd.height, 0, gl.GL_RGBA, gl.GL_UNSIGNED_BYTE, None)
104 | hmd.poses = (openvr.TrackedDevicePose_t * openvr.k_unMaxTrackedDeviceCount)()
105 | hmd.boundLeft = openvr.VRTextureBounds_t(0., 0., 0.5, 1.)
106 | hmd.boundRight = openvr.VRTextureBounds_t(0.5, 0., 1., 1.)
107 | hmd.vTex = openvr.Texture_t(hmd.idtex, openvr.TextureType_OpenGL, openvr.ColorSpace_Gamma)
108 |
109 |
110 | def v_update():
111 | ''' update vr poses and controller states '''
112 | global ctx, hmd
113 | openvr.VRCompositor().waitGetPoses(hmd.poses, openvr.k_unMaxTrackedDeviceCount, None, 0)
114 | m = np.array(hmd.poses[openvr.k_unTrackedDeviceIndex_Hmd].mDeviceToAbsoluteTracking.m)
115 | hmd.roompos, hmd.roommat = m[0:3, 3], m[0:3, 0:3]
116 | for n in range(2):
117 | ctx.scn.camera[n].pos[:] = hmd.roompos + np.matmul(hmd.roommat, hmd.eyeoffset[n])
118 | ctx.scn.camera[n].forward[0:3] = -hmd.roommat[:, 2]
119 | ctx.scn.camera[n].up[0:3] = hmd.roommat[:, 1]
120 |
121 |
122 | def v_render():
123 | ''' render to vr and window '''
124 | global hmd, ctx, window
125 | # resolve multi-sample offscreen buffer
126 | gl.glBindFramebuffer(gl.GL_READ_FRAMEBUFFER, ctx.con.offFBO)
127 | gl.glReadBuffer(gl.GL_COLOR_ATTACHMENT0)
128 | gl.glBindFramebuffer(gl.GL_DRAW_FRAMEBUFFER, ctx.con.offFBO_r)
129 | gl.glDrawBuffer(gl.GL_COLOR_ATTACHMENT0)
130 | gl.glBlitFramebuffer(0, 0, 2 * hmd.width, hmd.height,
131 | 0, 0, 2 * hmd.width, hmd.height,
132 | gl.GL_COLOR_BUFFER_BIT, gl.GL_NEAREST)
133 | # blit to window, left only, window is half-size
134 | gl.glBindFramebuffer(gl.GL_READ_FRAMEBUFFER, ctx.con.offFBO_r)
135 | gl.glReadBuffer(gl.GL_COLOR_ATTACHMENT0)
136 | gl.glBindFramebuffer(gl.GL_DRAW_FRAMEBUFFER, 0)
137 | gl.glDrawBuffer(gl.GL_BACK if ctx.con.windowDoublebuffer else gl.GL_FRONT)
138 | gl.glBlitFramebuffer(0, 0, hmd.width, hmd.height,
139 | 0, 0, hmd.width // 2, hmd.height // 2,
140 | gl.GL_COLOR_BUFFER_BIT, gl.GL_NEAREST)
141 | # blit to vr texture
142 | gl.glActiveTexture(gl.GL_TEXTURE2)
143 | gl.glBindFramebuffer(gl.GL_DRAW_FRAMEBUFFER, ctx.con.offFBO_r)
144 | gl.glFramebufferTexture2D(gl.GL_FRAMEBUFFER, gl.GL_COLOR_ATTACHMENT1, gl.GL_TEXTURE_2D, hmd.idtex, 0)
145 | gl.glDrawBuffer(gl.GL_COLOR_ATTACHMENT1)
146 | gl.glBlitFramebuffer(0, 0, 2 * hmd.width, hmd.height,
147 | 0, 0, 2 * hmd.width, hmd.height,
148 | gl.GL_COLOR_BUFFER_BIT, gl.GL_NEAREST)
149 | gl.glFramebufferTexture2D(gl.GL_FRAMEBUFFER, gl.GL_COLOR_ATTACHMENT1, gl.GL_TEXTURE_2D, 0, 0)
150 | gl.glDrawBuffer(gl.GL_COLOR_ATTACHMENT0)
151 | openvr.VRCompositor().submit(openvr.Eye_Left, hmd.vTex, hmd.boundLeft)
152 | openvr.VRCompositor().submit(openvr.Eye_Right, hmd.vTex, hmd.boundRight)
153 | # swap if window is double-buffered, flush just in case
154 | if ctx.con.windowDoublebuffer:
155 | glfw.swap_buffers(window)
156 | gl.glFlush()
157 |
158 |
159 | if __name__ == '__main__':
160 | filename = os.path.join(mujoco_path, 'model', 'humanoid.xml')
161 | v_initPre()
162 | initMuJoCo(filename, hmd.width * 2, hmd.height)
163 | v_initPost()
164 |
165 | FPS = 90.0
166 | lasttm = glfw.get_time()
167 | frametime = sim.data.time
168 | viewFull = PyMjrRect()
169 | viewFull.width, viewFull.height = 2 * hmd.width, hmd.height
170 | nullCam = PyMjvCamera()
171 |
172 | while not glfw.window_should_close(window):
173 | if sim.data.time - frametime > 1 / FPS or sim.data.time < frametime:
174 | functions.mjv_updateScene(sim.model, sim.data, ctx.vopt, ctx.pert, nullCam, CAT_ALL, ctx.scn)
175 | v_update()
176 | functions.mjr_setBuffer(FB_OFFSCREEN, ctx.con)
177 | functions.mjr_render(viewFull, ctx.scn, ctx.con)
178 | FPS = .9 * FPS + .1 / (glfw.get_time() - lasttm)
179 | lasttm = glfw.get_time()
180 | functions.mjr_overlay(FONT_BIG, GRID_BOTTOMLEFT, viewFull, 'FPS %.1f' % FPS, '', ctx.con)
181 | v_render()
182 | frametime = sim.data.time
183 | sim.step()
184 | glfw.poll_events()
185 | # close
186 | openvr.shutdown()
187 | gl.glDeleteTextures(1, hmd.idtex)
188 | del sim
189 | del ctx
190 | glfw.terminate()
191 |
--------------------------------------------------------------------------------
/examples/multigpu_rendering.py:
--------------------------------------------------------------------------------
1 | """
2 | This is an example for rendering on multiple GPUs in parallel,
3 | using the multiprocessing module.
4 | """
5 | from multiprocessing import set_start_method
6 | from time import perf_counter
7 |
8 | from mujoco_py import load_model_from_path, MjRenderPool
9 |
10 |
11 | def main():
12 | # Image size for rendering
13 | IMAGE_WIDTH = 255
14 | IMAGE_HEIGHT = 255
15 | # Number of frames to render per sim
16 | N_FRAMES = 100
17 | # Number of sims to run in parallel (assumes one per GPU),
18 | # so N_SIMS=2 assumes there are 2 GPUs available.
19 | N_SIMS = 2
20 |
21 | pool = MjRenderPool(load_model_from_path("xmls/tosser.xml"), device_ids=N_SIMS)
22 |
23 | print("main(): start benchmarking", flush=True)
24 | start_t = perf_counter()
25 |
26 | for _ in range(N_FRAMES):
27 | pool.render(IMAGE_WIDTH, IMAGE_HEIGHT)
28 |
29 | t = perf_counter() - start_t
30 | print("Completed in %.1fs: %.3fms, %.1f FPS" % (
31 | t, t / (N_FRAMES * N_SIMS) * 1000, (N_FRAMES * N_SIMS) / t),
32 | flush=True)
33 |
34 | print("main(): finished", flush=True)
35 |
36 |
37 | if __name__ == "__main__":
38 | set_start_method('spawn')
39 | main()
40 |
--------------------------------------------------------------------------------
/examples/render_callback.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 | """
3 | Shows how to use render callback.
4 | """
5 | from mujoco_py import load_model_from_path, MjSim, MjViewer
6 | from mujoco_py.modder import TextureModder
7 | import os
8 |
9 | modder = None
10 | def render_callback(sim, viewer):
11 | global modder
12 | if modder is None:
13 | modder = TextureModder(sim)
14 | for name in sim.model.geom_names:
15 | modder.rand_all(name)
16 |
17 | model = load_model_from_path("xmls/fetch/main.xml")
18 | sim = MjSim(model, render_callback=render_callback)
19 |
20 | viewer = MjViewer(sim)
21 |
22 | t = 0
23 |
24 | while True:
25 | viewer.render()
26 | t += 1
27 | if t > 100 and os.getenv('TESTING') is not None:
28 | break
--------------------------------------------------------------------------------
/examples/serialize_model.py:
--------------------------------------------------------------------------------
1 | """
2 | # Serialization/Deserialization of Models
3 |
4 | Sometimes its useful to send a mujoco model over the network, or save it
5 | to a file with all assets embedded.
6 | """
7 | import mujoco_py
8 |
9 | # The binary MJB format is preferable, since it includes assets like
10 | # textures and meshes.
11 | model = mujoco_py.load_model_from_path("xmls/claw.xml")
12 | mjb_bytestring = model.get_mjb()
13 | model_from_binary = mujoco_py.load_model_from_mjb(mjb_bytestring)
14 | assert model.nbody == model_from_binary.nbody
15 |
16 | # XML is preferable to MJB when readability and backward compatibility are
17 | # important.
18 | xml_string = model.get_xml()
19 | model_from_xml = mujoco_py.load_model_from_xml(xml_string)
20 | assert model.nbody == model_from_xml.nbody
21 |
--------------------------------------------------------------------------------
/examples/setting_state.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 | """
3 | Example for how to modifying the MuJoCo qpos during execution.
4 | """
5 |
6 | import os
7 | from mujoco_py import load_model_from_xml, MjSim, MjViewer
8 |
9 | MODEL_XML = """
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 | """
24 |
25 |
26 | def print_box_xpos(sim):
27 | print("box xpos:", sim.data.get_body_xpos("box"))
28 |
29 |
30 | model = load_model_from_xml(MODEL_XML)
31 | sim = MjSim(model)
32 | viewer = MjViewer(sim)
33 |
34 | states = [{'box:x': +0.8, 'box:y': +0.8},
35 | {'box:x': -0.8, 'box:y': +0.8},
36 | {'box:x': -0.8, 'box:y': -0.8},
37 | {'box:x': +0.8, 'box:y': -0.8},
38 | {'box:x': +0.0, 'box:y': +0.0}]
39 |
40 | # MjModel.joint_name2id returns the index of a joint in
41 | # MjData.qpos.
42 | x_joint_i = sim.model.get_joint_qpos_addr("box:x")
43 | y_joint_i = sim.model.get_joint_qpos_addr("box:y")
44 |
45 | print_box_xpos(sim)
46 |
47 | while True:
48 | for state in states:
49 | sim_state = sim.get_state()
50 | sim_state.qpos[x_joint_i] = state["box:x"]
51 | sim_state.qpos[y_joint_i] = state["box:y"]
52 | sim.set_state(sim_state)
53 | sim.forward()
54 | print("updated state to", state)
55 | print_box_xpos(sim)
56 | viewer.render()
57 |
58 | if os.getenv('TESTING') is not None:
59 | break
60 |
--------------------------------------------------------------------------------
/examples/substep_callback.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 | """
3 | Example how substep_callback can be used to detect contacts/penetrations that
4 | are not visible in between steps.
5 |
6 | In this example a sphere pushes a cylinder, which then slides away.
7 | The entirety of the contact and separation happens in substeps.
8 |
9 | In between steps there is always zero contacts, so the push is not observed.
10 |
11 | We use a substep_callback to get a sum of the external forces on the cylinder.
12 | """
13 | from mujoco_py import load_model_from_xml, MjSim
14 |
15 | MODEL_XML = """
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 | """
33 |
34 | fn = '''
35 | #define SQUARE(a) (a * a)
36 | void fun(const mjModel* m, mjData* d) {
37 | for (int i = d->ne; i < d->nefc; i++) {
38 | pos_sum += SQUARE(d->efc_pos[i]);
39 | }
40 | }
41 | '''
42 |
43 | sim = MjSim(load_model_from_xml(MODEL_XML), nsubsteps=50,
44 | substep_callback=fn, userdata_names=['pos_sum'])
45 | t = 0
46 | while t < 10:
47 | t += 1
48 | sim.data.ctrl[0] = .2
49 | print('t', t)
50 | sim.step()
51 | # verify that there are no contacts visible between steps
52 | assert sim.data.ncon == 0, 'No contacts should be detected here'
53 | # verify that contacts (and penetrations) are visible to substep_callback
54 | if t > 1:
55 | assert sim.data.get_userdata('pos_sum') > 0 # detected collision
56 |
--------------------------------------------------------------------------------
/examples/tosser.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 | """
3 | Shows how to toss a capsule to a container.
4 | """
5 | from mujoco_py import load_model_from_path, MjSim, MjViewer
6 | import os
7 |
8 | model = load_model_from_path("xmls/tosser.xml")
9 | sim = MjSim(model)
10 |
11 | viewer = MjViewer(sim)
12 |
13 |
14 | sim_state = sim.get_state()
15 |
16 | while True:
17 | sim.set_state(sim_state)
18 |
19 | for i in range(1000):
20 | if i < 150:
21 | sim.data.ctrl[:] = 0.0
22 | else:
23 | sim.data.ctrl[:] = -1.0
24 | sim.step()
25 | viewer.render()
26 |
27 | if os.getenv('TESTING') is not None:
28 | break
29 |
--------------------------------------------------------------------------------
/mujoco_py/__init__.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | from mujoco_py.builder import cymj, ignore_mujoco_warnings, functions, MujocoException
3 | from mujoco_py.generated import const
4 | from mujoco_py.mjrenderpool import MjRenderPool
5 | from mujoco_py.mjviewer import MjViewer, MjViewerBasic
6 | from mujoco_py.version import __version__, get_version
7 |
8 | load_model_from_path = cymj.load_model_from_path
9 | load_model_from_xml = cymj.load_model_from_xml
10 | load_model_from_mjb = cymj.load_model_from_mjb
11 | MjSim = cymj.MjSim
12 | MjSimState = cymj.MjSimState
13 | MjRenderContext = cymj.MjRenderContext
14 | MjRenderContextOffscreen = cymj.MjRenderContextOffscreen
15 | MjRenderContextWindow = cymj.MjRenderContextWindow
16 | MjBatchRenderer = cymj.MjBatchRenderer
17 | GlfwContext = cymj.GlfwContext
18 |
19 |
20 | # Public API:
21 | __all__ = ['MjSim', 'MjSimState',
22 | 'MjRenderContextOffscreen', 'MjRenderContextWindow',
23 | 'MjRenderContext', 'MjViewer', 'MjViewerBasic',
24 | 'MujocoException', 'MjRenderPool', 'MjBatchRenderer', 'GlfwContext',
25 | 'load_model_from_path', 'load_model_from_xml',
26 | 'load_model_from_mjb',
27 | 'ignore_mujoco_warnings', 'const', "functions",
28 | "__version__", "get_version"]
29 |
30 |
--------------------------------------------------------------------------------
/mujoco_py/cymj.pyx:
--------------------------------------------------------------------------------
1 | # cython: language_level=3
2 | import copy
3 | import logging
4 | import os
5 | import platform
6 | import tempfile
7 | import sys
8 | from collections import namedtuple
9 | from libc.stdlib cimport malloc, free
10 | from libc.string cimport strncpy
11 | from numbers import Number
12 | from tempfile import TemporaryDirectory
13 |
14 | import numpy as np
15 | from cython cimport view
16 | from cython.parallel import parallel, prange
17 | from mujoco_py.generated import const
18 |
19 | include "generated/wrappers.pxi"
20 | include "opengl_context.pyx"
21 | include "mjsim.pyx"
22 | include "mjsimstate.pyx"
23 | include "mjrendercontext.pyx"
24 | include "mjbatchrenderer.pyx"
25 | include "mjpid.pyx"
26 |
27 | cdef extern from "gl/glshim.h":
28 |
29 | cdef int usingEGL()
30 | cdef int initOpenGL(int device_id)
31 | cdef void closeOpenGL()
32 | cdef int makeOpenGLContextCurrent(int device_id)
33 | cdef int setOpenGLBufferSize(int device_id, int width, int height)
34 |
35 | cdef unsigned int createPBO(int width, int height, int batchSize, int use_short)
36 | cdef void freePBO(unsigned int pixelBuffer)
37 | cdef void copyFBOToPBO(mjrContext* con,
38 | unsigned int pbo_rgb, unsigned int pbo_depth,
39 | mjrRect viewport, int bufferOffset)
40 | cdef void readPBO(unsigned char *buffer_rgb, unsigned short *buffer_depth,
41 | unsigned int pbo_rgb, unsigned int pbo_depth,
42 | int width, int height, int batchSize)
43 |
44 |
45 |
46 | # TODO: make this function or class so these comments turn into doc strings:
47 |
48 | # Python warning callback function, which is set
49 | # MuJoCo has a user-settable callback function for warnings: mju_user_warning()
50 | # We want to supply a python function, and be able to raise exceptions.
51 | # To do this we have to wrap two things:
52 |
53 | # This is the python callback function. We save it in the global() context
54 | # so we can access it from a C wrapper function (c_warning_callback)
55 | cdef object py_warning_callback
56 | cdef object py_error_callback
57 | # This is the saved exception. Because the C callback can not propagate
58 | # exceptions, this must be set to None before calling into MuJoCo, and then
59 | # inspected afterwards.
60 | # These are combined in a simple class which handles both:
61 | # with wrap_mujoco_warning():
62 | # mj_somefunc()
63 | cdef object py_warning_exception = None
64 | cdef object py_error_exception = None
65 |
66 |
67 | cdef void c_warning_callback(const char *msg) with gil:
68 | '''
69 | Wraps the warning callback so we can raise exceptions.
70 | Because callbacks can't propagate exceptions, we set a global that has
71 | to be inspected later.
72 | Use wrap_mujoco_warning() to check for that saved exception and
73 | re-raise it back to the caller.
74 | '''
75 | global py_warning_callback
76 | try:
77 | ( py_warning_callback)(msg)
78 | except Exception as e:
79 | global py_warning_exception
80 | py_warning_exception = e
81 |
82 |
83 | def set_warning_callback(warn):
84 | '''
85 | Set a user-defined warning callback. It should take in a string message
86 | (the warning string) and raise an Exception.
87 | See c_warning_callback, which is the C wrapper to the user defined function
88 | '''
89 | global py_warning_callback
90 | global mju_user_warning
91 | py_warning_callback = warn
92 | mju_user_warning = c_warning_callback
93 |
94 |
95 | def get_warning_callback():
96 | '''
97 | Returns the user-defined warning callback, for use in e.g. a context
98 | manager.
99 | '''
100 | global py_warning_callback
101 | return py_warning_callback
102 |
103 |
104 | cdef void c_error_callback(const char *msg) with gil:
105 | '''
106 | Wraps the error callback so that we can pass a python function to the callback.
107 | MuJoCo error handlers are expected to terminate the program and never return.
108 | '''
109 | global py_error_callback
110 |
111 | try:
112 | ( py_error_callback)(msg)
113 | except Exception as e:
114 | global py_error_exception
115 | py_error_exception = e
116 |
117 |
118 | def set_error_callback(err_callback):
119 | '''
120 | Set a user-defined error callback. It should take in a string message
121 | (the warning string) and terminate the program.
122 | See c_warning_callback, which is the C wrapper to the user defined function
123 | '''
124 | global py_error_callback
125 | global mju_user_error
126 | py_error_callback = err_callback
127 | mju_user_error = c_error_callback
128 |
129 |
130 | def get_error_callback():
131 | '''
132 | Returns the user-defined warning callback, for use in e.g. a context
133 | manager.
134 | '''
135 | global py_error_callback
136 | return py_error_callback
137 |
138 |
139 | class wrap_mujoco_warning(object):
140 | '''
141 | Class to wrap capturing exceptions raised during warning callbacks.
142 | Use this to capture warnings in mujoco calls. Example:
143 | with wrap_mujoco_warning():
144 | mj_somefunc()
145 | '''
146 | def __enter__(self):
147 | global py_warning_exception
148 | py_warning_exception = None
149 | global py_error_exception
150 | py_error_exception = None
151 | def __exit__(self, type, value, traceback):
152 | global py_warning_exception
153 | global py_error_exception
154 |
155 | if py_warning_exception is not None:
156 | raise py_warning_exception
157 |
158 | if py_error_exception is not None:
159 | raise py_error_exception
160 |
161 |
162 | def load_model_from_path(str path):
163 | """Loads model from path."""
164 | cdef char errstr[300]
165 | cdef mjModel *model
166 | with wrap_mujoco_warning():
167 | if (path.endswith(".mjb")):
168 | model = mj_loadModel(path.encode(), NULL)
169 | elif (path.endswith(".xml")):
170 | model = mj_loadXML(path.encode(), NULL, errstr, 300)
171 | else:
172 | raise RuntimeError("Unrecognized extension for %s. Expected .xml or .mjb" % path)
173 |
174 | if model == NULL:
175 | raise Exception('Failed to load XML file: %s. mj_loadXML error: %s' % (path, errstr,))
176 | return WrapMjModel(model)
177 |
178 | def load_model_from_xml(str xml_str):
179 | """
180 | Loads and returns a PyMjModel model from a string containing XML markup.
181 | Saves the XML string used to create the returned model in `model.xml`.
182 | """
183 | cdef char errstr[300]
184 | cdef mjModel *model
185 | with wrap_mujoco_warning():
186 | with tempfile.NamedTemporaryFile(suffix=".xml", delete=True) as fp:
187 | fp.write(xml_str.encode())
188 | fp.flush()
189 | model = mj_loadXML(fp.name.encode(), NULL, errstr, 300)
190 | if model == NULL:
191 | raise Exception('%s\nFailed to load XML from string. mj_loadXML error: %s' % (xml_str, errstr,))
192 | return WrapMjModel(model)
193 |
194 |
195 | def load_model_from_mjb(bytes mjb_bytes):
196 | """
197 | Loads and returns a PyMjModel model from bytes encoded MJB.
198 | MJB is a MuJoCo-custom format that includes assets like meshes/textures.
199 | """
200 | cdef mjModel *model
201 | with wrap_mujoco_warning():
202 | with TemporaryDirectory() as td:
203 | filename = os.path.join(td, 'model.mjb')
204 | with open(filename, 'wb') as f:
205 | f.write(mjb_bytes)
206 | model = mj_loadModel(filename.encode(), NULL)
207 | if model == NULL:
208 | raise Exception('%s\nFailed to load MJB')
209 | return WrapMjModel(model)
210 |
--------------------------------------------------------------------------------
/mujoco_py/generated/README.md:
--------------------------------------------------------------------------------
1 | This directory contains files which are automatically generated.
2 | Don't modify them directly.
--------------------------------------------------------------------------------
/mujoco_py/generated/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/openai/mujoco-py/a13903b82f1ab316815e63b3575526005b3b2ae1/mujoco_py/generated/__init__.py
--------------------------------------------------------------------------------
/mujoco_py/gl/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/openai/mujoco-py/a13903b82f1ab316815e63b3575526005b3b2ae1/mujoco_py/gl/__init__.py
--------------------------------------------------------------------------------
/mujoco_py/gl/dummyshim.c:
--------------------------------------------------------------------------------
1 | #include "glshim.h"
2 |
3 | int usingEGL() {
4 | return 0;
5 | }
6 |
7 | int initOpenGL(int device_id) {
8 | return 1;
9 | }
10 |
11 | int setOpenGLBufferSize(int device_id, int width, int height) {
12 | return 1;
13 | }
14 |
15 | int makeOpenGLContextCurrent(int device_id) {
16 | return 1;
17 | }
18 |
19 | void closeOpenGL() {
20 | }
21 |
22 | unsigned int createPBO(int width, int height, int batchSize, int use_short) {
23 | return 0;
24 | }
25 |
26 | void freePBO(unsigned int pixelBuffer) {
27 | }
28 |
29 | void copyFBOToPBO(mjrContext* con,
30 | unsigned int pbo_rgb, unsigned int pbo_depth,
31 | mjrRect viewport, int bufferOffset) {
32 | }
33 |
34 | void readPBO(unsigned char *buffer_rgb, unsigned short *buffer_depth,
35 | unsigned int pbo_rgb, unsigned int pbo_depth,
36 | int width, int height, int batchSize) {
37 | }
38 |
--------------------------------------------------------------------------------
/mujoco_py/gl/eglplatform.h:
--------------------------------------------------------------------------------
1 | #ifndef __eglplatform_h_
2 | #define __eglplatform_h_
3 |
4 | /*
5 | ** Copyright (c) 2007-2013 The Khronos Group Inc.
6 | **
7 | ** Permission is hereby granted, free of charge, to any person obtaining a
8 | ** copy of this software and/or associated documentation files (the
9 | ** "Materials"), to deal in the Materials without restriction, including
10 | ** without limitation the rights to use, copy, modify, merge, publish,
11 | ** distribute, sublicense, and/or sell copies of the Materials, and to
12 | ** permit persons to whom the Materials are furnished to do so, subject to
13 | ** the following conditions:
14 | **
15 | ** The above copyright notice and this permission notice shall be included
16 | ** in all copies or substantial portions of the Materials.
17 | **
18 | ** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19 | ** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 | ** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
21 | ** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
22 | ** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 | ** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 | ** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
25 | */
26 |
27 | /* Platform-specific types and definitions for egl.h
28 | * $Revision: 30994 $ on $Date: 2015-04-30 13:36:48 -0700 (Thu, 30 Apr 2015) $
29 | *
30 | * Adopters may modify khrplatform.h and this file to suit their platform.
31 | * You are encouraged to submit all modifications to the Khronos group so that
32 | * they can be included in future versions of this file. Please submit changes
33 | * by sending them to the public Khronos Bugzilla (http://khronos.org/bugzilla)
34 | * by filing a bug against product "EGL" component "Registry".
35 | */
36 |
37 | #include "khrplatform.h"
38 |
39 | /* Macros used in EGL function prototype declarations.
40 | *
41 | * EGL functions should be prototyped as:
42 | *
43 | * EGLAPI return-type EGLAPIENTRY eglFunction(arguments);
44 | * typedef return-type (EXPAPIENTRYP PFNEGLFUNCTIONPROC) (arguments);
45 | *
46 | * KHRONOS_APICALL and KHRONOS_APIENTRY are defined in KHR/khrplatform.h
47 | */
48 |
49 | #ifndef EGLAPI
50 | #define EGLAPI KHRONOS_APICALL
51 | #endif
52 |
53 | #ifndef EGLAPIENTRY
54 | #define EGLAPIENTRY KHRONOS_APIENTRY
55 | #endif
56 | #define EGLAPIENTRYP EGLAPIENTRY*
57 |
58 | /* The types NativeDisplayType, NativeWindowType, and NativePixmapType
59 | * are aliases of window-system-dependent types, such as X Display * or
60 | * Windows Device Context. They must be defined in platform-specific
61 | * code below. The EGL-prefixed versions of Native*Type are the same
62 | * types, renamed in EGL 1.3 so all types in the API start with "EGL".
63 | *
64 | * Khronos STRONGLY RECOMMENDS that you use the default definitions
65 | * provided below, since these changes affect both binary and source
66 | * portability of applications using EGL running on different EGL
67 | * implementations.
68 | */
69 |
70 | #if defined(_WIN32) || defined(__VC32__) && !defined(__CYGWIN__) && !defined(__SCITECH_SNAP__) /* Win32 and WinCE */
71 | #ifndef WIN32_LEAN_AND_MEAN
72 | #define WIN32_LEAN_AND_MEAN 1
73 | #endif
74 | #include
75 |
76 | typedef HDC EGLNativeDisplayType;
77 | typedef HBITMAP EGLNativePixmapType;
78 | typedef HWND EGLNativeWindowType;
79 |
80 | #elif defined(__APPLE__) || defined(__WINSCW__) || defined(__SYMBIAN32__) /* Symbian */
81 |
82 | typedef int EGLNativeDisplayType;
83 | typedef void *EGLNativeWindowType;
84 | typedef void *EGLNativePixmapType;
85 |
86 | #elif defined(__ANDROID__) || defined(ANDROID)
87 |
88 | #include
89 |
90 | struct egl_native_pixmap_t;
91 |
92 | typedef struct ANativeWindow* EGLNativeWindowType;
93 | typedef struct egl_native_pixmap_t* EGLNativePixmapType;
94 | typedef void* EGLNativeDisplayType;
95 |
96 | #elif defined(__unix__)
97 |
98 | /* X11 (tentative) */
99 | #include
100 | #include
101 |
102 | typedef Display *EGLNativeDisplayType;
103 | typedef Pixmap EGLNativePixmapType;
104 | typedef Window EGLNativeWindowType;
105 |
106 | #else
107 | #error "Platform not recognized"
108 | #endif
109 |
110 | /* EGL 1.2 types, renamed for consistency in EGL 1.3 */
111 | typedef EGLNativeDisplayType NativeDisplayType;
112 | typedef EGLNativePixmapType NativePixmapType;
113 | typedef EGLNativeWindowType NativeWindowType;
114 |
115 |
116 | /* Define EGLint. This must be a signed integral type large enough to contain
117 | * all legal attribute names and values passed into and out of EGL, whether
118 | * their type is boolean, bitmask, enumerant (symbolic constant), integer,
119 | * handle, or other. While in general a 32-bit integer will suffice, if
120 | * handles are 64 bit types, then EGLint should be defined as a signed 64-bit
121 | * integer type.
122 | */
123 | typedef khronos_int32_t EGLint;
124 |
125 | #endif /* __eglplatform_h */
126 |
--------------------------------------------------------------------------------
/mujoco_py/gl/glshim.h:
--------------------------------------------------------------------------------
1 | #ifndef __GLSHIM_H__
2 | #define __GLSHIM_H__
3 |
4 | #include "mujoco.h"
5 | #include "mjrender.h"
6 |
7 | #ifdef __cplusplus
8 | extern "C" {
9 | #endif
10 |
11 | int usingEGL();
12 | int initOpenGL(int device_id);
13 | void closeOpenGL();
14 | int makeOpenGLContextCurrent(int device_id);
15 | int setOpenGLBufferSize(int device_id, int width, int height);
16 |
17 | unsigned int createPBO(int width, int height, int batchSize, int use_short);
18 | void freePBO(unsigned int pixelBuffer);
19 | void copyFBOToPBO(mjrContext* con,
20 | unsigned int pbo_rgb, unsigned int pbo_depth,
21 | mjrRect viewport, int bufferOffset);
22 | void readPBO(unsigned char *buffer_rgb, unsigned short *buffer_depth,
23 | unsigned int pbo_rgb, unsigned int pbo_depth,
24 | int width, int height, int batchSize);
25 |
26 | #ifdef __cplusplus
27 | } // extern "C"
28 | #endif
29 |
30 | #endif
31 |
--------------------------------------------------------------------------------
/mujoco_py/gl/osmesashim.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include "glshim.h"
3 |
4 | OSMesaContext ctx;
5 |
6 | // this size was picked pretty arbitrarily
7 | int BUFFER_WIDTH = 1024;
8 | int BUFFER_HEIGHT = 1024;
9 | // 4 channels for RGBA
10 | unsigned char buffer[1024 * 1024 * 4];
11 |
12 | int is_initialized = 0;
13 |
14 | int usingEGL() {
15 | return 0;
16 | }
17 |
18 | int initOpenGL(int device_id) {
19 | if (is_initialized)
20 | return 1;
21 |
22 | // note: device id not used here
23 | ctx = OSMesaCreateContextExt(GL_RGBA, 24, 8, 8, 0);
24 | if( !ctx ) {
25 | printf("OSMesa context creation failed\n");
26 | return -1;
27 | }
28 |
29 | if( !OSMesaMakeCurrent(ctx, buffer, GL_UNSIGNED_BYTE, BUFFER_WIDTH, BUFFER_HEIGHT) ) {
30 | printf("OSMesa make current failed\n");
31 | return -1;
32 | }
33 |
34 | is_initialized = 1;
35 |
36 | return 1;
37 | }
38 |
39 | int makeOpenGLContextCurrent(int device_id) {
40 | // Don't need to make context current here, causes issues with large tests
41 | return 1;
42 | }
43 |
44 | int setOpenGLBufferSize(int device_id, int width, int height) {
45 | if (width > BUFFER_WIDTH || height > BUFFER_HEIGHT) {
46 | printf("Buffer size too big\n");
47 | return -1;
48 | }
49 | // Noop since we don't support changing the actual buffer
50 | return 1;
51 | }
52 |
53 | void closeOpenGL() {
54 | if (is_initialized) {
55 | OSMesaDestroyContext(ctx);
56 | is_initialized = 0;
57 | }
58 | }
59 |
60 | unsigned int createPBO(int width, int height, int batchSize, int use_short) {
61 | return 0;
62 | }
63 |
64 | void freePBO(unsigned int pixelBuffer) {
65 | }
66 |
67 | void copyFBOToPBO(mjrContext* con,
68 | unsigned int pbo_rgb, unsigned int pbo_depth,
69 | mjrRect viewport, int bufferOffset) {
70 | }
71 |
72 | void readPBO(unsigned char *buffer_rgb, unsigned short *buffer_depth,
73 | unsigned int pbo_rgb, unsigned int pbo_depth,
74 | int width, int height, int batchSize) {
75 | }
76 |
--------------------------------------------------------------------------------
/mujoco_py/mjsimstate.pyx:
--------------------------------------------------------------------------------
1 |
2 | class MjSimState(namedtuple('SimStateBase', 'time qpos qvel act udd_state')):
3 | """Represents a snapshot of the simulator's state.
4 |
5 | This includes time, qpos, qvel, act, and udd_state.
6 | """
7 | __slots__ = ()
8 |
9 | # need to implement this because numpy doesn't support == on arrays
10 | def __eq__(self, other):
11 | if not isinstance(other, self.__class__):
12 | return NotImplemented
13 |
14 | if set(self.udd_state.keys()) != set(other.udd_state.keys()):
15 | return False
16 |
17 | for k in self.udd_state.keys():
18 | if isinstance(self.udd_state[k], Number) and self.udd_state[k] != other.udd_state[k]:
19 | return False
20 | elif not np.array_equal(self.udd_state[k], other.udd_state[k]):
21 | return False
22 |
23 | return (self.time == other.time and
24 | np.array_equal(self.qpos, other.qpos) and
25 | np.array_equal(self.qvel, other.qvel) and
26 | np.array_equal(self.act, other.act))
27 |
28 | def __ne__(self, other):
29 | return not self.__eq__(other)
30 |
31 | def flatten(self):
32 | """ Flattens a state into a numpy array of numbers."""
33 | if self.act is None:
34 | act = np.empty(0)
35 | else:
36 | act = self.act
37 | state_tuple = ([self.time], self.qpos, self.qvel, act,
38 | MjSimState._flatten_dict(self.udd_state))
39 | return np.concatenate(state_tuple)
40 |
41 | @staticmethod
42 | def _flatten_dict(d):
43 | a = []
44 | for k in sorted(d.keys()):
45 | v = d[k]
46 | if isinstance(v, Number):
47 | a.extend([v])
48 | else:
49 | a.extend(v.ravel())
50 |
51 | return np.array(a)
52 |
53 | @staticmethod
54 | def from_flattened(array, sim):
55 | idx_time = 0
56 | idx_qpos = idx_time + 1
57 | idx_qvel = idx_qpos + sim.model.nq
58 | idx_act = idx_qvel + sim.model.nv
59 | idx_udd = idx_act + sim.model.na
60 |
61 | time = array[idx_time]
62 | qpos = array[idx_qpos:idx_qpos + sim.model.nq]
63 | qvel = array[idx_qvel:idx_qvel + sim.model.nv]
64 | if sim.model.na == 0:
65 | act = None
66 | else:
67 | act = array[idx_act:idx_act + sim.model.na]
68 | flat_udd_state = array[idx_udd:]
69 | udd_state = MjSimState._unflatten_dict(flat_udd_state, sim.udd_state)
70 |
71 | return MjSimState(time, qpos, qvel, act, udd_state)
72 |
73 | @staticmethod
74 | def _unflatten_dict(a, schema_example):
75 | d = {}
76 | idx = 0
77 | for k in sorted(schema_example.keys()):
78 | schema_val = schema_example[k]
79 | if isinstance(schema_val, Number):
80 | val = a[idx]
81 | idx += 1
82 | d[k] = val
83 | else:
84 | assert isinstance(schema_val, np.ndarray)
85 | val_array = a[idx:idx+schema_val.size]
86 | idx += schema_val.size
87 | val = np.array(val_array).reshape(schema_val.shape)
88 | d[k] = val
89 | return d
90 |
--------------------------------------------------------------------------------
/mujoco_py/opengl_context.pyx:
--------------------------------------------------------------------------------
1 | import os
2 | import sys
3 | from abc import ABCMeta, abstractmethod
4 | from mujoco_py.utils import discover_mujoco
5 |
6 |
7 | def _add_mujoco_bin_to_dyld_library_path():
8 | mujoco_path = discover_mujoco()
9 | bin_path = os.path.join(mujoco_path, "bin")
10 | old_dyld_library_path = os.getenv("DYLD_LIBRARY_PATH", "")
11 | os.environ["DYLD_LIBRARY_PATH"] = "{}:{}".format(
12 | bin_path, old_dyld_library_path)
13 |
14 |
15 | try:
16 | _add_mujoco_bin_to_dyld_library_path()
17 | import glfw
18 | except ImportError:
19 | pass
20 |
21 |
22 | class OpenGLContext(metaclass=ABCMeta):
23 |
24 | @abstractmethod
25 | def make_context_current(self):
26 | raise NotImplementedError()
27 |
28 | @abstractmethod
29 | def set_buffer_size(self, width, height):
30 | raise NotImplementedError()
31 |
32 |
33 | class GlfwError(RuntimeError):
34 | pass
35 |
36 |
37 | class GlfwContext(OpenGLContext):
38 |
39 | _INIT_WIDTH = 1000
40 | _INIT_HEIGHT = 1000
41 | _GLFW_IS_INITIALIZED = False
42 |
43 | def __init__(self, offscreen=False, quiet=False):
44 | GlfwContext._init_glfw()
45 |
46 | self._width = self._INIT_WIDTH
47 | self._height = self._INIT_HEIGHT
48 | self.window = self._create_window(offscreen, quiet=quiet)
49 | self._set_window_size(self._width, self._height)
50 |
51 | @staticmethod
52 | def _init_glfw():
53 | if GlfwContext._GLFW_IS_INITIALIZED:
54 | return
55 |
56 | if 'glfw' not in globals():
57 | raise GlfwError("GLFW not installed")
58 |
59 | glfw.set_error_callback(GlfwContext._glfw_error_callback)
60 |
61 | # HAX: sometimes first init() fails, while second works fine.
62 | glfw.init()
63 | if not glfw.init():
64 | raise GlfwError("Failed to initialize GLFW")
65 |
66 | GlfwContext._GLFW_IS_INITIALIZED = True
67 |
68 | def make_context_current(self):
69 | glfw.make_context_current(self.window)
70 |
71 | def set_buffer_size(self, width, height):
72 | self._set_window_size(width, height)
73 | self._width = width
74 | self._height = height
75 |
76 | def _create_window(self, offscreen, quiet=False):
77 | if offscreen:
78 | if not quiet:
79 | print("Creating offscreen glfw")
80 | glfw.window_hint(glfw.VISIBLE, 0)
81 | glfw.window_hint(glfw.DOUBLEBUFFER, 0)
82 | init_width, init_height = self._INIT_WIDTH, self._INIT_HEIGHT
83 | else:
84 | if not quiet:
85 | print("Creating window glfw")
86 | glfw.window_hint(glfw.SAMPLES, 4)
87 | glfw.window_hint(glfw.VISIBLE, 1)
88 | glfw.window_hint(glfw.DOUBLEBUFFER, 1)
89 | resolution, _, refresh_rate = glfw.get_video_mode(
90 | glfw.get_primary_monitor())
91 | init_width, init_height = resolution
92 |
93 | self._width = init_width
94 | self._height = init_height
95 | window = glfw.create_window(
96 | self._width, self._height, "mujoco_py", None, None)
97 |
98 | if not window:
99 | raise GlfwError("Failed to create GLFW window")
100 |
101 | return window
102 |
103 | def get_buffer_size(self):
104 | return glfw.get_framebuffer_size(self.window)
105 |
106 | def _set_window_size(self, target_width, target_height):
107 | self.make_context_current()
108 | if target_width != self._width or target_height != self._height:
109 | self._width = target_width
110 | self._height = target_height
111 | glfw.set_window_size(self.window, target_width, target_height)
112 |
113 | # HAX: When running on a Mac with retina screen, the size
114 | # sometimes doubles
115 | width, height = glfw.get_framebuffer_size(self.window)
116 | if target_width != width and "darwin" in sys.platform.lower():
117 | glfw.set_window_size(self.window, target_width // 2, target_height // 2)
118 |
119 | @staticmethod
120 | def _glfw_error_callback(error_code, description):
121 | print("GLFW error (code %d): %s", error_code, description)
122 |
123 |
124 | class OffscreenOpenGLContext():
125 |
126 | def __init__(self, device_id):
127 | self.device_id = device_id
128 | res = initOpenGL(device_id)
129 | if res != 1:
130 | raise RuntimeError("Failed to initialize OpenGL")
131 |
132 | def close(self):
133 | # TODO: properly close OpenGL in our contexts
134 | closeOpenGL()
135 |
136 | def make_context_current(self):
137 | makeOpenGLContextCurrent(self.device_id)
138 |
139 | def set_buffer_size(self, int width, int height):
140 | res = setOpenGLBufferSize(self.device_id, width, height)
141 | if res != 1:
142 | raise RuntimeError("Failed to set buffer size")
143 |
--------------------------------------------------------------------------------
/mujoco_py/pxd/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/openai/mujoco-py/a13903b82f1ab316815e63b3575526005b3b2ae1/mujoco_py/pxd/__init__.py
--------------------------------------------------------------------------------
/mujoco_py/pxd/mjrender.pxd:
--------------------------------------------------------------------------------
1 | cdef extern from "mjrender.h" nogil:
2 | # Global constants
3 | enum: mjNAUX
4 | enum: mjMAXTEXTURE
5 |
6 | ctypedef enum mjtGridPos: # grid position for overlay
7 | mjGRID_TOPLEFT = 0, # top left
8 | mjGRID_TOPRIGHT, # top right
9 | mjGRID_BOTTOMLEFT, # bottom left
10 | mjGRID_BOTTOMRIGHT # bottom right
11 |
12 |
13 | ctypedef enum mjtFramebuffer: # OpenGL framebuffer option
14 | mjFB_WINDOW = 0, # default/window buffer
15 | mjFB_OFFSCREEN # offscreen buffer
16 |
17 |
18 | ctypedef enum mjtFontScale: # font scale, used at context creation
19 | mjFONTSCALE_100 = 100, # normal scale, suitable in the absence of DPI scaling
20 | mjFONTSCALE_150 = 150, # 150% scale
21 | mjFONTSCALE_200 = 200 # 200% scale
22 |
23 |
24 | ctypedef enum mjtFont: # font type, used at each text operation
25 | mjFONT_NORMAL = 0, # normal font
26 | mjFONT_SHADOW, # normal font with shadow (for higher contrast)
27 | mjFONT_BIG # big font (for user alerts)
28 |
29 | ctypedef struct mjrRect: # OpenGL rectangle
30 | int left # left (usually 0)
31 | int bottom # bottom (usually 0)
32 | int width # width (usually buffer width)
33 | int height # height (usually buffer height)
34 |
35 |
36 | ctypedef struct mjrContext: # custom OpenGL context
37 | # parameters copied from mjVisual
38 | float lineWidth # line width for wireframe rendering
39 | float shadowClip # clipping radius for directional lights
40 | float shadowScale # fraction of light cutoff for spot lights
41 | float fogStart # fog start = stat.extent * vis.map.fogstart
42 | float fogEnd # fog end = stat.extent * vis.map.fogend
43 | float fogRGBA[4] # fog rgba
44 | int shadowSize # size of shadow map texture
45 | int offWidth # width of offscreen buffer
46 | int offHeight # height of offscreen buffer
47 | int offSamples # number of offscreen buffer multisamples
48 |
49 | # parameters specified at creation
50 | int fontScale; # font scale
51 | int auxWidth[mjNAUX] # auxiliary buffer width
52 | int auxHeight[mjNAUX] # auxiliary buffer height
53 | int auxSamples[mjNAUX] # auxiliary buffer multisamples
54 |
55 | # offscreen rendering objects
56 | unsigned int offFBO # offscreen framebuffer object
57 | unsigned int offFBO_r # offscreen framebuffer for resolving multisamples
58 | unsigned int offColor # offscreen color buffer
59 | unsigned int offColor_r # offscreen color buffer for resolving multisamples
60 | unsigned int offDepthStencil # offscreen depth and stencil buffer
61 | unsigned int offDepthStencil_r # offscreen depth and stencil buffer for resolving multisamples
62 |
63 | # shadow rendering objects
64 | unsigned int shadowFBO # shadow map framebuffer object
65 | unsigned int shadowTex # shadow map texture
66 |
67 | # auxiliary buffers
68 | unsigned int auxFBO[mjNAUX] # auxiliary framebuffer object
69 | unsigned int auxFBO_r[mjNAUX] # auxiliary framebuffer object for resolving
70 | unsigned int auxColor[mjNAUX] # auxiliary color buffer
71 | unsigned int auxColor_r[mjNAUX] # auxiliary color buffer for resolving
72 |
73 | # texture objects and info
74 | int ntexture # number of allocated textures
75 | int textureType[100] # type of texture (mjtTexture)
76 | unsigned int texture[100] # texture names
77 |
78 | # displaylist starting positions
79 | unsigned int basePlane # all planes from model
80 | unsigned int baseMesh # all meshes from model
81 | unsigned int baseHField # all hfields from model
82 | unsigned int baseBuiltin # all buildin geoms, with quality from model
83 | unsigned int baseFontNormal # normal font
84 | unsigned int baseFontShadow # shadow font
85 | unsigned int baseFontBig # big font
86 |
87 | # displaylist ranges
88 | int rangePlane # all planes from model
89 | int rangeMesh # all meshes from model
90 | int rangeHField # all hfields from model
91 | int rangeBuiltin # all builtin geoms, with quality from model
92 | int rangeFont # all characters in font
93 |
94 | # skin VBOs
95 | int nskin # number of skins
96 | unsigned int* skinvertVBO # skin vertex position VBOs
97 | unsigned int* skinnormalVBO # skin vertex normal VBOs
98 | unsigned int* skintexcoordVBO # skin vertex texture coordinate VBOs
99 | unsigned int* skinfaceVBO # skin face index VBOs
100 |
101 | # character info
102 | int charWidth[127] # character widths: normal and shadow
103 | int charWidthBig[127] # chacarter widths: big
104 | int charHeight # character heights: normal and shadow
105 | int charHeightBig # character heights: big
106 |
107 | # capabilities
108 | int glewInitialized # is glew initialized
109 | int windowAvailable # is default/window framebuffer available
110 | int windowSamples # number of samples for default/window framebuffer
111 | int windowStereo # is stereo available for default/window framebuffer
112 | int windowDoublebuffer # is default/window framebuffer double buffered
113 |
114 | # only field that changes after mjr_makeContext
115 | int currentBuffer # currently active framebuffer: mjFB_WINDOW or mjFB_OFFSCREEN
116 |
--------------------------------------------------------------------------------
/mujoco_py/pxd/mjui.pxd:
--------------------------------------------------------------------------------
1 | cdef extern from "mjui.h" nogil:
2 | # Global constants
3 | enum: mjMAXUISECT
4 | enum: mjMAXUIITEM
5 | enum: mjMAXUITEXT
6 | enum: mjMAXUINAME
7 | enum: mjMAXUIMULTI
8 | enum: mjMAXUIEDIT
9 | enum: mjMAXUIRECT
10 | enum: mjSEPCLOSED
11 |
12 |
13 | # predicate function: set enable/disable based on item category
14 | ctypedef int (*mjfItemEnable)(int category, void* data);
15 |
16 | ctypedef struct mjuiState: # mouse and keyboard state
17 | # constants set by user
18 | int nrect # number of rectangles used
19 | mjrRect rect[mjMAXUIRECT] # rectangles (index 0: entire window)
20 | void* userdata # pointer to user data (for callbacks)
21 |
22 | # event type
23 | int type # (type mjtEvent)
24 |
25 | # mouse buttons
26 | int left # is left button down
27 | int right # is right button down
28 | int middle # is middle button down
29 | int doubleclick # is last press a double click
30 | int button # which button was pressed (mjtButton)
31 | double buttontime # time of last button press
32 |
33 | # mouse position
34 | double x # x position
35 | double y # y position
36 | double dx # x displacement
37 | double dy # y displacement
38 | double sx # x scroll
39 | double sy # y scroll
40 |
41 | # keyboard
42 | int control # is control down
43 | int shift # is shift down
44 | int alt # is alt down
45 | int key # which key was pressed
46 | double keytime # time of last key press
47 |
48 | # rectangle ownership and dragging
49 | int mouserect # which rectangle contains mouse
50 | int dragrect # which rectangle is dragged with mouse
51 | int dragbutton # which button started drag (mjtButton)
52 |
53 | ctypedef struct mjuiThemeSpacing: # UI visualization theme spacing
54 | int total # total width
55 | int scroll # scrollbar width
56 | int label # label width
57 | int section # section gap
58 | int itemside # item side gap
59 | int itemmid # item middle gap
60 | int itemver # item vertical gap
61 | int texthor # text horizontal gap
62 | int textver # text vertical gap
63 | int linescroll # number of pixels to scroll
64 | int samples # number of multisamples
65 |
66 |
67 | ctypedef struct mjuiThemeColor: # UI visualization theme color
68 | float master[3] # master background
69 | float thumb[3] # scrollbar thumb
70 | float secttitle[3] # section title
71 | float sectfont[3] # section font
72 | float sectsymbol[3] # section symbol
73 | float sectpane[3] # section pane
74 | float shortcut[3] # shortcut background
75 | float fontactive[3] # font active
76 | float fontinactive[3] # font inactive
77 | float decorinactive[3] # decor inactive
78 | float decorinactive2[3] # inactive slider color 2
79 | float button[3] # button
80 | float check[3] # check
81 | float radio[3] # radio
82 | float select[3] # select
83 | float select2[3] # select pane
84 | float slider[3] # slider
85 | float slider2[3] # slider color 2
86 | float edit[3] # edit
87 | float edit2[3] # edit invalid
88 | float cursor[3] # edit cursor
89 |
90 |
91 | ctypedef struct mjuiItem: # UI item
92 | # common properties
93 | int type # type (mjtItem)
94 | char name[mjMAXUINAME] # name
95 | int state # 0: disable, 1: enable, 2+: use predicate
96 | void *pdata # data pointer (type-specific)
97 | int sectionid # id of section containing item
98 | int itemid # id of item within section
99 |
100 | # internal
101 | mjrRect rect # rectangle occupied by item
102 |
103 |
104 | ctypedef struct mjuiSection: # UI section
105 | # properties
106 | char name[mjMAXUINAME] # name
107 | int state # 0: closed, 1: open
108 | int modifier # 0: none, 1: control, 2: shift; 4: alt
109 | int shortcut # shortcut key; 0: undefined
110 | int nitem # number of items in use
111 | mjuiItem item[mjMAXUIITEM] # preallocated array of items
112 | # internal
113 | mjrRect rtitle # rectangle occupied by title
114 | mjrRect rcontent # rectangle occupied by content
115 |
116 |
117 | ctypedef struct mjUI: # entire UI
118 | # constants set by user
119 | mjuiThemeSpacing spacing # UI theme spacing
120 | mjuiThemeColor color # UI theme color
121 | mjfItemEnable predicate # callback to set item state programmatically
122 | void* userdata # pointer to user data (passed to predicate)
123 | int rectid # index of this ui rectangle in mjuiState
124 | int auxid # aux buffer index of this ui
125 | int radiocol # number of radio columns (0 defaults to 2)
126 |
127 | # UI sizes (framebuffer units)
128 | int width # width
129 | int height # current heigth
130 | int maxheight # height when all sections open
131 | int scroll # scroll from top of UI
132 |
133 | # mouse focus
134 | int mousesect # 0: none, -1: scroll, otherwise 1+section
135 | int mouseitem # item within section
136 | int mousehelp # help button down: print shortcuts
137 |
138 | # keyboard focus and edit
139 | int editsect # 0: none, otherwise 1+section
140 | int edititem # item within section
141 | int editcursor # cursor position
142 | int editscroll # horizontal scroll
143 | char edittext[mjMAXUITEXT] # current text
144 | mjuiItem* editchanged # pointer to changed edit in last mjui_event
145 |
146 | # sections
147 | int nsect # number of sections in use
148 | mjuiSection sect[mjMAXUISECT] # preallocated array of sections
149 |
150 |
151 | ctypedef struct mjuiDef:
152 | int type # type (mjtItem); -1: section
153 | char name[mjMAXUINAME] # name
154 | int state # state
155 | void* pdata # pointer to data
156 | char other[mjMAXUITEXT] # string with type-specific properties
157 |
--------------------------------------------------------------------------------
/mujoco_py/test_imgs/test_glfw_context.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/openai/mujoco-py/a13903b82f1ab316815e63b3575526005b3b2ae1/mujoco_py/test_imgs/test_glfw_context.png
--------------------------------------------------------------------------------
/mujoco_py/test_imgs/test_materials.premod.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/openai/mujoco-py/a13903b82f1ab316815e63b3575526005b3b2ae1/mujoco_py/test_imgs/test_materials.premod.png
--------------------------------------------------------------------------------
/mujoco_py/test_imgs/test_materials.props.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/openai/mujoco-py/a13903b82f1ab316815e63b3575526005b3b2ae1/mujoco_py/test_imgs/test_materials.props.png
--------------------------------------------------------------------------------
/mujoco_py/test_imgs/test_materials.rand_all.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/openai/mujoco-py/a13903b82f1ab316815e63b3575526005b3b2ae1/mujoco_py/test_imgs/test_materials.rand_all.png
--------------------------------------------------------------------------------
/mujoco_py/test_imgs/test_multiple_sims.loop0_0.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/openai/mujoco-py/a13903b82f1ab316815e63b3575526005b3b2ae1/mujoco_py/test_imgs/test_multiple_sims.loop0_0.png
--------------------------------------------------------------------------------
/mujoco_py/test_imgs/test_multiple_sims.loop0_1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/openai/mujoco-py/a13903b82f1ab316815e63b3575526005b3b2ae1/mujoco_py/test_imgs/test_multiple_sims.loop0_1.png
--------------------------------------------------------------------------------
/mujoco_py/test_imgs/test_multiple_sims.loop1_0.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/openai/mujoco-py/a13903b82f1ab316815e63b3575526005b3b2ae1/mujoco_py/test_imgs/test_multiple_sims.loop1_0.png
--------------------------------------------------------------------------------
/mujoco_py/test_imgs/test_multiple_sims.loop1_1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/openai/mujoco-py/a13903b82f1ab316815e63b3575526005b3b2ae1/mujoco_py/test_imgs/test_multiple_sims.loop1_1.png
--------------------------------------------------------------------------------
/mujoco_py/test_imgs/test_multiple_sims.loop2_0.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/openai/mujoco-py/a13903b82f1ab316815e63b3575526005b3b2ae1/mujoco_py/test_imgs/test_multiple_sims.loop2_0.png
--------------------------------------------------------------------------------
/mujoco_py/test_imgs/test_multiple_sims.loop2_1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/openai/mujoco-py/a13903b82f1ab316815e63b3575526005b3b2ae1/mujoco_py/test_imgs/test_multiple_sims.loop2_1.png
--------------------------------------------------------------------------------
/mujoco_py/test_imgs/test_render_pool.mp_test_cameras.0.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/openai/mujoco-py/a13903b82f1ab316815e63b3575526005b3b2ae1/mujoco_py/test_imgs/test_render_pool.mp_test_cameras.0.png
--------------------------------------------------------------------------------
/mujoco_py/test_imgs/test_render_pool.mp_test_cameras.1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/openai/mujoco-py/a13903b82f1ab316815e63b3575526005b3b2ae1/mujoco_py/test_imgs/test_render_pool.mp_test_cameras.1.png
--------------------------------------------------------------------------------
/mujoco_py/test_imgs/test_render_pool.mp_test_rendering.0.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/openai/mujoco-py/a13903b82f1ab316815e63b3575526005b3b2ae1/mujoco_py/test_imgs/test_render_pool.mp_test_rendering.0.png
--------------------------------------------------------------------------------
/mujoco_py/test_imgs/test_render_pool.mp_test_states.1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/openai/mujoco-py/a13903b82f1ab316815e63b3575526005b3b2ae1/mujoco_py/test_imgs/test_render_pool.mp_test_states.1.png
--------------------------------------------------------------------------------
/mujoco_py/test_imgs/test_render_pool.mp_test_states.2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/openai/mujoco-py/a13903b82f1ab316815e63b3575526005b3b2ae1/mujoco_py/test_imgs/test_render_pool.mp_test_states.2.png
--------------------------------------------------------------------------------
/mujoco_py/test_imgs/test_render_pool.mp_test_states.3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/openai/mujoco-py/a13903b82f1ab316815e63b3575526005b3b2ae1/mujoco_py/test_imgs/test_render_pool.mp_test_states.3.png
--------------------------------------------------------------------------------
/mujoco_py/test_imgs/test_render_pool.mp_test_states.4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/openai/mujoco-py/a13903b82f1ab316815e63b3575526005b3b2ae1/mujoco_py/test_imgs/test_render_pool.mp_test_states.4.png
--------------------------------------------------------------------------------
/mujoco_py/test_imgs/test_render_pool.mp_test_states.5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/openai/mujoco-py/a13903b82f1ab316815e63b3575526005b3b2ae1/mujoco_py/test_imgs/test_render_pool.mp_test_states.5.png
--------------------------------------------------------------------------------
/mujoco_py/test_imgs/test_rendering.camera1.narrow.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/openai/mujoco-py/a13903b82f1ab316815e63b3575526005b3b2ae1/mujoco_py/test_imgs/test_rendering.camera1.narrow.png
--------------------------------------------------------------------------------
/mujoco_py/test_imgs/test_rendering.camera1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/openai/mujoco-py/a13903b82f1ab316815e63b3575526005b3b2ae1/mujoco_py/test_imgs/test_rendering.camera1.png
--------------------------------------------------------------------------------
/mujoco_py/test_imgs/test_rendering.freecam.depth-darwin.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/openai/mujoco-py/a13903b82f1ab316815e63b3575526005b3b2ae1/mujoco_py/test_imgs/test_rendering.freecam.depth-darwin.png
--------------------------------------------------------------------------------
/mujoco_py/test_imgs/test_rendering.freecam.depth.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/openai/mujoco-py/a13903b82f1ab316815e63b3575526005b3b2ae1/mujoco_py/test_imgs/test_rendering.freecam.depth.png
--------------------------------------------------------------------------------
/mujoco_py/test_imgs/test_rendering.freecam.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/openai/mujoco-py/a13903b82f1ab316815e63b3575526005b3b2ae1/mujoco_py/test_imgs/test_rendering.freecam.png
--------------------------------------------------------------------------------
/mujoco_py/test_imgs/test_rendering_markers.camera1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/openai/mujoco-py/a13903b82f1ab316815e63b3575526005b3b2ae1/mujoco_py/test_imgs/test_rendering_markers.camera1.png
--------------------------------------------------------------------------------
/mujoco_py/test_imgs/test_resetting.loop0_0.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/openai/mujoco-py/a13903b82f1ab316815e63b3575526005b3b2ae1/mujoco_py/test_imgs/test_resetting.loop0_0.png
--------------------------------------------------------------------------------
/mujoco_py/test_imgs/test_resetting.loop0_1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/openai/mujoco-py/a13903b82f1ab316815e63b3575526005b3b2ae1/mujoco_py/test_imgs/test_resetting.loop0_1.png
--------------------------------------------------------------------------------
/mujoco_py/test_imgs/test_resetting.loop1_0.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/openai/mujoco-py/a13903b82f1ab316815e63b3575526005b3b2ae1/mujoco_py/test_imgs/test_resetting.loop1_0.png
--------------------------------------------------------------------------------
/mujoco_py/test_imgs/test_resetting.loop1_1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/openai/mujoco-py/a13903b82f1ab316815e63b3575526005b3b2ae1/mujoco_py/test_imgs/test_resetting.loop1_1.png
--------------------------------------------------------------------------------
/mujoco_py/test_imgs/test_resetting.loop2_0.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/openai/mujoco-py/a13903b82f1ab316815e63b3575526005b3b2ae1/mujoco_py/test_imgs/test_resetting.loop2_0.png
--------------------------------------------------------------------------------
/mujoco_py/test_imgs/test_resetting.loop2_1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/openai/mujoco-py/a13903b82f1ab316815e63b3575526005b3b2ae1/mujoco_py/test_imgs/test_resetting.loop2_1.png
--------------------------------------------------------------------------------
/mujoco_py/test_imgs/test_textures.premod.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/openai/mujoco-py/a13903b82f1ab316815e63b3575526005b3b2ae1/mujoco_py/test_imgs/test_textures.premod.png
--------------------------------------------------------------------------------
/mujoco_py/test_imgs/test_textures.rand_all.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/openai/mujoco-py/a13903b82f1ab316815e63b3575526005b3b2ae1/mujoco_py/test_imgs/test_textures.rand_all.png
--------------------------------------------------------------------------------
/mujoco_py/test_imgs/test_textures.rand_specific.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/openai/mujoco-py/a13903b82f1ab316815e63b3575526005b3b2ae1/mujoco_py/test_imgs/test_textures.rand_specific.png
--------------------------------------------------------------------------------
/mujoco_py/test_imgs/test_textures.rand_texrepeat.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/openai/mujoco-py/a13903b82f1ab316815e63b3575526005b3b2ae1/mujoco_py/test_imgs/test_textures.rand_texrepeat.png
--------------------------------------------------------------------------------
/mujoco_py/test_imgs/test_textures.rgb.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/openai/mujoco-py/a13903b82f1ab316815e63b3575526005b3b2ae1/mujoco_py/test_imgs/test_textures.rgb.png
--------------------------------------------------------------------------------
/mujoco_py/test_imgs/test_textures.variety.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/openai/mujoco-py/a13903b82f1ab316815e63b3575526005b3b2ae1/mujoco_py/test_imgs/test_textures.variety.png
--------------------------------------------------------------------------------
/mujoco_py/tests/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/openai/mujoco-py/a13903b82f1ab316815e63b3575526005b3b2ae1/mujoco_py/tests/__init__.py
--------------------------------------------------------------------------------
/mujoco_py/tests/include.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/mujoco_py/tests/test.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/mujoco_py/tests/test_composite.py:
--------------------------------------------------------------------------------
1 | """
2 | Test whether library can parse composite object definitions - new in MuJoCo 2.0
3 | """
4 |
5 | from mujoco_py import load_model_from_xml
6 |
7 |
8 | PARTICLE_XML = """
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 | """
17 |
18 |
19 | def test_load_particle():
20 | load_model_from_xml(PARTICLE_XML)
21 |
--------------------------------------------------------------------------------
/mujoco_py/tests/test_examples.py:
--------------------------------------------------------------------------------
1 | import subprocess
2 | import glob
3 | import os.path
4 | import mujoco_py
5 | import sys
6 | import pytest
7 | mujoco_py_root = os.path.dirname(os.path.dirname(mujoco_py.__file__))
8 |
9 |
10 | @pytest.mark.requires_rendering
11 | @pytest.mark.requires_glfw
12 | def test_examples():
13 | scripts = glob.glob("%s/examples/*.py" % mujoco_py_root)
14 | env = os.environ.update({'TESTING': 'true'})
15 | assert len(scripts) > 0, 'No example scripts found!'
16 | for tutorial_script in scripts:
17 | if tutorial_script.find("mjvive") > -1:
18 | continue
19 | print("Executing %s" % tutorial_script)
20 |
21 | subprocess.check_call([sys.executable, tutorial_script], env=env)
22 |
--------------------------------------------------------------------------------
/mujoco_py/tests/test_gen_wrappers.py:
--------------------------------------------------------------------------------
1 | import subprocess
2 | import sys
3 | import os
4 | import pytest
5 | import mujoco_py
6 |
7 |
8 | @pytest.mark.skipif(sys.platform.startswith("win"), reason="This test fails on windows.")
9 | def test_gen_wrappers():
10 | # Verifies that gen_wrappers can be executed.
11 | fname = "/tmp/generated_wrappers.pxi"
12 | subprocess.check_call([sys.executable,
13 | os.path.join("scripts", "gen_wrappers.py"), fname])
14 | return fname
15 |
16 |
17 | @pytest.mark.skipif(sys.platform.startswith("win"), reason="This test fails on windows.")
18 | def test_deterministic():
19 | # Verifies that gen_wrappers is deterministic
20 | fname = test_gen_wrappers()
21 | with open(fname) as f:
22 | s = f.read()
23 | fname = test_gen_wrappers()
24 | with open(fname) as f:
25 | assert f.read() == s, 'Generate wrappers returned different result'
26 |
27 |
28 | @pytest.mark.skipif(sys.platform.startswith("win"), reason="This test fails on windows.")
29 | def test_generated():
30 | # Verifies generated wrappers match checked-in wrappers
31 | fname = test_gen_wrappers()
32 | with open(fname) as f:
33 | generated_str = f.read()
34 | gname = os.path.join(os.path.dirname(mujoco_py.cymj.__file__), 'wrappers.pxi')
35 | with open(gname) as f:
36 | checkedin_str = f.read()
37 | assert generated_str == checkedin_str, 'Generated wrappers do not match'
38 |
--------------------------------------------------------------------------------
/mujoco_py/tests/test_modder.py:
--------------------------------------------------------------------------------
1 | import pytest
2 | from mujoco_py import MjSim, load_model_from_xml
3 | from mujoco_py.modder import MaterialModder, TextureModder
4 | from mujoco_py.tests.utils import compare_imgs
5 | import numpy as np
6 |
7 | BASIC_MODEL_XML = """
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 | """
34 |
35 | @pytest.mark.requires_rendering
36 | def test_textures():
37 | model = load_model_from_xml(BASIC_MODEL_XML)
38 | sim = MjSim(model)
39 | sim.forward()
40 |
41 | compare_imgs(sim.render(201, 205, camera_name="topcam"),
42 | 'test_textures.premod.png')
43 |
44 | random_state = np.random.RandomState(0)
45 | modder = TextureModder(sim, random_state=random_state)
46 | modder.whiten_materials()
47 | modder.whiten_materials(['g1', 'g2'])
48 |
49 | modder.set_rgb('g1', (255, 0, 0))
50 | modder.set_rgb('g2', (0, 255, 0))
51 | modder.set_rgb('g3', (0, 0, 255))
52 | modder.set_rgb('g4', (255, 0, 255))
53 | compare_imgs(sim.render(201, 205, camera_name="topcam"),
54 | 'test_textures.rgb.png')
55 |
56 | modder.set_checker('g1', (255, 0, 0), (0, 255, 0))
57 | modder.set_gradient('g2', (0, 255, 0), (0, 0, 255), vertical=True)
58 | modder.set_gradient('g3', (255, 255, 0), (0, 0, 255), vertical=False)
59 | modder.set_noise('g4', (0, 0, 255), (255, 0, 0), 0.1)
60 | compare_imgs(sim.render(201, 205, camera_name="topcam"),
61 | 'test_textures.variety.png')
62 |
63 | modder.rand_checker('g1')
64 | modder.rand_gradient('g2')
65 | modder.rand_noise('g3')
66 | modder.rand_rgb('g4')
67 | compare_imgs(sim.render(201, 205, camera_name="topcam"),
68 | 'test_textures.rand_specific.png')
69 |
70 | modder.rand_all('g1')
71 | modder.rand_all('g2')
72 | modder.rand_all('g3')
73 | modder.rand_all('g4')
74 | compare_imgs(sim.render(201, 205, camera_name="topcam"),
75 | 'test_textures.rand_all.png')
76 |
77 | modder.rand_checker('g1')
78 | modder.rand_checker('g2')
79 | modder.rand_checker('g3')
80 | modder.rand_checker('g4')
81 | mat_modder = MaterialModder(sim, random_state=random_state)
82 | mat_modder.rand_texrepeat('g1')
83 | mat_modder.rand_texrepeat('g2')
84 | mat_modder.rand_texrepeat('g3')
85 | mat_modder.rand_texrepeat('g4')
86 | compare_imgs(sim.render(201, 205, camera_name="topcam"),
87 | 'test_textures.rand_texrepeat.png')
88 |
89 | @pytest.mark.requires_rendering
90 | def test_materials():
91 | model = load_model_from_xml(BASIC_MODEL_XML)
92 | sim = MjSim(model)
93 | sim.forward()
94 |
95 | compare_imgs(sim.render(201, 205, camera_name="topcam"),
96 | 'test_materials.premod.png')
97 |
98 | random_state = np.random.RandomState(0)
99 | modder = MaterialModder(sim, random_state=random_state)
100 |
101 | modder.set_specularity('g1', 1.0)
102 | modder.set_reflectance('g2', 1.0)
103 | modder.set_shininess('g3', 1.0)
104 | compare_imgs(sim.render(201, 205, camera_name="topcam"),
105 | 'test_materials.props.png')
106 |
107 | modder.rand_all('g4')
108 | compare_imgs(sim.render(201, 205, camera_name="topcam"),
109 | 'test_materials.rand_all.png')
110 |
111 | @pytest.mark.requires_rendering
112 | def test_multiple_sims():
113 | # Ensure that creating new simulators still produces good renderings.
114 | xml = """
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 | """
127 |
128 | model = load_model_from_xml(xml)
129 | random_state = np.random.RandomState(0)
130 |
131 | for i in range(3):
132 | sim = MjSim(model)
133 | sim.forward()
134 | modder = TextureModder(sim, random_state=random_state)
135 | for j in range(2):
136 | modder.rand_checker('g1')
137 | compare_imgs(
138 | sim.render(201, 205, camera_name="topcam"),
139 | 'test_multiple_sims.loop%d_%d.png' % (i, j))
140 |
141 |
142 | @pytest.mark.requires_rendering
143 | def test_resetting():
144 | # Ensure that resetting environment and creating new simulators
145 | # still produces good renderings.
146 | xml = """
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 | """
159 |
160 | def get_sim(seed):
161 | geom_type = ["box", "sphere"][seed % 2]
162 | model = load_model_from_xml(xml.format(geom_type=geom_type))
163 | return MjSim(model)
164 |
165 | random_state = np.random.RandomState(0)
166 |
167 | for i in range(3):
168 | sim = get_sim(i - 1)
169 | sim.forward()
170 | modder = TextureModder(sim, random_state=random_state)
171 | for j in range(2):
172 | modder.rand_checker('g1')
173 | compare_imgs(sim.render(201, 205, camera_name="topcam"),
174 | 'test_resetting.loop%d_%d.png' % (i, j))
175 |
--------------------------------------------------------------------------------
/mujoco_py/tests/test_opengl_context.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | import pytest
3 | import numpy as np
4 | from mujoco_py import MjSim, load_model_from_xml, MjRenderContext, GlfwContext
5 | from mujoco_py.tests.utils import compare_imgs
6 |
7 | BASIC_MODEL_XML = """
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 | """
34 |
35 | @pytest.mark.requires_rendering
36 | def test_glfw_context():
37 | model = load_model_from_xml(BASIC_MODEL_XML)
38 | sim = MjSim(model)
39 | sim.forward()
40 |
41 | render_context = MjRenderContext(sim, offscreen=True, opengl_backend='glfw')
42 | assert len(sim.render_contexts) == 1
43 | assert sim.render_contexts[0] is render_context
44 | assert isinstance(render_context.opengl_context, GlfwContext)
45 |
46 | compare_imgs(sim.render(201, 205, camera_name="topcam"), 'test_glfw_context.png')
47 | assert len(sim.render_contexts) == 1
48 | assert sim.render_contexts[0] is render_context
49 |
50 |
51 | @pytest.mark.requires_rendering
52 | def test_read_depth_buffer():
53 | model = load_model_from_xml(BASIC_MODEL_XML)
54 | sim = MjSim(model)
55 | sim.forward()
56 | ctx = MjRenderContext(sim, offscreen=True, opengl_backend='glfw')
57 |
58 | buf = np.zeros((11, 100), dtype=np.float32)
59 | assert buf.sum() == 0, f'{buf.sum()}'
60 |
61 | ctx.render(buf.shape[1], buf.shape[0], 0)
62 | ctx.read_pixels_depth(buf)
63 | assert buf.sum() != 0, f'{buf.sum()} {buf.max()}'
64 |
--------------------------------------------------------------------------------
/mujoco_py/tests/test_render_pool.py:
--------------------------------------------------------------------------------
1 | import multiprocessing as mp
2 | import os
3 | import subprocess
4 | import sys
5 | from os.path import abspath, dirname, join
6 |
7 | import numpy as np
8 | import pytest
9 |
10 | from mujoco_py import MjSim, MjRenderPool, load_model_from_xml
11 | from mujoco_py.modder import TextureModder
12 | from mujoco_py.tests.utils import compare_imgs
13 |
14 | BASIC_MODEL_XML = """
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 | """
43 |
44 |
45 | @pytest.mark.requires_rendering
46 | def test_spawn():
47 | # pytest and nose both use 'fork' by default, so we
48 | # expect a runtime error
49 | model = load_model_from_xml(BASIC_MODEL_XML)
50 | with pytest.raises(RuntimeError):
51 | MjRenderPool(model, n_workers=3)
52 |
53 |
54 | @pytest.mark.requires_rendering
55 | def test_multiprocessing():
56 | # pytest doesn't work well with multiprocessing, so just
57 | # run the multiprocessing tests manually by running this
58 | # script as a subprocess
59 | env = os.environ
60 | env['MUJOCO_PY_TEST_ASSET_DIR_PATH'] = abspath(
61 | join(dirname(__file__), '..', 'test_imgs'))
62 | subprocess.check_call([sys.executable, __file__], env=env, shell=True)
63 |
64 |
65 | def mp_test_create_destroy():
66 | model = load_model_from_xml(BASIC_MODEL_XML)
67 | pool = MjRenderPool(model, n_workers=2)
68 | del pool
69 |
70 | # closing before deleting should be fine too
71 | pool = MjRenderPool(model, n_workers=2)
72 | pool.close()
73 | del pool
74 |
75 |
76 | def mp_test_rendering():
77 | model = load_model_from_xml(BASIC_MODEL_XML)
78 | pool = MjRenderPool(model, n_workers=3)
79 |
80 | images = pool.render(100, 100)
81 | assert images.shape == (3, 100, 100, 3)
82 | compare_imgs(images[0], 'test_render_pool.mp_test_rendering.0.png')
83 | assert np.all(images[0] == images[1])
84 |
85 | images, depth = pool.render(101, 103, depth=True)
86 | assert images.shape == (3, 103, 101, 3)
87 | assert depth.shape == (3, 103, 101)
88 | assert np.all(images[0] == images[1])
89 | assert np.all(images[1] == images[2])
90 |
91 |
92 | def mp_test_cameras():
93 | model = load_model_from_xml(BASIC_MODEL_XML)
94 | pool = MjRenderPool(model, n_workers=1)
95 |
96 | image = pool.render(100, 100)
97 | assert image.shape == (1, 100, 100, 3)
98 | compare_imgs(image[0], 'test_render_pool.mp_test_cameras.0.png')
99 |
100 | image = pool.render(100, 100, camera_name='camera1')
101 | assert image.shape == (1, 100, 100, 3)
102 | compare_imgs(image[0], 'test_render_pool.mp_test_cameras.1.png')
103 |
104 |
105 | def mp_test_modder():
106 | model = load_model_from_xml(BASIC_MODEL_XML)
107 | pool = MjRenderPool(model, n_workers=2, modder=TextureModder)
108 |
109 | images = pool.render(100, 100, randomize=True)
110 | assert images.shape == (2, 100, 100, 3)
111 |
112 | # the order of the images aren't guaranteed to be consistent
113 | # between the render runs
114 | images1 = pool.render(100, 100, randomize=False)
115 | assert images1.shape == (2, 100, 100, 3)
116 |
117 | if np.all(images[0] == images1[0]) and np.all(images[1] == images1[1]):
118 | images_same = True
119 | elif np.all(images[0] == images1[1]) and np.all(images[1] == images1[0]):
120 | images_same = True
121 | else:
122 | images_same = False
123 | assert images_same
124 |
125 | images2 = pool.render(100, 100, randomize=True)
126 | assert images2.shape == (2, 100, 100, 3)
127 |
128 | if np.all(images[0] == images2[0]) and np.all(images[1] == images2[1]):
129 | images_same = True
130 | elif np.all(images[0] == images2[1]) and np.all(images[1] == images2[0]):
131 | images_same = True
132 | else:
133 | images_same = False
134 | assert not images_same
135 |
136 |
137 | def mp_test_states():
138 | sim = MjSim(load_model_from_xml(BASIC_MODEL_XML))
139 |
140 | states = []
141 | for val in range(3):
142 | sim.data.qpos[:3] = val * 0.1
143 | states.append(sim.get_state())
144 |
145 | pool = MjRenderPool(sim.model, n_workers=3)
146 |
147 | images = pool.render(100, 100, states=states[:2])
148 | assert images.shape == (2, 100, 100, 3)
149 | compare_imgs(images[0], 'test_render_pool.mp_test_states.1.png')
150 | compare_imgs(images[1], 'test_render_pool.mp_test_states.2.png')
151 |
152 | states = list(reversed(states))
153 | images = pool.render(100, 100, states=states)
154 | assert images.shape == (3, 100, 100, 3)
155 | compare_imgs(images[0], 'test_render_pool.mp_test_states.3.png')
156 | compare_imgs(images[1], 'test_render_pool.mp_test_states.4.png')
157 | compare_imgs(images[2], 'test_render_pool.mp_test_states.5.png')
158 |
159 |
160 | if __name__ == '__main__':
161 | mp.freeze_support()
162 | mp.set_start_method('spawn')
163 |
164 | mp_test_create_destroy()
165 | mp_test_rendering()
166 | mp_test_states()
167 | mp_test_cameras()
168 | mp_test_modder()
169 |
--------------------------------------------------------------------------------
/mujoco_py/tests/test_substep.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | import unittest
3 | import numpy as np
4 | from mujoco_py import load_model_from_xml, MjSim, functions
5 |
6 |
7 | XML = '''
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 | '''
26 |
27 | INCREMENT_FN = '''
28 | void fun(const mjModel* m, mjData* d) {
29 | d->userdata[0] += 1;
30 | }
31 | '''
32 |
33 |
34 | class TestSubstep(unittest.TestCase):
35 | def test_hello(self):
36 | fn = '''
37 | #include
38 | void fun(const mjModel* m, mjData* d) {
39 | printf("hello");
40 | }
41 | '''
42 | sim = MjSim(load_model_from_xml(XML.format(nuserdata=0)),
43 | substep_callback=fn)
44 | sim.step() # should print 'hello'
45 |
46 | def test_increment(self):
47 | sim = MjSim(load_model_from_xml(XML.format(nuserdata=1)),
48 | substep_callback=INCREMENT_FN)
49 | self.assertEqual(sim.data.userdata[0], 0)
50 | sim.step() # should increment userdata[0]
51 | self.assertEqual(sim.data.userdata[0], 1)
52 | # Test again with different nsubsteps, reuse model
53 | sim = MjSim(sim.model, nsubsteps=7, substep_callback=INCREMENT_FN)
54 | self.assertEqual(sim.data.userdata[0], 0)
55 | sim.step() # should increment userdata[0] 7 times
56 | self.assertEqual(sim.data.userdata[0], 7)
57 |
58 | def test_sum_ctrl(self):
59 | fn = '''
60 | void fun(const mjModel* m, mjData* d) {
61 | for (int i = 0; i < m->nu; i++) {
62 | my_sum += d->ctrl[i];
63 | }
64 | }
65 | '''
66 | sim = MjSim(load_model_from_xml(XML.format(nuserdata=1)),
67 | substep_callback=fn,
68 | userdata_names=['my_sum'])
69 | self.assertEqual(sim.data.userdata[0], 0)
70 | sim.step() # should set userdata[0] to sum of controls
71 | self.assertEqual(sim.data.userdata[0], 0)
72 | sim.data.ctrl[0] = 12.
73 | sim.data.ctrl[1] = .34
74 | sim.step()
75 | self.assertEqual(sim.data.userdata[0], 12.34)
76 | sim.step()
77 | self.assertEqual(sim.data.userdata[0], 24.68)
78 |
79 | def test_penetrations(self):
80 | # Test that we capture the max penetration of a falling sphere
81 | # Given a single step with many substeps
82 | xml = '''
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 | '''
94 | # NOTE: penetration is negative distance in contacts
95 | fn = '''
96 | #define MIN(a, b) (a < b ? a : b)
97 | void fun(const mjModel* m, mjData* d) {
98 | for (int i = 0; i < d->ncon; i++) {
99 | min_contact_dist = MIN(min_contact_dist, d->contact[i].dist);
100 | }
101 | }
102 | '''
103 | sim = MjSim(load_model_from_xml(xml), nsubsteps=1000,
104 | substep_callback=fn, userdata_names=['min_contact_dist'])
105 | self.assertEqual(sim.data.userdata[0], 0)
106 | sim.step()
107 | self.assertEqual(sim.data.ncon, 1) # Assert we have a contact
108 | self.assertLess(sim.data.contact[0].dist, 0) # assert penetration
109 | # Assert that min penetration is much less than current penetration
110 | self.assertLess(sim.data.userdata[0], 10 * sim.data.contact[0].dist)
111 |
112 | def test_reuse(self):
113 | ''' Test that we can re-use a substep_callback between sims '''
114 | fn = '''
115 | #define MAX(a, b) (a > b ? a : b)
116 | void fun(const mjModel* m, mjData* d) {
117 | for (int i = 0; i < m->nu; i++) {
118 | ctrl_max = MAX(ctrl_max, d->ctrl[i]);
119 | }
120 | }
121 | '''
122 | sim = MjSim(load_model_from_xml(XML.format(nuserdata=1)),
123 | substep_callback=fn, userdata_names=['ctrl_max'])
124 | sim.step()
125 | self.assertEqual(sim.data.userdata[0], 0)
126 | sim.data.ctrl[:] = [1, 2]
127 | sim.step()
128 | self.assertEqual(sim.data.userdata[0], 2)
129 | sim2 = MjSim(sim.model, substep_callback=sim.substep_callback_ptr)
130 | sim2.step()
131 | self.assertEqual(sim2.data.userdata[0], 0)
132 | sim2.data.ctrl[:] = [.1, .2]
133 | sim2.step()
134 | self.assertEqual(sim2.data.userdata[0], .2)
135 |
136 | def test_mjfunctions(self):
137 | # Test calling mujoco function from within callback
138 | fn = '''
139 | void fun(const mjModel *m, mjData *d) {
140 | // set userdata to rotation matrix for body_xquat[2]
141 | mju_quat2Mat(d->userdata, &(d->xquat[4 * 2]));
142 | }
143 | '''
144 | sim = MjSim(load_model_from_xml(XML.format(nuserdata=9)),
145 | substep_callback=fn)
146 | sim.data.ctrl[:] = [9, 13]
147 | for _ in range(30):
148 | sim.step()
149 | sim.substep_callback()
150 | mat = np.zeros(9, dtype=np.float64)
151 | functions.mju_quat2Mat(mat, sim.data.body_xquat[2])
152 | np.testing.assert_array_equal(sim.data.userdata, mat)
153 |
154 |
155 | if __name__ == '__main__':
156 | unittest.main()
157 |
--------------------------------------------------------------------------------
/mujoco_py/tests/test_vfs.py:
--------------------------------------------------------------------------------
1 | from tempfile import NamedTemporaryFile
2 | from mujoco_py import functions
3 | from mujoco_py.cymj import PyMjVFS
4 |
5 |
6 | def test_vfs():
7 | ''' Test basic VFS functionality '''
8 | vfs = PyMjVFS()
9 | functions.mj_defaultVFS(vfs)
10 | functions.mj_deleteVFS(vfs)
11 |
12 |
13 | def test_files():
14 | ''' Testing handling VFS files '''
15 | vfs = PyMjVFS()
16 | functions.mj_defaultVFS(vfs)
17 | f = NamedTemporaryFile(delete=False)
18 | name = f.name
19 | # Try to find file before added -> missing
20 | assert functions.mj_findFileVFS(vfs, name) == -1
21 | # Add file -> success
22 | assert functions.mj_addFileVFS(vfs, '', name) == 0
23 | # Add file again -> failure, duplicate
24 | assert functions.mj_addFileVFS(vfs, '', name) == 2
25 | # Find file -> success (index 0)
26 | assert functions.mj_findFileVFS(vfs, name) == 0
27 | # Delete file -> success
28 | assert functions.mj_deleteFileVFS(vfs, name) == 0
29 | # Delete file again -> failure, missing
30 | assert functions.mj_deleteFileVFS(vfs, name) == -1
31 | # Add a file which does not exist -> failure, missing
32 | assert functions.mj_addFileVFS(vfs, 'bla', name) == -1
33 |
--------------------------------------------------------------------------------
/mujoco_py/tests/test_viewer.py:
--------------------------------------------------------------------------------
1 | import pytest
2 | from mujoco_py import load_model_from_path, MjSim
3 | from mujoco_py.mjviewer import MjViewer
4 |
5 |
6 | @pytest.mark.requires_rendering
7 | @pytest.mark.requires_glfw
8 | def test_viewer():
9 | model = load_model_from_path("mujoco_py/tests/test.xml")
10 | sim = MjSim(model)
11 | viewer = MjViewer(sim)
12 | for _ in range(100):
13 | sim.step()
14 | viewer.render()
15 |
--------------------------------------------------------------------------------
/mujoco_py/tests/utils.py:
--------------------------------------------------------------------------------
1 | import os
2 | from PIL import Image
3 | from os.path import exists, join, dirname, abspath
4 | from shutil import move
5 | import numpy as np
6 | from os.path import splitext
7 | import imagehash
8 | import pytest
9 |
10 | if os.getenv('MUJOCO_PY_TEST_ASSET_DIR_PATH'):
11 | TEST_ASSET_DIR_PATH = os.getenv('MUJOCO_PY_TEST_ASSET_DIR_PATH')
12 | else:
13 | TEST_ASSET_DIR_PATH = abspath(join(dirname(__file__), '..', 'test_imgs'))
14 |
15 |
16 | def save_test_image(filename, array):
17 | Image.fromarray(array).save(filename)
18 |
19 |
20 | def compare_imgs(img, truth_filename, do_assert=True):
21 | """
22 | PROTIP: run the following to re-generate the test images:
23 |
24 | REGENERATE_TEST_IMAGES=1 pytest mujoco_py/tests/test_modder.py
25 |
26 | Note: do this in Docker so that images will work for testing.
27 | """
28 | assert isinstance(truth_filename, str)
29 | truth_filename = join(TEST_ASSET_DIR_PATH, truth_filename)
30 | if os.getenv('REGENERATE_TEST_IMAGES'):
31 | if exists(truth_filename):
32 | pre_path, ext = splitext(truth_filename)
33 | backup_path = "%s_old%s" % (pre_path, ext)
34 | move(truth_filename, backup_path)
35 | save_test_image(truth_filename, img)
36 | return 0
37 | true_img = np.asarray(Image.open(truth_filename))
38 | assert img.shape == true_img.shape
39 | hash0 = imagehash.dhash(Image.fromarray(img))
40 | hash1 = imagehash.dhash(Image.fromarray(true_img))
41 | diff = np.sum(hash0.hash != hash1.hash)
42 | if diff != 0:
43 | # If the assert fails, the best way to investigate is to run
44 | # pytest for the particular test. For example,
45 | #
46 | # pytest -k test_something_something path/to/test.py
47 | save_test_image("/tmp/img.png", img)
48 | save_test_image("/tmp/true_img.png", true_img)
49 | save_test_image("/tmp/diff_img.png", img - true_img)
50 | if do_assert:
51 | assert diff <= 1
52 | return diff
53 |
--------------------------------------------------------------------------------
/mujoco_py/utils.py:
--------------------------------------------------------------------------------
1 | import sys
2 | import os
3 | import copy
4 | from os.path import join, expanduser, exists
5 |
6 | import numpy as np
7 |
8 | MISSING_MUJOCO_MESSAGE = '''
9 | You appear to be missing MuJoCo. We expected to find the file here: {}
10 |
11 | This package only provides python bindings, the library must be installed separately.
12 |
13 | Please follow the instructions on the README to install MuJoCo
14 |
15 | https://github.com/openai/mujoco-py#install-mujoco
16 |
17 | Which can be downloaded from the website
18 |
19 | https://www.roboti.us/index.html
20 | '''
21 |
22 |
23 | def remove_empty_lines(string):
24 | lines = []
25 | for line in string.splitlines():
26 | if line.strip():
27 | lines.append(line)
28 | return "\n".join(lines)
29 |
30 |
31 | def rec_assign(node, assign):
32 | # Assigns values to node recursively.
33 | # This is neccessary to avoid overriding pointers in MuJoCo.
34 | for field in dir(node):
35 | if field.find("__") == -1 and field != 'uintptr':
36 | val = getattr(node, field)
37 | if isinstance(val, (int, bool, float, None.__class__, str)):
38 | setattr(node, field, assign[field])
39 | elif isinstance(val, np.ndarray):
40 | val[:] = assign[field][:]
41 | elif not hasattr(val, "__call__"):
42 | rec_assign(val, assign[field])
43 |
44 |
45 | def rec_copy(node):
46 | # Recursively copies object to dictionary.
47 | # Applying directly copy.deepcopy causes seg fault.
48 | ret = {}
49 | for field in dir(node):
50 | if field.find("__") == -1:
51 | val = getattr(node, field)
52 | if isinstance(val, (int, bool, float, None.__class__, str)):
53 | ret[field] = val
54 | elif isinstance(val, np.ndarray):
55 | ret[field] = copy.deepcopy(val)
56 | elif not hasattr(val, "__call__"):
57 | ret[field] = rec_copy(val)
58 | return ret
59 |
60 |
61 | def discover_mujoco():
62 | """
63 | Discovers where MuJoCo is located in the file system.
64 | Currently assumes path is in ~/.mujoco
65 |
66 | Returns:
67 | - mujoco_path (str): Path to MuJoCo 2.1 directory.
68 | """
69 | mujoco_path = os.getenv('MUJOCO_PY_MUJOCO_PATH')
70 | if not mujoco_path:
71 | mujoco_path = join(expanduser('~'), '.mujoco', 'mujoco210')
72 |
73 | # We get lots of github issues that seem to be missing these
74 | # so check that mujoco is really there and raise errors if not.
75 | if not exists(mujoco_path):
76 | message = MISSING_MUJOCO_MESSAGE.format(mujoco_path)
77 | print(message, file=sys.stderr)
78 | raise Exception(message)
79 |
80 | return mujoco_path
81 |
--------------------------------------------------------------------------------
/mujoco_py/version.py:
--------------------------------------------------------------------------------
1 | __all__ = ['__version__', 'get_version']
2 |
3 | version_info = (2, 1, 2, 14)
4 | # format:
5 | # ('mujoco_major', 'mujoco_minor', 'mujoco_py_major', 'mujoco_py_minor')
6 |
7 |
8 | def get_version():
9 | """ Returns the version as a human-format string. """
10 | return '%d.%d.%d.%d' % version_info
11 |
12 |
13 | __version__ = get_version()
14 |
--------------------------------------------------------------------------------
/pyproject.toml:
--------------------------------------------------------------------------------
1 | [build-system]
2 | requires = [
3 | "setuptools",
4 | "glfw>=1.4.0",
5 | "numpy>=1.11",
6 | "Cython>=0.27.2",
7 | "imageio>=2.1.2",
8 | "cffi>=1.10",
9 | "fasteners~=0.15"
10 | ]
11 |
--------------------------------------------------------------------------------
/requirements.dev.txt:
--------------------------------------------------------------------------------
1 | imagehash>=3.4
2 | ipdb
3 | Pillow>=4.0.0
4 | pycparser>=2.17.0
5 | pytest>=3.0.5
6 | pytest-instafail==0.3.0
7 | sphinx
8 | sphinx_rtd_theme
9 | numpydoc
10 |
--------------------------------------------------------------------------------
/requirements.txt:
--------------------------------------------------------------------------------
1 | # When updating these, you may need to also update pyproject.toml
2 | glfw>=1.4.0
3 | numpy>=1.11
4 | Cython>=0.27.2
5 | imageio>=2.1.2
6 | cffi>=1.10
7 | fasteners~=0.15
8 |
--------------------------------------------------------------------------------
/setup.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 | import os
3 |
4 | from os.path import join, dirname, realpath
5 | from setuptools import find_packages, setup
6 | from distutils.command.build import build as DistutilsBuild
7 |
8 |
9 | with open(join("mujoco_py", "version.py")) as version_file:
10 | exec(version_file.read())
11 |
12 |
13 | def read_requirements_file(filename):
14 | req_file_path = '%s/%s' % (dirname(realpath(__file__)), filename)
15 | with open(req_file_path) as f:
16 | return [line.strip() for line in f]
17 |
18 |
19 | packages = find_packages()
20 | # Ensure that we don't pollute the global namespace.
21 | for p in packages:
22 | assert p == 'mujoco_py' or p.startswith('mujoco_py.')
23 |
24 |
25 | class Build(DistutilsBuild):
26 | def run(self):
27 | os.environ['MUJOCO_PY_FORCE_REBUILD'] = 'True'
28 | os.environ['MUJOCO_PY_SKIP_ACTIVATE'] = 'True'
29 | import mujoco_py # noqa: force build
30 | DistutilsBuild.run(self)
31 |
32 |
33 | setup(
34 | name='mujoco-py',
35 | version=__version__, # noqa
36 | author='OpenAI Robotics Team',
37 | author_email='robotics@openai.com',
38 | url='https://github.com/openai/mujoco-py',
39 | packages=packages,
40 | include_package_data=True,
41 | cmdclass={'build': Build},
42 | package_dir={'mujoco_py': 'mujoco_py'},
43 | package_data={'mujoco_py': ['generated/*.so']},
44 | install_requires=read_requirements_file('requirements.txt'),
45 | tests_require=read_requirements_file('requirements.dev.txt'),
46 | python_requires='>=3.6',
47 | classifiers=[
48 | 'Programming Language :: Python :: 3',
49 | 'Programming Language :: Python :: 3.6',
50 | 'Programming Language :: Python :: 3.7',
51 | 'Programming Language :: Python :: 3 :: Only',
52 | ],
53 | )
54 |
--------------------------------------------------------------------------------
/vendor/10_nvidia.json:
--------------------------------------------------------------------------------
1 | {
2 | "file_format_version" : "1.0.0",
3 | "ICD" : {
4 | "library_path" : "libEGL_nvidia.so.0"
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/vendor/Xdummy-entrypoint:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python
2 | import argparse
3 | import os
4 | import sys
5 | import subprocess
6 |
7 | parser = argparse.ArgumentParser()
8 | args, extra_args = parser.parse_known_args()
9 | subprocess.Popen(["nohup", "Xdummy"], stdout=open('/dev/null', 'w'), stderr=open('/dev/null', 'w'))
10 | os.environ['DISPLAY'] = ':0'
11 | if not extra_args:
12 | sys.argv = ['/bin/bash']
13 | else:
14 | sys.argv = extra_args
15 | # Explicitly flush right before the exec since otherwise things might get
16 | # lost in Python's buffers around stdout/stderr (!).
17 | sys.stdout.flush()
18 | sys.stderr.flush()
19 | os.execvpe(sys.argv[0], sys.argv, os.environ)
20 |
21 |
--------------------------------------------------------------------------------
/xmls/claw.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
--------------------------------------------------------------------------------
/xmls/door.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/xmls/fetch/base_link_collision.stl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/openai/mujoco-py/a13903b82f1ab316815e63b3575526005b3b2ae1/xmls/fetch/base_link_collision.stl
--------------------------------------------------------------------------------
/xmls/fetch/bellows_link_collision.stl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/openai/mujoco-py/a13903b82f1ab316815e63b3575526005b3b2ae1/xmls/fetch/bellows_link_collision.stl
--------------------------------------------------------------------------------
/xmls/fetch/elbow_flex_link_collision.stl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/openai/mujoco-py/a13903b82f1ab316815e63b3575526005b3b2ae1/xmls/fetch/elbow_flex_link_collision.stl
--------------------------------------------------------------------------------
/xmls/fetch/estop_link.stl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/openai/mujoco-py/a13903b82f1ab316815e63b3575526005b3b2ae1/xmls/fetch/estop_link.stl
--------------------------------------------------------------------------------
/xmls/fetch/forearm_roll_link_collision.stl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/openai/mujoco-py/a13903b82f1ab316815e63b3575526005b3b2ae1/xmls/fetch/forearm_roll_link_collision.stl
--------------------------------------------------------------------------------
/xmls/fetch/gripper_link.stl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/openai/mujoco-py/a13903b82f1ab316815e63b3575526005b3b2ae1/xmls/fetch/gripper_link.stl
--------------------------------------------------------------------------------
/xmls/fetch/head_pan_link_collision.stl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/openai/mujoco-py/a13903b82f1ab316815e63b3575526005b3b2ae1/xmls/fetch/head_pan_link_collision.stl
--------------------------------------------------------------------------------
/xmls/fetch/head_tilt_link_collision.stl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/openai/mujoco-py/a13903b82f1ab316815e63b3575526005b3b2ae1/xmls/fetch/head_tilt_link_collision.stl
--------------------------------------------------------------------------------
/xmls/fetch/l_wheel_link_collision.stl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/openai/mujoco-py/a13903b82f1ab316815e63b3575526005b3b2ae1/xmls/fetch/l_wheel_link_collision.stl
--------------------------------------------------------------------------------
/xmls/fetch/laser_link.stl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/openai/mujoco-py/a13903b82f1ab316815e63b3575526005b3b2ae1/xmls/fetch/laser_link.stl
--------------------------------------------------------------------------------
/xmls/fetch/r_wheel_link_collision.stl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/openai/mujoco-py/a13903b82f1ab316815e63b3575526005b3b2ae1/xmls/fetch/r_wheel_link_collision.stl
--------------------------------------------------------------------------------
/xmls/fetch/shoulder_lift_link_collision.stl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/openai/mujoco-py/a13903b82f1ab316815e63b3575526005b3b2ae1/xmls/fetch/shoulder_lift_link_collision.stl
--------------------------------------------------------------------------------
/xmls/fetch/shoulder_pan_link_collision.stl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/openai/mujoco-py/a13903b82f1ab316815e63b3575526005b3b2ae1/xmls/fetch/shoulder_pan_link_collision.stl
--------------------------------------------------------------------------------
/xmls/fetch/torso_fixed_link.stl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/openai/mujoco-py/a13903b82f1ab316815e63b3575526005b3b2ae1/xmls/fetch/torso_fixed_link.stl
--------------------------------------------------------------------------------
/xmls/fetch/torso_lift_link_collision.stl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/openai/mujoco-py/a13903b82f1ab316815e63b3575526005b3b2ae1/xmls/fetch/torso_lift_link_collision.stl
--------------------------------------------------------------------------------
/xmls/fetch/upperarm_roll_link_collision.stl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/openai/mujoco-py/a13903b82f1ab316815e63b3575526005b3b2ae1/xmls/fetch/upperarm_roll_link_collision.stl
--------------------------------------------------------------------------------
/xmls/fetch/wrist_flex_link_collision.stl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/openai/mujoco-py/a13903b82f1ab316815e63b3575526005b3b2ae1/xmls/fetch/wrist_flex_link_collision.stl
--------------------------------------------------------------------------------
/xmls/fetch/wrist_roll_link_collision.stl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/openai/mujoco-py/a13903b82f1ab316815e63b3575526005b3b2ae1/xmls/fetch/wrist_roll_link_collision.stl
--------------------------------------------------------------------------------
/xmls/juggler.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
31 |
33 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
--------------------------------------------------------------------------------
/xmls/key.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/xmls/shelf.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
--------------------------------------------------------------------------------
/xmls/slider.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
25 |
26 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
--------------------------------------------------------------------------------
/xmls/tosser.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
25 |
27 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
--------------------------------------------------------------------------------