Merge branch 'google-deepmind:main' into tendons
This commit is contained in:
@@ -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}")
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
@@ -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)"
|
||||
]
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user