Skip to content

Commit c94efff

Browse files
author
Rhys
committed
Merge branch 'master' into release
2 parents ef6c802 + f7cdb44 commit c94efff

File tree

4 files changed

+308
-64
lines changed

4 files changed

+308
-64
lines changed
Lines changed: 229 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,229 @@
1+
#!/usr/bin/env python
2+
"""
3+
@author Kerry He and Rhys Newbury
4+
"""
5+
6+
import swift
7+
import spatialgeometry as sg
8+
import roboticstoolbox as rtb
9+
import spatialmath as sm
10+
import numpy as np
11+
import qpsolvers as qp
12+
import math
13+
14+
15+
def transform_between_vectors(a, b):
16+
# Finds the shortest rotation between two vectors using angle-axis,
17+
# then outputs it as a 4x4 transformation matrix
18+
a = a / np.linalg.norm(a)
19+
b = b / np.linalg.norm(b)
20+
21+
angle = np.arccos(np.dot(a, b))
22+
axis = np.cross(a, b)
23+
24+
return sm.SE3.AngleAxis(angle, axis)
25+
26+
# Launch the simulator Swift
27+
env = swift.Swift()
28+
env.launch()
29+
30+
# Create a Fetch and Camera robot object
31+
fetch = rtb.models.Fetch()
32+
fetch_camera = rtb.models.FetchCamera()
33+
34+
# Set joint angles to zero configuration
35+
fetch.q = fetch.qz
36+
fetch_camera.q = fetch_camera.qz
37+
38+
# Make target object obstacles with velocities
39+
target = sg.Sphere(radius=0.05, base=sm.SE3(-2.0, 0.0, 0.5))
40+
41+
# Make line of sight object to visualize where the camera is looking
42+
sight_base = sm.SE3.Ry(np.pi / 2) * sm.SE3(0.0, 0.0, 2.5)
43+
centroid_sight = sg.Cylinder(
44+
radius=0.001,
45+
length=5.0,
46+
base=fetch_camera.fkine(fetch_camera.q, fast=True) @ sight_base.A,
47+
)
48+
49+
# Add the Fetch and other shapes to the simulator
50+
env.add(fetch)
51+
env.add(fetch_camera)
52+
env.add(centroid_sight)
53+
env.add(target)
54+
55+
# Set the desired end-effector pose to the location of target
56+
Tep = fetch.fkine(fetch.q)
57+
Tep.A[:3, :3] = sm.SE3.Rz(np.pi).R
58+
Tep.A[:3, 3] = target.base.t
59+
60+
env.step()
61+
62+
n_base = 2
63+
n_arm = 8
64+
n_camera = 2
65+
n = n_base + n_arm + n_camera
66+
67+
68+
def step():
69+
70+
# Find end-effector pose in world frame
71+
wTe = fetch.fkine(fetch.q, fast=True)
72+
# Find camera pose in world frame
73+
wTc = fetch_camera.fkine(fetch_camera.q, fast=True)
74+
75+
# Find transform between end-effector and goal
76+
eTep = np.linalg.inv(wTe) @ Tep.A
77+
# Find transform between camera and goal
78+
cTep = np.linalg.inv(wTc) @ Tep.A
79+
80+
# Spatial error between end-effector and target
81+
et = np.sum(np.abs(eTep[:3, -1]))
82+
83+
# Weighting function used for objective function
84+
def w_lambda(et, alpha, gamma):
85+
return alpha * np.power(et, gamma)
86+
87+
# Quadratic component of objective function
88+
Q = np.eye(n + 10)
89+
90+
Q[: n_base + n_arm, : n_base + n_arm] *= 0.01 # Robotic manipulator
91+
Q[:n_base, :n_base] *= w_lambda(et, 1.0, -1.0) # Mobile base
92+
Q[n_base + n_arm : n, n_base + n_arm : n] *= 0.01 # Camera
93+
Q[n : n + 3, n : n + 3] *= w_lambda(et, 1000.0, -2.0) # Slack arm linear
94+
Q[n + 3 : n + 6, n + 3 : n + 6] *= w_lambda(et, 0.01, -5.0) # Slack arm angular
95+
Q[n + 6:-1, n + 6:-1] *= 100 # Slack camera
96+
Q[-1, -1] *= w_lambda(et, 1000.0, 3.0) # Slack self-occlusion
97+
98+
# Calculate target velocities for end-effector to reach target
99+
v_manip, _ = rtb.p_servo(wTe, Tep, 1.5)
100+
v_manip[3:] *= 1.3
101+
102+
# Calculate target angular velocity for camera to rotate towards target
103+
head_rotation = transform_between_vectors(
104+
np.array([1, 0, 0]), cTep[:3, 3]
105+
)
106+
v_camera, _ = rtb.p_servo(sm.SE3(), head_rotation, 25)
107+
108+
# The equality contraints to achieve velocity targets
109+
Aeq = np.c_[
110+
fetch.jacobe(fetch.q, fast=True),
111+
np.zeros((6, 2)),
112+
np.eye(6),
113+
np.zeros((6, 4))
114+
]
115+
beq = v_manip.reshape((6,))
116+
117+
jacobe_cam = fetch_camera.jacobe(fetch_camera.q, fast=True)[3:, :]
118+
Aeq_cam = np.c_[
119+
jacobe_cam[:, :3],
120+
np.zeros((3, 7)),
121+
jacobe_cam[:, 3:],
122+
np.zeros((3, 6)),
123+
np.eye(3),
124+
np.zeros((3, 1)),
125+
]
126+
Aeq = np.r_[Aeq, Aeq_cam]
127+
beq = np.r_[beq, v_camera[3:].reshape((3,))]
128+
129+
# The inequality constraints for joint limit avoidance
130+
Ain = np.zeros((n + 10, n + 10))
131+
bin = np.zeros(n + 10)
132+
133+
# The minimum angle (in radians) in which the joint is allowed to approach
134+
# to its limit
135+
ps = 0.1
136+
137+
# The influence angle (in radians) in which the velocity damper
138+
# becomes active
139+
pi = 0.9
140+
141+
# Form the joint limit velocity damper
142+
Ain[: fetch.n, : fetch.n], bin[: fetch.n] = fetch.joint_velocity_damper(
143+
ps, pi, fetch.n
144+
)
145+
146+
Ain_torso, bin_torso = fetch_camera.joint_velocity_damper(0.0, 0.05, fetch_camera.n)
147+
Ain[2, 2] = Ain_torso[2, 2]
148+
bin[2] = bin_torso[2]
149+
150+
Ain_cam, bin_cam = fetch_camera.joint_velocity_damper(ps, pi, fetch_camera.n)
151+
Ain[n_base + n_arm : n, n_base + n_arm : n] = Ain_cam[3:, 3:]
152+
bin[n_base + n_arm : n] = bin_cam[3:]
153+
154+
# Create line of sight object between camera and object
155+
c_Ain, c_bin = fetch.vision_collision_damper(
156+
target,
157+
camera=fetch_camera,
158+
camera_n=2,
159+
q=fetch.q[: fetch.n],
160+
di=0.3,
161+
ds=0.2,
162+
xi=1.0,
163+
end=fetch.link_dict["gripper_link"],
164+
start=fetch.link_dict["shoulder_pan_link"],
165+
)
166+
167+
if c_Ain is not None and c_bin is not None:
168+
c_Ain = np.c_[c_Ain, np.zeros((c_Ain.shape[0], 9)), -np.ones((c_Ain.shape[0], 1))]
169+
170+
Ain = np.r_[Ain, c_Ain]
171+
bin = np.r_[bin, c_bin]
172+
173+
# Linear component of objective function: the manipulability Jacobian
174+
c = np.concatenate(
175+
(
176+
np.zeros(n_base),
177+
-fetch.jacobm(start=fetch.links[3]).reshape((n_arm,)),
178+
np.zeros(n_camera),
179+
np.zeros(10),
180+
)
181+
)
182+
183+
# Get base to face end-effector
184+
= 0.5
185+
bTe = fetch.fkine(fetch.q, include_base=False, fast=True)
186+
θε = math.atan2(bTe[1, -1], bTe[0, -1])
187+
ε = * θε
188+
c[0] = -ε
189+
190+
# The lower and upper bounds on the joint velocity and slack variable
191+
lb = -np.r_[
192+
fetch.qdlim[: fetch.n],
193+
fetch_camera.qdlim[3 : fetch_camera.n],
194+
100 * np.ones(9),
195+
0,
196+
]
197+
ub = np.r_[
198+
fetch.qdlim[: fetch.n],
199+
fetch_camera.qdlim[3 : fetch_camera.n],
200+
100 * np.ones(9),
201+
100,
202+
]
203+
204+
# Solve for the joint velocities dq
205+
qd = qp.solve_qp(Q, c, Ain, bin, Aeq, beq, lb=lb, ub=ub)
206+
qd_cam = np.concatenate((qd[:3], qd[fetch.n : fetch.n + 2]))
207+
qd = qd[: fetch.n]
208+
209+
if et > 0.5:
210+
qd *= 0.7 / et
211+
qd_cam *= 0.7 / et
212+
else:
213+
qd *= 1.4
214+
qd_cam *= 1.4
215+
216+
arrived = et < 0.02
217+
218+
fetch.qd = qd
219+
fetch_camera.qd = qd_cam
220+
centroid_sight._base = fetch_camera.fkine(fetch_camera.q, fast=True) @ sight_base.A
221+
222+
return arrived
223+
224+
225+
arrived = False
226+
while not arrived:
227+
arrived = step()
228+
env.step(0.01)
229+

