tf_publish.py
Go to the documentation of this file.
1 #!/usr/bin/env python
2 #
3 # publish static tf which is set by SetDynamicTF service
4 # publishing tf is uniquely by child_frame_id
5 #
6 # TODO: delete target tf
7 # check tf tree consistency
8 # change frequency by frame_id
9 #
10 import roslib; roslib.load_manifest('dynamic_tf_publisher')
11 import rospy
12 import sys
13 from dynamic_tf_publisher.srv import * # SetDynamicTF
14 from geometry_msgs.msg import TransformStamped,Quaternion,Vector3
15 from std_srvs.srv import Empty, EmptyResponse
16 import tf
17 import tf.msg
18 import thread
19 from threading import Lock
20 import yaml
21 
23  def advertiseServiceUnlessFound(self, name, srv, callback):
24  try:
25  rospy.wait_for_service(name, 1.0)
26  rospy.logfatal("%s is already exists" % (name))
27  sys.exit(1)
28  except rospy.ROSException, e:
29  rospy.Service(name, srv, callback)
30  def __init__(self):
31  self.pub_tf = rospy.Publisher("/tf", tf.msg.tfMessage, queue_size=1)
32  self.pub_tf_mine = rospy.Publisher("~tf", tf.msg.tfMessage, queue_size=1)
33  self.cur_tf = dict()
34  self.original_parent = dict()
35  self.update_tf = dict()
37  self.tf_sleep_time = 1.0
38  self.lock = Lock()
39 
40  self.use_cache = rospy.get_param('~use_cache', True)
41  self.check_update = rospy.get_param('~check_update', False)
42  self.check_update_sleep_time = rospy.get_param('~check_update_sleep_time', 1.0)
43  self.check_update_last_update = rospy.Time(0)
44  # check the cache
45  if self.use_cache and rospy.has_param('dynamic_tf_publisher'+rospy.get_name()) :
46  tfm = tf.msg.tfMessage()
47  roslib.message.fill_message_args(tfm,[yaml.load(rospy.get_param('dynamic_tf_publisher'+rospy.get_name()))])
48  for pose in tfm.transforms :
49  self.cur_tf[pose.child_frame_id] = pose
50  self.advertiseServiceUnlessFound('/set_dynamic_tf', SetDynamicTF, self.set_tf)
51  self.advertiseServiceUnlessFound('/assoc_tf', AssocTF, self.assoc)
52  self.advertiseServiceUnlessFound('/publish_tf', Empty, self.publish_tf)
53  self.advertiseServiceUnlessFound('/dissoc_tf', DissocTF, self.dissoc)
54  self.advertiseServiceUnlessFound('/delete_tf', DeleteTF, self.delete)
55 
56  def publish_tf(self, req=None):
57  with self.lock:
58  time = rospy.Time.now()
59  tfm = tf.msg.tfMessage()
60 
61  if self.check_update:
62  publish_all = False
63  if self.check_update_last_update + rospy.Duration(self.check_update_sleep_time) < time:
64  publish_all = True
65  self.check_update_last_update = time
66 
67  for frame_id in self.cur_tf.keys():
68  if (not self.check_update) or publish_all or self.update_tf[frame_id]:
69  pose = self.cur_tf[frame_id]
70  pose.header.stamp = time
71  tfm.transforms.append(pose)
72  self.update_tf[frame_id] = False
73 
74  if len(tfm.transforms) > 0:
75  self.pub_tf.publish(tfm)
76  self.pub_tf_mine.publish(tfm)
77  return EmptyResponse()
78 
79  def assoc(self,req):
80  if (not self.cur_tf.has_key(req.child_frame)) or self.cur_tf[req.child_frame] == req.parent_frame:
81  rospy.logwarn("unkown key %s" % (req.child_frame))
82  return AssocTFResponse()
83  rospy.loginfo("assoc %s -> %s"%(req.parent_frame, req.child_frame))
84  self.listener.waitForTransform(req.parent_frame,
85  req.child_frame,
86  req.header.stamp, rospy.Duration(1.0))
87  ts = TransformStamped()
88  (trans,rot) = self.listener.lookupTransform(req.parent_frame, req.child_frame, req.header.stamp)
89  ts.transform.translation = Vector3(*trans)
90  ts.transform.rotation = Quaternion(*rot)
91  ts.header.stamp = req.header.stamp
92  ts.header.frame_id = req.parent_frame
93  ts.child_frame_id = req.child_frame
94  with self.lock:
95  self.original_parent[req.child_frame] = self.cur_tf[req.child_frame].header.frame_id
96  self.cur_tf[req.child_frame] = ts
97  self.update_tf[req.child_frame] = True
98  self.publish_tf()
99  return AssocTFResponse()
100 
101  def dissoc(self,req):
102  areq = None
103  rospy.loginfo("dissoc TF %s" % (req.frame_id))
104  with self.lock:
105  if self.original_parent.has_key(req.frame_id):
106  areq = AssocTFRequest()
107  areq.header = req.header
108  areq.child_frame = req.frame_id
109  areq.parent_frame = self.original_parent[req.frame_id]
110  if areq:
111  self.assoc(areq)
112  self.original_parent.pop(req.frame_id) # remove
113  return DissocTFResponse()
114 
115  def delete(self,req):
116  rospy.loginfo("delete TF %s"%(req.header.frame_id))
117  with self.lock:
118  if self.original_parent.has_key(req.header.frame_id):
119  del self.original_parent[req.header.frame_id]
120  if self.cur_tf.has_key(req.header.frame_id):
121  del self.cur_tf[req.header.frame_id]
122  if self.update_tf.has_key(req.header.frame_id):
123  del self.update_tf[req.header.frame_id]
124  return DeleteTFResponse()
125 
126  def set_tf(self,req):
127  rospy.loginfo("%s => %s" % (req.cur_tf.header.frame_id, req.cur_tf.child_frame_id))
128  with self.lock:
129  # if not assocd
130  if not self.original_parent.has_key(req.cur_tf.child_frame_id):
131  self.tf_sleep_time = 1.0/req.freq
132  self.cur_tf[req.cur_tf.child_frame_id] = req.cur_tf
133  self.update_tf[req.cur_tf.child_frame_id] = True
134  rospy.loginfo("Latch [%s]/[%shz]"%(req.cur_tf.child_frame_id,req.freq))
135  # set parameter
136  if self.use_cache:
137  time = rospy.Time.now()
138  tfm = tf.msg.tfMessage()
139  for frame_id in self.cur_tf.keys():
140  pose = self.cur_tf[frame_id]
141  pose.header.stamp = time
142  tfm.transforms.append(pose)
143  rospy.set_param('dynamic_tf_publisher'+rospy.get_name(),tfm.__str__())
144  return SetDynamicTFResponse()
145 
146  def publish_and_sleep(self):
147  self.publish_tf()
148  rospy.sleep(self.tf_sleep_time)
149 
150 
151 if __name__ == "__main__":
152  try:
153  rospy.init_node('tf_publish_server')
155  while not rospy.is_shutdown():
156  pub.publish_and_sleep()
157  except rospy.ROSInterruptException:
158  pass
159 
def advertiseServiceUnlessFound(self, name, srv, callback)
Definition: tf_publish.py:23
def publish_tf(self, req=None)
Definition: tf_publish.py:56


dynamic_tf_publisher
Author(s): Manabu Saito
autogenerated on Tue Feb 6 2018 03:44:59