imu_transformer.cpp
Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2012, Willow Garage, Inc.
00003  * All rights reserved.
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions are met:
00007  *
00008  *     * Redistributions of source code must retain the above copyright
00009  *       notice, this list of conditions and the following disclaimer.
00010  *     * Redistributions in binary form must reproduce the above copyright
00011  *       notice, this list of conditions and the following disclaimer in the
00012  *       documentation and/or other materials provided with the distribution.
00013  *     * Neither the name of the Willow Garage, Inc. nor the names of its
00014  *       contributors may be used to endorse or promote products derived from
00015  *       this software without specific prior written permission.
00016  *
00017  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00018  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00019  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00020  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
00021  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00022  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00023  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00024  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00025  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00026  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00027  * POSSIBILITY OF SUCH DAMAGE.
00028  */
00029 
00030 /* 
00031  * Author: Chad Rockey
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         // Create output message
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         // Get transform
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)); // Clear translation component so we can use TF's transform operator directly.
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     // Orienation
00083     if(msg->orientation_covariance[0] < 0){ // Invalid covariance.  Skip these elements.
00084         msg_out->orientation = msg->orientation;
00085         msg_out->orientation_covariance = msg->orientation_covariance;
00086         } else {
00087             // Transform orientation
00088             tf::Quaternion quat;
00089             tf::quaternionMsgToTF(msg->orientation, quat);
00090             tf::quaternionTFToMsg(transform*quat, msg_out->orientation);
00091 
00092             // Transform orientation_covariance
00093             transformCovariance(msg->orientation_covariance, msg_out->orientation_covariance, transform);
00094     }
00095 
00096     // Angular velocity
00097     if(msg->angular_velocity_covariance[0] < 0){ // Invalid covariance.  Skip these elements.
00098         msg_out->angular_velocity = msg->angular_velocity;
00099         msg_out->angular_velocity_covariance = msg->angular_velocity_covariance;
00100         } else {
00101             // Transform angular_velocity
00102             tf::Vector3 gyro;
00103             tf::vector3MsgToTF(msg->angular_velocity, gyro);
00104             tf::vector3TFToMsg(transform*gyro, msg_out->angular_velocity);
00105 
00106             // Transform angular_velocity_covariance
00107             transformCovariance(msg->angular_velocity_covariance, msg_out->angular_velocity_covariance, transform);
00108     }
00109 
00110     // Linear acceleration
00111     if(msg->linear_acceleration_covariance[0] < 0){ // Invalid covariance.  Skip these elements.
00112         msg_out->linear_acceleration = msg->linear_acceleration;
00113         msg_out->linear_acceleration_covariance = msg->linear_acceleration_covariance;
00114         } else {
00115             // Transform linear_acceleration
00116             tf::Vector3 accel;
00117             tf::vector3MsgToTF(msg->linear_acceleration, accel);
00118             tf::vector3TFToMsg(transform*accel, msg_out->linear_acceleration);
00119 
00120             // Transform linear_acceleration_covariance
00121             transformCovariance(msg->linear_acceleration_covariance, msg_out->linear_acceleration_covariance, transform);
00122     }
00123 
00124     // Publish transformed message
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   // Get parameters
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   // Create publisher
00140   pub_ = n.advertise<sensor_msgs::Imu>("imu_transformed", 2);
00141 
00142   // Create tf listener
00143   listener_.reset(new tf::TransformListener());
00144 
00145   // Create tf message filter to automatically handle queuing messages until tf is ready
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 }


imu_pipeline
Author(s): Chad Rockey
autogenerated on Fri Aug 28 2015 11:10:26