odometry_publisher.cpp
Go to the documentation of this file.
00001 
00002 /*
00003 * Software License Agreement (BSD License)
00004 *
00005 * Copyright (c) 2014, Daiki Maekawa and Robot Design and Control Lab.
00006 * All rights reserved.
00007 *
00008 * Redistribution and use in source and binary forms, with or without
00009 * modification, are permitted provided that the following conditions
00010 * are met:
00011 *
00012 * * Redistributions of source code must retain the above copyright
00013 * notice, this list of conditions and the following disclaimer.
00014 * * Redistributions in binary form must reproduce the above
00015 * copyright notice, this list of conditions and the following
00016 * disclaimer in the documentation and/or other materials provided
00017 * with the distribution.
00018 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00019 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00020 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00021 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00022 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00023 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00024 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00025 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00026 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00027 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
00028 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00029 * POSSIBILITY OF SUCH DAMAGE.
00030 */
00031 
00032 #include <combine_dr_measurements/odometry_publisher.h>
00033 
00034 #include <complex>
00035 
00036 #include <tf/transform_broadcaster.h>
00037 #include <tf/LinearMath/Quaternion.h>
00038 
00039 namespace combine_dr_measurements{
00040 
00041     OdometryPublisher::OdometryPublisher(ros::NodeHandle &nh) :
00042         nh_(nh),
00043         odom_sub_(nh, "odom", 1),
00044         imu_sub_(nh, "imu", 1),
00045         sync_(SyncPolicy(10), odom_sub_, imu_sub_)
00046     {
00047         odom_pub_ = nh_.advertise<nav_msgs::Odometry>("combined_odom", 5, this);
00048 
00049         sync_.registerCallback(boost::bind(&OdometryPublisher::syncMsgsCB, this, _1, _2));
00050         ros::NodeHandle private_nh("~");
00051         private_nh.param<double>("max_update_rate", max_update_rate_, 50);
00052     }
00053 
00054     void OdometryPublisher::syncMsgsCB(const nav_msgs::OdometryConstPtr &odom, const sensor_msgs::ImuConstPtr &imu){
00055         received_odom_ = *odom;
00056         received_imu_ = *imu;
00057     }
00058         
00059     void OdometryPublisher::run(){
00060         ros::Rate r(max_update_rate_);
00061         tf::TransformBroadcaster odom_broadcaster;
00062         nav_msgs::Odometry old_odom;
00063         
00064         while(nh_.ok()){
00065             if(received_odom_.header.stamp.toSec() > 0.001 && old_odom.header.stamp.toSec() > 0.001){
00066                 ros::Time time = ros::Time::now();
00067                 geometry_msgs::TransformStamped odom_trans;
00068                 nav_msgs::Odometry odom = received_odom_;
00069                 sensor_msgs::Imu imu = received_imu_;
00070 
00071                 odom.header.stamp    = odom_trans.header.stamp = time;
00072                 odom.header.frame_id = odom_trans.header.frame_id = "odom";
00073                 odom.child_frame_id  = odom_trans.child_frame_id  = "base_link";
00074                
00075                 //const double diff = std::abs((odom.header.stamp - imu.header.stamp).toSec());
00076                 //ROS_INFO_STREAM("diff = " << diff);
00077                 
00078                 const double dt = (odom.header.stamp - old_odom.header.stamp).toSec();
00079                 if(dt < 0.001){
00080                     ROS_WARN_STREAM("Interval too small to integrate with");
00081                 }else{
00082                                                         
00083                     odom.pose.pose.orientation = odom_trans.transform.rotation = imu.orientation;
00084                     
00085                     tf::Quaternion old_q(
00086                         old_odom.pose.pose.orientation.x,
00087                         old_odom.pose.pose.orientation.y,
00088                         old_odom.pose.pose.orientation.z,
00089                         old_odom.pose.pose.orientation.w
00090                     );
00091 
00092                     tf::Quaternion q(
00093                         odom.pose.pose.orientation.x,
00094                         odom.pose.pose.orientation.y,
00095                         odom.pose.pose.orientation.z,
00096                         odom.pose.pose.orientation.w
00097                     );
00098 
00099                     double roll, pitch, yaw, old_roll, old_pitch, old_yaw;
00100                     tf::Matrix3x3(old_q).getRPY(old_roll, old_pitch, old_yaw);
00101                     tf::Matrix3x3(q).getRPY(roll, pitch, yaw);
00102                     const double linear = odom.twist.twist.linear.x * dt;
00103                     const double angular = yaw - old_yaw;
00104                     
00105                     if(std::abs(angular) < 10e-3){
00106                         double direction = old_yaw + angular * 0.5;
00107                         odom.pose.pose.position.x = old_odom.pose.pose.position.x + linear * cos(direction);
00108                         odom.pose.pose.position.y = old_odom.pose.pose.position.y + linear * sin(direction);
00109                     }else{
00110                         const double r = linear / angular;
00111                         odom.pose.pose.position.x = old_odom.pose.pose.position.x + r * (sin(yaw) - sin(old_yaw));
00112                         odom.pose.pose.position.y = old_odom.pose.pose.position.y - r * (cos(yaw) - cos(old_yaw));
00113                     }
00114 
00115                     odom_trans.transform.translation.x = odom.pose.pose.position.x;
00116                     odom_trans.transform.translation.y = odom.pose.pose.position.y;
00117                     odom_trans.transform.translation.z = odom.pose.pose.position.z;
00118 
00119                     odom_broadcaster.sendTransform(odom_trans);
00120                     odom_pub_.publish(odom);
00121                        
00122                     old_odom = odom;
00123                 }
00124 
00125             }else{
00126                 ROS_INFO("Wait until receive messages.");
00127                 old_odom = received_odom_;
00128             }
00129             
00130             ros::spinOnce();
00131             r.sleep();
00132         }
00133     }
00134 }; //namespace combine_dr_measurements
00135 
00136 int main(int argc, char *argv[]){
00137     ros::init(argc, argv, "combine_dr_measurements");
00138 
00139     ros::NodeHandle n;
00140     combine_dr_measurements::OdometryPublisher odom_publisher(n);
00141     odom_publisher.run();
00142 
00143 }
00144 


combine_dr_measurements
Author(s): Daiki Maekawa
autogenerated on Fri Oct 16 2015 10:27:52