Go to the documentation of this file.00001
00002
00003 import rospy
00004 import numpy
00005 from nav_msgs.msg import Odometry
00006 from geometry_msgs.msg import Quaternion, Point, TransformStamped
00007 import tf
00008 import copy
00009 import threading
00010 from jsk_robot_startup.IIRFilter import IIRFilter
00011 from jsk_robot_startup.odometry_utils import transform_quaternion_to_euler
00012
00013 class OdometryIIRFilter(object):
00014 def __init__(self):
00015 rospy.init_node("OdometryIIRFilter", anonymous=True)
00016
00017 self.rate = float(rospy.get_param("~rate", 100))
00018 self.odom_frame = rospy.get_param("~odom_frame", "filtered_odom")
00019 self.filter_dim = rospy.get_param("~filter_dimension", 2)
00020 self.cutoff = min(float(rospy.get_param("~cutoff", 10)), self.rate / 2.0)
00021 self.odom = None
00022 self.filtered_odom = None
00023 self.prev_rpy = None
00024 self.dt = 0.0
00025 self.r = rospy.Rate(self.rate)
00026 self.lock = threading.Lock()
00027 self.filters = []
00028 for i in range(6):
00029 self.filters.append(IIRFilter(self.filter_dim, self.cutoff / self.rate))
00030
00031 self.publish_tf = rospy.get_param("~publish_tf", True)
00032 if self.publish_tf:
00033 self.invert_tf = rospy.get_param("~invert_tf", True)
00034 self.broadcast = tf.TransformBroadcaster()
00035 self.listener = tf.TransformListener()
00036
00037 self.pub = rospy.Publisher("~output", Odometry, queue_size=10)
00038 self.odom_sub = rospy.Subscriber("~source_odom", Odometry, self.source_odom_callback)
00039 self.init_transform_sub = rospy.Subscriber("~initial_base_link_transform", TransformStamped, self.init_transform_callback)
00040
00041 def initialize_filter(self):
00042 with self.lock:
00043 self.odom = None
00044 self.filtered_odom = None
00045 self.prev_rpy = None
00046 self.filters = []
00047 for i in range(6):
00048 self.filters.append(IIRFilter(self.filter_dim, self.cutoff / self.rate))
00049
00050 def execute(self):
00051 while not rospy.is_shutdown():
00052 self.update()
00053 self.r.sleep()
00054
00055 def init_transform_callback(self, msg):
00056 self.initialize_filter()
00057
00058 def source_odom_callback(self, msg):
00059 with self.lock:
00060 self.odom = msg
00061
00062 def update(self):
00063 with self.lock:
00064 if self.odom == None:
00065 return
00066 current_euler = transform_quaternion_to_euler([self.odom.pose.pose.orientation.x, self.odom.pose.pose.orientation.y, self.odom.pose.pose.orientation.z, self.odom.pose.pose.orientation.w], self.prev_rpy)
00067 current_6d_pose = [self.odom.pose.pose.position.x, self.odom.pose.pose.position.y, self.odom.pose.pose.position.z] + current_euler
00068 for i in range(6):
00069 current_6d_pose[i] = self.filters[i].execute(current_6d_pose[i])
00070 self.filtered_odom = copy.deepcopy(self.odom)
00071 self.filtered_odom.header.frame_id = self.odom_frame
00072 self.filtered_odom.pose.pose.position = Point(*current_6d_pose[:3])
00073 self.filtered_odom.pose.pose.orientation = Quaternion(*tf.transformations.quaternion_from_euler(*current_6d_pose[3:6]))
00074 self.prev_rpy = current_6d_pose[3:6]
00075 self.pub.publish(self.filtered_odom)
00076 if self.publish_tf:
00077 broadcast_transform(self.broadcast, self.filtered_odom, self.invert_tf)