costmap_3d.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2014-2018, the neonavigation authors
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  *
8  * * Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  * * Redistributions in binary form must reproduce the above copyright
11  * notice, this list of conditions and the following disclaimer in the
12  * documentation and/or other materials provided with the distribution.
13  * * Neither the name of the copyright holder nor the names of its
14  * contributors may be used to endorse or promote products derived from
15  * this software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
21  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27  * POSSIBILITY OF SUCH DAMAGE.
28  */
29 
30 #include <ros/ros.h>
31 #include <geometry_msgs/PolygonStamped.h>
32 #include <nav_msgs/OccupancyGrid.h>
33 #include <sensor_msgs/PointCloud.h>
34 
35 #include <string>
36 #include <utility>
37 #include <vector>
38 
39 #include <costmap_cspace_msgs/CSpace3D.h>
40 #include <costmap_cspace_msgs/CSpace3DUpdate.h>
41 
44 
46 {
47 protected:
51  std::vector<ros::Subscriber> sub_map_overlay_;
57 
59  std::vector<
60  std::pair<nav_msgs::OccupancyGrid::ConstPtr,
62 
63  void cbMap(
64  const nav_msgs::OccupancyGrid::ConstPtr& msg,
66  {
67  if (map->getAngularGrid() <= 0)
68  {
69  ROS_ERROR("ang_resolution is not set.");
70  std::runtime_error("ang_resolution is not set.");
71  }
72  ROS_INFO("2D costmap received");
73 
74  map->setBaseMap(msg);
75  ROS_DEBUG("C-Space costmap generated");
76 
77  if (map_buffer_.size() > 0)
78  {
79  for (auto& map : map_buffer_)
80  cbMapOverlay(map.first, map.second);
81  ROS_INFO("%ld buffered costmaps processed", map_buffer_.size());
82  map_buffer_.clear();
83  }
84  }
86  const nav_msgs::OccupancyGrid::ConstPtr& msg,
88  {
89  ROS_DEBUG("Overlay 2D costmap received");
90 
91  auto map_msg = map->getMap();
92  if (map_msg->info.width < 1 ||
93  map_msg->info.height < 1)
94  {
95  map_buffer_.push_back(
96  std::pair<nav_msgs::OccupancyGrid::ConstPtr,
98  return;
99  }
100 
101  map->processMapOverlay(msg);
102  ROS_DEBUG("C-Space costmap updated");
103  }
106  const costmap_cspace_msgs::CSpace3DUpdate::Ptr update)
107  {
108  publishDebug(*map);
109  pub_costmap_.publish<costmap_cspace_msgs::CSpace3D>(*map);
110  return true;
111  }
112  bool cbUpdate(
114  const costmap_cspace_msgs::CSpace3DUpdate::Ptr update)
115  {
116  publishDebug(*map);
117  pub_costmap_update_.publish(*update);
118  return true;
119  }
120  void publishDebug(const costmap_cspace_msgs::CSpace3D& map)
121  {
122  if (pub_debug_.getNumSubscribers() == 0)
123  return;
124  sensor_msgs::PointCloud pc;
125  pc.header = map.header;
126  pc.header.stamp = ros::Time::now();
127  for (size_t yaw = 0; yaw < map.info.angle; yaw++)
128  {
129  for (unsigned int i = 0; i < map.info.width * map.info.height; i++)
130  {
131  int gx = i % map.info.width;
132  int gy = i / map.info.width;
133  if (map.data[i + yaw * map.info.width * map.info.height] < 100)
134  continue;
135  geometry_msgs::Point32 p;
136  p.x = gx * map.info.linear_resolution + map.info.origin.position.x;
137  p.y = gy * map.info.linear_resolution + map.info.origin.position.y;
138  p.z = yaw * 0.1;
139  pc.points.push_back(p);
140  }
141  }
142  pub_debug_.publish(pc);
143  }
144  void cbPublishFootprint(const ros::TimerEvent& event, const geometry_msgs::PolygonStamped msg)
145  {
146  auto footprint = msg;
147  footprint.header.stamp = ros::Time::now();
148  pub_footprint_.publish(footprint);
149  }
150 
152  const std::string overlay_mode_str)
153  {
154  if (overlay_mode_str == "overwrite")
155  {
157  }
158  else if (overlay_mode_str == "max")
159  {
161  }
162  ROS_FATAL("Unknown overlay_mode \"%s\"", overlay_mode_str.c_str());
163  throw std::runtime_error("Unknown overlay_mode.");
164  };
165 
166 public:
168  : nh_()
169  , pnh_("~")
170  {
172  pub_costmap_ = neonavigation_common::compat::advertise<costmap_cspace_msgs::CSpace3D>(
173  nh_, "costmap",
174  pnh_, "costmap", 1, true);
175  pub_costmap_update_ = neonavigation_common::compat::advertise<costmap_cspace_msgs::CSpace3DUpdate>(
176  nh_, "costmap_update",
177  pnh_, "costmap_update", 1, true);
178  pub_footprint_ = pnh_.advertise<geometry_msgs::PolygonStamped>("footprint", 2, true);
179  pub_debug_ = pnh_.advertise<sensor_msgs::PointCloud>("debug", 1, true);
180 
181  int ang_resolution;
182  pnh_.param("ang_resolution", ang_resolution, 16);
183 
184  XmlRpc::XmlRpcValue footprint_xml;
185  if (!pnh_.hasParam("footprint"))
186  {
187  ROS_FATAL("Footprint doesn't specified");
188  throw std::runtime_error("Footprint doesn't specified.");
189  }
190  pnh_.getParam("footprint", footprint_xml);
191  costmap_cspace::Polygon footprint;
192  try
193  {
194  footprint = costmap_cspace::Polygon(footprint_xml);
195  }
196  catch (const std::exception& e)
197  {
198  ROS_FATAL("Invalid footprint");
199  throw e;
200  }
201 
202  costmap_.reset(new costmap_cspace::Costmap3d(ang_resolution));
203 
204  auto root_layer = costmap_->addRootLayer<costmap_cspace::Costmap3dLayerFootprint>();
205  float linear_expand;
206  float linear_spread;
207  pnh_.param("linear_expand", linear_expand, 0.2f);
208  pnh_.param("linear_spread", linear_spread, 0.5f);
209  root_layer->setExpansion(linear_expand, linear_spread);
210  root_layer->setFootprint(footprint);
211 
212  if (pnh_.hasParam("static_layers"))
213  {
214  XmlRpc::XmlRpcValue layers_xml;
215  pnh_.getParam("static_layers", layers_xml);
216 
217  if (layers_xml.getType() != XmlRpc::XmlRpcValue::TypeArray || layers_xml.size() < 1)
218  {
219  ROS_FATAL("static_layers parameter must contain at least one layer config.");
220  ROS_ERROR(
221  "Migration from old version:\n"
222  "--- # Old\n"
223  "static_layers:\n"
224  " YOUR_LAYER_NAME:\n"
225  " type: LAYER_TYPE\n"
226  " parameters: values\n"
227  "--- # New\n"
228  "static_layers:\n"
229  " - name: YOUR_LAYER_NAME\n"
230  " type: LAYER_TYPE\n"
231  " parameters: values\n"
232  "---\n");
233  throw std::runtime_error("layers parameter must contain at least one layer config.");
234  }
235  for (int i = 0; i < layers_xml.size(); ++i)
236  {
237  auto layer_xml = std::pair<std::string, XmlRpc::XmlRpcValue>(
238  layers_xml[i]["name"], layers_xml[i]);
239  ROS_INFO("New static layer: %s", layer_xml.first.c_str());
240 
242  if (layer_xml.second["overlay_mode"].getType() == XmlRpc::XmlRpcValue::TypeString)
243  overlay_mode = getMapOverlayModeFromString(
244  layer_xml.second["overlay_mode"]);
245  else
246  ROS_WARN("overlay_mode of the static layer is not specified. Using MAX mode.");
247 
248  std::string type;
249  if (layer_xml.second["type"].getType() == XmlRpc::XmlRpcValue::TypeString)
250  type = std::string(layer_xml.second["type"]);
251  else
252  {
253  ROS_FATAL("Layer type is not specified.");
254  throw std::runtime_error("Layer type is not specified.");
255  }
256 
257  if (!layer_xml.second.hasMember("footprint"))
258  layer_xml.second["footprint"] = footprint_xml;
259 
262  costmap_->addLayer(layer, overlay_mode);
263  layer->loadConfig(layer_xml.second);
264 
265  sub_map_overlay_.push_back(nh_.subscribe<nav_msgs::OccupancyGrid>(
266  layer_xml.first, 1,
267  boost::bind(&Costmap3DOFNode::cbMapOverlay, this, _1, layer)));
268  }
269  }
270 
271  auto static_output_layer = costmap_->addLayer<costmap_cspace::Costmap3dLayerOutput>();
272  static_output_layer->setHandler(boost::bind(&Costmap3DOFNode::cbUpdateStatic, this, _1, _2));
273 
274  sub_map_ = nh_.subscribe<nav_msgs::OccupancyGrid>(
275  "map", 1,
276  boost::bind(&Costmap3DOFNode::cbMap, this, _1, root_layer));
277 
278  if (pnh_.hasParam("layers"))
279  {
280  XmlRpc::XmlRpcValue layers_xml;
281  pnh_.getParam("layers", layers_xml);
282 
283  if (layers_xml.getType() != XmlRpc::XmlRpcValue::TypeArray || layers_xml.size() < 1)
284  {
285  ROS_FATAL("layers parameter must contain at least one layer config.");
286  ROS_ERROR(
287  "Migration from old version:\n"
288  "--- # Old\n"
289  "layers:\n"
290  " YOUR_LAYER_NAME:\n"
291  " type: LAYER_TYPE\n"
292  " parameters: values\n"
293  "--- # New\n"
294  "layers:\n"
295  " - name: YOUR_LAYER_NAME\n"
296  " type: LAYER_TYPE\n"
297  " parameters: values\n"
298  "---\n");
299  throw std::runtime_error("layers parameter must contain at least one layer config.");
300  }
301  for (int i = 0; i < layers_xml.size(); ++i)
302  {
303  auto layer_xml = std::pair<std::string, XmlRpc::XmlRpcValue>(
304  layers_xml[i]["name"], layers_xml[i]);
305  ROS_INFO("New layer: %s", layer_xml.first.c_str());
306 
308  if (layer_xml.second["overlay_mode"].getType() == XmlRpc::XmlRpcValue::TypeString)
309  overlay_mode = getMapOverlayModeFromString(
310  layer_xml.second["overlay_mode"]);
311  else
312  ROS_WARN("overlay_mode of the layer is not specified. Using MAX mode.");
313 
314  std::string type;
315  if (layer_xml.second["type"].getType() == XmlRpc::XmlRpcValue::TypeString)
316  type = std::string(layer_xml.second["type"]);
317  else
318  {
319  ROS_FATAL("Layer type is not specified.");
320  throw std::runtime_error("Layer type is not specified.");
321  }
322 
323  if (!layer_xml.second.hasMember("footprint"))
324  layer_xml.second["footprint"] = footprint_xml;
325 
328  costmap_->addLayer(layer, overlay_mode);
329  layer->loadConfig(layer_xml.second);
330 
331  sub_map_overlay_.push_back(nh_.subscribe<nav_msgs::OccupancyGrid>(
332  layer_xml.first, 1,
333  boost::bind(&Costmap3DOFNode::cbMapOverlay, this, _1, layer)));
334  }
335  }
336  else
337  {
338  // Single layer mode for backward-compatibility
339  costmap_cspace::MapOverlayMode overlay_mode;
340  std::string overlay_mode_str;
341  pnh_.param("overlay_mode", overlay_mode_str, std::string("max"));
342  if (overlay_mode_str.compare("overwrite") == 0)
344  else if (overlay_mode_str.compare("max") == 0)
346  else
347  {
348  ROS_FATAL("Unknown overlay_mode \"%s\"", overlay_mode_str.c_str());
349  throw std::runtime_error("Unknown overlay_mode.");
350  }
351  ROS_INFO("costmap_3d: %s mode", overlay_mode_str.c_str());
352 
353  XmlRpc::XmlRpcValue layer_xml;
354  layer_xml["footprint"] = footprint_xml;
355  layer_xml["linear_expand"] = linear_expand;
356  layer_xml["linear_spread"] = linear_spread;
357 
358  auto layer = costmap_->addLayer<costmap_cspace::Costmap3dLayerFootprint>(overlay_mode);
359  layer->loadConfig(layer_xml);
360  sub_map_overlay_.push_back(nh_.subscribe<nav_msgs::OccupancyGrid>(
361  "map_overlay", 1,
362  boost::bind(&Costmap3DOFNode::cbMapOverlay, this, _1, layer)));
363  }
364 
365  auto update_output_layer = costmap_->addLayer<costmap_cspace::Costmap3dLayerOutput>();
366  update_output_layer->setHandler(boost::bind(&Costmap3DOFNode::cbUpdate, this, _1, _2));
367 
368  const geometry_msgs::PolygonStamped footprint_msg = footprint.toMsg();
369  timer_footprint_ = nh_.createTimer(
370  ros::Duration(1.0),
371  boost::bind(&Costmap3DOFNode::cbPublishFootprint, this, _1, footprint_msg));
372  }
373 };
374 
375 int main(int argc, char* argv[])
376 {
377  ros::init(argc, argv, "costmap_3d");
378 
379  Costmap3DOFNode cm;
380  ros::spin();
381 
382  return 0;
383 }
#define ROS_FATAL(...)
void publish(const boost::shared_ptr< M > &message) const
f
int size() const
void setExpansion(const float linear_expand, const float linear_spread)
Definition: footprint.h:77
ROSCPP_DECL void init(int &argc, char **argv, const std::string &name, uint32_t options=0)
void loadConfig(XmlRpc::XmlRpcValue config)
Definition: footprint.h:70
geometry_msgs::PolygonStamped toMsg() const
Definition: polygon.h:119
void cbMapOverlay(const nav_msgs::OccupancyGrid::ConstPtr &msg, const costmap_cspace::Costmap3dLayerBase::Ptr map)
Definition: costmap_3d.cpp:85
Type const & getType() const
std::vector< ros::Subscriber > sub_map_overlay_
Definition: costmap_3d.cpp:51
#define ROS_WARN(...)
bool cbUpdate(const costmap_cspace::CSpace3DMsg::Ptr map, const costmap_cspace_msgs::CSpace3DUpdate::Ptr update)
Definition: costmap_3d.cpp:112
ROSCPP_DECL void spin(Spinner &spinner)
ros::Timer timer_footprint_
Definition: costmap_3d.cpp:56
ros::NodeHandle pnh_
Definition: costmap_3d.cpp:49
MapOverlayMode
Definition: base.h:80
ros::Publisher pub_debug_
Definition: costmap_3d.cpp:55
#define ROS_INFO(...)
bool cbUpdateStatic(const costmap_cspace::CSpace3DMsg::Ptr map, const costmap_cspace_msgs::CSpace3DUpdate::Ptr update)
Definition: costmap_3d.cpp:104
ros::NodeHandle nh_
Definition: costmap_3d.cpp:48
std::vector< std::pair< nav_msgs::OccupancyGrid::ConstPtr, costmap_cspace::Costmap3dLayerBase::Ptr > > map_buffer_
Definition: costmap_3d.cpp:61
uint32_t getNumSubscribers() const
static costmap_cspace::MapOverlayMode getMapOverlayModeFromString(const std::string overlay_mode_str)
Definition: costmap_3d.cpp:151
std::shared_ptr< CSpace3DMsg > Ptr
Definition: base.h:50
ros::Publisher pub_footprint_
Definition: costmap_3d.cpp:54
void publishDebug(const costmap_cspace_msgs::CSpace3D &map)
Definition: costmap_3d.cpp:120
costmap_cspace::Costmap3d::Ptr costmap_
Definition: costmap_3d.cpp:58
static Time now()
std::shared_ptr< Costmap3dLayerBase > Ptr
Definition: base.h:210
ros::Publisher pub_costmap_update_
Definition: costmap_3d.cpp:53
void cbPublishFootprint(const ros::TimerEvent &event, const geometry_msgs::PolygonStamped msg)
Definition: costmap_3d.cpp:144
void setHandler(Callback cb)
Definition: output.h:56
std::shared_ptr< Costmap3d > Ptr
Definition: costmap_3d.h:54
#define ROS_ERROR(...)
ros::Subscriber sub_map_
Definition: costmap_3d.cpp:50
ros::Publisher pub_costmap_
Definition: costmap_3d.cpp:52
int main(int argc, char *argv[])
Definition: costmap_3d.cpp:375
static Costmap3dLayerBase::Ptr loadClass(const std::string &name)
Definition: class_loader.h:70
void cbMap(const nav_msgs::OccupancyGrid::ConstPtr &msg, const costmap_cspace::Costmap3dLayerBase::Ptr map)
Definition: costmap_3d.cpp:63
#define ROS_DEBUG(...)


costmap_cspace
Author(s): Atsushi Watanabe
autogenerated on Tue Jul 9 2019 04:59:48