RBFilter.cpp
Go to the documentation of this file.
1 #include <boost/foreach.hpp>
2 
3 #include "rb_tracker/RBFilter.h"
5 
6 #include <boost/numeric/ublas/matrix.hpp>
7 
8 #include <iostream>
9 #include <fstream>
10 
11 #include <Eigen/Cholesky>
12 
13 #include <pcl/filters/filter.h>
14 #include <pcl/point_types.h>
15 #include <pcl_ros/transforms.h>
16 
17 using namespace omip;
18 
20 
21 using namespace MatrixWrapper;
22 using namespace BFL;
23 
24 // Dimensions of each measurement (each feature location)
25 #define MEAS_DIM_RBF 3
26 
27 // Value of the measurement noise (unused, only set at the beginning, but it will change for each concrete feature location)
28 #define COV_MEAS_RBF 1.0
29 
31  _estimation_error_threshold(-1.),
32  _id(RBFilter::_rb_id_generator++),
33  _velocity( 0., 0., 0., 0., 0., 0.),
34  _features_database(),
35  _loop_period_ns(0.),
36  _min_num_supporting_feats_to_correct(5),
37  _use_predicted_state_from_kh(false),
38  _use_predicted_measurement_from_kh(false),
39  _last_time_interval_ns(0.0)
40 {
41  _pose = Eigen::Matrix4d::Identity();
43 }
44 
45 RBFilter::RBFilter(double loop_period_ns,
46  const std::vector<Eigen::Matrix4d>& trajectory,
47  const Eigen::Twistd &initial_velocity,
48  FeaturesDataBase::Ptr feats_database,
49  double estimation_error_threshold) :
50  _loop_period_ns(loop_period_ns),
51  _last_time_interval_ns(loop_period_ns),
52  _estimation_error_threshold(estimation_error_threshold),
54  _pose(trajectory[trajectory.size()-1]),
55  _velocity(initial_velocity),
56  _features_database(feats_database),
60 {
61  this->_initial_location_of_centroid = Feature::Location(trajectory[0](0,3),trajectory[0](1,3),trajectory[0](2,3));
62  this->_trajectory = std::vector<Eigen::Matrix4d>(trajectory.begin()+1, trajectory.end());
63 }
64 
66 {
68 }
69 
71 {
72  this->_id = rbm._id;
73  this->_pose = rbm._pose;
74  this->_velocity = rbm._velocity;
75  this->_trajectory = rbm._trajectory;
85 }
86 
88 {
89 }
90 
91 void RBFilter::predictState(double time_interval_ns)
92 {
93  //Sanity check.
94  if(time_interval_ns < 0)
95  {
96  std::cout << "Time interval negative!" << std::endl;
97  this->_last_time_interval_ns = time_interval_ns;
98  getchar();
99  }
100 
101  // Estimate the new cov matrix depending on the time elapsed between the previous and the current measurement
102  Eigen::Matrix<double, 6, 6> sys_noise_COV = Eigen::Matrix<double, 6, 6>::Zero();
103  sys_noise_COV(0, 0) = this->_cov_sys_acc_tx;//* (std::pow((time_interval_ns/1e9),3) / 3.0);
104  sys_noise_COV(1, 1) = this->_cov_sys_acc_ty;//* (std::pow((time_interval_ns/1e9),3) / 3.0);
105  sys_noise_COV(2, 2) = this->_cov_sys_acc_tz;//* (std::pow((time_interval_ns/1e9),3) / 3.0);
106  sys_noise_COV(3, 3) = this->_cov_sys_acc_rx;//* (std::pow((time_interval_ns/1e9),3) / 3.0);
107  sys_noise_COV(4, 4) = this->_cov_sys_acc_ry;//* (std::pow((time_interval_ns/1e9),3) / 3.0);
108  sys_noise_COV(5, 5) = this->_cov_sys_acc_rz;//* (std::pow((time_interval_ns/1e9),3) / 3.0);
109 
110  // We update the pose with a non-linear rule:
111  // The predicted pose is the belief pose pre-multiplied by the corresponding
112  // delta in pose based on the belief velocity and the time elapsed
113  // This is slightly different to just adding the belief pose and the
114  // belief delta pose in exponential coordinates, but the difference is small
115  // because the delta pose is small when the velocity is small (it is the first linear approximation)
116  Eigen::Twistd belief_delta_pose_ec = (time_interval_ns/1e9)*_velocity;
117  _predicted_pose_vh = belief_delta_pose_ec.exp(1e-12).toHomogeneousMatrix()*_pose;
118 
119  // We also update the covariance based on Barfoot et al.
120  Eigen::Matrix<double, 6, 6> delta_pose_covariance = (time_interval_ns/1e9)*_velocity_covariance;
121 
122  Eigen::Twistd pose_ec;
123  TransformMatrix2Twist(_pose, pose_ec);
124  Eigen::Matrix<double,6,6> adjoint = pose_ec.exp(1e-12).adjoint();
125 
126  // pose_covariance_updated is 6x6
127  _predicted_pose_cov_vh = _pose_covariance + adjoint*delta_pose_covariance*adjoint.transpose();
128 
129  // Finally we add the system noise
130  _predicted_pose_cov_vh += sys_noise_COV;
131 
132  // The additive noise we use in the filter based on braking hypothesis is larger
133  this->_predicted_pose_bh = _pose;
134  this->_predicted_velocity_bh = Eigen::Twistd(0,0,0,0,0,0);
135  this->_predicted_pose_cov_bh = _pose_covariance + sys_noise_COV;
136  this->_predicted_velocity_cov_bh = Eigen::Matrix<double, 6, 6>::Zero();
137 }
138 
139 // This only predicts the location of the Features that are supporting the RBFilter
140 // at this moment.
141 // This happens at the end of the iteration
143 {
144  this->_predicted_measurement_pc_vh->points.clear();
145  this->_predicted_measurement_map_vh.clear();
146  this->_predicted_measurement_pc_bh->points.clear();
147  this->_predicted_measurement_map_bh.clear();
148  this->_predicted_measurement_pc_kh->points.clear();
149  this->_predicted_measurement_map_kh.clear();
150 
151  // We need to do this outside because if we do not have any features we still want to use the predictions from kh
153  {
155  }
156 
157  Feature::Location predicted_location;
158  FeaturePCLwc predicted_location_pcl;
159  Feature::Ptr supporting_feat_ptr;
160  BOOST_FOREACH(Feature::Id supporting_feat_id, this->_supporting_features_ids)
161  {
162  if(this->_features_database->isFeatureStored(supporting_feat_id))
163  {
164  supporting_feat_ptr = this->_features_database->getFeature(supporting_feat_id);
165 
166  // Predict feature location based on velocity hypothesis
167  this->PredictFeatureLocation(supporting_feat_ptr,this->_predicted_pose_vh, true, predicted_location);
168  LocationAndId2FeaturePCLwc(predicted_location, supporting_feat_id, predicted_location_pcl);
169  this->_predicted_measurement_pc_vh->points.push_back(predicted_location_pcl);
170  this->_predicted_measurement_map_vh[supporting_feat_id] = predicted_location;
171 
172  // Predict feature location based on brake hypothesis (same as last)
173  this->PredictFeatureLocation(supporting_feat_ptr,this->_predicted_pose_bh, true, predicted_location);
174  LocationAndId2FeaturePCLwc(predicted_location, supporting_feat_id, predicted_location_pcl);
175  this->_predicted_measurement_pc_bh->points.push_back(predicted_location_pcl);
176  this->_predicted_measurement_map_bh[supporting_feat_id] = predicted_location;
177 
179  {
180  // Predict feature location based on kinematic hypothesis
181  this->PredictFeatureLocation(supporting_feat_ptr,this->_predicted_pose_kh, true, predicted_location);
182  LocationAndId2FeaturePCLwc(predicted_location, supporting_feat_id, predicted_location_pcl);
183  this->_predicted_measurement_pc_kh->points.push_back(predicted_location_pcl);
184  this->_predicted_measurement_map_kh[supporting_feat_id] = predicted_location;
185  this->_use_predicted_state_from_kh = false;
186  }
187  }
188  }
189 }
190 
192 {
193 
194  // Resize matrices
195  int num_supporting_feats = (int)this->_supporting_features_ids.size();
196 
197  if(num_supporting_feats > this->_min_num_supporting_feats_to_correct)
198  {
199  int meas_dimension = 3 * num_supporting_feats;
200 
201  double feature_depth = 0.;
202 
203  Eigen::Map<Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic> > G_t((this->_G_t_memory.data()), 6, meas_dimension);
204  Eigen::Map<Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic> > R_inv_times_innovation((this->_R_inv_times_innovation_memory.data()), meas_dimension, 1);
205 
206  // We need to set them to zero because they are pointing to existing memory regions!
207  G_t.setZero();
208  R_inv_times_innovation.setZero();
209 
210  Feature::Location location_at_birth;
211 
212  int feat_idx = 0;
213 
214  Eigen::Matrix3d R_seq = Eigen::Matrix3d::Zero();
215  Eigen::Matrix<double, 6, 6> P_minus_seq = _predicted_pose_covariance;
216 
217  //std::cout << _predicted_pose_covariance << std::endl;
218  Eigen::Matrix<double, 6, 3> P_HT_seq = Eigen::Matrix<double, 6, 3>::Zero();
219  Eigen::Matrix3d S_seq = Eigen::Matrix3d::Zero();
220  Eigen::Matrix3d S_inv_seq = Eigen::Matrix3d::Zero();
221  Eigen::Matrix<double, 6, 3> K_seq = Eigen::Matrix<double, 6, 3>::Zero();
222 
223  Eigen::Matrix<double, 6, 6> temp_seq1 = Eigen::Matrix<double, 6, 6>::Zero();
224  Eigen::Matrix<double, 6, 6> temp_seq2 = Eigen::Matrix<double, 6, 6>::Zero();
225 
226  Eigen::Vector4d feature_innovation;
227  Eigen::Vector4d location_at_birth_eig;
228 
229  Eigen::Vector4d predicted_location;
230  Eigen::Vector4d current_location;
231 
232  Feature::Ptr supporting_feat_ptr;
233 
234  BOOST_FOREACH(Feature::Id supporting_feat_id, this->_supporting_features_ids)
235  {
236  supporting_feat_ptr = this->_features_database->getFeature(supporting_feat_id);
237 
238  if(supporting_feat_ptr->getFeatureAge() > 1)
239  this->GetLocationOfFeatureAtBirthOfRB( supporting_feat_ptr, false, location_at_birth);
240  LocationOfFeature2EigenVectorHomogeneous(location_at_birth, location_at_birth_eig);
241 
242  Feature::Location current_loc = supporting_feat_ptr->getLastLocation();
243  LocationOfFeature2EigenVectorHomogeneous(current_loc, current_location);
244 
245  predicted_location = _predicted_pose*location_at_birth_eig;
246 
247  feature_innovation = current_location - predicted_location;
248 
249  feature_depth = supporting_feat_ptr->getLastZ();
250 
251  R_seq( 0, 0) = std::max(this->_min_cov_meas_x, feature_depth / this->_meas_depth_factor);
252  R_seq( 1, 1) = std::max(this->_min_cov_meas_y, feature_depth / this->_meas_depth_factor);
253  R_seq( 2, 2) = std::max(this->_min_cov_meas_z, feature_depth / this->_meas_depth_factor);
254 
255  R_inv_times_innovation(3 * feat_idx ) = feature_innovation.x()/(std::max(this->_min_cov_meas_x, feature_depth / this->_meas_depth_factor));
256  R_inv_times_innovation(3 * feat_idx + 1) = feature_innovation.y()/(std::max(this->_min_cov_meas_y, feature_depth / this->_meas_depth_factor));
257  R_inv_times_innovation(3 * feat_idx + 2) = feature_innovation.z()/(std::max(this->_min_cov_meas_z, feature_depth / this->_meas_depth_factor));
258 
259  Eigen::Vector4d predicted_location_feat = _predicted_pose*location_at_birth_eig;
260 
261  _D_T_p0_circle(0,4) = predicted_location_feat[2];
262  _D_T_p0_circle(0,5) = -predicted_location_feat[1];
263  _D_T_p0_circle(1,3) = -predicted_location_feat[2];
264  _D_T_p0_circle(1,5) = predicted_location_feat[0];
265  _D_T_p0_circle(2,3) = predicted_location_feat[1];
266  _D_T_p0_circle(2,4) = -predicted_location_feat[0];
267 
268  G_t.block<6,3>(0, 3*feat_idx) = _D_T_p0_circle.transpose();
269 
270  P_HT_seq = P_minus_seq * _D_T_p0_circle.transpose();
271 
272  S_seq = _D_T_p0_circle * P_HT_seq;
273 
274  S_seq += R_seq;
275 
276  invert3x3MatrixEigen2(S_seq, S_inv_seq );
277 
278  K_seq = P_HT_seq * S_inv_seq;
279 
280  temp_seq1 = K_seq*_D_T_p0_circle;
281 
282  temp_seq2 = temp_seq1 * P_minus_seq;
283 
284  P_minus_seq -= temp_seq2;
285 
286  // copy elements
287  for ( unsigned int i=0; i<P_minus_seq.rows(); i++ )
288  {
289  for ( unsigned int j=0; j<=i; j++ )
290  {
291  P_minus_seq(j,i) = P_minus_seq(i,j);
292  }
293  }
294 
295  feat_idx++;
296  }
297 
298  _pose_covariance = P_minus_seq;
299 
300  Eigen::Matrix<double, 6, 1> pose_update = P_minus_seq * G_t * R_inv_times_innovation;
301 
302  Eigen::Twistd pose_update_ec(pose_update[3], pose_update[4], pose_update[5], pose_update[0], pose_update[1], pose_update[2]);
303  _pose = pose_update_ec.exp(1e-12).toHomogeneousMatrix()*_predicted_pose;
304  }else{
305  ROS_ERROR_STREAM_NAMED("RBFilter::correctState","RB" << this->_id << ": using predicted state as corrected state!");
308  }
309 
310  Eigen::Matrix4d delta_pose = _pose*_trajectory.at(_trajectory.size()-1).inverse();
311 
312  Eigen::Twistd delta_pose_ec;
313  TransformMatrix2Twist(delta_pose, delta_pose_ec);
314  this->_velocity = delta_pose_ec/(_last_time_interval_ns/1e9);
315  this->_trajectory.push_back(this->_pose);
316 }
317 
318 bool isPredictionYBetterThanX(boost::tuple<size_t, double, Eigen::Matrix<double, 6, 6> > X, boost::tuple<size_t, double, Eigen::Matrix<double, 6, 6> > Y)
319 {
320  // If the number of supporting features based on X is smaller than based on Y
321  // then YBetterThanX = true
322  if(boost::tuples::get<0>(X) < boost::tuples::get<0>(Y))
323  {
324  return true;
325  }
326  // If the number of supporting features based on X is larger than based on Y
327  // then YBetterThanX = false
328  else if(boost::tuples::get<0>(X) > boost::tuples::get<0>(Y))
329  {
330  return false;
331  }
332  // If the number of supporting features based on X is the same as based on Y
333  // then we check the accumulated error
334  else{
335  // If the accumulated error based on X is larger than based on Y
336  // then YBetterThanX = true
337  if(boost::tuples::get<1>(X) > boost::tuples::get<1>(Y))
338  {
339  return true;
340  }
341  // If the accumulated error based on X is smaller than based on Y
342  // then YBetterThanX = false
343  else if(boost::tuples::get<1>(X) < boost::tuples::get<1>(Y))
344  {
345  return false;
346  }
347  // If the accumulated error based on X is the same as based on Y
348  // then we check the covariances
349  else
350  {
351  int num_larger_x_covariance = 0;
352  for(int i =0; i<6; i++)
353  {
354  if(boost::tuples::get<2>(X)(i,i) > boost::tuples::get<2>(Y)(i,i))
355  {
356  num_larger_x_covariance +=1;
357  }
358  }
359  if(num_larger_x_covariance > 3)
360  {
361  return true;
362  }
363  else{
364  return false;
365  }
366  }
367  }
368 }
369 
370 //TODO: Decide if I want to test ALL features or only the previously supporting features
371 //NOW: Only supporting features
372 // This function is called when there are new Features added
374 {
375  // 1: Update the list of supporting features to only contain features that are still alive
376  std::vector<Feature::Id> alive_supporting_features_ids;
377  BOOST_FOREACH(Feature::Id supporting_feat_id, this->_supporting_features_ids)
378  {
379  if(this->_features_database->isFeatureStored(supporting_feat_id))
380  {
381  alive_supporting_features_ids.push_back(supporting_feat_id);
382  }
383  }
384  this->_supporting_features_ids.swap(alive_supporting_features_ids);
385 
386  std::vector<boost::tuple<size_t, double, Eigen::Matrix<double, 6, 6> > > num_supporting_feats_and_error_and_pose_cov;
387 
388  // 2: Count the supporting features by comparing the received feature location to the predicted location based on each
389  // hypothesis (velocity based, brake event based, kinematic state based)
390  std::vector<Feature::Id> supporting_feats_based_on_vh;
391  std::vector<Feature::Id> supporting_feats_based_on_bh;
392  std::vector<Feature::Id> supporting_feats_based_on_kh;
393  double error_vh = 0.0;
394  double error_bh = 0.0;
395  double error_kh = 0.0;
396  double acc_error_vh = 0.0;
397  double acc_error_bh = 0.0;
398  double acc_error_kh = 0.0;
399  BOOST_FOREACH(Feature::Id supporting_feat_id, this->_supporting_features_ids)
400  {
401  Feature::Location last_location = this->_features_database->getFeatureLastLocation(supporting_feat_id);
402 
403  Feature::Location predicted_location_vh = this->_predicted_measurement_map_vh[supporting_feat_id];
404  error_vh = L2Distance(last_location, predicted_location_vh);
405  if (error_vh < this->_estimation_error_threshold)
406  {
407  supporting_feats_based_on_vh.push_back(supporting_feat_id);
408  acc_error_vh += error_vh;
409  }
410 
411  Feature::Location predicted_location_bh = this->_predicted_measurement_map_bh[supporting_feat_id];
412  error_bh = L2Distance(last_location, predicted_location_bh);
413  if (error_bh < this->_estimation_error_threshold)
414  {
415  supporting_feats_based_on_bh.push_back(supporting_feat_id);
416  acc_error_bh += error_bh;
417  }
418 
419  // If we had a predicted state from kinematics that we used to predict measurements
421  {
422  Feature::Location predicted_location_kh = this->_predicted_measurement_map_kh[supporting_feat_id];
423  error_kh = L2Distance(last_location, predicted_location_kh);
424  if (error_kh < this->_estimation_error_threshold)
425  {
426  supporting_feats_based_on_kh.push_back(supporting_feat_id);
427  acc_error_kh += error_kh;
428  }
429  }
430  }
431 
432  num_supporting_feats_and_error_and_pose_cov.push_back(boost::tuple<size_t, double, Eigen::Matrix<double, 6, 6> >(supporting_feats_based_on_vh.size(), acc_error_vh, _predicted_pose_cov_vh));
433  num_supporting_feats_and_error_and_pose_cov.push_back(boost::tuple<size_t, double, Eigen::Matrix<double, 6, 6> >(supporting_feats_based_on_bh.size(), acc_error_bh, _predicted_pose_cov_bh));
434 
435  // If we had a predicted state from kinematics that we used to predict measurements
437  {
438  num_supporting_feats_and_error_and_pose_cov.push_back(boost::tuple<size_t, double, Eigen::Matrix<double, 6, 6> >(supporting_feats_based_on_kh.size(), acc_error_kh, _predicted_pose_cov_kh));
440  }
441  // Find the best hypothesis based on the number of supporting features and the accumulated error of them
442  // The criteria to select the best hypothesis is in the function ComparePredictions
443  std::vector<boost::tuple<size_t, double, Eigen::Matrix<double, 6, 6> > >::iterator hyp_with_max_support_it =
444  std::max_element(num_supporting_feats_and_error_and_pose_cov.begin(),
445  num_supporting_feats_and_error_and_pose_cov.end(),
447  int hyp_with_max_support_idx = std::distance(num_supporting_feats_and_error_and_pose_cov.begin(), hyp_with_max_support_it);
448 
449  switch(hyp_with_max_support_idx)
450  {
451 
452  case 0:
453  {
454  std::cout << "RB" << _id<<" Using velocity prediction" << std::endl;
457  this->_supporting_features_ids = supporting_feats_based_on_vh;
460  break;
461  }
462 
463  case 1:
464  {
465  std::cout << "RB" << _id<<" Using brake prediction" << std::endl;
468  this->_supporting_features_ids = supporting_feats_based_on_bh;
471  break;
472  }
473 
474  case 2:
475  {
476  ROS_ERROR_STREAM_NAMED("RBFilter.estimateBestPredictionAndSupportingFeatures",
477  "RB" << _id << " Using prediction from higher level!");
480  this->_supporting_features_ids = supporting_feats_based_on_kh;
483  break;
484  }
485  default:
486  break;
487  }
488 }
489 
491 {
492  this->_supporting_features_ids.push_back(supporting_feat_id);
493 }
494 
495 void RBFilter::setPredictedState(const omip_msgs::RigidBodyPoseAndVelMsg hypothesis)
496 {
497  this->_use_predicted_state_from_kh = true;
498 
499  Eigen::Twistd predicted_pose_kh_ec(hypothesis.pose_wc.twist.angular.x,
500  hypothesis.pose_wc.twist.angular.y,
501  hypothesis.pose_wc.twist.angular.z,
502  hypothesis.pose_wc.twist.linear.x,
503  hypothesis.pose_wc.twist.linear.y,
504  hypothesis.pose_wc.twist.linear.z);
505  this->_predicted_pose_kh = predicted_pose_kh_ec.exp(1e-12).toHomogeneousMatrix();
506 
507  this->_predicted_velocity_kh = Eigen::Twistd(hypothesis.velocity_wc.twist.angular.x,
508  hypothesis.velocity_wc.twist.angular.y,
509  hypothesis.velocity_wc.twist.angular.z,
510  hypothesis.velocity_wc.twist.linear.x,
511  hypothesis.velocity_wc.twist.linear.y,
512  hypothesis.velocity_wc.twist.linear.z);
513  for(int i =0; i<6; i++)
514  {
515  for(int j=0; j<6; j++)
516  {
517  this->_predicted_pose_cov_kh(i,j) = hypothesis.pose_wc.covariance[6*i + j];
518  this->_predicted_velocity_cov_kh(i,j) = hypothesis.velocity_wc.covariance[6*i + j];
519  }
520  }
521 }
522 
523 void RBFilter::integrateShapeBasedPose(const geometry_msgs::TwistWithCovariance twist_refinement, double pose_time_elapsed_ns)
524 {
525  Eigen::Twistd shape_based_pose_ec = Eigen::Twistd(twist_refinement.twist.angular.x, twist_refinement.twist.angular.y, twist_refinement.twist.angular.z,
526  twist_refinement.twist.linear.x, twist_refinement.twist.linear.y, twist_refinement.twist.linear.z);
527 
528  if(pose_time_elapsed_ns < this->_loop_period_ns || _supporting_features_ids.size() < _min_num_supporting_feats_to_correct)
529  {
530  ROS_INFO_STREAM_NAMED("RBFilter.integrateShapeBasedPose", "Using shape-based pose (time elapsed=" << pose_time_elapsed_ns/1e9 <<
531  " s, loop_period="<< _loop_period_ns/1e9 << " s)");
532  //ROS_INFO_STREAM_NAMED("RBFilter.integrateShapeBasedPose", "Pose before: " << std::endl << this->_pose);
533 
534  this->_pose = shape_based_pose_ec.exp(1e-12).toHomogeneousMatrix();
535  //ROS_INFO_STREAM_NAMED("RBFilter.integrateShapeBasedPose", "Pose after: " << std::endl << this->_pose);
536 
537  this->_trajectory.pop_back();
538  this->_trajectory.push_back(this->_pose);
539 
540  Eigen::Matrix4d delta_pose_ht = this->_trajectory[this->_trajectory.size()-1]*(this->_trajectory[this->_trajectory.size()-2].inverse());
541  Eigen::Twistd delta_pose_ec;
542  TransformMatrix2Twist(delta_pose_ht, delta_pose_ec);
543  this->_velocity = delta_pose_ec/(this->_loop_period_ns/1e9);
544  }else{
545  ROS_INFO_STREAM_NAMED("RBFilter.integrateShapeBasedPose", "Shape-based pose is too old (time elapsed=" << pose_time_elapsed_ns/1e9 <<
546  " s, loop_period="<< _loop_period_ns/1e9 << " s). Try reducing the framerate");
547  }
548 }
549 
550 void RBFilter::addPredictedFeatureLocation(const Feature::Location& predicted_location_velocity,const Feature::Location& predicted_location_brake , const Feature::Id feature_id)
551 {
552  FeaturePCLwc predicted_feature_pcl;
553 
554  LocationAndId2FeaturePCLwc(predicted_location_velocity, feature_id, predicted_feature_pcl);
555  this->_predicted_measurement->points.push_back(predicted_feature_pcl);
556  this->_predicted_measurement_map[feature_id] = predicted_location_velocity;
557 
558  this->_predicted_measurement_pc_vh->points.push_back(predicted_feature_pcl);
559  this->_predicted_measurement_map_vh[feature_id] = predicted_location_velocity;
560 
561  this->_predicted_measurement_pc_kh->points.push_back(predicted_feature_pcl);
562  this->_predicted_measurement_map_kh[feature_id] = predicted_location_brake;
563 
564  LocationAndId2FeaturePCLwc(predicted_location_brake, feature_id, predicted_feature_pcl);
565  this->_predicted_measurement_pc_bh->points.push_back(predicted_feature_pcl);
566  this->_predicted_measurement_map_bh[feature_id] = predicted_location_brake;
567 }
568 
570 {
571  this->_features_database = feats_database;
572 }
573 
575  const Eigen::Matrix4d& predicted_pose,
576  bool contemporary_last_feat_loc_and_last_pose_in_trajectory,
577  Feature::Location& predicted_location,
578  bool publish_locations) const
579 {
580  Feature::Location location_at_birth_of_rb;
581  this->GetLocationOfFeatureAtBirthOfRB(feature, contemporary_last_feat_loc_and_last_pose_in_trajectory, location_at_birth_of_rb);
582 
583 
584  TransformLocation(location_at_birth_of_rb, predicted_pose, predicted_location);
585 
586  if(publish_locations)
587  {
588  if(this->_id != 0)
589  {
590  Feature::Location at_birth_location = location_at_birth_of_rb + _initial_location_of_centroid;
591  boost::shared_ptr<FeaturePCLwc> at_birth_feat(new FeaturePCLwc());
592  at_birth_feat->x = boost::tuples::get<0>(at_birth_location);
593  at_birth_feat->y = boost::tuples::get<1>(at_birth_location);
594  at_birth_feat->z = boost::tuples::get<2>(at_birth_location);
595  at_birth_feat->label = feature->getId();
596 
597  _features_at_birth->points.push_back(*at_birth_feat);
598  }else{
599  boost::shared_ptr<FeaturePCLwc> at_birth_feat(new FeaturePCLwc());
600  at_birth_feat->x = boost::tuples::get<0>(location_at_birth_of_rb);
601  at_birth_feat->y = boost::tuples::get<1>(location_at_birth_of_rb);
602  at_birth_feat->z = boost::tuples::get<2>(location_at_birth_of_rb);
603  at_birth_feat->label = feature->getId();
604 
605  _features_at_birth->points.push_back(*at_birth_feat);
606  }
607  boost::shared_ptr<FeaturePCLwc> predicted_feat(new FeaturePCLwc());
608  predicted_feat->x = boost::tuples::get<0>(predicted_location);
609  predicted_feat->y = boost::tuples::get<1>(predicted_location);
610  predicted_feat->z = boost::tuples::get<2>(predicted_location);
611  predicted_feat->label = feature->getId();
612  _features_predicted->points.push_back(*predicted_feat);
613  }
614 }
615 
617  bool contemporary_last_feat_loc_and_last_pose_in_trajectory,
618  Feature::Location& location_at_birth) const
619 {
620  const Feature::Trajectory& feat_traj = feature->getTrajectory();
621 
622  // Feature age counts the last step (this)
623  size_t feature_age = feature->getFeatureAge();
624  size_t rigid_body_age = this->_trajectory.size();
625 
626  // If the last feature location and the last pose are not contemporary (because we are at the beginning of a loop and we have added the new
627  // feature locations to the database but we do not added a new trajectory because that only happens after the correction step), then we add
628  // one to the rigid_body_age
629  if(!contemporary_last_feat_loc_and_last_pose_in_trajectory)
630  {
631  rigid_body_age += 1;
632  }
633 
634  // Feature is younger than RB -> Two options:
635  // - Estimate the motion between feat birthday and current frame as the transformation between RB's birthday
636  // and current "minus" the transformation between RB's birthday and feat's birthday
637  // - Move the initial location of the feature to the RB's birthday using the inverse of the transform between
638  // RB's birthday and feat's birthday. Then move this location to current
639  // Using second option
640  if (feature_age < rigid_body_age + 1)
641  {
642  Eigen::Matrix4d transform_from_rb_birth_to_feat_birth = this->_trajectory.at(rigid_body_age - feature_age);
643 
644  // This moves the feature from its initial location to where it would be when the rb was born
645  Eigen::Matrix4d inverse_transform_from_rb_birth_to_feat_birth = transform_from_rb_birth_to_feat_birth.inverse();
646  TransformLocation(feat_traj.at(0), inverse_transform_from_rb_birth_to_feat_birth, location_at_birth);
647  }
648  else
649  {
650  location_at_birth = feat_traj.at(feature_age - (rigid_body_age + 1));
651  if(this->_id != 0)
652  {
653  location_at_birth = location_at_birth - _initial_location_of_centroid;
654  }
655  }
656 
657 
658 }
659 
661 {
662  return this->_id;
663 }
664 
665 Eigen::Matrix4d RBFilter::getPose() const
666 {
667  return _pose;
668 }
669 
670 Eigen::Matrix<double, 6, 6> RBFilter::getPoseCovariance() const
671 {
672  return _pose_covariance;
673 }
674 
675 Eigen::Twistd RBFilter::getVelocity() const
676 {
677  return _velocity;
678 }
679 
680 Eigen::Matrix<double, 6, 6> RBFilter::getVelocityCovariance() const
681 {
682  return _velocity_covariance;
683 }
684 
685 geometry_msgs::PoseWithCovariancePtr RBFilter::getPoseWithCovariance() const
686 {
687  geometry_msgs::PoseWithCovariancePtr pose_wc_ptr = geometry_msgs::PoseWithCovariancePtr(new geometry_msgs::PoseWithCovariance());
688  pose_wc_ptr->pose.position.x = _pose(0,3);
689  pose_wc_ptr->pose.position.y = _pose(1,3);
690  pose_wc_ptr->pose.position.z = _pose(2,3);
691  Eigen::Quaterniond quaternion(_pose.block<3,3>(0,0));
692  pose_wc_ptr->pose.orientation.x = quaternion.x();
693  pose_wc_ptr->pose.orientation.y = quaternion.y();
694  pose_wc_ptr->pose.orientation.z = quaternion.z();
695  pose_wc_ptr->pose.orientation.w = quaternion.w();
696 
697  for (unsigned int i = 0; i < 6; i++)
698  for (unsigned int j = 0; j < 6; j++)
699  pose_wc_ptr->covariance[6 * i + j] = _pose_covariance(i, j);
700 
701  return pose_wc_ptr;
702 }
703 
704 geometry_msgs::TwistWithCovariancePtr RBFilter::getPoseECWithCovariance() const
705 {
706  geometry_msgs::TwistWithCovariancePtr pose_wc_ptr = geometry_msgs::TwistWithCovariancePtr(new geometry_msgs::TwistWithCovariance());
707  Eigen::Twistd pose_ec;
708  TransformMatrix2Twist(_pose, pose_ec);
709 
710  pose_wc_ptr->twist.linear.x = pose_ec.vx();
711  pose_wc_ptr->twist.linear.y = pose_ec.vy();
712  pose_wc_ptr->twist.linear.z = pose_ec.vz();
713  pose_wc_ptr->twist.angular.x = pose_ec.rx();
714  pose_wc_ptr->twist.angular.y = pose_ec.ry();
715  pose_wc_ptr->twist.angular.z = pose_ec.rz();
716 
717  for (unsigned int i = 0; i < 6; i++)
718  for (unsigned int j = 0; j < 6; j++)
719  pose_wc_ptr->covariance[6 * i + j] = _pose_covariance(i, j);
720 
721  return pose_wc_ptr;
722 }
723 
724 geometry_msgs::TwistWithCovariancePtr RBFilter::getVelocityWithCovariance() const
725 {
726  // Error in the library. I cannot assign to rx, ry and rz if the function is const
727  Eigen::Twistd velocity_copy = _velocity;
728  geometry_msgs::TwistWithCovariancePtr vel_t_wc_ptr = geometry_msgs::TwistWithCovariancePtr(new geometry_msgs::TwistWithCovariance());
729  vel_t_wc_ptr->twist.linear.x = _velocity.vx();
730  vel_t_wc_ptr->twist.linear.y = _velocity.vy();
731  vel_t_wc_ptr->twist.linear.z = _velocity.vz();
732  vel_t_wc_ptr->twist.angular.x = velocity_copy.rx();
733  vel_t_wc_ptr->twist.angular.y = velocity_copy.ry();
734  vel_t_wc_ptr->twist.angular.z = velocity_copy.rz();
735 
736  for (unsigned int i = 0; i < 6; i++)
737  for (unsigned int j = 0; j < 6; j++)
738  vel_t_wc_ptr->covariance[6 * i + j] = _velocity_covariance(i, j);
739 
740  return vel_t_wc_ptr;
741 }
742 
743 std::vector<Eigen::Matrix4d> RBFilter::getTrajectory() const
744 {
745  return this->_trajectory;
746 }
747 
749 {
750  FeatureCloudPCLwc predicted_measurement;
751  switch(hypothesis)
752  {
753  case BASED_ON_VELOCITY:
754  predicted_measurement = *(this->_predicted_measurement_pc_vh);
755  break;
757  predicted_measurement = *(this->_predicted_measurement_pc_bh);
758  break;
759  default:
760  ROS_ERROR_STREAM_NAMED("RBFilter::getPredictedMeasurement", "Wrong hypothesis. Value " << hypothesis);
761  break;
762  }
763  return predicted_measurement;
764 }
765 
766 std::vector<Feature::Id> RBFilter::getSupportingFeatures() const
767 {
768  return this->_supporting_features_ids;
769 }
770 
772 {
773  return (int)this->_supporting_features_ids.size();
774 }
775 
777 {
778  return this->_features_database;
779 }
780 
782 {
783  _pose_covariance = Eigen::Matrix<double, 6, 6>::Zero();
784  _velocity_covariance = Eigen::Matrix<double, 6, 6>::Zero();
785  for (int i = 0; i < 6; i++)
786  {
787  _pose_covariance(i, i) = this->_prior_cov_pose;
788  _velocity_covariance(i, i) = this->_prior_cov_vel;
789  }
790 
791  this->_predicted_measurement_pc_vh = FeatureCloudPCLwc::Ptr(new FeatureCloudPCLwc());
792  this->_predicted_measurement_pc_bh = FeatureCloudPCLwc::Ptr(new FeatureCloudPCLwc());
793  this->_predicted_measurement_pc_kh = FeatureCloudPCLwc::Ptr(new FeatureCloudPCLwc());
794  this->_features_at_birth= FeatureCloudPCLwc::Ptr(new FeatureCloudPCLwc());
795  this->_features_predicted = FeatureCloudPCLwc::Ptr(new FeatureCloudPCLwc());
796  this->_predicted_pose_vh = Eigen::Matrix4d::Identity();
797  this->_predicted_pose_bh = Eigen::Matrix4d::Identity();
798  this->_predicted_pose_kh = Eigen::Matrix4d::Identity();
799 
800  _G_t_memory = Eigen::MatrixXd(6, 3*_num_tracked_feats);
802 
803  _D_T_p0_circle = Eigen::Matrix<double, 3, 6>::Zero();
804  _D_T_p0_circle.block<3,3>(0,0) = Eigen::Matrix3d::Identity();
805  _D_T_p0_circle.block<3,3>(0,3) = Eigen::Matrix3d::Zero();
806 }
double _loop_period_ns
Definition: RBFilter.h:536
FeatureCloudPCLwc::Ptr _predicted_measurement_pc_bh
Definition: RBFilter.h:525
virtual void setPredictedState(omip_msgs::RigidBodyPoseAndVelMsg hypothesis)
Definition: RBFilter.cpp:495
virtual void estimateBestPredictionAndSupportingFeatures()
Definition: RBFilter.cpp:373
std::map< Feature::Id, Feature::Location > _predicted_measurement_map_vh
Definition: RBFilter.h:530
boost::tuple< double, double, double > Location
FeatureCloudPCLwc::Ptr _predicted_measurement
Definition: RBFilter.h:528
double _last_time_interval_ns
Definition: RBFilter.h:537
virtual std::vector< Feature::Id > getSupportingFeatures() const
Definition: RBFilter.cpp:766
virtual std::vector< Eigen::Matrix4d > getTrajectory() const
Definition: RBFilter.cpp:743
virtual void addSupportingFeature(Feature::Id supporting_feat_id)
Definition: RBFilter.cpp:490
virtual Eigen::Matrix< double, 6, 6 > getPoseCovariance() const
Definition: RBFilter.cpp:670
#define ROS_ERROR_STREAM_NAMED(name, args)
virtual geometry_msgs::PoseWithCovariancePtr getPoseWithCovariance() const
Definition: RBFilter.cpp:685
virtual void setFeaturesDatabase(FeaturesDataBase::Ptr feats_database)
Definition: RBFilter.cpp:569
virtual FeatureCloudPCLwc getPredictedMeasurement(PredictionHypothesis hypothesis=BASED_ON_VELOCITY)
Definition: RBFilter.cpp:748
FeatureCloudPCLwc::Ptr _predicted_measurement_pc_vh
Definition: RBFilter.h:524
virtual void correctState()
Definition: RBFilter.cpp:191
double _cov_sys_acc_tz
Definition: RBFilter.h:463
double _cov_sys_acc_tx
Definition: RBFilter.h:461
bool _use_predicted_state_from_kh
Definition: RBFilter.h:518
virtual geometry_msgs::TwistWithCovariancePtr getPoseECWithCovariance() const
Definition: RBFilter.cpp:704
double L2Distance(const Feature::Location &first, const Feature::Location &second)
std::map< Feature::Id, Feature::Location > _predicted_measurement_map
Definition: RBFilter.h:534
double _min_cov_meas_x
Definition: RBFilter.h:457
void TransformMatrix2Twist(const Eigen::Matrix4d &transformation_matrix, Eigen::Twistd &twist)
Eigen::Matrix4d _predicted_pose
Definition: RBFilter.h:485
Eigen::VectorXd _R_inv_times_innovation_memory
Definition: RBFilter.h:470
Eigen::Matrix< double, 6, 6 > _predicted_velocity_cov_kh
Definition: RBFilter.h:516
#define ROS_INFO_STREAM_NAMED(name, args)
FeatureCloudPCLwc::Ptr _predicted_measurement_pc_kh
Definition: RBFilter.h:526
virtual Eigen::Matrix4d getPose() const
Definition: RBFilter.cpp:665
RB_id_t _id
Definition: RBFilter.h:476
long int RB_id_t
FeatureCloudPCLwc::Ptr _features_at_birth
Definition: RBFilter.h:522
Feature::Location _initial_location_of_centroid
Definition: RBFilter.h:491
int _num_tracked_feats
Definition: RBFilter.h:544
Eigen::Twistd _predicted_velocity_bh
Definition: RBFilter.h:511
virtual void integrateShapeBasedPose(const geometry_msgs::TwistWithCovariance twist_refinement, double pose_time_elapsed_ns)
Definition: RBFilter.cpp:523
static RB_id_t _rb_id_generator
Definition: RBFilter.h:474
std::map< Feature::Id, Feature::Location > _predicted_measurement_map_bh
Definition: RBFilter.h:531
double _cov_sys_acc_rz
Definition: RBFilter.h:466
virtual void _initializeAuxiliarMatrices()
Definition: RBFilter.cpp:781
Eigen::Matrix4d _pose
Definition: RBFilter.h:479
FeatureCloudPCLwc::Ptr _features_predicted
Definition: RBFilter.h:521
std::vector< Feature::Id > _supporting_features_ids
Definition: RBFilter.h:495
TFSIMD_FORCE_INLINE Quaternion inverse(const Quaternion &q)
Eigen::Matrix< double, 3, 6 > _D_T_p0_circle
Definition: RBFilter.h:472
void invert3x3MatrixEigen2(const Eigen::Matrix3d &to_inv, Eigen::Matrix3d &inverse)
virtual void GetLocationOfFeatureAtBirthOfRB(Feature::Ptr feature, bool contemporary_last_feat_loc_and_last_pose_in_trajectory, Feature::Location &location_at_birth) const
Get the location of the feature at the frame when the RB was detected first. If the feature is "young...
Definition: RBFilter.cpp:616
Eigen::Matrix4d _predicted_pose_kh
Definition: RBFilter.h:504
double _prior_cov_pose
Definition: RBFilter.h:455
bool _use_predicted_measurement_from_kh
Definition: RBFilter.h:519
Eigen::Matrix< double, 6, 6 > _predicted_velocity_cov_bh
Definition: RBFilter.h:515
double _cov_sys_acc_rx
Definition: RBFilter.h:465
std::vector< Location > Trajectory
virtual geometry_msgs::TwistWithCovariancePtr getVelocityWithCovariance() const
Definition: RBFilter.cpp:724
Eigen::Matrix< double, 6, 6 > _predicted_pose_covariance
Definition: RBFilter.h:486
virtual void Init()
Definition: RBFilter.cpp:65
Eigen::Matrix< double, 6, 6 > _pose_covariance
Definition: RBFilter.h:480
Eigen::Twistd _velocity
Definition: RBFilter.h:482
FeaturesDataBase::Ptr _features_database
Definition: RBFilter.h:498
void LocationOfFeature2EigenVectorHomogeneous(const Feature::Location &lof, Eigen::Vector4d &eig_vec)
virtual FeaturesDataBase::Ptr getFeaturesDatabase() const
Definition: RBFilter.cpp:776
virtual Eigen::Matrix< double, 6, 6 > getVelocityCovariance() const
Definition: RBFilter.cpp:680
Eigen::Twistd _predicted_velocity_kh
Definition: RBFilter.h:512
double _estimation_error_threshold
Definition: RBFilter.h:451
Eigen::Matrix< double, 6, 6 > _predicted_pose_cov_bh
Definition: RBFilter.h:507
virtual RB_id_t getId() const
Definition: RBFilter.cpp:660
double _prior_cov_vel
Definition: RBFilter.h:456
double _cov_sys_acc_ry
Definition: RBFilter.h:464
virtual void predictState(double time_interval_ns=-1.)
Definition: RBFilter.cpp:91
int _min_num_supporting_feats_to_correct
Definition: RBFilter.h:545
bool isPredictionYBetterThanX(boost::tuple< size_t, double, Eigen::Matrix< double, 6, 6 > > X, boost::tuple< size_t, double, Eigen::Matrix< double, 6, 6 > > Y)
Definition: RBFilter.cpp:318
double _meas_depth_factor
Definition: RBFilter.h:460
std::vector< Eigen::Matrix4d > _trajectory
Definition: RBFilter.h:493
virtual Eigen::Twistd getVelocity() const
Definition: RBFilter.cpp:675
pcl::PointCloud< FeaturePCLwc > FeatureCloudPCLwc
void TransformLocation(const Feature::Location &origin, const Eigen::Matrix4d &transformation, Feature::Location &new_location)
double _cov_sys_acc_ty
Definition: RBFilter.h:462
void LocationAndId2FeaturePCLwc(const Feature::Location &feature_location, const Feature::Id &feature_id, omip::FeaturePCLwc &feature_pcl)
Eigen::Matrix4d _predicted_pose_bh
Definition: RBFilter.h:502
virtual int getNumberSupportingFeatures() const
Definition: RBFilter.cpp:771
std::map< Feature::Id, Feature::Location > _predicted_measurement_map_kh
Definition: RBFilter.h:532
double _min_cov_meas_z
Definition: RBFilter.h:459
virtual void addPredictedFeatureLocation(const Feature::Location &predicted_location_velocity, const Feature::Location &predicted_location_brake, const Feature::Id feature_id)
Definition: RBFilter.cpp:550
virtual ~RBFilter()
Definition: RBFilter.cpp:87
Eigen::Matrix4d _predicted_pose_vh
Definition: RBFilter.h:501
Eigen::MatrixXd _G_t_memory
Definition: RBFilter.h:469
Eigen::Matrix< double, 6, 6 > _predicted_pose_cov_kh
Definition: RBFilter.h:508
Eigen::Matrix< double, 6, 6 > _velocity_covariance
Definition: RBFilter.h:483
double _min_cov_meas_y
Definition: RBFilter.h:458
virtual void predictMeasurement()
Second step when updating the filter. The next measurement is predicted from the predicted next state...
Definition: RBFilter.cpp:142
virtual void PredictFeatureLocation(Feature::Ptr feature, const Eigen::Matrix4d &predicted_pose, bool contemporary_last_feat_loc_and_last_pose_in_trajectory, Feature::Location &predicted_location, bool publish_locations=false) const
Definition: RBFilter.cpp:574
Eigen::Matrix< double, 6, 6 > _predicted_pose_cov_vh
Definition: RBFilter.h:506


rb_tracker
Author(s): Roberto Martín-Martín
autogenerated on Mon Jun 10 2019 14:06:11