poseupdate.cpp
Go to the documentation of this file.
1 //=================================================================================================
2 // Copyright (c) 2011, Johannes Meyer, TU Darmstadt
3 // All rights reserved.
4 
5 // Redistribution and use in source and binary forms, with or without
6 // modification, are permitted provided that the following conditions are met:
7 // * Redistributions of source code must retain the above copyright
8 // notice, this list of conditions and the following disclaimer.
9 // * Redistributions in binary form must reproduce the above copyright
10 // notice, this list of conditions and the following disclaimer in the
11 // documentation and/or other materials provided with the distribution.
12 // * Neither the name of the Flight Systems and Automatic Control group,
13 // TU Darmstadt, nor the names of its contributors may be used to
14 // endorse or promote products derived from this software without
15 // specific prior written permission.
16 
17 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
18 // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
21 // DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22 // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23 // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24 // ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 //=================================================================================================
28 
31 
32 #include <Eigen/Core>
33 
34 #include <boost/bind.hpp>
35 
36 namespace hector_pose_estimation {
37 
38 PoseUpdate::PoseUpdate(const std::string& name)
39  : Measurement(name)
40 {
41  fixed_alpha_ = 0.0;
42  fixed_beta_ = 0.0;
44 
46  predict_pose_ = true;
47 
48  jump_on_max_error_ = true;
49 
52  fixed_yaw_stddev_ = 0.0;
53 
58 
59  max_position_xy_error_ = 3.0; // 3 sigma
60  max_position_z_error_ = 3.0; // 3 sigma
61  max_yaw_error_ = 3.0; // 3 sigma
62 
63  max_velocity_xy_error_ = 3.0; // 3 sigma
64  max_velocity_z_error_ = 3.0; // 3 sigma
65  max_angular_rate_xy_error_ = 3.0; // 3 sigma
66  max_angular_rate_z_error_ = 3.0; // 3 sigma
67 
68  parameters().add("fixed_alpha", fixed_alpha_);
69  parameters().add("fixed_beta", fixed_beta_);
70  parameters().add("interpret_covariance_as_information_matrix", interpret_covariance_as_information_matrix_);
71  parameters().add("max_time_difference", max_time_difference_);
72  parameters().add("predict_pose", predict_pose_);
73  parameters().add("jump_on_max_error", jump_on_max_error_);
74 
75  parameters().add("fixed_position_xy_stddev", fixed_position_xy_stddev_);
76  parameters().add("fixed_position_z_stddev", fixed_position_z_stddev_);
77  parameters().add("fixed_yaw_stddev", fixed_yaw_stddev_);
78  parameters().add("fixed_velocity_xy_stddev", fixed_velocity_xy_stddev_);
79  parameters().add("fixed_velocity_z_stddev", fixed_velocity_z_stddev_);
80  parameters().add("fixed_angular_rate_xy_stddev", fixed_angular_rate_xy_stddev_);
81  parameters().add("fixed_angular_rate_z_stddev", fixed_angular_rate_z_stddev_);
82  parameters().add("max_position_xy_error", max_position_xy_error_ );
83  parameters().add("max_position_z_error", max_position_z_error_);
84  parameters().add("max_yaw_error", max_yaw_error_);
85  parameters().add("max_velocity_xy_error", max_velocity_xy_error_ );
86  parameters().add("max_velocity_z_error", max_velocity_z_error_);
87  parameters().add("max_angular_rate_xy_error", max_angular_rate_xy_error_ );
88  parameters().add("max_angular_rate_z_error", max_angular_rate_z_error_);
89 }
90 
92 {
93 }
94 
96 {
97  Update const &update = static_cast<Update const &>(update_);
98 
99  while (update.pose) {
100  // convert incoming update information to Eigen
101  Eigen::Vector3d update_pose(update.pose->pose.pose.position.x, update.pose->pose.pose.position.y, update.pose->pose.pose.position.z);
102  Eigen::Quaterniond update_orientation(update.pose->pose.pose.orientation.w, update.pose->pose.pose.orientation.x, update.pose->pose.pose.orientation.y, update.pose->pose.pose.orientation.z);
103  Eigen::Vector3d update_euler;
104 
105  // information is the information matrix if interpret_covariance_as_information_matrix_ is true and a covariance matrix otherwise
106  // zero elements are counted as zero information in any case
107  SymmetricMatrix6 information(Eigen::Map<const SymmetricMatrix6>(update.pose->pose.covariance.data()));
108 
109  ROS_DEBUG_STREAM_NAMED("poseupdate", "PoseUpdate: x = [ " << filter()->state().getVector().transpose() << " ], P = [ " << filter()->state().getCovariance() << " ]" << std::endl
110  << "update: pose = [ " << update_pose.transpose() << " ], rpy = [ " << update_euler.transpose() << " ], information = [ " << information << " ]");
111  ROS_DEBUG_STREAM_NAMED("poseupdate", "dt = " << (filter()->state().getTimestamp() - update.pose->header.stamp).toSec() << " s");
112 
113  // predict update pose using the estimated velocity and degrade information
114  if (!update.pose->header.stamp.isZero()) {
115  double dt = (filter()->state().getTimestamp() - update.pose->header.stamp).toSec();
116  if (dt < 0.0) {
117  ROS_DEBUG_STREAM_NAMED("poseupdate", "Ignoring pose update as it has a negative time difference: dt = " << dt << "s");
118  break;
119 
120  } else if (max_time_difference_ > 0.0 && dt >= max_time_difference_) {
121  ROS_DEBUG_STREAM_NAMED("poseupdate", "Ignoring pose update as the time difference is too large: dt = " << dt << "s");
122  break;
123 
124  } else if (max_time_difference_ > 0.0){
126  information = information * (1.0 - dt/max_time_difference_);
127  else
128  information = information / (1.0 - dt/max_time_difference_);
129  }
130 
131  if (predict_pose_) {
132  State::ConstVelocityType state_velocity(filter()->state().getVelocity());
133  update_pose = update_pose + state_velocity * dt;
134 
135  State::ConstRateType state_rate(filter()->state().getRate());
136  update_orientation = update_orientation * Eigen::Quaterniond().fromRotationVector(state_rate * dt);
137  }
138  }
139 
140  // Calculate euler angles
141  {
142  const Eigen::Quaterniond &q = update_orientation;
143  /* roll = */ update_euler(0) = atan2(2*(q.y()*q.z() + q.w()*q.x()), q.w()*q.w() - q.x()*q.x() - q.y()*q.y() + q.z()*q.z());
144  /* pitch = */ update_euler(1) = -asin(2*(q.x()*q.z() - q.w()*q.y()));
145  /* yaw = */ update_euler(2) = atan2(2*(q.x()*q.y() + q.w()*q.z()), q.w()*q.w() + q.x()*q.x() - q.y()*q.y() - q.z()*q.z());
146  }
147 
148  // update PositionXY
149  if (information(0,0) > 0.0 || information(1,1) > 0.0) {
150  // fetch observation matrix H and current state x
151  PositionXYModel::MeasurementMatrix H(position_xy_model_.getDimension(), filter()->state().getCovarianceDimension());
152  PositionXYModel::MeasurementVector x(position_xy_model_.getDimension());
153  position_xy_model_.getStateJacobian(H, filter()->state(), true);
155 
156  PositionXYModel::MeasurementVector y(update_pose.segment<2>(0));
157  PositionXYModel::NoiseVariance Iy(information.block<2,2>(0,0));
158 
159  // invert Iy if information is a covariance matrix
160  if (!interpret_covariance_as_information_matrix_) Iy = Iy.inverse().eval();
161 
162  // fixed_position_xy_stddev_ = 1.0;
163  if (fixed_position_xy_stddev_ != 0.0) {
164  Iy.setZero();
165  Iy(0,0) = Iy(1,1) = 1.0 / (fixed_position_xy_stddev_*fixed_position_xy_stddev_);
166  }
167 
168  ROS_DEBUG_STREAM_NAMED("poseupdate", "Position Update: ");
169  ROS_DEBUG_STREAM_NAMED("poseupdate", " x = [" << x.transpose() << "], H = [ " << H << " ], Px = [" << (H * filter()->state().P() * H.transpose()) << "], Ix = [ " << (H * filter()->state().P() * H.transpose()).inverse() << "]");
170  ROS_DEBUG_STREAM_NAMED("poseupdate", " y = [" << y.transpose() << "], Iy = [ " << Iy << " ]");
171  double innovation = updateInternal(filter()->state(), Iy, y - x, H, "position_xy", max_position_xy_error_, boost::bind(&PositionXYModel::updateState, &position_xy_model_, _1, _2));
173  ROS_DEBUG_STREAM_NAMED("poseupdate", " ==> xy = [" << x << "], Pxy = [ " << (H * filter()->state().P() * H.transpose()) << " ], innovation = " << innovation);
174 
176  }
177 
178  // update PositionZ
179  if (information(2,2) > 0.0) {
180  // fetch observation matrix H and current state x
181  PositionZModel::MeasurementMatrix H(position_z_model_.getDimension(), filter()->state().getCovarianceDimension());
182  PositionZModel::MeasurementVector x(position_z_model_.getDimension());
183  position_z_model_.getStateJacobian(H, filter()->state(), true);
185 
186  PositionZModel::MeasurementVector y(update_pose.segment<1>(2));
187  PositionZModel::NoiseVariance Iy(information.block<1,1>(2,2));
188 
189  // invert Iy if information is a covariance matrix
190  if (!interpret_covariance_as_information_matrix_) Iy = Iy.inverse().eval();
191 
192  // fixed_position_z_stddev_ = 1.0;
193  if (fixed_position_z_stddev_ != 0.0) {
194  Iy.setZero();
196  }
197 
198  ROS_DEBUG_STREAM_NAMED("poseupdate", "Height Update: ");
199  ROS_DEBUG_STREAM_NAMED("poseupdate", " x = " << x(0) << ", H = [ " << H << " ], Px = [" << (H * filter()->state().P() * H.transpose()) << "], Ix = [ " << (H * filter()->state().P() * H.transpose()).inverse() << "]");
200  ROS_DEBUG_STREAM_NAMED("poseupdate", " y = " << y(0) << ", Iy = [ " << Iy << " ]");
201  double innovation = updateInternal(filter()->state(), Iy, y - x, H, "position_z", max_position_z_error_, boost::bind(&PositionZModel::updateState, &position_z_model_, _1, _2));
203  ROS_DEBUG_STREAM_NAMED("poseupdate", " ==> xy = " << x(0) << ", Pxy = [ " << (H * filter()->state().P() * H.transpose()) << " ], innovation = " << innovation);
204 
206  }
207 
208  // update Yaw
209  if (information(5,5) > 0.0) {
210  YawModel::MeasurementMatrix H(yaw_model_.getDimension(), filter()->state().getCovarianceDimension());
211  YawModel::MeasurementVector x(yaw_model_.getDimension());
212  yaw_model_.getStateJacobian(H, filter()->state(), true);
213  yaw_model_.getExpectedValue(x, filter()->state());
214 
215  YawModel::MeasurementVector y(update_euler.tail<1>());
216  YawModel::NoiseVariance Iy(information.block<1,1>(5,5));
217 
218  // invert Iy if information is a covariance matrix
219  if (!interpret_covariance_as_information_matrix_) Iy = Iy.inverse().eval();
220 
221  // fixed_yaw_stddev_ = 5.0 * M_PI/180.0;
222  if (fixed_yaw_stddev_ != 0.0) {
223  Iy.setZero();
224  Iy(0,0) = 1.0 / (fixed_yaw_stddev_*fixed_yaw_stddev_);
225  }
226 
227  ROS_DEBUG_STREAM_NAMED("poseupdate", "Yaw Update: ");
228  ROS_DEBUG_STREAM_NAMED("poseupdate", " x = " << x(0) * 180.0/M_PI << "°, H = [ " << H << " ], Px = [" << (H * filter()->state().P() * H.transpose()) << "], Ix = [ " << (H * filter()->state().P() * H.transpose()).inverse() << "]");
229  ROS_DEBUG_STREAM_NAMED("poseupdate", " y = " << y(0) * 180.0/M_PI << "°, Iy = [ " << Iy << " ]");
230 
231  YawModel::MeasurementVector error(y - x);
232  error(0) = error(0) - 2.0*M_PI * round(error(0) / (2.0*M_PI));
233 
234  double innovation = updateInternal(filter()->state(), Iy, error, H, "yaw", max_yaw_error_, boost::bind(&YawModel::updateState, &yaw_model_, _1, _2));
235  yaw_model_.getExpectedValue(x, filter()->state());
236  ROS_DEBUG_STREAM_NAMED("poseupdate", " ==> xy = " << x(0) * 180.0/M_PI << "°, Pxy = [ " << (H * filter()->state().P() * H.transpose()) << " ], innovation = " << innovation);
237 
239  }
240 
241  break;
242  }
243 
244  while (update.twist) {
245  // convert incoming update information to Eigen
246  Eigen::Vector3d update_linear(update.twist->twist.twist.linear.x, update.twist->twist.twist.linear.y, update.twist->twist.twist.linear.z);
247  Eigen::Vector3d update_angular(update.twist->twist.twist.angular.x, update.twist->twist.twist.angular.y, update.twist->twist.twist.angular.z);
248 
249  // information is the information matrix if interpret_covariance_as_information_matrix_ is true and a covariance matrix otherwise
250  // zero elements are counted as zero information in any case
251  SymmetricMatrix6 information(Eigen::Map<const SymmetricMatrix6>(update.twist->twist.covariance.data()));
252 
253  ROS_DEBUG_STREAM_NAMED("poseupdate", "TwistUpdate: state = [ " << filter()->state().getVector().transpose() << " ], P = [ " << filter()->state().getCovariance() << " ]" << std::endl
254  << " update: linear = [ " << update_linear.transpose() << " ], angular = [ " << update_angular.transpose() << " ], information = [ " << information << " ]");
255  ROS_DEBUG_STREAM_NAMED("poseupdate", " dt = " << (filter()->state().getTimestamp() - update.twist->header.stamp).toSec() << " s");
256 
257  // degrade information if the time difference is too large
258  if (!update.twist->header.stamp.isZero()) {
259  double dt = (filter()->state().getTimestamp() - update.twist->header.stamp).toSec();
260  if (dt < 0.0) {
261  ROS_DEBUG_STREAM_NAMED("poseupdate", "Ignoring twist update as it has a negative time difference: dt = " << dt << "s");
262  break;
263 
264  } else if (max_time_difference_ > 0.0 && dt >= max_time_difference_) {
265  ROS_DEBUG_STREAM_NAMED("poseupdate", "Ignoring twist update as the time difference is too large: dt = " << dt << "s");
266  break;
267 
268  } else if (max_time_difference_ > 0.0){
270  information = information * (1.0 - dt/max_time_difference_);
271  else
272  information = information / (1.0 - dt/max_time_difference_);
273  }
274  }
275 
276  // fetch observation matrix H and current state x
277  TwistModel::MeasurementMatrix H(twist_model_.getDimension(), filter()->state().getCovarianceDimension());
278  TwistModel::MeasurementVector x(twist_model_.getDimension());
279  twist_model_.getStateJacobian(H, filter()->state(), true);
280  twist_model_.getExpectedValue(x, filter()->state());
281 
282  TwistModel::MeasurementVector y(twist_model_.getDimension());
283  TwistModel::NoiseVariance Iy(information);
284  y.segment<3>(0) = update_linear;
285  y.segment<3>(3) = update_angular;
286 
287  // invert Iy if information is a covariance matrix
289  ROS_DEBUG_NAMED("poseupdate", "Twist updates with covariance matrices are currently not supported");
290  break;
291  }
292 
293  // update VelocityXY
294  if (information(0,0) > 0.0 || information(0,0) > 0.0) {
296 
297  // fixed_velocity_xy_stddev_ = 1.0;
298  if (fixed_velocity_xy_stddev_ != 0.0) {
299  for(int i = 0; i < 6; ++i) Iy(0,i) = Iy(1,i) = Iy(i,0) = Iy(i,1) = 0.0;
300  Iy(0,0) = Iy(1,1) = 1.0 / (fixed_velocity_xy_stddev_*fixed_velocity_xy_stddev_);
301  }
302  }
303 
304  // update VelocityZ
305  if (information(2,2) > 0.0) {
307 
308  // fixed_velocity_z_stddev_ = 1.0;
309  if (fixed_velocity_z_stddev_ != 0.0) {
310  for(int i = 0; i < 6; ++i) Iy(2,i) = Iy(i,2) = 0.0;
312  }
313  }
314 
315  // update RateXY
316  if (information(3,3) > 0.0 || information(4,4) > 0.0) {
318 
319  // fixed_angular_rate_xy_stddev_ = 1.0;
320  if (fixed_angular_rate_xy_stddev_ != 0.0) {
321  for(int i = 0; i < 6; ++i) Iy(3,i) = Iy(3,i) = Iy(i,4) = Iy(i,4) = 0.0;
323  }
324  }
325 
326  // update RateZ
327  if (information(5,5) > 0.0) {
329 
330  // fixed_angular_rate_z_stddev_ = 1.0;
331  if (fixed_angular_rate_z_stddev_ != 0.0) {
332  for(int i = 0; i < 6; ++i) Iy(5,i) = Iy(i,5) = 0.0;
334  }
335  }
336 
337  ROS_DEBUG_STREAM_NAMED("poseupdate", "Twist Update: ");
338  ROS_DEBUG_STREAM_NAMED("poseupdate", " x = [" << x.transpose() << "], H = [ " << H << " ], Px = [" << (H * filter()->state().P() * H.transpose()) << "], Ix = [ " << (H * filter()->state().P() * H.transpose()).inverse() << "]");
339  ROS_DEBUG_STREAM_NAMED("poseupdate", " y = [" << y.transpose() << "], Iy = [ " << Iy << " ]");
340  double innovation = updateInternal(filter()->state(), Iy, y - x, H, "twist", 0.0);
341  twist_model_.getExpectedValue(x, filter()->state());
342  ROS_DEBUG_STREAM_NAMED("poseupdate", " ==> xy = [" << x.transpose() << "], Pxy = [ " << (H * filter()->state().P() * H.transpose()) << " ], innovation = " << innovation);
343 
344  break;
345  }
346 
347  // already done in Measurement::update()
348  // filter()->state().updated();
349  return true;
350 }
351 
353  double tr_x = Ix.trace();
354  double tr_y = Iy.trace();
355  return tr_y / (tr_x + tr_y);
356 }
357 
358 template <typename MeasurementVector, typename MeasurementMatrix, typename NoiseVariance>
359 double PoseUpdate::updateInternal(State &state, const NoiseVariance &Iy, const MeasurementVector &error, const MeasurementMatrix &H, const std::string& text, const double max_error, JumpFunction jump_function) {
360  NoiseVariance H_Px_HT(H * state.P() * H.transpose());
361 
362  if (H_Px_HT.determinant() <= 0) {
363  ROS_DEBUG_STREAM("Ignoring poseupdate for " << text << " as the a-priori state covariance is zero!");
364  return 0.0;
365  }
366  NoiseVariance Ix(H_Px_HT.inverse().eval());
367 
368  ROS_DEBUG_STREAM_NAMED("poseupdate", "H = [" << H << "]");
369  ROS_DEBUG_STREAM_NAMED("poseupdate", "Ix = [" << Ix << "]");
370 
371  double alpha = fixed_alpha_, beta = fixed_beta_;
372  if (alpha == 0.0 && beta == 0.0) {
373  beta = calculateOmega(Ix, Iy);
374  alpha = 1.0 - beta;
375 
376 // if (beta > 0.8) {
377 // ROS_DEBUG_STREAM("Reducing update variance for " << text << " due to high information difference between Ix = [" << Ix << "] and Iy = [" << Iy << "]");
378 // beta = 0.8;
379 // alpha = 1.0 - beta;
380 // }
381  }
382  ROS_DEBUG_STREAM_NAMED("poseupdate", "alpha = " << alpha << ", beta = " << beta);
383 
384  if (max_error > 0.0) {
385  double error2 = (error.transpose() * Ix * (Ix + Iy).inverse() * Iy * error)(0);
386  if (error2 > max_error * max_error) {
387  if (!jump_on_max_error_ || !jump_function) {
388  ROS_WARN_STREAM_NAMED("poseupdate", "Ignoring poseupdate for " << text << " as the error [ " << error.transpose() << " ], |error| = " << sqrt(error2) << " sigma exceeds max_error!");
389  return 0.0;
390  } else {
391  ROS_WARN_STREAM_NAMED("poseupdate", "Update for " << text << " with error [ " << error.transpose() << " ], |error| = " << sqrt(error2) << " sigma exceeds max_error!");
392  jump_function(state, error);
393  return 0.0;
394  }
395  }
396  }
397 
398 // SymmetricMatrix Ii(Ix * (alpha - 1) + Iy * beta);
399 // double innovation = Ii.determinant();
400 // ROS_DEBUG_STREAM_NAMED("poseupdate", "Ii = [" << Ii << "], innovation = " << innovation);
401 
402  // S_1 is equivalent to S^(-1) = (H*P*H^T + R)^(-1) in the standard Kalman gain
403  NoiseVariance S_1(Ix - Ix * (Ix * alpha + Iy * beta).inverse() * Ix);
405  ROS_DEBUG_STREAM_NAMED("poseupdate", "P*HT = [" << (P_HT) << "]");
406 
407  double innovation = S_1.determinant();
408  state.P() = state.P() - P_HT * S_1 * P_HT.transpose(); // may invalidate Px if &Pxy == &Px
409  state.P().assertSymmetric();
410  state.update(P_HT * Iy * beta * error);
411  // state.x() = state.x() + P_HT * Iy * beta * error;
412 
413  ROS_DEBUG_STREAM_NAMED("poseupdate", "K = [" << (P_HT * Iy * beta) << "]");
414  ROS_DEBUG_STREAM_NAMED("poseupdate", "dx = [" << (P_HT * Iy * beta * error).transpose() << "]");
415 
416  return innovation;
417 }
418 
419 void PositionXYModel::getExpectedValue(MeasurementVector &y_pred, const State &state) {
420  y_pred = state.getPosition().head<2>();
421 }
422 
423 void PositionXYModel::getStateJacobian(MeasurementMatrix &C, const State &state, bool init) {
424  if (init) {
425  if (state.position()) {
426  state.position()->cols(C)(0,X) = 1.0;
427  state.position()->cols(C)(1,Y) = 1.0;
428  }
429  }
430 }
431 
432 void PositionXYModel::updateState(State &state, const ColumnVector &diff) const {
433  if (state.position()) {
434  state.position()->vector().head<2>() += diff;
435  }
436 }
437 
438 void PositionZModel::getExpectedValue(MeasurementVector &y_pred, const State &state) {
439  y_pred(0) = state.getPosition().z();
440 }
441 
442 void PositionZModel::getStateJacobian(MeasurementMatrix &C, const State &state, bool init) {
443  if (init && state.position()) {
444  state.position()->cols(C)(0,Z) = 1.0;
445  }
446 }
447 
448 void PositionZModel::updateState(State &state, const ColumnVector &diff) const {
449  if (state.position()) {
450  state.position()->vector().segment<1>(Z) += diff;
451  }
452 }
453 
454 void YawModel::getExpectedValue(MeasurementVector &y_pred, const State &state) {
455  y_pred(0) = state.getYaw();
456 }
457 
458 void YawModel::getStateJacobian(MeasurementMatrix &C, const State &state, bool init) {
459  if (init && state.orientation()) {
460  state.orientation()->cols(C)(0,Z) = 1.0;
461  }
462 }
463 
464 void YawModel::updateState(State &state, const ColumnVector &diff) const {
465  Eigen::Quaterniond::Matrix3 rotation(Eigen::AngleAxisd(diff(0), Eigen::Vector3d::UnitZ()));
466 
467  Eigen::MatrixXd S(Eigen::MatrixXd::Identity(state.getCovarianceDimension(), state.getCovarianceDimension()));
468 
469  if (state.orientation()) {
470 // S.block(state.orientation()->getCovarianceIndex(), state.orientation()->getCovarianceIndex(), 4, 4) <<
471 // /* QUATERNION_X: */ rotation.w(), -rotation.z(), rotation.y(), rotation.x(),
472 // /* QUATERNION_Y: */ rotation.z(), rotation.w(), -rotation.x(), rotation.y(),
473 // /* QUATERNION_Z: */ -rotation.y(), rotation.x(), rotation.w(), rotation.z(),
474 // /* QUATERNION_W: */ -rotation.x(), -rotation.y(), -rotation.z(), rotation.w();
475  S.block(state.orientation()->getCovarianceIndex(), state.orientation()->getCovarianceIndex(), 3, 3) = rotation.transpose();
476  state.updateOrientation(ColumnVector3(0.0, 0.0, -diff(0)));
477  }
478 
479  if (state.velocity()) {
480  S.block(state.velocity()->getCovarianceIndex(), state.velocity()->getCovarianceIndex(), 3, 3) = rotation.transpose();
481  state.velocity()->vector() = rotation.transpose() * state.velocity()->vector();
482  }
483 
484 // Rate vector is in body frame. No need to rotate it.
485 // if (state.rate()) {
486 // S.block(state.rate()->getCovarianceIndex(), state.rate()->getCovarianceIndex(), 3, 3) = rotation.transpose();
487 // state.rate()->vector() = rotation.transpose() * state.rate()->vector();
488 // }
489 
490  ROS_DEBUG_STREAM_NAMED("poseupdate", "Jump yaw by " << (diff(0) * 180.0/M_PI) << " degrees. rotation = [" << rotation << "], S = [" << S << "].");
491 
492  // update covariance matrix P
493  state.P() = S * state.P() * S.transpose();
494 }
495 
496 void TwistModel::getExpectedValue(MeasurementVector &y_pred, const State &state) {
497  y_pred.segment<3>(0) = state.getVelocity();
498  y_pred.segment<3>(3) = state.getRate();
499 }
500 
501 void TwistModel::getStateJacobian(MeasurementMatrix &C, const State &state, bool init) {
502  if (init && state.velocity()) {
503  state.velocity()->cols(C)(0,X) = 1.0;
504  state.velocity()->cols(C)(1,Y) = 1.0;
505  state.velocity()->cols(C)(2,Z) = 1.0;
506  }
507 
508  if (init && state.rate()) {
509  state.rate()->cols(C)(3,X) = 1.0;
510  state.rate()->cols(C)(4,Y) = 1.0;
511  state.rate()->cols(C)(5,Z) = 1.0;
512  }
513 }
514 
515 } // namespace hector_pose_estimation
virtual bool update(const MeasurementUpdate &update)
double updateInternal(State &state, const NoiseVariance &Iy, const MeasurementVector &error, const MeasurementMatrix &H, const std::string &text, const double max_error=0.0, JumpFunction jump_function=JumpFunction())
Definition: poseupdate.cpp:359
#define ROS_DEBUG_STREAM_NAMED(name, args)
virtual const boost::shared_ptr< OrientationStateType > & orientation() const
Definition: state.h:112
virtual void getExpectedValue(MeasurementVector &y_pred, const State &state)
Definition: poseupdate.cpp:419
virtual void getExpectedValue(MeasurementVector &y_pred, const State &state)
Definition: poseupdate.cpp:438
void updateState(State &state, const ColumnVector &diff) const
Definition: poseupdate.cpp:432
virtual void getStateJacobian(MeasurementMatrix &C, const State &state, bool init)
Definition: poseupdate.cpp:442
void updateState(State &state, const ColumnVector &diff) const
Definition: poseupdate.cpp:464
virtual ConstRateType getRate() const
Definition: state.cpp:117
virtual ParameterList & parameters()
Definition: measurement.h:63
virtual ConstVelocityType getVelocity() const
Definition: state.cpp:119
virtual const boost::shared_ptr< PositionStateType > & position() const
Definition: state.h:114
void updateState(State &state, const ColumnVector &diff) const
Definition: poseupdate.cpp:448
virtual void updateOrientation(const ColumnVector3 &rotation_vector)
Definition: state.cpp:195
TFSIMD_FORCE_INLINE const tfScalar & y() const
virtual bool updateImpl(const MeasurementUpdate &update)
Definition: poseupdate.cpp:95
virtual void getExpectedValue(MeasurementVector &y_pred, const State &state)
Definition: poseupdate.cpp:454
geometry_msgs::PoseWithCovarianceStampedConstPtr pose
Definition: poseupdate.h:97
virtual Filter * filter() const
Definition: measurement.h:56
virtual const State & state() const
Definition: filter.h:50
ParameterList & add(const std::string &key, T &value, const T &default_value)
Definition: parameters.h:148
#define ROS_DEBUG_NAMED(name,...)
SymmetricMatrix_< 6 >::type SymmetricMatrix6
Definition: matrix.h:87
TFSIMD_FORCE_INLINE Quaternion inverse(const Quaternion &q)
virtual IndexType getCovarianceDimension() const
Definition: state.h:77
Matrix_< 3, 3 >::type Matrix3
Definition: matrix.h:80
virtual Covariance & P()
Definition: state.h:93
TFSIMD_FORCE_INLINE const tfScalar & x() const
double getYaw() const
Definition: state.cpp:139
double calculateOmega(const SymmetricMatrix &Ix, const SymmetricMatrix &Iy)
Definition: poseupdate.cpp:352
virtual void getExpectedValue(MeasurementVector &y_pred, const State &state)
Definition: poseupdate.cpp:496
ColumnVector_< Dynamic >::type ColumnVector
Definition: matrix.h:58
Eigen::Matrix< ScalarType, Rows, Cols,(Rows==1 &&Cols!=1?Eigen::RowMajor:Eigen::ColMajor),(Rows!=Dynamic?Rows:MaxMatrixRowsCols),(Cols!=Dynamic?Cols:MaxMatrixRowsCols) > type
Definition: matrix.h:77
#define ROS_DEBUG_STREAM(args)
virtual const boost::shared_ptr< VelocityStateType > & velocity() const
Definition: state.h:115
geometry_msgs::TwistWithCovarianceStampedConstPtr twist
Definition: poseupdate.h:98
virtual bool init(PoseEstimation &estimator, State &state)
Definition: measurement.cpp:53
boost::function< void(State &state, const ColumnVector &diff)> JumpFunction
Definition: poseupdate.h:133
const ros::Time & getTimestamp(const T &t)
virtual const boost::shared_ptr< RateStateType > & rate() const
Definition: state.h:113
VectorBlock< const Vector, 3 > ConstRateType
Definition: state.h:58
virtual void getStateJacobian(MeasurementMatrix &C, const State &state, bool init)
Definition: poseupdate.cpp:458
virtual void update(const Vector &vector_update)
Definition: state.cpp:160
const ros::Time & getTimestamp() const
Definition: state.h:147
SymmetricMatrix_< Dynamic >::type SymmetricMatrix
Definition: matrix.h:88
ColumnVector_< 3 >::type ColumnVector3
Definition: matrix.h:59
virtual ConstPositionType getPosition() const
Definition: state.cpp:118
VectorBlock< const Vector, 3 > ConstVelocityType
Definition: state.h:64
virtual void getStateJacobian(MeasurementMatrix &C, const State &state, bool init)
Definition: poseupdate.cpp:423
PoseUpdate(const std::string &name="poseupdate")
Definition: poseupdate.cpp:38
#define ROS_WARN_STREAM_NAMED(name, args)
virtual void getStateJacobian(MeasurementMatrix &C, const State &state, bool init)
Definition: poseupdate.cpp:501


hector_pose_estimation_core
Author(s): Johannes Meyer
autogenerated on Thu Feb 18 2021 03:29:30