roboticstoolbox/models/URDF/Fetch.py

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,10 @@ class Fetch(ERobot):
2121
2222
Defined joint configurations are:
2323
24-
- qz, zero joint angle configuration, 'L' shaped configuration
25-
- qr, vertical 'READY' configuration
26-
- qs, arm is stretched out in the x-direction
27-
- qn, arm is at a nominal non-singular configuration
24+
- qz, zero joint angle configuration, arm is stretched out in the x-direction
25+
- qr, tucked arm configuration
2826
29-
.. codeauthor:: Jesse Haviland
27+
.. codeauthor:: Kerry He
3028
.. sectionauthor:: Peter Corke
3129
"""
3230

@@ -45,16 +43,14 @@ def __init__(self):
4543
urdf_filepath=urdf_filepath,
4644
)
4745

48-
# self.grippers[0].tool = SE3(0, 0, 0.1034)
49-
5046
self.qdlim = np.array(
5147
[4.0, 4.0, 0.1, 1.25, 1.45, 1.57, 1.52, 1.57, 2.26, 2.26]
5248
)
5349

5450
self.addconfiguration("qz", np.array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0]))
5551

5652
self.addconfiguration(
57-
"qr", np.array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0])
53+
"qr", np.array([0, 0, 0.05, 1.32, 1.4, -0.2, 1.72, 0, 1.66, 0])
5854
)
5955

6056

roboticstoolbox/models/URDF/FetchCamera.py

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,9 @@
77

88
class FetchCamera(ERobot):
99
"""
10-
Class that imports a Fetch URDF model
10+
Class that imports a FetchCamera URDF model
1111
12-
``Fetch()`` is a class which imports a Fetch robot definition
12+
``FetchCamera()`` is a class which imports a FetchCamera robot definition
1313
from a URDF file. The model describes its kinematic and graphical
1414
characteristics.
1515
@@ -21,12 +21,10 @@ class FetchCamera(ERobot):
2121
2222
Defined joint configurations are:
2323
24-
- qz, zero joint angle configuration, 'L' shaped configuration
25-
- qr, vertical 'READY' configuration
26-
- qs, arm is stretched out in the x-direction
27-
- qn, arm is at a nominal non-singular configuration
24+
- qz, zero joint angle configuration
25+
- qr, zero joint angle configuration
2826
29-
.. codeauthor:: Jesse Haviland
27+
.. codeauthor:: Kerry He
3028
.. sectionauthor:: Peter Corke
3129
"""
3230

0 commit comments

Comments
 (0)