35 import xml.dom.minidom
38 import sensor_msgs.msg
42 private =
"~%s" % name
43 if rospy.has_param(private):
44 return rospy.get_param(private)
45 elif rospy.has_param(name):
46 return rospy.get_param(name)
53 robot = robot.getElementsByTagName(
'kinematics_model')[0].getElementsByTagName(
'technique_common')[0]
54 for child
in robot.childNodes:
55 if child.nodeType
is child.TEXT_NODE:
57 if child.localName ==
'joint':
58 name = child.getAttribute(
'name')
59 if child.getElementsByTagName(
'revolute'):
60 joint = child.getElementsByTagName(
'revolute')[0]
62 rospy.logwarn(
"Unknown joint type %s", child)
66 limit = joint.getElementsByTagName(
'limits')[0]
67 minval = float(limit.getElementsByTagName(
'min')[0].childNodes[0].nodeValue)
68 maxval = float(limit.getElementsByTagName(
'max')[0].childNodes[0].nodeValue)
72 self.joint_list.append(name)
73 joint = {
'min':minval*math.pi/180.0,
'max':maxval*math.pi/180.0,
'zero':0,
'position':0,
'velocity':0,
'effort':0}
77 robot = robot.getElementsByTagName(
'robot')[0]
79 for child
in robot.childNodes:
80 if child.nodeType
is child.TEXT_NODE:
82 if child.localName ==
'joint':
83 jtype = child.getAttribute(
'type')
84 if jtype
in [
'fixed',
'floating',
'planar']:
86 name = child.getAttribute(
'name')
87 self.joint_list.append(name)
88 if jtype ==
'continuous':
93 limit = child.getElementsByTagName(
'limit')[0]
94 minval = float(limit.getAttribute(
'lower'))
95 maxval = float(limit.getAttribute(
'upper'))
97 rospy.logwarn(
"%s is not fixed, nor continuous, but limits are not specified!" % name)
100 safety_tags = child.getElementsByTagName(
'safety_controller')
101 if self.
use_small and len(safety_tags) == 1:
103 if tag.hasAttribute(
'soft_lower_limit'):
104 minval = max(minval, float(tag.getAttribute(
'soft_lower_limit')))
105 if tag.hasAttribute(
'soft_upper_limit'):
106 maxval = min(maxval, float(tag.getAttribute(
'soft_upper_limit')))
108 mimic_tags = child.getElementsByTagName(
'mimic')
109 if self.
use_mimic and len(mimic_tags) == 1:
111 entry = {
'parent': tag.getAttribute(
'joint')}
112 if tag.hasAttribute(
'multiplier'):
113 entry[
'factor'] = float(tag.getAttribute(
'multiplier'))
114 if tag.hasAttribute(
'offset'):
115 entry[
'offset'] = float(tag.getAttribute(
'offset'))
124 zeroval = self.
zeros[name]
125 elif minval > 0
or maxval < 0:
126 zeroval = (maxval + minval)/2
130 joint = {
'min': minval,
'max': maxval,
'zero': zeroval}
132 joint[
'position'] = zeroval
134 joint[
'velocity'] = 0.0
136 joint[
'effort'] = 0.0
138 if jtype ==
'continuous':
139 joint[
'continuous'] =
True 143 description =
get_param(
'robot_description')
144 if description
is None:
145 raise RuntimeError(
'The robot_description parameter is required and not set.')
159 robot = xml.dom.minidom.parseString(description.encode(
'utf-8'))
160 if robot.getElementsByTagName(
'COLLADA'):
170 source_list =
get_param(
"source_list", [])
172 for source
in source_list:
173 self.sources.append(rospy.Subscriber(source, sensor_msgs.msg.JointState, self.
source_cb))
175 self.
pub = rospy.Publisher(
'joint_states', sensor_msgs.msg.JointState, queue_size=5)
178 for i
in range(len(msg.name)):
184 position = msg.position[i]
188 velocity = msg.velocity[i]
192 effort = msg.effort[i]
197 if position
is not None:
198 joint[
'position'] = position
199 if velocity
is not None:
200 joint[
'velocity'] = velocity
201 if effort
is not None:
202 joint[
'effort'] = effort
217 while not rospy.is_shutdown():
218 msg = sensor_msgs.msg.JointState()
219 msg.header.stamp = rospy.Time.now()
225 has_position = len(self.dependent_joints.items()) > 0
228 for name, joint
in self.free_joints.items():
229 if not has_position
and 'position' in joint:
231 if not has_velocity
and 'velocity' in joint:
233 if not has_effort
and 'effort' in joint:
235 num_joints = (len(self.free_joints.items()) +
236 len(self.dependent_joints.items()))
238 msg.position = num_joints * [0.0]
240 msg.velocity = num_joints * [0.0]
242 msg.effort = num_joints * [0.0]
245 msg.name.append(name)
256 parent = param[
'parent']
257 factor = param.get(
'factor', 1)
258 offset = param.get(
'offset', 0)
260 recursive_mimic_chain_joints = [name]
262 if parent
in recursive_mimic_chain_joints:
263 error_message =
"Found an infinite recursive mimic chain" 264 rospy.logerr(
"%s: [%s, %s]", error_message,
', '.join(recursive_mimic_chain_joints), parent)
266 recursive_mimic_chain_joints.append(parent)
268 parent = param[
'parent']
269 offset += factor * param.get(
'offset', 0)
270 factor *= param.get(
'factor', 1)
273 if has_position
and 'position' in joint:
274 msg.position[i] = joint[
'position'] * factor + offset
275 if has_velocity
and 'velocity' in joint:
276 msg.velocity[i] = joint[
'velocity'] * factor
277 if has_effort
and 'effort' in joint:
278 msg.effort[i] = joint[
'effort']
280 if msg.name
or msg.position
or msg.velocity
or msg.effort:
282 self.pub.publish(msg)
285 except rospy.exceptions.ROSTimeMovedBackwardsException:
289 for name, joint
in self.free_joints.iteritems():
290 forward = joint.get(
'forward',
True)
292 joint[
'position'] += delta
293 if joint[
'position'] > joint[
'max']:
294 if joint.get(
'continuous',
False):
295 joint[
'position'] = joint[
'min']
297 joint[
'position'] = joint[
'max']
298 joint[
'forward'] =
not forward
300 joint[
'position'] -= delta
301 if joint[
'position'] < joint[
'min']:
302 joint[
'position'] = joint[
'min']
303 joint[
'forward'] =
not forward
def get_param(name, value=None)
def init_collada(self, robot)
def set_source_update_cb(self, user_cb)
def init_urdf(self, robot)