00001
00002
00003 import rospy
00004 import numpy
00005 from nav_msgs.msg import Odometry
00006 from geometry_msgs.msg import Quaternion, Vector3, TransformStamped
00007 import tf
00008 import threading
00009 from odometry_utils import make_homogeneous_matrix
00010
00011 class CalculateOdomInitToBaseLinkTransform(object):
00012 def __init__(self):
00013 rospy.init_node("CalculateOdomInitToBaseLinkTransform", anonymous=True)
00014 self.offset_transform = None
00015 self.base_odom = None
00016 self.lock = threading.Lock()
00017 self.odom_frame = rospy.get_param("~init_odom_frame", "odom_init")
00018 self.body_frame = rospy.get_param("~body_link_frame", "BODY")
00019
00020 self.rate = float(rospy.get_param("~rate", 10))
00021 self.r = rospy.Rate(self.rate)
00022 self.pub = rospy.Publisher("~output", TransformStamped, queue_size = 1, latch = True)
00023 self.base_odom_sub = rospy.Subscriber("~base_odom", Odometry, self.base_odom_callback)
00024 self.base_to_init_transform_sub = rospy.Subscriber("~base_to_init_transform", TransformStamped, self.base_to_init_transform_callback)
00025
00026 def calculate_init_to_base_link_transform(self, base_odom, base_to_init_transform, stamp):
00027
00028
00029
00030 if base_odom == None or base_to_init_transform == None:
00031 return None
00032 base_odom_matrix = make_homogeneous_matrix([getattr(self.base_odom.pose.pose.position, attr) for attr in ["x", "y", "z"]], [getattr(self.base_odom.pose.pose.orientation, attr) for attr in ["x", "y", "z", "w"]])
00033 offset_matrix = numpy.linalg.inv(base_to_init_transform).dot(base_odom_matrix)
00034 trans = list(offset_matrix[:3, 3])
00035 rot = list(tf.transformations.quaternion_from_matrix(offset_matrix))
00036 offset_transform = TransformStamped()
00037 offset_transform.header.stamp = stamp
00038 offset_transform.header.frame_id = self.odom_frame
00039 offset_transform.child_frame_id = self.body_frame
00040 offset_transform.transform.translation = Vector3(*trans)
00041 offset_transform.transform.rotation = Quaternion(*rot)
00042 return offset_transform
00043
00044 def execute(self):
00045 while not rospy.is_shutdown():
00046 self.r.sleep()
00047
00048 def base_to_init_transform_callback(self, msg):
00049 with self.lock:
00050 base_to_init_transform = make_homogeneous_matrix([getattr(msg.transform.translation, attr) for attr in ["x", "y", "z"]], [getattr(msg.transform.rotation, attr) for attr in ["x", "y", "z", "w"]])
00051 self.offset_transform = self.calculate_init_to_base_link_transform(self.base_odom, base_to_init_transform, msg.header.stamp)
00052 if self.offset_transform != None:
00053 self.pub.publish(self.offset_transform)
00054
00055 def base_odom_callback(self, msg):
00056 with self.lock:
00057 self.base_odom = msg
00058 if not self.offset_transform:
00059
00060 base_to_init_transform = make_homogeneous_matrix([0, 0, 0], [0, 0, 0, 1])
00061 self.offset_transform = self.calculate_init_to_base_link_transform(self.base_odom, base_to_init_transform, msg.header.stamp)
00062 if self.offset_transform != None:
00063 self.pub.publish(self.offset_transform)