imu2pose.py
Go to the documentation of this file.
00001 #!/usr/bin/env python
00002 import roslib
00003 roslib.load_manifest('iri_msg_to_odom')
00004 import os
00005 import sys
00006 import rospy
00007 import tf
00008 from sensor_msgs.msg import Imu
00009 from iri_segway_rmp_msgs.msg import SegwayRMP400Status
00010 from geometry_msgs.msg import PoseStamped,Quaternion,Vector3
00011 from tf.transformations import euler_from_quaternion
00012 import math
00013 
00014 
00015 #  -------------------------------------------
00016 #  node: imu2pose.py
00017 #  author: Marti Morta (mmorta@iri.upc.edu)
00018 #  date: 25 Jun 2013
00019 #  -------------------------------------------
00020 #
00021 #   This node converts imu and segway data to ready to be plot data
00022 #   
00023 #   <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
00024 #   Subscribers
00025 #     imu: Imu topic
00026 #     segway rmp400 status: SegwayRMP400Status topic
00027 #     
00028 #   >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
00029 #   Publishers
00030 #     imu_pose: PoseStamped as 0 and imu orientation. Rviz axes
00031 #     imu_angles: Vector of roll,pitch,yaw angles from Imu orientation quaternion. Rxplot
00032 #     imu_angles_from_vel: RPY from the integration of Imu angular velocities. Rxplot
00033 #     segway_angles_from_vel: RPY from the integratino of Segway's angular velocities. Rxplot
00034 #     
00035 #   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
00036 #   Parameters:
00037 #     use_degrees: Publishes the angles in degrees
00038 #     use_first_only: In segway's angles calculation use only the first base
00039 #     use_second_only: In segway's angles calculation use only the second base
00040 #   
00041 
00042 # Set Publishers
00043 p_p = rospy.Publisher('imu_pose', PoseStamped)
00044 p_a = rospy.Publisher('imu_angles', Vector3)
00045 p_A = rospy.Publisher('imu_angles_from_vel', Vector3)
00046 p_s = rospy.Publisher('segway_angles_from_vel', Vector3)
00047 
00048 # IMU Callback function
00049 #   pre: imu message
00050 #   post: 1) Imu orientation as PoseStamped
00051 #         2) RPY from Imu orientation quaternion
00052 #         3) RPY from Imu angular velocities integration
00053 def callback_imu(data):
00054   # 
00055   # 1)
00056   # 
00057   # Set transform position between /teo/imu2 (=/teo/imu), frame where the axes will be attached, and base_link
00058   br = tf.TransformBroadcaster()
00059   br.sendTransform((0.0, 0.0, 0.0),(0.0, 0.0, -0.7071, 0.7071), rospy.Time.now(), "/teo/imu2", "/teo/base_link")
00060   # cook the message
00061   imu_pose.header = data.header
00062   imu_pose.header.frame_id = "/teo/imu2"  
00063   imu_pose.pose.orientation  = data.orientation
00064   # >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
00065   p_p.publish(imu_pose)
00066   # >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
00067   #  
00068   # 2)
00069   # 
00070   # Transform the data
00071   q = [data.orientation.x, data.orientation.y, data.orientation.z, data.orientation.w]
00072   imu_angles.x, imu_angles.y,imu_angles.z = euler_from_quaternion(q)
00073   # Adapt message for degrees/radians and x (roll) for plot reading convenience
00074   if (use_degrees):
00075     if imu_angles.x <0:
00076       imu_angles.x = 360+math.degrees(imu_angles.x) # trick
00077     else:
00078       imu_angles.x = math.degrees(imu_angles.x)
00079     imu_angles.y = math.degrees(imu_angles.y)
00080     imu_angles.z = math.degrees(imu_angles.z)
00081   else:
00082     if imu_angles.x <0:
00083       imu_angles.x = 2*math.pi+imu_angles.x # trick
00084     else:
00085       imu_angles.x = imu_angles.x
00086   # >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
00087   p_a.publish(imu_angles)
00088   # >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
00089   #
00090   # 3)
00091   # 
00092   global imu_last_time, imu_angles_from_vel
00093   # Calculate time delta
00094   current_time = data.header.stamp
00095   dt = (current_time - imu_last_time).to_sec()
00096   imu_last_time = current_time
00097   # Avoid huge first value
00098   if math.fabs(dt)>1: dt = 0 # trick
00099   # Cook the message
00100   imu_angles_from_vel.x += data.angular_velocity.x*dt
00101   imu_angles_from_vel.y -= data.angular_velocity.y*dt
00102   imu_angles_from_vel.z -= data.angular_velocity.z*dt
00103   # >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
00104   p_A.publish(imu_angles_from_vel)
00105   # >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
00106   
00107 
00108 # Segway Callback function
00109 #   pre: segway status message
00110 #   post: 1) RPY from segway angular velocities integration
00111 def callback_seg(data):
00112   # 
00113   # 1)
00114   # 
00115   global seg_last_time, segway_angles_from_vel
00116   # Calculate time delta
00117   current_time = data.rmp200[0].uptime
00118   dt = current_time - seg_last_time
00119   seg_last_time = current_time
00120   # Avoid huge first value
00121   if math.fabs(dt)>1: dt = 0 # trick
00122   # Cook the message
00123   if (use_first_only):
00124     segway_angles_from_vel.x += data.rmp200[0].roll_rate*dt
00125     segway_angles_from_vel.y += data.rmp200[0].pitch_rate*dt
00126     segway_angles_from_vel.z -= data.rmp200[0].yaw_rate*dt
00127   elif (use_second_only):
00128     segway_angles_from_vel.x += data.rmp200[1].roll_rate*dt
00129     segway_angles_from_vel.y += data.rmp200[1].pitch_rate*dt
00130     segway_angles_from_vel.z -= data.rmp200[1].yaw_rate*dt
00131   else:
00132     segway_angles_from_vel.x += (data.rmp200[1].roll_rate+data.rmp200[0].roll_rate)/2*dt
00133     segway_angles_from_vel.y += (data.rmp200[1].pitch_rate+data.rmp200[0].pitch_rate)/2*dt
00134     segway_angles_from_vel.z -= (data.rmp200[1].yaw_rate+data.rmp200[0].yaw_rate)/2*dt
00135   #>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
00136   p_s.publish(segway_angles_from_vel)
00137   #>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
00138   
00139 
00140 # Main function
00141 #   pre: -
00142 #   post: -
00143 def main(args):
00144   #
00145   # Init Node
00146   # 
00147   rospy.init_node('imu2pose')
00148   rospy.loginfo("IMU 2 POSE Node started")
00149   r = rospy.Rate(10) # 10hz
00150   #
00151   # Init variables
00152   #
00153   global imu_pose, imu_angles, imu_angles_from_vel, segway_angles_from_vel
00154   imu_pose = PoseStamped()
00155   imu_angles = Vector3()
00156   imu_angles_from_vel = Vector3()
00157   imu_angles_from_vel.x = imu_angles_from_vel.y = imu_angles_from_vel.z = 0
00158   segway_angles_from_vel = Vector3()
00159   segway_angles_from_vel.x = segway_angles_from_vel.y = segway_angles_from_vel.z = 0
00160   global imu_last_time, seg_last_time
00161   imu_last_time = rospy.Time()
00162   imu_last_time = rospy.Time.now()
00163   seg_last_time = 0
00164   global use_degrees, use_first_only, use_second_only
00165   use_degrees = rospy.get_param('use_degrees', 'False')
00166   use_first_only = rospy.get_param('use_first_only', 'False')
00167   use_second_only = rospy.get_param('use_second_only', 'False')
00168   #
00169   # <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
00170   rospy.Subscriber('imu', Imu, callback_imu)
00171   rospy.Subscriber('status', SegwayRMP400Status, callback_seg)
00172   # <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
00173   #
00174   # Spin!
00175   # 
00176   rospy.spin()
00177 
00178 
00179 if __name__ == '__main__':
00180     main(sys.argv)


iri_msg_to_odom
Author(s): Marti Morta, mmorta at iri.upc.edu
autogenerated on Fri Dec 6 2013 22:08:38