00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 
00026 
00027 
00028 
00029 
00030 
00031 
00032 
00033 
00034 
00035 
00036 
00037 
00038 
00039 
00040 
00041 
00042 
00043 
00044 
00045 
00046 
00047 
00048 
00049 
00050 
00051 
00052 
00053 
00054 
00055 
00056 
00057 
00058 
00059  
00060 
00061 
00062 
00063 
00064 
00065 
00066 
00067 
00068 
00069 
00070 
00071 
00072 
00073 
00074 
00075 
00076 
00077 
00078 
00079 
00080 
00081 
00082 
00083 
00084 
00085 
00086 
00087 
00088 
00089 
00090 
00091 
00092 
00093 
00094 
00095 
00096 
00097 
00098 
00099 #include <ros/ros.h>
00100 
00101 #include <cob_leg_detection/LegDetectionConfig.h>
00102 #include <cob_leg_detection/laser_processor.h>
00103 #include <cob_leg_detection/calc_leg_features.h>
00104 
00105 #include <opencv/cxcore.h>
00106 #include <opencv/cv.h>
00107 #include <opencv/ml.h>
00108 
00109 #include <cob_perception_msgs/PositionMeasurement.h>
00110 #include <cob_perception_msgs/PositionMeasurementArray.h>
00111 #include <cob_perception_msgs/Person.h>
00112 #include <cob_perception_msgs/People.h>
00113 #include <sensor_msgs/LaserScan.h>
00114 
00115 #include <tf/transform_listener.h>
00116 #include <tf/message_filter.h>
00117 #include <message_filters/subscriber.h>
00118 
00119 #include <cob_people_tracking_filter/tracker_kalman.h>
00120 #include <cob_people_tracking_filter/state_pos_vel.h>
00121 #include <cob_people_tracking_filter/rgb.h>
00122 #include <visualization_msgs/Marker.h>
00123 #include <dynamic_reconfigure/server.h>
00124 
00125 #include <tf/transform_broadcaster.h>
00126 #include <tf/transform_listener.h>
00127 
00128 #include <algorithm>
00129 #include <vector>
00130 
00131 using namespace std;
00132 using namespace laser_processor;
00133 using namespace ros;
00134 using namespace tf;
00135 using namespace estimation;
00136 using namespace BFL;
00137 using namespace MatrixWrapper;
00138 
00139 
00140 static double no_observation_timeout_s = 0.5;
00141 static double max_second_leg_age_s     = 2.0 ;  
00142 static double max_track_jump_m         = 1.0; 
00143 static double max_meas_jump_m          = 0.75; 
00144 static double leg_pair_separation_m    = 0.50;  
00145 static string fixed_frame              = "base_link";
00146 static double cov_meas_legs_m          = 0.025;
00147 static double cov_meas_people_m        = 0.025;
00148 
00149 static double kal_p = 4, kal_q = .002, kal_r = 10;
00150 static bool use_filter = true;
00151 
00152 static string detector_ = "laser_scaner";
00153 
00154 
00155 
00156 
00157 
00158 
00159 
00160 
00161 
00162 
00163 
00164 
00165 
00166 
00167 
00168 
00169 
00170 
00171 
00172 
00173 
00174 
00175 
00176 
00177 class SavedPersonFeature
00178 {
00179 public:
00180 
00181         string id_;
00182         string object_id;
00183         string person_name;
00184 
00185         Stamped<Point> position_;
00186         Stamped<Vector3> velocity_;
00187 
00188         
00189         
00190         BFL::StatePosVel sys_sigma_;
00191         TrackerKalman filter_;
00192         ros::Time time_;
00193         ros::Time meas_time_;
00194 
00195         double reliability, p, probability;
00196 
00197         
00198         SavedPersonFeature(Stamped<Point> loc, std::string& id, std::string& name)
00199         : sys_sigma_(Vector3(0.05, 0.05, 0.05), Vector3(1.0, 1.0, 1.0)),
00200           filter_("tracker_people",sys_sigma_),
00201           reliability(-1.), p(4)
00202         {
00203                 object_id = id;
00204                 person_name = name;
00205                 time_ = loc.stamp_;
00206 
00207                 
00208                 
00209                 
00210 
00211 
00212 
00213                 StatePosVel prior_sigma(Vector3(0.1,0.1,0.1), Vector3(0.0000001, 0.0000001, 0.0000001));
00214                 filter_.initialize(loc, prior_sigma, time_.toSec());
00215                 StatePosVel est;
00216                 filter_.getEstimate(est);
00217                 updatePosition();
00218         }
00219         
00220 
00221 
00222 
00223         void propagate(ros::Time time)
00224         {
00225                 time_ = time;
00226                 filter_.updatePrediction(time.toSec());
00227                 updatePosition();
00228         }
00229 
00230         
00231 
00232 
00233 
00234 
00235         void update(Stamped<Point> loc, double probability)
00236         {
00237                 
00238                 
00239                 meas_time_ = loc.stamp_;
00240                 time_ = meas_time_;
00241 
00242                 
00243                 SymmetricMatrix cov(3);
00244                 cov = 0.0;
00245                 cov(1,1) = cov_meas_people_m;
00246                 cov(2,2) = cov_meas_people_m;
00247                 cov(3,3) = cov_meas_people_m;
00248 
00249                 filter_.updateCorrection(loc, cov);
00250                 updatePosition();
00251 
00252         }
00253         
00254 
00255 
00256 
00257         double getLifetime()
00258         {
00259                 return filter_.getLifetime();
00260         }
00261 
00262         double getReliability()
00263         {
00264                 return reliability;
00265         }
00266 
00267 private:
00268         
00269 
00270 
00271 
00272         void updatePosition()
00273         {
00274                 StatePosVel est;
00275                 filter_.getEstimate(est);
00276 
00277                 position_[0] = est.pos_[0];
00278                 position_[1] = est.pos_[1];
00279                 position_[2] = est.pos_[2];
00280 
00281                 velocity_[0] = est.vel_[0];
00282                 velocity_[1] = est.vel_[1];
00283                 velocity_[2] = est.vel_[2];
00284 
00285                 position_.stamp_ = time_;
00286                 position_.frame_id_ = fixed_frame;
00287                 velocity_.stamp_ = time_;
00288                 velocity_.frame_id_ = fixed_frame;
00289         }
00290 };
00291 
00292 class SavedFeature
00293 {
00294 public:
00295         static int nextid;
00296         TransformListener& tfl_;
00297 
00298         BFL::StatePosVel sys_sigma_;
00299         TrackerKalman filter_;
00300 
00301         string id_;
00302         string object_id;
00303         ros::Time time_;
00304         ros::Time meas_time_;
00305 
00306         double reliability, p, probability;
00307 
00308         Stamped<Point> position_;
00309         Stamped<Vector3> velocity_;
00310         SavedFeature* other;
00311         float dist_to_person_;
00312 
00313 
00314         
00315         SavedFeature(Stamped<Point> loc, TransformListener& tfl)
00316         : tfl_(tfl),
00317           sys_sigma_(Vector3(0.05, 0.05, 0.05), Vector3(1.0, 1.0, 1.0)),
00318           filter_("tracker_legs",sys_sigma_),
00319           reliability(-1.), p(4)
00320         {
00321                 char id[100];
00322                 snprintf(id,100,"legtrack %d", nextid++);
00323                 id_ = std::string(id);
00324 
00325                 object_id = "";
00326                 time_ = loc.stamp_;
00327                 meas_time_ = loc.stamp_;
00328                 other = NULL;
00329 
00330                 try {
00331                         tfl_.transformPoint(fixed_frame, loc, loc);
00332                 } catch(...) {
00333                         ROS_WARN("TF exception spot 6.");
00334                 }
00335                 StampedTransform pose( Pose(Quaternion(0.0, 0.0, 0.0, 1.0), loc), loc.stamp_, id_, loc.frame_id_);
00336                 tfl_.setTransform(pose);
00337 
00338                 StatePosVel prior_sigma(Vector3(0.1,0.1,0.1), Vector3(0.0000001, 0.0000001, 0.0000001));
00339                 filter_.initialize(loc, prior_sigma, time_.toSec());
00340                 StatePosVel est;
00341                 filter_.getEstimate(est);
00342                 updatePosition();
00343 
00344         }
00345 
00346         void propagate(ros::Time time)
00347         {
00348                 time_ = time;
00349                 filter_.updatePrediction(time.toSec());
00350                 updatePosition();
00351         }
00352 
00353         void update(Stamped<Point> loc, double probability)
00354         {
00355                 StampedTransform pose( Pose(Quaternion(0.0, 0.0, 0.0, 1.0), loc), loc.stamp_, id_, loc.frame_id_);
00356                 tfl_.setTransform(pose);
00357 
00358                 meas_time_ = loc.stamp_;
00359                 time_ = meas_time_;
00360 
00361                 SymmetricMatrix cov(3);
00362                 cov = 0.0;
00363                 cov(1,1) = cov_meas_legs_m;
00364                 cov(2,2) = cov_meas_legs_m;
00365                 cov(3,3) = cov_meas_legs_m;
00366 
00367                 filter_.updateCorrection(loc, cov);
00368                 updatePosition();
00369 
00370                 if(reliability<0 || !use_filter){
00371                         reliability = probability;
00372                         p = kal_p;
00373                 }
00374                 else{
00375                         p += kal_q;
00376                         double k = p / (p+kal_r);
00377                         reliability += k * (probability - reliability);
00378                         p *= (1 - k);
00379                 }
00380         }
00381 
00382         double getLifetime()
00383         {
00384                 return filter_.getLifetime();
00385         }
00386 
00387         double getReliability()
00388         {
00389                 return reliability;
00390         }
00391 
00392 private:
00393         void updatePosition()
00394         {
00395                 StatePosVel est;
00396                 filter_.getEstimate(est);
00397 
00398                 position_[0] = est.pos_[0];
00399                 position_[1] = est.pos_[1];
00400                 position_[2] = est.pos_[2];
00401 
00402                 velocity_[0] = est.vel_[0];
00403                 velocity_[1] = est.vel_[1];
00404                 velocity_[2] = est.vel_[2];
00405 
00406                 position_.stamp_ = time_;
00407                 position_.frame_id_ = fixed_frame;
00408                 velocity_.stamp_ = time_;
00409                 velocity_.frame_id_ = fixed_frame;
00410 
00411                 double nreliability = fmin(1.0, fmax(0.1, est.vel_.length() / 0.5));
00412         }
00413 
00414 };
00415 
00416 int SavedFeature::nextid = 0;
00417 
00418 
00419 class MatchedFeature
00420 {
00421 public:
00422         SampleSet* candidate_;
00423         SavedFeature* closest_;
00424         float distance_;
00425         double probability_;
00426 
00427         MatchedFeature(SampleSet* candidate, SavedFeature* closest, float distance, double probability)
00428         : candidate_(candidate)
00429         , closest_(closest)
00430         , distance_(distance)
00431         , probability_(probability)
00432         {}
00433 
00434         inline bool operator< (const MatchedFeature& b) const
00435         {
00436                 return (distance_ <  b.distance_);
00437         }
00438 };
00439 
00440 int g_argc;
00441 char** g_argv;
00442 
00443 
00444 
00445 
00446 
00447 class LegDetector
00448 {
00449 public:
00450         NodeHandle nh_;
00451         TransformListener tfl_;
00452         
00453         ScanMask mask_;
00454         int mask_count_;
00455         CvRTrees forest;
00456         float connected_thresh_;
00457         int feat_count_;
00458         char save_[100];
00459         list<SavedFeature*> saved_features_;
00460         boost::mutex saved_mutex_;
00461         int feature_id_;
00462         bool use_seeds_;
00463         bool publish_legs_, publish_people_, publish_leg_markers_, publish_people_markers_, publish_vel_markers_;
00464         int next_p_id_;
00465         double leg_reliability_limit_;
00466         int min_points_per_group;
00467 
00468         ros::Publisher people_measurements_pub_;
00469         ros::Publisher leg_measurements_pub_;
00470         ros::Publisher people_pub_;
00471         ros::Publisher markers_pub_;
00472 
00473         dynamic_reconfigure::Server<cob_leg_detection::LegDetectionConfig> server_;
00474 
00475         message_filters::Subscriber<cob_perception_msgs::PositionMeasurementArray> people_sub_;
00476         message_filters::Subscriber<sensor_msgs::LaserScan> laser_sub_;
00477         
00478         tf::MessageFilter<sensor_msgs::LaserScan> laser_notifier_;
00479 
00480         
00481         list<SavedPersonFeature*>saved_people_;
00482 
00483         tf::TransformBroadcaster br_;
00484 
00485         LegDetector(ros::NodeHandle nh) :
00486                 nh_(nh),
00487                 mask_count_(0),
00488                 feat_count_(0),
00489                 next_p_id_(0),
00490                 laser_sub_(nh_,"scan",10),
00491                 laser_notifier_(laser_sub_,tfl_,fixed_frame,10)
00492         {
00493 
00494                 if (g_argc > 1) {
00495                         forest.load(g_argv[1]);
00496                         feat_count_ = forest.get_active_var_mask()->cols;
00497                         printf("Loaded forest with %d features: %s\n", feat_count_, g_argv[1]);
00498                 } else {
00499                         printf("Please provide a trained random forests classifier as an input.\n");
00500                         shutdown();
00501                 }
00502 
00503                 
00504                 leg_measurements_pub_ = nh_.advertise<cob_perception_msgs::PositionMeasurementArray>("leg_tracker_measurements",0);
00505                 people_measurements_pub_ = nh_.advertise<cob_perception_msgs::PositionMeasurementArray>("people_tracker_measurements", 0);
00506                 
00507                 people_pub_ = nh_.advertise<cob_perception_msgs::People>("people",0);
00508                 markers_pub_ = nh_.advertise<visualization_msgs::Marker>("visualization_marker", 20);
00509 
00510                 laser_notifier_.registerCallback(boost::bind(&LegDetector::laserCallback, this, _1));
00511                 laser_notifier_.setTolerance(ros::Duration(0.01));
00512 
00513                 people_sub_.subscribe(nh_,"people_tracker_measurements",10);
00514                 people_sub_.registerCallback(boost::bind(&LegDetector::peopleCallback, this, _1));
00515 
00516                 dynamic_reconfigure::Server<cob_leg_detection::LegDetectionConfig>::CallbackType f;
00517                 f = boost::bind(&LegDetector::configure, this, _1, _2);
00518                 server_.setCallback(f);
00519 
00520                 feature_id_ = 0;
00521         }
00522 
00523         ~LegDetector()
00524         {
00525         }
00526 
00527         void configure(cob_leg_detection::LegDetectionConfig &config, uint32_t level)
00528         {
00529                 connected_thresh_       = config.connection_threshold;
00530                 min_points_per_group    = config.min_points_per_group;
00531                 leg_reliability_limit_  = config.leg_reliability_limit;
00532                 publish_legs_           = config.publish_legs;
00533                 publish_people_         = config.publish_people;
00534                 publish_leg_markers_    = config.publish_leg_markers;
00535                 publish_vel_markers_    = config.publish_vel_markers;
00536                 publish_people_markers_ = config.publish_people_markers;
00537 
00538                 no_observation_timeout_s = config.no_observation_timeout;
00539                 max_second_leg_age_s     = config.max_second_leg_age;
00540                 max_track_jump_m         = config.max_track_jump;
00541                 max_meas_jump_m          = config.max_meas_jump;
00542                 leg_pair_separation_m    = config.leg_pair_separation;
00543                 cov_meas_legs_m                  = config.cov_meas_legs;
00544                 cov_meas_people_m        = config.cov_meas_people;
00545 
00546                 if(fixed_frame.compare(config.fixed_frame) != 0){
00547                         fixed_frame              = config.fixed_frame;
00548                         laser_notifier_.setTargetFrame(fixed_frame);
00549                         
00550                 }
00551                 kal_p                    = config.kalman_p;
00552                 kal_q                    = config.kalman_q;
00553                 kal_r                    = config.kalman_r;
00554                 use_filter               = config.kalman_on == 1;
00555         }
00556 
00557 
00558         
00559 
00560 
00561 
00562 
00563         void peopleCallback(const cob_perception_msgs::PositionMeasurementArray::ConstPtr& people_meas)
00564         {
00565                 
00566                 if (people_meas->people.empty())
00567                         return;
00568 
00569                 boost::mutex::scoped_lock lock(saved_mutex_);
00570                 list<SavedPersonFeature*>::iterator it;
00571                 cob_perception_msgs::PositionMeasurement ppl;
00572                 list<SavedPersonFeature*> saved_people;
00573 
00574                 
00575                 if(saved_people_.size() != 0){
00576                         
00577                         
00578                         for(list<SavedPersonFeature*>::iterator iter_ = saved_people_.begin();
00579                                         iter_ != saved_people_.end(); ++iter_){
00580                                 (*iter_)->propagate(people_meas->header.stamp);
00581                         }
00582                 }
00583 
00584                 
00585                 for(int i = 0; i < people_meas->people.size(); i++){
00586                         ppl = people_meas->people.at(i);
00587                         Stamped<Point> person_loc(Vector3(ppl.pos.x, ppl.pos.y, ppl.pos.z), people_meas->header.stamp, ppl.header.frame_id);
00588                         
00589                         if(saved_people.size() == 0){
00590                                 saved_people.insert(saved_people.end(), new SavedPersonFeature(person_loc, ppl.object_id, ppl.name));
00591                         }else{
00592                                 bool found = false;
00593                                 
00594                                 for (it = saved_people.begin(); it != saved_people.end(); ++it){
00595                                         if(ppl.name.compare((*it)->person_name) == 0 )
00596                                                 found = true;
00597                                 }
00598                                 
00599                                 if(!found){
00600                                         found = false;
00601                                         saved_people.insert(saved_people.end(), new SavedPersonFeature(person_loc, ppl.object_id, ppl.name));
00602                                 }
00603                         }
00604                 }
00605 
00606                 
00607                 
00608                 
00609 
00610                 
00611                 
00612                 if(saved_people_.size() == 0){
00613                         for(list<SavedPersonFeature*>::iterator iter = saved_people.begin(); iter != saved_people.end(); ++iter){
00614                                 saved_people_.push_back((*iter));
00615                         }
00616                 }else{ 
00617                         for(list<SavedPersonFeature*>::iterator iter = saved_people.begin(); iter != saved_people.end(); ++iter)
00618                         {
00619                                 bool found_temp = false;
00620                                 for(list<SavedPersonFeature*>::iterator iter_ = saved_people_.begin(); iter_ != saved_people_.end(); ++iter_){
00621                                         if((*iter)->person_name.compare((*iter_)->person_name) == 0){
00622                                                 found_temp = true;
00623                                                 
00624                                                 
00625                                                 (*iter_)->update((*iter)->position_, 1.0);
00626                                         }
00627                                 }
00628 
00629                                 if(found_temp == false ){
00630                                         saved_people_.push_back((*iter));
00631                                 }
00632                         }
00633                 }
00634 
00635                 
00636                 for(list<SavedPersonFeature*>::iterator iter = saved_people_.begin(); iter != saved_people_.end(); ++iter){
00637                         bool found_temp = false;
00638                         for(list<SavedPersonFeature*>::iterator iter_ = saved_people.begin(); iter_ != saved_people.end(); ++iter_){
00639                                 if((*iter)->person_name.compare((*iter_)->person_name) == 0){
00640                                         found_temp = true;
00641                                 }
00642                         }
00643                         if(found_temp == false ){
00644                                 delete (*iter);
00645                                 saved_people_.erase(iter++);
00646                         }
00647                 }
00648 
00649 
00650                 PRINT_LIST(saved_people_, "LIST saved_people ::  ");
00651                 
00652 
00653                 int i = 0;
00654 
00655                 vector<cob_perception_msgs::Person> people;
00656 
00657                 for (list<SavedPersonFeature*>::iterator sp_iter = saved_people_.begin();
00658                                 sp_iter != saved_people_.end(); sp_iter++,i++){
00659                         
00660                         cob_perception_msgs::Person person;
00661                         person.detector = detector_;
00662                         person.name = (*sp_iter)->person_name; 
00663                         person.position.position.x = (*sp_iter)->position_[0];
00664                         person.position.position.y = (*sp_iter)->position_[1];
00665                         person.position.position.z = (*sp_iter)->position_[2];
00666 
00667                         person.velocity.x = (*sp_iter)->velocity_[0];
00668                         person.velocity.y = (*sp_iter)->velocity_[1];
00669                         person.velocity.z = (*sp_iter)->velocity_[2];
00670 
00671                         people.push_back(person);
00672 
00673                         double dx = (*sp_iter)->velocity_[0], dy = (*sp_iter)->velocity_[1];
00674                         visualization_msgs::Marker m;
00675                         m.header.stamp = people_meas->header.stamp;
00676                         m.header.frame_id = fixed_frame;
00677                         m.ns = "SPEED";
00678                         m.type = m.ARROW;
00679                         m.pose.position.x = (*sp_iter)->position_[0];
00680                         m.pose.position.y = (*sp_iter)->position_[1];
00681                         m.pose.position.z = (*sp_iter)->position_[2];
00682                         m.pose.orientation.x = (*sp_iter)->velocity_[0];
00683                         m.pose.orientation.y = (*sp_iter)->velocity_[1];
00684                         m.pose.orientation.z = 0.0;
00685                         m.scale.x = sqrt(dx*dx+dy*dy);
00686                         ROS_INFO("speed %f", m.scale.x);
00687                         
00688                         m.scale.y = .05;
00689                         m.scale.z = .05;
00690                         m.color.a = 1;
00691                         m.color.r = 1;
00692                         m.lifetime = ros::Duration(0.5);
00693 
00694                         markers_pub_.publish(m);
00695                 }
00696                 
00697                 cob_perception_msgs::People array;
00698                 array.header.stamp = ros::Time::now();
00699                 array.people = people;
00700                 people_pub_.publish(array);
00701         }
00702 
00703 
00704         
00705 
00706         void laserCallback(const sensor_msgs::LaserScan::ConstPtr& scan)
00707         {
00708                 ScanProcessor processor(*scan, mask_);
00709                 processor.splitConnected(connected_thresh_);
00710                 processor.removeLessThan(5);
00711                 CvMat* tmp_mat = cvCreateMat(1,feat_count_,CV_32FC1);
00712 
00713                 
00714                 ros::Time purge = scan->header.stamp + ros::Duration().fromSec(-no_observation_timeout_s);
00715                 list<SavedFeature*>::iterator sf_iter = saved_features_.begin();
00716                 while (sf_iter != saved_features_.end()){
00717                         if ((*sf_iter)->meas_time_ < purge){
00718                                 if( (*sf_iter)->other )
00719                                         (*sf_iter)->other->other = NULL;
00720                                 delete (*sf_iter);
00721                                 saved_features_.erase(sf_iter++);
00722                         }else
00723                                 ++sf_iter;
00724                 }
00725 
00726 
00727                 
00728                 list<SavedFeature*> propagated;
00729                 for (list<SavedFeature*>::iterator sf_iter = saved_features_.begin();
00730                                 sf_iter != saved_features_.end();
00731                                 sf_iter++){
00732                         (*sf_iter)->propagate(scan->header.stamp);
00733                         propagated.push_back(*sf_iter);
00734                 }
00735 
00736                 
00737                 
00738                 
00739                 multiset<MatchedFeature> matches;
00740                 for (list<SampleSet*>::iterator i = processor.getClusters().begin();
00741                                 i != processor.getClusters().end();i++){
00742                         vector<float> f = calcLegFeatures(*i, *scan);
00743 
00744                         for (int k = 0; k < feat_count_; k++)
00745                                 tmp_mat->data.fl[k] = (float)(f[k]);
00746 
00747                         float probability = forest.predict_prob( tmp_mat );
00748                         Stamped<Point> loc((*i)->center(), scan->header.stamp, scan->header.frame_id);
00749                         try {
00750                                 tfl_.transformPoint(fixed_frame, loc, loc);
00751                         } catch(...) {
00752                                 ROS_WARN("TF exception spot 3.");
00753                         }
00754 
00755                         list<SavedFeature*>::iterator closest = propagated.end();
00756                         float closest_dist = max_track_jump_m;
00757 
00758                         for (list<SavedFeature*>::iterator pf_iter = propagated.begin();
00759                                         pf_iter != propagated.end();pf_iter++){
00760                                 
00761                                 float dist = loc.distance((*pf_iter)->position_);
00762                                 if ( dist < closest_dist ){
00763                                         closest = pf_iter;
00764                                         closest_dist = dist;
00765                                 }
00766                         }
00767                         
00768                         if (closest == propagated.end()){
00769                                 list<SavedFeature*>::iterator new_saved = saved_features_.insert(saved_features_.end(), new SavedFeature(loc, tfl_));
00770                         }else 
00771                                 matches.insert(MatchedFeature(*i,*closest,closest_dist,probability));
00772                 }
00773 
00774                 
00775                 
00776                 while (matches.size() > 0){
00777                         multiset<MatchedFeature>::iterator matched_iter = matches.begin();
00778                         bool found = false;
00779                         list<SavedFeature*>::iterator pf_iter = propagated.begin();
00780                         while (pf_iter != propagated.end()){
00781                                 
00782                                 if (matched_iter->closest_ == *pf_iter){
00783                                         
00784                                         Stamped<Point> loc(matched_iter->candidate_->center(), scan->header.stamp, scan->header.frame_id);
00785                                         try {
00786                                                 tfl_.transformPoint(fixed_frame, loc, loc);
00787                                         } catch(...) {
00788                                                 ROS_WARN("TF exception spot 4.");
00789                                         }
00790 
00791                                         
00792                                         matched_iter->closest_->update(loc, matched_iter->probability_);
00793 
00794                                         
00795                                         matches.erase(matched_iter);
00796                                         propagated.erase(pf_iter++);
00797                                         found = true;
00798                                         break;
00799                                 }else{  
00800                                         pf_iter++;
00801                                 }
00802                         }
00803 
00804                         
00805                         
00806                         if (!found){
00807                                 Stamped<Point> loc(matched_iter->candidate_->center(), scan->header.stamp, scan->header.frame_id);
00808                                 try {
00809                                         tfl_.transformPoint(fixed_frame, loc, loc);
00810                                 } catch(...) {
00811                                         ROS_WARN("TF exception spot 5.");
00812                                 }
00813                                 list<SavedFeature*>::iterator closest = propagated.end();
00814                                 float closest_dist = max_track_jump_m;
00815 
00816                                 for (list<SavedFeature*>::iterator remain_iter = propagated.begin();
00817                                                 remain_iter != propagated.end();remain_iter++){
00818                                         float dist = loc.distance((*remain_iter)->position_);
00819                                         if ( dist < closest_dist ){
00820                                                 closest = remain_iter;
00821                                                 closest_dist = dist;
00822                                         }
00823                                 }
00824 
00825                                 
00826                                 
00827                                 if (closest == propagated.end())
00828                                         list<SavedFeature*>::iterator new_saved = saved_features_.insert(saved_features_.end(), new SavedFeature(loc, tfl_));
00829                                 else
00830                                         matches.insert(MatchedFeature(matched_iter->candidate_,*closest,closest_dist, matched_iter->probability_));
00831                                 matches.erase(matched_iter);
00832                         }
00833                 }
00834 
00835                 cvReleaseMat(&tmp_mat); tmp_mat = 0;
00836                 
00837                 pairLegs();
00838 
00839                 
00840 
00841                 int i = 0;
00842                 vector<cob_perception_msgs::PositionMeasurement> people;
00843                 vector<cob_perception_msgs::PositionMeasurement> legs;
00844 
00845                 for (list<SavedFeature*>::iterator sf_iter = saved_features_.begin();
00846                                 sf_iter != saved_features_.end(); sf_iter++,i++){
00847                         
00848                         double reliability = (*sf_iter)->getReliability();
00849                         
00850 
00851                         if ((*sf_iter)->getReliability() > leg_reliability_limit_
00852                                         && publish_legs_){
00853 
00854                                 cob_perception_msgs::PositionMeasurement pos;
00855                                 pos.header.stamp = scan->header.stamp;
00856                                 pos.header.frame_id = fixed_frame;
00857                                 pos.name = "leg_detection";
00858                                 pos.object_id = (*sf_iter)->id_;
00859                                 pos.pos.x = (*sf_iter)->position_[0];
00860                                 pos.pos.y = (*sf_iter)->position_[1];
00861                                 pos.pos.z = (*sf_iter)->position_[2];
00862                                 pos.vel.x = (*sf_iter)->velocity_[0];
00863                                 pos.vel.y = (*sf_iter)->velocity_[1];
00864                                 pos.vel.z = (*sf_iter)->velocity_[2];
00865                                 pos.reliability = reliability;
00866                                 pos.covariance[0] = pow(0.3 / reliability,2.0);
00867                                 pos.covariance[1] = 0.0;
00868                                 pos.covariance[2] = 0.0;
00869                                 pos.covariance[3] = 0.0;
00870                                 pos.covariance[4] = pow(0.3 / reliability,2.0);
00871                                 pos.covariance[5] = 0.0;
00872                                 pos.covariance[6] = 0.0;
00873                                 pos.covariance[7] = 0.0;
00874                                 pos.covariance[8] = 10000.0;
00875                                 pos.initialization = 0;
00876                                 legs.push_back(pos);
00877                         }
00878 
00879                         if (publish_leg_markers_){
00880                                 visualization_msgs::Marker m;
00881                                 m.header.stamp = (*sf_iter)->time_;
00882                                 m.header.frame_id = fixed_frame;
00883                                 m.ns = "LEGS";
00884                                 m.id = i;
00885                                 m.type = m.SPHERE;
00886                                 m.pose.position.x = (*sf_iter)->position_[0];
00887                                 m.pose.position.y = (*sf_iter)->position_[1];
00888                                 m.pose.position.z = (*sf_iter)->position_[2];
00889 
00890                                 m.scale.x = .1;
00891                                 m.scale.y = .1;
00892                                 m.scale.z = .1;
00893                                 m.color.a = 1;
00894                                 m.lifetime = ros::Duration(0.5);
00895                                 if((*sf_iter)->object_id != ""){
00896                                         m.color.r = 1;
00897                                 }else{
00898                                         m.color.b = (*sf_iter)->getReliability();
00899                                 }
00900                                 markers_pub_.publish(m);
00901                         }
00902 
00903                         if (publish_people_ || publish_people_markers_ ){
00904                                 SavedFeature* other = (*sf_iter)->other;
00905                                 if(other!=NULL && other<(*sf_iter)){
00906 
00907                                         Stamped<Point> one = (*sf_iter)->position_, two = (other)->position_;
00908                                         double ddx = one[0]-two[0], ddy = one[1]-two[1], ddz = one[2]-two[2];
00909                                         double d =  sqrt(ddx*ddx + ddy*ddy + ddz*ddz);
00910                                         
00911 
00912                                         double dx = ((*sf_iter)->position_[0] + other->position_[0])/2,
00913                                                         dy = ((*sf_iter)->position_[1] + other->position_[1])/2,
00914                                                         dz = ((*sf_iter)->position_[2] + other->position_[2])/2;
00915 
00916                                         double vx = ((*sf_iter)->velocity_[0]- ((*sf_iter)->velocity_[0] - other->velocity_[0])/2),
00917                                                         vy = ((*sf_iter)->velocity_[1]- ((*sf_iter)->velocity_[1] - other->velocity_[1])/2),
00918                                                         vz = ((*sf_iter)->velocity_[2]- ((*sf_iter)->velocity_[2] - other->velocity_[2])/2);
00919 
00920                                         double speed = sqrt(vx*vx + vy*vy + vz*vz);
00921                                         
00922 
00923                                         if (publish_people_ ){
00924 
00925                                                 reliability = reliability * other->reliability;
00926                                                 cob_perception_msgs::PositionMeasurement pos;
00927                                                 pos.header.stamp = (*sf_iter)->time_;
00928                                                 pos.header.frame_id = fixed_frame;
00929                                                 pos.name = (*sf_iter)->object_id;
00930                                                 pos.object_id = (*sf_iter)->id_ + "|" + other->id_;
00931                                                 pos.pos.x = dx;
00932                                                 pos.pos.y = dy;
00933                                                 pos.pos.z = dz;
00934                                                 pos.vel.x = vx;
00935                                                 pos.vel.y = vy;
00936                                                 pos.vel.z = vz;
00937                                                 pos.reliability = reliability;
00938                                                 pos.covariance[0] = pow(0.3 / reliability,2.0);
00939                                                 pos.covariance[1] = 0.0;
00940                                                 pos.covariance[2] = 0.0;
00941                                                 pos.covariance[3] = 0.0;
00942                                                 pos.covariance[4] = pow(0.3 / reliability,2.0);
00943                                                 pos.covariance[5] = 0.0;
00944                                                 pos.covariance[6] = 0.0;
00945                                                 pos.covariance[7] = 0.0;
00946                                                 pos.covariance[8] = 10000.0;
00947                                                 pos.initialization = 0;
00948 
00949                                                 people.push_back(pos);
00950 
00951                                                 ros::Time time = ros::Time::now();
00952                                                 tf::Transform person(tf::Quaternion(0,0,0,1), tf::Vector3(dx, dy, dz));
00953                                                 try
00954                                                 {
00955                                                         br_.sendTransform(tf::StampedTransform(person, time,
00956                                                                         "/base_link" , pos.name.c_str()));
00957                                                 }catch (tf::TransformException ex){
00958                                                         ROS_ERROR("Broadcaster unavailable %s", ex.what());
00959                                                 }
00960                                         }
00961 
00962                                         if (publish_people_markers_ ){
00963                                                 visualization_msgs::Marker m;
00964                                                 m.header.stamp = (*sf_iter)->time_;
00965                                                 m.header.frame_id = fixed_frame;
00966                                                 m.ns = "PEOPLE";
00967                                                 m.id = i;
00968                                                 m.type = m.SPHERE;
00969                                                 m.pose.position.x = dx;
00970                                                 m.pose.position.y = dy;
00971                                                 m.pose.position.z = dz;
00972                                                 m.scale.x = .2;
00973                                                 m.scale.y = .2;
00974                                                 m.scale.z = .2;
00975                                                 m.color.a = 1;
00976                                                 m.color.g = 1;
00977                                                 m.lifetime = ros::Duration(0.5);
00978                                                 markers_pub_.publish(m);
00979                                         }
00980 
00981                                         if(publish_people_markers_ ){
00982                                                 visualization_msgs::Marker m;
00983                                                 m.header.stamp = (*sf_iter)->time_;
00984                                                 m.header.frame_id = fixed_frame;
00985                                                 m.ns = "TEXT";
00986                                                 m.id = i;
00987                                                 m.type = m.TEXT_VIEW_FACING;
00988                                                 m.pose.position.x = dx;
00989                                                 m.pose.position.y = dy;
00990                                                 m.pose.position.z = dz;
00991                                                 m.pose.orientation.w = 1.0;
00992                                                 m.text = (*sf_iter)->object_id.c_str();
00993                                                 m.scale.z = 0.3;
00994                                                 m.color.a = 1;
00995                                                 m.color.r = 0.5;
00996                                                 m.color.g = 0.5;
00997                                                 m.lifetime = ros::Duration(0.5);
00998                                                 markers_pub_.publish(m);
00999                                         }
01000                                         
01001 
01002 
01003 
01004 
01005 
01006 
01007 
01008 
01009 
01010 
01011 
01012 
01013 
01014 
01015 
01016 
01017 
01018 
01019 
01020 
01021 
01022 
01023 
01024 
01025                                 }
01026                         }
01027                 }
01028                 cob_perception_msgs::PositionMeasurementArray array;
01029                 array.header.stamp = ros::Time::now();
01030                 array.header.frame_id = fixed_frame;
01031 
01032                 if(publish_legs_){
01033                         array.people = legs;
01034                         leg_measurements_pub_.publish(array);
01035                 }
01036 
01037                 if(publish_people_){
01038                         array.people = people;
01039                         people_measurements_pub_.publish(array);
01040                 }
01041         }
01042 
01043 
01044         double distance( list<SavedFeature*>::iterator it1,  list<SavedFeature*>::iterator it2)
01045         {
01046                 Stamped<Point> one = (*it1)->position_, two = (*it2)->position_;
01047                 double dx = one[0]-two[0], dy = one[1]-two[1], dz = one[2]-two[2];
01048                 return sqrt(dx*dx+dy*dy+dz*dz);
01049         }
01050 
01051 
01052         inline void PRINT_LIST  (list<SavedPersonFeature*>& coll, const char* optcstr="")
01053         {
01054                 std::cout << optcstr;
01055                 for (   list<SavedPersonFeature*>::iterator it =coll.begin();it !=coll.end(); ++it) {
01056                         std::cout << (*it)->person_name << ' ';
01057                 }
01058                 std::cout << std::endl;
01059         }
01060 
01061 
01062         void pairLegs()
01063         {
01064                 
01065                 list<SavedFeature*>::iterator begin = saved_features_.begin();
01066                 list<SavedFeature*>::iterator end = saved_features_.end();
01067                 list<SavedFeature*>::iterator leg1, leg2, best, it;
01068 
01069                 for (leg1 = begin; leg1 != end; ++leg1){
01070                         
01071                         if ((*leg1)->object_id == "")
01072                                 continue;
01073 
01074                         leg2 = end;
01075                         best = end;
01076                         
01077 
01078                         double closest_dist = leg_pair_separation_m;
01079                         for ( it = begin; it != end; ++it){
01080                                 if(it==leg1) continue;
01081 
01082                                 if ( (*it)->object_id == (*leg1)->object_id ) {
01083                                         leg2 = it;
01084                                         break;
01085                                 }
01086 
01087                                 if ((*it)->object_id != "")
01088                                         continue;
01089 
01090                                 double d = distance(it, leg1);
01091                                 if (((*it)->getLifetime() <= max_second_leg_age_s)
01092                                                 && (d < closest_dist)){
01093                                         closest_dist = d;
01094                                         best = it;
01095                                 }
01096                         }
01097 
01098                         if(leg2 != end){
01099                                 double dist_between_legs = distance(leg1, leg2);
01100                                 if (dist_between_legs > leg_pair_separation_m){
01101                                         (*leg1)->object_id = "";
01102                                         (*leg1)->other = NULL;
01103                                         (*leg2)->object_id = "";
01104                                         (*leg2)->other = NULL;
01105                                 }else{
01106                                         (*leg1)->other = *leg2;
01107                                         (*leg2)->other = *leg1;
01108                                 }
01109                         }else if(best != end){
01110                                 (*best)->object_id = (*leg1)->object_id;
01111                                 (*leg1)->other = *best;
01112                                 (*best)->other = *leg1;
01113 
01114                         }
01115                 }
01116 
01117                 
01118                 for(;;){
01119                         list<SavedFeature*>::iterator best1 = end, best2 = end;
01120                         double closest_dist = leg_pair_separation_m;
01121 
01122                         for (leg1 = begin; leg1 != end; ++leg1){
01123                                 
01124                                 if ((*leg1)->object_id != ""
01125                                                 || (*leg1)->getReliability() < leg_reliability_limit_)
01126                                         continue;
01127 
01128                                 for ( leg2 = begin; leg2 != end; ++leg2){
01129                                         if(((*leg2)->object_id != "")
01130                                                         || ((*leg2)->getReliability() < leg_reliability_limit_)
01131                                                         || (leg1==leg2)) continue;
01132 
01133                                         double d = distance(leg1, leg2);
01134 
01135                                         if(d < closest_dist){
01136                                                 best1 = leg1;
01137                                                 best2 = leg2;
01138                                         }
01139                                 }
01140                         }
01141 
01142                         if(best1 != end){
01143                                 char id[100];
01144                                 float number = next_p_id_;
01145                                 snprintf(id,100,"Person%d", next_p_id_++);
01146                                 (*best1)->object_id = std::string(id);
01147                                 (*best2)->object_id = std::string(id);
01148                                 (*best1)->other = *best2;
01149                                 (*best2)->other = *best1;
01150                         }else{
01151                                 break;
01152                         }
01153                 }
01154         }
01155 };
01156 
01157 int main(int argc, char **argv)
01158 {
01159         ros::init(argc, argv,"leg_detection");
01160         g_argc = argc;
01161         g_argv = argv;
01162         ros::NodeHandle nh;
01163         LegDetector ld(nh);
01164         ROS_INFO("Execute main");
01165         ros::spin();
01166 
01167         return 0;
01168 }