Skip to content

Commit f995252

Browse files
committed
gripper implemented
1 parent 7010f8f commit f995252

File tree

3 files changed

+188
-38
lines changed

3 files changed

+188
-38
lines changed

roboticstoolbox/models/URDF/Panda.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,18 +38,17 @@ def __init__(self):
3838
elinks,
3939
name=name,
4040
manufacturer='Franka Emika',
41-
ee_links=elinks[7],
4241
gripper_links=elinks[9]
4342
)
4443

4544
self.qdlim = np.array([
4645
2.1750, 2.1750, 2.1750, 2.1750, 2.6100, 2.6100, 2.6100, 3.0, 3.0])
4746

4847
self.addconfiguration("qz", np.array(
49-
[0, 0, 0, 0, 0, 0, 0, 0, 0]))
48+
[0, 0, 0, 0, 0, 0, 0]))
5049

5150
self.addconfiguration("qr", np.array(
52-
[0, -0.3, 0, -2.2, 0, 2.0, np.pi/4, 0, 0]))
51+
[0, -0.3, 0, -2.2, 0, 2.0, np.pi/4]))
5352

5453

5554
if __name__ == '__main__': # pragma nocover

roboticstoolbox/robot/ERobot.py

Lines changed: 83 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,12 @@ def __init__(
125125
# Make a gripper object for each gripper
126126
for link in gripper_links:
127127
g_links = self.dfs_links(link)
128+
129+
# Remove gripper links from the robot
130+
for g_link in g_links:
131+
elinks.remove(g_link)
132+
133+
# Save the gripper object
128134
self.grippers.append(Gripper(g_links))
129135

130136
# Subtract the n of the grippers from the n of the robot
@@ -139,24 +145,19 @@ def __init__(
139145
if len(link.child) == 0:
140146
# no children, must be an end-effector
141147
self.ee_links.append(link)
142-
# else:
143-
# for link = self.gripper_links:
144-
# # use the passed in value
145-
# self.ee_links.append(link.)
146-
148+
else:
149+
for link in gripper_links:
150+
# use the passed in value
151+
self.ee_links.append(link.parent)
147152

148153
# assign the joint indices
149154
if all([link.jindex is None for link in elinks]):
150-
# no jindex set, assign them
151-
# if len(self.ee_links) > 1:
152-
# raise ValueError('for a robot with multiple end-effectors must assign joint indices')
153-
# maybe do the DFS in where somewhere
154155

155156
jindex = [0] # "mutable integer" hack
156157

157158
def visit_link(link, jindex):
158159
# if it's a joint, assign it a jindex and increment it
159-
if link.isjoint:
160+
if link.isjoint and link in elinks:
160161
link.jindex = jindex[0]
161162
jindex[0] += 1
162163

@@ -166,7 +167,7 @@ def visit_link(link, jindex):
166167

167168
elif all([link.jindex is not None for link in elinks]):
168169
# jindex set on all, check they are unique and sequential
169-
jset = set(range(n))
170+
jset = set(range(self._n))
170171
for link in elinks:
171172
if link.jindex not in jset:
172173
raise ValueError(
@@ -267,6 +268,32 @@ def to_dict(self):
267268

268269
ob['links'].append(li)
269270

271+
# Do the grippers now
272+
for gripper in self.grippers:
273+
for link in gripper.links:
274+
li = {
275+
'axis': [],
276+
'eta': [],
277+
'geometry': [],
278+
'collision': []
279+
}
280+
281+
for et in link.ets():
282+
li['axis'].append(et.axis)
283+
li['eta'].append(et.eta)
284+
285+
if link.v is not None:
286+
li['axis'].append(link.v.axis)
287+
li['eta'].append(link.v.eta)
288+
289+
for gi in link.geometry:
290+
li['geometry'].append(gi.to_dict())
291+
292+
for gi in link.collision:
293+
li['collision'].append(gi.to_dict())
294+
295+
ob['links'].append(li)
296+
270297
return ob
271298

272299
def fk_dict(self):
@@ -276,6 +303,7 @@ def fk_dict(self):
276303

277304
self.fkine_all()
278305

306+
# Do the robot
279307
for link in self.links:
280308

281309
li = {
@@ -291,6 +319,22 @@ def fk_dict(self):
291319

292320
ob['links'].append(li)
293321

322+
# Do the grippers now
323+
for gripper in self.grippers:
324+
for link in gripper.links:
325+
li = {
326+
'geometry': [],
327+
'collision': []
328+
}
329+
330+
for gi in link.geometry:
331+
li['geometry'].append(gi.fk_dict())
332+
333+
for gi in link.collision:
334+
li['collision'].append(gi.fk_dict())
335+
336+
ob['links'].append(li)
337+
294338
return ob
295339

296340
# @classmethod
@@ -628,37 +672,41 @@ def fkine_all(self, q=None):
628672
else:
629673
q = getvector(q, self.n)
630674

631-
# t = self.base
632-
# Tall = SE3()
633-
j = 0
675+
for link in self.links:
676+
if link.isjoint:
677+
t = link.A(q[link.jindex])
678+
else:
679+
t = link.A()
634680

635-
if self.links[0].isjoint:
636-
self.links[0]._fk = self.base * self.links[0].A(q[j])
637-
j += 1
638-
else:
639-
self.links[0]._fk = self.base * self.links[0].A()
681+
if link.parent is None:
682+
link._fk = self.base * t
683+
else:
684+
link._fk = link.parent._fk * t
640685

641-
for col in self.links[0].collision:
642-
col.wT = self.links[0]._fk
686+
# Update the collision objects transform as well
687+
for col in link.collision:
688+
col.wT = link._fk
643689

644-
for gi in self.links[0].geometry:
645-
gi.wT = self.links[0]._fk
690+
for gi in link.geometry:
691+
gi.wT = link._fk
646692

647-
for i in range(1, len(self.links)):
648-
if self.links[i].isjoint:
649-
t = self.links[i].A(q[j])
650-
j += 1
651-
else:
652-
t = self.links[i].A()
693+
# Do the grippers now
694+
for gripper in self.grippers:
695+
for link in gripper.links:
696+
# print(link.jindex)
697+
if link.isjoint:
698+
t = link.A(gripper.q[link.jindex])
699+
else:
700+
t = link.A()
653701

654-
self.links[i]._fk = self.links[i].parent._fk * t
702+
link._fk = link.parent._fk * t
655703

656-
# Update the collision objects transform as well
657-
for col in self.links[i].collision:
658-
col.wT = self.links[i]._fk
704+
# Update the collision objects transform as well
705+
for col in link.collision:
706+
col.wT = link._fk
659707

660-
for gi in self.links[i].geometry:
661-
gi.wT = self.links[i]._fk
708+
for gi in link.geometry:
709+
gi.wT = link._fk
662710

663711
# def jacob0(self, q=None):
664712
# """

roboticstoolbox/robot/Gripper.py

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@
33
@author Jesse Haviland
44
"""
55

6+
import numpy as np
7+
from spatialmath.base.argcheck import getvector
8+
69

710
class Gripper():
811

@@ -17,6 +20,106 @@ def __init__(
1720
if link.isjoint:
1821
self._n += 1
1922

23+
self.q = np.zeros(self.n)
24+
self._links = elinks
25+
26+
# assign the joint indices
27+
if all([link.jindex is None for link in elinks]):
28+
29+
jindex = [0] # "mutable integer" hack
30+
31+
def visit_link(link, jindex):
32+
# if it's a joint, assign it a jindex and increment it
33+
if link.isjoint:
34+
link.jindex = jindex[0]
35+
jindex[0] += 1
36+
37+
# visit all links in DFS order
38+
self.dfs_links(
39+
elinks[0], lambda link: visit_link(link, jindex))
40+
41+
elif all([link.jindex is not None for link in elinks]):
42+
# jindex set on all, check they are unique and sequential
43+
jset = set(range(self.n))
44+
for link in elinks:
45+
if link.jindex not in jset:
46+
raise ValueError(
47+
'gripper joint index {link.jindex} was '
48+
'repeated or out of range')
49+
jset -= set(link.jindex)
50+
if len(jset) > 0:
51+
raise ValueError('gripper joints {jset} were not assigned')
52+
else:
53+
# must be a mixture of ELinks with/without jindex
54+
raise ValueError(
55+
'all gripper links must have a jindex, or none have a jindex')
56+
57+
def dfs_links(self, start, func=None):
58+
"""
59+
Visit all links from start in depth-first order and will apply
60+
func to each visited link
61+
62+
:param start: the link to start at
63+
:type start: ELink
64+
:param func: An optional function to apply to each link as it is found
65+
:type func: function
66+
67+
:returns: A list of links
68+
:rtype: list of ELink
69+
"""
70+
visited = []
71+
72+
def vis_children(link):
73+
visited.append(link)
74+
if func is not None:
75+
func(link)
76+
77+
for li in link.child:
78+
if li not in visited:
79+
vis_children(li)
80+
81+
vis_children(start)
82+
83+
return visited
84+
2085
@property
2186
def n(self):
2287
return self._n
88+
89+
@property
90+
def q(self):
91+
"""
92+
Get/set gripper joint configuration
93+
94+
- ``gripper.q`` is the gripper joint configuration
95+
96+
:return: gripper joint configuration
97+
:rtype: ndarray(n,)
98+
99+
- ``gripper.q = ...`` checks and sets the joint configuration
100+
101+
.. note:: ???
102+
"""
103+
return self._q
104+
105+
@q.setter
106+
def q(self, q_new):
107+
self._q = getvector(q_new, self.n)
108+
109+
# --------------------------------------------------------------------- #
110+
111+
@property
112+
def links(self):
113+
"""
114+
Gripper links
115+
116+
:return: A list of link objects
117+
:rtype: list of Link subclass instances
118+
119+
.. note:: It is probably more concise to index the robot object rather
120+
than the list of links, ie. the following are equivalent::
121+
122+
robot.links[i]
123+
robot[i]
124+
"""
125+
return self._links

0 commit comments

Comments
 (0)