1 #include <boost/foreach.hpp> 9 #include <pcl/correspondence.h> 10 #include <pcl/registration/correspondence_rejection_sample_consensus.h> 14 #if ROS_VERSION_MINIMUM(1, 11, 1) // if current ros version is >= 1.11.1 (indigo) 19 #include <pcl/console/print.h> 25 Eigen::Matrix4d &transformation_matrix)
28 const int npts =
static_cast<int>(last2locations.size());
30 Eigen::Matrix<double, 3, Eigen::Dynamic> cloud_src(3, npts);
31 Eigen::Matrix<double, 3, Eigen::Dynamic> cloud_tgt(3, npts);
33 FeaturesDataBase::MapOfFeatureLocationPairs::const_iterator locations_it =
34 last2locations.begin();
35 FeaturesDataBase::MapOfFeatureLocationPairs::const_iterator locations_it_end =
37 for (
int i = 0; locations_it != locations_it_end; locations_it++, i++)
39 cloud_src(0, i) = locations_it->second.second.get<0>();
40 cloud_src(1, i) = locations_it->second.second.get<1>();
41 cloud_src(2, i) = locations_it->second.second.get<2>();
43 cloud_tgt(0, i) = locations_it->second.first.get<0>();
44 cloud_tgt(1, i) = locations_it->second.first.get<1>();
45 cloud_tgt(2, i) = locations_it->second.first.get<2>();
49 transformation_matrix = Eigen::umeyama(cloud_src, cloud_tgt,
false);
53 double loop_period_ns,
54 int ransac_iterations,
55 double estimation_error_threshold,
56 double static_motion_threshold,
57 double new_rbm_error_threshold,
58 double max_error_to_reassign_feats,
59 int supporting_features_threshold,
60 int min_num_feats_for_new_rb,
61 int min_num_frames_for_new_rb,
62 int initial_cam_motion_constraint,
65 _max_num_rb(max_num_rb),
66 _ransac_iterations(ransac_iterations),
67 _estimation_error_threshold(estimation_error_threshold),
68 _static_motion_threshold(static_motion_threshold),
69 _new_rbm_error_threshold(new_rbm_error_threshold),
70 _max_error_to_reassign_feats(max_error_to_reassign_feats),
71 _supporting_features_threshold(supporting_features_threshold),
72 _min_num_feats_for_new_rb(min_num_feats_for_new_rb),
73 _min_num_frames_for_new_rb(min_num_frames_for_new_rb),
74 _min_num_points_in_segment(0),
75 _min_probabilistic_value(0.0),
76 _max_fitness_score(0.0),
77 _min_num_supporting_feats_to_correct(7),
140 int num_tracked_features = acquired_measurement->points.size();
142 int tracked_features_index = 0;
144 for (; tracked_features_index < num_tracked_features; tracked_features_index++)
146 feature_id = acquired_measurement->points[tracked_features_index].label;
149 Feature::Location feature_location =
Feature::Location(acquired_measurement->points[tracked_features_index].x, acquired_measurement->points[tracked_features_index].y,
150 acquired_measurement->points[tracked_features_index].z);
162 (*filter_it)->predictState(time_interval_ns);
163 (*filter_it)->doNotUsePredictionFromHigherLevel();
178 std::vector<RBFilter::Ptr>::iterator filter_it = this->
_kalman_filters.begin();
181 (*filter_it)->predictMeasurement();
186 std::vector<Feature::Id> feature_ids;
192 one_filter_predicted_measurement = (*filter_it)->getPredictedMeasurement();
193 for (
size_t feat_idx = 0; feat_idx < one_filter_predicted_measurement.points.size(); feat_idx++)
196 feature_ids.push_back(one_filter_predicted_measurement.points.at(feat_idx).label);
203 for (
size_t feat_idx = 0; feat_idx < free_features_ids.size(); feat_idx++)
205 free_feat.x = this->
_features_db->getFeatureLastX(free_features_ids.at(feat_idx));
206 free_feat.y = this->
_features_db->getFeatureLastY(free_features_ids.at(feat_idx));
207 free_feat.z = this->
_features_db->getFeatureLastZ(free_features_ids.at(feat_idx));
208 free_feat.
label = free_features_ids.at(feat_idx);
222 std::vector<Feature::Id> all_filters_supporting_features;
225 (*filter_it)->estimateBestPredictionAndSupportingFeatures();
226 std::vector<Feature::Id> this_filter_supporting_features = (*filter_it)->getSupportingFeatures();
233 Eigen::Twistd last_pose_ec;
235 ROS_ERROR_NAMED(
"MultiRBTracker.estimateBestPredictionsAndSupportingFeatures",
236 "RBFilter %2d: Supporting feats:%3d (<%3d), Pose (vx,vy,vz,rx,ry,rz): % 2.2f,% 2.2f,% 2.2f,% 2.2f,% 2.2f,% 2.2f. REMOVED",
237 (
int)(*filter_it)->getId(),
238 (int)this_filter_supporting_features.size() ,
250 all_filters_supporting_features.insert(all_filters_supporting_features.end(),
251 this_filter_supporting_features.begin(),
252 this_filter_supporting_features.end());
256 return all_filters_supporting_features;
265 std::vector<Feature::Id> free_feat_ids = this->
EstimateFreeFeatures(all_filters_supporting_features);
270 ROS_INFO_NAMED(
"MultiRBTracker::correctState",
"Moving bodies: %3d, free features: %3d", (
int)this->
_kalman_filters.size(), (int)really_free_feat_ids.size());
275 (*filter_it)->correctState();
288 this->
_state.rb_poses_and_vels.clear();
292 std::vector<Eigen::Vector3d> centroids = this->
getCentroids();
296 for (
size_t poses_idx = 0; poses_idx < tracked_poses_twist_with_cov.size(); poses_idx++)
298 RB_id = this->
getRBId(poses_idx);
300 geometry_msgs::Point centroid;
301 centroid.x = centroids.at(poses_idx).x();
302 centroid.y = centroids.at(poses_idx).y();
303 centroid.z = centroids.at(poses_idx).z();
305 omip_msgs::RigidBodyPoseAndVelMsg rbpose_and_vel;
306 rbpose_and_vel.rb_id = RB_id;
307 rbpose_and_vel.pose_wc = *(tracked_poses_twist_with_cov.at(poses_idx));
308 rbpose_and_vel.velocity_wc = *(tracked_vels_twist_with_cov.at(poses_idx));
309 rbpose_and_vel.centroid = centroid;
310 this->
_state.rb_poses_and_vels.push_back(rbpose_and_vel);
328 for(
int idx = 0; idx < meas_from_st.shape_tracker_states.size(); idx++)
332 if (filter->getId() == meas_from_st.shape_tracker_states.at(idx).rb_id )
340 ROS_ERROR_STREAM(
"Integrating shape-based tracked pose RB " << meas_from_st.shape_tracker_states.at(idx).rb_id);
341 filter->integrateShapeBasedPose(meas_from_st.shape_tracker_states.at(idx).pose_wc, this->
_measurement_timestamp_ns - meas_from_st.header.stamp.toNSec() );
343 ROS_ERROR_STREAM(
"Ignoring shape-based tracked pose RB " << meas_from_st.shape_tracker_states.at(idx).rb_id);
351 const Eigen::Twistd& initial_velocity,
352 const std::vector<Feature::Id>& initial_supporting_feats)
378 BOOST_FOREACH(
Feature::Id supporting_feat_id, initial_supporting_feats)
380 new_kf->addSupportingFeature(supporting_feat_id);
387 std::vector<Feature::Id> alive_feat_ids = this->
_features_db->getListOfAliveFeatureIds();
388 std::vector<Feature::Id> free_feat_ids;
389 BOOST_FOREACH(
Feature::Id alive_feat_id, alive_feat_ids)
392 if (std::find(supporting_features.begin(), supporting_features.end(),alive_feat_id) == supporting_features.end())
394 free_feat_ids.push_back(alive_feat_id);
398 return free_feat_ids;
406 std::vector<Feature::Id> really_free_feat_ids;
412 double feat_error = 0.0;
413 double prediction_error = 0.0;
414 int best_ekf_idx = -1;
415 Eigen::Matrix4d predicted_pose;
418 BOOST_FOREACH(
Feature::Id free_feat_id, free_feat_ids)
420 free_feature_last_location = this->
_features_db->getFeatureLastLocation(free_feat_id);
421 free_feature_pre_last_location = this->
_features_db->getFeatureNextToLastLocation(free_feat_id);
422 free_feat = this->
_features_db->getFeature(free_feat_id);
429 for (
size_t filter_idx = 0; filter_idx < this->
_kalman_filters.size();filter_idx++)
436 this->
_kalman_filters.at(filter_idx)->PredictFeatureLocation(free_feat, predicted_pose,
false, free_feature_predicted_location,
true);
437 prediction_error =
L2Distance(free_feature_last_location, free_feature_predicted_location);
439 if (prediction_error < feat_error)
441 feat_error = prediction_error;
442 best_ekf_idx = filter_idx;
443 best_predicted_location = free_feature_predicted_location;
447 if (best_ekf_idx != -1)
449 this->
_kalman_filters.at(best_ekf_idx)->addSupportingFeature(free_feat_id);
450 this->
_kalman_filters.at(best_ekf_idx)->addPredictedFeatureLocation(best_predicted_location,free_feature_pre_last_location, free_feat_id);
454 really_free_feat_ids.push_back(free_feat_id);
458 return really_free_feat_ids;
466 pcl::PointCloud<pcl::PointXYZ>::Ptr source = pcl::PointCloud<pcl::PointXYZ>::Ptr(
new pcl::PointCloud<pcl::PointXYZ>());
467 pcl::PointCloud<pcl::PointXYZ>::Ptr target = pcl::PointCloud<pcl::PointXYZ>::Ptr(
new pcl::PointCloud<pcl::PointXYZ>());
468 pcl::Correspondences initial_correspondeces, filtered_correspondences;
470 std::map<int, int> index_to_feat_id;
474 BOOST_FOREACH(
Feature::Id free_feat_id, really_free_feat_ids)
482 source->push_back(point_pcl);
484 target->push_back(point_pcl);
485 initial_correspondeces.push_back(pcl::Correspondence(index, index, 0.0));
486 index_to_feat_id[index] = free_feat_id;
496 pcl::registration::CorrespondenceRejectorSampleConsensus<pcl::PointXYZ> rejector;
497 rejector.setInputSource(source);
498 rejector.setInputTarget(target);
501 rejector.getRemainingCorrespondences(initial_correspondeces, filtered_correspondences);
503 Eigen::Matrix4f best_transformation = rejector.getBestTransformation();
509 Eigen::Transform<float, 3, Eigen::Affine> best_transformation2(best_transformation);
510 double amount_translation = best_transformation2.translation().norm();
511 Eigen::AngleAxisf best_axis_angle;
512 double amount_rotation = best_axis_angle.fromRotationMatrix(best_transformation2.rotation()).
angle();
518 std::vector<Eigen::Matrix4d> trajectory;
525 std::vector<Feature::Id> ransac_best_trial_inliers;
526 BOOST_FOREACH(pcl::Correspondence filter_correspondence, filtered_correspondences)
528 int feature_id = index_to_feat_id.at(filter_correspondence.index_match);
529 ransac_best_trial_inliers.push_back(feature_id);
531 boost::tuples::get<0>(centroid_in_cf) = boost::tuples::get<0>(centroid_in_cf) + boost::tuples::get<0>(feat_loc);
532 boost::tuples::get<1>(centroid_in_cf) = boost::tuples::get<1>(centroid_in_cf) + boost::tuples::get<1>(feat_loc);
533 boost::tuples::get<2>(centroid_in_cf) = boost::tuples::get<2>(centroid_in_cf) + boost::tuples::get<2>(feat_loc);
536 boost::tuples::get<0>(centroid_in_cf) = boost::tuples::get<0>(centroid_in_cf)/(double)filtered_correspondences.size();
537 boost::tuples::get<1>(centroid_in_cf) = boost::tuples::get<1>(centroid_in_cf)/(double)filtered_correspondences.size();
538 boost::tuples::get<2>(centroid_in_cf) = boost::tuples::get<2>(centroid_in_cf)/(double)filtered_correspondences.size();
540 Eigen::Matrix4d pre_translation = Eigen::Matrix4d::Identity();
541 pre_translation(0,3) = boost::tuples::get<0>(centroid_in_cf);
542 pre_translation(1,3) = boost::tuples::get<1>(centroid_in_cf);
543 pre_translation(2,3) = boost::tuples::get<2>(centroid_in_cf);
545 trajectory.push_back(pre_translation);
551 BOOST_FOREACH(
Feature::Id matched_feat_id, ransac_best_trial_inliers)
557 Eigen::Matrix4d one_frame_best_transformation_matrix;
559 trajectory.push_back(one_frame_best_transformation_matrix);
562 Eigen::Matrix4d last_delta = trajectory.at(trajectory.size()-1)*(trajectory.at(trajectory.size()-2).
inverse());
563 Eigen::Twistd initial_velocity;
567 initial_velocity /=(measured_loop_period_ns/1e9);
569 this->
CreateNewFilter(trajectory, initial_velocity, ransac_best_trial_inliers);
572 ROS_INFO_STREAM_NAMED(
"RBMTracker._createNewFilters",
"Not enough Consensus to create a new Filter with the free Features ("<<
573 filtered_correspondences.size() <<
" inliers are too few, or the the amount of translation " <<
584 std::vector<Eigen::Matrix4d> return_filter_results;
588 return_filter_results.push_back(filter->getPose());
590 return return_filter_results;
595 std::vector<geometry_msgs::PoseWithCovariancePtr> return_filter_results;
598 return_filter_results.push_back(filter->getPoseWithCovariance());
600 return return_filter_results;
605 std::vector<geometry_msgs::TwistWithCovariancePtr> return_filter_results;
608 return_filter_results.push_back(filter->getPoseECWithCovariance());
610 return return_filter_results;
615 std::vector<geometry_msgs::TwistWithCovariancePtr> return_filter_results;
618 return_filter_results.push_back(filter->getVelocityWithCovariance());
620 return return_filter_results;
625 if (this->
_features_db->addFeatureLocation(f_id, f_loc))
645 std::vector<RBFilter::Ptr>::iterator filter_it =this->
_kalman_filters.begin();
652 std::vector<Feature::Id> this_filter_supporting_features = (*filter_it)->getSupportingFeatures();
653 for (
size_t feat_idx = 0; feat_idx < this_filter_supporting_features.size();feat_idx++)
655 if (this->
_features_db->isFeatureStored(this_filter_supporting_features.at(feat_idx)))
658 RB_id_t label = (*filter_it)->getId();
659 temp_point.x = this->
_features_db->getFeatureLastX(this_filter_supporting_features.at(feat_idx));
660 temp_point.y = this->
_features_db->getFeatureLastY(this_filter_supporting_features.at(feat_idx));
661 temp_point.z = this->
_features_db->getFeatureLastZ(this_filter_supporting_features.at(feat_idx));
663 temp_point.label = label;
664 colored_pc.points.push_back(temp_point);
684 colored_pc.points.push_back(temp_point);
693 std::vector<RBFilter::Ptr>::iterator filter_it =this->
_kalman_filters.begin();
697 FeatureCloudPCLwc::Ptr predicted_locations_pc = (*filter_it)->getFeaturesPredicted();
698 for (
size_t feat_idx = 0; feat_idx < predicted_locations_pc->points.size();feat_idx++)
701 temp_point.x = predicted_locations_pc->points[feat_idx].x;
702 temp_point.y = predicted_locations_pc->points[feat_idx].y;
703 temp_point.z = predicted_locations_pc->points[feat_idx].z;
704 temp_point.label = predicted_locations_pc->points[feat_idx].label;
705 colored_pc.points.push_back(temp_point);
707 (*filter_it)->resetFeaturesPredicted();
715 std::vector<RBFilter::Ptr>::iterator filter_it =this->
_kalman_filters.begin();
719 FeatureCloudPCLwc::Ptr at_birth_locations_pc = (*filter_it)->getFeaturesAtBirth();
720 for (
size_t feat_idx = 0; feat_idx < at_birth_locations_pc->points.size();feat_idx++)
723 temp_point.x = at_birth_locations_pc->points[feat_idx].x;
724 temp_point.y = at_birth_locations_pc->points[feat_idx].y;
725 temp_point.z = at_birth_locations_pc->points[feat_idx].z;
726 temp_point.label = at_birth_locations_pc->points[feat_idx].label;
727 colored_pc.points.push_back(temp_point);
729 (*filter_it)->resetFeaturesAtBirth();
736 std::vector<Eigen::Vector3d> centroids;
737 centroids.push_back(Eigen::Vector3d(0., 0., 0.));
738 std::vector<RBFilter::Ptr>::const_iterator filter_it = this->
_kalman_filters.begin();
747 Feature::Location initial_location = (*filter_it)->getIntialLocationOfCentroid();
748 centroids.push_back(Eigen::Vector3d(boost::tuples::get<0>(initial_location),
749 boost::tuples::get<1>(initial_location),
750 boost::tuples::get<2>(initial_location)));
752 Eigen::Vector3d temp_centroid = Eigen::Vector3d(0., 0., 0.);
753 int supporting_feats_ctr = 0;
754 std::vector<Feature::Id> this_filter_supporting_features = (*filter_it)->getSupportingFeatures();
755 for (
size_t feat_idx = 0; feat_idx < this_filter_supporting_features.size();feat_idx++)
757 if (this->
_features_db->isFeatureStored(this_filter_supporting_features.at(feat_idx)))
759 temp_centroid.x() += this->
_features_db->getFeatureLastX(this_filter_supporting_features.at(feat_idx));
760 temp_centroid.y() += this->
_features_db->getFeatureLastY(this_filter_supporting_features.at(feat_idx));
761 temp_centroid.z() += this->
_features_db->getFeatureLastZ(this_filter_supporting_features.at(feat_idx));
762 supporting_feats_ctr++;
765 centroids.push_back(temp_centroid / (
double)supporting_feats_ctr);
773 BOOST_FOREACH(omip_msgs::RigidBodyPoseAndVelMsg predicted_pose_and_vel, predicted_state.rb_poses_and_vels)
777 if (filter->getId() == predicted_pose_and_vel.rb_id)
780 filter->setPredictedState(predicted_pose_and_vel);
virtual ~MultiRBTracker()
StaticEnvironmentFilter::Ptr _static_environment_filter
EIGEN_MAKE_ALIGNED_OPERATOR_NEW typedef boost::shared_ptr< RBFilter > Ptr
boost::tuple< double, double, double > Location
#define ROS_INFO_NAMED(name,...)
virtual void correctState()
Third and final step when updating the filter. The predicted next state is corrected based on the dif...
int getNumberSupportingFeatures(int n) const
std::vector< Feature::Id > estimateBestPredictionsAndSupportingFeatures()
void ReflectState()
Prepare the corrected state to be published.
int _min_num_frames_for_new_rb
virtual void predictMeasurement()
Second step when updating the filter. The next measurement is predicted from the predicted next state...
double L2Distance(const Feature::Location &first, const Feature::Location &second)
OMIP_ADD_POINT4D uint32_t label
void TransformMatrix2Twist(const Eigen::Matrix4d &transformation_matrix, Eigen::Twistd &twist)
virtual void setMeasurement(rbt_measurement_t acquired_measurement, const double &measurement_timestamp)
Set the latest acquired measurement.
omip_msgs::RigidBodyPosesAndVelsMsg rbt_state_t
#define ROS_INFO_STREAM_NAMED(name, args)
double _max_error_to_reassign_feats
std::vector< Eigen::Vector3d > getCentroids() const
virtual rbt_state_t getState() const
Get the currently belief state.
TFSIMD_FORCE_INLINE tfScalar angle(const Quaternion &q1, const Quaternion &q2)
virtual void setDynamicReconfigureValues(rb_tracker::RBTrackerDynReconfConfig &config)
Dynamic configuration.
double _new_rbm_error_threshold
boost::mutex _measurement_timestamp_ns_mutex
MeasurementType _measurement
double _meas_depth_factor
std::pair< Location, Location > LocationPair
double _previous_measurement_timestamp_ns
void addFeatureLocation(Feature::Id f_id, Feature::Location f_loc)
boost::shared_ptr< FeaturesDataBase > Ptr
TFSIMD_FORCE_INLINE Quaternion inverse(const Quaternion &q)
std::vector< RBFilter::Ptr > _kalman_filters
double _static_motion_threshold
FeatureCloudPCL getFreeFeatures()
double _min_probabilistic_value
virtual void processMeasurementFromShapeTracker(const omip_msgs::ShapeTrackerStates &meas_from_st)
Process the measurement coming from the ShapeTrackerNode that is a refinement/substitute of the featu...
double _estimation_error_threshold
void CreateNewFilter(const std::vector< Eigen::Matrix4d > &initial_trajectory, const Eigen::Twistd &initial_velocity, const std::vector< Feature::Id > &initial_supporting_feats)
FeatureCloudPCL getLabelledSupportingFeatures()
double _measurement_timestamp_ns
double _max_fitness_score
virtual rbt_measurement_t getPredictedMeasurement() const
Get the predicted next measurement.
boost::shared_ptr< StaticEnvironmentFilter > Ptr
boost::unordered_map< Feature::Id, Feature::LocationPair > MapOfFeatureLocationPairs
double _min_amount_rotation_for_new_rb
int _min_num_supporting_feats_to_correct
void estimateRigidTransformation(const FeaturesDataBase::MapOfFeatureLocationPairs &last2locations, Eigen::Matrix4d &transformation_matrix)
FeatureCloudPCL getAtBirthFeatures()
pcl::PointXYZL FeaturePCL
virtual void predictState(double time_interval_ns)
First step when updating the filter. The next state is predicted from current state and system model ...
FeaturesDataBase::Ptr _features_db
std::vector< geometry_msgs::TwistWithCovariancePtr > getPosesECWithCovariance() const
pcl::PointCloud< FeaturePCL > FeatureCloudPCL
std::vector< Feature::Id > ReassignFreeFeatures(const std::vector< Feature::Id > &free_feat_ids)
std::vector< geometry_msgs::TwistWithCovariancePtr > getVelocitiesWithCovariance() const
int _min_num_points_in_segment
#define ROS_ERROR_NAMED(name,...)
RB_id_t getRBId(int n) const
pcl::PointCloud< FeaturePCLwc > FeatureCloudPCLwc
std::vector< Feature::Id > EstimateFreeFeatures(const std::vector< Feature::Id > &supporting_features)
int _supporting_features_threshold
FeatureCloudPCL getPredictedFeatures()
static_environment_tracker_t
#define ROS_ERROR_STREAM(args)
void Location2PointPCL(const Feature::Location &point_location, pcl::PointXYZ &point_pcl)
FeatureCloudPCLwc::Ptr rbt_measurement_t
std::vector< Feature::Id > _free_feat_ids
MultiRBTracker(int max_num_rb, double loop_period_ns, int ransac_iterations, double estimation_error_threshold, double static_motion_threshold, double new_rbm_error_threshold, double max_error_to_reassign_feats, int supporting_features_threshold, int min_num_feats_for_new_rb, int min_num_frames_for_new_rb, int initial_cam_motion_constraint, static_environment_tracker_t static_environment_tracker_type)
virtual void addPredictedState(const rbt_state_t &predicted_state, const double &predicted_state_timestamp_ns)
void TryToCreateNewFilter(const std::vector< Feature::Id > &really_free_feat_ids)
std::vector< Feature::Id > _really_free_feat_ids
std::vector< Eigen::Matrix4d > getPoses() const
MeasurementType _predicted_measurement
double _min_amount_translation_for_new_rb
FeaturesDataBase::Ptr getFeaturesDatabase()
void toPCL(const ros::Time &stamp, pcl::uint64_t &pcl_stamp)
int _min_num_feats_for_new_rb
std::vector< geometry_msgs::PoseWithCovariancePtr > getPosesWithCovariance() const