Skip to content

Commit b4b9cc9

Browse files
committed
Alternative to ros-planning#641: Checking which layers to clear
1 parent 7d7e7e0 commit b4b9cc9

File tree

1 file changed

+102
-13
lines changed

1 file changed

+102
-13
lines changed

clear_costmap_recovery/src/clear_costmap_recovery.cpp

+102-13
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,58 @@ PLUGINLIB_EXPORT_CLASS(clear_costmap_recovery::ClearCostmapRecovery, nav_core::R
4444
using costmap_2d::NO_INFORMATION;
4545

4646
namespace clear_costmap_recovery {
47+
48+
/**
49+
* @brief return the names of the layers in the costmap, each prefixed with prefix
50+
*/
51+
std::vector<std::string> getLayerNames(const costmap_2d::Costmap2DROS& costmap)
52+
{
53+
std::vector<std::string> names;
54+
std::vector<boost::shared_ptr<costmap_2d::Layer> >* plugins = costmap.getLayeredCostmap()->getPlugins();
55+
for (std::vector<boost::shared_ptr<costmap_2d::Layer> >::const_iterator pluginp = plugins->begin();
56+
pluginp != plugins->end();
57+
++pluginp) {
58+
names.push_back((*pluginp)->getName());
59+
}
60+
return names;
61+
}
62+
63+
/**
64+
* @brief A layer is considered "matching" if the raw name (after the slash) is in the name_specs set
65+
*/
66+
bool isMatchingLayerName(const std::string& layer_name, const std::set<std::string>& name_specs)
67+
{
68+
size_t slash = layer_name.rfind('/');
69+
if(slash != std::string::npos)
70+
{
71+
// If no slash, use whole string
72+
return name_specs.count(layer_name) != 0;
73+
}
74+
else
75+
{
76+
// Check the part after the slash
77+
return name_specs.count(layer_name.substr(slash + 1)) != 0;
78+
}
79+
}
80+
81+
/**
82+
* @brief Returns the subset of layer_names which match the name spec
83+
*/
84+
std::vector<std::string> getLayerMatches(const std::vector<std::string>& layer_names,
85+
const std::set<std::string>& name_specs)
86+
{
87+
std::vector<std::string> matches;
88+
for (unsigned int i = 0; i < layer_names.size(); i++)
89+
{
90+
if (isMatchingLayerName(layer_names[i], name_specs))
91+
{
92+
matches.push_back(layer_names[i]);
93+
}
94+
}
95+
return matches;
96+
}
97+
98+
4799
ClearCostmapRecovery::ClearCostmapRecovery(): global_costmap_(NULL), local_costmap_(NULL),
48100
tf_(NULL), initialized_(false) {}
49101

@@ -68,13 +120,55 @@ void ClearCostmapRecovery::initialize(std::string name, tf2_ros::Buffer* tf,
68120
affected_maps_ = "both";
69121
}
70122

71-
std::vector<std::string> clearable_layers_default, clearable_layers;
72-
clearable_layers_default.push_back( std::string("obstacles") );
73-
private_nh.param("layer_names", clearable_layers, clearable_layers_default);
123+
// Get a list of layer names
124+
std::vector<std::string> layer_names = getLayerNames(*global_costmap_);
125+
std::vector<std::string> local_layer_names = getLayerNames(*local_costmap_);
126+
layer_names.insert(layer_names.end(), local_layer_names.begin(), local_layer_names.end());
127+
128+
std::vector<std::string> clearable_layers_vector;
129+
if (private_nh.getParam("layer_names", clearable_layers_vector))
130+
{
131+
clearable_layers_ = std::set<std::string>(clearable_layers_vector.begin(), clearable_layers_vector.end());
132+
}
133+
else
134+
{
135+
// If the parameter is not specified, try two different defaults
136+
std::vector<std::string> possible_defaults {"obstacles", "obstacle_layer"};
137+
for (unsigned int i = 0; i < possible_defaults.size(); i++)
138+
{
139+
std::set<std::string> default_set;
140+
default_set.insert(possible_defaults[i]);
141+
if (getLayerMatches(layer_names, default_set).size() > 0)
142+
{
143+
clearable_layers_ = default_set;
144+
break;
145+
}
146+
}
147+
}
74148

75-
for(unsigned i=0; i < clearable_layers.size(); i++) {
76-
ROS_INFO("Recovery behavior will clear layer '%s'", clearable_layers[i].c_str());
77-
clearable_layers_.insert(clearable_layers[i]);
149+
std::vector<std::string> clearable_layer_names = getLayerMatches(layer_names, clearable_layers_);
150+
if (clearable_layer_names.empty())
151+
{
152+
ROS_ERROR("In recovery behavior %s, none of the layer names match the layer_names parameter.", name.c_str());
153+
ROS_ERROR("Layer names:");
154+
for (unsigned int i = 0; i < layer_names.size(); i++)
155+
{
156+
ROS_ERROR("\t%s", layer_names[i].c_str());
157+
}
158+
ROS_ERROR("Value of %s:", private_nh.resolveName("layer_names").c_str());
159+
for (std::set<std::string>::const_iterator it = clearable_layers_.begin();
160+
it != clearable_layers_.end();
161+
++it) {
162+
ROS_ERROR("\t%s", it->c_str());
163+
}
164+
}
165+
else
166+
{
167+
ROS_INFO("Recovery behavior %s will clear layers:", name.c_str());
168+
for(unsigned int i = 0; i < clearable_layer_names.size(); i++)
169+
{
170+
ROS_INFO("\t%s", clearable_layer_names[i].c_str());
171+
}
78172
}
79173

80174
initialized_ = true;
@@ -136,13 +230,8 @@ void ClearCostmapRecovery::clear(costmap_2d::Costmap2DROS* costmap){
136230

137231
for (std::vector<boost::shared_ptr<costmap_2d::Layer> >::iterator pluginp = plugins->begin(); pluginp != plugins->end(); ++pluginp) {
138232
boost::shared_ptr<costmap_2d::Layer> plugin = *pluginp;
139-
std::string name = plugin->getName();
140-
int slash = name.rfind('/');
141-
if( slash != std::string::npos ){
142-
name = name.substr(slash+1);
143-
}
144-
145-
if(clearable_layers_.count(name)!=0){
233+
if (isMatchingLayerName(plugin->getName(), clearable_layers_))
234+
{
146235
boost::shared_ptr<costmap_2d::CostmapLayer> costmap;
147236
costmap = boost::static_pointer_cast<costmap_2d::CostmapLayer>(plugin);
148237
clearMap(costmap, x, y);

0 commit comments

Comments
 (0)