Go to the documentation of this file.00001 #include <four_wheel_steering_controller/odometry.h>
00002
00003 #include <boost/bind.hpp>
00004
00005 namespace four_wheel_steering_controller
00006 {
00007 namespace bacc = boost::accumulators;
00008
00009 Odometry::Odometry(size_t velocity_rolling_window_size)
00010 : timestamp_(0.0)
00011 , last_update_timestamp_(0.0)
00012 , x_(0.0)
00013 , y_(0.0)
00014 , heading_(0.0)
00015 , linear_(0.0)
00016 , linear_x_(0.0)
00017 , linear_y_(0.0)
00018 , angular_(0.0)
00019 , track_(0.0)
00020 , wheel_radius_(0.0)
00021 , wheel_base_(0.0)
00022 , wheel_old_pos_(0.0)
00023 , velocity_rolling_window_size_(velocity_rolling_window_size)
00024 , linear_acc_(RollingWindow::window_size = velocity_rolling_window_size)
00025 , angular_acc_(RollingWindow::window_size = velocity_rolling_window_size)
00026 {
00027 }
00028
00029 void Odometry::init(const ros::Time& time)
00030 {
00031
00032 resetAccumulators();
00033 timestamp_ = time;
00034 }
00035
00036
00037 bool Odometry::update(const double &fl_speed, const double &fr_speed,
00038 const double &rl_speed, const double &rr_speed,
00039 double front_steering, double rear_steering, const ros::Time &time)
00040 {
00041
00042
00043
00044
00045 const double rear_tmp = cos(rear_steering)*(tan(front_steering)-tan(rear_steering))/wheel_base_;
00046 const double rear_linear_speed = wheel_radius_ * copysign(1.0, rl_speed+rr_speed)*
00047 sqrt((pow(rl_speed,2)+pow(rr_speed,2))/(2+pow(track_*rear_tmp,2)/2.0));
00048
00049 angular_ = rear_linear_speed*rear_tmp;
00050
00051 linear_x_ = rear_linear_speed*cos(rear_steering);
00052 linear_y_ = rear_linear_speed*sin(rear_steering)
00053 + wheel_base_*angular_/2.0;
00054 linear_ = copysign(1.0, rear_linear_speed)*sqrt(pow(linear_x_,2)+pow(linear_y_,2));
00055
00057 const double dt = (time - last_update_timestamp_).toSec();
00058 last_update_timestamp_ = time;
00060 integrateXY(linear_x_*dt, linear_y_*dt, angular_*dt);
00061
00062 return true;
00063 }
00064
00065 void Odometry::updateOpenLoop(double linear, double angular, const ros::Time &time)
00066 {
00068 linear_ = linear;
00069 angular_ = angular;
00070
00072 const double dt = (time - timestamp_).toSec();
00073 timestamp_ = time;
00074 integrateExact(linear * dt, angular * dt);
00075 }
00076
00077 void Odometry::setWheelParams(double track, double wheel_radius, double wheel_base)
00078 {
00079 track_ = track;
00080 wheel_radius_ = wheel_radius;
00081 wheel_base_ = wheel_base;
00082 }
00083
00084 void Odometry::setVelocityRollingWindowSize(size_t velocity_rolling_window_size)
00085 {
00086 velocity_rolling_window_size_ = velocity_rolling_window_size;
00087
00088 resetAccumulators();
00089 }
00090
00091 void Odometry::integrateXY(double linear_x, double linear_y, double angular)
00092 {
00093 const double delta_x = linear_x*cos(heading_) - linear_y*sin(heading_);
00094 const double delta_y = linear_x*sin(heading_) + linear_y*cos(heading_);
00095
00096 x_ += delta_x;
00097 y_ += delta_y;
00098 heading_ += angular;
00099 }
00100
00101 void Odometry::integrateRungeKutta2(double linear, double angular)
00102 {
00103 const double direction = heading_ + angular * 0.5;
00104
00106 x_ += linear * cos(direction);
00107 y_ += linear * sin(direction);
00108 heading_ += angular;
00109 }
00110
00111 void Odometry::integrateExact(double linear, double angular)
00112 {
00113 if (fabs(angular) < 1e-6)
00114 integrateRungeKutta2(linear, angular);
00115 else
00116 {
00118 const double heading_old = heading_;
00119 const double r = linear/angular;
00120 heading_ += angular;
00121 x_ += r * (sin(heading_) - sin(heading_old));
00122 y_ += -r * (cos(heading_) - cos(heading_old));
00123 }
00124 }
00125
00126 void Odometry::resetAccumulators()
00127 {
00128 linear_acc_ = RollingMeanAcc(RollingWindow::window_size = velocity_rolling_window_size_);
00129 angular_acc_ = RollingMeanAcc(RollingWindow::window_size = velocity_rolling_window_size_);
00130 }
00131
00132 }