odometry.cpp
Go to the documentation of this file.
00001 
00010 /*****************************************************************************
00011 ** Includes
00012 *****************************************************************************/
00013 
00014 #include "../../include/kobuki_node/odometry.hpp"
00015 
00016 /*****************************************************************************
00017 ** Namespaces
00018 *****************************************************************************/
00019 
00020 namespace kobuki {
00021 
00022 /*****************************************************************************
00023 ** Implementation
00024 *****************************************************************************/
00025 
00026 Odometry::Odometry () :
00027   odom_frame("odom"),
00028   base_frame("base_footprint"),
00029   use_imu_heading(true),
00030   publish_tf(true)
00031 {};
00032 
00033 void Odometry::init(ros::NodeHandle& nh, const std::string& name) {
00034   double timeout;
00035   nh.param("cmd_vel_timeout", timeout, 0.6);
00036   cmd_vel_timeout.fromSec(timeout);
00037   ROS_INFO_STREAM("Kobuki : Velocity commands timeout: " << cmd_vel_timeout << " seconds [" << name << "].");
00038 
00039   if (!nh.getParam("odom_frame", odom_frame)) {
00040     ROS_WARN_STREAM("Kobuki : no param server setting for odom_frame, using default [" << odom_frame << "][" << name << "].");
00041   } else {
00042     ROS_INFO_STREAM("Kobuki : using odom_frame [" << odom_frame << "][" << name << "].");
00043   }
00044 
00045   if (!nh.getParam("base_frame", base_frame)) {
00046     ROS_WARN_STREAM("Kobuki : no param server setting for base_frame, using default [" << base_frame << "][" << name << "].");
00047   } else {
00048     ROS_INFO_STREAM("Kobuki : using base_frame [" << base_frame << "][" << name << "].");
00049   }
00050 
00051   if (!nh.getParam("publish_tf", publish_tf)) {
00052     ROS_WARN_STREAM("Kobuki : no param server setting for publish_tf, using default [" << publish_tf << "][" << name << "].");
00053   } else {
00054     if ( publish_tf ) {
00055       ROS_INFO_STREAM("Kobuki : publishing transforms [" << name << "].");
00056     } else {
00057       ROS_INFO_STREAM("Kobuki : not publishing transforms (see robot_pose_ekf) [" << name << "].");
00058     }
00059   }
00060 
00061   if (!nh.getParam("use_imu_heading", use_imu_heading)) {
00062     ROS_WARN_STREAM("Kobuki : no param server setting for use_imu_heading, using default [" << use_imu_heading << "][" << name << "].");
00063   } else {
00064     if ( use_imu_heading ) {
00065       ROS_INFO_STREAM("Kobuki : using imu data for heading [" << name << "].");
00066     } else {
00067       ROS_INFO_STREAM("Kobuki : using encoders for heading (see robot_pose_ekf) [" << name << "].");
00068     }
00069   }
00070 
00071   odom_trans.header.frame_id = odom_frame;
00072   odom_trans.child_frame_id = base_frame;
00073 
00074   pose.setIdentity();
00075 
00076   odom_publisher = nh.advertise<nav_msgs::Odometry>("odom", 50); // topic name and queue size
00077 }
00078 
00079 bool Odometry::commandTimeout() const {
00080   if ( (!last_cmd_time.isZero()) && ((ros::Time::now() - last_cmd_time) > cmd_vel_timeout) ) {
00081     return true;
00082   } else {
00083     return false;
00084   }
00085 }
00086 
00087 void Odometry::update(const ecl::Pose2D<double> &pose_update, ecl::linear_algebra::Vector3d &pose_update_rates,
00088                       double imu_heading, double imu_angular_velocity) {
00089   pose *= pose_update;
00090 
00091   if (use_imu_heading == true) {
00092     // Overwite with gyro heading data
00093     pose.heading(imu_heading);
00094     pose_update_rates[2] = imu_angular_velocity;
00095   }
00096 
00097   //since all ros tf odometry is 6DOF we'll need a quaternion created from yaw
00098   geometry_msgs::Quaternion odom_quat = tf::createQuaternionMsgFromYaw(pose.heading());
00099 
00100   if ( ros::ok() ) {
00101     publishTransform(odom_quat);
00102     publishOdometry(odom_quat, pose_update_rates);
00103   }
00104 }
00105 
00106 /*****************************************************************************
00107 ** Private Implementation
00108 *****************************************************************************/
00109 
00110 void Odometry::publishTransform(const geometry_msgs::Quaternion &odom_quat)
00111 {
00112   if (publish_tf == false)
00113     return;
00114 
00115   odom_trans.header.stamp = ros::Time::now();
00116   odom_trans.transform.translation.x = pose.x();
00117   odom_trans.transform.translation.y = pose.y();
00118   odom_trans.transform.translation.z = 0.0;
00119   odom_trans.transform.rotation = odom_quat;
00120   odom_broadcaster.sendTransform(odom_trans);
00121 }
00122 
00123 void Odometry::publishOdometry(const geometry_msgs::Quaternion &odom_quat,
00124                                const ecl::linear_algebra::Vector3d &pose_update_rates)
00125 {
00126   // Publish as shared pointer to leverage the nodelets' zero-copy pub/sub feature
00127   nav_msgs::OdometryPtr odom(new nav_msgs::Odometry);
00128 
00129   // Header
00130   odom->header.stamp = ros::Time::now();
00131   odom->header.frame_id = odom_frame;
00132   odom->child_frame_id = base_frame;
00133 
00134   // Position
00135   odom->pose.pose.position.x = pose.x();
00136   odom->pose.pose.position.y = pose.y();
00137   odom->pose.pose.position.z = 0.0;
00138   odom->pose.pose.orientation = odom_quat;
00139 
00140   // Velocity
00141   odom->twist.twist.linear.x = pose_update_rates[0];
00142   odom->twist.twist.linear.y = pose_update_rates[1];
00143   odom->twist.twist.angular.z = pose_update_rates[2];
00144 
00145   // Pose covariance (required by robot_pose_ekf) TODO: publish realistic values
00146   // Odometry yaw covariance must be much bigger than the covariance provided
00147   // by the imu, as the later takes much better measures
00148   odom->pose.covariance[0]  = 0.1;
00149   odom->pose.covariance[7]  = 0.1;
00150   odom->pose.covariance[35] = use_imu_heading ? 0.05 : 0.2;
00151 
00152   odom->pose.covariance[14] = DBL_MAX; // set a non-zero covariance on unused
00153   odom->pose.covariance[21] = DBL_MAX; // dimensions (z, pitch and roll); this
00154   odom->pose.covariance[28] = DBL_MAX; // is a requirement of robot_pose_ekf
00155 
00156   odom_publisher.publish(odom);
00157 }
00158 
00159 } // namespace kobuki


kobuki_node
Author(s): Daniel Stonier , Younghun Ju , Jorge Santos Simon
autogenerated on Wed Sep 16 2015 04:35:37