-
Notifications
You must be signed in to change notification settings - Fork 454
/
neo.py
145 lines (106 loc) · 3.62 KB
/
neo.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
#!/usr/bin/env python
"""
@author Jesse Haviland
"""
import swift
import spatialgeometry as sg
import roboticstoolbox as rtb
import spatialmath as sm
import numpy as np
import qpsolvers as qp
# Launch the simulator Swift
env = swift.Swift()
env.launch()
# Create a Panda robot object
panda = rtb.models.Panda()
# Set joint angles to ready configuration
panda.q = panda.qr
# Number of joint in the panda which we are controlling
n = 7
# Make two obstacles with velocities
s0 = sg.Sphere(radius=0.05, pose=sm.SE3(0.52, 0.4, 0.3))
s0.v = [0, -0.2, 0, 0, 0, 0]
s1 = sg.Sphere(radius=0.05, pose=sm.SE3(0.1, 0.35, 0.65))
s1.v = [0, -0.2, 0, 0, 0, 0]
collisions = [s0, s1]
# Make a target
target = sg.Sphere(radius=0.02, pose=sm.SE3(0.6, -0.2, 0.0))
# Add the Panda and shapes to the simulator
env.add(panda)
env.add(s0)
env.add(s1)
env.add(target)
# Set the desired end-effector pose to the location of target
Tep = panda.fkine(panda.q)
Tep.A[:3, 3] = target.T[:3, -1]
# Tep.A[2, 3] += 0.1
def step():
# The pose of the Panda's end-effector
Te = panda.fkine(panda.q)
# Transform from the end-effector to desired pose
eTep = Te.inv() * Tep
# Spatial error
e = np.sum(np.abs(np.r_[eTep.t, eTep.rpy() * np.pi / 180]))
# Calulate the required end-effector spatial velocity for the robot
# to approach the goal. Gain is set to 1.0
v, arrived = rtb.p_servo(Te, Tep, 0.5, 0.01)
# Gain term (lambda) for control minimisation
Y = 0.01
# Quadratic component of objective function
Q = np.eye(n + 6)
# Joint velocity component of Q
Q[:n, :n] *= Y
# Slack component of Q
Q[n:, n:] = (1 / e) * np.eye(6)
# The equality contraints
Aeq = np.c_[panda.jacobe(panda.q), np.eye(6)]
beq = v.reshape((6,))
# The inequality constraints for joint limit avoidance
Ain = np.zeros((n + 6, n + 6))
bin = np.zeros(n + 6)
# The minimum angle (in radians) in which the joint is allowed to approach
# to its limit
ps = 0.05
# The influence angle (in radians) in which the velocity damper
# becomes active
pi = 0.9
# Form the joint limit velocity damper
Ain[:n, :n], bin[:n] = panda.joint_velocity_damper(ps, pi, n)
# For each collision in the scene
for collision in collisions:
# Form the velocity damper inequality contraint for each collision
# object on the robot to the collision in the scene
c_Ain, c_bin = panda.link_collision_damper(
collision,
panda.q[:n],
0.3,
0.05,
1.0,
start=panda.link_dict["panda_link1"],
end=panda.link_dict["panda_hand"],
)
# If there are any parts of the robot within the influence distance
# to the collision in the scene
if c_Ain is not None and c_bin is not None:
c_Ain = np.c_[c_Ain, np.zeros((c_Ain.shape[0], 6))]
# Stack the inequality constraints
Ain = np.r_[Ain, c_Ain]
bin = np.r_[bin, c_bin]
# Linear component of objective function: the manipulability Jacobian
c = np.r_[-panda.jacobm(panda.q).reshape((n,)), np.zeros(6)]
# The lower and upper bounds on the joint velocity and slack variable
lb = -np.r_[panda.qdlim[:n], 10 * np.ones(6)]
ub = np.r_[panda.qdlim[:n], 10 * np.ones(6)]
# Solve for the joint velocities dq
qd = qp.solve_qp(Q, c, Ain, bin, Aeq, beq, lb=lb, ub=ub)
# Apply the joint velocities to the Panda
panda.qd[:n] = qd[:n]
# Step the simulator by 50 ms
env.step(0.01)
return arrived
def run():
arrived = False
while not arrived:
arrived = step()
step()
run()