Skip to content

Commit e4ea7c4

Browse files
committed
fetch experiments/math fixes
1 parent c99fdd8 commit e4ea7c4

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

56 files changed

+3088
-6
lines changed
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
#!/usr/bin/env python
2+
3+
import numpy as np
4+
from roboticstoolbox.robot.ERobot import ERobot
5+
from spatialmath import SE3
6+
7+
8+
class Fetch(ERobot):
9+
"""
10+
Class that imports a Fetch URDF model
11+
12+
``Fetch()`` is a class which imports a Fetch robot definition
13+
from a URDF file. The model describes its kinematic and graphical
14+
characteristics.
15+
16+
.. runblock:: pycon
17+
18+
>>> import roboticstoolbox as rtb
19+
>>> robot = rtb.models.URDF.Fetch()
20+
>>> print(robot)
21+
22+
Defined joint configurations are:
23+
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
28+
29+
.. codeauthor:: Jesse Haviland
30+
.. sectionauthor:: Peter Corke
31+
"""
32+
33+
def __init__(self):
34+
35+
links, name, urdf_string, urdf_filepath = self.URDF_read(
36+
"fetch_description/robots/fetch.urdf"
37+
)
38+
39+
super().__init__(
40+
links,
41+
name=name,
42+
manufacturer="Fetch",
43+
gripper_links=links[11],
44+
urdf_string=urdf_string,
45+
urdf_filepath=urdf_filepath,
46+
)
47+
48+
# self.grippers[0].tool = SE3(0, 0, 0.1034)
49+
50+
self.qdlim = np.array(
51+
[4.0, 4.0, 0.1, 1.25, 1.45, 1.57, 1.52, 1.57, 2.26, 2.26]
52+
)
53+
54+
self.addconfiguration("qz", np.array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0]))
55+
56+
self.addconfiguration(
57+
"qr", np.array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0])
58+
)
59+
60+
61+
if __name__ == "__main__": # pragma nocover
62+
63+
robot = Fetch()
64+
print(robot)
65+
66+
for link in robot.links:
67+
print(link.name)
68+
print(link.isjoint)
69+
print(len(link.collision))
70+
71+
print()
72+
73+
for link in robot.grippers[0].links:
74+
print(link.name)
75+
print(link.isjoint)
76+
print(len(link.collision))

roboticstoolbox/models/URDF/__init__.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
from roboticstoolbox.models.URDF.LBR import LBR
2020
from roboticstoolbox.models.URDF.KinovaGen3 import KinovaGen3
2121
from roboticstoolbox.models.URDF.YuMi import YuMi
22-
22+
from roboticstoolbox.models.URDF.Fetch import Fetch
2323
__all__ = [
2424
"Panda",
2525
"Frankie",
@@ -42,4 +42,5 @@
4242
"LBR",
4343
"KinovaGen3",
4444
"YuMi",
45+
"Fetch"
4546
]

roboticstoolbox/robot/ERobot.py

