00001 /* 00002 * IMUDataProcessor.cpp 00003 * 00004 * Created on: Aug 16, 2012 00005 * Author: mriedel 00006 */ 00007 00008 #include "IMUDataProcessor.hpp" 00009 00010 // ROS Module 00011 #include <telekyb_base/ROS/ROSModule.hpp> 00012 00013 00014 // Defines 00015 #define ACCEL_CENTER 512 00016 #define ACCEL_MAX 1024 00017 #define GYRO_CENTER 512 00018 #define GYRO_MAX 1024 00019 00020 00021 00022 namespace TELEKYB_NAMESPACE { 00023 00024 IMUDataProcessor::IMUDataProcessor() 00025 : driftEstimRunning(true) 00026 { 00027 ros::NodeHandle n = ROSModule::Instance().getMainNodeHandle(); 00028 // create publisher 00029 imuPublisher = n.advertise<tk_draft_msgs::TKSmallImu>(options.tTopicName->getValue() ,10); 00030 } 00031 00032 IMUDataProcessor::~IMUDataProcessor() { 00033 // TODO Auto-generated destructor stub 00034 } 00035 00036 00037 bool IMUDataProcessor::init() { 00038 00039 if (options.tInitialDriftEstim->getValue()) { 00040 Eigen::Vector3d gyroOffsets = options.tGyroOffsets->getValue(); 00041 if (calibrator.driftEstimation(gyroOffsets)) { 00042 // set again after successful calibration 00043 options.tGyroOffsets->setValue(gyroOffsets); 00044 //ROS_INFO_STREAM(options.tGyroOffsets->getValue()); 00045 } else { 00046 // calibration failed 00047 ROS_ERROR("An Error occurred during Gyro Drift Estimation"); 00048 return false; 00049 } 00050 } 00051 00052 driftEstimRunning = false; 00053 return true; 00054 } 00055 00056 void IMUDataProcessor::processRawIMUData(const RawImuData& data) 00057 { 00058 if (driftEstimRunning) { 00059 // forward to calibrator 00060 calibrator.processRawIMUData(data); 00061 return; 00062 } 00063 00064 // Normal mode 00065 00066 // Calculate SI Data 00067 Eigen::Vector3d accelData(data.accX, data.accY, data.accZ); 00068 Eigen::Vector3d gyroData(data.gyroRoll, data.gyroPitch, data.gyroYaw); 00069 00070 // Offsets 00071 accelData -= options.tAccOffsets->getValue(); 00072 gyroData -= options.tGyroOffsets->getValue(); 00073 00074 //ROS_INFO_STREAM("Acc: " << std::endl << accelData); 00075 00076 // Scale 00077 gyroData = (gyroData / GYRO_MAX) - Eigen::Vector3d::Constant(0.5); 00078 gyroData *= options.tGyroScale->getValue(); 00079 00080 accelData = (accelData / ACCEL_MAX) - Eigen::Vector3d::Constant(0.5); 00081 accelData *= options.tAccScale->getValue(); 00082 00083 // ROS_INFO_STREAM("Gyro: " << std::endl << gyroData); 00084 // ROS_INFO_STREAM("Accel: " << std::endl << accelData); 00085 00086 // process IMU Data 00087 rosMsg.header.stamp = ros::Time::now(); 00088 00089 // Acc 00090 rosMsg.linear_acceleration.x = -accelData(0); 00091 rosMsg.linear_acceleration.y = -accelData(1); 00092 rosMsg.linear_acceleration.z = -accelData(2); 00093 00094 // Gyro 00095 rosMsg.angular_velocity.x = -gyroData(0); // roll inverted 00096 rosMsg.angular_velocity.y = -gyroData(1); // pitch inverted 00097 rosMsg.angular_velocity.z = gyroData(2); 00098 00099 imuPublisher.publish(rosMsg); 00100 } 00101 00102 //bool IMUDataProcessor::driftEstimation() 00103 //{ 00104 // Timer timeoutTimer; 00105 // 00106 // while(timeoutTimer.getElapsed().toDSec() < options.tDriftEstimTimeout->getValue()) { 00107 // 00108 // if (driftEstimDone.x && driftEstimDone.y && driftEstimDone.z) { 00109 // // all done 00110 // //ROS_INFO("Successfully did driftEstimation!"); 00111 // returnValue = true; 00112 // break; 00113 // } 00114 // 00115 // 00116 // usleep(1000); 00117 // } 00118 // 00119 // 00120 // return true; 00121 //} 00122 00123 //void IMUDataProcessor::attitudeEstimation(const RawImuData& data) 00124 //{ 00125 // Time passed = elapsedTime.getElapsed(); 00126 // elapsedTime.reset(); 00127 // 00128 // /************* ROLL ************/ 00129 // rollDot_acc = ACC_FILT_GAIN * c_asin(data.accY - ACCEL_OFFSET_ROLL) - (ACC_FILT_GAIN * estRoll); 00130 // estRollVel = (-(data.gyroRoll - GYRO_OFFSET) * GYRO_SCALING) / GYRO_ZERO_VAL + driftRoll; 00131 // estRollVel = GYRO_MULT_NUM*estRollVel/GYRO_MULT_DEN; 00132 // 00133 // rollDot = rollDot_acc + estRollVel; 00134 // estRoll = estRoll + (rollDot * passed.toDSec()); //estimation in 10000 parts of degrees 00135 // 00136 // 00137 // /************* PITCH ************/ 00138 // pitchDot_acc = -ACC_FILT_GAIN *c_asin(data.accX - ACCEL_OFFSET_PITCH) - (ACC_FILT_GAIN*estPitch); 00139 // estPitchVel=(-(data.gyroPitch - GYRO_OFFSET) * GYRO_SCALING) / GYRO_ZERO_VAL + driftPitch; 00140 // estPitchVel = GYRO_MULT_NUM*estPitchVel/GYRO_MULT_DEN; 00141 // 00142 // pitchDot = pitchDot_acc + estPitchVel; 00143 // estPitch = estPitch + (pitchDot * passed.toDSec()); 00144 // 00145 // if (outputTimer.getElapsed().toDSec() > 0.1) 00146 // { 00147 // ROS_INFO("EstRoll: %04f", (double)estRoll/100000); 00148 // ROS_INFO("EstPitch: %04f", (double)estPitch/100000); 00149 // outputTimer.reset(); 00150 // } 00151 // /************* YAW ************/ 00152 // estYawVel=((data.gyroYaw - GYRO_OFFSET) * GYRO_SCALING) / GYRO_ZERO_VAL + driftYaw; 00153 // 00154 // /*** first-order low pass filtering of the angular velocity, to be used in the control loop, frequency at wn rad/s ***/ 00155 // estRollVel_fil += (LOW_PASS_SCALING*(estRollVel - estRollVel_fil))/(485); 00156 // 00157 // estPitchVel_fil += (LOW_PASS_SCALING*(estPitchVel - estPitchVel_fil))/(485); 00158 // 00159 // estYawVel_fil += (LOW_PASS_SCALING*(estYawVel - estYawVel_fil))/(485); 00160 //} 00161 // 00162 //int IMUDataProcessor::c_asin(int input) const { 00163 // double val = (asin((double)input/200)*180/M_PI) * 100000; 00164 // return (int)val; 00165 //} 00166 00167 } /* namespace telekyb */