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
00014
00015 nh_private_.param<int>("period", period_, 8);
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));
00018 nh_private_.param<double>("linear_acceleration_stdev", linear_acceleration_stdev_, 300.0 * 1e-6 * G);
00019 nh_private_.param<int>("serial_number", serial_number_, -1);
00020
00021
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
00031
00032 cal_srv_ = nh_.advertiseService(
00033 "imu/calibrate", &ImuRosI::calibrateService, this);
00034
00035
00036
00037 imu_msg_.header.frame_id = frame_id_;
00038
00039
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
00079 setDataRate(period_);
00080
00081
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
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
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
00122
00123 if (!initialized_)
00124 {
00125 last_imu_time_ = time_now;
00126 initialized_ = true;
00127 }
00128
00129
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
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
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
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 }
00181