Lines changed: 262 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2066,6 +2066,7 @@ def link_collision_damper(
20662066
j = 0
20672067
Ain = None
20682068
bin = None
2069+
din = None
20692070

20702071
def indiv_calculation(link, link_col, q):
20712072
d, wTlp, wTcp = link_col.closest_point(shape, di)
@@ -2074,22 +2075,30 @@ def indiv_calculation(link, link_col, q):
20742075
lpTcp = -wTlp + wTcp
20752076

20762077
norm = lpTcp / d
2078+
# norm = self.fkine(q, end=link, fast=True)[:3, :3] @ norm
20772079
norm_h = np.expand_dims(np.r_[norm, 0, 0, 0], axis=0)
20782080

2079-
Je = self.jacobe(
2080-
q, start=self.base_link, end=link, tool=link_col.base.A, fast=True
2081+
tool = SE3((np.linalg.inv(self.fkine(q, end=link, fast=True)) @ SE3(wTlp).A)[:3, 3])
2082+
2083+
Je = self.jacob0(
2084+
q, end=link, tool=tool.A, fast=True
20812085
)
2086+
Je[:3, :] = self._base.A[:3, :3] @ Je[:3, :]
2087+
2088+
2089+
# print(Je)
2090+
20822091
n_dim = Je.shape[1]
20832092
dp = norm_h @ shape.v
2084-
l_Ain = np.zeros((1, n))
2093+
l_Ain = np.zeros((1, self.n))
20852094
l_Ain[0, :n_dim] = norm_h @ Je
2086-
l_bin = (xi * (d - ds) / (di - ds)) + dp
2095+
l_bin = (xi * (d - ds) / (di - ds)) + 0
20872096
else:
20882097
l_Ain = None
20892098
l_bin = None
20902099

20912100
return l_Ain, l_bin, d, wTcp
2092-
2101+
20932102
for link in links:
20942103
if link.isjoint:
20952104
j += 1
@@ -2113,8 +2122,256 @@ def indiv_calculation(link, link_col, q):
21132122
else:
21142123
bin = np.r_[bin, l_bin]
21152124

2125+
if din is None:
2126+
din = d
2127+
else:
2128+
din = np.r_[din, d]
2129+
21162130
return Ain, bin
21172131

2132+
def vision_collision_damper(
2133+
self,
2134+
shape,
2135+
q=None,
2136+
di=0.3,
2137+
ds=0.05,
2138+
xi=1.0,
2139+
end=None,
2140+
start=None,
2141+
collision_list=None,
2142+
camera=None
2143+
):
2144+
"""
2145+
Formulates an inequality contraint which, when optimised for will
2146+
make it impossible for the robot to run into a collision. Requires
2147+
See examples/neo.py for use case
2148+
:param ds: The minimum distance in which a joint is allowed to
2149+
approach the collision object shape
2150+
:type ds: float
2151+
:param di: The influence distance in which the velocity
2152+
damper becomes active
2153+
:type di: float
2154+
:param xi: The gain for the velocity damper
2155+
:type xi: float
2156+
:param from_link: The first link to consider, defaults to the base
2157+
link
2158+
:type from_link: ELink
2159+
:param to_link: The last link to consider, will consider all links
2160+
between from_link and to_link in the robot, defaults to the
2161+
end-effector link
2162+
:type to_link: ELink
2163+
:returns: Ain, Bin as the inequality contraints for an omptimisor
2164+
:rtype: ndarray(6), ndarray(6)
2165+
"""
2166+
2167+
if start is None:
2168+
start = self.base_link
2169+
2170+
if end is None:
2171+
end = self.ee_link
2172+
2173+
links, n, _ = self.get_path(start=start, end=end)
2174+
2175+
# if q is None:
2176+
# q = np.copy(self.q)
2177+
# else:
2178+
# q = getvector(q, n)
2179+
2180+
j = 0
2181+
Ain = None
2182+
bin = None
2183+
din = None
2184+
2185+
def indiv_calculation(link, link_col, q):
2186+
d, wTlp, wTcp = link_col.closest_point(shape, di)
2187+
2188+
if d is not None:
2189+
lpTcp = -wTlp + wTcp
2190+
2191+
norm = lpTcp / d
2192+
norm_h = np.expand_dims(np.r_[norm, 0, 0, 0], axis=0)
2193+
2194+
tool = SE3((np.linalg.inv(self.fkine(q, end=link, fast=True)) @ SE3(wTlp).A)[:3, 3])
2195+
2196+
Je = self.jacob0(
2197+
q, end=link, tool=tool.A, fast=True
2198+
)
2199+
Je[:3, :] = self._base.A[:3, :3] @ Je[:3, :]
2200+
2201+
wTc = camera.fkine(camera.q, fast=True)
2202+
Jv = camera.jacob0(
2203+
camera.q, tool=SE3(np.linalg.inv(wTc[:3, :3]) @ (wTcp - wTc[:3, -1])).A, fast=True
2204+
)
2205+
Jv[:3, :] = self._base.A[:3, :3] @ Jv[:3, :]
2206+
2207+
n_dim = Je.shape[1]
2208+
dp = norm_h @ Jv
2209+
l_Ain = np.zeros((1, self.n + 2 + 10))
2210+
l_Ain[0, :n_dim] = norm_h @ Je
2211+
l_Ain -= np.r_[dp[0, :3], np.zeros(7), dp[0, 3:], np.zeros(9), 1]
2212+
l_bin = (xi * (d - ds) / (di - ds))
2213+
else:
2214+
l_Ain = None
2215+
l_bin = None
2216+
2217+
return l_Ain, l_bin, d, wTcp
2218+
2219+
for link in links:
2220+
if link.isjoint:
2221+
j += 1
2222+
2223+
if collision_list is None:
2224+
col_list = link.collision
2225+
else:
2226+
col_list = collision_list[j - 1]
2227+
2228+
for link_col in col_list:
2229+
l_Ain, l_bin, d, wTcp = indiv_calculation(link, link_col, q)
2230+
2231+
if l_Ain is not None and l_bin is not None:
2232+
if Ain is None:
2233+
Ain = l_Ain
2234+
else:
2235+
Ain = np.r_[Ain, l_Ain]
2236+
2237+
if bin is None:
2238+
bin = np.array(l_bin)
2239+
else:
2240+
bin = np.r_[bin, l_bin]
2241+
2242+
if din is None:
2243+
din = d
2244+
else:
2245+
din = np.r_[din, d]
2246+
2247+
return Ain, bin, din
2248+
2249+
def new_vision_collision_damper(
2250+
self,
2251+
shape,
2252+
q=None,
2253+
di=0.3,
2254+
ds=0.05,
2255+
xi=1.0,
2256+
end=None,
2257+
start=None,
2258+
collision_list=None,
2259+
camera=None,
2260+
obj=None
2261+
):
2262+
"""
2263+
Formulates an inequality contraint which, when optimised for will
2264+
make it impossible for the robot to run into a collision. Requires
2265+
See examples/neo.py for use case
2266+
:param ds: The minimum distance in which a joint is allowed to
2267+
approach the collision object shape
2268+
:type ds: float
2269+
:param di: The influence distance in which the velocity
2270+
damper becomes active
2271+
:type di: float
2272+
:param xi: The gain for the velocity damper
2273+
:type xi: float
2274+
:param from_link: The first link to consider, defaults to the base
2275+
link
2276+
:type from_link: ELink
2277+
:param to_link: The last link to consider, will consider all links
2278+
between from_link and to_link in the robot, defaults to the
2279+
end-effector link
2280+
:type to_link: ELink
2281+
:returns: Ain, Bin as the inequality contraints for an omptimisor
2282+
:rtype: ndarray(6), ndarray(6)
2283+
"""
2284+
2285+
if start is None:
2286+
start = self.base_link
2287+
2288+
if end is None:
2289+
end = self.ee_link
2290+
2291+
links, n, _ = self.get_path(start=start, end=end)
2292+
2293+
# if q is None:
2294+
# q = np.copy(self.q)
2295+
# else:
2296+
# q = getvector(q, n)
2297+
2298+
j = 0
2299+
Ain = None
2300+
bin = None
2301+
din = None
2302+
2303+
def indiv_calculation(link, link_col, q):
2304+
d, wTlp, wTcp = link_col.closest_point(shape, di)
2305+
2306+
if d is not None:
2307+
lpTcp = -wTlp + wTcp
2308+
2309+
norm = lpTcp / d
2310+
2311+
norm_e = self.fkine(q, end=link, fast=True)[:3, :3] @ norm
2312+
norm_v = camera.fkine(camera.q, fast=True)[:3, :3] @ norm
2313+
2314+
norm_e = np.expand_dims(np.r_[norm_e, 0, 0, 0], axis=0)
2315+
norm_v = np.expand_dims(np.r_[norm_v, 0, 0, 0], axis=0)
2316+
2317+
norm_h = np.expand_dims(np.r_[norm, 0, 0, 0], axis=0)
2318+
2319+
tool = SE3((np.linalg.inv(self.fkine(q, end=link, fast=True)) @ SE3(wTlp).A)[:3, 3])
2320+
2321+
Je = self.jacobe(
2322+
q, end=link, tool=tool.A, fast=True
2323+
)
2324+
2325+
Jv = camera.jacobe(camera.q, fast=True)
2326+
2327+
total_length = shape._length
2328+
length = np.linalg.norm(wTcp - obj)
2329+
Jv *= length / total_length
2330+
2331+
n_dim = Je.shape[1]
2332+
dp = norm_v @ Jv
2333+
l_Ain = np.zeros((1, self.n + 2 + 10))
2334+
l_Ain[0, :n_dim] = norm_e @ Je
2335+
l_Ain -= np.r_[dp[0, :3], np.zeros(7), dp[0, 3:], np.zeros(9), 1]
2336+
l_bin = (xi * (d - ds) / (di - ds))
2337+
2338+
else:
2339+
l_Ain = None
2340+
l_bin = None
2341+
2342+
return l_Ain, l_bin, d, wTcp
2343+
2344+
for link in links:
2345+
if link.isjoint:
2346+
j += 1
2347+
2348+
if collision_list is None:
2349+
col_list = link.collision
2350+
else:
2351+
col_list = collision_list[j - 1]
2352+
2353+
for link_col in col_list:
2354+
l_Ain, l_bin, d, wTcp = indiv_calculation(link, link_col, q)
2355+
2356+
if l_Ain is not None and l_bin is not None:
2357+
if Ain is None:
2358+
Ain = l_Ain
2359+
else:
2360+
Ain = np.r_[Ain, l_Ain]
2361+
2362+
if bin is None:
2363+
bin = np.array(l_bin)
2364+
else:
2365+
bin = np.r_[bin, l_bin]
2366+
2367+
if din is None:
2368+
din = d
2369+
else:
2370+
din = np.r_[din, d]
2371+
2372+
return Ain, bin, din
2373+
2374+
21182375
# inverse dynamics (recursive Newton-Euler) using spatial vector notation
21192376
def rne(robot, q, qd, qdd, symbolic=False, gravity=None):
21202377

0 commit comments

Comments
 (0)