Skip to content

Commit 89d91bd

Browse files
committed
Merge branch 'monica-branch' into rory-branch
2 parents 25ea050 + 0a53032 commit 89d91bd

File tree

2 files changed

+621
-48
lines changed

2 files changed

+621
-48
lines changed

control.py

Lines changed: 130 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -8,51 +8,125 @@
88

99
import numpy as np
1010

11+
from zmq.constants import THREAD_AFFINITY_CPU_REMOVE
1112
from 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

Comments
 (0)