RAPP Platform  v0.6.0
RAPP Platform is a collection of ROS nodes and back-end processes that aim to deliver ready-to-use generic services to robots
 All Classes Namespaces Files Functions Variables Macros
rapp_static_layer.cpp
Go to the documentation of this file.
1 /*********************************************************************
2  *
3  * Software License Agreement (BSD License)
4  *
5  * Copyright (c) 2008, 2013, Willow Garage, Inc.
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * * Redistributions of source code must retain the above copyright
13  * notice, this list of conditions and the following disclaimer.
14  * * Redistributions in binary form must reproduce the above
15  * copyright notice, this list of conditions and the following
16  * disclaimer in the documentation and/or other materials provided
17  * with the distribution.
18  * * Neither the name of Willow Garage, Inc. nor the names of its
19  * contributors may be used to endorse or promote products derived
20  * from this software without specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
25  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
26  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
27  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
28  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
30  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
32  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33  * POSSIBILITY OF SUCH DAMAGE.
34  *
35  * Author: Eitan Marder-Eppstein
36  * David V. Lu!!
37  *********************************************************************/
39 #include <costmap_2d/costmap_math.h>
40 #include <pluginlib/class_list_macros.h>
41 
42 PLUGINLIB_EXPORT_CLASS(costmap_2d::RappStaticLayer, costmap_2d::Layer)
43 
44 using costmap_2d::NO_INFORMATION;
45 using costmap_2d::LETHAL_OBSTACLE;
46 using costmap_2d::FREE_SPACE;
47 
48 namespace costmap_2d
49 {
50 RappStaticLayer::RappStaticLayer() : dsrv_(NULL) {}
51 
53 {
54  if(dsrv_)
55  delete dsrv_;
56 }
57 
59 {
60  ros::NodeHandle nh("~/" + name_), g_nh;
61  current_ = true;
62 
63  global_frame_ = layered_costmap_->getGlobalFrameID();
64 
65  std::string map_service;
66  nh.param("map_service", map_service, std::string("/static_map"));
67  nh.param("subscribe_to_updates", subscribe_to_updates_, false);
68 
69  nh.param("track_unknown_space", track_unknown_space_, true);
70  nh.param("use_maximum", use_maximum_, false);
71 
72  int temp_lethal_threshold, temp_unknown_cost_value;
73  nh.param("lethal_cost_threshold", temp_lethal_threshold, int(100));
74  nh.param("unknown_cost_value", temp_unknown_cost_value, int(-1));
75  nh.param("trinary_costmap", trinary_costmap_, true);
76 
77  lethal_threshold_ = std::max(std::min(temp_lethal_threshold, 100), 0);
78  unknown_cost_value_ = temp_unknown_cost_value;
79  //we'll subscribe to the latched topic that the map server uses
80  ROS_INFO("Requesting the map...");
81 
82  ros::ServiceManager srv_manager;
83 std::string host_name;
84 uint32_t port_srv;
85  ROS_DEBUG_STREAM("COSTMAP calls:\n" << map_service);
86 
87  if (srv_manager.lookupService(map_service,host_name, port_srv)){
88  ros::ServiceClient map_client = nh.serviceClient<nav_msgs::GetMap>(map_service);
89  nav_msgs::GetMap srv;
90 
91  if (map_client.call(srv))
92  {
93  nav_msgs::OccupancyGrid const new_map = srv.response.map;
94 
95 auto a_ptr=boost::make_shared<::nav_msgs::OccupancyGrid const>(new_map);
96  // nav_msgs::OccupancyGrid *new_map = new res.map;
97  // boost::shared_ptr<nav_msgs::OccupancyGrid> new_map_ptr(new_map);
98  nav_msgs::OccupancyGridConstPtr const new_map_occupancy_ptr = a_ptr;
99  RappStaticLayer::incomingMap(new_map_occupancy_ptr);
100  // ROS_INFO("Costmap2D got new map");
101  // std::string node_name = ros::this_node::getName();
102  // ros::ServiceServer costmap_update_service = g_nh.advertiseService(node_name+"/costmap_map_update", &RappStaticLayer::incomingUpdateService, this);
103 
104  }
105 
106  else
107  {
108  ROS_ERROR("Costmap2D can not request new map from rapp_map_server");
109  ROS_ERROR_STREAM("Requested service:\n"<<map_service);
110  }
111 
112  }
113  //map_sub_ = g_nh.subscribe(map_service, 1, &RappStaticLayer::incomingMap, this);
114  map_received_ = true;
115  has_updated_data_ = true;
116 
117  ros::Rate r(10);
118  while (!map_received_ && g_nh.ok())
119  {
120  ros::spinOnce();
121  r.sleep();
122  }
123  std::string node_name = ros::this_node::getName();
124  // std::cout << "NODENAME= " << node_name <<std::endl;
125  ROS_INFO_STREAM("Starting rapp_costmap for: " << node_name);
126 
127  ROS_INFO("Received a %d X %d map at %f m/pix", getSizeInCellsX(), getSizeInCellsY(), getResolution());
128 
129 // if(subscribe_to_updates_)
130 // {
131  // std::string node_name = ros::this_node::getName();
132  ROS_DEBUG("Subscribing to updates");
133  costmap_update_service = g_nh.advertiseService(node_name+"/costmap_map_update", &RappStaticLayer::incomingUpdateService, this);
134 
135  //map_update_sub_ = g_nh.advertizeService("/"+name_ + "_costmap_update", 10, &RappStaticLayer::incomingUpdate, this);
136  // }
137 
138  if(dsrv_)
139  {
140  delete dsrv_;
141  }
142 
143  dsrv_ = new dynamic_reconfigure::Server<costmap_2d::GenericPluginConfig>(nh);
144  dynamic_reconfigure::Server<costmap_2d::GenericPluginConfig>::CallbackType cb = boost::bind(
145  &RappStaticLayer::reconfigureCB, this, _1, _2);
146  dsrv_->setCallback(cb);
147 }
148 bool RappStaticLayer::incomingUpdateService( rapp_platform_ros_communications::Costmap2dRosSrvRequest& req,
149  rapp_platform_ros_communications::Costmap2dRosSrvResponse& res){
150 
151  nav_msgs::OccupancyGrid const new_map = req.map;
152 
153 auto a_ptr=boost::make_shared<::nav_msgs::OccupancyGrid const>(new_map);
154  // nav_msgs::OccupancyGrid *new_map = new res.map;
155  // boost::shared_ptr<nav_msgs::OccupancyGrid> new_map_ptr(new_map);
156  nav_msgs::OccupancyGridConstPtr const new_map_occupancy_ptr = a_ptr;
157  RappStaticLayer::incomingMap(new_map_occupancy_ptr);
158  res.status = true;
159  return true;
160 }
161 void RappStaticLayer::reconfigureCB(costmap_2d::GenericPluginConfig &config, uint32_t level)
162 {
163  if (config.enabled != enabled_)
164  {
165  enabled_ = config.enabled;
166  has_updated_data_ = true;
167  x_ = y_ = 0;
168  width_ = size_x_;
169  height_ = size_y_;
170  }
171 }
172 
174 {
175  Costmap2D* master = layered_costmap_->getCostmap();
176  resizeMap(master->getSizeInCellsX(), master->getSizeInCellsY(), master->getResolution(),
177  master->getOriginX(), master->getOriginY());
178 }
179 
180 unsigned char RappStaticLayer::interpretValue(unsigned char value)
181 {
182  //check if the static value is above the unknown or lethal thresholds
184  return NO_INFORMATION;
185  else if (value >= lethal_threshold_)
186  return LETHAL_OBSTACLE;
187  else if (trinary_costmap_)
188  return FREE_SPACE;
189 
190  double scale = (double) value / lethal_threshold_;
191  return scale * LETHAL_OBSTACLE;
192 }
193 
194 void RappStaticLayer::incomingMap(const nav_msgs::OccupancyGridConstPtr& new_map)
195 {
196  unsigned int size_x = new_map->info.width, size_y = new_map->info.height;
197 
198  ROS_DEBUG("Received a %d X %d map at %f m/pix", size_x, size_y, new_map->info.resolution);
199 
200  // resize costmap if size, resolution or origin do not match
201  Costmap2D* master = layered_costmap_->getCostmap();
202  if (master->getSizeInCellsX() != size_x ||
203  master->getSizeInCellsY() != size_y ||
204  master->getResolution() != new_map->info.resolution ||
205  master->getOriginX() != new_map->info.origin.position.x ||
206  master->getOriginY() != new_map->info.origin.position.y ||
207  !layered_costmap_->isSizeLocked())
208  {
209  ROS_INFO("Resizing costmap to %d X %d at %f m/pix", size_x, size_y, new_map->info.resolution);
210  layered_costmap_->resizeMap(size_x, size_y, new_map->info.resolution, new_map->info.origin.position.x,
211  new_map->info.origin.position.y, true);
212  }else if(size_x_ != size_x || size_y_ != size_y ||
213  resolution_ != new_map->info.resolution ||
214  origin_x_ != new_map->info.origin.position.x ||
215  origin_y_ != new_map->info.origin.position.y){
216  matchSize();
217  }
218 
219  unsigned int index = 0;
220 
221  //initialize the costmap with static data
222  for (unsigned int i = 0; i < size_y; ++i)
223  {
224  for (unsigned int j = 0; j < size_x; ++j)
225  {
226  unsigned char value = new_map->data[index];
227  costmap_[index] = interpretValue(value);
228  ++index;
229  }
230  }
231  x_ = y_ = 0;
232  width_ = size_x_;
233  height_ = size_y_;
234  map_received_ = true;
235  has_updated_data_ = true;
236 }
237 
238 void RappStaticLayer::incomingUpdate(const map_msgs::OccupancyGridUpdateConstPtr& update)
239 {
240  unsigned int di = 0;
241  for (unsigned int y = 0; y < update->height ; y++)
242  {
243  unsigned int index_base = (update->y + y) * size_x_;
244  for (unsigned int x = 0; x < update->width ; x++)
245  {
246  unsigned int index = index_base + x + update->x;
247  costmap_[index] = interpretValue( update->data[di++] );
248  }
249  }
250  x_ = update->x;
251  y_ = update->y;
252  width_ = update->width;
253  height_ = update->height;
254  has_updated_data_ = true;
255 }
256 
258 {
259  onInitialize();
260 }
261 
263 {
264  map_sub_.shutdown();
266  map_update_sub_.shutdown();
267 }
268 
270 {
271  deactivate();
272  activate();
273 }
274 
275 void RappStaticLayer::updateBounds(double robot_x, double robot_y, double robot_yaw, double* min_x, double* min_y,
276  double* max_x, double* max_y)
277 {
278  if (!map_received_ || !(has_updated_data_ || has_extra_bounds_))
279  return;
280 
281  useExtraBounds(min_x, min_y, max_x, max_y);
282 
283  double mx, my;
284 
285  mapToWorld(x_, y_, mx, my);
286  *min_x = std::min(mx, *min_x);
287  *min_y = std::min(my, *min_y);
288 
289  mapToWorld(x_ + width_, y_ + height_, mx, my);
290  *max_x = std::max(mx, *max_x);
291  *max_y = std::max(my, *max_y);
292 
293  has_updated_data_ = false;
294 }
295 
296 void RappStaticLayer::updateCosts(costmap_2d::Costmap2D& master_grid, int min_i, int min_j, int max_i, int max_j)
297 {
298  if (!map_received_)
299  return;
300  if (!use_maximum_)
301  updateWithTrueOverwrite(master_grid, min_i, min_j, max_i, max_j);
302  else
303  updateWithMax(master_grid, min_i, min_j, max_i, max_j);
304 }
305 
306 } // namespace rapp_costmap_2d
virtual void updateBounds(double robot_x, double robot_y, double robot_yaw, double *min_x, double *min_y, double *max_x, double *max_y)
std::string global_frame_
The global frame for the costmap.
virtual void updateCosts(costmap_2d::Costmap2D &master_grid, int min_i, int min_j, int max_i, int max_j)
bool incomingUpdateService(rapp_platform_ros_communications::Costmap2dRosSrvRequest &req, rapp_platform_ros_communications::Costmap2dRosSrvResponse &res)
void incomingUpdate(const map_msgs::OccupancyGridUpdateConstPtr &update)
ros::ServiceServer costmap_update_service
unsigned char interpretValue(unsigned char value)
void incomingMap(const nav_msgs::OccupancyGridConstPtr &new_map)
Callback to update the costmap's map from the map_server.
void reconfigureCB(costmap_2d::GenericPluginConfig &config, uint32_t level)
dynamic_reconfigure::Server< costmap_2d::GenericPluginConfig > * dsrv_