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 #include <angles/angles.h>
00032 #include <boost/foreach.hpp>
00033 #include <boost/tuple/tuple.hpp>
00034 
00035 
00036 #include "collvoid_local_planner/ROSAgent.h"
00037 
00038 #include "collvoid_local_planner/orca.h"
00039 #include "collvoid_local_planner/collvoid_publishers.h"
00040 
00041 
00042 template <typename T>
00043 void getParam (const ros::NodeHandle nh, const std::string& name, T* place)
00044 {
00045   bool found = nh.getParam(name, *place);
00046   ROS_ASSERT_MSG (found, "Could not find parameter %s", name.c_str());
00047   ROS_DEBUG_STREAM_NAMED ("init", "Initialized " << name << " to " << *place);
00048 }
00049 
00050 
00051 template <class T>
00052 T getParamDef (const ros::NodeHandle nh, const std::string& name, const T& default_val)
00053 {
00054   T val;
00055   nh.param(name, val, default_val);
00056   ROS_DEBUG_STREAM_NAMED ("init", "Initialized " << name << " to " << val <<
00057                           "(default was " << default_val << ")");
00058   return val;
00059 }
00060 
00061 using namespace collvoid;
00062 
00063 namespace collvoid{
00064 
00065   ROSAgent::ROSAgent(){
00066     initialized_ = false;
00067     cur_allowed_error_ = 0;
00068     cur_loc_unc_radius_ = 0;
00069     min_dist_obst_ = DBL_MAX;
00070   }
00071   
00072   void ROSAgent::init(ros::NodeHandle private_nh, tf::TransformListener* tf){
00073     tf_ = tf;
00074     private_nh.param<std::string>("base_frame", base_frame_, "/base_link");
00075     private_nh.param<std::string>("global_frame", global_frame_, "/map");
00076 
00077     standalone_ = getParamDef(private_nh, "standalone", false);
00078    
00079     if (standalone_) {
00080       ros::NodeHandle nh;
00081       id_ = nh.getNamespace();
00082       if (strcmp(id_.c_str(), "/") == 0) {
00083         char hostname[1024];
00084         hostname[1023] = '\0';
00085         gethostname(hostname,1023); 
00086         id_ = std::string(hostname);
00087       }
00088       ROS_INFO("Standalone My name is: %s",id_.c_str());
00089       controlled_ = false;
00090       ros::Duration(2.0).sleep();
00091       initCommon(nh);
00092     }
00093     else {
00094       id_ = private_nh.getNamespace();
00095       if (strcmp(id_.c_str(), "/") == 0) {
00096         char hostname[1024];
00097         hostname[1023] = '\0';
00098         gethostname(hostname,1023); 
00099         id_ = std::string(hostname);
00100       }
00101       ROS_INFO("My name is: %s",id_.c_str());
00102       controlled_ = false;
00103       initCommon(private_nh);
00104     }
00105     getParam(private_nh,"footprint_radius",&footprint_radius_);
00106 
00107     radius_ = footprint_radius_;
00108     
00109     geometry_msgs::PolygonStamped footprint;
00110     geometry_msgs::Point32 p;
00111     double angle = 0;
00112     double step = 2 * M_PI / 72;
00113     while(angle < 2 * M_PI){
00114       geometry_msgs::Point32 pt;
00115       pt.x = radius_ * cos(angle);
00116       pt.y = radius_ * sin(angle);
00117       pt.z = 0.0;
00118       footprint.polygon.points.push_back(pt);
00119       angle += step;
00120     }
00121     setFootprint(footprint);
00122     
00123     eps_= getParamDef(private_nh, "eps", 0.1);
00124     getParam(private_nh, "convex", &convex_);
00125     getParam(private_nh, "holo_robot",&holo_robot_);
00126     
00127 
00128     publish_positions_period_ = getParamDef(private_nh,"publish_positions_frequency",10.0);
00129     publish_positions_period_ = 1.0 / publish_positions_period_;
00130     
00131     publish_me_period_ = getParamDef(private_nh,"publish_me_frequency",10.0);
00132     publish_me_period_ = 1.0/publish_me_period_;
00133     
00134     if (standalone_) {
00135       
00136     }
00137 
00138     initialized_ = true;
00139 
00140   }
00141 
00142 
00143   void ROSAgent::initParams(ros::NodeHandle private_nh) {
00144     getParam(private_nh,"max_vel_with_obstacles", &max_vel_with_obstacles_);
00145     getParam(private_nh,"max_vel_x", &max_vel_x_);
00146     getParam(private_nh,"min_vel_x", &min_vel_x_);
00147     getParam(private_nh,"max_vel_y", &max_vel_y_);
00148     getParam(private_nh,"min_vel_y", &min_vel_y_);
00149     getParam(private_nh,"max_vel_th", &max_vel_th_);
00150     getParam(private_nh,"min_vel_th", &min_vel_th_);
00151     getParam(private_nh,"min_vel_th_inplace", &min_vel_th_inplace_);
00152 
00153     time_horizon_obst_ = getParamDef(private_nh,"time_horizon_obst",10.0);
00154     time_to_holo_ = getParamDef(private_nh,"time_to_holo", 0.4);
00155     min_error_holo_ = getParamDef(private_nh,"min_error_holo", 0.01);
00156     max_error_holo_ = getParamDef(private_nh, "max_error_holo", 0.15);
00157     delete_observations_ = getParamDef(private_nh, "delete_observations", true);
00158     threshold_last_seen_ = getParamDef(private_nh,"threshold_last_seen",1.0);
00159    
00160     getParam(private_nh, "orca", &orca_);
00161     getParam(private_nh, "clearpath", &clearpath_);
00162     getParam(private_nh, "use_truncation", &use_truncation_);
00163     
00164     num_samples_ = getParamDef(private_nh, "num_samples", 400);
00165     type_vo_ = getParamDef(private_nh, "type_vo", 0); 
00166 
00167     trunc_time_ = getParamDef(private_nh,"trunc_time",10.0);
00168     left_pref_ = getParamDef(private_nh,"left_pref",0.1);
00169   }
00170 
00171 
00172   void ROSAgent::initAsMe(tf::TransformListener* tf){
00173     
00174     tf_ = tf;
00175     controlled_ = true;
00176     ros::NodeHandle nh;
00177     getParam(nh, "move_base/use_obstacles", &use_obstacles_);
00178     controlled_ = getParamDef(nh,"move_base/controlled", true);
00179     initCommon(nh);
00180     initialized_ = true;
00181   }
00182  
00183   void ROSAgent::initCommon(ros::NodeHandle nh){
00184     
00185     vo_pub_ = nh.advertise<visualization_msgs::Marker>("vo", 1);
00186     neighbors_pub_ = nh.advertise<visualization_msgs::MarkerArray>("neighbors", 1);
00187     me_pub_ = nh.advertise<visualization_msgs::MarkerArray>("me", 1);
00188     lines_pub_ = nh.advertise<visualization_msgs::Marker>("orca_lines", 1);
00189     samples_pub_ = nh.advertise<visualization_msgs::MarkerArray>("samples", 1);
00190     polygon_pub_ = nh.advertise<geometry_msgs::PolygonStamped>("convex_hull",1);
00191     speed_pub_ = nh.advertise<visualization_msgs::Marker>("speed",1);
00192     position_share_pub_ = nh.advertise<collvoid_msgs::PoseTwistWithCovariance>("/position_share_out",1);
00193 
00194     obstacles_pub_ = nh.advertise<visualization_msgs::Marker>("obstacles", 1);
00195 
00196 
00197     
00198     amcl_posearray_sub_ = nh.subscribe("particlecloud_weighted", 1, &ROSAgent::amclPoseArrayWeightedCallback,this);
00199     position_share_sub_ = nh.subscribe("/position_share_in",10, &ROSAgent::positionShareCallback, this);
00200     odom_sub_ = nh.subscribe("odom",1, &ROSAgent::odomCallback, this);
00201 
00202 
00203     laser_scan_sub_.subscribe (nh, "base_scan", 1);
00204     laser_notifier.reset(new tf::MessageFilter<sensor_msgs::LaserScan>(laser_scan_sub_, *tf_, global_frame_, 10));
00205 
00206     laser_notifier->registerCallback(boost::bind(&ROSAgent::baseScanCallback, this, _1));
00207     laser_notifier->setTolerance(ros::Duration(0.1));
00208     
00209     
00210 
00211     ROS_INFO("New Agent as me initialized");
00212  
00213   }
00214 
00215   void ROSAgent::computeNewVelocity(Vector2 pref_velocity, geometry_msgs::Twist& cmd_vel){
00216     boost::mutex::scoped_lock lock(me_lock_);
00217     
00218     setAgentParams(this);
00219     updateAllNeighbors();
00220 
00221     new_velocity_ = Vector2(0.0,0.0);
00222 
00223     additional_orca_lines_.clear();
00224     vo_agents_.clear();
00225 
00226     
00227     double min_dist_neigh = DBL_MAX;
00228     if (agent_neighbors_.size() > 0)
00229       min_dist_neigh =  collvoid::abs(agent_neighbors_[0]->position_ - position_);
00230 
00231     double min_dist = std::min(min_dist_neigh, min_dist_obst_);
00232     
00233     
00234     max_speed_x_ = max_vel_x_;
00235 
00236     if (!holo_robot_) {
00237       addNHConstraints(min_dist, pref_velocity);
00238     }
00239     
00240     addAccelerationConstraintsXY(max_vel_x_,acc_lim_x_, max_vel_y_, acc_lim_y_, velocity_, heading_, sim_period_, holo_robot_, additional_orca_lines_);
00241 
00242     computeObstacles();
00243     
00244     if (orca_){
00245       computeOrcaVelocity(pref_velocity);
00246     }
00247     else {
00248       samples_.clear();
00249       if(clearpath_) {
00250         computeClearpathVelocity(pref_velocity);
00251       }
00252       else {
00253         computeSampledVelocity(pref_velocity);
00254       }
00255     }
00256 
00257 
00258     double speed_ang = atan2(new_velocity_.y(), new_velocity_.x());
00259     double dif_ang = angles::shortest_angular_distance(heading_, speed_ang);
00260 
00261     if (!holo_robot_){
00262       double vel = collvoid::abs(new_velocity_);
00263       double vstar;
00264  
00265       if (std::abs(dif_ang) > EPSILON)
00266         vstar = calcVstar(vel,dif_ang);
00267       else
00268         vstar = max_vel_x_;
00269 
00270       cmd_vel.linear.x = std::min(vstar,vMaxAng());
00271       cmd_vel.linear.y = 0.0;
00272 
00273       
00274       if (std::abs(dif_ang) > 3.0*M_PI / 4.0) {
00275         cmd_vel.angular.z = sign(base_odom_.twist.twist.angular.z) * std::min(std::abs(dif_ang/time_to_holo_),max_vel_th_);
00276         
00277       }
00278       else {
00279         cmd_vel.angular.z = sign(dif_ang) * std::min(std::abs(dif_ang/time_to_holo_),max_vel_th_);
00280       }
00281       
00282       
00283       
00284       
00285   
00286     }
00287     else {
00288       collvoid::Vector2 rotated_vel = rotateVectorByAngle(new_velocity_.x(), new_velocity_.y(), -heading_);
00289 
00290       cmd_vel.linear.x = rotated_vel.x();
00291       cmd_vel.linear.y = rotated_vel.y();
00292       
00293       
00294       
00295       
00296       
00297       
00298       
00299 
00300       
00301       
00302       
00303       
00304       if (min_dist > 2*footprint_radius_)
00305         cmd_vel.angular.z = sign(dif_ang) * std::min(std::abs(dif_ang),max_vel_th_);
00306     }
00307 
00308   }
00309 
00310   
00311   void ROSAgent::computeClearpathVelocity(Vector2 pref_velocity) {
00312     
00313     boost::mutex::scoped_lock lock(neighbors_lock_);
00314 
00315     radius_ += cur_allowed_error_;
00316     ((Agent*) this) -> computeClearpathVelocity(pref_velocity);
00317     radius_ -= cur_allowed_error_;
00318     
00319     publishHoloSpeed(position_, new_velocity_, global_frame_, base_frame_, speed_pub_);
00320     publishVOs(position_, vo_agents_, use_truncation_, global_frame_, base_frame_, vo_pub_);
00321     publishPoints(position_, samples_, global_frame_, base_frame_, samples_pub_);
00322     publishOrcaLines(additional_orca_lines_, position_, global_frame_, base_frame_, lines_pub_);
00323 
00324   }
00325   
00326 
00327   void ROSAgent::computeSampledVelocity(Vector2 pref_velocity) {
00328 
00329     createSamplesWithinMovementConstraints(samples_, base_odom_.twist.twist.linear.x, base_odom_.twist.twist.linear.y, base_odom_.twist.twist.angular.z, acc_lim_x_, acc_lim_y_, acc_lim_th_, min_vel_x_, max_vel_x_, min_vel_y_, max_vel_y_, min_vel_th_, max_vel_th_ , heading_, pref_velocity, sim_period_, num_samples_, holo_robot_);
00330 
00331     
00332     boost::mutex::scoped_lock lock(neighbors_lock_);
00333 
00334     radius_ += cur_allowed_error_;
00335     ((Agent*) this) -> computeSampledVelocity(pref_velocity);
00336     radius_ -= cur_allowed_error_;
00337    
00338     
00339     publishHoloSpeed(position_, new_velocity_, global_frame_, base_frame_, speed_pub_);
00340     publishVOs(position_, vo_agents_, use_truncation_, global_frame_, base_frame_, vo_pub_);
00341     publishPoints(position_, samples_, global_frame_, base_frame_, samples_pub_);
00342     publishOrcaLines(additional_orca_lines_, position_, global_frame_, base_frame_, lines_pub_);
00343     
00344   }
00345   
00346   
00347   void ROSAgent::computeOrcaVelocity(Vector2 pref_velocity){
00348     ((Agent*) this) -> computeOrcaVelocity(pref_velocity, convex_);
00349 
00350     
00351     publishHoloSpeed(position_, new_velocity_, global_frame_, base_frame_, speed_pub_);
00352     publishOrcaLines(orca_lines_, position_, global_frame_, base_frame_, lines_pub_);
00353 
00354   }
00355 
00356   void ROSAgent::addNHConstraints(double min_dist, Vector2 pref_velocity){
00357     double min_error = min_error_holo_;
00358     double max_error = max_error_holo_;
00359     double error = max_error;
00360     double v_max_ang = vMaxAng();
00361 
00362     
00363 
00364     if (min_dist < 2.0*footprint_radius_ + cur_loc_unc_radius_){
00365       error = (max_error-min_error) / (collvoid::sqr(2*(footprint_radius_ + cur_loc_unc_radius_))) * collvoid::sqr(min_dist) + min_error; 
00366       
00367       if (min_dist < 0) {
00368         error = min_error;
00369         
00370       }
00371     }
00372     cur_allowed_error_ = 1.0/3.0 * cur_allowed_error_ + 2.0/3.0 * error;
00373     
00374     double speed_ang = atan2(pref_velocity.y(), pref_velocity.x());
00375     double dif_ang = angles::shortest_angular_distance(heading_, speed_ang);
00376     if (std::abs(dif_ang) > M_PI/2.0) { 
00377       double max_track_speed  = calculateMaxTrackSpeedAngle(time_to_holo_, M_PI / 2.0, cur_allowed_error_, max_vel_x_, max_vel_th_, v_max_ang);
00378       if (max_track_speed <= 2*min_error) {
00379         max_track_speed = 2* min_error;
00380       }
00381       addMovementConstraintsDiffSimple(max_track_speed, heading_, additional_orca_lines_);
00382     }
00383     else {
00384       addMovementConstraintsDiff(cur_allowed_error_, time_to_holo_, max_vel_x_,max_vel_th_, heading_, v_max_ang, additional_orca_lines_);
00385     }
00386     max_speed_x_ = vMaxAng();
00387  
00388   }
00389 
00390   void ROSAgent::computeObstacles(){
00391     boost::mutex::scoped_lock lock(obstacle_lock_);
00392     
00393     std::vector<Vector2> own_footprint;
00394     BOOST_FOREACH(geometry_msgs::Point32 p, footprint_msg_.polygon.points) {
00395       own_footprint.push_back(Vector2(p.x, p.y));
00396       
00397     }
00398     min_dist_obst_ = DBL_MAX;
00399     ros::Time cur_time = ros::Time::now();
00400     int i = 0;
00401     std::vector<int> delete_list;
00402     BOOST_FOREACH(Obstacle obst, obstacles_from_laser_) {
00403       if (obst.point1 != obst.point2) {
00404         double dist = distSqPointLineSegment(obst.point1, obst.point2, position_);
00405         if (dist < sqr((abs(velocity_) + 4.0 * footprint_radius_))) {
00406           if (use_obstacles_) {
00407             if (orca_) {
00408               createObstacleLine(own_footprint, obst.point1, obst.point2);
00409             }
00410             else {
00411               VO obstacle_vo = createObstacleVO(position_, footprint_radius_, own_footprint, obst.point1, obst.point2);
00412               vo_agents_.push_back(obstacle_vo);
00413             }
00414           }
00415           if (dist < min_dist_obst_) {
00416             min_dist_obst_ = dist;
00417           }
00418         }
00419       }
00420       else {
00421         delete_list.push_back(i);
00422       }
00423       i++;
00424     }
00425     for (int i = (int)delete_list.size() -1; i >= 0; i--) {
00426      obstacles_from_laser_.erase(obstacles_from_laser_.begin() + delete_list[i]);
00427     }
00428 
00429   }
00430   
00431 
00432   bool ROSAgent::compareNeighborsPositions(const AgentPtr& agent1, const AgentPtr& agent2) {
00433     return compareVectorPosition(agent1->position_, agent2->position_);
00434   }
00435 
00436 
00437   bool ROSAgent::compareConvexHullPointsPosition(const ConvexHullPoint& p1, const ConvexHullPoint& p2) {
00438     return collvoid::absSqr(p1.point) <= collvoid::absSqr(p2.point);
00439   }
00440 
00441   
00442   bool ROSAgent::compareVectorPosition(const collvoid::Vector2& v1, const collvoid::Vector2& v2){
00443     return collvoid::absSqr(position_ - v1) <= collvoid::absSqr(position_ - v2);
00444   }
00445 
00446   void ROSAgent::sortObstacleLines(){
00447     boost::mutex::scoped_lock lock(obstacle_lock_);
00448     std::sort(obstacle_points_.begin(),obstacle_points_.end(), boost::bind(&ROSAgent::compareVectorPosition,this,_1,_2));
00449   }
00450 
00451   collvoid::Vector2 ROSAgent::LineSegmentToLineSegmentIntersection(double x1, double y1, double x2, double y2, double x3, double y3, double x4, double y4){
00452     double r, s, d;
00453     collvoid::Vector2 res;
00454     
00455     if ((y2 - y1) / (x2 - x1) != (y4 - y3) / (x4 - x3)){
00456       d = (((x2 - x1) * (y4 - y3)) - (y2 - y1) * (x4 - x3));
00457       if (d != 0){
00458         r = (((y1 - y3) * (x4 - x3)) - (x1 - x3) * (y4 - y3)) / d;
00459         s = (((y1 - y3) * (x2 - x1)) - (x1 - x3) * (y2 - y1)) / d;
00460         if (r >= 0 && r <= 1){
00461           if (s >= 0 && s <= 1){
00462             return collvoid::Vector2(x1 + r * (x2 - x1), y1 + r * (y2 - y1));
00463           }
00464         }
00465       }
00466     } 
00467     return res;
00468   }
00469 
00470   bool ROSAgent::pointInNeighbor(collvoid::Vector2& point) {
00471     for (size_t i = 0; i<agent_neighbors_.size();i++){
00472       if (collvoid::abs(point - agent_neighbors_[i]->position_) <= agent_neighbors_[i]->radius_)
00473         return true;
00474     }
00475     return false;
00476   }
00477 
00478   double ROSAgent::getDistToFootprint(collvoid::Vector2& point){
00479     collvoid::Vector2 result, null;
00480     for (size_t i = 0; i < footprint_lines_.size(); i++){
00481       collvoid::Vector2 first = footprint_lines_[i].first;
00482       collvoid::Vector2 second = footprint_lines_[i].second;
00483           
00484       result = LineSegmentToLineSegmentIntersection(first.x(),first.y(),second.x(),second.y(), 0.0, 0.0, point.x(),point.y());
00485       if (result != null) {
00486         
00487         return collvoid::abs(result);
00488       }
00489     }
00490     ROS_DEBUG("Obstacle Point within Footprint. I am close to/in collision");
00491     return -1;
00492   }
00493 
00494   void ROSAgent::computeObstacleLine(Vector2& obst){
00495     Line line;
00496     Vector2 relative_position = obst - position_;
00497     double dist_to_footprint;
00498     double dist = collvoid::abs(position_ - obst);
00499     if (!has_polygon_footprint_)
00500       dist_to_footprint = footprint_radius_;
00501     else {
00502       dist_to_footprint = getDistToFootprint(relative_position);
00503       if (dist_to_footprint == -1){
00504         dist_to_footprint = footprint_radius_;
00505       }
00506     }
00507     dist  = dist - dist_to_footprint - 0.03;
00508     
00509     
00510     
00511     
00512     line.point = normalize(relative_position) * (dist); 
00513     line.dir = Vector2 (-normalize(relative_position).y(),normalize(relative_position).x()) ; 
00514     additional_orca_lines_.push_back(line);
00515   }
00516   
00517   void ROSAgent::createObstacleLine(std::vector<Vector2>& own_footprint, Vector2& obst1, Vector2& obst2) {
00518       
00519     double dist = distSqPointLineSegment(obst1, obst2, position_);
00520 
00521     if (dist == absSqr(position_ - obst1)) {
00522       computeObstacleLine(obst1);
00523     }
00524     else if (dist == absSqr(position_ - obst2)) {
00525       computeObstacleLine(obst2);
00526     }
00527     
00528     
00529     else {
00530       Vector2 position_obst = projectPointOnLine(obst1, obst2-obst1, position_);
00531       Vector2 rel_position = position_obst - position_;
00532       dist = std::sqrt(dist);
00533       double dist_to_footprint = getDistToFootprint(rel_position);
00534       if (dist_to_footprint == -1){
00535         dist_to_footprint = footprint_radius_;
00536       }
00537       dist = dist - dist_to_footprint - 0.03;
00538 
00539       if (dist < 0.0) {
00540         Line line;
00541         line.point = (dist - 0.02) * normalize (rel_position);
00542         line.dir = normalize(obst1 - obst2);
00543         additional_orca_lines_.push_back(line);
00544         return;
00545       }
00546 
00547       if (abs(position_ - obst1) > 2 * footprint_radius_ && abs(position_ - obst2) > 2 * footprint_radius_) {
00548         Line line;
00549         line.point = dist * normalize (rel_position);
00550         line.dir = -normalize(obst1 - obst2);
00551         additional_orca_lines_.push_back(line);
00552         return;
00553         
00554       }
00555       
00556       rel_position = (abs(rel_position) - dist / 2.0) * normalize(rel_position);
00557       
00558       std::vector<Vector2> obst;
00559       obst.push_back(obst1 - position_obst);
00560       obst.push_back(obst2 - position_obst);
00561       std::vector<Vector2> mink_sum = minkowskiSum(own_footprint, obst);
00562 
00563       Vector2 min, max;
00564       double min_ang = 0.0;
00565       double max_ang = 0.0; 
00566       
00567       for (int i = 0; i< (int) mink_sum.size(); i++){
00568         double angle = angleBetween(rel_position, rel_position + mink_sum[i]);
00569         if (leftOf(Vector2(0.0,0.0), rel_position, rel_position + mink_sum[i])) {
00570           if (-angle < min_ang) {
00571             min = rel_position + mink_sum[i];
00572             min_ang = -angle;
00573           }
00574       }
00575         else {
00576           if (angle > max_ang) {
00577             max = rel_position + mink_sum[i];
00578           max_ang = angle;
00579           }
00580         }
00581       }
00582       
00583       Line line;
00584       line.point = (dist / 2.0) * normalize(rel_position);
00585       if (absSqr(position_obst - obst1) > absSqr(position_obst - obst2)) {
00586         
00587         line.dir = rotateVectorByAngle(normalize(max), 0.1);
00588       }
00589       else {
00590         
00591         line.dir = rotateVectorByAngle(normalize(min), 0.1);;
00592       }
00593       additional_orca_lines_.push_back(line);
00594 
00595     }
00596   }
00597 
00598   
00599   
00600   
00601   
00602   
00603   
00604   
00605   
00606   
00607   
00608   
00609   
00610   
00611   
00612   
00613   
00614   
00615   
00616   
00617   
00618   
00619   
00620   
00621   
00622   
00623   
00624   
00625   
00626 
00627   
00628   
00629   
00630 
00631       
00632   
00633     
00634   
00635   
00636   
00637   
00638   
00639   
00640   
00641   
00642   
00643   
00644   
00645  
00646   void ROSAgent::setFootprint(geometry_msgs::PolygonStamped footprint ){
00647     if (footprint.polygon.points.size() < 2) {
00648       ROS_ERROR("The footprint specified has less than two nodes");
00649       return;
00650     }
00651     footprint_msg_ = footprint;
00652     setMinkowskiFootprintVector2(footprint_msg_);
00653 
00654     footprint_lines_.clear();
00655     geometry_msgs::Point32 p = footprint_msg_.polygon.points[0];
00656     collvoid::Vector2 first = collvoid::Vector2(p.x, p.y);
00657     collvoid::Vector2 old = collvoid::Vector2(p.x, p.y);
00658     
00659     for (size_t i = 0; i<footprint_msg_.polygon.points.size(); i++) {
00660       p = footprint_msg_.polygon.points[i];
00661       collvoid::Vector2 point = collvoid::Vector2(p.x, p.y);
00662       footprint_lines_.push_back(std::make_pair(old, point));
00663       old = point;
00664     }
00665     
00666     footprint_lines_.push_back(std::make_pair(old, first));
00667     has_polygon_footprint_ = true;
00668   }
00669 
00670   void ROSAgent::setFootprintRadius(double radius){
00671     footprint_radius_ = radius;
00672     radius_ = radius + cur_loc_unc_radius_;
00673   }
00674 
00675   void ROSAgent::setMinkowskiFootprintVector2(geometry_msgs::PolygonStamped minkowski_footprint) {
00676     minkowski_footprint_.clear();
00677     BOOST_FOREACH(geometry_msgs::Point32 p, minkowski_footprint.polygon.points) {
00678       minkowski_footprint_.push_back(Vector2(p.x, p.y));
00679     }
00680   }
00681 
00682   void ROSAgent::setIsHoloRobot(bool holo_robot) {
00683     holo_robot_ = holo_robot;
00684   }
00685   
00686   void ROSAgent::setRobotBaseFrame(std::string base_frame){
00687     base_frame_ = base_frame;
00688   }
00689 
00690   void ROSAgent::setGlobalFrame(std::string global_frame){
00691     global_frame_ = global_frame;
00692   }
00693 
00694   void ROSAgent::setId(std::string id) {
00695     this->id_ = id;
00696   }
00697 
00698   void ROSAgent::setMaxVelWithObstacles(double max_vel_with_obstacles){
00699     max_vel_with_obstacles_ = max_vel_with_obstacles;
00700   }
00701 
00702   void ROSAgent::setWheelBase(double wheel_base){
00703     wheel_base_ = wheel_base;
00704   }
00705 
00706   void ROSAgent::setAccelerationConstraints(double acc_lim_x, double acc_lim_y, double acc_lim_th){
00707     acc_lim_x_ = acc_lim_x;
00708     acc_lim_y_ = acc_lim_y;
00709     acc_lim_th_ = acc_lim_th;
00710   }
00711   
00712   void ROSAgent::setMinMaxSpeeds(double min_vel_x, double max_vel_x, double min_vel_y, double max_vel_y, double min_vel_th, double max_vel_th, double min_vel_th_inplace){
00713     min_vel_x_ = min_vel_x;
00714     max_vel_x_ = max_vel_x;
00715     min_vel_y_ = min_vel_y;
00716     max_vel_y_ = max_vel_y;
00717     min_vel_th_ = min_vel_th;
00718     max_vel_th_ = max_vel_th;
00719     min_vel_th_inplace_ = min_vel_th_inplace;
00720   }
00721 
00722   void ROSAgent::setPublishPositionsPeriod(double publish_positions_period){
00723     publish_positions_period_ = publish_positions_period;
00724   }
00725   
00726   void ROSAgent::setPublishMePeriod(double publish_me_period){
00727     publish_me_period_ = publish_me_period;
00728   }
00729   
00730   void ROSAgent::setTimeToHolo(double time_to_holo){
00731     time_to_holo_ = time_to_holo;
00732   }
00733   
00734   void ROSAgent::setTimeHorizonObst(double time_horizon_obst){
00735     time_horizon_obst_ = time_horizon_obst;
00736   }
00737   
00738   void ROSAgent::setMinMaxErrorHolo(double min_error_holo, double max_error_holo){
00739     min_error_holo_ = min_error_holo;
00740     max_error_holo_ = max_error_holo;
00741   }
00742   
00743   void ROSAgent::setDeleteObservations(bool delete_observations){
00744     delete_observations_ = delete_observations;
00745   }
00746   
00747   void ROSAgent::setThresholdLastSeen(double threshold_last_seen){ 
00748     threshold_last_seen_ = threshold_last_seen;
00749   }
00750   
00751   void ROSAgent::setLocalizationEps(double eps) {
00752     eps_ = eps;
00753     if (pose_array_weighted_.size() > 0) {
00754       
00755       if (!convex_) {
00756         computeNewLocUncertainty();
00757       }
00758       else{
00759         computeNewMinkowskiFootprint();
00760       }
00761     }
00762   }
00763 
00764   void ROSAgent::setTypeVO(int type_vo) {
00765     type_vo_ = type_vo;
00766   }
00767 
00768   void ROSAgent::setOrca(bool orca) {
00769     orca_ = orca;
00770   }
00771 
00772   void ROSAgent::setConvex(bool convex) {
00773     convex_ = convex;
00774   }
00775 
00776   void ROSAgent::setClearpath(bool clearpath) {
00777     clearpath_ = clearpath;
00778   }
00779 
00780   void ROSAgent::setUseTruncation(bool use_truncation){
00781     use_truncation_ = use_truncation;
00782   }
00783 
00784   void ROSAgent::setNumSamples(int num_samples){
00785     num_samples_ = num_samples;
00786   }
00787 
00788   bool ROSAgent::isHoloRobot() {
00789     return holo_robot_;
00790   }
00791   
00792   ros::Time ROSAgent::lastSeen(){
00793     return last_seen_;
00794   }
00795 
00796   void ROSAgent::positionShareCallback(const collvoid_msgs::PoseTwistWithCovariance::ConstPtr& msg){
00797     boost::mutex::scoped_lock lock(neighbors_lock_);
00798     std::string cur_id = msg->robot_id;
00799     if (strcmp(cur_id.c_str(),id_.c_str()) != 0) {  
00800       size_t i;
00801       for (i = 0; i< agent_neighbors_.size(); i++) {
00802 
00803         ROSAgentPtr agent = boost::dynamic_pointer_cast<ROSAgent>(agent_neighbors_[i]);
00804 
00805         if (strcmp(agent->id_.c_str(),cur_id.c_str()) == 0) {
00806           
00807           break;
00808         }
00809       }
00810       if (i>=agent_neighbors_.size()) { 
00811         ROSAgentPtr new_robot(new ROSAgent);
00812         new_robot->id_ = cur_id;
00813         new_robot->holo_robot_ = msg->holo_robot;
00814         agent_neighbors_.push_back(new_robot);
00815         ROS_DEBUG("I added a new neighbor with id %s and radius %f",cur_id.c_str(),msg->radius);
00816       }
00817       ROSAgentPtr agent = boost::dynamic_pointer_cast<ROSAgent>(agent_neighbors_[i]);
00818       agent->base_odom_.pose.pose = msg->pose.pose;
00819       agent->heading_ = tf::getYaw(msg->pose.pose.orientation);
00820       agent->base_odom_.twist.twist = msg->twist.twist;
00821       agent->holo_velocity_ = Vector2(msg->holonomic_velocity.x, msg->holonomic_velocity.x);
00822       agent->radius_ = msg->radius;
00823 
00824       agent->controlled_ = msg->controlled;
00825       
00826       agent->footprint_msg_ = msg->footprint;
00827       agent->setMinkowskiFootprintVector2(msg->footprint);
00828 
00829       agent->last_seen_ = msg->header.stamp;
00830     }
00831     
00832     if ((ros::Time::now() - last_time_positions_published_).toSec() > publish_positions_period_) {
00833       last_time_positions_published_ = ros::Time::now();
00834       publishNeighborPositions(agent_neighbors_, global_frame_, base_frame_, neighbors_pub_);
00835       publishMePosition(this, global_frame_, base_frame_, me_pub_);
00836     }
00837   }
00838 
00839   void ROSAgent::amclPoseArrayWeightedCallback(const amcl::PoseArrayWeighted::ConstPtr& msg){
00840     boost::mutex::scoped_lock lock(convex_lock_);
00841     
00842     pose_array_weighted_.clear();
00843     geometry_msgs::PoseStamped in;
00844     in.header = msg->header;
00845     for (int i = 0; i< (int)msg->poses.size(); i++){
00846       in.pose = msg->poses[i];
00847       geometry_msgs::PoseStamped result;
00848       try {
00849         tf_->waitForTransform(global_frame_, base_frame_, in.header.stamp, ros::Duration(0.2));
00850         tf_->transformPose(base_frame_, in, result);    
00851         pose_array_weighted_.push_back(std::make_pair(msg->weights[i], result));
00852       }
00853       catch (tf::TransformException ex){
00854         ROS_ERROR("%s",ex.what());
00855         ROS_ERROR("point transform failed");
00856       };
00857     }
00858     
00859     if (!convex_) {
00860       computeNewLocUncertainty();
00861     }
00862     else{
00863       computeNewMinkowskiFootprint();
00864     }
00865 
00866   }
00867 
00868   void ROSAgent::odomCallback(const nav_msgs::Odometry::ConstPtr& msg){
00869     
00870     boost::mutex::scoped_lock(me_lock_);
00871     base_odom_.twist.twist.linear.x = msg->twist.twist.linear.x;
00872     base_odom_.twist.twist.linear.y = msg->twist.twist.linear.y;
00873     base_odom_.twist.twist.angular.z = msg->twist.twist.angular.z;
00874     
00875     last_seen_ = msg->header.stamp;
00876     tf::Stamped<tf::Pose> global_pose;
00877     
00878     global_pose.setIdentity();
00879     global_pose.frame_id_ = base_frame_;
00880     global_pose.stamp_ = msg->header.stamp;
00881 
00882     try {
00883       tf_->waitForTransform(global_frame_, base_frame_, global_pose.stamp_, ros::Duration(0.2));
00884       tf_->transformPose(global_frame_, global_pose, global_pose);
00885     }
00886     catch (tf::TransformException ex){
00887       ROS_ERROR("%s",ex.what());
00888       ROS_ERROR("point odom transform failed");
00889       return;
00890     };
00891 
00892     geometry_msgs::PoseStamped pose_msg;
00893     tf::poseStampedTFToMsg(global_pose, pose_msg);
00894 
00895     base_odom_.pose.pose = pose_msg.pose;
00896 
00897     if ((ros::Time::now() - last_time_me_published_).toSec() > publish_me_period_) {
00898       last_time_me_published_ = ros::Time::now();
00899       publishMePoseTwist();
00900     }
00901   }
00902 
00903   void ROSAgent::updateAllNeighbors(){
00904     boost::mutex::scoped_lock lock(neighbors_lock_);
00905     BOOST_FOREACH (AgentPtr a, agent_neighbors_) {
00906       ROSAgentPtr agent = boost::dynamic_pointer_cast<ROSAgent>(a);
00907       setAgentParams(agent.get());
00908     }
00909     std::sort(agent_neighbors_.begin(),agent_neighbors_.end(), boost::bind(&ROSAgent::compareNeighborsPositions, this, _1, _2));
00910   }
00911 
00912   
00913   void ROSAgent::setAgentParams(ROSAgent* agent) {
00914     double time_dif = (ros::Time::now() - agent->last_seen_).toSec();
00915     double yaw, x_dif, y_dif, th_dif;
00916     
00917 
00918     yaw = tf::getYaw(agent->base_odom_.pose.pose.orientation);
00919     th_dif =  time_dif * agent->base_odom_.twist.twist.angular.z;
00920     if (agent->isHoloRobot()) {
00921       x_dif = time_dif * agent->base_odom_.twist.twist.linear.x;
00922       y_dif = time_dif * agent->base_odom_.twist.twist.linear.y;
00923     }
00924     else {
00925       x_dif = time_dif * agent->base_odom_.twist.twist.linear.x * cos(yaw + th_dif/2.0);
00926       y_dif = time_dif * agent->base_odom_.twist.twist.linear.x * sin(yaw + th_dif/2.0);
00927     }
00928     agent->heading_ = yaw + th_dif;
00929     agent->position_ = Vector2(agent->base_odom_.pose.pose.position.x + x_dif, agent->base_odom_.pose.pose.position.y + y_dif);
00930     
00931     agent->timestep_ = time_dif;
00932 
00933     
00934     agent->footprint_ = rotateFootprint(agent->minkowski_footprint_, agent->heading_);
00935       
00936     if (agent->holo_robot_) {
00937       agent->velocity_ = rotateVectorByAngle(agent->base_odom_.twist.twist.linear.x, agent->base_odom_.twist.twist.linear.y, (yaw+th_dif));
00938     }
00939     else {
00940       double dif_x, dif_y, dif_ang;
00941       dif_ang = sim_period_ * agent->base_odom_.twist.twist.angular.z;
00942       dif_x = agent->base_odom_.twist.twist.linear.x * cos(dif_ang / 2.0);
00943       dif_y = agent->base_odom_.twist.twist.linear.x * sin(dif_ang / 2.0);
00944       agent->velocity_ = rotateVectorByAngle(dif_x, dif_y, (yaw+th_dif));
00945     }
00946   }
00947   
00948   double ROSAgent::vMaxAng(){
00949     
00950     
00951     return max_vel_x_; 
00952   }
00953 
00954   
00955 
00956   void ROSAgent::publishMePoseTwist() {
00957 
00958     collvoid_msgs::PoseTwistWithCovariance me_msg;
00959     me_msg.header.stamp = ros::Time::now();
00960     me_msg.header.frame_id = base_frame_;
00961 
00962     me_msg.pose.pose = base_odom_.pose.pose;
00963     me_msg.twist.twist = base_odom_.twist.twist;
00964 
00965     me_msg.controlled = controlled_;
00966     me_msg.holonomic_velocity.x = holo_velocity_.x();
00967     me_msg.holonomic_velocity.y = holo_velocity_.y();
00968 
00969     me_msg.holo_robot = holo_robot_;
00970     me_msg.radius = footprint_radius_ + cur_loc_unc_radius_;
00971     me_msg.robot_id = id_;
00972     me_msg.controlled = controlled_;
00973     
00974     me_msg.footprint = createFootprintMsgFromVector2(minkowski_footprint_);
00975     position_share_pub_.publish(me_msg);
00976   }
00977 
00978   geometry_msgs::PolygonStamped ROSAgent::createFootprintMsgFromVector2(const std::vector<Vector2>& footprint) {
00979     geometry_msgs::PolygonStamped result;
00980     result.header.frame_id = base_frame_;
00981     result.header.stamp = ros::Time::now();
00982     
00983     BOOST_FOREACH(Vector2 point, footprint) {
00984       geometry_msgs::Point32 p;
00985       p.x = point.x();
00986       p.y = point.y();
00987       result.polygon.points.push_back(p);
00988     }
00989     
00990     return result;
00991   }
00992 
00993   std::vector<Vector2> ROSAgent::rotateFootprint(const std::vector<Vector2>& footprint, double angle) {
00994     std::vector<Vector2> result;
00995     BOOST_FOREACH(Vector2 point, footprint) {
00996       Vector2 rotated = rotateVectorByAngle(point, angle);
00997       result.push_back(rotated);
00998     }
00999     return result;
01000   }
01001   
01002   geometry_msgs::PoseStamped ROSAgent::transformMapPoseToBaseLink(geometry_msgs::PoseStamped in) {
01003     geometry_msgs::PoseStamped result;
01004     try {
01005       tf_->waitForTransform(global_frame_, base_frame_, in.header.stamp, ros::Duration(0.3));
01006       tf_->transformPose(base_frame_, in, result);
01007     }
01008     catch (tf::TransformException ex){
01009       ROS_ERROR("%s",ex.what());
01010       ROS_ERROR("point transform failed");
01011     };
01012     return result;
01013   }
01014 
01015 
01016   void ROSAgent::computeNewLocUncertainty(){
01017     std::vector<ConvexHullPoint> points;
01018 
01019     for (int i = 0; i < (int) pose_array_weighted_.size(); i++) {
01020       ConvexHullPoint p;
01021       p.point = Vector2(pose_array_weighted_[i].second.pose.position.x, pose_array_weighted_[i].second.pose.position.y);
01022       p.weight = pose_array_weighted_[i].first;
01023       p.index = i;
01024       p.orig_index = i;
01025       points.push_back(p);
01026     }
01027 
01028     std::sort(points.begin(),points.end(), boost::bind(&ROSAgent::compareConvexHullPointsPosition, this, _1, _2));
01029     double sum = 0.0;
01030     int j = 0;
01031     while (sum <= 1.0 - eps_ && j < (int) points.size()) {
01032       sum += points[j].weight;
01033       j++;
01034     }
01035     cur_loc_unc_radius_ = std::min(footprint_radius_ * 2.0, collvoid::abs(points[j-1].point));
01036     
01037     radius_ = footprint_radius_ + cur_loc_unc_radius_;
01038   }
01039 
01040   void ROSAgent::computeNewMinkowskiFootprint(){
01041     bool done = false;
01042     std::vector<ConvexHullPoint> convex_hull;
01043     std::vector<ConvexHullPoint> points;
01044     points.clear();
01045 
01046     
01047     for (int i = 0; i < (int) pose_array_weighted_.size(); i++) {
01048       ConvexHullPoint p;
01049       p.point = Vector2(pose_array_weighted_[i].second.pose.position.x, pose_array_weighted_[i].second.pose.position.y);
01050       p.weight = pose_array_weighted_[i].first;
01051       p.index = i;
01052       p.orig_index = i;
01053       points.push_back(p);
01054     }
01055     std::sort(points.begin(), points.end(), compareVectorsLexigraphically);
01056     for (int i = 0; i < (int) points.size(); i++) {
01057       points[i].index = i;
01058     }
01059 
01060     double total_sum = 0;
01061     std::vector<int> skip_list;
01062     
01063     while (!done && points.size() >= 3) {
01064       double sum = 0;
01065       convex_hull.clear();
01066       convex_hull = convexHull(points, true);
01067 
01068       skip_list.clear();
01069       for (int j = 0; j< (int) convex_hull.size()-1; j++){
01070         skip_list.push_back(convex_hull[j].index);
01071         sum += convex_hull[j].weight;
01072       }
01073       total_sum +=sum;
01074 
01075       
01076 
01077       if (total_sum >= eps_){
01078         done = true;
01079         break;
01080       }
01081             
01082       std::sort(skip_list.begin(), skip_list.end());
01083       for (int i = (int)skip_list.size() -1; i >= 0; i--) {
01084         points.erase(points.begin() + skip_list[i]);
01085       }
01086 
01087       for (int i = 0; i < (int) points.size(); i++) {
01088         points[i].index = i;
01089       }
01090     }
01091 
01092     std::vector<Vector2> localization_footprint, own_footprint;
01093     for (int i = 0; i < (int)convex_hull.size(); i++) {
01094       localization_footprint.push_back(convex_hull[i].point);
01095     }
01096 
01097     BOOST_FOREACH(geometry_msgs::Point32 p, footprint_msg_.polygon.points) {
01098       own_footprint.push_back(Vector2(p.x, p.y));
01099       
01100     }
01101     minkowski_footprint_ = minkowskiSum(localization_footprint, own_footprint);
01102 
01103     
01104     geometry_msgs::PolygonStamped msg_pub = createFootprintMsgFromVector2(minkowski_footprint_);
01105     polygon_pub_.publish(msg_pub);
01106   
01107   }
01108 
01109   void ROSAgent::baseScanCallback(const sensor_msgs::LaserScan::ConstPtr& msg) {
01110     sensor_msgs::PointCloud cloud;
01111     
01112 
01113     try {
01114       tf_->waitForTransform(msg->header.frame_id, global_frame_, msg->header.stamp, ros::Duration(0.3));
01115       projector_.transformLaserScanToPointCloud(global_frame_, *msg, cloud, *tf_);
01116     }
01117     catch (tf::TransformException& e) {
01118       ROS_ERROR("%s", e.what());
01119       return;
01120     }
01121 
01122 
01123     boost::mutex::scoped_lock lock(obstacle_lock_);
01124 
01125     obstacles_from_laser_.clear();
01126 
01127     double threshold_convex = 0.03;
01128     double threshold_concave = -0.03;
01129     
01130     
01131     for (int i = 0; i< (int)cloud.points.size(); i++) {
01132       Vector2 start = Vector2(cloud.points[i].x, cloud.points[i].y);
01133       while (pointInNeighbor(start) && i < (int) cloud.points.size() ) {
01134         i++;
01135         start = Vector2(cloud.points[i].x, cloud.points[i].y);
01136       }
01137       if (i == (int)cloud.points.size()) {
01138         if (!pointInNeighbor(start)) {
01139           
01140         }
01141         return;
01142       }
01143       
01144       bool found = false;
01145       Vector2 prev = Vector2(start.x(), start.y());
01146       double first_ang = 0;
01147       double prev_ang = 0;
01148       Vector2 next;
01149       while (!found) {
01150         i++;
01151         if (i == (int)cloud.points.size()) {
01152           break;
01153         }
01154         next = Vector2(cloud.points[i].x, cloud.points[i].y);
01155         while (pointInNeighbor(next) && i < (int) cloud.points.size() ) {
01156           i++;
01157           next = Vector2(cloud.points[i].x, cloud.points[i].y);
01158         }
01159      
01160         if (abs(next-prev) > 2*footprint_radius_) {
01161           found = true;
01162           break;
01163         }
01164         Vector2 dif = next - start;
01165         double ang = atan2(dif.y(), dif.x());
01166         if (prev != start) {
01167           if (ang - first_ang < threshold_concave) {
01168             found = true;
01169             i -=2;
01170             break;
01171           }
01172           if (ang - prev_ang < threshold_concave) {
01173             found = true;
01174             i-=2;
01175             break;
01176           }
01177           if (ang - prev_ang > threshold_convex) { 
01178             found = true;
01179             i -=2;
01180             break;
01181           }
01182           if (ang - first_ang > threshold_convex) { 
01183             found = true;
01184             i -=2;
01185             break;
01186           }
01187 
01188           
01189         }
01190         else {
01191           first_ang = ang;
01192         }
01193         prev = next;
01194         prev_ang = ang;
01195       }
01196       Obstacle obst;
01197       obst.point1 = start;
01198       obst.point2 = prev;
01199       obst.last_seen = msg->header.stamp;
01200     
01201       obstacles_from_laser_.push_back(obst);
01202     }
01203     publishObstacleLines(obstacles_from_laser_, global_frame_, base_frame_, obstacles_pub_);
01204     
01205   }
01206   
01207   
01208   
01209   
01210   
01211   
01212   
01213   
01214   
01215   
01216   
01217   
01218   
01219   
01220   
01221   
01222   
01223 
01224  
01225 }
01226 
01227 int main(int argc, char **argv) {
01228   ros::init(argc, argv, "ROSAgent");
01229   
01230   ros::NodeHandle nh("~");
01231    
01232   ROSAgentPtr me(new ROSAgent);
01233   tf::TransformListener tf;
01234   me->init(nh,&tf);
01235   ROS_INFO("ROSAgent initialized");
01236   ros::spin();
01237   
01238 }
01239 
01240