Go to the documentation of this file.00001
00010
00011
00012
00013
00014 #include "../../include/kobuki_node/odometry.hpp"
00015
00016
00017
00018
00019
00020 namespace kobuki {
00021
00022
00023
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);
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
00093 pose.heading(imu_heading);
00094 pose_update_rates[2] = imu_angular_velocity;
00095 }
00096
00097
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
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
00127 nav_msgs::OdometryPtr odom(new nav_msgs::Odometry);
00128
00129
00130 odom->header.stamp = ros::Time::now();
00131 odom->header.frame_id = odom_frame;
00132 odom->child_frame_id = base_frame;
00133
00134
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
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
00146
00147
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;
00153 odom->pose.covariance[21] = DBL_MAX;
00154 odom->pose.covariance[28] = DBL_MAX;
00155
00156 odom_publisher.publish(odom);
00157 }
00158
00159 }