Go to the documentation of this file.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 #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
00076
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 };
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