00001
00035 #include <string>
00036
00037 #include "geometry_msgs/Vector3Stamped.h"
00038 #include "ros/ros.h"
00039 #include "sensor_msgs/Imu.h"
00040 #include "serial/serial.h"
00041 #include "std_msgs/Float32.h"
00042 #include "std_msgs/Header.h"
00043 #include "um6/comms.h"
00044 #include "um6/registers.h"
00045 #include "um6/Reset.h"
00046
00047
00048
00049 const uint8_t TRIGGER_PACKET = UM6_TEMPERATURE;
00050
00055 template<typename RegT>
00056 void configureVector3(um6::Comms* sensor, const um6::Accessor<RegT>& reg,
00057 std::string param, std::string human_name)
00058 {
00059 if (reg.length != 3)
00060 {
00061 throw std::logic_error("configureVector3 may only be used with 3-field registers!");
00062 }
00063
00064 if (ros::param::has(param))
00065 {
00066 double x, y, z;
00067 ros::param::get(param + "/x", x);
00068 ros::param::get(param + "/y", y);
00069 ros::param::get(param + "/z", z);
00070 ROS_INFO_STREAM("Configuring " << human_name << " to ("
00071 << x << ", " << y << ", " << z << ")");
00072 reg.set_scaled(0, x);
00073 reg.set_scaled(1, y);
00074 reg.set_scaled(2, z);
00075 if (sensor->sendWaitAck(reg))
00076 {
00077 throw std::runtime_error("Unable to configure vector.");
00078 }
00079 }
00080 }
00081
00086 template<typename RegT>
00087 void sendCommand(um6::Comms* sensor, const um6::Accessor<RegT>& reg, std::string human_name)
00088 {
00089 ROS_INFO_STREAM("Sending command: " << human_name);
00090 if (!sensor->sendWaitAck(reg))
00091 {
00092 throw std::runtime_error("Command to device failed.");
00093 }
00094 }
00095
00096
00101 void configureSensor(um6::Comms* sensor)
00102 {
00103 um6::Registers r;
00104
00105
00106 const uint8_t UM6_BAUD_115200 = 0x5;
00107 uint32_t comm_reg = UM6_BROADCAST_ENABLED |
00108 UM6_GYROS_PROC_ENABLED | UM6_ACCELS_PROC_ENABLED | UM6_MAG_PROC_ENABLED |
00109 UM6_QUAT_ENABLED | UM6_EULER_ENABLED | UM6_COV_ENABLED | UM6_TEMPERATURE_ENABLED |
00110 UM6_BAUD_115200 << UM6_BAUD_START_BIT;
00111 r.communication.set(0, comm_reg);
00112 if (!sensor->sendWaitAck(r.communication))
00113 {
00114 throw std::runtime_error("Unable to set communication register.");
00115 }
00116
00117
00118 bool mag_updates, accel_updates;
00119 ros::param::param<bool>("~mag_updates", mag_updates, true);
00120 ros::param::param<bool>("~accel_updates", accel_updates, true);
00121 uint32_t misc_config_reg = UM6_QUAT_ESTIMATE_ENABLED;
00122 if (mag_updates)
00123 {
00124 misc_config_reg |= UM6_MAG_UPDATE_ENABLED;
00125 }
00126 else
00127 {
00128 ROS_WARN("Excluding magnetometer updates from EKF.");
00129 }
00130 if (accel_updates)
00131 {
00132 misc_config_reg |= UM6_ACCEL_UPDATE_ENABLED;
00133 }
00134 else
00135 {
00136 ROS_WARN("Excluding accelerometer updates from EKF.");
00137 }
00138 r.misc_config.set(0, misc_config_reg);
00139 if (!sensor->sendWaitAck(r.misc_config))
00140 {
00141 throw std::runtime_error("Unable to set misc config register.");
00142 }
00143
00144
00145
00146
00147 bool zero_gyros;
00148 ros::param::param<bool>("~zero_gyros", zero_gyros, true);
00149 if (zero_gyros) sendCommand(sensor, r.cmd_zero_gyros, "zero gyroscopes");
00150
00151
00152 configureVector3(sensor, r.mag_ref, "~mag_ref", "magnetic reference vector");
00153 configureVector3(sensor, r.accel_ref, "~accel_ref", "accelerometer reference vector");
00154 configureVector3(sensor, r.mag_bias, "~mag_bias", "magnetic bias vector");
00155 configureVector3(sensor, r.accel_bias, "~accel_bias", "accelerometer bias vector");
00156 configureVector3(sensor, r.gyro_bias, "~gyro_bias", "gyroscope bias vector");
00157 }
00158
00159
00160 bool handleResetService(um6::Comms* sensor,
00161 const um6::Reset::Request& req, const um6::Reset::Response& resp)
00162 {
00163 um6::Registers r;
00164 if (req.zero_gyros) sendCommand(sensor, r.cmd_zero_gyros, "zero gyroscopes");
00165 if (req.reset_ekf) sendCommand(sensor, r.cmd_reset_ekf, "reset EKF");
00166 if (req.set_mag_ref) sendCommand(sensor, r.cmd_set_mag_ref, "set magnetometer reference");
00167 if (req.set_accel_ref) sendCommand(sensor, r.cmd_set_accel_ref, "set accelerometer reference");
00168 return true;
00169 }
00170
00175 void publishMsgs(um6::Registers& r, ros::NodeHandle* n, const std_msgs::Header& header)
00176 {
00177 static ros::Publisher imu_pub = n->advertise<sensor_msgs::Imu>("imu/data", 1, false);
00178 static ros::Publisher mag_pub = n->advertise<geometry_msgs::Vector3Stamped>("imu/mag", 1, false);
00179 static ros::Publisher rpy_pub = n->advertise<geometry_msgs::Vector3Stamped>("imu/rpy", 1, false);
00180 static ros::Publisher temp_pub = n->advertise<std_msgs::Float32>("imu/temperature", 1, false);
00181
00182 if (imu_pub.getNumSubscribers() > 0)
00183 {
00184 sensor_msgs::Imu imu_msg;
00185 imu_msg.header = header;
00186
00187
00188 imu_msg.orientation.x = r.quat.get_scaled(2);
00189 imu_msg.orientation.y = r.quat.get_scaled(1);
00190 imu_msg.orientation.z = -r.quat.get_scaled(3);
00191 imu_msg.orientation.w = r.quat.get_scaled(0);
00192
00193
00194
00195 imu_msg.orientation_covariance[0] = r.covariance.get_scaled(5);
00196 imu_msg.orientation_covariance[1] = r.covariance.get_scaled(6);
00197 imu_msg.orientation_covariance[2] = r.covariance.get_scaled(7);
00198 imu_msg.orientation_covariance[3] = r.covariance.get_scaled(9);
00199 imu_msg.orientation_covariance[4] = r.covariance.get_scaled(10);
00200 imu_msg.orientation_covariance[5] = r.covariance.get_scaled(11);
00201 imu_msg.orientation_covariance[6] = r.covariance.get_scaled(13);
00202 imu_msg.orientation_covariance[7] = r.covariance.get_scaled(14);
00203 imu_msg.orientation_covariance[8] = r.covariance.get_scaled(15);
00204
00205
00206 imu_msg.angular_velocity.x = r.gyro.get_scaled(1);
00207 imu_msg.angular_velocity.y = r.gyro.get_scaled(0);
00208 imu_msg.angular_velocity.z = -r.gyro.get_scaled(2);
00209
00210
00211 imu_msg.linear_acceleration.x = r.accel.get_scaled(1);
00212 imu_msg.linear_acceleration.y = r.accel.get_scaled(0);
00213 imu_msg.linear_acceleration.z = -r.accel.get_scaled(2);
00214
00215 imu_pub.publish(imu_msg);
00216 }
00217
00218 if (mag_pub.getNumSubscribers() > 0)
00219 {
00220 geometry_msgs::Vector3Stamped mag_msg;
00221 mag_msg.header = header;
00222 mag_msg.vector.x = r.mag.get_scaled(1);
00223 mag_msg.vector.y = r.mag.get_scaled(0);
00224 mag_msg.vector.z = -r.mag.get_scaled(2);
00225 mag_pub.publish(mag_msg);
00226 }
00227
00228 if (rpy_pub.getNumSubscribers() > 0)
00229 {
00230 geometry_msgs::Vector3Stamped rpy_msg;
00231 rpy_msg.header = header;
00232 rpy_msg.vector.x = r.euler.get_scaled(1);
00233 rpy_msg.vector.y = r.euler.get_scaled(0);
00234 rpy_msg.vector.z = -r.euler.get_scaled(2);
00235 rpy_pub.publish(rpy_msg);
00236 }
00237
00238 if (temp_pub.getNumSubscribers() > 0)
00239 {
00240 std_msgs::Float32 temp_msg;
00241 temp_msg.data = r.temperature.get_scaled(0);
00242 temp_pub.publish(temp_msg);
00243 }
00244 }
00245
00246
00250 int main(int argc, char **argv)
00251 {
00252 ros::init(argc, argv, "um6_driver");
00253
00254
00255 std::string port;
00256 int32_t baud;
00257 ros::param::param<std::string>("~port", port, "/dev/ttyUSB0");
00258 ros::param::param<int32_t>("~baud", baud, 115200);
00259
00260 serial::Serial ser;
00261 ser.setPort(port);
00262 ser.setBaudrate(baud);
00263 serial::Timeout to = serial::Timeout(50, 50, 0, 50, 0);
00264 ser.setTimeout(to);
00265
00266 ros::NodeHandle n;
00267 std_msgs::Header header;
00268 ros::param::param<std::string>("~frame_id", header.frame_id, "imu_link");
00269
00270 bool first_failure = true;
00271 while (ros::ok())
00272 {
00273 try
00274 {
00275 ser.open();
00276 }
00277 catch(const serial::IOException& e)
00278 {
00279 ROS_DEBUG("Unable to connect to port.");
00280 }
00281 if (ser.isOpen())
00282 {
00283 ROS_INFO("Successfully connected to serial port.");
00284 first_failure = true;
00285 try
00286 {
00287 um6::Comms sensor(&ser);
00288 configureSensor(&sensor);
00289 um6::Registers registers;
00290 ros::ServiceServer srv = n.advertiseService<um6::Reset::Request, um6::Reset::Response>(
00291 "reset", boost::bind(handleResetService, &sensor, _1, _2));
00292
00293 while (ros::ok())
00294 {
00295 if (sensor.receive(®isters) == TRIGGER_PACKET)
00296 {
00297
00298 header.stamp = ros::Time::now();
00299 publishMsgs(registers, &n, header);
00300 ros::spinOnce();
00301 }
00302 }
00303 }
00304 catch(const std::exception& e)
00305 {
00306 if (ser.isOpen()) ser.close();
00307 ROS_ERROR_STREAM(e.what());
00308 ROS_INFO("Attempting reconnection after error.");
00309 ros::Duration(1.0).sleep();
00310 }
00311 }
00312 else
00313 {
00314 ROS_WARN_STREAM_COND(first_failure, "Could not connect to serial device "
00315 << port << ". Trying again every 1 second.");
00316 first_failure = false;
00317 ros::Duration(1.0).sleep();
00318 }
00319 }
00320 }