$search
00001 00002 00003 #include "ros/ros.h" 00004 00005 #include "laser_processor.h" 00006 #include "calc_leg_features.h" 00007 00008 #include "opencv/cxcore.h" 00009 #include "opencv/cv.h" 00010 #include "opencv/ml.h" 00011 00012 //#include "rosrecord/Player.h" 00013 //#include "rosbag/bag.h" 00014 00015 #include "srs_msgs/PositionMeasurement.h" 00016 #include "srs_msgs/HS_distance.h" 00017 00018 #include "sensor_msgs/LaserScan.h" 00019 #include "std_msgs/Header.h" 00020 00021 #include "tf/transform_listener.h" 00022 #include "tf/message_filter.h" 00023 #include "message_filters/subscriber.h" 00024 00025 #include "srs_people_tracking_filter/tracker_kalman.h" 00026 //#include "srs_people_tracking_filter/tracker_particle.h" // particle 00027 #include "srs_people_tracking_filter/gaussian_pos_vel.h" 00028 00029 #include "srs_people_tracking_filter/state_pos_vel.h" 00030 #include "srs_people_tracking_filter/rgb.h" 00031 00032 #include <algorithm> 00033 00034 00035 //#include "actionlib/client/simple_action_client.h" - prevously used to pause the DM no longer needed 00036 //#include "srs_decision_making/ExecutionAction.h" 00037 00038 #include "nav_msgs/OccupancyGrid.h" 00039 #include "nav_msgs/GetMap.h" 00040 00041 // services 00042 #include <srs_leg_detector/DetectLegs.h> 00043 00044 //typedef actionlib::SimpleActionClient <srs_decision_making::ExecutionAction> Client; - pausing no longer needed 00045 00046 using namespace std; 00047 using namespace laser_processor; 00048 using namespace ros; 00049 using namespace tf; 00050 using namespace estimation; 00051 using namespace BFL; 00052 using namespace MatrixWrapper; 00053 00054 00055 static const double no_observation_timeout_s = 0.7; 00056 static const double max_second_leg_age_s = 2.0; 00057 static const double max_track_jump_m = 1; //1.0; 00058 static const double max_meas_jump_m = 1; //0.75; // 1.0 00059 static const double leg_pair_separation_m = 0.5; 00060 //static const string fixed_frame = "odom_combined"; 00061 static const string fixed_frame = "/map"; 00062 00063 static const double det_dist__for_pause = 0.5; // the distance to the person when the robot decides to pause 00064 static const double det_dist__for_resume = 2.5; // the distance to the person when the robot decides to resume 00065 // 00066 //static const unsigned int num_particles=100; // particle 00067 00068 00069 00070 00071 00072 class SavedFeature 00073 { 00074 public: 00075 static int nextid; 00076 TransformListener& tfl_; 00077 00078 BFL::StatePosVel sys_sigma_; 00079 TrackerKalman filter_; 00080 //TrackerParticle filter_; // particle 00081 00082 string id_; 00083 string object_id; 00084 ros::Time time_; 00085 ros::Time meas_time_; 00086 00087 Stamped<Point> position_; 00088 float dist_to_person_; 00089 00090 // leg tracker 00091 SavedFeature(Stamped<Point> loc, TransformListener& tfl) 00092 : tfl_(tfl), 00093 sys_sigma_(Vector3(0.05, 0.05, 0.05), Vector3(1.0, 1.0, 1.0)), 00094 filter_("tracker_name",sys_sigma_) 00095 // filter_("tracker_name",num_particles,sys_sigma_) // particle 00096 { 00097 char id[100]; 00098 snprintf(id,100,"legtrack%d", nextid++); 00099 id_ = std::string(id); 00100 00101 object_id = ""; 00102 time_ = loc.stamp_; 00103 meas_time_ = loc.stamp_; 00104 00105 try { 00106 tfl_.transformPoint(fixed_frame, loc, loc); 00107 } catch(...) { 00108 ROS_WARN("TF exception spot 6."); 00109 } 00110 StampedTransform pose( btTransform(Quaternion(0.0, 0.0, 0.0, 1.0), loc), loc.stamp_, id_, loc.frame_id_); 00111 tfl_.setTransform(pose); 00112 00113 StatePosVel prior_sigma(Vector3(0.1,0.1,0.1), Vector3(0.0000001, 0.0000001, 0.0000001)); 00114 // cout<<loc.m_floats[0]<<", "<<loc.m_floats[1]<<","<<loc.m_floats[2]<<endl; 00115 filter_.initialize(loc, prior_sigma, time_.toSec()); 00116 00117 StatePosVel est; 00118 filter_.getEstimate(est); 00119 00120 updatePosition(); 00121 } 00122 00123 void propagate(ros::Time time) 00124 { 00125 time_ = time; 00126 00127 filter_.updatePrediction(time.toSec()); 00128 00129 updatePosition(); 00130 } 00131 00132 void update(Stamped<Point> loc) 00133 { 00134 StampedTransform pose( btTransform(Quaternion(0.0, 0.0, 0.0, 1.0), loc), loc.stamp_, id_, loc.frame_id_); 00135 tfl_.setTransform(pose); 00136 00137 meas_time_ = loc.stamp_; 00138 time_ = meas_time_; 00139 00140 SymmetricMatrix cov(3); 00141 cov = 0.0; 00142 cov(1,1) = 0.0025; 00143 cov(2,2) = 0.0025; 00144 cov(3,3) = 0.0025; 00145 00146 filter_.updateCorrection(loc, cov); 00147 00148 updatePosition(); 00149 } 00150 00151 double getLifetime() 00152 { 00153 return filter_.getLifetime(); 00154 } 00155 00156 private: 00157 void updatePosition() 00158 { 00159 StatePosVel est; 00160 filter_.getEstimate(est); 00161 00162 position_[0] = est.pos_[0]; 00163 position_[1] = est.pos_[1]; 00164 position_[2] = est.pos_[2]; 00165 position_.stamp_ = time_; 00166 position_.frame_id_ = fixed_frame; 00167 } 00168 }; 00169 00170 int SavedFeature::nextid = 0; 00171 00172 00173 00174 00175 00176 class Legs 00177 { 00178 public: 00179 Stamped<Point> loc_; 00180 string type_; 00181 Legs(Stamped<Point> loc, string type) 00182 : loc_(loc) 00183 , type_(type) 00184 {}; 00185 00186 }; 00187 00188 class Pair 00189 { 00190 public: 00191 Point pos1_; 00192 Point pos2_; 00193 float dist_sep_m; 00194 Pair(Point pos1,Point pos2,float dist) 00195 :pos1_(pos1) 00196 ,pos2_(pos2) 00197 ,dist_sep_m(dist) 00198 {}; 00199 }; 00200 00201 class MatchedFeature 00202 { 00203 public: 00204 Legs* candidate_; 00205 SavedFeature* closest_; 00206 float distance_; 00207 00208 MatchedFeature(Legs* candidate, SavedFeature* closest, float distance) 00209 : candidate_(candidate) 00210 , closest_(closest) 00211 , distance_(distance) 00212 {} 00213 00214 inline bool operator< (const MatchedFeature& b) const 00215 { 00216 return (distance_ < b.distance_); 00217 } 00218 }; 00219 00220 00221 int g_argc; 00222 char** g_argv; 00223 string scan_topic = "scan_front"; 00224 00225 00226 00227 // actual legdetector node 00228 class LegDetector 00229 { 00230 00231 00232 // srs_decision_making::ExecutionGoal goal; // goal that will be sent to the actionserver - - pausing no longer needed 00233 00234 00235 bool pauseSent; 00236 int counter; 00237 srs_msgs::HS_distance distance_msg; 00238 00239 // Client client; // actionLib client for connection with DM action server - - pausing no longer needed 00240 00241 00242 ros::ServiceClient client_map; // clent for the getMap service 00243 nav_msgs::GetMap srv_map; 00244 00245 int ind_x, ind_y; 00246 00247 short int map_data []; 00248 00249 double tmp; 00250 00251 int indtmp; 00252 00253 00254 public: 00255 NodeHandle nh_; 00256 00257 TransformListener tfl_; 00258 00259 ScanMask mask_; 00260 00261 int mask_count_; 00262 00263 CvRTrees forest; 00264 00265 float connected_thresh_; 00266 00267 int feat_count_; 00268 00269 char save_[100]; 00270 00271 list<SavedFeature*> saved_features_; 00272 boost::mutex saved_mutex_; 00273 00274 int feature_id_; 00275 00276 // topics 00277 ros::Publisher leg_cloud_pub_ , leg_detections_pub_ , human_distance_pub_ ; //ROS topic publishers 00278 00279 ros::Publisher tracker_measurements_pub_; 00280 00281 message_filters::Subscriber<srs_msgs::PositionMeasurement> people_sub_; 00282 message_filters::Subscriber<sensor_msgs::LaserScan> laser_sub_; 00283 tf::MessageFilter<srs_msgs::PositionMeasurement> people_notifier_; 00284 tf::MessageFilter<sensor_msgs::LaserScan> laser_notifier_; 00285 00286 // services 00287 ros::ServiceServer service_server_detect_legs_; 00288 00289 // detections data for service_server_detect_legs_ service 00290 vector<geometry_msgs::Point32> detected_legs; 00291 00292 00293 00294 00295 00296 00297 00298 LegDetector(ros::NodeHandle nh) : 00299 nh_(nh), 00300 mask_count_(0), 00301 connected_thresh_(0.06), 00302 feat_count_(0), 00303 people_sub_(nh_,"people_tracker_filter",10), 00304 // //laser_sub_(nh_,"scan",10), 00305 laser_sub_(nh_,scan_topic,10), 00306 // laser_sub_(nh_,"scan_front",10), 00307 people_notifier_(people_sub_,tfl_,fixed_frame,10), 00308 laser_notifier_(laser_sub_,tfl_,fixed_frame,10), 00309 detected_legs () 00310 // client ("srs_decision_making_actions",true) - - pausing no longer needed 00311 00312 { 00313 00314 if (g_argc > 1) { 00315 forest.load(g_argv[1]); 00316 feat_count_ = forest.get_active_var_mask()->cols; 00317 printf("Loaded forest with %d features: %s\n", feat_count_, g_argv[1]); 00318 } else { 00319 printf("Please provide a trained random forests classifier as an input.\n"); 00320 shutdown(); 00321 } 00322 00323 // advertise topics 00324 // leg_cloud_pub_ = nh_.advertise<sensor_msgs::PointCloud>("kalman_filt_cloud",10); 00325 leg_cloud_pub_ = nh_.advertise<sensor_msgs::PointCloud>("tracked_people",10); 00326 leg_detections_pub_ = nh_.advertise<sensor_msgs::PointCloud>("leg_detections_cloud",10); 00327 tracker_measurements_pub_ = nh_.advertise<srs_msgs::PositionMeasurement>("people_tracker_measurements",1); 00328 human_distance_pub_= nh_.advertise<srs_msgs::HS_distance>("HS_distance",10); 00329 00330 // people_notifier_.registerCallback(boost::bind(&LegDetector::peopleCallback, this, _1)); 00331 people_notifier_.setTolerance(ros::Duration(0.01)); 00332 laser_notifier_.registerCallback(boost::bind(&LegDetector::laserCallback, this, _1)); 00333 laser_notifier_.setTolerance(ros::Duration(0.01)); 00334 00335 //services 00336 service_server_detect_legs_ = nh_.advertiseService("detect_legs", &LegDetector::detectLegsCallback, this); 00337 00338 00339 00340 feature_id_ = 0; 00341 pauseSent = false; 00342 counter = 1; 00343 00344 client_map = nh_.serviceClient<nav_msgs::GetMap>("/static_map"); // geting the clent for the map ready 00345 00346 if (client_map.call(srv_map)) { // call to srv_map OK 00347 printf ("The cells in the ocupancy grid with size %i are:\n", srv_map.response.map.data.size()); 00348 printf (" width %i are:\n", srv_map.response.map.info.width); 00349 printf (" height %i are:\n", srv_map.response.map.info.height); 00350 printf (" resolution %f is:\n", srv_map.response.map.info.resolution); 00351 geometry_msgs::Pose pose = srv_map.response.map.info.origin; 00352 printf (" x position is %f \n", pose.position.x); 00353 printf (" y position is %f \n", pose.position.y); 00354 printf (" z position is %f \n", pose.position.z); 00355 printf (" x orientation is %f \n", pose.orientation.x); 00356 printf (" y orientation is %f \n", pose.orientation.y); 00357 printf (" z orientation is %f \n", pose.orientation.z); 00358 printf (" w orientation is %f \n", pose.orientation.w); 00359 00360 00361 00362 // printing the map 00363 for (int i = 0 ; i<320 ; i++) { 00364 for (int k = 0; k<320 ; k++) { 00365 if (srv_map.response.map.data [i*320+k]<0) printf ("."); 00366 else if (srv_map.response.map.data [i*320+k]>=0 && srv_map.response.map.data [i*320+k]<100) printf ("#"); 00367 else if (srv_map.response.map.data [i*320+k]==100) printf ("@"); 00368 } 00369 printf ("\n"); 00370 } 00371 00372 } 00373 else 00374 { 00375 ROS_ERROR("Failed to call service GetMap"); 00376 } 00377 } 00378 00379 00380 ~LegDetector() 00381 { 00382 } 00383 00384 00385 // actionlib Pause Call 00386 bool sendActionLibGoalPause() 00387 { 00388 00389 return true; //- - pausing no longer needed 00390 00391 /* if (pauseSent) // Pause Action has been sent already 00392 return true; 00393 00394 00395 00396 00397 // Client client ("srs_decision_making_actions",true); 00398 00399 00400 if (!client.waitForServer(ros::Duration(10))) // ros::Duration(5) 00401 00402 00403 { 00404 printf(" Unable to establish connection with ActionServer in DM !!! Sending goals to DM when person is detected is disabled\n"); 00405 return false; 00406 } 00407 00408 00409 // goal.action="pause"; - - pausing no longer needed 00410 // goal.parameter=""; - - pausing no longer needed 00411 // goal.priority=counter++; -- - pausing no longer needed 00412 // client.sendGoal(goal); - - pausing no longer needed 00413 pauseSent = true; 00414 //wait for the action to return 00415 bool finished_before_timeout = client.waitForResult(ros::Duration(2)); 00416 00417 if (finished_before_timeout) 00418 { 00419 actionlib::SimpleClientGoalState state = client.getState(); 00420 ROS_INFO("Action call to DM finished with state: %s",state.toString().c_str()); 00421 return true; 00422 } 00423 else 00424 ROS_INFO("Action call to DM did not finish before timeout"); 00425 00426 return false; 00427 */ 00428 } 00429 00430 00431 00432 00433 // alerts when the distance is bigger that a specified treshold 00434 void measure_distance (double dist) { 00435 printf ("Distance %f \n" , dist); // the distance to the detected human 00436 00437 distance_msg.distance = dist*100; 00438 human_distance_pub_.publish(distance_msg); 00439 00440 if ( !pauseSent && dist < det_dist__for_pause ) 00441 { 00442 printf ("Local user too close ! Sending Pause ActionLibGoal to the server. Waiting for Action server responce \n"); 00443 sendActionLibGoalPause(); 00444 } 00445 else if ( dist > det_dist__for_resume && pauseSent ) { 00446 printf ("Local user is far away now ! Sending Resume ActionLibGoal to the server. Waiting for Action server responce \n"); 00447 sendActionLibGoalResume(); 00448 00449 } 00450 00451 } 00452 00453 // actionlib Resume Call 00454 bool sendActionLibGoalResume() 00455 { 00456 00457 return true; // pause no longer needed 00458 /* 00459 00460 if (!pauseSent ) // Resume Action has been sent already 00461 return true; 00462 00463 00464 00465 00466 00467 // Client client ("srs_decision_making_actions",true); 00468 00469 00470 if (!client.waitForServer()) // ros::Duration(5) 00471 00472 00473 { 00474 printf(" Unable to establish connection with ActionServer in DM !!! Sending goals to DM when person is detected is disabled\n"); 00475 return false; 00476 } 00477 00478 00479 goal.action="resume"; 00480 goal.parameter=""; 00481 goal.priority=counter++; 00482 client.sendGoal(goal); 00483 pauseSent = false; 00484 //wait for the action to return 00485 bool finished_before_timeout = client.waitForResult(ros::Duration(2)); 00486 00487 if (finished_before_timeout) 00488 { 00489 actionlib::SimpleClientGoalState state = client.getState(); 00490 ROS_INFO("Action call to DM finished with state: %s",state.toString().c_str()); 00491 return true; 00492 } 00493 else 00494 ROS_INFO("Action call to DM did not finish before timeout"); 00495 00496 return false; 00497 */ 00498 00499 } 00500 00501 00502 00503 // calback for the DetectLegs service 00504 bool detectLegsCallback(srs_leg_detector::DetectLegs::Request &req, srs_leg_detector::DetectLegs::Response &res) 00505 { 00506 00507 00508 res.leg_list.header.stamp = ros::Time::now(); 00509 00510 00511 geometry_msgs::Point32 pt1,pt2,pt3,pt4; 00512 00513 pt1.x=2.0; pt1.y=2.0; 00514 pt2.x=-2.0; pt2.y=2.0; 00515 pt3.x=2.0; pt3.y=-2.0; 00516 pt4.x=-2.0; pt4.y=-2.0; 00517 00518 //res.leg_list.points = detected_legs; 00519 res.leg_list.points.push_back(pt1); 00520 res.leg_list.points.push_back(pt2); 00521 res.leg_list.points.push_back(pt3); 00522 res.leg_list.points.push_back(pt4); 00523 00524 return true; 00525 } 00526 00527 00528 00529 void laserCallback(const sensor_msgs::LaserScan::ConstPtr& scan) 00530 { 00531 geometry_msgs::Point32 pt_temp; // used in building the detected_legs vector 00532 detected_legs.clear(); //to be ready for the new detections 00533 float map_value; 00534 ScanProcessor processor(*scan, mask_); 00535 00536 processor.splitConnected(connected_thresh_); 00537 processor.removeLessThan(5); 00538 00539 CvMat* tmp_mat = cvCreateMat(1,feat_count_,CV_32FC1); 00540 00541 // if no measurement matches to a tracker in the last <no_observation_timeout> seconds: erase tracker 00542 ros::Time purge = scan->header.stamp + ros::Duration().fromSec(-no_observation_timeout_s); 00543 list<SavedFeature*>::iterator sf_iter = saved_features_.begin(); 00544 while (sf_iter != saved_features_.end()) 00545 { 00546 if ((*sf_iter)->meas_time_ < purge) 00547 { 00548 delete (*sf_iter); 00549 saved_features_.erase(sf_iter++); 00550 } 00551 else 00552 ++sf_iter; 00553 } 00554 00555 00556 // System update of trackers, and copy updated ones in propagate list 00557 list<SavedFeature*> propagated; 00558 for (list<SavedFeature*>::iterator sf_iter = saved_features_.begin(); 00559 sf_iter != saved_features_.end(); 00560 sf_iter++) 00561 { 00562 (*sf_iter)->propagate(scan->header.stamp); 00563 propagated.push_back(*sf_iter); 00564 } 00565 00566 // Detection step: build up the set of leg candidates clusters 00567 list<SampleSet*> leg_candidates; 00568 for (list<SampleSet*>::iterator i = processor.getClusters().begin(); 00569 i != processor.getClusters().end(); 00570 i++) 00571 { 00572 vector<float> f = calcLegFeatures(*i, *scan); 00573 00574 for (int k = 0; k < feat_count_; k++) 00575 tmp_mat->data.fl[k] = (float)(f[k]); 00576 00577 if (forest.predict( tmp_mat ) > 0) 00578 { 00579 leg_candidates.push_back(*i); // adds a new element 00580 } 00581 } 00582 // build list of positions 00583 list<Point> positions; 00584 for (list<SampleSet*>::iterator i = leg_candidates.begin(); 00585 i != leg_candidates.end(); 00586 i++) 00587 { 00588 Point pos=(*i)->center(); 00589 positions.push_back(pos); 00590 00591 measure_distance ((*i)->center().distance(Point(0,0,0))); // measures the distance from the robot to the detected human and pause if needed 00592 00593 00594 00595 00596 } 00597 00598 // Build up the set of pair of closest positions 00599 list<Pair*> candidates; 00600 00601 00602 while (positions.size()!=0){ 00603 if (positions.size()==1){ 00604 list<Point>::iterator it1=positions.begin(); 00605 00606 list<Pair*>::iterator new_c=candidates.insert(candidates.end(),new Pair((*it1),(*it1),float(0))); 00607 00608 positions.erase(it1); 00609 00610 } 00611 else{ 00612 list<Point>::iterator it1=positions.begin(); 00613 list<Point>::iterator it2=it1; 00614 ++it2; 00615 00616 float closest_dist; 00617 closest_dist=(*it1).distance(*it2); 00618 00619 float dist; 00620 list<Point>::iterator it3; 00621 it3=it2; 00622 ++it2; 00623 for (;it2!= positions.end();it2++){ 00624 dist=(*it1).distance(*it2); 00625 00626 if (dist<closest_dist){ 00627 closest_dist=dist; 00628 it3=it2; 00629 } 00630 } 00631 00632 list<Pair*>::iterator new_c=candidates.insert(candidates.end(),new Pair((*it1),(*it3),closest_dist)); 00633 positions.erase(it1); 00634 positions.erase(it3); 00635 00636 } 00637 00638 } 00639 00640 //Build the set of pair of legs and single legs 00641 list<Legs*> legs; 00642 00643 for(list<Pair*>::iterator i = candidates.begin();i != candidates.end();i++){ 00644 00645 if((*i)->dist_sep_m==0){ 00646 Stamped<Point> loc1((*i)->pos1_,scan->header.stamp, scan->header.frame_id); 00647 list<Legs*>::iterator new_pair=legs.insert(legs.end(),new Legs(loc1,"single")); 00648 00649 } else { 00650 if ((*i)->dist_sep_m<=leg_pair_separation_m){ 00651 Stamped<Point> loc((((*i)->pos1_).operator +=((*i)->pos2_)).operator /=(btScalar(2)),scan->header.stamp, scan->header.frame_id); 00652 list<Legs*>::iterator new_pair=legs.insert(legs.end(),new Legs(loc,"pair")); 00653 } 00654 else{ 00655 Stamped<Point> loc1((*i)->pos1_,scan->header.stamp, scan->header.frame_id); 00656 Stamped<Point> loc2((*i)->pos2_,scan->header.stamp, scan->header.frame_id); 00657 list<Legs*>::iterator new_s=legs.insert(legs.end(),new Legs(loc1,"single")); 00658 new_s=legs.insert(legs.end(),new Legs(loc2,"single")); 00659 } 00660 } 00661 00662 } 00663 00664 00665 // For each candidate, find the closest tracker (within threshold) and add to the match list 00666 // If no tracker is found, start a new one 00667 multiset<MatchedFeature> matches; 00668 00669 vector<geometry_msgs::Point32> detections_visualize(legs.size()); // used to visuallise the leg candidates 00670 00671 int i = 0; 00672 for (list<Legs*>::iterator cf_iter = legs.begin();cf_iter != legs.end(); cf_iter++,i++) { 00673 00674 Stamped<Point> loc=(*cf_iter)->loc_; 00675 try { 00676 tfl_.transformPoint(fixed_frame, loc, loc); 00677 } catch(...) { 00678 ROS_WARN("TF exception spot 3."); 00679 } 00680 00681 // int y111 = (*loc); 00682 00683 00684 00685 00686 00687 ind_x = (loc[0] / srv_map.response.map.info.resolution + srv_map.response.map.info.width / 2); //x index in the ocupancy map 00688 ind_y = (loc[1] / srv_map.response.map.info.resolution + srv_map.response.map.info.height / 2); //y index in the ocupancy map 00689 00690 indtmp = ind_y*160+ind_x; //printing for checking 00691 printf ("map index: %i \n",indtmp ); 00692 00693 printf ( "map x: %f, map y: %f, index_x: %i, index_y:%i, comb index:%i ",loc[0], loc[1], ind_x , ind_y, ind_y*160+ind_x ); 00694 map_value = srv_map.response.map.data [ind_y*160+ind_x]; 00695 printf ("map_value: %f \n",map_value); 00696 00697 if (map_value == 100) { 00698 printf ("the point is on occupied cell of the map \n"); 00699 } 00700 00701 if (map_value < 0) { 00702 printf ("the point is outside the map \n"); 00703 } 00704 00705 if (map_value > 0 && map_value < 100) { 00706 printf ("GOOD - the point is inside the map \n"); 00707 if (pauseSent) 00708 00709 detections_visualize[i].z=1.0; 00710 00711 else 00712 00713 detections_visualize[i].z=0.0; 00714 00715 00716 } else { 00717 detections_visualize[i].z =-1.0; 00718 } 00719 00720 00721 00722 00723 detections_visualize[i].x = loc[0]; 00724 detections_visualize[i].y = loc[1]; 00725 00726 00727 00728 00729 00730 list<SavedFeature*>::iterator closest = propagated.end(); 00731 float closest_dist = max_track_jump_m; 00732 00733 for (list<SavedFeature*>::iterator pf_iter = propagated.begin(); 00734 pf_iter != propagated.end(); 00735 pf_iter++) 00736 { 00737 // find the closest distance between candidate and trackers 00738 float dist = loc.distance((*pf_iter)->position_); 00739 if ( dist < closest_dist ) 00740 { 00741 closest = pf_iter; 00742 closest_dist = dist; 00743 } 00744 } 00745 // Nothing close to it, start a new track 00746 if (closest == propagated.end()) 00747 { 00748 list<SavedFeature*>::iterator new_saved = saved_features_.insert(saved_features_.end(), new SavedFeature(loc, tfl_)); 00749 } 00750 // Add the candidate, the tracker and the distance to a match list 00751 else 00752 matches.insert(MatchedFeature(*cf_iter,*closest,closest_dist)); 00753 } 00754 00755 00756 00757 00758 // loop through _sorted_ matches list 00759 // find the match with the shortest distance for each tracker 00760 while (matches.size() > 0) 00761 { 00762 multiset<MatchedFeature>::iterator matched_iter = matches.begin(); 00763 bool found = false; 00764 list<SavedFeature*>::iterator pf_iter = propagated.begin(); 00765 while (pf_iter != propagated.end()) 00766 { 00767 // update the tracker with this candidate 00768 if (matched_iter->closest_ == *pf_iter) 00769 { 00770 // Transform candidate to fixed frame 00771 Stamped<Point> loc(matched_iter->candidate_->loc_, scan->header.stamp, scan->header.frame_id); 00772 try { 00773 tfl_.transformPoint(fixed_frame, loc, loc); 00774 } catch(...) { 00775 ROS_WARN("TF exception spot 4."); 00776 } 00777 00778 // Update the tracker with the candidate location 00779 matched_iter->closest_->update(loc); 00780 00781 // remove this match and 00782 matches.erase(matched_iter); 00783 propagated.erase(pf_iter++); 00784 found = true; 00785 break; 00786 } 00787 // still looking for the tracker to update 00788 else 00789 { 00790 pf_iter++; 00791 } 00792 } 00793 00794 // didn't find tracker to update, because it was deleted above 00795 // try to assign the candidate to another tracker 00796 if (!found) 00797 { 00798 Stamped<Point> loc(matched_iter->candidate_->loc_, scan->header.stamp, scan->header.frame_id); 00799 try { 00800 tfl_.transformPoint(fixed_frame, loc, loc); 00801 } catch(...) { 00802 ROS_WARN("TF exception spot 5."); 00803 } 00804 00805 list<SavedFeature*>::iterator closest = propagated.end(); 00806 float closest_dist = max_track_jump_m; 00807 00808 for (list<SavedFeature*>::iterator remain_iter = propagated.begin(); 00809 remain_iter != propagated.end(); 00810 remain_iter++) 00811 { 00812 float dist = loc.distance((*remain_iter)->position_); 00813 if ( dist < closest_dist ) 00814 { 00815 closest = remain_iter; 00816 closest_dist = dist; 00817 } 00818 } 00819 00820 // no tracker is within a threshold of this candidate 00821 // so create a new tracker for this candidate 00822 if (closest == propagated.end()) 00823 list<SavedFeature*>::iterator new_saved = saved_features_.insert(saved_features_.end(), new SavedFeature(loc, tfl_)); 00824 else 00825 matches.insert(MatchedFeature(matched_iter->candidate_,*closest,closest_dist)); 00826 matches.erase(matched_iter); 00827 } 00828 } 00829 00830 cvReleaseMat(&tmp_mat); tmp_mat = 0; 00831 00832 vector<geometry_msgs::Point32> filter_visualize(saved_features_.size()); 00833 00834 00835 vector<float> weights(saved_features_.size()); 00836 sensor_msgs::ChannelFloat32 channel; 00837 00838 i = 0; 00839 00840 for (list<SavedFeature*>::iterator sf_iter = saved_features_.begin(); 00841 sf_iter != saved_features_.end(); 00842 sf_iter++,i++) 00843 { 00844 // reliability 00845 StatePosVel est; 00846 (*sf_iter)->filter_.getEstimate(est); 00847 double reliability = fmin(1.0, fmax(0.1, est.vel_.length() / 0.5)); 00848 00849 // publish filter result 00850 00851 filter_visualize[i].x = est.pos_[0]; 00852 filter_visualize[i].y = est.pos_[1]; 00853 // filter_visualize[i].z = est.pos_[2]; 00854 if (pauseSent) 00855 filter_visualize[i].z=1.0; 00856 else 00857 filter_visualize[i].z=0.0; 00858 00859 00860 00861 00862 // fill up the detected_legs vector for later use 00863 00864 pt_temp.x = est.pos_[0]; 00865 pt_temp.y = est.pos_[1]; 00866 pt_temp.z = 0; 00867 00868 detected_legs.push_back(pt_temp); 00869 00870 00871 00872 weights[i] = *(float*)&(rgb[min(998, max(1, (int)trunc( reliability*999.0 )))]); 00873 00874 srs_msgs::PositionMeasurement pos; 00875 pos.header.stamp = (*sf_iter)->time_; 00876 pos.header.frame_id = fixed_frame; 00877 pos.name = "leg_detector"; 00878 pos.object_id = (*sf_iter)->object_id; 00879 pos.pos.x = est.pos_[0]; 00880 pos.pos.y = est.pos_[1]; 00881 pos.pos.z = est.pos_[2]; 00882 pos.covariance[0] = pow(0.3 / reliability,2.0); 00883 pos.covariance[1] = 0.0; 00884 pos.covariance[2] = 0.0; 00885 pos.covariance[3] = 0.0; 00886 pos.covariance[4] = pow(0.3 / reliability,2.0); 00887 pos.covariance[5] = 0.0; 00888 pos.covariance[6] = 0.0; 00889 pos.covariance[7] = 0.0; 00890 pos.covariance[8] = 10000.0; 00891 pos.initialization = 0; 00892 00893 // If I've already seen this leg, publish its position. 00894 if ((*sf_iter)->object_id != "") 00895 tracker_measurements_pub_.publish(pos); 00896 } 00897 00898 // visualize all trackers 00899 00900 channel.name = "rgb"; 00901 channel.values = weights; 00902 sensor_msgs::PointCloud people_cloud; //from the filter 00903 sensor_msgs::PointCloud detections_cloud; //directly from detections 00904 00905 people_cloud.channels.push_back(channel); 00906 people_cloud.header.frame_id = fixed_frame;//scan_.header.frame_id; 00907 people_cloud.header.stamp = scan->header.stamp; 00908 people_cloud.points = filter_visualize; 00909 leg_cloud_pub_.publish(people_cloud); 00910 00911 detections_cloud.channels.push_back(channel); 00912 detections_cloud.header.frame_id = fixed_frame;//scan_.header.frame_id; 00913 detections_cloud.header.stamp = scan->header.stamp; 00914 detections_cloud.points = detections_visualize; 00915 leg_detections_pub_.publish(detections_cloud); 00916 00917 00918 00919 } 00920 00921 }; 00922 00923 00924 00925 00926 00927 int main(int argc, char **argv) 00928 { 00929 ros::init(argc, argv,"laser_processor"); 00930 g_argc = argc; 00931 g_argv = argv; 00932 00933 if (g_argc > 2) { 00934 scan_topic = g_argv[2]; 00935 00936 printf("Listening on topic %s : \n", g_argv[2]); 00937 } else { 00938 printf("Please provide the input topic as a parameter,e.g. scan_front. Assuming scan_front ! \n"); 00939 shutdown(); 00940 } 00941 00942 00943 00944 00945 00946 00947 00948 ros::NodeHandle nh; 00949 LegDetector ld(nh); 00950 00951 00952 ros::spin(); 00953 00954 00955 return 0; 00956 } 00957