MultiJointTracker.cpp
Go to the documentation of this file.
1 #include <boost/foreach.hpp>
2 
4 
5 #include <geometry_msgs/Vector3.h>
6 
7 #include <cmath>
8 
9 #include <wrappers/matrix/matrix_wrapper.h>
10 
11 #include "omip_msgs/RigidBodyTwistWithCovMsg.h"
12 #include "omip_common/OMIPUtils.h"
13 
14 using namespace omip;
15 using namespace MatrixWrapper;
16 using namespace BFL;
17 
18 MultiJointTracker::MultiJointTracker(double loop_period_ns, ks_analysis_t ks_analysis_type, double dj_ne) :
19  RecursiveEstimatorFilterInterface(loop_period_ns),
20  _ks_analysis_type(ks_analysis_type),
21  _disconnected_j_ne(dj_ne),
22  _likelihood_sample_num(0),
23  _sigma_delta_meas_uncertainty_linear(0),
24  _sigma_delta_meas_uncertainty_angular(0)
25 {
26  this->_filter_name = "KSFilter";
27 }
28 
30 {
31 
32 }
33 
34 void MultiJointTracker::predictState(double time_interval_ns)
35 {
36  BOOST_FOREACH(joint_combined_filters_map::value_type joint_combined_filter_it, this->_joint_combined_filters)
37  {
38  joint_combined_filter_it.second->predictState(time_interval_ns);
39  }
40 }
41 
43 {
44  // We query the predictions from each joint
45  // In order to propagate a prediction to the lower level, it must fulfill:
46  // 1) It is not a prediction from a disconnected joint (we could remove this condition, it would be ignored at the lower level)
47  // 2) There should be only one prediction for a rigid body. The prediction with highest likelihood gets propagated
48  this->_predicted_measurement.rb_poses_and_vels.clear();
49  omip_msgs::RigidBodyPoseAndVelMsg pose_and_vel_one_rb;
50  RB_id_t rbid_predicted;
51 
52  std::map<int, double> rbid_predicted_and_likelihood;
53  std::map<int, omip_msgs::RigidBodyPoseAndVelMsg> rbid_predicted_and_predictions;
54  BOOST_FOREACH(joint_combined_filters_map::value_type joint_combined_filter_it, this->_joint_combined_filters)
55  {
56  joint_combined_filter_it.second->predictMeasurement();
57  rbid_predicted = joint_combined_filter_it.first.second;
58  JointFilterPtr most_probable_joint_hypothesis = joint_combined_filter_it.second->getMostProbableJointFilter();
59 
60  // The prediction is useful only if the bodies are not disconnected
61  // Only one prediction per RB
62  if(most_probable_joint_hypothesis->getJointFilterType() != DISCONNECTED_JOINT)
63  {
64  std::map<int, double>::iterator previous_prediction_it = rbid_predicted_and_likelihood.find(rbid_predicted);
65  // If we already have a prediction for this (second) rigid body, we check which of the two generating models has higher probability
66  if(previous_prediction_it != rbid_predicted_and_likelihood.end())
67  {
68  // If the new prediction comes from a model that is more likely, we take this prediction
69  if(previous_prediction_it->second < most_probable_joint_hypothesis->getProbabilityOfJointFilter())
70  {
71  ROS_INFO_STREAM_NAMED("MultiJointTracker.predictMeasurement", "Replacing previous prediction with prediction from "
72  << most_probable_joint_hypothesis->getJointFilterTypeStr());
73  pose_and_vel_one_rb.rb_id = rbid_predicted;
74  pose_and_vel_one_rb.pose_wc = most_probable_joint_hypothesis->getPredictedSRBDeltaPoseWithCovInSensorFrame();
75  pose_and_vel_one_rb.velocity_wc = most_probable_joint_hypothesis->getPredictedSRBVelocityWithCovInSensorFrame();
76  rbid_predicted_and_predictions[rbid_predicted] = pose_and_vel_one_rb;
77  rbid_predicted_and_likelihood[rbid_predicted] = most_probable_joint_hypothesis->getProbabilityOfJointFilter();
78  }
79  }
80  // If we don't have any prediction for this (second) rigid body, we use this prediction
81  else{
82  ROS_INFO_STREAM_NAMED("MultiJointTracker.predictMeasurement", "Use prediction from "
83  << most_probable_joint_hypothesis->getJointFilterTypeStr());
84  pose_and_vel_one_rb.rb_id = rbid_predicted;
85  pose_and_vel_one_rb.pose_wc = most_probable_joint_hypothesis->getPredictedSRBDeltaPoseWithCovInSensorFrame();
86  pose_and_vel_one_rb.velocity_wc = most_probable_joint_hypothesis->getPredictedSRBVelocityWithCovInSensorFrame();
87  rbid_predicted_and_predictions[rbid_predicted] = pose_and_vel_one_rb;
88  rbid_predicted_and_likelihood[rbid_predicted] = most_probable_joint_hypothesis->getProbabilityOfJointFilter();
89  }
90  }
91  }
92 
93  // We collect all the best predictions into the vector of predicted measurements
94  std::map<int, omip_msgs::RigidBodyPoseAndVelMsg>::iterator best_predictions_it = rbid_predicted_and_predictions.begin();
95  std::map<int, omip_msgs::RigidBodyPoseAndVelMsg>::iterator best_predictions_it_end = rbid_predicted_and_predictions.end();
96  for(; best_predictions_it != best_predictions_it_end; best_predictions_it++)
97  {
98  this->_predicted_measurement.rb_poses_and_vels.push_back(best_predictions_it->second);
99  }
100 }
101 
102 void MultiJointTracker::setMeasurement(const ks_measurement_t &poses_and_vels, const double &measurement_timestamp_ns)
103 {
105  this->_measurement_timestamp_ns = measurement_timestamp_ns;
106 
109 
112  {
114  }
115 
116  size_t rrb_idx_begin = 0;
117  size_t rrb_idx_end = 0;
118 
119  switch(this->_ks_analysis_type)
120  {
122  rrb_idx_begin = 0;
123  rrb_idx_end = 1;
124  break;
126  rrb_idx_begin = 1;
127  rrb_idx_end = this->_last_rcvd_poses_and_vels->rb_poses_and_vels.size();
128  break;
129  case FULL_ANALYSIS:
130  rrb_idx_begin = 0;
131  rrb_idx_end = this->_last_rcvd_poses_and_vels->rb_poses_and_vels.size();
132  break;
133  }
134 
135  for (size_t rrb_idx = rrb_idx_begin; rrb_idx < rrb_idx_end; rrb_idx++)
136  {
137  for (size_t srb_idx = rrb_idx + 1; srb_idx < this->_last_rcvd_poses_and_vels->rb_poses_and_vels.size(); srb_idx++)
138  {
139  // Extract RB ids
140  int rrb_id = this->_last_rcvd_poses_and_vels->rb_poses_and_vels.at(rrb_idx).rb_id;
141  int srb_id = this->_last_rcvd_poses_and_vels->rb_poses_and_vels.at(srb_idx).rb_id;
142 
143  std::pair<int, int> rrb_srb_ids = std::pair<int, int>(rrb_id, srb_id);
144 
145  // Check if this pair of rbs were observed before -> joint was estimated before
146  std::map<std::pair<int, int>, JointCombinedFilterPtr>::iterator prev_joint_combined_filter_it =this->_joint_combined_filters.find(rrb_srb_ids);
147 
148  // If this is a new pair of RB not analyzed before
149  if (prev_joint_combined_filter_it != this->_joint_combined_filters.end())
150  { // It was previously stored -> Use it and pass the new measurements
151  prev_joint_combined_filter_it->second->setMeasurement(joint_measurement_t(
152  this->_last_rcvd_poses_and_vels->rb_poses_and_vels.at(rrb_idx),
153  this->_last_rcvd_poses_and_vels->rb_poses_and_vels.at(srb_idx)), measurement_timestamp_ns);
154  }
155  }
156  }
157 }
158 
160 {
161  joint_combined_filters_map::iterator it = this->_joint_combined_filters.begin();
162 
163  for(int k=0; k<n; k++)
164  {
165  it++;
166  }
167  return it->second;
168 }
169 
171 {
172  // I create a new one so that the joints are either created, corrected, or deleted if there is no more information about them
173  joint_combined_filters_map corrected_joint_combined_filters;
174 
175  size_t rrb_idx_begin = 0;
176  size_t rrb_idx_end = 0;
177 
178  switch(this->_ks_analysis_type)
179  {
181  rrb_idx_begin = 0;
182  rrb_idx_end = 1;
183  break;
185  rrb_idx_begin = 1;
186  rrb_idx_end = this->_last_rcvd_poses_and_vels->rb_poses_and_vels.size();
187  break;
188  case FULL_ANALYSIS:
189  rrb_idx_begin = 0;
190  rrb_idx_end = this->_last_rcvd_poses_and_vels->rb_poses_and_vels.size();
191  break;
192  }
193 
194  for (size_t rrb_idx = rrb_idx_begin; rrb_idx < rrb_idx_end; rrb_idx++)
195  {
196  for (size_t srb_idx = rrb_idx + 1; srb_idx < this->_last_rcvd_poses_and_vels->rb_poses_and_vels.size(); srb_idx++)
197  {
198  // Extract RB ids
199  int rrb_id = this->_last_rcvd_poses_and_vels->rb_poses_and_vels.at(rrb_idx).rb_id;
200  int srb_id = this->_last_rcvd_poses_and_vels->rb_poses_and_vels.at(srb_idx).rb_id;
201 
202  std::pair<int, int> rrb_srb_ids = std::pair<int, int>(rrb_id, srb_id);
203 
204  // Check if this pair of rbs were observed before and we already have a joint filter for it
205  std::map<std::pair<int, int>, JointCombinedFilterPtr>::iterator prev_joint_combined_filter_it =this->_joint_combined_filters.find(rrb_srb_ids);
206 
207  // If we don't have a joint filter for it
208  if (prev_joint_combined_filter_it == this->_joint_combined_filters.end())
209  {
210  // If we it is the very first time we see this pair rrb-srb (probably because it is the first frame we track the srb)
211  if (this->_precomputing_counter.find(rrb_srb_ids) == this->_precomputing_counter.end())
212  {
213  // 1)
214  // We create an entry for this pair rrb-srb into our counter and set the counter to zero
215  this->_precomputing_counter[rrb_srb_ids] = 0;
216 
217  // 2)
218  // We store the pose of the reference rigid body at the frame/time step when the new (second) rb was detected
219  // Since we estimate an initial trajectory of length _min_num_frames_for_new_rb we query the pose of the
220  // reference rigid body _min_num_frames_for_new_rb frames before
221  // Actually, we are not sure that the reference rb existed _min_num_frames_for_new_rb before
222  // so we query the oldest in our accumulator
223  Eigen::Twistd rrb_pose_at_srb_birthday_in_sf_twist = Eigen::Twistd(0.,0.,0.,0.,0.,0.);
224  std::list<omip_msgs::RigidBodyPosesAndVelsMsgPtr>::iterator acc_frames_it = this->_n_previous_rcvd_poses_and_vels.begin();
225  std::list<omip_msgs::RigidBodyPosesAndVelsMsgPtr>::iterator acc_frames_end = this->_n_previous_rcvd_poses_and_vels.end();
226 
227  for(; acc_frames_it != acc_frames_end; acc_frames_it++)
228  {
229  for(int rb_prev_idx = 0; rb_prev_idx < (*acc_frames_it)->rb_poses_and_vels.size(); rb_prev_idx++)
230  {
231  // The RRB was existing in the previous frame
232  if((*acc_frames_it)->rb_poses_and_vels.at(rb_prev_idx).rb_id == rrb_id)
233  {
234  ROSTwist2EigenTwist((*acc_frames_it)->rb_poses_and_vels.at(rb_prev_idx).pose_wc.twist, rrb_pose_at_srb_birthday_in_sf_twist);
235  }
236  }
237  }
238  this->_rrb_pose_at_srb_birthday_in_sf[rrb_srb_ids] = rrb_pose_at_srb_birthday_in_sf_twist;
239 
240  // 3)
241  // We store the first pose of the second rigid body
242  // Due to the initial trajectory estimation, the first pose received is actually not really the first pose.
243  // Before, with the OMIP version that does NOT place the body frames at the centroid of the body we could assume that the first pose
244  // of the body wrt the sensor was the identity
245  // Now, with the OMIP version that places the body frames at the centroid of the body that assumption does not hold any longer
246  // SOLUTION: at the first frame/time step we get from the RBTracker in the field centroid of the rigid body the centroid we used for the trajectory estimation
247  // We can use this centroid as initial translation
248  Eigen::Twistd srb_pose_at_srb_birthday_in_sf_twist = Eigen::Twistd(0.,0.,0.,0.,0.,0.);
249  for(int rb_prev_idx = 0; rb_prev_idx < this->_last_rcvd_poses_and_vels->rb_poses_and_vels.size(); rb_prev_idx++)
250  {
251  // The SRB was existing in the previous frame
252  if(this->_last_rcvd_poses_and_vels->rb_poses_and_vels.at(rb_prev_idx).rb_id == srb_id)
253  {
254  srb_pose_at_srb_birthday_in_sf_twist.vx() = this->_last_rcvd_poses_and_vels->rb_poses_and_vels.at(rb_prev_idx).centroid.x;
255  srb_pose_at_srb_birthday_in_sf_twist.vy() = this->_last_rcvd_poses_and_vels->rb_poses_and_vels.at(rb_prev_idx).centroid.y;
256  srb_pose_at_srb_birthday_in_sf_twist.vz() = this->_last_rcvd_poses_and_vels->rb_poses_and_vels.at(rb_prev_idx).centroid.z;
257  }
258  }
259 
260  this->_srb_pose_at_srb_birthday_in_sf[rrb_srb_ids] = srb_pose_at_srb_birthday_in_sf_twist;
261  }
262  else
263  {
264  Eigen::Twistd new_twist;
265  ROSTwist2EigenTwist(this->_last_rcvd_poses_and_vels->rb_poses_and_vels.at(srb_idx).pose_wc.twist, new_twist);
266 
267  // We accumulate _min_joint_age_for_ee iterations (pairs of poses) to initialize the filters with a better estimation
268  if (this->_precomputing_counter[rrb_srb_ids] >= this->_min_joint_age_for_ee)
269  {
270  corrected_joint_combined_filters[rrb_srb_ids] = JointCombinedFilterPtr(new JointCombinedFilter());
271  corrected_joint_combined_filters[rrb_srb_ids]->setLoopPeriodNS(this->_loop_period_ns);
272  corrected_joint_combined_filters[rrb_srb_ids]->setNumSamplesForLikelihoodEstimation(this->_likelihood_sample_num);
273  corrected_joint_combined_filters[rrb_srb_ids]->setCovarianceDeltaMeasurementLinear(this->_sigma_delta_meas_uncertainty_linear);
274  corrected_joint_combined_filters[rrb_srb_ids]->setCovarianceDeltaMeasurementAngular(this->_sigma_delta_meas_uncertainty_angular);
275  corrected_joint_combined_filters[rrb_srb_ids]->setMaxTranslationRigid(this->_rig_max_translation);
276  corrected_joint_combined_filters[rrb_srb_ids]->setMaxRotationRigid(this->_rig_max_rotation);
277  corrected_joint_combined_filters[rrb_srb_ids]->setJointLikelihoodDisconnected(this->_disconnected_j_ne);
278  corrected_joint_combined_filters[rrb_srb_ids]->setCovariancePrior(PRISMATIC_JOINT, this->_prism_prior_cov_vel);
279  corrected_joint_combined_filters[rrb_srb_ids]->setCovarianceAdditiveSystemNoisePhi(PRISMATIC_JOINT, this->_prism_sigma_sys_noise_phi);
280  corrected_joint_combined_filters[rrb_srb_ids]->setCovarianceAdditiveSystemNoiseTheta(PRISMATIC_JOINT, this->_prism_sigma_sys_noise_theta);
281  corrected_joint_combined_filters[rrb_srb_ids]->setCovarianceAdditiveSystemNoiseJointState(PRISMATIC_JOINT, this->_prism_sigma_sys_noise_pv);
282  corrected_joint_combined_filters[rrb_srb_ids]->setCovarianceAdditiveSystemNoiseJointVelocity(PRISMATIC_JOINT, this->_prism_sigma_sys_noise_pvd);
283  corrected_joint_combined_filters[rrb_srb_ids]->setCovarianceMeasurementNoise(PRISMATIC_JOINT, this->_prism_sigma_meas_noise);
284  corrected_joint_combined_filters[rrb_srb_ids]->setCovariancePrior(REVOLUTE_JOINT, this->_rev_prior_cov_vel);
285  corrected_joint_combined_filters[rrb_srb_ids]->setCovarianceAdditiveSystemNoisePhi(REVOLUTE_JOINT, this->_rev_sigma_sys_noise_phi);
286  corrected_joint_combined_filters[rrb_srb_ids]->setCovarianceAdditiveSystemNoiseTheta(REVOLUTE_JOINT, this->_rev_sigma_sys_noise_theta);
287  corrected_joint_combined_filters[rrb_srb_ids]->setCovarianceAdditiveSystemNoiseJointState(REVOLUTE_JOINT, this->_rev_sigma_sys_noise_rv);
288  corrected_joint_combined_filters[rrb_srb_ids]->setCovarianceAdditiveSystemNoiseJointVelocity(REVOLUTE_JOINT, this->_rev_sigma_sys_noise_rvd);
289  corrected_joint_combined_filters[rrb_srb_ids]->setCovarianceAdditiveSystemNoisePx(REVOLUTE_JOINT, this->_rev_sigma_sys_noise_px);
290  corrected_joint_combined_filters[rrb_srb_ids]->setCovarianceAdditiveSystemNoisePy(REVOLUTE_JOINT, this->_rev_sigma_sys_noise_py);
291  corrected_joint_combined_filters[rrb_srb_ids]->setCovarianceAdditiveSystemNoisePz(REVOLUTE_JOINT, this->_rev_sigma_sys_noise_pz);
292  corrected_joint_combined_filters[rrb_srb_ids]->setCovarianceMeasurementNoise(REVOLUTE_JOINT, this->_rev_sigma_meas_noise);
293  corrected_joint_combined_filters[rrb_srb_ids]->setMinRotationRevolute(this->_rev_min_rot_for_ee);
294  corrected_joint_combined_filters[rrb_srb_ids]->setMaxRadiusDistanceRevolute(this->_rev_max_joint_distance_for_ee);
295  corrected_joint_combined_filters[rrb_srb_ids]->setInitialMeasurement(joint_measurement_t(this->_last_rcvd_poses_and_vels->rb_poses_and_vels.at(rrb_idx),
296  this->_last_rcvd_poses_and_vels->rb_poses_and_vels.at(srb_idx)),
297  this->_rrb_pose_at_srb_birthday_in_sf[rrb_srb_ids],
298  this->_srb_pose_at_srb_birthday_in_sf[rrb_srb_ids]);
299  corrected_joint_combined_filters[rrb_srb_ids]->initialize();
300  }
301  else
302  {
303  this->_precomputing_counter[rrb_srb_ids] += 1;
304  }
305  }
306  }else{
307  prev_joint_combined_filter_it->second->correctState();
308  corrected_joint_combined_filters[rrb_srb_ids] = prev_joint_combined_filter_it->second;
309  }
310 
311  }
312  }
313 
314  this->_joint_combined_filters = corrected_joint_combined_filters;
315  this->_reflectState();
316 }
317 
319 {
320  this->_state.clear();
321  this->_state = this->_joint_combined_filters;
322 }
323 
325 {
326  BOOST_FOREACH(joint_combined_filters_map::value_type joint_combined_filter_it, this->_joint_combined_filters)
327  {
328  joint_combined_filter_it.second->estimateJointFilterProbabilities();
329  }
330 }
331 
std::pair< omip_msgs::RigidBodyPoseAndVelMsg, omip_msgs::RigidBodyPoseAndVelMsg > joint_measurement_t
omip_msgs::RigidBodyPosesAndVelsMsg ks_measurement_t
MultiJointTracker(double loop_period_ns, ks_analysis_t ks_analysis_type, double dj_ne)
omip_msgs::RigidBodyPosesAndVelsMsgPtr _last_rcvd_poses_and_vels
virtual JointCombinedFilterPtr getCombinedFilter(int n)
virtual void estimateJointFiltersProbabilities()
joint_combined_filters_map _joint_combined_filters
#define ROS_INFO_STREAM_NAMED(name, args)
long int RB_id_t
omip_msgs::RigidBodyPosesAndVelsMsgPtr _previous_rcvd_poses_and_vels
std::map< std::pair< int, int >, Eigen::Twistd > _srb_pose_at_srb_birthday_in_sf
virtual void predictState(double time_interval_ns)
First step when updating the filter. The next state is predicted from current state and system model...
virtual void _reflectState()
Prepares the state variable to be returned (getState is constant and we cannot change the state there...
boost::shared_ptr< JointCombinedFilter > JointCombinedFilterPtr
virtual void setMeasurement(const ks_measurement_t &poses_and_vels, const double &measurement_timestamp_ns)
void ROSTwist2EigenTwist(const geometry_msgs::Twist &ros_twist, Eigen::Twistd &eigen_twist)
virtual void predictMeasurement()
Second step when updating the filter. The next measurement is predicted from the predicted next state...
std::list< omip_msgs::RigidBodyPosesAndVelsMsgPtr > _n_previous_rcvd_poses_and_vels
virtual void correctState()
Third and final step when updating the filter. The predicted next state is corrected based on the dif...
std::map< std::pair< int, int >, int > _precomputing_counter
std::map< std::pair< int, int >, JointCombinedFilterPtr > joint_combined_filters_map
std::map< std::pair< int, int >, Eigen::Twistd > _rrb_pose_at_srb_birthday_in_sf


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