Mujoco KDL Wrapper  0.3.18
MuJoCo + KDL bridge for robot kinematics and dynamics
Loading...
Searching...
No Matches
ex_table_scene.py
Go to the documentation of this file.
1#!/usr/bin/env python3
2"""Table-scene example ported from src/examples/ex_table_scene.cpp.
3
4Arm + gripper on a table with free objects. The arm runs KDL gravity
5compensation and the gripper cycles open/closed. An Env on_reset hook re-homes
6the arm so the simulate-UI reset button restores the scene.
7"""
8
9from __future__ import annotations
10
11import argparse
12import math
13
14import mj_kdl_wrapper as mjk
15
16SURFACE_Z = 0.7
17HOME_POSE = [0.0, 0.2618, 3.1416, -2.2689, 0.0, 0.9599, 1.5708]
18
19
20def attachment_gripper(path: str) -> mjk.AttachmentSpec:
21 spec = mjk.AttachmentSpec()
22 spec.mjcf_path = path
23 spec.attach_to = mjk.AttachTarget(mjk.AttachKind.Site, "pinch_site")
24 spec.prefix = "g_"
25 return spec
26
27
28def table_object(path: str) -> mjk.SceneObject:
29 obj = mjk.SceneObject()
30 obj.name = "table"
31 obj.mjcf_path = path
32 obj.pos = [0.0, 0.0, SURFACE_Z]
33 obj.fixed = True
34 return obj
35
36
37def make_box(name, x, y, hx, hy, hz, color) -> mjk.SceneObject:
38 obj = mjk.SceneObject()
39 obj.name = name
40 obj.shape = mjk.Shape.BOX
41 obj.size = [hx, hy, hz]
42 obj.pos = [x, y, SURFACE_Z + hz]
43 obj.rgba = [color[0], color[1], color[2], 1.0]
44 obj.mass = 0.2
45 obj.friction = [1.0, 0.005, 0.0001]
46 return obj
47
48
49def make_sphere(name, x, y, radius, color) -> mjk.SceneObject:
50 obj = mjk.SceneObject()
51 obj.name = name
52 obj.shape = mjk.Shape.SPHERE
53 obj.size = [radius, 0.0, 0.0]
54 obj.pos = [x, y, SURFACE_Z + radius]
55 obj.rgba = [color[0], color[1], color[2], 1.0]
56 obj.mass = 0.1
57 obj.friction = [1.0, 0.005, 0.0001]
58 return obj
59
60
61def scene_objects(table_path):
62 return [
63 table_object(table_path),
64 make_box("red_cube", 0.35, 0.10, 0.03, 0.03, 0.03, (1.0, 0.2, 0.2)),
65 make_box("green_cube", 0.35, -0.10, 0.03, 0.03, 0.03, (0.2, 1.0, 0.2)),
66 make_box("blue_cube", 0.35, 0.30, 0.04, 0.04, 0.04, (0.2, 0.2, 1.0)),
67 make_sphere("orange_sphere", -0.20, 0.20, 0.035, (1.0, 0.55, 0.0)),
68 make_sphere("purple_sphere", -0.20, -0.20, 0.025, (0.7, 0.0, 0.9)),
69 ]
70
71
72def build_env(model_path: str, gripper_path: str, table_path: str) -> tuple[mjk.Env, mjk.Robot]:
73 spec = mjk.SceneSpec()
74 spec.timestep = 0.002
75 spec.add_floor = True
76 spec.add_skybox = True
77 spec.objects = scene_objects(table_path)
78 robot_spec = mjk.RobotSpec()
79 robot_spec.path = model_path
80 robot_spec.pos = [0.0, 0.0, SURFACE_Z]
81 robot_spec.attachments = [attachment_gripper(gripper_path)]
82 spec.robots = [robot_spec]
83 overview = mjk.CameraSpec()
84 overview.name = "overview"
85 overview.pos = [0.0, -0.6, 1.6]
86 overview.quat = [0.29237170472273677, 0.0, 0.0, 0.9563047559630354] # roll 34 deg
87 overview.fovy = 45.0
88 side = mjk.CameraSpec()
89 side.name = "side"
90 side.pos = [-1.0, 0.0, 1.1]
91 side.quat = [0.0, -0.5591929034707469, 0.0, 0.8290375725550416] # pitch -68 deg
92 side.fovy = 45.0
93 spec.cameras = [overview, side]
94 env = mjk.Env.build(spec)
95 tool = mjk.ToolFrameSpec()
96 tool.tool_body = "g_base"
97 tool.tcp_site = "g_pinch"
98 robot = env.create_robot("base_link", "bracelet_link", tool=tool)
99 return env, robot
100
101
102def run_loop(env: mjk.Env, robot: mjk.Robot, step_fn, *, duration: float, gui: bool) -> None:
103 if gui:
104 viewer = mjk.SimulateViewer.open(robot, "ex_table_scene.py")
105 prev = env.time()
106 try:
107 while viewer.is_running():
108 if env.time() < prev - 1e-6:
109 env.reset()
110 prev = env.time()
111 step_fn()
112 if not viewer.step():
113 break
114 viewer.pace()
115 finally:
116 viewer.close()
117 return
118 end = env.time() + duration
119 while env.time() < end:
120 step_fn()
121 robot.step()
122 robot.pace()
123
124
125def main() -> int:
126 parser = argparse.ArgumentParser()
127 parser.add_argument("--gui", action="store_true")
128 args = parser.parse_args()
129
130 env, robot = build_env(
131 mjk.menagerie.model_path("kinova_gen3", env_var="MJ_KDL_MODEL"),
132 mjk.menagerie.asset_path("robotiq_2f85/2f85.xml", env_var="MJ_KDL_GRIPPER"),
133 mjk.menagerie.asset_path("table.xml", env_var="MJ_KDL_TABLE"),
134 )
135 try:
136 robot.ctrl_mode = mjk.CtrlMode.TORQUE
137 env.on_reset = lambda ctx: robot.set_joint_pos(HOME_POSE, call_forward=False)
138 env.reset()
139
140 top = env.site_frame(mjk.scene_object_site_name(env.spec.objects[0], "table_top"))
141 print(f"table top z = {top.p.z():.3f}")
142 print(f"cameras: {' '.join(env.camera_names())}")
143
144 def step():
145 robot.update()
146 robot.jnt_trq_cmd = robot.gravity_torques(-9.81)
147 if env.has_actuator("g_fingers_actuator"):
148 env.set_actuator_ctrl(
149 "g_fingers_actuator", 255.0 if math.fmod(env.time(), 6.0) < 3.0 else 0.0
150 )
151
152 run_loop(env, robot, step, duration=1.0, gui=args.gui)
153 finally:
154 env.close()
155 return 0
156
157
158if __name__ == "__main__":
159 raise SystemExit(main())
mjk.AttachmentSpec attachment_gripper(str path)
None run_loop(mjk.Env env, mjk.Robot robot, step_fn, *, float duration, bool gui)
scene_objects(table_path)
mjk.SceneObject make_sphere(name, x, y, radius, color)
tuple[mjk.Env, mjk.Robot] build_env(str model_path, str gripper_path, str table_path)
mjk.SceneObject table_object(str path)
mjk.SceneObject make_box(name, x, y, hx, hy, hz, color)