00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034 #include <ros/ros.h>
00035 #include <tf/tf.h>
00036 #include <tf/transform_listener.h>
00037 #include <tf/message_filter.h>
00038 #include <message_filters/subscriber.h>
00039
00040 #include <sensor_msgs/Imu.h>
00041 #include <geometry_msgs/Vector3Stamped.h>
00042 #include <geometry_msgs/QuaternionStamped.h>
00043 #include <geometry_msgs/PoseStamped.h>
00044 #include <iostream>
00045
00046 ros::Publisher pub_;
00047 boost::shared_ptr<tf::TransformListener> listener_;
00048 std::string target_frame_id_;
00049
00050 void transformCovariance(const boost::array<double, 9>& in, boost::array<double, 9>& out, const tf::StampedTransform& transform){
00051 tf::Matrix3x3 cov_in(in[0], in[1], in[2],
00052 in[3], in[4], in[5],
00053 in[6], in[7], in[8]);
00054
00055 tf::Matrix3x3 rot(transform.getRotation());
00056 tf::Matrix3x3 cov_out = rot*cov_in*(rot.transpose());
00057 for(size_t i = 0; i < 3; i++){
00058 tf::Vector3 row = cov_out.getRow(i);
00059 out[3*i] = row.getX();
00060 out[3*i+1] = row.getY();
00061 out[3*i+2] = row.getZ();
00062 }
00063 }
00064
00065 void imu_callback(const sensor_msgs::ImuConstPtr& msg){
00066
00067 sensor_msgs::ImuPtr msg_out(new sensor_msgs::Imu());
00068 msg_out->header = msg->header;
00069 msg_out->header.frame_id = target_frame_id_;
00070
00071
00072 tf::StampedTransform transform;
00073
00074 try {
00075 listener_->lookupTransform(target_frame_id_, msg->header.frame_id, msg->header.stamp, transform);
00076 transform.setOrigin(tf::Vector3(0,0,0));
00077 } catch (tf::TransformException &ex) {
00078 ROS_ERROR("Could not transform imu from frame %s to %s: %s", msg->header.frame_id.c_str(), target_frame_id_.c_str(), ex.what());
00079 return;
00080 }
00081
00082
00083 if(msg->orientation_covariance[0] < 0){
00084 msg_out->orientation = msg->orientation;
00085 msg_out->orientation_covariance = msg->orientation_covariance;
00086 } else {
00087
00088 tf::Quaternion quat;
00089 tf::quaternionMsgToTF(msg->orientation, quat);
00090 tf::quaternionTFToMsg(transform*quat, msg_out->orientation);
00091
00092
00093 transformCovariance(msg->orientation_covariance, msg_out->orientation_covariance, transform);
00094 }
00095
00096
00097 if(msg->angular_velocity_covariance[0] < 0){
00098 msg_out->angular_velocity = msg->angular_velocity;
00099 msg_out->angular_velocity_covariance = msg->angular_velocity_covariance;
00100 } else {
00101
00102 tf::Vector3 gyro;
00103 tf::vector3MsgToTF(msg->angular_velocity, gyro);
00104 tf::vector3TFToMsg(transform*gyro, msg_out->angular_velocity);
00105
00106
00107 transformCovariance(msg->angular_velocity_covariance, msg_out->angular_velocity_covariance, transform);
00108 }
00109
00110
00111 if(msg->linear_acceleration_covariance[0] < 0){
00112 msg_out->linear_acceleration = msg->linear_acceleration;
00113 msg_out->linear_acceleration_covariance = msg->linear_acceleration_covariance;
00114 } else {
00115
00116 tf::Vector3 accel;
00117 tf::vector3MsgToTF(msg->linear_acceleration, accel);
00118 tf::vector3TFToMsg(transform*accel, msg_out->linear_acceleration);
00119
00120
00121 transformCovariance(msg->linear_acceleration_covariance, msg_out->linear_acceleration_covariance, transform);
00122 }
00123
00124
00125 pub_.publish(msg_out);
00126 }
00127
00128
00129 int main(int argc, char **argv){
00130 ros::init(argc, argv, "imu_transformer");
00131 ros::NodeHandle n;
00132 ros::NodeHandle pnh("~");
00133
00134
00135 pnh.param<std::string>("target_frame_id", target_frame_id_, "base_link");
00136 int message_filter_queue_size;
00137 pnh.param<int>("queue_size", message_filter_queue_size, 1000);
00138
00139
00140 pub_ = n.advertise<sensor_msgs::Imu>("imu_transformed", 2);
00141
00142
00143 listener_.reset(new tf::TransformListener());
00144
00145
00146 message_filters::Subscriber<sensor_msgs::Imu> sub;
00147 sub.subscribe(n, "imu", 2);
00148 tf::MessageFilter<sensor_msgs::Imu>* tf_filter;
00149 tf_filter = new tf::MessageFilter<sensor_msgs::Imu>(sub, *listener_, target_frame_id_, message_filter_queue_size);
00150 tf_filter->registerCallback(boost::bind(&imu_callback, _1));
00151
00152 ros::spin();
00153
00154 return 0;
00155 }