|
477 | 477 | "ax.set_axis_off()" |
478 | 478 | ] |
479 | 479 | }, |
| 480 | + { |
| 481 | + "cell_type": "code", |
| 482 | + "execution_count": null, |
| 483 | + "metadata": { |
| 484 | + "id": "R_jkaXd_9Eiu" |
| 485 | + }, |
| 486 | + "outputs": [], |
| 487 | + "source": [ |
| 488 | + "#@title Adding arbitrary 3D geometry {vertical-output: true}\n", |
| 489 | + "\n", |
| 490 | + "def get_geom_speed(physics, geom_name):\n", |
| 491 | + " \"\"\"Returns the speed of a geom.\"\"\"\n", |
| 492 | + " geom_vel = np.zeros(6)\n", |
| 493 | + " geom_type = mujoco.mjtObj.mjOBJ_GEOM\n", |
| 494 | + " geom_id = mujoco.mj_name2id(physics.model.ptr, geom_type, geom_name)\n", |
| 495 | + " mujoco.mj_objectVelocity(physics.model.ptr, physics.data.ptr,\n", |
| 496 | + " geom_type, geom_id, geom_vel, 0)\n", |
| 497 | + " return np.linalg.norm(geom_vel)\n", |
| 498 | + "\n", |
| 499 | + "def add_visual_capsule(scene, point1, point2, radius, rgba):\n", |
| 500 | + " \"\"\"Adds one capsule to an mjvScene.\"\"\"\n", |
| 501 | + " if scene.ngeom \u003e= scene.maxgeom:\n", |
| 502 | + " return\n", |
| 503 | + " scene.ngeom += 1 # increment ngeom\n", |
| 504 | + " # initialise a new capsule, add it to the scene using mjv_makeConnector\n", |
| 505 | + " mujoco.mjv_initGeom(scene.geoms[scene.ngeom-1],\n", |
| 506 | + " mujoco.mjtGeom.mjGEOM_CAPSULE, np.zeros(3),\n", |
| 507 | + " np.zeros(3), np.zeros(9), rgba.astype(np.float32))\n", |
| 508 | + " mujoco.mjv_makeConnector(scene.geoms[scene.ngeom-1],\n", |
| 509 | + " mujoco.mjtGeom.mjGEOM_CAPSULE, radius,\n", |
| 510 | + " point1[0], point1[1], point1[2],\n", |
| 511 | + " point2[0], point2[1], point2[2])\n", |
| 512 | + "\n", |
| 513 | + " # traces of time, position and speed\n", |
| 514 | + "time = []\n", |
| 515 | + "position = []\n", |
| 516 | + "speed = []\n", |
| 517 | + "offset = physics.model.jnt_axis[0]/8 # offset along the joint axis\n", |
| 518 | + "\n", |
| 519 | + "def scene_callback(physics, scn):\n", |
| 520 | + " \"\"\"Draw position trace, speed modifies width and colours.\"\"\"\n", |
| 521 | + " if len(position) \u003e 1:\n", |
| 522 | + " for i in range(len(position)-1):\n", |
| 523 | + " rgba=np.array((np.clip(speed[i]/10, 0, 1),\n", |
| 524 | + " np.clip(1-speed[i]/10, 0, 1),\n", |
| 525 | + " .5, 1.))\n", |
| 526 | + " radius=.003*(1+speed[i])\n", |
| 527 | + " point1 = position[i] + offset*time[i]\n", |
| 528 | + " point2 = position[i+1] + offset*time[i+1]\n", |
| 529 | + " add_visual_capsule(scn, point1, point2, radius, rgba)\n", |
| 530 | + "\n", |
| 531 | + "duration = 6 # (seconds)\n", |
| 532 | + "framerate = 30 # (Hz)\n", |
| 533 | + "\n", |
| 534 | + "# Simulate and display video.\n", |
| 535 | + "frames = []\n", |
| 536 | + "physics.reset() # Reset state and time\n", |
| 537 | + "while physics.data.time \u003c duration:\n", |
| 538 | + " # append data to the traces\n", |
| 539 | + " position.append(physics.named.data.geom_xpos[\"green_sphere\"].copy())\n", |
| 540 | + " time.append(physics.data.time)\n", |
| 541 | + " speed.append(get_geom_speed(physics, \"green_sphere\"))\n", |
| 542 | + " physics.step()\n", |
| 543 | + " if len(frames) \u003c physics.data.time * framerate:\n", |
| 544 | + " camera = mujoco.Camera(physics, max_geom=10000,\n", |
| 545 | + " scene_callback=scene_callback)\n", |
| 546 | + " pixels = camera.render()\n", |
| 547 | + " frames.append(pixels)\n", |
| 548 | + "display_video(frames, framerate)" |
| 549 | + ] |
| 550 | + }, |
480 | 551 | { |
481 | 552 | "cell_type": "markdown", |
482 | 553 | "metadata": { |
|
0 commit comments