CalculateOdomInitToBaseLinkTransform.py
Go to the documentation of this file.
00001 #! /usr/bin/env python
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         # execute rate
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) # init_transform is assumed to be transform of base_odom -> init_odom
00025 
00026     def calculate_init_to_base_link_transform(self, base_odom, base_to_init_transform, stamp):
00027         # tf relationships: init_odom <- base_odom -> base_link
00028         # offset_odom is init_odom -> base_link
00029         # TODO: check timestamps of base_odom and source_odom and fix if necessary
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"]]) # base_odom -> body_link
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"]]) # base_odom -> init_odom
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                 # offset is not initialized
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)


jsk_robot_startup
Author(s):
autogenerated on Sat Jul 1 2017 02:42:18