88
99import numpy as np
1010
11+ from zmq .constants import THREAD_AFFINITY_CPU_REMOVE
1112from bezier import Bezier
13+ from typing import List
14+ import pinocchio as pin
15+ from cube_trajectory_wrapper import GlobalMinJerkLinearJTraj
16+ from tools import setcubeplacement
17+ from config import LEFT_HAND , RIGHT_HAND
18+
19+ import pybullet as pyb
1220
1321# in my solution these gains were good enough for all joints but you might want to tune this.
14- Kp = 300. # proportional gain (P of PD)
15- Kv = 2 * np .sqrt (Kp ) # derivative gain (D of PD)
22+ Kp = 1000 # proportional gain (P of PD)
23+ Kv = 30 * np .sqrt (Kp ) # derivative gain (D of PD)
24+
25+ Kx_lin = 2000 # Very stiff position control
26+ Dx_lin = 5 * np .sqrt (Kx_lin )
27+
28+ Kx_rot = 1000
29+ Dx_rot = 10
1630
17- def controllaw (sim , robot , trajs , tcurrent , cube ):
31+ def controllaw (sim , robot , trajs , tcurrent ):
32+ """Joint trajectory tracking with end-effector force correction"""
1833 q , vq = sim .getpybulletstate ()
1934
2035 q_target = trajs [0 ](tcurrent )
2136 vq_target = trajs [1 ](tcurrent )
37+ vvq_target = trajs [2 ](tcurrent )
38+
39+ vvq_des = vvq_target + Kp * (q_target - q ) + Kv * (vq_target - vq )
40+ M = robot .mass (q )
41+ h = robot .nle (q , vq )
42+ tau_base = M @ vvq_des + h
2243
44+ cube_pos , cube_quat = pyb .getBasePositionAndOrientation (sim .cubeId )
45+ R = np .array (pyb .getMatrixFromQuaternion (cube_quat )).reshape (3 , 3 )
46+ cube_current_SE3 = pin .SE3 (R , np .array (cube_pos ))
2347
24- error = q_target - q
25- vvq_des = Kp * error + Kv * vq_target
48+ # cube_target_SE3 = pin.SE3(rotate('z', 0.), cube_trajs(tcurrent))
49+ setcubeplacement ( robot , cube , cube_current_SE3 )
2650
27- # data = robot.data
51+ # Forward kinematics
52+ model , data = robot .model , robot .data
53+ left_id = model .getFrameId (LEFT_HAND )
54+ right_id = model .getFrameId (RIGHT_HAND )
2855
29- # Mass matrix
30- M = robot .mass (q )
31- h = robot .nle (q , vq )
56+ pin .forwardKinematics (model , data , trajs [0 ](0 ))
57+ pin .updateFramePlacements (model , data )
3258
33- torques = M @ vvq_des + h
59+ oMLhand_desired = data .oMf [left_id ] # From joint trajectory
60+ oMRhand_desired = data .oMf [right_id ]
3461
35- # print('Order: ', sim.bulletCtrlJointsInPinOrder)
36-
37- # torques = [torques[i] for i in sim.bulletCtrlJointsInPinOrder]
38- sim .step (torques )
62+
63+ pin .forwardKinematics (model , data , q , vq )
64+ pin .updateFramePlacements (model , data )
65+ pin .computeJointJacobians (model , data , q )
66+
67+ # Jacobians
68+ J_l = pin .computeFrameJacobian (model , data , q , left_id ,
69+ pin .ReferenceFrame .LOCAL_WORLD_ALIGNED )
70+ J_r = pin .computeFrameJacobian (model , data , q , right_id ,
71+ pin .ReferenceFrame .LOCAL_WORLD_ALIGNED )
72+
73+ oMLhand_actual = data .oMf [left_id ]
74+ oMRhand_actual = data .oMf [right_id ]
3975
40- if __name__ == "__main__" :
41-
42- from tools import setupwithpybullet , setupwithpybulletandmeshcat , rununtil
43- from config import DT
76+ error_pos_hands = oMLhand_actual .translation - oMRhand_actual .translation
4477
45- # `setupwithpybullet` currently returns (robot, sim, cube).
46- # Unpack and avoid depending on any `table` object.
47- robot , sim , cube = setupwithpybullet ()
78+ # Orientation errors
79+ R_err_l = oMLhand_desired .rotation @ oMLhand_actual .rotation .T
80+ err_rot_l = pin .log3 (R_err_l )
81+
82+ R_err_r = oMRhand_desired .rotation @ oMRhand_actual .rotation .T
83+ err_rot_r = pin .log3 (R_err_r )
84+
85+ # Velocities
86+ v_l = pin .getFrameVelocity (model , data , left_id ,
87+ pin .ReferenceFrame .LOCAL_WORLD_ALIGNED )
88+ vel_l = np .hstack ([v_l .linear , v_l .angular ])
89+ v_r = pin .getFrameVelocity (model , data , right_id ,
90+ pin .ReferenceFrame .LOCAL_WORLD_ALIGNED )
91+ vel_r = np .hstack ([v_r .linear , v_r .angular ])
4892
93+ # Compute correction forces
94+ F_l = np .hstack ([
95+ - Kx_lin * error_pos_hands - Dx_lin * vel_l [:3 ],
96+ Kx_rot * err_rot_l - Dx_rot * vel_l [3 :]
97+ ])
98+ F_r = np .hstack ([
99+ Kx_lin * error_pos_hands - Dx_lin * vel_r [:3 ],
100+ Kx_rot * err_rot_r - Dx_rot * vel_r [3 :]
101+ ])
49102
50- from config import CUBE_PLACEMENT , CUBE_PLACEMENT_TARGET
103+ # Map to joint torques
104+ tau_l = J_l [:, :].T @ F_l
105+ tau_r = J_r [:, :].T @ F_r
106+
107+ tau_l = np .clip (tau_l , - 200.0 , 200.0 )
108+ tau_r = np .clip (tau_r , - 200.0 , 200.0 )
109+
110+ # Combine: base tracking + end-effector correction
111+ tau_total = tau_base + tau_r + tau_l
112+ sim .step (tau_total )
113+
114+ if __name__ == "__main__" :
115+
116+ from tools import setupwithpybullet , setupwithpybulletandmeshcat , rununtil
117+ from config import CUBE_PLACEMENT , CUBE_PLACEMENT_TARGET , DT
51118 from inverse_geometry import computeqgrasppose
52119 from path import computepath
53120
54- q0 ,successinit = computeqgrasppose (robot , robot .q0 , cube , CUBE_PLACEMENT , None )
55- qe ,successend = computeqgrasppose (robot , robot .q0 , cube , CUBE_PLACEMENT_TARGET , None )
121+ robot , sim , table , cube = setupwithpybullet ()
122+
123+ q0 , successinit = computeqgrasppose (robot , robot .q0 , cube , CUBE_PLACEMENT , None )
124+ qe , successend = computeqgrasppose (robot , robot .q0 , cube , CUBE_PLACEMENT_TARGET , None )
125+
126+ if not successinit or not successend :
127+ print ('Failed to compute grasp pose' )
128+ exit ()
129+
56130 path , cube_placements = computepath (
57131 q0 ,
58132 qe ,
@@ -62,44 +136,52 @@ def controllaw(sim, robot, trajs, tcurrent, cube):
62136 cube = cube ,
63137 computeqgrasppose = computeqgrasppose )
64138
65-
66- print ('Success Init: ' , successinit )
67- print ('Success End: ' , successend )
68-
69-
70- #setting initial configuration
71139 sim .setqsim (q0 )
72-
73-
74- #TODO this is just an example, you are free to do as you please.
75- #In any case this trajectory does not follow the path
76- #0 init and end velocities
77- def maketraj (q0 ,q1 ,path , T ): #TODO compute a real trajectory !
78- poimtlist = [q0 , q0 ] + path + [q1 , q1 ]
79- # point = [q0, q0, q1, q1]
80- q_of_t = Bezier (poimtlist ,t_max = T )
140+
141+ def maketraj (q0 , q1 , path , T ): #TODO compute a real trajectory !
142+ points = [q0 , q0 ] + path + [q1 , q1 ]
143+ q_of_t = Bezier (points ,t_max = T )
81144 vq_of_t = q_of_t .derivative (1 )
82145 vvq_of_t = vq_of_t .derivative (1 )
83146 return q_of_t , vq_of_t , vvq_of_t
147+
148+
149+ def maketraj_with_joint_space_linear (
150+ waypoints : List [np .array ],
151+ T : int ):
152+ joint_space_trajectory = GlobalMinJerkLinearJTraj (
153+ waypoints = waypoints ,
154+ T_max = T ,
155+ )
156+
157+ return (
158+ joint_space_trajectory ,
159+ joint_space_trajectory .derivative (1 ),
160+ joint_space_trajectory .derivative (2 )
161+ )
84162
85-
86- #TODO this is just a random trajectory, you need to do this yourself
87163 total_time = 10.
88- trajs = maketraj (q0 , qe , path , total_time )
89-
164+
165+ trajs = maketraj_with_joint_space_linear (
166+ waypoints = path ,
167+ T = total_time
168+ )
169+
170+ cube_trajs = maketraj_with_joint_space_linear (
171+ waypoints = [p .translation for p in cube_placements ],
172+ T = total_time
173+ )[0 ]
174+
90175 tcur = 0.
91176
92-
93177 while tcur < total_time :
94178 rununtil (
95179 controllaw ,
96180 DT ,
97181 sim ,
98182 robot ,
99183 trajs ,
100- tcur ,
101- cube )
184+ tcur )
102185 tcur += DT
103-
104-
186+
105187
0 commit comments