imu_ros_i.cpp
Go to the documentation of this file.
00001 #include "carl_phidgets/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   nh_private_.param<int>("period", period_, 8); // 8 ms
00016   nh_private_.param<std::string>("frame_id", frame_id_, "imu");
00017   nh_private_.param<double>("angular_velocity_stdev", angular_velocity_stdev_, 0.02 * (M_PI / 180.0)); // 0.02 deg/s resolution, as per manual
00018   nh_private_.param<double>("linear_acceleration_stdev", linear_acceleration_stdev_, 300.0 * 1e-6 * G); // 300 ug as per manual
00019   nh_private_.param<int>("serial_number", serial_number_, -1);
00020 
00021   // **** advertise topics
00022 
00023   imu_publisher_ = nh_.advertise<ImuMsg>(
00024     "imu/data_raw", 5);
00025   mag_publisher_ = nh_.advertise<MagMsg>(
00026     "imu/mag", 5);
00027   cal_publisher_ = nh_.advertise<std_msgs::Bool>(
00028     "imu/is_calibrated", 5);
00029 
00030   // **** advertise services
00031 
00032   cal_srv_ = nh_.advertiseService(
00033     "imu/calibrate", &ImuRosI::calibrateService, this);
00034 
00035   // **** initialize variables and device
00036   
00037   imu_msg_.header.frame_id = frame_id_;
00038 
00039   // build covariance matrices
00040 
00041   double ang_vel_var = angular_velocity_stdev_ * angular_velocity_stdev_;
00042   double lin_acc_var = linear_acceleration_stdev_ * linear_acceleration_stdev_;
00043 
00044   for (int i = 0; i < 3; ++i)
00045   for (int j = 0; j < 3; ++j)
00046   {
00047     int idx = j*3 +i;
00048 
00049     if (i == j)
00050     {
00051       imu_msg_.angular_velocity_covariance[idx]    = ang_vel_var;
00052       imu_msg_.linear_acceleration_covariance[idx] = lin_acc_var;
00053     }
00054     else
00055     {
00056       imu_msg_.angular_velocity_covariance[idx]    = 0.0;
00057       imu_msg_.linear_acceleration_covariance[idx] = 0.0;
00058     }
00059   }
00060 
00061   initDevice();
00062 }
00063 
00064 void ImuRosI::initDevice()
00065 {
00066   ROS_INFO("Opening device");
00067   open(serial_number_);
00068 
00069   ROS_INFO("Waiting for IMU to be attached...");
00070   int result = waitForAttachment(10000);
00071   if(result)
00072   {
00073     const char *err;
00074     CPhidget_getErrorDescription(result, &err);
00075     ROS_FATAL("Problem waiting for IMU attachment: %s Make sure the USB cable is connected and you have executed the phidgets_c_api/setup-udev.sh script.", err);
00076   }
00077 
00078   // set the data rate for the spatial events
00079   setDataRate(period_);
00080 
00081   // calibrate on startup
00082   calibrate();
00083 }
00084 
00085 bool ImuRosI::calibrateService(std_srvs::Empty::Request  &req,
00086                                std_srvs::Empty::Response &res)
00087 {
00088   calibrate();
00089   return true;
00090 }
00091 
00092 void ImuRosI::calibrate()
00093 {
00094   ROS_INFO("Calibrating IMU...");
00095   zero();
00096   ROS_INFO("Calibrating IMU done.");
00097 
00098   time_zero_ = ros::Time::now();
00099 
00100   // publish message
00101   std_msgs::Bool is_calibrated_msg;
00102   is_calibrated_msg.data = true;
00103   cal_publisher_.publish(is_calibrated_msg);
00104 }
00105 
00106 void ImuRosI::processImuData(CPhidgetSpatial_SpatialEventDataHandle* data, int i)
00107 {
00108   // **** calculate time from timestamp
00109   ros::Duration time_imu(data[i]->timestamp.seconds + 
00110                          data[i]->timestamp.microseconds * 1e-6);
00111 
00112   ros::Time time_now = time_zero_ + time_imu;
00113 
00114   double timediff = time_now.toSec() - ros::Time::now().toSec();
00115   if (fabs(timediff) > 0.1) {
00116     ROS_WARN("IMU time lags behind by %f seconds, resetting IMU time offset!", timediff);
00117     time_zero_ = ros::Time::now() - time_imu;
00118     time_now = ros::Time::now();
00119   }
00120 
00121   // **** initialize if needed
00122 
00123   if (!initialized_)
00124   { 
00125     last_imu_time_ = time_now;
00126     initialized_ = true;
00127   }
00128 
00129   // **** create and publish imu message
00130 
00131   boost::shared_ptr<ImuMsg> imu_msg = 
00132     boost::make_shared<ImuMsg>(imu_msg_);
00133 
00134   imu_msg->header.stamp = time_now;
00135 
00136   // set linear acceleration
00137   imu_msg->linear_acceleration.x = - data[i]->acceleration[0] * G;
00138   imu_msg->linear_acceleration.y = - data[i]->acceleration[1] * G;
00139   imu_msg->linear_acceleration.z = - data[i]->acceleration[2] * G;
00140 
00141   // set angular velocities
00142   imu_msg->angular_velocity.x = data[i]->angularRate[0] * (M_PI / 180.0);
00143   imu_msg->angular_velocity.y = data[i]->angularRate[1] * (M_PI / 180.0);
00144   imu_msg->angular_velocity.z = data[i]->angularRate[2] * (M_PI / 180.0);
00145 
00146   imu_publisher_.publish(imu_msg);
00147 
00148   // **** create and publish magnetic field message
00149 
00150   boost::shared_ptr<MagMsg> mag_msg = 
00151     boost::make_shared<MagMsg>();
00152   
00153   mag_msg->header.frame_id = frame_id_;
00154   mag_msg->header.stamp = time_now;
00155 
00156   if (data[i]->magneticField[0] != PUNK_DBL)
00157   {
00158     mag_msg->vector.x = data[i]->magneticField[0];
00159     mag_msg->vector.y = data[i]->magneticField[1];
00160     mag_msg->vector.z = data[i]->magneticField[2];
00161   }
00162   else
00163   {
00164     double nan = std::numeric_limits<double>::quiet_NaN();
00165 
00166     mag_msg->vector.x = nan;
00167     mag_msg->vector.y = nan;
00168     mag_msg->vector.z = nan;
00169   }
00170    
00171   mag_publisher_.publish(mag_msg);
00172 }
00173 
00174 void ImuRosI::dataHandler(CPhidgetSpatial_SpatialEventDataHandle *data, int count)
00175 {
00176   for(int i = 0; i < count; i++)
00177     processImuData(data, i);
00178 }
00179 
00180 } // namespace phidgets
00181 


carl_phidgets
Author(s): David Kent , Russell Toris
autogenerated on Thu Jun 6 2019 21:09:54