@@ -58,12 +58,16 @@ namespace diff_drive_controller
5858
5959 Odometry::Odometry (size_t velocity_rolling_window_size)
6060 : timestamp_(0.0 )
61+ , timestamp_twist_(0.0 )
6162 , x_(0.0 )
6263 , y_(0.0 )
6364 , heading_(0.0 )
6465 , v_x_(0.0 )
6566 , v_y_(0.0 )
6667 , v_yaw_(0.0 )
68+ , d_x_(0.0 )
69+ , d_y_(0.0 )
70+ , d_yaw_(0.0 )
6771 , wheel_separation_(0.0 )
6872 , left_wheel_radius_(0.0 )
6973 , right_wheel_radius_(0.0 )
@@ -86,19 +90,19 @@ namespace diff_drive_controller
8690 minimum_twist_covariance_.setIdentity ();
8791 minimum_twist_covariance_ *= DEFAULT_MINIMUM_TWIST_COVARIANCE;
8892
89- // There's no need to initialize the twist covariance because it's updated
90- // from scratch on each cycle, but it's safer to initialize it anyway:
9193 twist_covariance_ = minimum_twist_covariance_;
9294
9395 pose_covariance_.setIdentity ();
9496 pose_covariance_ *= DEFAULT_POSE_COVARIANCE;
97+
98+ incremental_pose_covariance_.setZero ();
9599 }
96100
97101 void Odometry::init (const ros::Time& time)
98102 {
99103 // Reset accumulators and timestamp:
100104 resetAccumulators ();
101- timestamp_ = time;
105+ timestamp_ = timestamp_twist_ = time;
102106 }
103107
104108 bool Odometry::updateCloseLoop (
@@ -138,6 +142,7 @@ namespace diff_drive_controller
138142
139143 // / Compute time step:
140144 const double dt = (time - timestamp_).toSec ();
145+ timestamp_ = time;
141146
142147 // / Update pose and twist:
143148 return update (v_l * dt, v_r * dt, v_l, v_r, time);
@@ -166,72 +171,67 @@ namespace diff_drive_controller
166171 // / Safe new state:
167172 const SE2 p1 (SE2::Scalar (heading_), SE2::Point (x_, y_));
168173
169- // / Update twist:
170- return updateTwist (p0, p1, v_l, v_r, time);
174+ // / Update incremental pose:
175+ // @todo in principle there's no need to use v_l, v_r at all!
176+ // updateIncrementalPose(v_l * dt, v_r * dt);
177+ updateIncrementalPose (dp_l, dp_r);
178+
179+ return true ;
171180 }
172181
173- bool Odometry::updateTwist ( const SE2& p0, const SE2& p1,
174- double v_l, double v_r , const ros::Time& time )
182+ void Odometry::updateIncrementalPose (
183+ const double dp_l , const double dp_r )
175184 {
176- // / We cannot estimate the speed with very small time intervals :
177- const double dt = (time - timestamp_). toSec () ;
178- if (dt < 0.0001 )
179- return false ;
185+ // / Integrate incremental odometry pose :
186+ IntegrateFunction::PoseJacobian J_pose ;
187+ IntegrateFunction::MeasJacobian J_meas;
188+ (*integrate_fun_)(d_x_, d_y_, d_yaw_, dp_l, dp_r, J_pose, J_meas) ;
180189
181- timestamp_ = time;
190+ // / Update Measurement Covariance with the wheel joint position increments:
191+ updateMeasCovariance (dp_l, dp_r);
182192
183- // / Compute relative transformation:
184- const SE2 p = p0.inverse () * p1;
193+ // / Update incremental pose covariance:
194+ incremental_pose_covariance_ =
195+ J_pose * incremental_pose_covariance_ * J_pose.transpose () +
196+ J_meas * meas_covariance_ * J_meas.transpose ();
197+ }
185198
186- // / Retrieve rotation and translation:
187- // / Note that we don't use the log from SE(2) because we didn't use exp
188- // / to create p0 and p1.
189- // / So instead of:
190- // /
191- // / const SE2::Tangent v = p.log();
192- // /
193- // / we use the following:
194- const SE2::ConstTranslationReference t = p.translation ();
199+ bool Odometry::updateTwist (const ros::Time& time)
200+ {
201+ // / We cannot estimate the speed with very small time intervals:
202+ const double dt = (time - timestamp_twist_).toSec ();
203+ if (dt < 0.0001 )
204+ {
205+ return false ;
206+ }
195207
196- v_x_ = t[0 ];
197- v_y_ = t[1 ];
198- v_yaw_ = p.so2 ().log ();
208+ timestamp_twist_ = time;
199209
200210 // / Estimate speeds using a rolling mean to filter them out:
201- v_x_acc_ (v_x_/dt);
202- v_y_acc_ (v_y_/dt);
203- v_yaw_acc_ (v_yaw_/dt);
211+ const double f = 1.0 / dt;
212+
213+ v_x_acc_ (d_x_ * f);
214+ v_y_acc_ (d_y_ * f);
215+ v_yaw_acc_ (d_yaw_ * f);
204216
205217 v_x_ = bacc::rolling_mean (v_x_acc_);
206218 v_y_ = bacc::rolling_mean (v_y_acc_);
207219 v_yaw_ = bacc::rolling_mean (v_yaw_acc_);
208220
209- // / Integrate odometry twist:
210- // / Note that this is done this way because it isn't trivial to compute the
211- // / Jacobians for the relative transformation between p0 and p1
212- const double dp_l = v_l * dt;
213- const double dp_r = v_r * dt;
214-
215- IntegrateFunction::PoseJacobian J_dummy;
216- IntegrateFunction::MeasJacobian J_meas;
217- double x = 0.0 , y = 0.0 , yaw = 0.0 ;
218- (*integrate_fun_)(x, y, yaw, dp_l, dp_r, J_dummy, J_meas);
219-
220- // / Include the Jacobian of dividing by dt, which is equivalent to divide
221- // / all the elements of the other Jacobian by dt:
222- J_meas /= dt;
223-
224- // / Update Measurement Covariance with the wheel joint velocites:
225- updateMeasCovariance (dp_l, dp_r);
226-
227221 // / Update twist covariance:
228- twist_covariance_ = J_meas * meas_covariance_ * J_meas.transpose ();
222+ IntegrateFunction::PoseJacobian J_twist =
223+ IntegrateFunction::PoseJacobian::Identity () * f;
224+ twist_covariance_ = J_twist * incremental_pose_covariance_ * J_twist.transpose ();
229225
230226 // / Add minimum (diagonal) covariance to avoid ill-conditioned covariance
231227 // / matrices, i.e. with a very large condition number, which would make
232228 // / inverse or Cholesky decomposition fail on many algorithms:
233229 twist_covariance_ += minimum_twist_covariance_;
234230
231+ // / Reset incremental pose and its covariance:
232+ d_x_ = d_y_ = d_yaw_ = 0.0 ;
233+ incremental_pose_covariance_.setZero ();
234+
235235 return true ;
236236 }
237237
0 commit comments