16HOME = [0.0, 0.2618, 3.1416, -2.2689, 0.0, 0.9599, 1.5708]
17KP = [100.0, 200.0, 100.0, 200.0, 100.0, 200.0, 100.0]
18KD = [20.0, 28.0, 20.0, 28.0, 20.0, 28.0, 20.0]
28 table = mjk.SceneObject()
30 table.mjcf_path = mjk.menagerie.asset_path(
"table.xml", env_var=
"MJ_KDL_TABLE")
31 table.pos = [0.0, 0.0, SURFACE_Z]
33 cube = mjk.SceneObject()
35 cube.shape = mjk.Shape.BOX
36 cube.size = [0.02, 0.02, 0.02]
37 cube.pos = CUBE_START[:]
38 cube.rgba = [0.1, 0.35, 1.0, 1.0]
40 cube.friction = [1.0, 0.005, 0.0001]
42 attach = mjk.AttachmentSpec()
43 attach.mjcf_path = mjk.menagerie.asset_path(
"robotiq_2f85/2f85.xml", env_var=
"MJ_KDL_GRIPPER")
44 attach.attach_to = mjk.AttachTarget(mjk.AttachKind.Site,
"pinch_site")
46 spec = mjk.SceneSpec()
49 spec.add_skybox =
True
50 spec.objects = [table, cube]
51 robot_spec = mjk.RobotSpec()
52 robot_spec.path = mjk.menagerie.model_path(
"kinova_gen3", env_var=
"MJ_KDL_MODEL")
53 robot_spec.pos = [0.0, 0.0, SURFACE_Z]
54 robot_spec.attachments = [attach]
55 spec.robots = [robot_spec]
56 env = mjk.Env.build(spec)
57 tool = mjk.ToolFrameSpec()
58 tool.tool_body =
"g_base"
59 tool.tcp_site =
"g_pinch"
60 robot = env.create_robot(
"base_link",
"bracelet_link", tool=tool)
75def solve_position_ik(chain: kdl.Chain, seed_values: list[float], target: kdl.Vector) -> list[float]:
76 fk = kdl.ChainFkSolverPos_recursive(chain)
77 ik = kdl.ChainIkSolverVel_wdls(chain)
80 dq = kdl.JntArray(q.rows())
83 fk.JntToCart(q, current)
84 dx = kdl.diff(current, kdl.Frame(current.M, target))
85 dx.rot = kdl.Vector.Zero()
86 if dx.vel.Norm() < 0.003:
88 if dx.vel.Norm() > 0.05:
89 dx.vel = dx.vel * (0.05 / dx.vel.Norm())
90 if ik.CartToJnt(q, dx, dq) < 0:
91 raise RuntimeError(
"PyKDL IK velocity step failed")
92 for i
in range(q.rows()):
94 raise RuntimeError(
"PyKDL IK did not converge")
97def waypoints(chain: kdl.Chain) -> dict[str, list[float]]:
107 "pick_above": solve([0.40, 0.0, 0.24]),
108 "pick": solve([0.40, 0.0, 0.04]),
109 "lift": solve([0.40, 0.0, 0.34]),
110 "place_above": solve([0.40, 0.24, 0.24]),
111 "place": solve([0.40, 0.24, 0.04]),
117 q =
jnt(robot.jnt_pos_msr)
118 qdot =
jnt(robot.jnt_vel_msr)
119 qddot = kdl.JntArray(robot.n_joints)
120 tau = kdl.JntArray(robot.n_joints)
121 for i
in range(robot.n_joints):
122 qddot[i] = KP[i] * (target[i] - q[i]) - KD[i] * qdot[i]
123 wrenches = [kdl.Wrench.Zero()
for _
in range(chain.getNrOfSegments())]
124 if solver.CartToJnt(q, qdot, qddot, wrenches, tau) < 0:
125 raise RuntimeError(
"PyKDL RNEA failed")
126 robot.jnt_trq_cmd =
as_list(tau)
141def run_phase(env, robot, solver, chain, phase, viewer, state) -> bool:
142 print(f
"State: {phase['name']}")
143 start = robot.jnt_pos_msr[:]
145 while env.time() - t0 < phase[
"duration"]:
146 a = max(0.0, min(1.0, (env.time() - t0) / phase[
"duration"]))
147 target = [x + a * (y - x)
for x, y
in zip(start, phase[
"target"])]
149 if env.has_actuator(
"g_fingers_actuator"):
150 env.set_actuator_ctrl(
"g_fingers_actuator", phase[
"gripper"])
151 if viewer
is not None and not viewer.is_running():
153 if not step_once(env, robot, viewer, state):
159 parser = argparse.ArgumentParser()
160 parser.add_argument(
"--gui", action=
"store_true")
161 args = parser.parse_args()
165 chain = robot.kdl_chain()
166 solver = kdl.ChainIdSolver_RNE(chain, kdl.Vector(0.0, 0.0, -9.81))
167 robot.ctrl_mode = mjk.CtrlMode.TORQUE
170 robot.set_joint_pos(HOME, call_forward=
False)
171 env.set_body_pose(
"cube", CUBE_START)
172 if env.has_actuator(
"g_fingers_actuator"):
173 env.set_actuator_ctrl(
"g_fingers_actuator", 0.0)
175 env.on_reset = on_reset
180 {
"name":
"HOME",
"target": q[
"home"],
"duration": 0.8,
"gripper": 0.0},
181 {
"name":
"PICK_ABOVE",
"target": q[
"pick_above"],
"duration": 2.0,
"gripper": 0.0},
182 {
"name":
"PICK",
"target": q[
"pick"],
"duration": 2.0,
"gripper": 0.0},
183 {
"name":
"CLOSE",
"target": q[
"pick"],
"duration": 1.0,
"gripper": 255.0},
184 {
"name":
"LIFT",
"target": q[
"lift"],
"duration": 1.5,
"gripper": 255.0},
185 {
"name":
"PLACE_ABOVE",
"target": q[
"place_above"],
"duration": 1.5,
"gripper": 255.0},
186 {
"name":
"PLACE",
"target": q[
"place"],
"duration": 2.0,
"gripper": 255.0},
187 {
"name":
"OPEN",
"target": q[
"place"],
"duration": 0.8,
"gripper": 0.0},
188 {
"name":
"RETREAT",
"target": q[
"place_above"],
"duration": 1.2,
"gripper": 0.0},
190 state = {
"prev": env.time()}
192 viewer = mjk.SimulateViewer.open(robot,
"ex_rnea_pick_place.py")
194 while viewer.is_running():
197 if not run_phase(env, robot, solver, chain, phase, viewer, state):
200 except ResetRequested:
202 except StopIteration:
208 if not run_phase(env, robot, solver, chain, phase,
None, state):
210 cube_frame = env.body_frame(
"cube")
211 cube_pos = [cube_frame.p.x(), cube_frame.p.y(), cube_frame.p.z()]
212 print(f
"cube final position: {[round(x, 3) for x in cube_pos]}")