Skip to content

Commit fae5af2

Browse files
Example for publishing URDF Fragment from python
This examples shows how to take a URDF fragment and send it into the robot via URDFConfiguration message. That segment will then get incorporated into the robot's internal URDF model. This is mostly useful for reconfiguring the end effector or replacing Baxter's pedestal with a mobile base.
1 parent e11a8d8 commit fae5af2

File tree

3 files changed

+113
-0
lines changed

3 files changed

+113
-0
lines changed

CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ find_package(catkin
55
REQUIRED
66
COMPONENTS
77
rospy
8+
xacro
89
actionlib
910
sensor_msgs
1011
control_msgs
@@ -24,6 +25,7 @@ generate_dynamic_reconfigure_options(
2425
catkin_package(
2526
CATKIN_DEPENDS
2627
rospy
28+
xacro
2729
actionlib
2830
sensor_msgs
2931
control_msgs

package.xml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
<buildtool_depend>catkin</buildtool_depend>
2323

2424
<build_depend>rospy</build_depend>
25+
<build_depend>xacro</build_depend>
2526
<build_depend>actionlib</build_depend>
2627
<build_depend>sensor_msgs</build_depend>
2728
<build_depend>control_msgs</build_depend>
@@ -32,6 +33,7 @@
3233
<build_depend>baxter_interface</build_depend>
3334

3435
<run_depend>rospy</run_depend>
36+
<run_depend>xacro</run_depend>
3537
<run_depend>actionlib</run_depend>
3638
<run_depend>sensor_msgs</run_depend>
3739
<run_depend>control_msgs</run_depend>

scripts/send_urdf_fragment.py

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
#!/usr/bin/python2
2+
3+
# Copyright (c) 2013-2015, Rethink Robotics
4+
# All rights reserved.
5+
#
6+
# Redistribution and use in source and binary forms, with or without
7+
# modification, are permitted provided that the following conditions are met:
8+
#
9+
# 1. Redistributions of source code must retain the above copyright notice,
10+
# this list of conditions and the following disclaimer.
11+
# 2. Redistributions in binary form must reproduce the above copyright
12+
# notice, this list of conditions and the following disclaimer in the
13+
# documentation and/or other materials provided with the distribution.
14+
# 3. Neither the name of the Rethink Robotics nor the names of its
15+
# contributors may be used to endorse or promote products derived from
16+
# this software without specific prior written permission.
17+
#
18+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19+
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20+
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21+
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
22+
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23+
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24+
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25+
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26+
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27+
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28+
# POSSIBILITY OF SUCH DAMAGE.
29+
30+
import os
31+
import sys
32+
import argparse
33+
34+
import rospy
35+
import xacro_jade
36+
37+
from baxter_core_msgs.msg import (
38+
URDFConfiguration,
39+
)
40+
41+
def xacro_parse(filename):
42+
doc = xacro_jade.parse(None, filename)
43+
xacro_jade.process_doc(doc, in_order=True)
44+
return doc.toprettyxml(indent=' ')
45+
46+
def send_urdf(parent_link, root_joint, urdf_filename):
47+
"""
48+
Send the URDF Fragment located at the specified path to
49+
modify the electric gripper on Baxter.
50+
51+
@param parent_link: parent link to attach the URDF fragment to
52+
(usually <side>_hand)
53+
@param root_joint: root link of the URDF fragment (usually <side>_gripper_base)
54+
@param urdf_filename: path to the urdf XML file to load into xacro and send
55+
"""
56+
msg = URDFConfiguration()
57+
# The updating the time parameter tells
58+
# the robot that this is a new configuration.
59+
# Only update the time when an updated internal
60+
# model is required. Do not continuously update
61+
# the time parameter.
62+
msg.time = rospy.Time.now()
63+
# link to attach this urdf to onboard the robot
64+
msg.link = parent_link
65+
# root linkage in your URDF Fragment
66+
msg.joint = root_joint
67+
msg.urdf = xacro_parse(urdf_filename)
68+
pub = rospy.Publisher('/robot/urdf', URDFConfiguration, queue_size=10)
69+
rate = rospy.Rate(5) # 5hz
70+
while not rospy.is_shutdown():
71+
# Only one publish is necessary, but here we
72+
# will continue to publish until ctrl+c is invoked
73+
pub.publish(msg)
74+
rate.sleep()
75+
76+
def main():
77+
"""RSDK URDF Fragment Example:
78+
This example shows a proof of concept for
79+
adding your URDF fragment to the robot's
80+
onboard URDF (which is currently in use).
81+
"""
82+
arg_fmt = argparse.RawDescriptionHelpFormatter
83+
parser = argparse.ArgumentParser(formatter_class=arg_fmt,
84+
description=main.__doc__)
85+
required = parser.add_argument_group('required arguments')
86+
required.add_argument(
87+
'-f', '--file', metavar='PATH', required=True,
88+
help='Path to URDF file to send'
89+
)
90+
required.add_argument(
91+
'-l', '--link', required=False, default="left_hand"
92+
help='URDF Link already to attach fragment to (usually <left/right>_hand)'
93+
)
94+
required.add_argument(
95+
'-j', '--joint', required=False, defult"left_gripper_base"
96+
help='Root joint for fragment (usually <left/right>_gripper_base)'
97+
)
98+
args = parser.parse_args(rospy.myargv()[1:])
99+
100+
rospy.init_node('rsdk_configure_urdf', anonymous=True)
101+
102+
if not os.access(args.file, os.R_OK):
103+
rospy.logerr("Cannot read file at '%s'" % (args.file,))
104+
return 1
105+
send_urdf(args.joint, args.link, args.file)
106+
return 0
107+
108+
if __name__ == '__main__':
109+
sys.exit(main())

0 commit comments

Comments
 (0)