ROSAgent.cpp
Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2012, Daniel Claes, Maastricht University
00003  * All rights reserved.
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions are met:
00007  *
00008  *     * Redistributions of source code must retain the above copyright
00009  *       notice, this list of conditions and the following disclaimer.
00010  *     * Redistributions in binary form must reproduce the above copyright
00011  *       notice, this list of conditions and the following disclaimer in the
00012  *       documentation and/or other materials provided with the distribution.
00013  *     * Neither the name of the Maastricht University nor the names of its
00014  *       contributors may be used to endorse or promote products derived from
00015  *       this software without specific prior written permission.
00016  *
00017  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00018  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00019  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00020  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
00021  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00022  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00023  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00024  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00025  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00026  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00027  * POSSIBILITY OF SUCH DAMAGE.
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     //only coverting round footprints for now
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     //getParam(private_nh, "sim_period", &sim_period_);
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       //initParams(private_nh);
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); //HRVO
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     //Params (get from server or set via local_planner)
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     //Publishers
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     //Subscribers
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     //laser_scan_sub_ = nh.subscribe("base_scan", 1, &ROSAgent::baseScanCallback, this);
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     //Forward project agents
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     //get closest agent/obstacle
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     //incorporate NH constraints
00234     max_speed_x_ = max_vel_x_;
00235 
00236     if (!holo_robot_) {
00237       addNHConstraints(min_dist, pref_velocity);
00238     }
00239     //add acceleration constraints
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       //ROS_ERROR("dif_ang %f", dif_ang);
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       //ROS_ERROR("vstar = %.3f", vstar);
00282       // if (std::abs(cmd_vel.angular.z) == max_vel_th_)
00283       //        cmd_vel.linear.x = 0;
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       // if (min_dist < 1.0/2.0 * radius_) {
00293       //        if (min_dist == min_dist_neigh) {
00294       //          dif_ang = dif_ang;
00295       //        }
00296       //        else {
00297       //          double ang_obst = atan2(min_obst_vec.y(), min_obst_vec.x());
00298       //          double diff = angles::shortest_angular_distance(heading_, ang_obst);
00299 
00300       //          dif_ang = angles::shortest_angular_distance(0.0, diff - sign(diff) * M_PI / 2.0);
00301       //        }
00302       // }
00303       //      if (std::abs(dif_ang) < M_PI/2.0) 
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     //account for nh error
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     //account for nh error
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     //    Vector2 null_vec = Vector2(0,0);
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     // publish calcuated speed and orca_lines
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     //ROS_ERROR("v_max_ang %.2f", v_max_ang);
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; // how much error do i allow?
00366       //ROS_DEBUG("Error = %f", error);
00367       if (min_dist < 0) {
00368         error = min_error;
00369         // ROS_DEBUG("%s I think I am in collision", me_->getId().c_str());
00370       }
00371     }
00372     cur_allowed_error_ = 1.0/3.0 * cur_allowed_error_ + 2.0/3.0 * error;
00373     //ROS_ERROR("error = %f", cur_allowed_error_);
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) { // || cur_allowed_error_ < 2.0 * min_error) {
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       //      ROS_WARN("footprint point p = (%f, %f) ", footprint_[i].x, footprint_[i].y);
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) {// && (cur_time - obst.last_seen).toSec() < 0.2) {
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     //Make sure the lines aren't parallel
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         //ROS_DEBUG("Result = %f, %f, dist %f", result.x(), result.y(), collvoid::abs(result));
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     //if (dist < (double)max_vel_with_obstacles_){
00509     //  dist *= dist;
00510     //} 
00511     //    line.point = normalize(relative_position) * (dist - dist_to_footprint - 0.03);
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     // if (false) {
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       // return;
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         // ROS_ERROR("max_ang = %.2f", max_ang);
00587         line.dir = rotateVectorByAngle(normalize(max), 0.1);
00588       }
00589       else {
00590         // ROS_ERROR("min_ang = %.2f", min_ang);
00591         line.dir = rotateVectorByAngle(normalize(min), 0.1);;
00592       }
00593       additional_orca_lines_.push_back(line);
00594 
00595     }
00596   }
00597 
00598   
00599   // void ROSAgent::computeObstacleLines(){
00600   //   std::vector<int> delete_points;
00601   //   for(size_t i = 0; i< obstacle_points_.size(); i++){
00602   //     //ROS_DEBUG("obstacle at %f %f dist %f",obstacle_points_[i].x(),obstacle_points_[i].y(),collvoid::abs(position_-obstacle_points_[i]));
00603   //     if (pointInNeighbor(obstacle_points_[i])){
00604   //    delete_points.push_back((int)i);
00605   //    continue;
00606   //     }
00607   //     double dist = collvoid::abs(position_ - obstacle_points_[i]);
00608   //     Line line;
00609   //     Vector2 relative_position = obstacle_points_[i] - position_;
00610   //     double dist_to_footprint;
00611   //     if (!has_polygon_footprint_)
00612   //    dist_to_footprint = footprint_radius_;
00613   //     else {
00614   //    dist_to_footprint = getDistToFootprint(relative_position);
00615   //    if (dist_to_footprint == -1){
00616   //      dist_to_footprint = footprint_radius_;
00617   //    }
00618   //     }
00619   //     dist = std::min(dist - dist_to_footprint - 0.01, (double)max_vel_with_obstacles_);
00620   //     //if (dist < (double)max_vel_with_obstacles_){
00621   //     //  dist *= dist;
00622   //     //} 
00623   //     //    line.point = normalize(relative_position) * (dist - dist_to_footprint - 0.03);
00624   //     line.point = normalize(relative_position) * (dist); 
00625   //     line.dir = Vector2 (-normalize(relative_position).y(),normalize(relative_position).x()) ; 
00626 
00627   //     //TODO relatvie velocity instead of velocity!!
00628   //     if (dist > time_horizon_obst_ * collvoid::abs(velocity_))
00629   //    return;
00630 
00631       
00632   //     additional_orca_lines_.push_back(line);
00633     
00634   //   }
00635   //   if (delete_observations_) 
00636   //     return;
00637   //   else {
00638   //     while(!delete_points.empty()){
00639   //    int del = delete_points.back();
00640   //    obstacle_points_.erase(obstacle_points_.begin()+del);
00641   //    delete_points.pop_back();
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     //add linesegments for footprint
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     //add last segment
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){ //implement!!
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       //if (!convex_ || orca_) {
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) {  //if it is not me do something
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           //I found the robot
00807           break;
00808         }
00809       }
00810       if (i>=agent_neighbors_.size()) { //Robot is new, so it will be added to the list
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     //publish visualization if neccessary
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     //    if (!convex_ || orca_) {
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     //we assume that the odometry is published in the frame of the base
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     //let's get the pose of the robot in the frame of the plan
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     //time_dif = 0.0;
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     //agent->last_seen_ = ros::Time::now();
00931     agent->timestep_ = time_dif;
00932 
00933     //agent->footprint_ = agent->minkowski_footprint_;
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     //double theoretical_max_v = max_vel_th_ * wheel_base_ / 2.0; 
00950     //return theoretical_max_v - std::abs(base_odom_.twist.twist.angular.z) * wheel_base_/2.0;
00951     return max_vel_x_; //TODO: fixme!!
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     //ROS_ERROR("Loc Uncertainty = %f", cur_loc_unc_radius_);
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       //ROS_WARN("SUM = %f (%f), num Particles = %d, eps = %f", sum, total_sum, (int) points.size(), eps_);
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       //      ROS_WARN("footprint point p = (%f, %f) ", footprint_[i].x, footprint_[i].y);
01100     }
01101     minkowski_footprint_ = minkowskiSum(localization_footprint, own_footprint);
01102 
01103     //publish footprint
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     //  ROS_ERROR("got cloud");
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     //    ROS_ERROR("%d", (int)cloud.points.size());
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           //obstacles_from_laser_.push_back(std::make_pair(start,start));
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) { //going towards me
01178             found = true;
01179             i -=2;
01180             break;
01181           }
01182           if (ang - first_ang > threshold_convex) { //going towards me
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   // double pointToSegmentDistance(Vector2 line1, Vector2 line2, Vector2 point) {
01207   //   //  http://stackoverflow.com/questions/849211/shortest-distance-between-a-point-and-a-line-segment
01208   //   // Return minimum distance between line segment vw and point point
01209   //   const double length = absSqr(line2-line1);  // i.e. |w-v|^2 -  avoid a sqrt
01210   //   if (length == 0.0)
01211   //     return abs(point-line1);   // v == w case
01212   //   // Consider the line extending the segment, parameterized as v + t (w - v).
01213   //   // We find projection of point p onto the line.
01214   //   // It falls where t = [(p-v) . (w-v)] / |w-v|^2
01215   //   const double t = (point - line1) * (line2 - line1) /  length;
01216   //   if (t < 0.0)
01217   //     return abs(point - line1);       // Beyond the 'v' end of the segment
01218   //   else if (t > 1.0)
01219   //     return abs(point - line2);  // Beyond the 'w' end of the segment
01220   //   const Vector2 projection = v + t * (w - v);  // Projection falls on the segment
01221   //   return abs(point - projection);
01222   // }  
01223 
01224  
01225 }
01226 
01227 int main(int argc, char **argv) {
01228   ros::init(argc, argv, "ROSAgent");
01229   //ros::NodeHandle nh;
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 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Properties Friends Defines


collvoid_local_planner
Author(s): Daniel Claes
autogenerated on Sun Aug 25 2013 10:10:23