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
00014
00015 if (!nh_private_.getParam ("period", period_))
00016 period_ = 8;
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);
00021 if (!nh_private_.getParam ("linear_acceleration_stdev", linear_acceleration_stdev_))
00022 linear_acceleration_stdev_ = 300.0 * 1e-6 * G;
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
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
00049
00050 cal_srv_ = nh_.advertiseService(
00051 "imu/calibrate", &ImuRosI::calibrateService, this);
00052
00053
00054
00055 imu_msg_.header.frame_id = frame_id_;
00056
00057
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
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
00117 setDataRate(period_);
00118
00119
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
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
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
00160
00161 if (!initialized_)
00162 {
00163 last_imu_time_ = time_now;
00164 initialized_ = true;
00165 }
00166
00167
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
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
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
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 }
00219