Add examples of scaling assets into tutorial notebook. Fixes #2476
PiperOrigin-RevId: 760617809 Change-Id: I86d4fadb473cf8ad9bcfd058567551c431f2bf31
This commit is contained in:
committed by
Copybara-Service
parent
84d658a5ad
commit
6c201d3e1c
+397
-23
@@ -124,12 +124,12 @@
|
||||
" highlighted = pygments.highlight(xml_string, lexer, formatter)\n",
|
||||
" display(HTML(f\"<style>{formatter.get_style_defs()}</style>{highlighted}\"))\n",
|
||||
"\n",
|
||||
"def render(model, data=None, height=300):\n",
|
||||
"def render(model, data=None, height=300, camera=-1):\n",
|
||||
" if data is None:\n",
|
||||
" data = mj.MjData(model)\n",
|
||||
" with mj.Renderer(model, 480, 640) as renderer:\n",
|
||||
" mj.mj_forward(model, data)\n",
|
||||
" renderer.update_scene(data)\n",
|
||||
" renderer.update_scene(data, camera)\n",
|
||||
" media.show_image(renderer.render(), height=height)"
|
||||
]
|
||||
},
|
||||
@@ -148,6 +148,7 @@
|
||||
"cell_type": "code",
|
||||
"execution_count": 0,
|
||||
"metadata": {
|
||||
"cellView": "form",
|
||||
"id": "oummB7I7EfSq"
|
||||
},
|
||||
"outputs": [],
|
||||
@@ -987,7 +988,7 @@
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"#@title Six Creatures on a floor.{vertical-output: true}\n",
|
||||
"#@title Six Creatures on a floor {vertical-output: true}\n",
|
||||
"\n",
|
||||
"arena = mj.MjSpec()\n",
|
||||
"\n",
|
||||
@@ -1046,7 +1047,7 @@
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"#@title Video of the movement{vertical-output: true}\n",
|
||||
"#@title Video of the movement {vertical-output: true}\n",
|
||||
"\n",
|
||||
"data = mj.MjData(model)\n",
|
||||
"duration = 10 # (Seconds)\n",
|
||||
@@ -1094,7 +1095,7 @@
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"#@title Movement trajectories{vertical-output: true}\n",
|
||||
"#@title Movement trajectories {vertical-output: true}\n",
|
||||
"\n",
|
||||
"creature_colors = [torso.rgba[:3] for torso in torsos_model]\n",
|
||||
"fig, ax = plt.subplots(figsize=(4, 4))\n",
|
||||
@@ -1120,6 +1121,57 @@
|
||||
"# Model editing"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 0,
|
||||
"metadata": {
|
||||
"cellView": "form",
|
||||
"id": "m4sppBqvf7yd"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# @title Get resources\n",
|
||||
"\n",
|
||||
"# Get Models\n",
|
||||
"print('Getting MuJoCo humanoid XML description from GitHub:')\n",
|
||||
"!git clone https://github.com/google-deepmind/mujoco\n",
|
||||
"humanoid_file = 'mujoco/model/humanoid/humanoid.xml'\n",
|
||||
"humanoid100_file = 'mujoco/model/humanoid/humanoid100.xml'\n",
|
||||
"print('Getting MuJoCo Fly and Franka XML description from GitHub:')\n",
|
||||
"!git clone https://github.com/google-deepmind/mujoco_menagerie\n",
|
||||
"fly_file = 'mujoco_menagerie/flybody/fruitfly.xml'\n",
|
||||
"franka_file = 'mujoco_menagerie/franka_fr3/fr3.xml'\n",
|
||||
"\n",
|
||||
"# Camera options\n",
|
||||
"cam = mj.MjvCamera()\n",
|
||||
"mj.mjv_defaultCamera(cam)\n",
|
||||
"cam.elevation = -10\n",
|
||||
"cam.lookat = [0, 0, 1]\n",
|
||||
"cam.distance = 4\n",
|
||||
"cam.azimuth = 135\n",
|
||||
"\n",
|
||||
"# Arena\n",
|
||||
"arena_xml = \"\"\"\n",
|
||||
"<mujoco>\n",
|
||||
" <visual>\n",
|
||||
" <headlight diffuse=\".5 .5 .5\" specular=\"1 1 1\"/>\n",
|
||||
" <global offwidth=\"2048\" offheight=\"1536\"/>\n",
|
||||
" <quality shadowsize=\"8192\"/>\n",
|
||||
" </visual>\n",
|
||||
"\n",
|
||||
" <asset>\n",
|
||||
" <texture type=\"skybox\" builtin=\"gradient\" rgb1=\"1 1 1\" rgb2=\"1 1 1\" width=\"10\" height=\"10\"/>\n",
|
||||
" <texture type=\"2d\" name=\"groundplane\" builtin=\"checker\" mark=\"edge\" rgb1=\"1 1 1\" rgb2=\"1 1 1\" markrgb=\"0 0 0\" width=\"400\" height=\"400\"/>\n",
|
||||
" <material name=\"groundplane\" texture=\"groundplane\" texrepeat=\"45 45\" reflectance=\"0\"/>\n",
|
||||
" </asset>\n",
|
||||
"\n",
|
||||
" <worldbody>\n",
|
||||
" <geom name=\"floor\" size=\"10 10 0.1\" type=\"plane\" material=\"groundplane\"/>\n",
|
||||
" </worldbody>\n",
|
||||
"</mujoco>\n",
|
||||
"\"\"\"\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
@@ -1140,13 +1192,7 @@
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"#@title Traversing the spec.{vertical-output: true}\n",
|
||||
"\n",
|
||||
"# Get MuJoCo's humanoid model.\n",
|
||||
"print('Getting MuJoCo humanoid XML description from GitHub:')\n",
|
||||
"!git clone https://github.com/google-deepmind/mujoco\n",
|
||||
"humanoid_file = 'mujoco/model/humanoid/humanoid.xml'\n",
|
||||
"humanoid100_file = 'mujoco/model/humanoid/humanoid100.xml'\n",
|
||||
"#@title Traversing the spec {vertical-output: true}\n",
|
||||
"\n",
|
||||
"spec = mj.MjSpec.from_file(humanoid_file)\n",
|
||||
"\n",
|
||||
@@ -1183,7 +1229,7 @@
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"#@title Model re-compilation with state preservation.{vertical-output: true}\n",
|
||||
"#@title Model re-compilation with state preservation {vertical-output: true}\n",
|
||||
"\n",
|
||||
"spec = mj.MjSpec.from_file(humanoid100_file)\n",
|
||||
"model = spec.compile()\n",
|
||||
@@ -1239,7 +1285,7 @@
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"#@title Humanoid model.{vertical-output: true}\n",
|
||||
"#@title Humanoid model {vertical-output: true}\n",
|
||||
"\n",
|
||||
"spec = mj.MjSpec.from_file(humanoid_file)\n",
|
||||
"\n",
|
||||
@@ -1264,7 +1310,7 @@
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"#@title Humanoid with arms replaced by legs.{vertical-output: true}\n",
|
||||
"#@title Humanoid with arms replaced by legs {vertical-output: true}\n",
|
||||
"\n",
|
||||
"spec = mj.MjSpec.from_file(humanoid_file)\n",
|
||||
"spec.copy_during_attach = True\n",
|
||||
@@ -1309,11 +1355,7 @@
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"#@title Humanoid with Franka arm.{vertical-output: true}\n",
|
||||
"\n",
|
||||
"# Get Franka arm from the MuJoCo Menagerie.\n",
|
||||
"!git clone https://github.com/google-deepmind/mujoco_menagerie\n",
|
||||
"franka_file = 'mujoco_menagerie/franka_fr3/fr3.xml'\n",
|
||||
"#@title Humanoid with Franka arm {vertical-output: true}\n",
|
||||
"\n",
|
||||
"spec = mj.MjSpec.from_file(humanoid_file)\n",
|
||||
"franka = mj.MjSpec.from_file(franka_file)\n",
|
||||
@@ -1350,11 +1392,12 @@
|
||||
"cell_type": "code",
|
||||
"execution_count": 0,
|
||||
"metadata": {
|
||||
"cellView": "form",
|
||||
"id": "50lOgJ7mQ2bV"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"#@title Imported actuators.{vertical-output: true}\n",
|
||||
"#@title Imported actuators {vertical-output: true}\n",
|
||||
"\n",
|
||||
"for actuator in spec.actuators:\n",
|
||||
" print(actuator.name)"
|
||||
@@ -1377,7 +1420,7 @@
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"#@title Humanoid with randomized heads and arm poses.{vertical-output: true}\n",
|
||||
"#@title Humanoid with randomized heads and arm poses {vertical-output: true}\n",
|
||||
"\n",
|
||||
"humanoid = mj.MjSpec.from_file(humanoid_file)\n",
|
||||
"spec = mj.MjSpec()\n",
|
||||
@@ -1412,13 +1455,344 @@
|
||||
"model = spec.compile()\n",
|
||||
"render(model, height=400)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "iXgYCVzEWFTU"
|
||||
},
|
||||
"source": [
|
||||
"## Model scaling"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 0,
|
||||
"metadata": {
|
||||
"id": "-hSJKyH4A2VY"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"#@title Uniformly scale humanoid {vertical-output: true}\n",
|
||||
"\n",
|
||||
"def scale_spec(spec, scale):\n",
|
||||
" scaled_spec = spec.copy()\n",
|
||||
" # Traverse the kinematic tree, scaling all geoms\n",
|
||||
" def scale_bodies(parent, scale=1.0):\n",
|
||||
" body = parent.first_body()\n",
|
||||
" while body:\n",
|
||||
" if body.pos is not None:\n",
|
||||
" body.pos = body.pos * scale\n",
|
||||
" for geom in body.geoms:\n",
|
||||
" geom.fromto = geom.fromto * scale\n",
|
||||
" geom.size = geom.size * scale\n",
|
||||
" if geom.pos is not None:\n",
|
||||
" geom.pos = geom.pos * scale\n",
|
||||
" scale_bodies(body, scale)\n",
|
||||
" body = parent.next_body(body)\n",
|
||||
"\n",
|
||||
" scale_bodies(scaled_spec.body('world'), scale)\n",
|
||||
" return scaled_spec\n",
|
||||
"\n",
|
||||
"spec = mj.MjSpec.from_string(arena_xml)\n",
|
||||
"humanoid = mj.MjSpec.from_file(humanoid_file)\n",
|
||||
"small_humanoid = scale_spec(humanoid, 0.75)\n",
|
||||
"large_humanoid = scale_spec(humanoid, 1.25)\n",
|
||||
"\n",
|
||||
"# Create a line-up of humanoids\n",
|
||||
"frame = spec.worldbody.add_frame(pos=[-1, 0, 0],\n",
|
||||
" quat=[-np.sqrt(2)/2, 0, 0, np.sqrt(2) / 2])\n",
|
||||
"frame.attach_body(humanoid.body('torso'), str(0))\n",
|
||||
"\n",
|
||||
"frame = spec.worldbody.add_frame(pos=[0, 0, 0],\n",
|
||||
" quat=[-np.sqrt(2)/2, 0, 0, np.sqrt(2) / 2])\n",
|
||||
"frame.attach_body(small_humanoid.body('torso'), str(1))\n",
|
||||
"\n",
|
||||
"frame = spec.worldbody.add_frame(pos=[1, 0, 0],\n",
|
||||
" quat=[-np.sqrt(2)/2, 0, 0, np.sqrt(2) / 2] )\n",
|
||||
"frame.attach_body(large_humanoid.body('torso'), str(2))\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"spec.worldbody.add_light(mode=mj.mjtCamLight.mjCAMLIGHT_TARGETBODYCOM,\n",
|
||||
" targetbody='1torso', diffuse=[.8, .8, .8],\n",
|
||||
" specular=[0.3, 0.3, 0.3], pos=[0, -6, 4], cutoff=30)\n",
|
||||
"model = spec.compile()\n",
|
||||
"render(model, height=400, camera=cam)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "tBH5vmqJXleD"
|
||||
},
|
||||
"source": [
|
||||
"We can scale the size of a model by traversing the kinematic tree and applying the the scale to the relevant geoms. Above we can see humanoids of three different sizes."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 0,
|
||||
"metadata": {
|
||||
"id": "cV4tkG6siFQp"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# @title Scaling actuator forces {vertical-output: true}\n",
|
||||
"\n",
|
||||
"def scale_spec(spec, scale, scale_actuators=False):\n",
|
||||
" scaled_spec = spec.copy()\n",
|
||||
" # Traverse the kinematic tree, scaling all geoms\n",
|
||||
" def scale_bodies(parent, scale=1.0):\n",
|
||||
" body = parent.first_body()\n",
|
||||
" while body:\n",
|
||||
" if body.pos is not None:\n",
|
||||
" body.pos = body.pos * scale\n",
|
||||
" for geom in body.geoms:\n",
|
||||
" geom.fromto = geom.fromto * scale\n",
|
||||
" geom.size = geom.size * scale\n",
|
||||
" if geom.pos is not None:\n",
|
||||
" geom.pos = geom.pos * scale\n",
|
||||
" scale_bodies(body, scale)\n",
|
||||
" body = parent.next_body(body)\n",
|
||||
"\n",
|
||||
" if scale_actuators:\n",
|
||||
" # scale gear\n",
|
||||
" for actuator in scaled_spec.actuators:\n",
|
||||
" # scale the actuator gear by (scale ** 2),\n",
|
||||
" # this is because muscle force-generating capacity\n",
|
||||
" # scales with the cross-sectional area of the muscle\n",
|
||||
" actuator.gear = actuator.gear * scale * scale\n",
|
||||
"\n",
|
||||
" # scale the z-position of the humanoid for all keypoints\n",
|
||||
" for keypoint in scaled_spec.keys:\n",
|
||||
" qpos = keypoint.qpos\n",
|
||||
" qpos[2] = qpos[2] * scale\n",
|
||||
" keypoint.qpos = qpos\n",
|
||||
" keypoint.qpos[2] = keypoint.qpos[2] * scale\n",
|
||||
"\n",
|
||||
" scale_bodies(scaled_spec.body('world'), scale)\n",
|
||||
" return scaled_spec\n",
|
||||
"\n",
|
||||
"# Create specs\n",
|
||||
"scale = 0.6\n",
|
||||
"spec = mj.MjSpec.from_string(arena_xml)\n",
|
||||
"humanoid = mj.MjSpec.from_file(humanoid_file)\n",
|
||||
"small_humanoid = scale_spec(humanoid, scale)\n",
|
||||
"small_humanoid_actuators_scaled = scale_spec(humanoid, scale, True)\n",
|
||||
"\n",
|
||||
"# Create a line-up of humanoids\n",
|
||||
"squat_qpos = []\n",
|
||||
"\n",
|
||||
"# Add unscaled humanoid\n",
|
||||
"frame = spec.worldbody.add_frame(pos=[-1, 0, 0],\n",
|
||||
" quat=[-np.sqrt(2)/2, 0, 0, np.sqrt(2) / 2])\n",
|
||||
"frame.attach_body(humanoid.body('torso'), str(0))\n",
|
||||
"# Record squat pose\n",
|
||||
"humanoid_squat = humanoid.key('squat').qpos\n",
|
||||
"humanoid_squat[:2] = frame.pos[:2]\n",
|
||||
"humanoid_squat[3:7] = frame.quat\n",
|
||||
"squat_qpos.append(humanoid_squat)\n",
|
||||
"\n",
|
||||
"# Add small humanoid\n",
|
||||
"frame = spec.worldbody.add_frame(pos=[0, 0, 0],\n",
|
||||
" quat=[-np.sqrt(2)/2, 0, 0, np.sqrt(2) / 2])\n",
|
||||
"frame.attach_body(small_humanoid.body('torso'), str(1))\n",
|
||||
"# Record squat pose\n",
|
||||
"humanoid_squat = small_humanoid.key('squat').qpos\n",
|
||||
"humanoid_squat[:2] = frame.pos[:2]\n",
|
||||
"humanoid_squat[3:7] = frame.quat\n",
|
||||
"squat_qpos.append(humanoid_squat)\n",
|
||||
"\n",
|
||||
"# Add small humanoid with scaled actuators\n",
|
||||
"frame = spec.worldbody.add_frame(pos=[1, 0, 0],\n",
|
||||
" quat=[-np.sqrt(2)/2, 0, 0, np.sqrt(2) / 2] )\n",
|
||||
"frame.attach_body(small_humanoid_actuators_scaled.body('torso'), str(2))\n",
|
||||
"# Record squat pose\n",
|
||||
"humanoid_squat = small_humanoid_actuators_scaled.key('squat').qpos\n",
|
||||
"humanoid_squat[:2] = frame.pos[:2]\n",
|
||||
"humanoid_squat[3:7] = frame.quat\n",
|
||||
"squat_qpos.append(humanoid_squat)\n",
|
||||
"squat_qpos = np.concatenate(squat_qpos)\n",
|
||||
"\n",
|
||||
"spec.worldbody.add_light(mode=mj.mjtCamLight.mjCAMLIGHT_TARGETBODYCOM,\n",
|
||||
" targetbody='1torso', diffuse=[.8, .8, .8],\n",
|
||||
" specular=[0.3, 0.3, 0.3], pos=[0, -6, 4], cutoff=30)\n",
|
||||
"model = spec.compile()\n",
|
||||
"\n",
|
||||
"# Initialize to squat position\n",
|
||||
"data = mj.MjData(model)\n",
|
||||
"data.qpos = squat_qpos\n",
|
||||
"\n",
|
||||
"# jumping motion\n",
|
||||
"u_t = lambda t: 10.0 * t / duration\n",
|
||||
"\n",
|
||||
"# Simulate and display video.\n",
|
||||
"duration = 2 # (seconds)\n",
|
||||
"framerate = 30 # (Hz)\n",
|
||||
"frames = []\n",
|
||||
"\n",
|
||||
"with mj.Renderer(model, 480, 640) as renderer:\n",
|
||||
" while data.time < duration:\n",
|
||||
" data.ctrl = u_t(data.time)\n",
|
||||
" mj.mj_step(model, data)\n",
|
||||
" if len(frames) < data.time * framerate:\n",
|
||||
" renderer.update_scene(data, camera=cam)\n",
|
||||
" pixels = renderer.render()\n",
|
||||
" frames.append(pixels)\n",
|
||||
"\n",
|
||||
"media.show_video(frames, fps=framerate, height=400)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "ZSOra3S2YpIB"
|
||||
},
|
||||
"source": [
|
||||
"We can also apply scaling to the actuators. In the humanoid case, scaling the geoms without scaling the `gear` parameter for the actuators results in a humanoid that can jump higher proportional to its size."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 0,
|
||||
"metadata": {
|
||||
"id": "9IuwQQ0F2ddA"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# @title Long-limbed humanoid {vertical-output: true}\n",
|
||||
"\n",
|
||||
"def scale_spec(spec, scale):\n",
|
||||
" scaled_spec = spec.copy()\n",
|
||||
" # Traverse the kinematic tree, scaling all geoms\n",
|
||||
" def scale_bodies(parent, scale=1.0):\n",
|
||||
" if parent is not None:\n",
|
||||
" for geom in parent.geoms:\n",
|
||||
" # Only scale fromto, not size to scale length of capsules\n",
|
||||
" geom.fromto = geom.fromto * scale\n",
|
||||
" if geom.pos is not None:\n",
|
||||
" geom.pos = geom.pos * scale\n",
|
||||
" body = parent.first_body()\n",
|
||||
" while body:\n",
|
||||
" if body.pos is not None:\n",
|
||||
" body.pos = body.pos * scale\n",
|
||||
" scale_bodies(body, scale)\n",
|
||||
" body = parent.next_body(body)\n",
|
||||
"\n",
|
||||
" # Scale all the limbs\n",
|
||||
" scale_bodies(scaled_spec.body('upper_arm_right'), scale)\n",
|
||||
" scale_bodies(scaled_spec.body('upper_arm_left'), scale)\n",
|
||||
" scale_bodies(scaled_spec.body('thigh_right'), scale)\n",
|
||||
" scale_bodies(scaled_spec.body('thigh_left'), scale)\n",
|
||||
" return scaled_spec\n",
|
||||
"\n",
|
||||
"spec = mj.MjSpec.from_string(arena_xml)\n",
|
||||
"humanoid = mj.MjSpec.from_file(humanoid_file)\n",
|
||||
"small_humanoid = scale_spec(humanoid, 1.25)\n",
|
||||
"large_humanoid = scale_spec(humanoid, 2)\n",
|
||||
"\n",
|
||||
"# Create a line-up of humanoids by attaching\n",
|
||||
"frame = spec.worldbody.add_frame(pos=[-1, 0, 0],\n",
|
||||
" quat=[-np.sqrt(2)/2, 0, 0, np.sqrt(2) / 2])\n",
|
||||
"frame.attach_body(humanoid.body('torso'), str(0), str(0))\n",
|
||||
"\n",
|
||||
"frame = spec.worldbody.add_frame(pos=[0, 0, 0.2],\n",
|
||||
" quat=[-np.sqrt(2)/2, 0, 0, np.sqrt(2) / 2])\n",
|
||||
"frame.attach_body(small_humanoid.body('torso'), str(0), str(1))\n",
|
||||
"\n",
|
||||
"frame = spec.worldbody.add_frame(pos=[1, 0, 0.8],\n",
|
||||
" quat=[-np.sqrt(2)/2, 0, 0, np.sqrt(2) / 2] )\n",
|
||||
"frame.attach_body(large_humanoid.body('torso'), str(0), str(2))\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"spec.worldbody.add_light(mode=mj.mjtCamLight.mjCAMLIGHT_TARGETBODYCOM,\n",
|
||||
" targetbody='0torso1', diffuse=[.8, .8, .8],\n",
|
||||
" specular=[0.3, 0.3, 0.3], pos=[0, -6, 4], cutoff=30)\n",
|
||||
"model = spec.compile()\n",
|
||||
"\n",
|
||||
"# camera options\n",
|
||||
"render(model, height=400, camera=cam)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "D2DrPBvBZjI0"
|
||||
},
|
||||
"source": [
|
||||
"We can also apply scaling to the model non-uniformly. In this instance we scale the humanoid to have long limbs, by only applying the scale to the length of the capsule geoms for the arms, legs and feet."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 0,
|
||||
"metadata": {
|
||||
"id": "1G8VO45v2ddA"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# @title Meshes {vertical-output: true}\n",
|
||||
"\n",
|
||||
"def scale_spec(spec, scale):\n",
|
||||
" scaled_spec = spec.copy()\n",
|
||||
" # scale all meshes\n",
|
||||
" for mesh in scaled_spec.meshes:\n",
|
||||
" if mesh.scale is None:\n",
|
||||
" mesh.scale = np.ones(3)\n",
|
||||
" mesh.scale = mesh.scale * scale\n",
|
||||
"\n",
|
||||
" # Traverse the kinematic tree\n",
|
||||
" def scale_bodies(parent, scale=1.0):\n",
|
||||
" if parent is not None:\n",
|
||||
" for geom in parent.geoms:\n",
|
||||
" if geom.pos is not None:\n",
|
||||
" geom.pos = geom.pos * scale\n",
|
||||
" body = parent.first_body()\n",
|
||||
" while body:\n",
|
||||
" if body.pos is not None:\n",
|
||||
" body.pos = body.pos * scale\n",
|
||||
" scale_bodies(body, scale)\n",
|
||||
" body = parent.next_body(body)\n",
|
||||
"\n",
|
||||
" # Scale all the limbs\n",
|
||||
" scale_bodies(scaled_spec.body('world'), scale)\n",
|
||||
"\n",
|
||||
" return scaled_spec\n",
|
||||
"\n",
|
||||
"spec = mj.MjSpec.from_string(arena_xml)\n",
|
||||
"fly = mj.MjSpec.from_file(fly_file)\n",
|
||||
"# Remove lights from fly so they are not duplicated in line-up\n",
|
||||
"for light in fly.lights:\n",
|
||||
" light.delete()\n",
|
||||
"\n",
|
||||
"small_fly = scale_spec(fly, 1.25)\n",
|
||||
"large_fly = scale_spec(fly, 2)\n",
|
||||
"\n",
|
||||
"# Create a line-up of flys by attaching\n",
|
||||
"frame = spec.worldbody.add_frame(pos=[-1, 0, 0.25],\n",
|
||||
" quat=[-np.sqrt(2)/2, 0, 0, np.sqrt(2) / 2])\n",
|
||||
"frame.attach_body(fly.body('thorax'), str(0), str(0))\n",
|
||||
"\n",
|
||||
"frame = spec.worldbody.add_frame(pos=[0, 0, 0.25],\n",
|
||||
" quat=[-np.sqrt(2)/2, 0, 0, np.sqrt(2) / 2])\n",
|
||||
"frame.attach_body(small_fly.body('thorax'), str(0), str(1))\n",
|
||||
"\n",
|
||||
"frame = spec.worldbody.add_frame(pos=[1, 0, 0.25],\n",
|
||||
" quat=[-np.sqrt(2)/2, 0, 0, np.sqrt(2) / 2] )\n",
|
||||
"frame.attach_body(large_fly.body('thorax'), str(0), str(2))\n",
|
||||
"\n",
|
||||
"spec.worldbody.add_light(mode=mj.mjtCamLight.mjCAMLIGHT_TARGETBODYCOM,\n",
|
||||
" targetbody='0thorax1', diffuse=[.8, .8, .8],\n",
|
||||
" specular=[0.3, 0.3, 0.3], pos=[0, -6, 4], cutoff=30)\n",
|
||||
"model = spec.compile()\n",
|
||||
"render(model, height=400, camera=cam)\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"accelerator": "GPU",
|
||||
"colab": {
|
||||
"collapsed_sections": [
|
||||
"sJFuNetilv4m",
|
||||
"yXY7HGfVsVlo"
|
||||
],
|
||||
"gpuClass": "premium",
|
||||
|
||||
Reference in New Issue
Block a user