leg_detector.cpp
Go to the documentation of this file.
00001 /*
00002  *****************************************************************
00003  * Copyright (c) 2015 \n
00004  * Fraunhofer Institute for Manufacturing Engineering
00005  * and Automation (IPA) \n\n
00006  *
00007  *****************************************************************
00008  *
00009  * \note
00010  * Project name: Care-O-bot
00011  * \note
00012  * ROS stack name: cob_people_perception
00013  * \note
00014  * ROS package name: cob_leg_detection
00015  *
00016  * \author
00017  * Author: Olha Meyer
00018  * \author
00019  * Supervised by: Richard Bormann
00020  *
00021  * \date Date of creation: 01.11.2014
00022  *
00023  * \brief
00024  * functions for detecting people within a scan data cloud
00025  * current approach: read the current scan data.
00026  * Assign each valid pair of detected legs to a person.
00027  *
00028  *****************************************************************
00029  *
00030  * Redistribution and use in source and binary forms, with or without
00031  * modification, are permitted provided that the following conditions are met:
00032  *
00033  * - Redistributions of source code must retain the above copyright
00034  * notice, this list of conditions and the following disclaimer. \n
00035  * - Redistributions in binary form must reproduce the above copyright
00036  * notice, this list of conditions and the following disclaimer in the
00037  * documentation and/or other materials provided with the distribution. \n
00038  * - Neither the name of the Fraunhofer Institute for Manufacturing
00039  * Engineering and Automation (IPA) nor the names of its
00040  * contributors may be used to endorse or promote products derived from
00041  * this software without specific prior written permission. \n
00042  *
00043  * This program is free software: you can redistribute it and/or modify
00044  * it under the terms of the GNU Lesser General Public License LGPL as
00045  * published by the Free Software Foundation, either version 3 of the
00046  * License, or (at your option) any later version.
00047  *
00048  * This program is distributed in the hope that it will be useful,
00049  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00050  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00051  * GNU Lesser General Public License LGPL for more details.
00052  *
00053  * You should have received a copy of the GNU Lesser General Public
00054  * License LGPL along with this program.
00055  * If not, see <http://www.gnu.org/licenses/>.
00056  *
00057  ****************************************************************/
00058 
00059  /*
00060   * Other Copyrights :
00061   *
00062 /*********************************************************************
00063  * Software License Agreement (BSD License)
00064  *
00065  *  Copyright (c) 2008, Willow Garage, Inc.
00066  *  All rights reserved.
00067  *
00068  *  Redistribution and use in source and binary forms, with or without
00069  *  modification, are permitted provided that the following conditions
00070  *  are met:
00071  *
00072  *   * Redistributions of source code must retain the above copyright
00073  *     notice, this list of conditions and the following disclaimer.
00074  *   * Redistributions in binary form must reproduce the above
00075  *     copyright notice, this list of conditions and the following
00076  *     disclaimer in the documentation and/or other materials provided
00077  *     with the distribution.
00078  *   * Neither the name of the Willow Garage nor the names of its
00079  *     contributors may be used to endorse or promote products derived
00080  *     from this software without specific prior written permission.
00081  *
00082  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00083  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00084  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00085  *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00086  *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00087  *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00088  *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00089  *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00090  *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00091  *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
00092  *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00093  *  POSSIBILITY OF SUCH DAMAGE.
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 ;  //2.0;
00142 static double max_track_jump_m         = 1.0; 
00143 static double max_meas_jump_m          = 0.75; // 1.0
00144 static double leg_pair_separation_m    = 0.50;  //1.0;
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  * INFO TO KF:
00158  *
00159  * the Kalman filter is a recursive optimization algorithm
00160  * that generates an estimate based upon potentially noisy
00161  * observation data.
00162  *
00163  * The estimation of the Kalman filter operates in two primary cycles, propagation and correction.
00164  * During the propagation cycle, the filter propagates the state of the system, using a system model
00165  * to predict the state of the system one time step in the future.
00166  *
00167  * The correction cycle inputs measurements of the system state and utilizes these observations to correct
00168  *  for differences between the state propagated from the system model and the measured satellite state.
00169  *  However, the correction cycle encounters particular difficulty due to the fact that some amount of noise
00170  *  and imprecision is embodied in the measurements themselves.
00171  *
00172  *  Additional INFO on:
00173  *  [http://www.usafa.edu/df/dfas/Papers/20042005/
00174  * Kalman%20Filtering%20and%20the%20Attitude%20Determination%20and%20Control%20Task%20-%20Hale.pdf]
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         //static int nextid;
00189         //TransformListener& tfl_;
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         // person tracker
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                 //P-Matrix = covariance matrix
00208                 //Q-Matrix = process noise covariance matrix
00209                 //F-Matrix = state matrix
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          * predicts parameter values ahead of current
00221          * measurements
00222          */
00223         void propagate(ros::Time time)
00224         {
00225                 time_ = time;
00226                 filter_.updatePrediction(time.toSec());
00227                 updatePosition();
00228         }
00229 
00230         /*
00231          * updates current values with correction:
00232          * estimates parameter values using future, current
00233          * and previous measurements
00234          */
00235         void update(Stamped<Point> loc, double probability)
00236         {
00237                 //float cov_meas = 0.05;
00238                 //float cov_meas = 0.0025;
00239                 meas_time_ = loc.stamp_;
00240                 time_ = meas_time_;
00241 
00242                 //R-Matrix
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          * time between prediction and correction:
00255          * lifetime of a tracker
00256          */
00257         double getLifetime()
00258         {
00259                 return filter_.getLifetime();
00260         }
00261 
00262         double getReliability()
00263         {
00264                 return reliability;
00265         }
00266 
00267 private:
00268         /*
00269          * estimates parameter values using current and
00270          * previous measurements
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         // one leg tracker
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 // actual legdetector node
00447 class LegDetector
00448 {
00449 public:
00450         NodeHandle nh_;
00451         TransformListener tfl_;
00452         //TransformListener tflp_;
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         //tf::MessageFilter<cob_perception_msgs::PositionMeasurementArray> people_notifier_;
00478         tf::MessageFilter<sensor_msgs::LaserScan> laser_notifier_;
00479 
00480         //list<cob_perception_msgs::PositionMeasurement*>saved_people_;
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                 // advertise topics
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                 //people_pub_ = nh_.advertise<cob_perception_msgs::PositionMeasurementArray>("people",0);
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                         //people_notifier_.setTargetFrame(fixed_frame);
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          * keeps tracking the same person after their name
00560          * with the help of a Kalman Filter. Determins the
00561          * current position and velocity and speed of a tracked person.
00562          */
00563         void peopleCallback(const cob_perception_msgs::PositionMeasurementArray::ConstPtr& people_meas)
00564         {
00565                 //ROS_INFO("start people callback");
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                 //if there are some people in memory list
00575                 if(saved_people_.size() != 0){
00576                         //predict distribution of error measurement values over the next time
00577                         // by a known correct state from the previous time ->
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                 //extracts the data from the comming message and saves new people in the list
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                         //if the list is empty, add the person to the list
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                                 //if the list is not empty, check for a person name in the list
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                                 //if there is no same name in the list, add the person to the list
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                 // Compare two lists:
00607                 // saved_people_ - global list over the time with current detected people
00608                 // saved_people  - temporary list within this message with the current detected people
00609 
00610                 //if the memory list of people is empty, put all new people on the list
00611                 // same people are excluded
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{ // if the memory list is not empty, check the list for the same people to update there values
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                                                 // update distribution over current state of values
00624                                                 //by known prediction of state and next measurements:
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                 //erase unnecessary tracks on people if they are called the same
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                 //publish data
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                         //ROS_INFO("Velocity [%f, %f, %f]}: ", (*sp_iter)->velocity_[0], (*sp_iter)->velocity_[1], (*sp_iter)->velocity_[2]);
00660                         cob_perception_msgs::Person person;
00661                         person.detector = detector_;
00662                         person.name = (*sp_iter)->person_name; // name of the person
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                         //m.scale.x = .4;
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                 //cob_perception_msgs::PositionMeasurementArray array;
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         //callback for laser data
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                 // if no measurement matches to a tracker in the last <no_observation_timeout>  seconds: erase tracker
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                 // System update of trackers, and copy updated ones in propagate list
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                 // Detection step: build up the set of "candidate" clusters
00737                 // For each candidate, find the closest tracker (within threshold) and add to the match list
00738                 // If no tracker is found, start a new one
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                                 // find the closest distance between candidate and trackers
00761                                 float dist = loc.distance((*pf_iter)->position_);
00762                                 if ( dist < closest_dist ){
00763                                         closest = pf_iter;
00764                                         closest_dist = dist;
00765                                 }
00766                         }
00767                         // Nothing close to it, start a new track
00768                         if (closest == propagated.end()){
00769                                 list<SavedFeature*>::iterator new_saved = saved_features_.insert(saved_features_.end(), new SavedFeature(loc, tfl_));
00770                         }else // Add the candidate, the tracker and the distance to a match list
00771                                 matches.insert(MatchedFeature(*i,*closest,closest_dist,probability));
00772                 }
00773 
00774                 // loop through _sorted_ matches list
00775                 // find the match with the shortest distance for each tracker
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                                 // update the tracker with this candidate
00782                                 if (matched_iter->closest_ == *pf_iter){
00783                                         // Transform candidate to fixed frame
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                                         // Update the tracker with the candidate location
00792                                         matched_iter->closest_->update(loc, matched_iter->probability_);
00793 
00794                                         // remove this match and
00795                                         matches.erase(matched_iter);
00796                                         propagated.erase(pf_iter++);
00797                                         found = true;
00798                                         break;
00799                                 }else{  // still looking for the tracker to update
00800                                         pf_iter++;
00801                                 }
00802                         }
00803 
00804                         // didn't find tracker to update, because it was deleted above
00805                         // try to assign the candidate to another tracker
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                                 // no tracker is within a threshold of this candidate
00826                                 // so create a new tracker for this candidate
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                 // if(!use_seeds_)
00837                 pairLegs();
00838 
00839                 // Publish Data!
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                         // reliability
00848                         double reliability = (*sf_iter)->getReliability();
00849                         //  ROS_INFO("reliability %f", reliability);
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                                         //ROS_INFO("Person %s with distance %f",  (*sf_iter)->object_id.c_str() , d);
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                                         //ROS_INFO("speed %f: ", speed );
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                                                 if (publish_people_markers_ ){
01002                                                         visualization_msgs::Marker m;
01003                                                         m.header.stamp = (*sf_iter)->time_;
01004                                                         m.header.frame_id = fixed_frame;
01005                                                         m.ns = "SPEED";
01006                                                         m.id = i;
01007                                                         m.type = m.ARROW;
01008                                                         m.pose.position.x = dx;
01009                                                         m.pose.position.y = dy;
01010                                                         m.pose.position.z = dz;
01011                                                         m.pose.orientation.x = vx;
01012                                                         m.pose.orientation.y = vy;
01013                                                         m.pose.orientation.z = vz;
01014 
01015                                                         m.scale.x = .4;
01016                                                         m.scale.y = .05;
01017                                                         m.scale.z = .05;
01018                                                         m.color.a = 1;
01019                                                         m.color.r = 1;
01020                                                         m.lifetime = ros::Duration(0.5);
01021 
01022                                                         markers_pub_.publish(m);
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                 // Deal With legs that already have ids
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                         // If this leg has no id, skip
01071                         if ((*leg1)->object_id == "")
01072                                 continue;
01073 
01074                         leg2 = end;
01075                         best = end;
01076                         // ROS_INFO("leg pair separation %f", leg_pair_separation_m);
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                 // Attempt to pair up legs with no id
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                                 // If this leg has an id or low reliability, skip
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 }


cob_leg_detection
Author(s): Caroline Pantofaru, Olha Meyer
autogenerated on Fri Aug 28 2015 10:24:01