tf_publish.py
Go to the documentation of this file.
00001 #!/usr/bin/env python
00002 #
00003 # publish static tf which is set by SetDynamicTF service
00004 # publishing tf is uniquely by child_frame_id
00005 #
00006 # TODO: delete target tf
00007 #       check tf tree consistency
00008 #       change frequency by frame_id
00009 #
00010 import roslib; roslib.load_manifest('dynamic_tf_publisher')
00011 import rospy
00012 import sys
00013 from dynamic_tf_publisher.srv import * # SetDynamicTF
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         # check the cache
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) # remove 
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             # if not assocd
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             # set parameter
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 


dynamic_tf_publisher
Author(s): Manabu Saito
autogenerated on Fri Sep 8 2017 03:38:38