36 from xml.dom.minidom
import parse
40 from copy
import deepcopy
41 from shutil
import copy2
46 from sr_moveit_hand_config.generate_hand_srdf
import SRDFHandGenerator
72 def __init__(self, name, side, has_arm, has_hand):
80 if self.
side ==
"right":
81 self.arm.prefix =
"ra_" 82 self.arm.internal_name =
"right_arm" 84 self.arm.prefix =
"la_" 85 self.arm.internal_name =
"left_arm" 88 if self.
side ==
"right":
89 self.hand.prefix =
"rh_" 90 self.hand.internal_name =
"right_hand" 92 self.hand.prefix =
"lh_" 93 self.hand.internal_name =
"left_hand" 97 child = xacro.first_child_element(elt)
100 while elt
and elt.nodeType == xml.dom.Node.ELEMENT_NODE:
101 next = xacro.next_sibling_element(elt)
115 if "robot" in yamldoc:
116 robot_yaml = yamldoc[
"robot"]
117 self.
name = robot_yaml[
"name"]
118 if "manipulators" in robot_yaml:
119 manipulators_yaml = robot_yaml[
"manipulators"]
120 for manipulator_name
in manipulators_yaml.keys():
121 manipulator_yaml = manipulators_yaml[manipulator_name]
122 side = manipulator_yaml[
"side"]
123 if side
not in [
"left",
"right"]:
125 "a correct side for a manipulator")
126 has_arm =
True if "arm" in manipulator_yaml
else False 127 has_hand =
True if "hand" in manipulator_yaml
else False 128 if not has_hand
and not has_arm:
130 "either an arm or hand for a manipulator")
132 manipulator =
Manipulator(manipulator_name, side, has_arm, has_hand)
134 arm_yaml = manipulator_yaml[
"arm"]
135 if "name" in arm_yaml:
136 manipulator.arm.name = arm_yaml[
"name"]
139 if "moveit_path" in arm_yaml:
140 package_name = arm_yaml[
"moveit_path"][
"package"]
141 relative_path = arm_yaml[
"moveit_path"][
"relative_path"]
142 manipulator.arm.moveit_path = rospkg.RosPack().get_path(package_name) + relative_path
143 if "extra_groups_config_path" in arm_yaml:
144 relative_path = arm_yaml[
"extra_groups_config_path"]
145 manipulator.arm.extra_groups_config_path = \
146 rospkg.RosPack().get_path(
"sr_multi_moveit_config") + relative_path
147 if "main_group" in arm_yaml:
148 manipulator.arm.main_group = arm_yaml[
"main_group"]
151 if "other_groups" in arm_yaml:
152 for group
in arm_yaml[
"other_groups"]:
153 manipulator.arm.other_groups.append(group)
154 if "group_states" in arm_yaml:
155 for group_state
in arm_yaml[
"group_states"]:
156 manipulator.arm.group_states.append(group_state)
159 hand_yaml = manipulator_yaml[
"hand"]
160 if "name" in hand_yaml:
161 manipulator.hand.name = hand_yaml[
"name"]
162 if "main_group" in hand_yaml:
163 manipulator.hand.main_group = hand_yaml[
"main_group"]
164 if "other_groups" in hand_yaml:
165 for group
in hand_yaml[
"other_groups"]:
166 manipulator.hand.other_groups.append(group)
167 if "group_states" in hand_yaml:
168 for group_state
in hand_yaml[
"group_states"]:
169 manipulator.hand.group_states.append(group_state)
170 if "is_lite" in hand_yaml:
171 manipulator.hand.is_lite = bool(hand_yaml[
"is_lite"])
173 self.manipulators.append(manipulator)
179 def __init__(self, description_file=None, load=True):
180 if description_file
is None and len(sys.argv) > 1:
181 description_file = sys.argv[1]
185 self.
_file_name = rospy.get_param(
'~file_name',
"generated_robot")
193 with open(description_file,
"r") as stream: 194 yamldoc = yaml.load(stream) 196 self.robot.set_parameters(yamldoc) 200 new_srdf_file_name = "generated_robot.srdf" 202 for manipulator_id, manipulator
in enumerate(self.robot.manipulators):
203 if manipulator.has_arm:
205 arm_srdf_path = manipulator.arm.moveit_path +
"/" + manipulator.arm.name +
".srdf" 206 with open(arm_srdf_path,
'r') as stream: 207 self.arm_srdf_xmls.append(parse(stream)) 211 if manipulator.has_hand:
213 hand_urdf_path = self.rospack.get_path(
'sr_description') +
"/robots/" + manipulator.hand.name
214 with open(hand_urdf_path,
'r') as hand_urdf_xacro_file: 215 hand_urdf_xml = parse(hand_urdf_xacro_file) 219 hand_urdf = hand_urdf_xml.toprettyxml(indent=' ')
220 srdfHandGenerator = SRDFHandGenerator(hand_urdf, load=
False, save=
False)
221 self.hand_srdf_xmls.append(srdfHandGenerator.get_hand_srdf())
223 comment = [
"Manipulator:" + manipulator.name]
227 if manipulator.has_arm:
229 if manipulator.has_hand:
233 if len(self.robot.manipulators) == 2:
234 if self.robot.manipulators[0].has_arm
and self.robot.manipulators[1].has_arm:
235 comment = [
"Bimanual groups"]
238 self.robot.manipulators[1].arm.internal_name)
240 for manipulator_id, manipulator
in enumerate(self.robot.manipulators):
243 comment = [
"END EFFECTOR: Purpose: Represent information about an end effector."]
245 if manipulator.has_hand:
247 if manipulator.has_arm:
251 if manipulator.has_arm:
258 comment = [
"DISABLE COLLISIONS: By default it is assumed that any link of the robot could potentially " +
259 "come into collision with any other link in the robot. This tag disables collision checking " +
260 "between a specified pair of links."]
262 if manipulator.has_arm:
264 if manipulator.has_hand:
268 self.new_robot_srdf.write(
'</robot>\n')
269 self.new_robot_srdf.close()
271 with open(self.
package_path +
"/config/" + new_srdf_file_name,
'r') as stream: 274 rospy.loginfo("Loading SRDF on parameter server")
275 robot_description_param = rospy.resolve_name(
'robot_description') +
"_semantic" 276 rospy.set_param(robot_description_param,
277 srdf.toprettyxml(indent=
' '))
287 if rospy.has_param(
'/robot_description'):
288 urdf_str = rospy.get_param(
'/robot_description')
290 urdf_file.write(urdf_str)
293 rospy.loginfo(
"generated_robot.srdf has been generated and saved.")
299 self.new_robot_srdf.write(
'<?xml version="1.0" ?>\n')
300 banner = [
"This does not replace URDF, and is not an extension of URDF.\n" +
301 " This is a format for representing semantic information about the robot structure.\n" +
302 " A URDF file must exist for this robot as well, where the joints and the links that are" +
303 "referenced are defined\n"]
305 self.new_robot_srdf.write(
'<robot name="' + self.robot.name +
'">\n')
306 comments = [
"GROUPS: Representation of a set of joints and links. This can be useful for specifying DOF to " +
307 "plan for, defining arms, end effectors, etc",
308 "LINKS: When a link is specified, the parent joint of that link (if it exists) is automatically" +
310 "JOINTS: When a joint is specified, the child link of that joint (which will always exist) is" +
311 "automatically included",
312 "CHAINS: When a chain is specified, all the links along the chain (including endpoints) are" +
313 "included in the group. Additionally, all the joints that are parents to included links are " +
314 "also included. This means that joints along the chain and the parent joint of the base link " +
315 "are included in the group",
316 "SUBGROUPS: Groups can also be formed by referencing to already defined group names"]
320 previous = self.
arm_srdf_xmls[manipulator_id].documentElement
323 if elt.tagName ==
'group':
325 if len(elt.childNodes) > 0:
326 group_name = elt.getAttribute(
'name')
327 if group_name == manipulator.arm.main_group
or group_name
in manipulator.arm.other_groups:
328 if group_name == manipulator.arm.main_group:
329 elt.setAttribute(
'name', manipulator.arm.internal_name)
331 elt.setAttribute(
'name', manipulator.arm.prefix + group_name)
332 for index, group_element
in enumerate(elt.getElementsByTagName(
"chain")):
333 attributes = [
"base_link",
"tip_link"]
334 for attribute
in attributes:
335 node_attribute = group_element.getAttributeNode(attribute)
336 node_attribute.nodeValue = (manipulator.arm.prefix +
337 group_element.getAttribute(attribute))
338 for tagName
in [
"joint",
"link",
"group"]:
339 for index, group_element
in enumerate(elt.getElementsByTagName(tagName)):
340 attribute_name = group_element.getAttribute(
"name")
341 node_attribute = group_element.getAttributeNode(
"name")
342 node_attribute.nodeValue = (manipulator.arm.prefix + attribute_name)
344 elt.writexml(self.
new_robot_srdf, indent=
" ", addindent=
" ", newl=
"\n")
345 if group_name == manipulator.arm.main_group
and (manipulator.has_hand
and 346 not manipulator.hand.is_lite):
347 elt.setAttribute(
'name', manipulator.arm.internal_name +
"_and_wrist")
348 for group_element
in elt.getElementsByTagName(
"chain"):
349 node_attribute = group_element.getAttributeNode(
"tip_link")
350 node_attribute.nodeValue = (manipulator.hand.prefix +
"palm")
351 if len(elt.getElementsByTagName(
"joint")) > 0:
352 node = deepcopy(elt.getElementsByTagName(
"joint")[0])
353 node_attribute = node.getAttributeNode(
"name")
354 node_attribute.nodeValue = (manipulator.hand.prefix +
"WRJ2")
355 newatt = elt.appendChild(node)
356 node = deepcopy(elt.getElementsByTagName(
"joint")[0])
357 node_attribute = node.getAttributeNode(
"name")
358 node_attribute.nodeValue = (manipulator.hand.prefix +
"WRJ1")
359 newatt = elt.appendChild(node)
360 elt.writexml(self.
new_robot_srdf, indent=
" ", addindent=
" ", newl=
"\n")
361 elt.setAttribute(
'name', manipulator.arm.internal_name +
"_and_manipulator")
362 for group_element
in elt.getElementsByTagName(
"chain"):
363 node_attribute = group_element.getAttributeNode(
"tip_link")
364 node_attribute.nodeValue = (manipulator.hand.prefix +
"manipulator")
365 elt.writexml(self.
new_robot_srdf, indent=
" ", addindent=
" ", newl=
"\n")
366 if group_name == manipulator.arm.main_group
and (manipulator.has_hand):
367 new_group = xml.dom.minidom.Document().createElement(
'group')
368 new_group.setAttribute(
"name", manipulator.arm.internal_name +
"_and_hand")
369 if manipulator.hand.is_lite:
370 arm_group = xml.dom.minidom.Document().createElement(
'group name="' +
371 manipulator.arm.internal_name +
'"')
373 arm_group = xml.dom.minidom.Document().createElement(
'group name="' +
374 manipulator.arm.internal_name +
'"')
375 new_group.appendChild(arm_group)
376 hand_group = xml.dom.minidom.Document().createElement(
'group name="' +
377 manipulator.hand.internal_name +
'"')
378 new_group.appendChild(hand_group)
379 new_group.writexml(self.
new_robot_srdf, indent=
" ", addindent=
" ", newl=
"\n")
380 elif elt.tagName ==
'group_state':
381 group_state_name = elt.getAttribute(
'name')
382 group_name = elt.getAttribute(
'group')
383 if group_state_name
in manipulator.arm.group_states
and (group_name == manipulator.arm.main_group
or 384 group_name
in manipulator.arm.other_groups):
385 elt.setAttribute(
'name', manipulator.arm.prefix + group_state_name)
386 if group_name == manipulator.arm.main_group:
387 elt.setAttribute(
'group', manipulator.arm.internal_name)
389 elt.setAttribute(
'group', manipulator.arm.prefix + group_name)
390 for index, group_element
in enumerate(elt.getElementsByTagName(
"joint")):
391 attribute_name = group_element.getAttribute(
"name")
392 if attribute_name
in [
"WRJ1",
"WRJ2"]:
393 if manipulator.has_hand:
394 if not manipulator.hand.is_lite:
395 node_attribute = group_element.getAttributeNode(
"name")
396 node_attribute.nodeValue = (manipulator.hand.prefix + attribute_name)
398 group_element.parentNode.removeChild(group_element)
400 node_attribute = group_element.getAttributeNode(
"name")
401 node_attribute.nodeValue = (manipulator.arm.prefix + attribute_name)
402 elt.writexml(self.
new_robot_srdf, indent=
" ", addindent=
" ", newl=
"\n")
407 new_group = xml.dom.minidom.Document().createElement(
'group')
408 new_group.setAttribute(
"name",
"two_arms")
409 arm_group_1 = xml.dom.minidom.Document().createElement(
'group name="' + group_1 +
'"')
410 new_group.appendChild(arm_group_1)
411 arm_group_2 = xml.dom.minidom.Document().createElement(
'group name="' + group_2 +
'"')
412 new_group.appendChild(arm_group_2)
413 new_group.writexml(self.
new_robot_srdf, indent=
" ", addindent=
" ", newl=
"\n")
415 new_group = xml.dom.minidom.Document().createElement(
'group')
416 new_group.setAttribute(
"name",
"two_arms_and_hands")
417 arm_group_1 = xml.dom.minidom.Document().createElement(
'group name="' + group_1 +
'_and_hand"')
418 new_group.appendChild(arm_group_1)
419 arm_group_2 = xml.dom.minidom.Document().createElement(
'group name="' + group_2 +
'_and_hand"')
420 new_group.appendChild(arm_group_2)
421 new_group.writexml(self.
new_robot_srdf, indent=
" ", addindent=
" ", newl=
"\n")
427 if elt.tagName ==
'group':
429 if len(elt.childNodes) > 0:
430 elt.writexml(self.
new_robot_srdf, indent=
" ", addindent=
" ", newl=
"\n")
431 elif elt.tagName ==
'group_state':
432 for index, group_element
in enumerate(elt.getElementsByTagName(
"joint")):
433 attribute_name = group_element.getAttribute(
"name")
434 attribute_name = attribute_name.split(
"_")[1]
435 if attribute_name
in [
"WRJ1",
"WRJ2"]
and manipulator.has_arm:
436 group_element.parentNode.removeChild(group_element)
437 elt.writexml(self.
new_robot_srdf, indent=
" ", addindent=
" ", newl=
"\n")
445 if elt.tagName ==
'end_effector':
446 elt.writexml(self.
new_robot_srdf, indent=
" ", addindent=
" ", newl=
"\n")
451 previous = self.
arm_srdf_xmls[manipulator_id].documentElement
454 if elt.tagName ==
'end_effector':
455 if manipulator.has_hand:
456 elt.getAttributeNode(
"name").nodeValue = manipulator.arm.internal_name +
"_ee" 457 elt.getAttributeNode(
"parent_link").nodeValue = (manipulator.arm.prefix +
458 elt.getAttribute(
"parent_link"))
459 elt.getAttributeNode(
"group").nodeValue = manipulator.hand.internal_name
460 elt.setAttribute(
'parent_group', manipulator.arm.internal_name)
461 elt.writexml(self.
new_robot_srdf, indent=
" ", addindent=
" ", newl=
"\n")
462 newElement = deepcopy(elt)
463 newElement.getAttributeNode(
"name").nodeValue = manipulator.arm.prefix +
"and_wrist_ee" 464 newElement.getAttributeNode(
"parent_link").nodeValue = manipulator.hand.prefix +
"palm" 465 newElement.getAttributeNode(
"group").nodeValue = manipulator.hand.prefix +
"fingers" 466 newElement.setAttribute(
'parent_group', manipulator.arm.internal_name +
"_and_wrist")
467 newElement.writexml(self.
new_robot_srdf, indent=
" ", addindent=
" ", newl=
"\n")
468 newElement = deepcopy(elt)
469 newElement.getAttributeNode(
"name").nodeValue = manipulator.arm.prefix +
"and_manipulator_ee" 470 newElement.getAttributeNode(
"parent_link").nodeValue = manipulator.hand.prefix +
"manipulator" 471 newElement.getAttributeNode(
"group").nodeValue = manipulator.hand.prefix +
"fingers" 472 newElement.setAttribute(
'parent_group', manipulator.arm.internal_name +
"_and_manipulator")
473 newElement.writexml(self.
new_robot_srdf, indent=
" ", addindent=
" ", newl=
"\n")
475 elt.getAttributeNode(
"name").nodeValue = manipulator.arm.internal_name +
"_ee" 476 elt.getAttributeNode(
"parent_link").nodeValue = (manipulator.arm.prefix +
477 elt.getAttribute(
"parent_link"))
478 elt.getAttributeNode(
"group").nodeValue = (manipulator.arm.prefix +
479 elt.getAttribute(
"group"))
480 elt.setAttribute(
'parent_group', manipulator.arm.internal_name)
481 elt.writexml(self.
new_robot_srdf, indent=
" ", addindent=
" ", newl=
"\n")
486 comment = [
"VIRTUAL JOINT: Purpose: this element defines a virtual joint between a robot link and an " +
487 "external frame of reference (considered fixed with respect to the robot)"]
489 previous = self.
arm_srdf_xmls[manipulator_id].documentElement
492 if elt.tagName ==
'virtual_joint':
493 elt.getAttributeNode(
"name").nodeValue =
"world_to_" + manipulator.arm.internal_name
494 elt.getAttributeNode(
"child_link").nodeValue = manipulator.arm.prefix + elt.getAttribute(
"child_link")
495 elt.writexml(self.
new_robot_srdf, indent=
" ", addindent=
" ", newl=
"\n")
500 comment = [
"VIRTUAL JOINT: Purpose: this element defines a virtual joint between a robot link and an " +
501 "external frame of reference (considered fixed with respect to the robot)"]
506 if elt.tagName ==
'virtual_joint':
507 elt.writexml(self.
new_robot_srdf, indent=
" ", addindent=
" ", newl=
"\n")
512 comment = [manipulator.arm.internal_name +
" collisions"]
514 previous = self.
arm_srdf_xmls[manipulator_id].documentElement
518 if elt.tagName ==
'disable_collisions':
519 elt.getAttributeNode(
"link1").nodeValue = (manipulator.arm.prefix + elt.getAttribute(
"link1"))
520 elt.getAttributeNode(
"link2").nodeValue = (manipulator.arm.prefix + elt.getAttribute(
"link2"))
521 elt.writexml(self.
new_robot_srdf, indent=
" ", addindent=
" ", newl=
"\n")
522 newElement = deepcopy(elt)
527 if manipulator.has_hand:
528 if rospy.has_param(
'/robot_description'):
529 urdf_str = rospy.get_param(
'/robot_description')
530 robot = URDF.from_xml_string(urdf_str)
531 arm_chain = robot.get_chain(
"world", manipulator.hand.prefix +
"forearm", joints=
False, fixed=
False)
533 newElement.getAttributeNode(
"link1").nodeValue = arm_chain[-2]
534 newElement.getAttributeNode(
"link2").nodeValue = manipulator.hand.prefix +
"forearm" 535 newElement.getAttributeNode(
"reason").nodeValue =
"Adjacent" 536 newElement.writexml(self.
new_robot_srdf, indent=
" ", addindent=
" ", newl=
"\n")
538 newElement.getAttributeNode(
"link1").nodeValue = arm_chain[-3]
539 newElement.getAttributeNode(
"link2").nodeValue = manipulator.hand.prefix +
"forearm" 540 newElement.getAttributeNode(
"reason").nodeValue =
"Adjacent" 541 newElement.writexml(self.
new_robot_srdf, indent=
" ", addindent=
" ", newl=
"\n")
543 newElement.getAttributeNode(
"link1").nodeValue = arm_chain[-4]
544 newElement.getAttributeNode(
"link2").nodeValue = manipulator.hand.prefix +
"forearm" 545 newElement.getAttributeNode(
"reason").nodeValue =
"Adjacent" 546 newElement.writexml(self.
new_robot_srdf, indent=
" ", addindent=
" ", newl=
"\n")
549 comment = [manipulator.hand.internal_name +
" collisions"]
554 if elt.tagName ==
'disable_collisions':
555 elt.writexml(self.
new_robot_srdf, indent=
" ", addindent=
" ", newl=
"\n")
561 xml_comments = [xml.dom.minidom.Comment(c)
for c
in comments]
562 for comment
in xml_comments:
563 comment.writexml(self.
new_robot_srdf, indent=addindent, addindent=addindent, newl=
"\n")
566 if __name__ ==
'__main__':
567 rospy.init_node(
'robot_srdf_generator', anonymous=
True)
def process_includes(elt, macros=None, symbols=None)
def parse_hand_groups(self, manipulator_id, manipulator)
def parse_hand_end_effectors(self, manipulator_id, manipulator)
def parse_arm_virtual_joint(self, manipulator_id, manipulator)
def process_doc(doc, in_order=False, just_deps=False, just_includes=False, mappings=None, xacro_ns=True, kwargs)
def add_comments(self, comments, addindent=" ")
def __init__(self, description_file=None, load=True)
def parse_arm_groups(self, manipulator_id, manipulator)
def __init__(self, name, side, has_arm, has_hand)
def set_parameters(self, yamldoc)
def parse_hand_collisions(self, manipulator_id, manipulator)
def parse_hand_virtual_joint(self, manipulator_id, manipulator)
def start_new_srdf(self, file_name)
def add_bimanual_arm_groups(self, group_1, group_2)
def parse_arm_collisions(self, manipulator_id, manipulator)
def parse_arm_end_effectors(self, manipulator_id, manipulator)