Go to the documentation of this file.00001
00026 #include "ros/ros.h"
00027 #include "tf/transform_datatypes.h"
00028 #include "grizzly_motion/dead_reckoning.h"
00029
00030 using Eigen::Vector2f;
00031
00037 bool DeadReckoning::next(const grizzly_msgs::DriveConstPtr& encoders, nav_msgs::Odometry* odom)
00038 {
00039 bool success = false;
00040
00041
00042 Vector2f avg_rotations((encoders->front_left + encoders->rear_left) / 2,
00043 (encoders->front_right + encoders->rear_right) / 2);
00044 Vector2f vels = avg_rotations * radius_;
00045
00046 ros::Duration dt = encoders->header.stamp - last_time_;
00047 if (dt <= max_dt_) {
00048
00049 position_.x += cos(yaw_) * twist_.linear.x * dt.toSec();
00050 position_.y += sin(yaw_) * twist_.linear.x * dt.toSec();
00051
00052
00053 yaw_ += twist_.angular.z * dt.toSec();
00054
00055
00056 twist_.linear.x = vels.mean();
00057 twist_.angular.z = (vels[1] - vels[0]) / width_;
00058
00059
00060 odom->header = encoders->header;
00061 odom->header.frame_id = "odom";
00062 odom->child_frame_id = "base_footprint";
00063 odom->pose.pose.position = position_;
00064 odom->pose.pose.orientation = tf::createQuaternionMsgFromRollPitchYaw(0, 0, yaw_);
00065 odom->twist.twist = twist_;
00066
00067 Eigen::Map<Eigen::MatrixXd> poseCov(odom->pose.covariance.data(), 6, 6);
00068 Eigen::Map<Eigen::MatrixXd> twistCov(odom->twist.covariance.data(), 6, 6);
00069
00070 if(twist_.linear.x <= 1e-3 && twist_.angular.z <= 1e-3) {
00071 poseCov = ODOM_POSE_COVAR_NOMOVE;
00072 twistCov = ODOM_TWIST_COVAR_NOMOVE;
00073 } else {
00074 poseCov = ODOM_POSE_COVAR_MOTION;
00075 twistCov = ODOM_TWIST_COVAR_MOTION;
00076 }
00077
00078 success = true;
00079 } else {
00080 static bool first = true;
00081 ROS_WARN_COND(first, "Gap between encoders messages is too large, no odom generated.");
00082 first = false;
00083 }
00084
00085 last_time_ = encoders->header.stamp;
00086 last_vels_ = vels;
00087 return success;
00088 }