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 }