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