imu_ros_i.cpp
Go to the documentation of this file.
00001 #include "phidgets_imu/imu_ros_i.h"
00002 
00003 namespace phidgets {
00004 
00005 ImuRosI::ImuRosI(ros::NodeHandle nh, ros::NodeHandle nh_private):
00006   Imu(),
00007   nh_(nh), 
00008   nh_private_(nh_private),
00009   initialized_(false)
00010 {
00011   ROS_INFO ("Starting Phidgets IMU");
00012 
00013   // **** get parameters
00014 
00015   if (!nh_private_.getParam ("period", period_))
00016     period_ = 8; // 8 ms
00017   if (!nh_private_.getParam ("frame_id", frame_id_))
00018     frame_id_ = "imu";
00019   if (!nh_private_.getParam ("angular_velocity_stdev", angular_velocity_stdev_))
00020     angular_velocity_stdev_ = 0.02 * (M_PI / 180.0); // 0.02 deg/s resolution, as per manual
00021   if (!nh_private_.getParam ("linear_acceleration_stdev", linear_acceleration_stdev_))
00022     linear_acceleration_stdev_ = 300.0 * 1e-6 * G; // 300 ug as per manual
00023 
00024   bool has_compass_params =
00025       nh_private_.getParam ("cc_mag_field", cc_mag_field_)
00026       && nh_private_.getParam ("cc_offset0", cc_offset0_)
00027       && nh_private_.getParam ("cc_offset1", cc_offset1_)
00028       && nh_private_.getParam ("cc_offset2", cc_offset2_)
00029       && nh_private_.getParam ("cc_gain0", cc_gain0_)
00030       && nh_private_.getParam ("cc_gain1", cc_gain1_)
00031       && nh_private_.getParam ("cc_gain2", cc_gain2_)
00032       && nh_private_.getParam ("cc_t0", cc_T0_)
00033       && nh_private_.getParam ("cc_t1", cc_T1_)
00034       && nh_private_.getParam ("cc_t2", cc_T2_)
00035       && nh_private_.getParam ("cc_t3", cc_T3_)
00036       && nh_private_.getParam ("cc_t4", cc_T4_)
00037       && nh_private_.getParam ("cc_t5", cc_T5_);
00038 
00039   // **** advertise topics
00040 
00041   imu_publisher_ = nh_.advertise<ImuMsg>(
00042     "imu/data_raw", 5);
00043   mag_publisher_ = nh_.advertise<MagMsg>(
00044     "imu/mag", 5);
00045   cal_publisher_ = nh_.advertise<std_msgs::Bool>(
00046     "imu/is_calibrated", 5);
00047 
00048   // **** advertise services
00049 
00050   cal_srv_ = nh_.advertiseService(
00051     "imu/calibrate", &ImuRosI::calibrateService, this);
00052 
00053   // **** initialize variables and device
00054   
00055   imu_msg_.header.frame_id = frame_id_;
00056 
00057   // build covariance matrices
00058 
00059   double ang_vel_var = angular_velocity_stdev_ * angular_velocity_stdev_;
00060   double lin_acc_var = linear_acceleration_stdev_ * linear_acceleration_stdev_;
00061 
00062   for (int i = 0; i < 3; ++i)
00063   for (int j = 0; j < 3; ++j)
00064   {
00065     int idx = j*3 +i;
00066 
00067     if (i == j)
00068     {
00069       imu_msg_.angular_velocity_covariance[idx]    = ang_vel_var;
00070       imu_msg_.linear_acceleration_covariance[idx] = lin_acc_var;
00071     }
00072     else
00073     {
00074       imu_msg_.angular_velocity_covariance[idx]    = 0.0;
00075       imu_msg_.linear_acceleration_covariance[idx] = 0.0;
00076     }
00077   }
00078 
00079   // signal that we have no orientation estimate (see Imu.msg)
00080   imu_msg_.orientation_covariance[0] = -1;
00081 
00082   initDevice();
00083 
00084   if (has_compass_params)
00085   {
00086     int result = CPhidgetSpatial_setCompassCorrectionParameters(imu_handle_, cc_mag_field_,
00087           cc_offset0_, cc_offset1_, cc_offset2_, cc_gain0_, cc_gain1_, cc_gain2_,
00088           cc_T0_, cc_T1_, cc_T2_, cc_T3_, cc_T4_, cc_T5_);
00089     if (result)
00090     {
00091       const char *err;
00092       CPhidget_getErrorDescription(result, &err);
00093       ROS_ERROR("Problem while trying to set compass correction params: '%s'.", err);
00094     }
00095   }
00096   else
00097   {
00098     ROS_INFO("No compass correction params found.");
00099   }
00100 }
00101 
00102 void ImuRosI::initDevice()
00103 {
00104         ROS_INFO("Opening device");
00105         open(-1);
00106 
00107         ROS_INFO("Waiting for IMU to be attached...");
00108         int result = waitForAttachment(10000);
00109         if(result)
00110         {
00111           const char *err;
00112                 CPhidget_getErrorDescription(result, &err);
00113                 ROS_FATAL("Problem waiting for IMU attachment: %s Make sure the USB cable is connected and you have executed the phidgets_api/share/setup-udev.sh script.", err);
00114         }
00115 
00116         // set the data rate for the spatial events
00117   setDataRate(period_);
00118 
00119   // calibrate on startup
00120   calibrate();
00121 }
00122 
00123 bool ImuRosI::calibrateService(std_srvs::Empty::Request  &req,
00124                                std_srvs::Empty::Response &res)
00125 {
00126   calibrate();
00127   return true;
00128 }
00129 
00130 void ImuRosI::calibrate()
00131 {
00132   ROS_INFO("Calibrating IMU...");
00133   zero();
00134   ROS_INFO("Calibrating IMU done.");
00135 
00136   time_zero_ = ros::Time::now();
00137 
00138   // publish message
00139   std_msgs::Bool is_calibrated_msg;
00140   is_calibrated_msg.data = true;
00141   cal_publisher_.publish(is_calibrated_msg);
00142 }
00143 
00144 void ImuRosI::processImuData(CPhidgetSpatial_SpatialEventDataHandle* data, int i)
00145 {
00146   // **** calculate time from timestamp
00147   ros::Duration time_imu(data[i]->timestamp.seconds + 
00148                          data[i]->timestamp.microseconds * 1e-6);
00149 
00150   ros::Time time_now = time_zero_ + time_imu;
00151 
00152   double timediff = time_now.toSec() - ros::Time::now().toSec();
00153   if (fabs(timediff) > 0.1) {
00154     ROS_WARN("IMU time lags behind by %f seconds, resetting IMU time offset!", timediff);
00155     time_zero_ = ros::Time::now() - time_imu;
00156     time_now = ros::Time::now();
00157   }
00158 
00159   // **** initialize if needed
00160 
00161   if (!initialized_)
00162   { 
00163     last_imu_time_ = time_now;
00164     initialized_ = true;
00165   }
00166 
00167   // **** create and publish imu message
00168 
00169   boost::shared_ptr<ImuMsg> imu_msg = 
00170     boost::make_shared<ImuMsg>(imu_msg_);
00171 
00172   imu_msg->header.stamp = time_now;
00173 
00174   // set linear acceleration
00175   imu_msg->linear_acceleration.x = - data[i]->acceleration[0] * G;
00176   imu_msg->linear_acceleration.y = - data[i]->acceleration[1] * G;
00177   imu_msg->linear_acceleration.z = - data[i]->acceleration[2] * G;
00178 
00179   // set angular velocities
00180   imu_msg->angular_velocity.x = data[i]->angularRate[0] * (M_PI / 180.0);
00181   imu_msg->angular_velocity.y = data[i]->angularRate[1] * (M_PI / 180.0);
00182   imu_msg->angular_velocity.z = data[i]->angularRate[2] * (M_PI / 180.0);
00183 
00184   imu_publisher_.publish(imu_msg);
00185 
00186   // **** create and publish magnetic field message
00187 
00188   boost::shared_ptr<MagMsg> mag_msg = 
00189     boost::make_shared<MagMsg>();
00190   
00191   mag_msg->header.frame_id = frame_id_;
00192   mag_msg->header.stamp = time_now;
00193 
00194   if (data[i]->magneticField[0] != PUNK_DBL)
00195   {
00196     mag_msg->vector.x = data[i]->magneticField[0];
00197     mag_msg->vector.y = data[i]->magneticField[1];
00198     mag_msg->vector.z = data[i]->magneticField[2];
00199   }
00200   else
00201   {
00202     double nan = std::numeric_limits<double>::quiet_NaN();
00203 
00204     mag_msg->vector.x = nan;
00205     mag_msg->vector.y = nan;
00206     mag_msg->vector.z = nan;
00207   }
00208    
00209   mag_publisher_.publish(mag_msg);
00210 }
00211 
00212 void ImuRosI::dataHandler(CPhidgetSpatial_SpatialEventDataHandle *data, int count)
00213 {
00214   for(int i = 0; i < count; i++)
00215     processImuData(data, i);
00216 }
00217 
00218 } // namespace phidgets
00219 


phidgets_imu
Author(s): Ivan Dryanovski
autogenerated on Wed Aug 26 2015 15:28:19