Mujoco KDL Wrapper  0.2.2
MuJoCo + KDL bridge for robot kinematics and dynamics
Loading...
Searching...
No Matches
ex_pos_ctrl.py
Go to the documentation of this file.
1#!/usr/bin/env python3
2"""Joint position-control example ported from src/examples/ex_pos_ctrl.cpp.
3
4Drives the arm from home to a target with linearly interpolated position
5setpoints. An Env on_reset hook re-homes the arm and restarts the motion clock
6so the simulate-UI reset button replays the motion.
7"""
8
9from __future__ import annotations
10
11import argparse
12
13import mj_kdl_wrapper as mjk
14
15HOME_POSE = [0.0, 0.2618, 3.1416, -2.2689, 0.0, 0.9599, 1.5708]
16TARGET_POSE = [0.3, 0.5, 2.9, -2.0, 0.3, 1.2, 1.3]
17MOTION_DURATION = 2.0
18
19
20def clamp(value: float, low: float, high: float) -> float:
21 return max(low, min(high, value))
22
23
24def build_env(model_path: str) -> tuple[mjk.Env, mjk.Robot]:
25 spec = mjk.SceneSpec()
26 spec.timestep = 0.002
27 spec.add_floor = True
28 spec.add_skybox = True
29 robot_spec = mjk.RobotSpec()
30 robot_spec.path = model_path
31 spec.robots = [robot_spec]
32 env = mjk.Env.build(spec)
33 robot = env.create_robot("base_link", "bracelet_link")
34 robot.ctrl_mode = mjk.CtrlMode.POSITION
35 return env, robot
36
37
38def main() -> int:
39 parser = argparse.ArgumentParser()
40 parser.add_argument("--gui", action="store_true", help="Open the custom Simulate UI.")
41 args = parser.parse_args()
42
43 model_path = mjk.menagerie.model_path("kinova_gen3", env_var="MJ_KDL_MODEL")
44 env, robot = build_env(model_path)
45 try:
46 # t_start is reset on every env reset so the trajectory replays from home.
47 state = {"t_start": 0.0}
48
49 def on_reset(ctx):
50 robot.set_joint_pos(HOME_POSE, call_forward=False)
51 robot.jnt_pos_cmd = HOME_POSE[:]
52 state["t_start"] = env.time()
53
54 env.on_reset = on_reset
55 env.reset()
56
57 def control_step():
58 robot.update()
59 alpha = clamp((env.time() - state["t_start"]) / MOTION_DURATION, 0.0, 1.0)
60 robot.jnt_pos_cmd = [
61 HOME_POSE[i] + alpha * (TARGET_POSE[i] - HOME_POSE[i])
62 for i in range(robot.n_joints)
63 ]
64
65 if args.gui:
66 viewer = mjk.SimulateViewer.open(robot, "ex_pos_ctrl.py")
67 prev = env.time()
68 try:
69 while viewer.is_running():
70 if env.time() < prev - 1e-6:
71 env.reset()
72 prev = env.time()
73 control_step()
74 if not viewer.step():
75 break
76 finally:
77 viewer.close()
78 else:
79 end = env.time() + MOTION_DURATION + 1.0
80 while env.time() < end:
81 control_step()
82 robot.step()
83 max_err = max(abs(TARGET_POSE[i] - robot.jnt_pos_msr[i]) for i in range(robot.n_joints))
84 print(f"max joint error at end: {max_err:.4f} rad")
85 finally:
86 env.close()
87
88 return 0
89
90
91if __name__ == "__main__":
92 raise SystemExit(main())
float clamp(float value, float low, float high)
tuple[mjk.Env, mjk.Robot] build_env(str model_path)