franka_robot_urdf.py
Go to the documentation of this file.
1 import os
2 import sys
3 import subprocess
4 from unittest import TestCase
5 from parameterized import parameterized_class
6 from .urdf_test_case import UrdfTestCase, PKG
7 from urdf_parser_py.urdf import URDF, Mesh, Cylinder, Sphere
8 
9 
10 @parameterized_class(('robot',), [("panda",), ("fr3",)])
12 
13  @property
14  def file(self):
15  return os.path.join(self.robot, self.robot + '.urdf.xacro')
16 
18  self.xacro(self.file) # does not throw
19 
21  arm_id = self.robot
22  urdf = self.xacro(self.file)
23  for i in range(0, 9):
24  self.assertContainsLink(urdf, '%s_link%s' % (arm_id, i))
25 
27  arm_id = self.robot
28  urdf = self.xacro(self.file)
29  for i in range(1, 9):
30  joint = 'panda_joint%s' % i
31  self.assertContainsJoint(urdf, '%s_joint%s' % (arm_id, i))
32 
34  urdf = self.xacro(self.file)
35  self.assertFalse(
36  self.links_with(urdf, lambda link: 'hand' in link), # should be empty
37  'Found one or more links containing "hand", probably URDF contains a franka_gripper'
38  )
39  self.assertFalse(
40  self.joints_with(urdf, lambda joint: 'hand' in joint), # should be empty
41  'Found one or more joints containing "hand", probably URDF contains a franka_gripper'
42  )
43 
45  arm_id = self.robot
46  urdf = self.xacro(self.file)
47  for i in range(0, 8):
48  link = '%s_link%s' % (arm_id, i)
49  collisions = self.collision_geometries(urdf, link)
50  self.assertGreaterEqual(len(collisions), 1, "Link '%s' does not have any collision meshes assigned to it" % link)
51  self.assertIsInstance(
52  collisions[0], Mesh,
53  "Link '%s' is expected to have mesh geometries in <collision> not '%s'" % (link, collisions[0].__class__.__name__)
54  )
55 
57  urdf = self.xacro(self.file)
58  for name in urdf.link_map:
59  if not name.endswith('_sc'): continue
60  geometries = self.collision_geometries(urdf, name)
61  for geometry in geometries:
62  self.assertIsInstance(
63  geometry, (Cylinder, Sphere),
64  "Link '%s' is expected to define only a capsule <collision> geometry (made from Cylinders and Spheres, not '%s')" % (name, geometry.__class__.__name__)
65  )
66 
68  urdf = self.xacro(self.file)
69  for name, link in urdf.link_map.items():
70  self.assertIsNone(
71  link.inertial,
72  "Link '%s' is expected to have no <inertial> defined but actually has one:\n%s" % (name, link.inertial)
73  )
74 
76  urdf = self.xacro(self.file, args='hand:=true')
77  for name, link in urdf.link_map.items():
78  self.assertIsNone(
79  link.inertial,
80  "Link '%s' is expected to have no <inertial> defined but actually has one:\n%s" % (name, link.inertial)
81  )
82 
84  arm_id = 'foo'
85  urdf = self.xacro(self.file, args='arm_id:=%s' % arm_id)
86  for link in urdf.link_map.keys():
87  self.assertIn(arm_id, link)
88 
90  arm_id = 'foo'
91  urdf = self.xacro(self.file, args='arm_id:=%s' % arm_id)
92  for joint in urdf.joint_map.keys():
93  self.assertIn(arm_id, joint)
94 
96  arm_id = self.robot
97  urdf = self.xacro(self.file, args='hand:=true')
98  for name in ['hand', 'hand_tcp', 'leftfinger', 'rightfinger']:
99  link = '%s_%s' % (arm_id, name)
100  self.assertContainsLink(urdf, link)
101 
102  for name in ['hand_joint', 'hand_tcp_joint', 'finger_joint1', 'finger_joint2']:
103  joint = '%s_%s' % (arm_id, name)
104  self.assertContainsJoint(urdf, joint)
105 
107  arm_id = 'foo'
108  urdf = self.xacro(self.file, args='arm_id:=%s hand:=true' % arm_id)
109  for name in ['hand', 'hand_tcp', 'leftfinger', 'rightfinger']:
110  link = '%s_%s' % (arm_id, name)
111  self.assertContainsLink(urdf, link)
112 
113  for name in ['hand_joint', 'hand_tcp_joint', 'finger_joint1', 'finger_joint2']:
114  joint = '%s_%s' % (arm_id, name)
115  self.assertContainsJoint(urdf, joint)
116 
118  arm_id = self.robot
119  urdf = self.xacro(self.file, args='gazebo:=true')
120 
121  # Check if the world link exists
122  self.assertEqual('world', urdf.get_root())
123 
124  # Check if robot is directly connected to the world link
125  self.assertJointBetween(urdf, 'world', arm_id + '_link0', type="fixed")
126 
128  urdf = self.xacro(self.file, args='gazebo:=true')
129 
130  for gazebo in urdf.gazebos:
131  for child in gazebo:
132  if child.tag == 'plugin':
133  self.assertIn('name', child.attrib, '<plugin> tag does not have a "name" attribute')
134  self.assertEqual('gazebo_ros_control', child.attrib['name'])
135  # Successfully found plugin, break out of all loops
136  break
137  else:
138  # Inner loop not broken, continue with next gazebo tag
139  continue
140  # Inner loop was broken, break also outer loop
141  break
142  else:
143  # Outer loop not broken -> no valid plugin found!
144  self.fail('No <plugin name="gazebo_ros_control"> found in URDF')
145 
147  arm_id = self.robot
148  urdf = self.xacro(self.file, args='gazebo:=true')
149  for joint in ['%s_joint%s' % (arm_id, i) for i in range(1,8)]:
150  self.assertJointHasTransmission(urdf, joint, 'hardware_interface/PositionJointInterface')
151 
153  arm_id = self.robot
154  urdf = self.xacro(self.file, args='gazebo:=true')
155  for joint in ['%s_joint%s' % (arm_id, i) for i in range(1,8)]:
156  self.assertJointHasTransmission(urdf, joint, 'hardware_interface/VelocityJointInterface')
157 
159  arm_id = self.robot
160  urdf = self.xacro(self.file, args='gazebo:=true')
161  for joint in ['%s_joint%s' % (arm_id, i) for i in range(1,8)]:
162  self.assertJointHasTransmission(urdf, joint, 'hardware_interface/EffortJointInterface')
163 
165  arm_id = self.robot
166  urdf = self.xacro(self.file, 'gazebo:=true')
167  for transmission in urdf.transmissions:
168  if transmission.type == 'franka_hw/FrankaStateInterface':
169  self.assertListEqual(
170  ['%s_joint%s' % (arm_id, i) for i in range(1,8)],
171  [joint.name for joint in transmission.joints]
172  )
173  break
174  else:
175  # Didn't break out of loop -> no state interface found
176  self.fail('No franka_hw/FrankaStateInterface found in URDF')
177 
179  arm_id = self.robot
180  urdf = self.xacro(self.file, args='gazebo:=true')
181  for transmission in urdf.transmissions:
182  if transmission.type == 'franka_hw/FrankaModelInterface':
183  self.assertEqual(
184  arm_id + '_joint1', transmission.joints[0].name,
185  "First joint in the FrankaModelInterface transmission must be the root of the chain, i.e. '$(arm_id)_joint1' not '%s'" % transmission.joints[0].name
186  )
187  self.assertEqual(
188  arm_id + '_joint8', transmission.joints[1].name,
189  "Second joint in the FrankaModelInterface transmission must be the tip of the chain, i.e. '$(arm_id)_joint8' not '%s'" % transmission.joints[1].name
190  )
191  break
192  else:
193  # Didn't break out of loop -> no model interface found
194  self.fail('No franka_hw/FrankaModelInterface found in URDF')
195 
197  arm_id = self.robot
198  urdf = self.xacro(self.file, args='gazebo:=true hand:=true')
199  for joint in [arm_id + '_finger_joint1', arm_id + '_finger_joint2']:
200  self.assertJointHasTransmission(urdf, joint, 'hardware_interface/EffortJointInterface')
201 
203  urdf = self.xacro(self.file, args='gazebo:=true')
204  for name, link in urdf.link_map.items():
205  if not name.endswith('_sc'): continue
206  self.assertEqual(
207  len(link.collisions), 0,
208  "Link '%s' is expected to have no <collision> tags defined but has %s" % (name, len(link.collisions))
209  )
210 
212  urdf = self.xacro(self.file, args='gazebo:=true hand:=true')
213  for name, link in urdf.link_map.items():
214  if not name.endswith('_sc'): continue
215  self.assertEqual(
216  len(link.collisions), 0,
217  "Link '%s' is expected to have no <collision> tags defined but has %s" % (name, len(link.collisions))
218  )
219 
221  arm_id = self.robot
222  urdf = self.xacro(self.file, args='hand:=true')
223  joint = urdf.joint_map[arm_id + '_hand_tcp_joint']
224  self.assertListEqual(joint.origin.xyz, [0, 0, 0.1034])
225  self.assertListEqual(joint.origin.rpy, [0, 0, 0])
226 
228  arm_id = self.robot
229  urdf = self.xacro(self.file, args='hand:=true tcp_xyz:="1 2 3"')
230  joint = urdf.joint_map[arm_id + '_hand_tcp_joint']
231  self.assertListEqual(joint.origin.xyz, [1, 2, 3])
232 
234  arm_id = self.robot
235  urdf = self.xacro(self.file, args='hand:=true tcp_rpy:="3.1415 0.123 42"')
236  joint = urdf.joint_map[arm_id + '_hand_tcp_joint']
237  self.assertListEqual(joint.origin.rpy, [3.1415, 0.123, 42])
238 
239 if __name__ == '__main__':
240  import rosunit
241  rosunit.unitrun(PKG, 'URDF', FrankaRobotUrdfTest)
def assertJointBetween(self, urdf, parent, child, type=None)
def joints_with(self, urdf, predicate)
def test_setting_gazebo_arg_forces_to_have_no_geometries_inside_sc_links(self)
def assertJointHasTransmission(self, urdf, joint, type)
def links_with(self, urdf, predicate)
def assertContainsLink(self, urdf, link)
def assertContainsJoint(self, urdf, joint)
def test_generate_urdf_without_xacro_args_contains_joint1_up_to_joint8(self)
def test_generate_urdf_with_hand_but_not_gazebo_doesnt_insert_inertial_tags_for_any_link(self)
def test_setting_gazebo_arg_with_hand_forces_to_have_no_geometries_inside_sc_links(self)
def xacro(self, file, args='')
def test_generate_urdf_without_tcp_args_uses_default_10_34_cm_hand_tcp_offset(self)
def test_generate_urdf_without_xacro_args_uses_coarse_collision_models_for_sc_links(self)
def test_generate_urdf_without_xacro_args_doesnt_insert_inertial_tags_for_any_link(self)
def collision_geometries(self, urdf, link)


franka_description
Author(s): Franka Emika GmbH
autogenerated on Mon Sep 19 2022 03:05:53