Merge branch 'google-deepmind:main' into tendons

This commit is contained in:
Abhishek Joshi
2024-06-16 23:40:10 -05:00
committed by GitHub
134 changed files with 12574 additions and 2764 deletions
+2 -2
View File
@@ -84,7 +84,7 @@ if(NOT TARGET mujoco)
if(MUJOCO_FRAMEWORK)
message("MuJoCo framework is at ${MUJOCO_FRAMEWORK}/mujoco.framework")
set(MUJOCO_LIBRARY
${MUJOCO_FRAMEWORK}/mujoco.framework/Versions/A/libmujoco.3.1.6.dylib
${MUJOCO_FRAMEWORK}/mujoco.framework/Versions/A/libmujoco.3.1.7.dylib
)
target_compile_options(mujoco INTERFACE -F${MUJOCO_FRAMEWORK})
endif()
@@ -92,7 +92,7 @@ if(NOT TARGET mujoco)
if(NOT MUJOCO_FRAMEWORK)
find_library(
MUJOCO_LIBRARY mujoco mujoco.3.1.6 HINTS ${MUJOCO_LIBRARY_DIR} REQUIRED
MUJOCO_LIBRARY mujoco mujoco.3.1.7 HINTS ${MUJOCO_LIBRARY_DIR} REQUIRED
)
find_path(MUJOCO_INCLUDE mujoco/mujoco.h HINTS ${MUJOCO_INCLUDE_DIR} REQUIRED)
message("MuJoCo is at ${MUJOCO_LIBRARY}")
+32
View File
@@ -27,6 +27,7 @@ import numpy as np
TEST_XML = r"""
<mujoco model="test">
<compiler coordinate="local" angle="radian" eulerseq="xyz"/>
<size nkey="2"/>
<option timestep="0.002" gravity="0 0 -9.81"/>
<visual>
<global fovy="50" />
@@ -745,6 +746,37 @@ class MuJoCoBindingsTest(parameterized.TestCase):
# Expect next states to be equal.
np.testing.assert_array_equal(state1a, state1b)
def test_mj_setKeyframe(self): # pylint: disable=invalid-name
mujoco.mj_step(self.model, self.data)
# Test for invalid state spec
invalid_key = 2
expected_message = (
f'mj_setKeyframe: index must be smaller than {invalid_key} (keyframes'
' allocated in model)'
)
with self.assertRaisesWithLiteralMatch(mujoco.FatalError, expected_message):
mujoco.mj_setKeyframe(self.model, self.data, invalid_key)
valid_key = 1
time = self.data.time
qpos = self.data.qpos.copy()
qvel = self.data.qvel.copy()
act = self.data.act.copy()
mujoco.mj_setKeyframe(self.model, self.data, valid_key)
# Step, assert that time has changed.
mujoco.mj_step(self.model, self.data)
self.assertNotEqual(time, self.data.time)
# Reset to keyframe, assert that time, qpos, qvel, act are the same.
mujoco.mj_resetDataKeyframe(self.model, self.data, valid_key)
self.assertEqual(time, self.data.time)
np.testing.assert_array_equal(qpos, self.data.qpos)
np.testing.assert_array_equal(qvel, self.data.qvel)
np.testing.assert_array_equal(act, self.data.act)
def test_mj_angmomMat(self): # pylint: disable=invalid-name
self.data.qvel = np.ones(self.model.nv, np.float64)
mujoco.mj_forward(self.model, self.data)
+3
View File
@@ -302,6 +302,7 @@ PYBIND11_MODULE(_functions, pymodule) {
}
return InterceptMjErrors(::mj_setState)(m, d, state.data(), spec);
});
Def<traits::mj_setKeyframe>(pymodule);
Def<traits::mj_addContact>(pymodule);
Def<traits::mj_isPyramidal>(pymodule);
Def<traits::mj_isSparse>(pymodule);
@@ -697,6 +698,8 @@ PYBIND11_MODULE(_functions, pymodule) {
Def<traits::mju_norm3>(pymodule);
Def<traits::mju_dot3>(pymodule);
Def<traits::mju_dist3>(pymodule);
Def<traits::mju_mulMatVec3>(pymodule);
Def<traits::mju_mulMatTVec3>(pymodule);
Def<traits::mju_rotVecMat>(pymodule);
Def<traits::mju_rotVecMatT>(pymodule);
Def<traits::mju_cross>(pymodule);
+4 -4
View File
@@ -7,13 +7,13 @@
<key>CFBundleIdentifier</key>
<string>org.mujoco.mjpython</string>
<key>CFBundleVersion</key>
<string>3.1.6</string>
<string>3.1.7</string>
<key>CFBundleGetInfoString</key>
<string>3.1.6</string>
<string>3.1.7</string>
<key>CFBundleLongVersionString</key>
<string>3.1.6</string>
<string>3.1.7</string>
<key>CFBundleShortVersionString</key>
<string>3.1.6</string>
<string>3.1.7</string>
<key>CFBundleExecutable</key>
<string>mjpython</string>
<key>CFBundleIconFile</key>
+3
View File
@@ -1390,6 +1390,7 @@ PYBIND11_MODULE(_structs, m) {
});
DefineStructFunctions(mjVisualGlobal);
#define X(var) mjVisualGlobal.def_readwrite(#var, &raw::MjVisualGlobal::var)
X(orthographic);
X(fovy);
X(ipd);
X(azimuth);
@@ -2123,6 +2124,7 @@ This is useful for example when the MJB is not available as a file on disk.)"));
X(distance);
X(azimuth);
X(elevation);
X(orthographic);
#undef X
#define X(var) DefinePyArray(mjvCamera, #var, &MjvCameraWrapper::var)
@@ -2153,6 +2155,7 @@ This is useful for example when the MJB is not available as a file on disk.)"));
X(frustum_top);
X(frustum_near);
X(frustum_far);
X(orthographic);
#undef X
#define X(var) DefinePyArray(mjvGLCamera, #var, &MjvGLCameraWrapper::var)
+3 -3
View File
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
[project]
name = "mujoco"
version = "3.1.6"
version = "3.1.7"
authors = [
{name = "Google DeepMind", email = "mujoco@deepmind.com"},
]
@@ -36,9 +36,9 @@ dynamic = ["readme", "scripts"]
[project.urls]
Homepage = "https://github.com/google-deepmind/mujoco"
Documentation = "https://mujoco.readthedocs.io/en/3.1.6"
Documentation = "https://mujoco.readthedocs.io/en/3.1.7"
Repository = "https://github.com/google-deepmind/mujoco"
Changelog = "https://mujoco.readthedocs.io/en/3.1.6/changelog.html"
Changelog = "https://mujoco.readthedocs.io/en/3.1.7/changelog.html"
[tool.setuptools]
include-package-data = false
+29 -15
View File
@@ -479,8 +479,8 @@
"\"\"\"\n",
"model = mujoco.MjModel.from_xml_string(xml)\n",
"data = mujoco.MjData(model)\n",
"renderer = mujoco.Renderer(model)\n",
"\n",
"renderer = mujoco.Renderer(model)\n",
"mujoco.mj_forward(model, data)\n",
"renderer.update_scene(data)\n",
"\n",
@@ -509,6 +509,7 @@
"# Run this cell multiple times for different colors\n",
"model.geom('red_box').rgba[:3] = np.random.rand(3)\n",
"renderer.update_scene(data)\n",
"\n",
"media.show_image(renderer.render())"
]
},
@@ -545,6 +546,7 @@
" renderer.update_scene(data)\n",
" pixels = renderer.render()\n",
" frames.append(pixels)\n",
"\n",
"media.show_video(frames, fps=framerate)"
]
},
@@ -590,6 +592,7 @@
"duration = 3.8 # (seconds)\n",
"framerate = 60 # (Hz)\n",
"\n",
"# Simulate and display video.\n",
"frames = []\n",
"mujoco.mj_resetData(model, data)\n",
"while data.time < duration:\n",
@@ -599,7 +602,6 @@
" pixels = renderer.render()\n",
" frames.append(pixels)\n",
"\n",
"# Simulate and display video.\n",
"media.show_video(frames, fps=framerate)"
]
},
@@ -646,6 +648,7 @@
"model.opt.gravity = (0, 0, 10)\n",
"print('flipped gravity', model.opt.gravity)\n",
"\n",
"# Simulate and display video.\n",
"frames = []\n",
"mujoco.mj_resetData(model, data)\n",
"while data.time < duration:\n",
@@ -756,10 +759,12 @@
"</mujoco>\n",
"\"\"\"\n",
"model = mujoco.MjModel.from_xml_string(tippe_top)\n",
"renderer = mujoco.Renderer(model)\n",
"data = mujoco.MjData(model)\n",
"renderer = mujoco.Renderer(model)\n",
"\n",
"mujoco.mj_forward(model, data)\n",
"renderer.update_scene(data, camera=\"closeup\")\n",
"\n",
"media.show_image(renderer.render())"
]
},
@@ -933,10 +938,12 @@
"</mujoco>\n",
"\"\"\"\n",
"model = mujoco.MjModel.from_xml_string(chaotic_pendulum)\n",
"renderer = mujoco.Renderer(model, 480, 640)\n",
"data = mujoco.MjData(model)\n",
"renderer = mujoco.Renderer(model, 480, 640)\n",
"\n",
"mujoco.mj_forward(model, data)\n",
"renderer.update_scene(data, camera=\"fixed\")\n",
"\n",
"media.show_image(renderer.render())"
]
},
@@ -965,12 +972,10 @@
"frames = []\n",
"renderer = mujoco.Renderer(model, 240, 320)\n",
"\n",
"\n",
"# set initial state\n",
"mujoco.mj_resetData(model, data)\n",
"data.joint('root').qvel = 10\n",
"\n",
"\n",
"# simulate and record frames\n",
"frame = 0\n",
"sim_time = 0\n",
@@ -1176,14 +1181,13 @@
" ax.plot(sim_time, energy, label='timestep = {:2.2g}ms'.format(1000*dt))\n",
" ax.set_yscale('log')\n",
"\n",
"\n",
"# finalize plot\n",
"ax.set_ybound(1, 1e3)\n",
"ax.set_title('energy')\n",
"ax.set_ylabel('Joule')\n",
"ax.set_xlabel('second')\n",
"ax.legend(frameon=True, loc='lower right');\n",
"plt.tight_layout()\n"
"plt.tight_layout()"
]
},
{
@@ -1228,10 +1232,12 @@
"</mujoco>\n",
"\"\"\"\n",
"model = mujoco.MjModel.from_xml_string(free_body_MJCF)\n",
"renderer = mujoco.Renderer(model, 400, 600)\n",
"data = mujoco.MjData(model)\n",
"renderer = mujoco.Renderer(model, 400, 600)\n",
"\n",
"mujoco.mj_forward(model, data)\n",
"renderer.update_scene(data, \"fixed\")\n",
"\n",
"media.show_image(renderer.render())"
]
},
@@ -1275,7 +1281,7 @@
"mujoco.mj_resetData(model, data)\n",
"data.qvel[3:6] = 5*np.random.randn(3)\n",
"\n",
"# simulate and render\n",
"# Simulate and display video.\n",
"for i in range(n_frames):\n",
" while data.time < i/120.0: #1/4x real time\n",
" mujoco.mj_step(model, data)\n",
@@ -1283,7 +1289,6 @@
" frame = renderer.render()\n",
" frames.append(frame)\n",
"\n",
"# show video\n",
"media.show_video(frames, fps=30)"
]
},
@@ -1437,7 +1442,7 @@
"data = mujoco.MjData(model)\n",
"renderer = mujoco.Renderer(model, height, width)\n",
"\n",
"# simulate and render\n",
"# Simulate and display video.\n",
"mujoco.mj_resetData(model, data)\n",
"for i in range(n_frames):\n",
" while data.time < i/30.0:\n",
@@ -1445,6 +1450,7 @@
" renderer.update_scene(data, \"y\")\n",
" frame = renderer.render()\n",
" frames.append(frame)\n",
"\n",
"media.show_video(frames, fps=30)"
]
},
@@ -1513,10 +1519,12 @@
"</mujoco>\n",
"\"\"\"\n",
"model = mujoco.MjModel.from_xml_string(MJCF)\n",
"renderer = mujoco.Renderer(model, 480, 480)\n",
"data = mujoco.MjData(model)\n",
"renderer = mujoco.Renderer(model, 480, 480)\n",
"\n",
"mujoco.mj_forward(model, data)\n",
"renderer.update_scene(data, \"fixed\")\n",
"\n",
"media.show_image(renderer.render())\n"
]
},
@@ -1551,7 +1559,7 @@
"mujoco.mj_resetData(model, data)\n",
"data.ctrl = 20\n",
"\n",
"# simulate and render\n",
"# Simulate and display video.\n",
"for i in range(n_frames):\n",
" while data.time < i/fps:\n",
" mujoco.mj_step(model, data)\n",
@@ -1783,10 +1791,10 @@
"outputs": [],
"source": [
"#@title Project from world to camera coordinates {vertical-output: true}\n",
"\n",
"# reset the scene\n",
"renderer.update_scene(data)\n",
"\n",
"\n",
"# Get the world coordinates of the box corners\n",
"box_pos = data.geom_xpos[model.geom('red_box').id]\n",
"box_mat = data.geom_xmat[model.geom('red_box').id].reshape(3, 3)\n",
@@ -1897,6 +1905,7 @@
" modify_scene(renderer.scene)\n",
" pixels = renderer.render()\n",
" frames.append(pixels)\n",
"\n",
"media.show_video(frames, fps=framerate)"
]
},
@@ -1923,6 +1932,7 @@
"outputs": [],
"source": [
"#@title Load the \"dominos\" model\n",
"\n",
"dominos_xml = \"\"\"\n",
"<mujoco>\n",
" <asset>\n",
@@ -2022,6 +2032,7 @@
"outputs": [],
"source": [
"#@title Render from fixed camera\n",
"\n",
"duration = 2.5 # (seconds)\n",
"framerate = 60 # (Hz)\n",
"\n",
@@ -2034,6 +2045,7 @@
" renderer.update_scene(data, camera='top')\n",
" pixels = renderer.render()\n",
" frames.append(pixels)\n",
"\n",
"media.show_video(frames, fps=framerate)"
]
},
@@ -2047,6 +2059,7 @@
"outputs": [],
"source": [
"#@title Render from moving camera\n",
"\n",
"duration = 3 # (seconds)\n",
"\n",
"# find time when box is thrown (speed > 2cm/s)\n",
@@ -2109,6 +2122,7 @@
" renderer.update_scene(data, cam)\n",
" pixels = renderer.render()\n",
" frames.append(pixels)\n",
"\n",
"media.show_video(frames, fps=framerate)"
]
}