1717from roboticstoolbox .backend import xacro
1818from roboticstoolbox .backend import URDF
1919from roboticstoolbox .robot .Robot import Robot
20+ from roboticstoolbox .robot .Gripper import Gripper
2021from pathlib import PurePath , PurePosixPath
2122from ansitable import ANSITable , Column
2223
@@ -52,15 +53,13 @@ def __init__(
5253 self ,
5354 elinks ,
5455 base_link = None ,
55- ee_links = None ,
56+ gripper_links = None ,
5657 ** kwargs
5758 ):
5859
5960 self ._ets = []
6061 self ._linkdict = {}
6162 self ._n = 0
62- # self._M = 0
63- # self._q_idx = []
6463 self ._ee_links = []
6564 self ._base_link = None
6665
@@ -101,8 +100,7 @@ def __init__(
101100
102101 self ._n = n
103102
104- # scan for base and ee links
105- ee = []
103+ # scan for base
106104 for link in elinks :
107105 # is this a base link?
108106 if link ._parent is None :
@@ -113,18 +111,39 @@ def __init__(
113111 # no, update children of this link's parent
114112 link ._parent ._child .append (link )
115113
116- for link in elinks :
117- # is this a leaf node?
118- if ee_links is None and len (link .child ) == 0 :
119- # no children, must be an end-effector
120- ee .append (link )
121-
122- if ee_links is not None :
123- # use the passed in value
124- self .ee_links = ee_links
114+ # Set up the gripper, make a list containing the root of all
115+ # grippers
116+ if gripper_links is not None :
117+ if isinstance (gripper_links , ELink ):
118+ gripper_links = [gripper_links ]
125119 else :
126- # use the leaf links
127- self .ee_links = ee
120+ gripper_links = []
121+
122+ # An empty list to hold all grippers
123+ self .grippers = []
124+
125+ # Make a gripper object for each gripper
126+ for link in gripper_links :
127+ g_links = self .dfs_links (link )
128+ self .grippers .append (Gripper (g_links ))
129+
130+ # Subtract the n of the grippers from the n of the robot
131+ for gripper in self .grippers :
132+ self ._n -= gripper .n
133+
134+ # Set the ee links
135+ self .ee_links = []
136+ if gripper_links is None :
137+ for link in elinks :
138+ # is this a leaf node? and do we not have any grippers
139+ if len (link .child ) == 0 :
140+ # no children, must be an end-effector
141+ 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+
128147
129148 # assign the joint indices
130149 if all ([link .jindex is None for link in elinks ]):
@@ -141,12 +160,9 @@ def visit_link(link, jindex):
141160 link .jindex = jindex [0 ]
142161 jindex [0 ] += 1
143162
144- # visit all links in BFS order
145- self .bfs_link (
163+ # visit all links in DFS order
164+ self .dfs_links (
146165 self .base_link , lambda link : visit_link (link , jindex ))
147- # self._n = len(self._q_idx)
148-
149- self ._reset_fk_path ()
150166
151167 elif all ([link .jindex is not None for link in elinks ]):
152168 # jindex set on all, check they are unique and sequential
@@ -163,49 +179,6 @@ def visit_link(link, jindex):
163179 # must be a mixture of ELinks with/without jindex
164180 raise ValueError ('all links must have a jindex, or none have a jindex' )
165181
166-
167- # # Set up references between links, a bi-directional linked list
168- # # Also find the top of the tree
169- # self.end = []
170- # for link in elinks:
171- # if link.parent is None:
172- # self.root = link
173- # else:
174- # link.parent._child.append(link)
175-
176- # # Find the bottom of the tree
177- # for link in elinks:
178- # if len(link.child) == 0:
179- # self.end.append(link)
180-
181- # # If the base link is not defined, use the root of the tree
182- # if base_link is None:
183- # self._base_link = self.root # Needs to be private attrib
184- # else:
185- # self._base_link = base_link # Needs to be private attrib
186-
187- # # If the ee link is not defined, use the bottom of the tree
188- # if ee_link is None:
189- # self._ee_link = self.end[-1]
190- # else:
191- # self._ee_link = [ee_link]
192-
193- # scan for the base and ee links
194- # assign joint variables
195- # def add_links(link, lst, q_idx):
196-
197- # if link.isjoint:
198- # q_idx.append(len(lst))
199-
200- # lst.append(link)
201-
202- # Figure out the order of links with respect to joint variables
203- # self.bfs_link(
204- # lambda link: add_links(link, self._ets, self._q_idx))
205- # self._n = len(self._q_idx)
206-
207- # self._reset_fk_path()
208-
209182 # Current joint angles of the robot
210183 # TODO should go to Robot class?
211184 self .q = np .zeros (self .n )
@@ -215,45 +188,34 @@ def visit_link(link, jindex):
215188
216189 super ().__init__ (elinks , ** kwargs )
217190
218- def _reset_fk_path (self ):
219- # Pre-calculate the forward kinematics path
220- self ._fkpath = self .dfs_path (self .base_link , self .ee_links )
221-
222- # def bfs_link(self, func):
223- # queue = self.root
224-
225- # for li in queue:
226- # func(li)
227-
228- # def vis_children(link):
229- # for li in link.child:
230- # if li not in queue:
231- # queue.append(li)
232- # func(li)
233-
234- # while len(queue) > 0:
235- # link = queue.pop(0)
236- # vis_children(link)
237-
238- def bfs_link (self , start , func ):
191+ def dfs_links (self , start , func = None ):
239192 """
240- Visit each link in BFS order
193+ Visit all links from start in depth-first order and will apply
194+ func to each visited link
195+
196+ :param start: the link to start at
197+ :type start: ELink
198+ :param func: An optional function to apply to each link as it is found
199+ :type func: function
241200
242- :param func: [description]
243- :type func: [type]
201+ :returns: A list of links
202+ :rtype: list of ELink
244203 """
245- visited = [start ]
204+ visited = []
246205
247206 def vis_children (link ):
248207 visited .append (link )
249- func (link )
208+ if func is not None :
209+ func (link )
250210
251211 for li in link .child :
252212 if li not in visited :
253213 vis_children (li )
254214
255215 vis_children (start )
256216
217+ return visited
218+
257219 def dfs_path (self , l1 , l2 ):
258220 path = []
259221 visited = [l1 ]
@@ -475,7 +437,7 @@ def base_link(self, link):
475437 else :
476438 # self._base_link = self.links[link]
477439 raise ValueError ('must be an ELink' )
478- self ._reset_fk_path ()
440+ # self._reset_fk_path()
479441# --------------------------------------------------------------------- #
480442
481443 @property
@@ -498,7 +460,7 @@ def ee_links(self, link):
498460 self ._ee_links = link
499461 else :
500462 raise ValueError ('expecting an ELink or list of ELinks' )
501- self ._reset_fk_path ()
463+ # self._reset_fk_path()
502464# --------------------------------------------------------------------- #
503465
504466 # @property
0 commit comments