MultiJointTracker.cpp
Go to the documentation of this file.
00001 #include <boost/foreach.hpp>
00002 
00003 #include "joint_tracker/MultiJointTracker.h"
00004 
00005 #include <geometry_msgs/Vector3.h>
00006 
00007 #include <cmath>
00008 
00009 #include <wrappers/matrix/matrix_wrapper.h>
00010 
00011 #include "omip_msgs/RigidBodyTwistWithCovMsg.h"
00012 #include "omip_common/OMIPUtils.h"
00013 
00014 using namespace omip;
00015 using namespace MatrixWrapper;
00016 using namespace BFL;
00017 
00018 MultiJointTracker::MultiJointTracker(double loop_period_ns, ks_analysis_t ks_analysis_type, double dj_ne) :
00019     RecursiveEstimatorFilterInterface(loop_period_ns),
00020     _ks_analysis_type(ks_analysis_type),
00021     _disconnected_j_ne(dj_ne),
00022     _likelihood_sample_num(0),
00023     _sigma_delta_meas_uncertainty_linear(0),
00024     _sigma_delta_meas_uncertainty_angular(0)
00025 {
00026     this->_filter_name = "KSFilter";
00027 }
00028 
00029 MultiJointTracker::~MultiJointTracker()
00030 {
00031 
00032 }
00033 
00034 void MultiJointTracker::predictState(double time_interval_ns)
00035 {
00036     BOOST_FOREACH(joint_combined_filters_map::value_type joint_combined_filter_it, this->_joint_combined_filters)
00037     {
00038         joint_combined_filter_it.second->predictState(time_interval_ns);
00039     }
00040 }
00041 
00042 void MultiJointTracker::predictMeasurement()
00043 {
00044     // We query the predictions from each joint
00045     // In order to propagate a prediction to the lower level, it must fulfill:
00046     //  1) It is not a prediction from a disconnected joint (we could remove this condition, it would be ignored at the lower level)
00047     //  2) There should be only one prediction for a rigid body. The prediction with highest likelihood gets propagated
00048     this->_predicted_measurement.rb_poses_and_vels.clear();
00049     omip_msgs::RigidBodyPoseAndVelMsg pose_and_vel_one_rb;
00050     RB_id_t rbid_predicted;
00051 
00052     std::map<int, double> rbid_predicted_and_likelihood;
00053     std::map<int, omip_msgs::RigidBodyPoseAndVelMsg> rbid_predicted_and_predictions;
00054     BOOST_FOREACH(joint_combined_filters_map::value_type joint_combined_filter_it, this->_joint_combined_filters)
00055     {
00056         joint_combined_filter_it.second->predictMeasurement();
00057         rbid_predicted = joint_combined_filter_it.first.second;
00058         JointFilterPtr most_probable_joint_hypothesis = joint_combined_filter_it.second->getMostProbableJointFilter();
00059 
00060         // The prediction is useful only if the bodies are not disconnected
00061         // Only one prediction per RB
00062         if(most_probable_joint_hypothesis->getJointFilterType() != DISCONNECTED_JOINT)
00063         {
00064             std::map<int, double>::iterator previous_prediction_it = rbid_predicted_and_likelihood.find(rbid_predicted);
00065             // If we already have a prediction for this (second) rigid body, we check which of the two generating models has higher probability
00066             if(previous_prediction_it != rbid_predicted_and_likelihood.end())
00067             {
00068                 // If the new prediction comes from a model that is more likely, we take this prediction
00069                 if(previous_prediction_it->second < most_probable_joint_hypothesis->getProbabilityOfJointFilter())
00070                 {
00071                     ROS_INFO_STREAM_NAMED("MultiJointTracker.predictMeasurement", "Replacing previous prediction with prediction from "
00072                                           << most_probable_joint_hypothesis->getJointFilterTypeStr());
00073                     pose_and_vel_one_rb.rb_id = rbid_predicted;
00074                     pose_and_vel_one_rb.pose_wc = most_probable_joint_hypothesis->getPredictedSRBDeltaPoseWithCovInSensorFrame();
00075                     pose_and_vel_one_rb.velocity_wc = most_probable_joint_hypothesis->getPredictedSRBVelocityWithCovInSensorFrame();
00076                     rbid_predicted_and_predictions[rbid_predicted] = pose_and_vel_one_rb;
00077                     rbid_predicted_and_likelihood[rbid_predicted] = most_probable_joint_hypothesis->getProbabilityOfJointFilter();
00078                 }
00079             }
00080             // If we don't have any prediction for this (second) rigid body, we use this prediction
00081             else{
00082                 ROS_INFO_STREAM_NAMED("MultiJointTracker.predictMeasurement", "Use prediction from "
00083                                       << most_probable_joint_hypothesis->getJointFilterTypeStr());
00084                 pose_and_vel_one_rb.rb_id = rbid_predicted;
00085                 pose_and_vel_one_rb.pose_wc = most_probable_joint_hypothesis->getPredictedSRBDeltaPoseWithCovInSensorFrame();
00086                 pose_and_vel_one_rb.velocity_wc = most_probable_joint_hypothesis->getPredictedSRBVelocityWithCovInSensorFrame();
00087                 rbid_predicted_and_predictions[rbid_predicted] = pose_and_vel_one_rb;
00088                 rbid_predicted_and_likelihood[rbid_predicted] = most_probable_joint_hypothesis->getProbabilityOfJointFilter();
00089             }
00090         }
00091     }
00092 
00093     // We collect all the best predictions into the vector of predicted measurements
00094     std::map<int, omip_msgs::RigidBodyPoseAndVelMsg>::iterator best_predictions_it = rbid_predicted_and_predictions.begin();
00095     std::map<int, omip_msgs::RigidBodyPoseAndVelMsg>::iterator best_predictions_it_end = rbid_predicted_and_predictions.end();
00096     for(; best_predictions_it != best_predictions_it_end; best_predictions_it++)
00097     {
00098         this->_predicted_measurement.rb_poses_and_vels.push_back(best_predictions_it->second);
00099     }
00100 }
00101 
00102 void MultiJointTracker::setMeasurement(const ks_measurement_t &poses_and_vels, const double &measurement_timestamp_ns)
00103 {
00104     this->_previous_measurement_timestamp_ns = this->_measurement_timestamp_ns;
00105     this->_measurement_timestamp_ns = measurement_timestamp_ns;
00106 
00107     this->_previous_rcvd_poses_and_vels.swap(this->_last_rcvd_poses_and_vels);
00108     this->_last_rcvd_poses_and_vels = boost::shared_ptr<ks_measurement_t>(new ks_measurement_t(poses_and_vels));
00109 
00110     _n_previous_rcvd_poses_and_vels.push_back(boost::shared_ptr<ks_measurement_t>(new ks_measurement_t(poses_and_vels)));
00111     if(_n_previous_rcvd_poses_and_vels.size() > _min_num_frames_for_new_rb)
00112     {
00113         _n_previous_rcvd_poses_and_vels.pop_front();
00114     }
00115 
00116     size_t rrb_idx_begin = 0;
00117     size_t rrb_idx_end = 0;
00118 
00119     switch(this->_ks_analysis_type)
00120     {
00121     case MOVING_BODIES_TO_STATIC_ENV:
00122         rrb_idx_begin = 0;
00123         rrb_idx_end = 1;
00124         break;
00125     case BETWEEN_MOVING_BODIES:
00126         rrb_idx_begin = 1;
00127         rrb_idx_end = this->_last_rcvd_poses_and_vels->rb_poses_and_vels.size();
00128         break;
00129     case FULL_ANALYSIS:
00130         rrb_idx_begin = 0;
00131         rrb_idx_end = this->_last_rcvd_poses_and_vels->rb_poses_and_vels.size();
00132         break;
00133     }
00134 
00135     for (size_t rrb_idx = rrb_idx_begin; rrb_idx < rrb_idx_end; rrb_idx++)
00136     {
00137         for (size_t srb_idx = rrb_idx + 1; srb_idx < this->_last_rcvd_poses_and_vels->rb_poses_and_vels.size(); srb_idx++)
00138         {
00139             // Extract RB ids
00140             int rrb_id = this->_last_rcvd_poses_and_vels->rb_poses_and_vels.at(rrb_idx).rb_id;
00141             int srb_id = this->_last_rcvd_poses_and_vels->rb_poses_and_vels.at(srb_idx).rb_id;
00142 
00143             std::pair<int, int> rrb_srb_ids = std::pair<int, int>(rrb_id, srb_id);
00144 
00145             // Check if this pair of rbs were observed before -> joint was estimated before
00146             std::map<std::pair<int, int>, JointCombinedFilterPtr>::iterator prev_joint_combined_filter_it =this->_joint_combined_filters.find(rrb_srb_ids);
00147 
00148             // If this is a new pair of RB not analyzed before
00149             if (prev_joint_combined_filter_it != this->_joint_combined_filters.end())
00150             { // It was previously stored -> Use it and pass the new measurements
00151                 prev_joint_combined_filter_it->second->setMeasurement(joint_measurement_t(
00152                                                                           this->_last_rcvd_poses_and_vels->rb_poses_and_vels.at(rrb_idx),
00153                                                                           this->_last_rcvd_poses_and_vels->rb_poses_and_vels.at(srb_idx)), measurement_timestamp_ns);
00154             }
00155         }
00156     }
00157 }
00158 
00159 JointCombinedFilterPtr MultiJointTracker::getCombinedFilter(int n)
00160 {
00161     joint_combined_filters_map::iterator it = this->_joint_combined_filters.begin();
00162 
00163     for(int k=0; k<n; k++)
00164     {
00165         it++;
00166     }
00167     return it->second;
00168 }
00169 
00170 void MultiJointTracker::correctState()
00171 {
00172     // I create a new one so that the joints are either created, corrected, or deleted if there is no more information about them
00173     joint_combined_filters_map corrected_joint_combined_filters;
00174 
00175     size_t rrb_idx_begin = 0;
00176     size_t rrb_idx_end = 0;
00177 
00178     switch(this->_ks_analysis_type)
00179     {
00180     case MOVING_BODIES_TO_STATIC_ENV:
00181         rrb_idx_begin = 0;
00182         rrb_idx_end = 1;
00183         break;
00184     case BETWEEN_MOVING_BODIES:
00185         rrb_idx_begin = 1;
00186         rrb_idx_end = this->_last_rcvd_poses_and_vels->rb_poses_and_vels.size();
00187         break;
00188     case FULL_ANALYSIS:
00189         rrb_idx_begin = 0;
00190         rrb_idx_end = this->_last_rcvd_poses_and_vels->rb_poses_and_vels.size();
00191         break;
00192     }
00193 
00194     for (size_t rrb_idx = rrb_idx_begin; rrb_idx < rrb_idx_end; rrb_idx++)
00195     {
00196         for (size_t srb_idx = rrb_idx + 1; srb_idx < this->_last_rcvd_poses_and_vels->rb_poses_and_vels.size(); srb_idx++)
00197         {
00198             // Extract RB ids
00199             int rrb_id = this->_last_rcvd_poses_and_vels->rb_poses_and_vels.at(rrb_idx).rb_id;
00200             int srb_id = this->_last_rcvd_poses_and_vels->rb_poses_and_vels.at(srb_idx).rb_id;
00201 
00202             std::pair<int, int> rrb_srb_ids = std::pair<int, int>(rrb_id, srb_id);
00203 
00204             // Check if this pair of rbs were observed before and we already have a joint filter for it
00205             std::map<std::pair<int, int>, JointCombinedFilterPtr>::iterator prev_joint_combined_filter_it =this->_joint_combined_filters.find(rrb_srb_ids);
00206 
00207             // If we don't have a joint filter for it
00208             if (prev_joint_combined_filter_it == this->_joint_combined_filters.end())
00209             {
00210                 // 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)
00211                 if (this->_precomputing_counter.find(rrb_srb_ids) == this->_precomputing_counter.end())
00212                 {
00213                     // 1)
00214                     // We create an entry for this pair rrb-srb into our counter and set the counter to zero
00215                     this->_precomputing_counter[rrb_srb_ids] = 0;
00216 
00217                     // 2)
00218                     // We store the pose of the reference rigid body at the frame/time step when the new (second) rb was detected
00219                     // Since we estimate an initial trajectory of length _min_num_frames_for_new_rb we query the pose of the
00220                     // reference rigid body _min_num_frames_for_new_rb frames before
00221                     // Actually, we are not sure that the reference rb existed _min_num_frames_for_new_rb before
00222                     // so we query the oldest in our accumulator
00223                     Eigen::Twistd rrb_pose_at_srb_birthday_in_sf_twist = Eigen::Twistd(0.,0.,0.,0.,0.,0.);
00224                     std::list<omip_msgs::RigidBodyPosesAndVelsMsgPtr>::iterator acc_frames_it = this->_n_previous_rcvd_poses_and_vels.begin();
00225                     std::list<omip_msgs::RigidBodyPosesAndVelsMsgPtr>::iterator acc_frames_end = this->_n_previous_rcvd_poses_and_vels.end();
00226 
00227                     for(; acc_frames_it !=  acc_frames_end; acc_frames_it++)
00228                     {
00229                         for(int rb_prev_idx = 0; rb_prev_idx < (*acc_frames_it)->rb_poses_and_vels.size(); rb_prev_idx++)
00230                         {
00231                             // The RRB was existing in the previous frame
00232                             if((*acc_frames_it)->rb_poses_and_vels.at(rb_prev_idx).rb_id == rrb_id)
00233                             {
00234                                 ROSTwist2EigenTwist((*acc_frames_it)->rb_poses_and_vels.at(rb_prev_idx).pose_wc.twist, rrb_pose_at_srb_birthday_in_sf_twist);
00235                             }
00236                         }
00237                     }
00238                     this->_rrb_pose_at_srb_birthday_in_sf[rrb_srb_ids] = rrb_pose_at_srb_birthday_in_sf_twist;
00239 
00240                     // 3)
00241                     // We store the first pose of the second rigid body
00242                     // Due to the initial trajectory estimation, the first pose received is actually not really the first pose.
00243                     // 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
00244                     // of the body wrt the sensor was the identity
00245                     // Now, with the OMIP version that places the body frames at the centroid of the body that assumption does not hold any longer
00246                     // 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
00247                     // We can use this centroid as initial translation
00248                     Eigen::Twistd srb_pose_at_srb_birthday_in_sf_twist = Eigen::Twistd(0.,0.,0.,0.,0.,0.);
00249                     for(int rb_prev_idx = 0; rb_prev_idx < this->_last_rcvd_poses_and_vels->rb_poses_and_vels.size(); rb_prev_idx++)
00250                     {
00251                         // The SRB was existing in the previous frame
00252                         if(this->_last_rcvd_poses_and_vels->rb_poses_and_vels.at(rb_prev_idx).rb_id == srb_id)
00253                         {
00254                             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;
00255                             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;
00256                             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;
00257                         }
00258                     }
00259 
00260                     this->_srb_pose_at_srb_birthday_in_sf[rrb_srb_ids] = srb_pose_at_srb_birthday_in_sf_twist;
00261                 }
00262                 else
00263                 {
00264                     Eigen::Twistd new_twist;
00265                     ROSTwist2EigenTwist(this->_last_rcvd_poses_and_vels->rb_poses_and_vels.at(srb_idx).pose_wc.twist, new_twist);
00266 
00267                     // We accumulate _min_joint_age_for_ee iterations (pairs of poses) to initialize the filters with a better estimation
00268                     if (this->_precomputing_counter[rrb_srb_ids] >= this->_min_joint_age_for_ee)
00269                     {
00270                         corrected_joint_combined_filters[rrb_srb_ids] = JointCombinedFilterPtr(new JointCombinedFilter());
00271                         corrected_joint_combined_filters[rrb_srb_ids]->setLoopPeriodNS(this->_loop_period_ns);
00272                         corrected_joint_combined_filters[rrb_srb_ids]->setNumSamplesForLikelihoodEstimation(this->_likelihood_sample_num);
00273                         corrected_joint_combined_filters[rrb_srb_ids]->setCovarianceDeltaMeasurementLinear(this->_sigma_delta_meas_uncertainty_linear);
00274                         corrected_joint_combined_filters[rrb_srb_ids]->setCovarianceDeltaMeasurementAngular(this->_sigma_delta_meas_uncertainty_angular);
00275                         corrected_joint_combined_filters[rrb_srb_ids]->setMaxTranslationRigid(this->_rig_max_translation);
00276                         corrected_joint_combined_filters[rrb_srb_ids]->setMaxRotationRigid(this->_rig_max_rotation);
00277                         corrected_joint_combined_filters[rrb_srb_ids]->setJointLikelihoodDisconnected(this->_disconnected_j_ne);
00278                         corrected_joint_combined_filters[rrb_srb_ids]->setCovariancePrior(PRISMATIC_JOINT, this->_prism_prior_cov_vel);
00279                         corrected_joint_combined_filters[rrb_srb_ids]->setCovarianceAdditiveSystemNoisePhi(PRISMATIC_JOINT, this->_prism_sigma_sys_noise_phi);
00280                         corrected_joint_combined_filters[rrb_srb_ids]->setCovarianceAdditiveSystemNoiseTheta(PRISMATIC_JOINT, this->_prism_sigma_sys_noise_theta);
00281                         corrected_joint_combined_filters[rrb_srb_ids]->setCovarianceAdditiveSystemNoiseJointState(PRISMATIC_JOINT, this->_prism_sigma_sys_noise_pv);
00282                         corrected_joint_combined_filters[rrb_srb_ids]->setCovarianceAdditiveSystemNoiseJointVelocity(PRISMATIC_JOINT, this->_prism_sigma_sys_noise_pvd);
00283                         corrected_joint_combined_filters[rrb_srb_ids]->setCovarianceMeasurementNoise(PRISMATIC_JOINT, this->_prism_sigma_meas_noise);
00284                         corrected_joint_combined_filters[rrb_srb_ids]->setCovariancePrior(REVOLUTE_JOINT, this->_rev_prior_cov_vel);
00285                         corrected_joint_combined_filters[rrb_srb_ids]->setCovarianceAdditiveSystemNoisePhi(REVOLUTE_JOINT, this->_rev_sigma_sys_noise_phi);
00286                         corrected_joint_combined_filters[rrb_srb_ids]->setCovarianceAdditiveSystemNoiseTheta(REVOLUTE_JOINT, this->_rev_sigma_sys_noise_theta);
00287                         corrected_joint_combined_filters[rrb_srb_ids]->setCovarianceAdditiveSystemNoiseJointState(REVOLUTE_JOINT, this->_rev_sigma_sys_noise_rv);
00288                         corrected_joint_combined_filters[rrb_srb_ids]->setCovarianceAdditiveSystemNoiseJointVelocity(REVOLUTE_JOINT, this->_rev_sigma_sys_noise_rvd);
00289                         corrected_joint_combined_filters[rrb_srb_ids]->setCovarianceAdditiveSystemNoisePx(REVOLUTE_JOINT, this->_rev_sigma_sys_noise_px);
00290                         corrected_joint_combined_filters[rrb_srb_ids]->setCovarianceAdditiveSystemNoisePy(REVOLUTE_JOINT, this->_rev_sigma_sys_noise_py);
00291                         corrected_joint_combined_filters[rrb_srb_ids]->setCovarianceAdditiveSystemNoisePz(REVOLUTE_JOINT, this->_rev_sigma_sys_noise_pz);
00292                         corrected_joint_combined_filters[rrb_srb_ids]->setCovarianceMeasurementNoise(REVOLUTE_JOINT, this->_rev_sigma_meas_noise);
00293                         corrected_joint_combined_filters[rrb_srb_ids]->setMinRotationRevolute(this->_rev_min_rot_for_ee);
00294                         corrected_joint_combined_filters[rrb_srb_ids]->setMaxRadiusDistanceRevolute(this->_rev_max_joint_distance_for_ee);
00295                         corrected_joint_combined_filters[rrb_srb_ids]->setInitialMeasurement(joint_measurement_t(this->_last_rcvd_poses_and_vels->rb_poses_and_vels.at(rrb_idx),
00296                                                                                                                  this->_last_rcvd_poses_and_vels->rb_poses_and_vels.at(srb_idx)),
00297                                                                                              this->_rrb_pose_at_srb_birthday_in_sf[rrb_srb_ids],
00298                                                                                              this->_srb_pose_at_srb_birthday_in_sf[rrb_srb_ids]);
00299                         corrected_joint_combined_filters[rrb_srb_ids]->initialize();
00300                     }
00301                     else
00302                     {
00303                         this->_precomputing_counter[rrb_srb_ids] += 1;
00304                     }
00305                 }
00306             }else{
00307                 prev_joint_combined_filter_it->second->correctState();
00308                 corrected_joint_combined_filters[rrb_srb_ids] = prev_joint_combined_filter_it->second;
00309             }
00310 
00311         }
00312     }
00313 
00314     this->_joint_combined_filters = corrected_joint_combined_filters;
00315     this->_reflectState();
00316 }
00317 
00318 void MultiJointTracker::_reflectState()
00319 {
00320     this->_state.clear();
00321     this->_state = this->_joint_combined_filters;
00322 }
00323 
00324 void MultiJointTracker::estimateJointFiltersProbabilities()
00325 {
00326     BOOST_FOREACH(joint_combined_filters_map::value_type joint_combined_filter_it, this->_joint_combined_filters)
00327     {
00328         joint_combined_filter_it.second->estimateJointFilterProbabilities();
00329     }
00330 }
00331 


joint_tracker
Author(s): Roberto Martín-Martín
autogenerated on Sat Jun 8 2019 18:26:46