imu_recalibration.py
Go to the documentation of this file.
00001 #!/usr/bin/env python
00002 '''
00003 Created on 16.10.2012
00004 
00005 @author: Jochen Sprickerhof <jochen@sprickerhof.de> and Martin Guenther <mguenthe@uos.de>
00006 '''
00007 
00008 import roslib; roslib.load_manifest('imu_recalibration')
00009 import rospy
00010 import tf
00011 from sensor_msgs.msg import Imu
00012 from nav_msgs.msg import Odometry
00013 from math import pi
00014 
00015 class ImuRecalibration:
00016     """
00017     This ROS node recalibrates the IMU (i.e., calculates the IMU drift and
00018     subtracts it) whenever the robot is standing.
00019     """
00020 
00021     # number of IMU messages to average over
00022     NUM_SAMPLES = 100
00023 
00024     # drifts larger than this value are ignored (rad/s)
00025     # (the maximum drift actually measured is 2pi in 120 seconds)
00026     MAX_DELTA = 2.0 * pi / 120.0 / NUM_SAMPLES
00027 
00028     # the robot is considered to be moving if the angular velocity is larger than this (rad/s)
00029     MAX_ANGULAR_VEL = 2.0 * pi / 3600.0
00030 
00031     def __init__(self):
00032         rospy.init_node('imu_recalibration')
00033         rospy.Subscriber("imu", Imu, self.imu_callback)
00034         rospy.Subscriber("odom", Odometry, self.odom_callback)
00035         self.pub = rospy.Publisher('imu_recalibrated', Imu, queue_size=100)
00036         self.error = 0.0
00037         self.delta = 0.0
00038         self.delta_new = 0.0
00039         self.yaw_old = 0.0
00040         self.calibration_counter = -1
00041         #self.debug_file = open('/tmp/imu_recalibration.txt', 'w')
00042         rospy.loginfo('imu_recalibration node initialized.')
00043 
00044     @classmethod
00045     def normalize(cls, angle):
00046         while angle < pi:
00047             angle += 2.0 * pi
00048         while angle > pi:
00049             angle -= 2.0 * pi
00050         return angle
00051 
00052     def imu_callback(self, msg_in):
00053         (r, p, yaw) = tf.transformations.euler_from_quaternion([msg_in.orientation.x,
00054             msg_in.orientation.y, msg_in.orientation.z, msg_in.orientation.w])
00055 
00056         self.calibration_counter += 1
00057         if self.calibration_counter == 0:
00058             # start of calibration interval --> reset
00059             self.delta_new = 0.0
00060         else:
00061             # inside calibration interval --> accumulate
00062             self.delta_new += self.normalize(yaw - self.yaw_old)
00063 
00064         if self.calibration_counter == ImuRecalibration.NUM_SAMPLES:
00065             self.delta_new /= ImuRecalibration.NUM_SAMPLES
00066             # end of calibration interval
00067             if abs(self.delta_new) < ImuRecalibration.MAX_DELTA:
00068                 self.delta = self.delta_new
00069                 rospy.loginfo("New IMU delta: %f" % self.delta)
00070             else:
00071                 # this can happen if the base was switched off and on again
00072                 rospy.logwarn("IMU delta too large, ignoring: %f" % self.delta_new)
00073 
00074             self.calibration_counter = -1
00075 
00076         self.error += self.delta;
00077         self.error = self.normalize(self.error)
00078         self.yaw_old = yaw
00079         yaw_new = self.normalize(yaw - self.error)
00080 
00081         q = tf.transformations.quaternion_from_euler(r, p, yaw_new)
00082         msg_out = msg_in
00083         msg_out.orientation.x = q[0]
00084         msg_out.orientation.y = q[1]
00085         msg_out.orientation.z = q[2]
00086         msg_out.orientation.w = q[3]
00087 
00088         #self.debug_file.write("%s %s %s %s %s %s\n" % (yaw, yaw_new, self.error, self.delta, self.delta_new, self.calibration_counter))
00089         self.pub.publish(msg_out)
00090 
00091     def odom_callback(self, msg):
00092         if abs(msg.twist.twist.angular.z) > ImuRecalibration.MAX_ANGULAR_VEL:
00093             rospy.logdebug("Resetting imu_recalibration (robot is moving)")
00094             self.calibration_counter = -1
00095 
00096 if __name__ == '__main__':
00097     ImuRecalibration()
00098     try:
00099         rospy.spin()
00100     except rospy.ROSInterruptException:
00101         pass


imu_recalibration
Author(s): Martin Günther , Jochen Sprickerhof
autogenerated on Thu Aug 27 2015 13:44:40