costmap_2d_ros.cpp
Go to the documentation of this file.
00001 /*********************************************************************
00002  *
00003  * Software License Agreement (BSD License)
00004  *
00005  *  Copyright (c) 2008, 2013, Willow Garage, Inc.
00006  *  All rights reserved.
00007  *
00008  *  Redistribution and use in source and binary forms, with or without
00009  *  modification, are permitted provided that the following conditions
00010  *  are met:
00011  *
00012  *   * Redistributions of source code must retain the above copyright
00013  *     notice, this list of conditions and the following disclaimer.
00014  *   * Redistributions in binary form must reproduce the above
00015  *     copyright notice, this list of conditions and the following
00016  *     disclaimer in the documentation and/or other materials provided
00017  *     with the distribution.
00018  *   * Neither the name of Willow Garage, Inc. nor the names of its
00019  *     contributors may be used to endorse or promote products derived
00020  *     from this software without specific prior written permission.
00021  *
00022  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00023  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00024  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00025  *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00026  *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00027  *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00028  *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00029  *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00030  *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00031  *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
00032  *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00033  *  POSSIBILITY OF SUCH DAMAGE.
00034  *
00035  * Author: Eitan Marder-Eppstein
00036  *         David V. Lu!!
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   // get our tf prefix
00073   ros::NodeHandle prefix_nh;
00074   std::string tf_prefix = tf::getPrefixParam(prefix_nh);
00075 
00076   // get two frames
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   // make sure that we set the frames appropriately based on the tf_prefix
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   // we need to make sure that the transform between the robot base frame and the global frame is available
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   // check if we want a rolling window version of the costmap
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   // subscribe to the footprint topic
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   // create a thread to handle updating the map
00144   stop_updates_ = false;
00145   initialized_ = true;
00146   stopped_ = false;
00147 
00148   // Create a time r to check if the robot is moving
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   // find size parameters
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   // If the padding has changed, call setUnpaddedRobotFootprint() to
00283   // re-apply the padding.
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   // Only change the footprint if footprint or robot_radius has
00301   // changed.  Otherwise we might overwrite a footprint sent on a
00302   // topic by a dynamic_reconfigure call which was setting some other
00303   // variable.
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     // robot_radius may be 0, but that must be intended at this point.
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   // convert vvf into points.
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   // Loop over 16 angles around a circle making a point each time
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   // Else neither param was found anywhere this knows about, so
00411   // defaults will come from dynamic_reconfigure stuff, set in
00412   // cfg/Costmap2D.cfg and read in this file in reconfigureCB().
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   // Make sure that the value we're looking at is either a double or an int.
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   // Make sure we have an array of at least 3 elements.
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     // Make sure each element of the list is an array of size 2. (x and y coordinates)
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   // apply footprint_padding_ to padded_footprint_ (changing it in place).
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   //don't allow configuration to happen while this check occurs
00509   //boost::recursive_mutex::scoped_lock mcl(configuration_mutex_);
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   //make sure that the robot is not moving
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   // the user might not want to run the loop every cycle
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     // make sure to sleep for the remainder of our cycle time
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     //get global pose
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   // check if we're stopped or just paused
00592   if (stopped_)
00593   {
00594     // if we're stopped we need to re-subscribe to topics
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   // block until the costmap is re-initialized.. meaning one update cycle has run
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   // unsubscribe from topics
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   // block until the costmap is re-initialized.. meaning one update cycle has run
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(); // save time for checking tf delay later
00662 
00663   //get the global pose of the robot
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   // check global_pose timeout
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   //build the oriented footprint at the robot's current location
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 } // namespace layered_costmap


costmap_2d
Author(s): Eitan Marder-Eppstein, David V. Lu!!, Dave Hershberger, contradict@gmail.com
autogenerated on Thu Aug 27 2015 14:06:55