Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 import roslib; roslib.load_manifest('dynamic_tf_publisher')
00011 import rospy
00012 import sys
00013 from dynamic_tf_publisher.srv import *
00014 from geometry_msgs.msg import TransformStamped,Quaternion,Vector3
00015 from std_srvs.srv import Empty, EmptyResponse
00016 import tf
00017 import tf.msg
00018 import thread
00019 from threading import Lock
00020 import yaml
00021
00022 class dynamic_tf_publisher:
00023 def advertiseServiceUnlessFound(self, name, srv, callback):
00024 try:
00025 rospy.wait_for_service(name, 1.0)
00026 rospy.logfatal("%s is already exists" % (name))
00027 sys.exit(1)
00028 except rospy.ROSException, e:
00029 rospy.Service(name, srv, callback)
00030 def __init__(self):
00031 self.pub_tf = rospy.Publisher("/tf", tf.msg.tfMessage, queue_size=1)
00032 self.pub_tf_mine = rospy.Publisher("~tf", tf.msg.tfMessage, queue_size=1)
00033 self.cur_tf = dict()
00034 self.original_parent = dict()
00035 self.update_tf = dict()
00036 self.listener = tf.TransformListener()
00037 self.tf_sleep_time = 1.0
00038 self.lock = Lock()
00039
00040 self.use_cache = rospy.get_param('~use_cache', True)
00041 self.check_update = rospy.get_param('~check_update', False)
00042 self.check_update_sleep_time = rospy.get_param('~check_update_sleep_time', 1.0)
00043 self.check_update_last_update = rospy.Time(0)
00044
00045 if self.use_cache and rospy.has_param('dynamic_tf_publisher'+rospy.get_name()) :
00046 tfm = tf.msg.tfMessage()
00047 roslib.message.fill_message_args(tfm,[yaml.load(rospy.get_param('dynamic_tf_publisher'+rospy.get_name()))])
00048 for pose in tfm.transforms :
00049 self.cur_tf[pose.child_frame_id] = pose
00050 self.advertiseServiceUnlessFound('/set_dynamic_tf', SetDynamicTF, self.set_tf)
00051 self.advertiseServiceUnlessFound('/assoc_tf', AssocTF, self.assoc)
00052 self.advertiseServiceUnlessFound('/publish_tf', Empty, self.publish_tf)
00053 self.advertiseServiceUnlessFound('/dissoc_tf', DissocTF, self.dissoc)
00054 self.advertiseServiceUnlessFound('/delete_tf', DeleteTF, self.delete)
00055
00056 def publish_tf(self, req=None):
00057 with self.lock:
00058 time = rospy.Time.now()
00059 tfm = tf.msg.tfMessage()
00060
00061 if self.check_update:
00062 publish_all = False
00063 if self.check_update_last_update + rospy.Duration(self.check_update_sleep_time) < time:
00064 publish_all = True
00065 self.check_update_last_update = time
00066
00067 for frame_id in self.cur_tf.keys():
00068 if (not self.check_update) or publish_all or self.update_tf[frame_id]:
00069 pose = self.cur_tf[frame_id]
00070 pose.header.stamp = time
00071 tfm.transforms.append(pose)
00072 self.update_tf[frame_id] = False
00073
00074 if len(tfm.transforms) > 0:
00075 self.pub_tf.publish(tfm)
00076 self.pub_tf_mine.publish(tfm)
00077 return EmptyResponse()
00078
00079 def assoc(self,req):
00080 if (not self.cur_tf.has_key(req.child_frame)) or self.cur_tf[req.child_frame] == req.parent_frame:
00081 rospy.logwarn("unkown key %s" % (req.child_frame))
00082 return AssocTFResponse()
00083 rospy.loginfo("assoc %s -> %s"%(req.parent_frame, req.child_frame))
00084 self.listener.waitForTransform(req.parent_frame,
00085 req.child_frame,
00086 req.header.stamp, rospy.Duration(1.0))
00087 ts = TransformStamped()
00088 (trans,rot) = self.listener.lookupTransform(req.parent_frame, req.child_frame, req.header.stamp)
00089 ts.transform.translation = Vector3(*trans)
00090 ts.transform.rotation = Quaternion(*rot)
00091 ts.header.stamp = req.header.stamp
00092 ts.header.frame_id = req.parent_frame
00093 ts.child_frame_id = req.child_frame
00094 with self.lock:
00095 self.original_parent[req.child_frame] = self.cur_tf[req.child_frame].header.frame_id
00096 self.cur_tf[req.child_frame] = ts
00097 self.update_tf[req.child_frame] = True
00098 self.publish_tf()
00099 return AssocTFResponse()
00100
00101 def dissoc(self,req):
00102 areq = None
00103 rospy.loginfo("dissoc TF %s" % (req.frame_id))
00104 with self.lock:
00105 if self.original_parent.has_key(req.frame_id):
00106 areq = AssocTFRequest()
00107 areq.header = req.header
00108 areq.child_frame = req.frame_id
00109 areq.parent_frame = self.original_parent[req.frame_id]
00110 if areq:
00111 self.assoc(areq)
00112 self.original_parent.pop(req.frame_id)
00113 return DissocTFResponse()
00114
00115 def delete(self,req):
00116 rospy.loginfo("delete TF %s"%(req.header.frame_id))
00117 with self.lock:
00118 if self.original_parent.has_key(req.header.frame_id):
00119 del self.original_parent[req.header.frame_id]
00120 if self.cur_tf.has_key(req.header.frame_id):
00121 del self.cur_tf[req.header.frame_id]
00122 if self.update_tf.has_key(req.header.frame_id):
00123 del self.update_tf[req.header.frame_id]
00124 return DeleteTFResponse()
00125
00126 def set_tf(self,req):
00127 rospy.loginfo("%s => %s" % (req.cur_tf.header.frame_id, req.cur_tf.child_frame_id))
00128 with self.lock:
00129
00130 if not self.original_parent.has_key(req.cur_tf.child_frame_id):
00131 self.tf_sleep_time = 1.0/req.freq
00132 self.cur_tf[req.cur_tf.child_frame_id] = req.cur_tf
00133 self.update_tf[req.cur_tf.child_frame_id] = True
00134 rospy.loginfo("Latch [%s]/[%shz]"%(req.cur_tf.child_frame_id,req.freq))
00135
00136 if self.use_cache:
00137 time = rospy.Time.now()
00138 tfm = tf.msg.tfMessage()
00139 for frame_id in self.cur_tf.keys():
00140 pose = self.cur_tf[frame_id]
00141 pose.header.stamp = time
00142 tfm.transforms.append(pose)
00143 rospy.set_param('dynamic_tf_publisher'+rospy.get_name(),tfm.__str__())
00144 return SetDynamicTFResponse()
00145
00146 def publish_and_sleep(self):
00147 self.publish_tf()
00148 rospy.sleep(self.tf_sleep_time)
00149
00150
00151 if __name__ == "__main__":
00152 try:
00153 rospy.init_node('tf_publish_server')
00154 pub = dynamic_tf_publisher()
00155 while not rospy.is_shutdown():
00156 pub.publish_and_sleep()
00157 except rospy.ROSInterruptException:
00158 pass
00159