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
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 import yaml
00020 import os
00021 if os.getenv('ROS_DISTRO') != 'electric' :
00022 import genpy
00023
00024 class dynamic_tf_publisher:
00025 def __init__(self):
00026 self.pub_tf = rospy.Publisher("/tf", tf.msg.tfMessage)
00027 self.pub_tf_mine = rospy.Publisher("~tf", tf.msg.tfMessage)
00028 self.cur_tf = dict()
00029 self.original_parent = dict()
00030 self.update_tf = dict()
00031 self.listener = tf.TransformListener()
00032 self.tf_sleep_time = 1.0
00033 self.lockobj = thread.allocate_lock()
00034 rospy.Service('/set_dynamic_tf', SetDynamicTF, self.set_tf)
00035 rospy.Service('/assoc_tf', AssocTF, self.assoc)
00036 rospy.Service('/publish_tf', Empty, self.publish_tf)
00037 rospy.Service('/dissoc_tf', DissocTF, self.dissoc)
00038 rospy.Service('/delete_tf', DeleteTF, self.delete)
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 if os.getenv('ROS_DISTRO') != 'electric' :
00048 genpy.message.fill_message_args(tfm,[yaml.load(rospy.get_param('dynamic_tf_publisher'+rospy.get_name()))])
00049 else :
00050 roslib.message.fill_message_args(tfm,[yaml.load(rospy.get_param('dynamic_tf_publisher'+rospy.get_name()))])
00051 for pose in tfm.transforms :
00052 self.cur_tf[pose.child_frame_id] = pose
00053
00054 def publish_tf(self, req=None):
00055 self.lockobj.acquire()
00056 time = rospy.Time.now()
00057 tfm = tf.msg.tfMessage()
00058
00059 if self.check_update:
00060 publish_all = False
00061 if self.check_update_last_update + rospy.Duration(self.check_update_sleep_time) < time:
00062 publish_all = True
00063 self.check_update_last_update = time
00064
00065 for frame_id in self.cur_tf.keys():
00066 if (not self.check_update) or publish_all or self.update_tf[frame_id]:
00067 pose = self.cur_tf[frame_id]
00068 pose.header.stamp = time
00069 tfm.transforms.append(pose)
00070 self.update_tf[frame_id] = False
00071
00072 if len(tfm.transforms) > 0:
00073 self.pub_tf.publish(tfm)
00074 self.pub_tf_mine.publish(tfm)
00075 self.lockobj.release()
00076 return EmptyResponse()
00077
00078 def assoc(self,req):
00079 if (not self.cur_tf.has_key(req.child_frame)) or self.cur_tf[req.child_frame] == req.parent_frame:
00080 rospy.logwarn("unkown key %s" % (req.child_frame))
00081 return AssocTFResponse()
00082 rospy.loginfo("assoc %s -> %s"%(req.parent_frame, req.child_frame))
00083 self.listener.waitForTransform(req.parent_frame,
00084 req.child_frame,
00085 req.header.stamp, rospy.Duration(1.0))
00086 ts = TransformStamped()
00087 (trans,rot) = self.listener.lookupTransform(req.parent_frame, req.child_frame, req.header.stamp)
00088 ts.transform.translation = Vector3(*trans)
00089 ts.transform.rotation = Quaternion(*rot)
00090 ts.header.stamp = req.header.stamp
00091 ts.header.frame_id = req.parent_frame
00092 ts.child_frame_id = req.child_frame
00093 self.lockobj.acquire()
00094 self.original_parent[req.child_frame] = self.cur_tf[req.child_frame].header.frame_id
00095 self.cur_tf[req.child_frame] = ts
00096 self.update_tf[req.child_frame] = True
00097 self.lockobj.release()
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 self.lockobj.acquire()
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 self.lockobj.release()
00111 if areq:
00112 self.assoc(areq)
00113 self.original_parent.pop(req.frame_id)
00114 return DissocTFResponse()
00115
00116 def delete(self,req):
00117 rospy.loginfo("delete TF %s"%(req.header.frame_id))
00118 self.lockobj.acquire()
00119 if self.original_parent.has_key(req.header.frame_id):
00120 del self.original_parent[req.header.frame_id]
00121 if self.cur_tf.has_key(req.header.frame_id):
00122 del self.cur_tf[req.header.frame_id]
00123 if self.update_tf.has_key(req.header.frame_id):
00124 del self.update_tf[req.header.frame_id]
00125 self.lockobj.release()
00126 return DeleteTFResponse()
00127
00128 def set_tf(self,req):
00129 self.lockobj.acquire()
00130
00131 if not self.original_parent.has_key(req.cur_tf.child_frame_id):
00132 self.tf_sleep_time = 1.0/req.freq
00133 self.cur_tf[req.cur_tf.child_frame_id] = req.cur_tf
00134 self.update_tf[req.cur_tf.child_frame_id] = True
00135 print "Latch [%s]/[%shz]"%(req.cur_tf.child_frame_id,req.freq)
00136 self.lockobj.release()
00137
00138 if self.use_cache:
00139 time = rospy.Time.now()
00140 tfm = tf.msg.tfMessage()
00141 for frame_id in self.cur_tf.keys():
00142 pose = self.cur_tf[frame_id]
00143 pose.header.stamp = time
00144 tfm.transforms.append(pose)
00145 rospy.set_param('dynamic_tf_publisher'+rospy.get_name(),tfm.__str__())
00146 return SetDynamicTFResponse()
00147
00148 def publish_and_sleep(self):
00149 self.publish_tf()
00150 rospy.sleep(self.tf_sleep_time)
00151
00152
00153 if __name__ == "__main__":
00154 rospy.init_node('tf_publish_server')
00155 pub = dynamic_tf_publisher()
00156 while not rospy.is_shutdown():
00157 pub.publish_and_sleep()
00158 print "exit"
00159