00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038 #include "costmap_2d/array_parser.h"
00039 #include <costmap_2d/layered_costmap.h>
00040 #include <costmap_2d/costmap_2d_ros.h>
00041 #include <cstdio>
00042 #include <string>
00043 #include <algorithm>
00044 #include <vector>
00045
00046
00047 using namespace std;
00048
00049 namespace costmap_2d
00050 {
00051
00052 void move_parameter(ros::NodeHandle& old_h, ros::NodeHandle& new_h, std::string name, bool should_delete=true)
00053 {
00054 if (!old_h.hasParam(name))
00055 return;
00056
00057 XmlRpc::XmlRpcValue value;
00058 old_h.getParam(name, value);
00059 new_h.setParam(name, value);
00060 if(should_delete) old_h.deleteParam(name);
00061 }
00062
00063 Costmap2DROS::Costmap2DROS(std::string name, tf::TransformListener& tf) :
00064 layered_costmap_(NULL), name_(name), tf_(tf), stop_updates_(false), initialized_(true), stopped_(false), robot_stopped_(
00065 false), map_update_thread_(NULL), last_publish_(0), plugin_loader_("costmap_2d",
00066 "costmap_2d::Layer"), publisher_(
00067 NULL)
00068 {
00069 ros::NodeHandle private_nh("~/" + name);
00070 ros::NodeHandle g_nh;
00071
00072
00073 ros::NodeHandle prefix_nh;
00074 std::string tf_prefix = tf::getPrefixParam(prefix_nh);
00075
00076
00077 private_nh.param("global_frame", global_frame_, std::string("/map"));
00078 private_nh.param("robot_base_frame", robot_base_frame_, std::string("base_link"));
00079
00080
00081 global_frame_ = tf::resolve(tf_prefix, global_frame_);
00082 robot_base_frame_ = tf::resolve(tf_prefix, robot_base_frame_);
00083
00084 ros::Time last_error = ros::Time::now();
00085 std::string tf_error;
00086
00087 while (ros::ok()
00088 && !tf_.waitForTransform(global_frame_, robot_base_frame_, ros::Time(), ros::Duration(0.1), ros::Duration(0.01),
00089 &tf_error))
00090 {
00091 ros::spinOnce();
00092 if (last_error + ros::Duration(5.0) < ros::Time::now())
00093 {
00094 ROS_WARN("Waiting on transform from %s to %s to become available before running costmap, tf error: %s",
00095 robot_base_frame_.c_str(), global_frame_.c_str(), tf_error.c_str());
00096 last_error = ros::Time::now();
00097 }
00098 }
00099
00100
00101 bool rolling_window, track_unknown_space, always_send_full_costmap;
00102 private_nh.param("rolling_window", rolling_window, false);
00103 private_nh.param("track_unknown_space", track_unknown_space, false);
00104 private_nh.param("always_send_full_costmap", always_send_full_costmap, false);
00105
00106 layered_costmap_ = new LayeredCostmap(global_frame_, rolling_window, track_unknown_space);
00107
00108 if (!private_nh.hasParam("plugins"))
00109 {
00110 resetOldParameters(private_nh);
00111 }
00112
00113 if (private_nh.hasParam("plugins"))
00114 {
00115 XmlRpc::XmlRpcValue my_list;
00116 private_nh.getParam("plugins", my_list);
00117 for (int32_t i = 0; i < my_list.size(); ++i)
00118 {
00119 std::string pname = static_cast<std::string>(my_list[i]["name"]);
00120 std::string type = static_cast<std::string>(my_list[i]["type"]);
00121 ROS_INFO("Using plugin \"%s\"", pname.c_str());
00122
00123 boost::shared_ptr<Layer> plugin = plugin_loader_.createInstance(type);
00124 layered_costmap_->addPlugin(plugin);
00125 plugin->initialize(layered_costmap_, name + "/" + pname, &tf_);
00126 }
00127 }
00128
00129
00130 std::string topic_param, topic;
00131 if(!private_nh.searchParam("footprint_topic", topic_param))
00132 {
00133 topic_param = "footprint_topic";
00134 }
00135
00136 private_nh.param(topic_param, topic, std::string("footprint"));
00137 footprint_sub_ = private_nh.subscribe(topic, 1, &Costmap2DROS::setUnpaddedRobotFootprintPolygon, this);
00138
00139 readFootprintFromParams( private_nh );
00140
00141 publisher_ = new Costmap2DPublisher(&private_nh, layered_costmap_->getCostmap(), global_frame_, "costmap", always_send_full_costmap);
00142
00143
00144 stop_updates_ = false;
00145 initialized_ = true;
00146 stopped_ = false;
00147
00148
00149 robot_stopped_ = false;
00150 timer_ = private_nh.createTimer(ros::Duration(.1), &Costmap2DROS::movementCB, this);
00151
00152 dsrv_ = new dynamic_reconfigure::Server<Costmap2DConfig>(ros::NodeHandle("~/" + name));
00153 dynamic_reconfigure::Server<Costmap2DConfig>::CallbackType cb = boost::bind(&Costmap2DROS::reconfigureCB, this, _1,
00154 _2);
00155 dsrv_->setCallback(cb);
00156 }
00157
00158 void Costmap2DROS::setUnpaddedRobotFootprintPolygon( const geometry_msgs::Polygon& footprint )
00159 {
00160 setUnpaddedRobotFootprint( toPointVector( footprint ));
00161 }
00162
00163 Costmap2DROS::~Costmap2DROS()
00164 {
00165 map_update_thread_shutdown_ = true;
00166 if (map_update_thread_ != NULL)
00167 {
00168 map_update_thread_->join();
00169 delete map_update_thread_;
00170 }
00171 if (publisher_ != NULL)
00172 delete publisher_;
00173
00174 delete layered_costmap_;
00175 delete dsrv_;
00176 }
00177
00178 void Costmap2DROS::resetOldParameters(ros::NodeHandle& nh)
00179 {
00180 ROS_INFO("Loading from pre-hydro parameter style");
00181 bool flag;
00182 std::string s;
00183 std::vector < XmlRpc::XmlRpcValue > plugins;
00184
00185 XmlRpc::XmlRpcValue::ValueStruct map;
00186 SuperValue super_map;
00187 SuperValue super_array;
00188
00189 if (nh.getParam("static_map", flag) && flag)
00190 {
00191 map["name"] = XmlRpc::XmlRpcValue("static_layer");
00192 map["type"] = XmlRpc::XmlRpcValue("costmap_2d::StaticLayer");
00193 super_map.setStruct(&map);
00194 plugins.push_back(super_map);
00195
00196 ros::NodeHandle map_layer(nh, "static_layer");
00197 move_parameter(nh, map_layer, "map_topic");
00198 move_parameter(nh, map_layer, "unknown_cost_value");
00199 move_parameter(nh, map_layer, "lethal_cost_threshold");
00200 move_parameter(nh, map_layer, "track_unknown_space", false);
00201 }
00202
00203 ros::NodeHandle obstacles(nh, "obstacle_layer");
00204 if (nh.getParam("map_type", s) && s == "voxel")
00205 {
00206
00207 map["name"] = XmlRpc::XmlRpcValue("obstacle_layer");
00208 map["type"] = XmlRpc::XmlRpcValue("costmap_2d::VoxelLayer");
00209 super_map.setStruct(&map);
00210 plugins.push_back(super_map);
00211
00212 move_parameter(nh, obstacles, "origin_z");
00213 move_parameter(nh, obstacles, "z_resolution");
00214 move_parameter(nh, obstacles, "z_voxels");
00215 move_parameter(nh, obstacles, "mark_threshold");
00216 move_parameter(nh, obstacles, "unknown_threshold");
00217 move_parameter(nh, obstacles, "publish_voxel_map");
00218 }
00219 else
00220 {
00221 map["name"] = XmlRpc::XmlRpcValue("obstacle_layer");
00222 map["type"] = XmlRpc::XmlRpcValue("costmap_2d::ObstacleLayer");
00223 super_map.setStruct(&map);
00224 plugins.push_back(super_map);
00225 }
00226
00227 move_parameter(nh, obstacles, "max_obstacle_height");
00228 move_parameter(nh, obstacles, "raytrace_range");
00229 move_parameter(nh, obstacles, "obstacle_range");
00230 move_parameter(nh, obstacles, "track_unknown_space", true);
00231 nh.param("observation_sources", s, std::string(""));
00232 std::stringstream ss(s);
00233 std::string source;
00234 while (ss >> source)
00235 {
00236 move_parameter(nh, obstacles, source);
00237 }
00238 move_parameter(nh, obstacles, "observation_sources");
00239
00240 ros::NodeHandle inflation(nh, "inflation_layer");
00241 move_parameter(nh, inflation, "cost_scaling_factor");
00242 move_parameter(nh, inflation, "inflation_radius");
00243 map["name"] = XmlRpc::XmlRpcValue("inflation_layer");
00244 map["type"] = XmlRpc::XmlRpcValue("costmap_2d::InflationLayer");
00245 super_map.setStruct(&map);
00246 plugins.push_back(super_map);
00247
00248 super_array.setArray(&plugins);
00249 nh.setParam("plugins", super_array);
00250
00251 }
00252
00253 void Costmap2DROS::reconfigureCB(costmap_2d::Costmap2DConfig &config, uint32_t level)
00254 {
00255 transform_tolerance_ = config.transform_tolerance;
00256 if (map_update_thread_ != NULL)
00257 {
00258 map_update_thread_shutdown_ = true;
00259 map_update_thread_->join();
00260 delete map_update_thread_;
00261 }
00262 map_update_thread_shutdown_ = false;
00263 double map_update_frequency = config.update_frequency;
00264
00265 double map_publish_frequency = config.publish_frequency;
00266 if (map_publish_frequency > 0)
00267 publish_cycle = ros::Duration(1 / map_publish_frequency);
00268 else
00269 publish_cycle = ros::Duration(-1);
00270
00271
00272 double map_width_meters = config.width, map_height_meters = config.height, resolution = config.resolution, origin_x =
00273 config.origin_x,
00274 origin_y = config.origin_y;
00275
00276 if (!layered_costmap_->isSizeLocked())
00277 {
00278 layered_costmap_->resizeMap((unsigned int)(map_width_meters / resolution),
00279 (unsigned int)(map_height_meters / resolution), resolution, origin_x, origin_y);
00280 }
00281
00282
00283
00284 if( footprint_padding_ != config.footprint_padding )
00285 {
00286 footprint_padding_ = config.footprint_padding;
00287 setUnpaddedRobotFootprint( unpadded_footprint_ );
00288 }
00289
00290 readFootprintFromConfig( config, old_config_ );
00291
00292 old_config_ = config;
00293
00294 map_update_thread_ = new boost::thread(boost::bind(&Costmap2DROS::mapUpdateLoop, this, map_update_frequency));
00295 }
00296
00297 void Costmap2DROS::readFootprintFromConfig( const costmap_2d::Costmap2DConfig &new_config,
00298 const costmap_2d::Costmap2DConfig &old_config )
00299 {
00300
00301
00302
00303
00304 if( new_config.footprint == old_config.footprint &&
00305 new_config.robot_radius == old_config.robot_radius )
00306 {
00307 return;
00308 }
00309
00310 if( new_config.footprint != "" && new_config.footprint != "[]" )
00311 {
00312 readFootprintFromString( new_config.footprint );
00313 }
00314 else
00315 {
00316
00317 setFootprintFromRadius( new_config.robot_radius );
00318 }
00319 }
00320
00321 bool Costmap2DROS::readFootprintFromString( const std::string& footprint_string )
00322 {
00323 std::string error;
00324 std::vector<std::vector<float> > vvf = parseVVF( footprint_string, error );
00325 if( error != "" )
00326 {
00327 ROS_ERROR( "Error parsing footprint parameter: '%s'", error.c_str() );
00328 ROS_ERROR( " Footprint string was '%s'.", footprint_string.c_str() );
00329 return false;
00330 }
00331
00332
00333 if( vvf.size() < 3 )
00334 {
00335 ROS_ERROR( "You must specify at least three points for the robot footprint, reverting to previous footprint." );
00336 return false;
00337 }
00338 std::vector<geometry_msgs::Point> points;
00339 points.reserve( vvf.size() );
00340 for( unsigned int i = 0; i < vvf.size(); i++ )
00341 {
00342 if( vvf[ i ].size() == 2 )
00343 {
00344 geometry_msgs::Point point;
00345 point.x = vvf[ i ][ 0 ];
00346 point.y = vvf[ i ][ 1 ];
00347 point.z = 0;
00348 points.push_back( point );
00349 }
00350 else
00351 {
00352 ROS_ERROR( "Points in the footprint specification must be pairs of numbers. Found a point with %d numbers.",
00353 int( vvf[ i ].size() ));
00354 return false;
00355 }
00356 }
00357
00358 setUnpaddedRobotFootprint( points );
00359 return true;
00360 }
00361
00362 void Costmap2DROS::setFootprintFromRadius( double radius )
00363 {
00364 std::vector<geometry_msgs::Point> points;
00365
00366
00367 int N = 16;
00368 geometry_msgs::Point pt;
00369 for( int i = 0; i < N; ++i )
00370 {
00371 double angle = i * 2 * M_PI / N;
00372 pt.x = cos( angle ) * radius;
00373 pt.y = sin( angle ) * radius;
00374
00375 points.push_back( pt );
00376 }
00377
00378 setUnpaddedRobotFootprint( points );
00379 }
00380
00381 void Costmap2DROS::readFootprintFromParams( ros::NodeHandle& nh )
00382 {
00383 std::string full_param_name;
00384 std::string full_radius_param_name;
00385
00386 if( nh.searchParam( "footprint", full_param_name ))
00387 {
00388 XmlRpc::XmlRpcValue footprint_xmlrpc;
00389 nh.getParam( full_param_name, footprint_xmlrpc );
00390 if( footprint_xmlrpc.getType() == XmlRpc::XmlRpcValue::TypeString )
00391 {
00392 if( readFootprintFromString( std::string( footprint_xmlrpc )))
00393 {
00394 writeFootprintToParam( nh );
00395 }
00396 }
00397 else if( footprint_xmlrpc.getType() == XmlRpc::XmlRpcValue::TypeArray )
00398 {
00399 readFootprintFromXMLRPC( footprint_xmlrpc, full_param_name );
00400 writeFootprintToParam( nh );
00401 }
00402 }
00403 else if( nh.searchParam( "robot_radius", full_radius_param_name ))
00404 {
00405 double robot_radius;
00406 nh.param( full_radius_param_name, robot_radius, 1.234 );
00407 setFootprintFromRadius( robot_radius );
00408 nh.setParam( "robot_radius", robot_radius );
00409 }
00410
00411
00412
00413 }
00414
00415 void Costmap2DROS::writeFootprintToParam( ros::NodeHandle& nh )
00416 {
00417 ostringstream oss;
00418 bool first = true;
00419 for( unsigned int i = 0; i < unpadded_footprint_.size(); i++ )
00420 {
00421 geometry_msgs::Point& p = unpadded_footprint_[ i ];
00422 if( first )
00423 {
00424 oss << "[[" << p.x << "," << p.y << "]";
00425 first = false;
00426 }
00427 else
00428 {
00429 oss << ",[" << p.x << "," << p.y << "]";
00430 }
00431 }
00432 oss << "]";
00433 nh.setParam( "footprint", oss.str().c_str() );
00434 }
00435
00436 double getNumberFromXMLRPC( XmlRpc::XmlRpcValue& value, const std::string& full_param_name )
00437 {
00438
00439 if( value.getType() != XmlRpc::XmlRpcValue::TypeInt &&
00440 value.getType() != XmlRpc::XmlRpcValue::TypeDouble )
00441 {
00442 std::string& value_string = value;
00443 ROS_FATAL( "Values in the footprint specification (param %s) must be numbers. Found value %s.",
00444 full_param_name.c_str(), value_string.c_str() );
00445 throw std::runtime_error("Values in the footprint specification must be numbers");
00446 }
00447 return value.getType() == XmlRpc::XmlRpcValue::TypeInt ? (int)(value) : (double)(value);
00448 }
00449
00450 void Costmap2DROS::readFootprintFromXMLRPC( XmlRpc::XmlRpcValue& footprint_xmlrpc,
00451 const std::string& full_param_name )
00452 {
00453
00454 if( footprint_xmlrpc.getType() != XmlRpc::XmlRpcValue::TypeArray ||
00455 footprint_xmlrpc.size() < 3 )
00456 {
00457 ROS_FATAL( "The footprint must be specified as list of lists on the parameter server, %s was specified as %s",
00458 full_param_name.c_str(), std::string( footprint_xmlrpc ).c_str() );
00459 throw std::runtime_error( "The footprint must be specified as list of lists on the parameter server with at least 3 points eg: [[x1, y1], [x2, y2], ..., [xn, yn]]");
00460 }
00461
00462 std::vector<geometry_msgs::Point> footprint;
00463 geometry_msgs::Point pt;
00464
00465 for( int i = 0; i < footprint_xmlrpc.size(); ++i )
00466 {
00467
00468 XmlRpc::XmlRpcValue point = footprint_xmlrpc[ i ];
00469 if( point.getType() != XmlRpc::XmlRpcValue::TypeArray ||
00470 point.size() != 2 )
00471 {
00472 ROS_FATAL( "The footprint (parameter %s) must be specified as list of lists on the parameter server eg: [[x1, y1], [x2, y2], ..., [xn, yn]], but this spec is not of that form.",
00473 full_param_name.c_str() );
00474 throw std::runtime_error( "The footprint must be specified as list of lists on the parameter server eg: [[x1, y1], [x2, y2], ..., [xn, yn]], but this spec is not of that form" );
00475 }
00476
00477 pt.x = getNumberFromXMLRPC( point[ 0 ], full_param_name );
00478 pt.y = getNumberFromXMLRPC( point[ 1 ], full_param_name );
00479
00480 footprint.push_back( pt );
00481 }
00482
00483 setUnpaddedRobotFootprint( footprint );
00484 }
00485
00486 double sign(double x){
00487 return x < 0.0 ? -1.0 : (x > 0.0 ? 1.0 : 0.0);
00488 }
00489
00490 void Costmap2DROS::setUnpaddedRobotFootprint( const std::vector<geometry_msgs::Point>& points )
00491 {
00492 unpadded_footprint_ = points;
00493 padded_footprint_ = points;
00494
00495
00496 for( unsigned int i = 0; i < padded_footprint_.size(); i++ )
00497 {
00498 geometry_msgs::Point& pt = padded_footprint_[ i ];
00499 pt.x += sign( pt.x ) * footprint_padding_;
00500 pt.y += sign( pt.y ) * footprint_padding_;
00501 }
00502
00503 layered_costmap_->setFootprint( padded_footprint_ );
00504 }
00505
00506 void Costmap2DROS::movementCB(const ros::TimerEvent &event)
00507 {
00508
00509
00510
00511 tf::Stamped < tf::Pose > new_pose;
00512
00513 if (!getRobotPose(new_pose))
00514 {
00515 ROS_WARN_THROTTLE(1.0, "Could not get robot pose, cancelling reconfiguration");
00516 robot_stopped_ = false;
00517 }
00518
00519 else if (fabs((old_pose_.getOrigin() - new_pose.getOrigin()).length()) < 1e-3
00520 && fabs(old_pose_.getRotation().angle(new_pose.getRotation())) < 1e-3)
00521 {
00522 old_pose_ = new_pose;
00523 robot_stopped_ = true;
00524 }
00525 else
00526 {
00527 old_pose_ = new_pose;
00528 robot_stopped_ = false;
00529 }
00530 }
00531
00532 void Costmap2DROS::mapUpdateLoop(double frequency)
00533 {
00534
00535 if (frequency == 0.0)
00536 return;
00537
00538 ros::NodeHandle nh;
00539 ros::Rate r(frequency);
00540 while (nh.ok() && !map_update_thread_shutdown_)
00541 {
00542 struct timeval start, end;
00543 double start_t, end_t, t_diff;
00544 gettimeofday(&start, NULL);
00545
00546 updateMap();
00547
00548 gettimeofday(&end, NULL);
00549 start_t = start.tv_sec + double(start.tv_usec) / 1e6;
00550 end_t = end.tv_sec + double(end.tv_usec) / 1e6;
00551 t_diff = end_t - start_t;
00552 ROS_DEBUG("Map update time: %.9f", t_diff);
00553 if (publish_cycle.toSec() > 0 and layered_costmap_->isInitialized())
00554 {
00555 unsigned int x0, y0, xn, yn;
00556 layered_costmap_->getBounds(&x0, &xn, &y0, &yn);
00557 publisher_->updateBounds(x0, xn, y0, yn);
00558
00559 ros::Time now = ros::Time::now();
00560 if (last_publish_ + publish_cycle < now)
00561 {
00562 publisher_->publishCostmap();
00563 last_publish_ = now;
00564 }
00565 }
00566 r.sleep();
00567
00568 if (r.cycleTime() > ros::Duration(1 / frequency))
00569 ROS_WARN("Map update loop missed its desired rate of %.4fHz... the loop actually took %.4f seconds", frequency,
00570 r.cycleTime().toSec());
00571 }
00572 }
00573
00574 void Costmap2DROS::updateMap()
00575 {
00576 if (!stop_updates_)
00577 {
00578
00579 tf::Stamped < tf::Pose > pose;
00580 if (getRobotPose (pose))
00581 {
00582 layered_costmap_->updateMap(pose.getOrigin().x(), pose.getOrigin().y(), tf::getYaw(pose.getRotation()));
00583 initialized_ = true;
00584 }
00585 }
00586 }
00587
00588 void Costmap2DROS::start()
00589 {
00590 std::vector < boost::shared_ptr<Layer> > *plugins = layered_costmap_->getPlugins();
00591
00592 if (stopped_)
00593 {
00594
00595 for (vector<boost::shared_ptr<Layer> >::iterator plugin = plugins->begin(); plugin != plugins->end();
00596 ++plugin)
00597 {
00598 (*plugin)->activate();
00599 }
00600 stopped_ = false;
00601 }
00602 stop_updates_ = false;
00603
00604
00605 ros::Rate r(100.0);
00606 while (ros::ok() && !initialized_)
00607 r.sleep();
00608 }
00609
00610 void Costmap2DROS::stop()
00611 {
00612 stop_updates_ = true;
00613 std::vector < boost::shared_ptr<Layer> > *plugins = layered_costmap_->getPlugins();
00614
00615 for (vector<boost::shared_ptr<Layer> >::iterator plugin = plugins->begin(); plugin != plugins->end();
00616 ++plugin)
00617 {
00618 (*plugin)->deactivate();
00619 }
00620 initialized_ = false;
00621 stopped_ = true;
00622 }
00623
00624 void Costmap2DROS::pause()
00625 {
00626 stop_updates_ = true;
00627 initialized_ = false;
00628 }
00629
00630 void Costmap2DROS::resume()
00631 {
00632 stop_updates_ = false;
00633
00634
00635 ros::Rate r(100.0);
00636 while (!initialized_)
00637 r.sleep();
00638 }
00639
00640
00641 void Costmap2DROS::resetLayers()
00642 {
00643 Costmap2D* top = layered_costmap_->getCostmap();
00644 top->resetMap(0, 0, top->getSizeInCellsX(), top->getSizeInCellsY());
00645 std::vector < boost::shared_ptr<Layer> > *plugins = layered_costmap_->getPlugins();
00646 for (vector<boost::shared_ptr<Layer> >::iterator plugin = plugins->begin(); plugin != plugins->end();
00647 ++plugin)
00648 {
00649 (*plugin)->reset();
00650 }
00651 }
00652
00653 bool Costmap2DROS::getRobotPose(tf::Stamped<tf::Pose>& global_pose) const
00654 {
00655
00656 global_pose.setIdentity();
00657 tf::Stamped < tf::Pose > robot_pose;
00658 robot_pose.setIdentity();
00659 robot_pose.frame_id_ = robot_base_frame_;
00660 robot_pose.stamp_ = ros::Time();
00661 ros::Time current_time = ros::Time::now();
00662
00663
00664 try
00665 {
00666 tf_.transformPose(global_frame_, robot_pose, global_pose);
00667 }
00668 catch (tf::LookupException& ex)
00669 {
00670 ROS_ERROR_THROTTLE(1.0, "No Transform available Error looking up robot pose: %s\n", ex.what());
00671 return false;
00672 }
00673 catch (tf::ConnectivityException& ex)
00674 {
00675 ROS_ERROR_THROTTLE(1.0, "Connectivity Error looking up robot pose: %s\n", ex.what());
00676 return false;
00677 }
00678 catch (tf::ExtrapolationException& ex)
00679 {
00680 ROS_ERROR_THROTTLE(1.0, "Extrapolation Error looking up robot pose: %s\n", ex.what());
00681 return false;
00682 }
00683
00684 if (current_time.toSec() - global_pose.stamp_.toSec() > transform_tolerance_)
00685 {
00686 ROS_WARN_THROTTLE(1.0,
00687 "Costmap2DROS transform timeout. Current time: %.4f, global_pose stamp: %.4f, tolerance: %.4f",
00688 current_time.toSec(), global_pose.stamp_.toSec(), transform_tolerance_);
00689 return false;
00690 }
00691
00692 return true;
00693 }
00694
00695 void Costmap2DROS::getOrientedFootprint(std::vector<geometry_msgs::Point>& oriented_footprint) const {
00696 tf::Stamped<tf::Pose> global_pose;
00697 if(!getRobotPose(global_pose))
00698 return;
00699
00700 double yaw = tf::getYaw(global_pose.getRotation());
00701 getOrientedFootprint(global_pose.getOrigin().x(), global_pose.getOrigin().y(), yaw, oriented_footprint);
00702 }
00703
00704 void Costmap2DROS::getOrientedFootprint(double x, double y, double theta, std::vector<geometry_msgs::Point>& oriented_footprint) const {
00705
00706 double cos_th = cos(theta);
00707 double sin_th = sin(theta);
00708 for(unsigned int i = 0; i < padded_footprint_.size(); ++i){
00709 geometry_msgs::Point new_pt;
00710 new_pt.x = x + (padded_footprint_[i].x * cos_th - padded_footprint_[i].y * sin_th);
00711 new_pt.y = y + (padded_footprint_[i].x * sin_th + padded_footprint_[i].y * cos_th);
00712 oriented_footprint.push_back(new_pt);
00713 }
00714 }
00715
00716 }