Mujoco KDL Wrapper  0.5.1
MuJoCo + KDL bridge for robot kinematics and dynamics
Loading...
Searching...
No Matches
ex_joint_ctrl.py
Go to the documentation of this file.
1#!/usr/bin/env python3
2"""Joint POSITION then VELOCITY control on the Gen3; Python counterpart of ex_joint_ctrl.cpp."""
3
4from __future__ import annotations
5
6import argparse
7import math
8
9import mj_kdl_wrapper as mjk
10
11HOME_POSE = [0.0, 0.2618, 3.1416, -2.2689, 0.0, 0.9599, 1.5708]
12TARGET_POSE = [0.3, 0.5, 2.9, -2.0, 0.3, 1.2, 1.3]
13MOTION_DURATION = 2.0 # [s]
14HOLD_TIME = 1.0 # [s]
15MAX_ERR = 0.01 # [rad]
16VEL_GAIN = 500.0 # velocity actuator kv [Nm s/rad]
17KV = 2.0 # [rad/s per rad]
18MAX_VEL = 0.6 # [rad/s]
19TOL = 0.01 # [rad]
20TIMEOUT = 5.0 # [s]
21
22
23def main() -> int:
24 parser = argparse.ArgumentParser()
25 parser.add_argument("--gui", action="store_true")
26 args = parser.parse_args()
27
28 spec = mjk.SceneSpec()
29 spec.timestep = 0.002
30 spec.add_floor = True
31 spec.add_skybox = True
32 robot_spec = mjk.RobotSpec()
33 robot_spec.path = str(mjk.ASSETS_DIR / "kinova_gen3/gen3.xml")
34 velocity = mjk.CtrlModeSpec()
35 velocity.mode = mjk.CtrlMode.VELOCITY
36 velocity.kv = VEL_GAIN
37 robot_spec.modes = [velocity]
38 spec.robots = [robot_spec]
39
40 env = mjk.Env.build(spec)
41 try:
42 robot = env.create_robot("base_link", "bracelet_link")
43 state = {"restart": False}
44
45 def on_reset(ctx):
46 robot.set_joint_pos(HOME_POSE)
47 robot.jnt_pos_cmd = HOME_POSE
48 state["restart"] = True
49
50 env.on_reset = on_reset
51 env.reset()
52 if args.gui:
53 env.open_viewer("ex_joint_ctrl.py")
54
55 motion, t_start = "position", 0.0
56 pos_err = vel_err = math.inf
57 vel_time = 0.0
58 while True:
59 if state["restart"]:
60 state["restart"] = False
61 robot.set_control_mode(mjk.CtrlMode.POSITION)
62 motion, t_start = "position", env.data.time
63 pos_err = vel_err = math.inf
64 env.update()
65 t = env.data.time - t_start
66 if motion == "position":
67 alpha = min(1.0, max(0.0, t / MOTION_DURATION))
68 robot.jnt_pos_cmd = [h + alpha * (g - h) for h, g in zip(HOME_POSE, TARGET_POSE)]
69 max_err = max(abs(g - q) for g, q in zip(TARGET_POSE, robot.jnt_pos_msr))
70 if t >= MOTION_DURATION + HOLD_TIME:
71 pos_err = max_err
72 robot.set_control_mode(mjk.CtrlMode.VELOCITY)
73 motion, t_start = "velocity", env.data.time
74 continue
75 else:
76 errors = [h - q for h, q in zip(HOME_POSE, robot.jnt_pos_msr)]
77 max_err = max(abs(e) for e in errors)
78 robot.jnt_vel_cmd = [max(-MAX_VEL, min(MAX_VEL, KV * e)) for e in errors]
79 if max_err < TOL or t >= TIMEOUT:
80 vel_err, vel_time = max_err, t
81 break
82 if not env.step():
83 break
84 env.pace()
85 pos_ok, vel_ok = pos_err <= MAX_ERR, vel_err < TOL
86 status = "converged" if vel_ok else "not converged"
87 print(f"POSITION: max joint error at the target {pos_err:.4f} rad (limit {MAX_ERR} rad)")
88 print(
89 f"VELOCITY: max joint error at home {vel_err:.4f} rad "
90 f"({status} at t = {vel_time:.2f} s, timeout {TIMEOUT} s)"
91 )
92 finally:
93 env.close()
94 if args.gui:
95 return 0
96 ok = pos_ok and vel_ok
97 print(f"{'PASS' if ok else 'FAIL'}: both motions reached their goal")
98 return 0 if ok else 1
99
100
101if __name__ == "__main__":
102 raise SystemExit(main())