Skip to content

Commit 841c50c

Browse files
authored
Merge pull request #90 from naturerobots/fix/cost-layers-get-lost-over-network-connections
Move cost layer publishing responsibility to the layer manager
2 parents f178977 + ea7beea commit 841c50c

5 files changed

Lines changed: 101 additions & 86 deletions

File tree

mesh_map/include/mesh_map/layer_manager.h

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,9 @@
4747
#include <mesh_map/abstract_layer.h>
4848
#include <mesh_map/definitions.h>
4949

50+
#include <mesh_msgs/msg/mesh_vertex_costs_stamped.hpp>
51+
#include <mesh_msgs/msg/mesh_vertex_costs_sparse_stamped.hpp>
52+
5053
namespace mesh_map
5154
{
5255

@@ -55,9 +58,9 @@ class LayerManager
5558
public:
5659

5760
/**
58-
* @brief Read the configured layers and dependencies from the node
61+
* @brief Read the configured layers and dependencies from the stored node
5962
*/
60-
void read_configured_layers(const rclcpp::Node::SharedPtr& node);
63+
void read_configured_layers();
6164

6265
/**
6366
* @brief Create instances of the configured layers
@@ -69,7 +72,7 @@ class LayerManager
6972
* @brief Initialize all layer plugins and load or compute their values
7073
* @return true If all loaded layers were initialized sucessfully
7174
*/
72-
bool initialize_layer_plugins(const rclcpp::Node::SharedPtr& node, const std::shared_ptr<MeshMap>& map);
75+
bool initialize_layer_plugins(const std::shared_ptr<MeshMap>& map);
7376

7477
/**
7578
* @brief Get the plugin type of a layer
@@ -109,6 +112,22 @@ class LayerManager
109112
return instances_;
110113
}
111114

115+
/**
116+
* @brief Publishes the given vertex map as mesh_msgs/VertexCosts, e.g. to visualize these.
117+
* @param costs The cost map to publish
118+
* @param name The name of the cost map
119+
* @param timestamp The timestamp of the cost layer
120+
*/
121+
void publish_cost_layer(const lvr2::VertexMap<float>& costs, const std::string& name, const rclcpp::Time& timestamp);
122+
123+
/**
124+
* @brief Publishes the given vertex map as mesh_msgs/VertexCostsSparse, e.g. to update the visualization in RVIZ.
125+
* @param costs The cost map to publish
126+
* @param name The name of the cost map
127+
* @param timestamp The timestamp of the cost update
128+
*/
129+
void publish_cost_update(const lvr2::VertexMap<float>& costs, const float default_value, const std::string& name, const rclcpp::Time& timestamp);
130+
112131
/**
113132
* @brief Init the layer manager. Stores a reference to the map, which is not used
114133
* in the constructor!
@@ -162,6 +181,13 @@ class LayerManager
162181
//! Maps layer name to instance
163182
std::map<std::string, std::shared_ptr<AbstractLayer>> instances_;
164183

184+
//! Publisher for vertex costs
185+
rclcpp::Publisher<mesh_msgs::msg::MeshVertexCostsStamped>::SharedPtr cost_pub_;
186+
rclcpp::TimerBase::SharedPtr cost_subscribe_checker_;
187+
size_t vertex_cost_sub_count_ = 0;
188+
189+
//! Publisher for vertex cost changes
190+
rclcpp::Publisher<mesh_msgs::msg::MeshVertexCostsSparseStamped>::SharedPtr cost_update_pub_;
165191
};
166192

167193
} /* namespace mesh_map */

mesh_map/include/mesh_map/mesh_map.h

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -143,16 +143,10 @@ class MeshMap
143143
* @brief Publishes the given vertex map as mesh_msgs/VertexCosts, e.g. to visualize these.
144144
* @param costs The cost map to publish
145145
* @param name The name of the cost map
146+
* @param timestamp The timestamp of the costmap
146147
*/
147148
void publishVertexCosts(const lvr2::VertexMap<float>& costs, const std::string& name, const rclcpp::Time& map_stamp);
148149

149-
/**
150-
* @brief Publishes the given vertex map as mesh_msgs/VertexCostsSparse, e.g. to update the visualization in RVIZ.
151-
* @param costs The cost map to publish
152-
* @param name The name of the cost map
153-
*/
154-
void publishVertexCostsUpdate(const lvr2::VertexMap<float>& costs, const float default_value, const std::string& name, const rclcpp::Time& map_stamp);
155-
156150
/**
157151
* @briefP Publishes the vertex colors if these exists.
158152
*/
@@ -529,12 +523,6 @@ class MeshMap
529523
//! vertex normals
530524
lvr2::DenseVertexMap<Normal> vertex_normals;
531525

532-
//! publisher for vertex costs
533-
rclcpp::Publisher<mesh_msgs::msg::MeshVertexCostsStamped>::SharedPtr vertex_costs_pub;
534-
rclcpp::TimerBase::SharedPtr vertex_costs_subscribe_checker_;
535-
size_t vertex_costs_sub_count_ = 0;
536-
rclcpp::Publisher<mesh_msgs::msg::MeshVertexCostsSparseStamped>::SharedPtr vertex_costs_update_pub_;
537-
538526
//! publisher for vertex colors
539527
rclcpp::Publisher<mesh_msgs::msg::MeshVertexColorsStamped>::SharedPtr vertex_colors_pub;
540528

mesh_map/src/layer_manager.cpp

Lines changed: 65 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,9 @@ LayerManager::LayerManager(MeshMap& map, const rclcpp::Node::SharedPtr& node)
1515
, loader_("mesh_map", "mesh_map::AbstractLayer")
1616
{}
1717

18-
void LayerManager::read_configured_layers(const rclcpp::Node::SharedPtr& node)
18+
void LayerManager::read_configured_layers()
1919
{
20-
const auto layer_names = node->declare_parameter(
20+
const auto layer_names = node_->declare_parameter(
2121
MeshMap::MESH_MAP_NAMESPACE + ".layers", std::vector<std::string>()
2222
);
2323
const rclcpp::ParameterType ros_param_type = rclcpp::ParameterType::PARAMETER_STRING;
@@ -29,7 +29,7 @@ void LayerManager::read_configured_layers(const rclcpp::Node::SharedPtr& node)
2929
throw rclcpp::exceptions::InvalidParametersException("The layer name " + layer_name + " is used more than once. Layer names must be unique!");
3030
}
3131
// This will throws rclcpp::ParameterValue exception if mesh_map.layer_name.type is not set
32-
const std::string layer_type = node->declare_parameter<std::string>(
32+
const std::string layer_type = node_->declare_parameter<std::string>(
3333
MeshMap::MESH_MAP_NAMESPACE + "." + layer_name + ".type"
3434
);
3535

@@ -42,7 +42,7 @@ void LayerManager::read_configured_layers(const rclcpp::Node::SharedPtr& node)
4242
// output warning if no layer plugins were configured
4343
if (names_.size() == 0)
4444
{
45-
RCLCPP_WARN_STREAM(node->get_logger(), "No MeshMap layer plugins configured!"
45+
RCLCPP_WARN_STREAM(node_->get_logger(), "No MeshMap layer plugins configured!"
4646
<< " - Use the param \"" << MeshMap::MESH_MAP_NAMESPACE << ".layers\", which must be a list of strings with arbitrary layer names. "
4747
<< "For each layer_name, also define layer_name.type with the respective type that shall be loaded via pluginlib.");
4848
}
@@ -59,7 +59,7 @@ void LayerManager::read_configured_layers(const rclcpp::Node::SharedPtr& node)
5959
{
6060
const Vertex& v = vertices_[layer_name];
6161
// If mesh_map.layer_name.inputs is not set we assume the layer needs no inputs
62-
const auto dependencies = node->declare_parameter<std::vector<std::string>>(
62+
const auto dependencies = node_->declare_parameter<std::vector<std::string>>(
6363
MeshMap::MESH_MAP_NAMESPACE + "." + layer_name + ".inputs", std::vector<std::string>()
6464
);
6565

@@ -72,7 +72,7 @@ void LayerManager::read_configured_layers(const rclcpp::Node::SharedPtr& node)
7272
}
7373

7474
// Print the dependencies
75-
RCLCPP_INFO(node->get_logger(), "Layer dependencies:");
75+
RCLCPP_INFO(node_->get_logger(), "Layer dependencies:");
7676
for (const auto& [name, vertex]: vertices_)
7777
{
7878
auto [it, end] = boost::adjacent_vertices(vertex, graph_);
@@ -90,8 +90,28 @@ void LayerManager::read_configured_layers(const rclcpp::Node::SharedPtr& node)
9090
}
9191
builder << ']';
9292

93-
RCLCPP_INFO(node->get_logger(), " %s: %s", name.c_str(), builder.str().c_str());
93+
RCLCPP_INFO(node_->get_logger(), " %s: %s", name.c_str(), builder.str().c_str());
9494
}
95+
96+
// Initialize the publishers
97+
cost_pub_ = node_->create_publisher<mesh_msgs::msg::MeshVertexCostsStamped>("~/vertex_costs", rclcpp::QoS(names_.size()).transient_local());
98+
99+
// we dont want to publish static costs all the time.
100+
// therefore we have to check if someone newly subscribed to the topic
101+
cost_subscribe_checker_ = node_->create_wall_timer(std::chrono::milliseconds(200), [this]{
102+
const size_t count = cost_pub_->get_subscription_count() + cost_pub_->get_intra_process_subscription_count();
103+
if (count > vertex_cost_sub_count_)
104+
{
105+
RCLCPP_INFO(node_->get_logger(), "New cost layer subscriber detected. Publishing vertex costs once...");
106+
for (const auto& [layer_name, layer_ptr]: layer_instances())
107+
{
108+
publish_cost_layer(layer_ptr->costs(), layer_name, node_->get_clock()->now());
109+
}
110+
}
111+
vertex_cost_sub_count_ = count;
112+
});
113+
114+
cost_update_pub_ = node_->create_publisher<mesh_msgs::msg::MeshVertexCostsSparseStamped>(std::string(cost_pub_->get_topic_name()) + "/updates", rclcpp::QoS(10).transient_local());
95115
}
96116

97117
bool LayerManager::load_layer_plugins(const rclcpp::Logger& logger)
@@ -125,7 +145,7 @@ bool LayerManager::load_layer_plugins(const rclcpp::Logger& logger)
125145
return instances_.empty() ? false : true;
126146
}
127147

128-
bool LayerManager::initialize_layer_plugins(const rclcpp::Node::SharedPtr& node, const MeshMap::Ptr& map)
148+
bool LayerManager::initialize_layer_plugins(const MeshMap::Ptr& map)
129149
{
130150
// Prevent layers from publishing updates while initialization is still ongoing initialization
131151
std::unique_lock lock(layer_mtx_);
@@ -142,7 +162,7 @@ bool LayerManager::initialize_layer_plugins(const rclcpp::Node::SharedPtr& node,
142162
if (nullptr == instance)
143163
{
144164
RCLCPP_WARN(
145-
node->get_logger(),
165+
node_->get_logger(),
146166
"Skipping initialization of layer '%s' because it failed to load",
147167
name.c_str()
148168
);
@@ -156,10 +176,10 @@ bool LayerManager::initialize_layer_plugins(const rclcpp::Node::SharedPtr& node,
156176
std::placeholders::_3
157177
);
158178

159-
if (!instance->initialize(name, callback, map, node))
179+
if (!instance->initialize(name, callback, map, node_))
160180
{
161181
RCLCPP_ERROR(
162-
node->get_logger(),
182+
node_->get_logger(),
163183
"Could not initialize the layer plugin with the name \"%s\"!",
164184
name.c_str()
165185
);
@@ -168,12 +188,12 @@ bool LayerManager::initialize_layer_plugins(const rclcpp::Node::SharedPtr& node,
168188

169189
if (!instance->readLayer())
170190
{
171-
RCLCPP_INFO(node->get_logger(), "Computing layer '%s' ...", name.c_str());
191+
RCLCPP_INFO(node_->get_logger(), "Computing layer '%s' ...", name.c_str());
172192
instance->computeLayer();
173193
}
174194

175195
// Publish the layer
176-
map_.publishVertexCosts(instance->costs(), name, node_->get_clock()->now());
196+
publish_cost_layer(instance->costs(), name, node_->get_clock()->now());
177197
}
178198

179199
return true;
@@ -199,14 +219,14 @@ void LayerManager::layer_changed(
199219
const auto& ptr = get_layer(name);
200220
if (nullptr == ptr)
201221
{
202-
// TODO: Log error
222+
RCLCPP_ERROR(node_->get_logger(), "LayerManager::layer_changed() - Could not get pointer to changed layer %s", name.c_str());
203223
return;
204224
}
205225

206226
const auto v_it = vertices_.find(name);
207227
if (v_it == vertices_.end())
208228
{
209-
// TODO: Log error
229+
RCLCPP_ERROR(node_->get_logger(), "LayerManager::layer_changed() - Could not find dependency graph vertex for layer %s", name.c_str());
210230
return;
211231
}
212232

@@ -221,7 +241,7 @@ void LayerManager::layer_changed(
221241
c.insert(v, cm.containsKey(v)? cm[v]: ptr->defaultValue());
222242
}
223243
rlock.unlock();
224-
map_.publishVertexCostsUpdate(c, ptr->defaultValue(), name, timestamp);
244+
publish_cost_update(c, ptr->defaultValue(), name, timestamp);
225245

226246
// Notify the map
227247
map_.layerChanged(name, changed);
@@ -242,4 +262,33 @@ void LayerManager::layer_changed(
242262
}
243263
}
244264

265+
void LayerManager::publish_cost_layer(const lvr2::VertexMap<float>& costs, const std::string& name, const rclcpp::Time& timestamp)
266+
{
267+
cost_pub_->publish(
268+
mesh_msgs_conversions::toVertexCostsStamped(
269+
costs,
270+
map_.mesh()->numVertices(),
271+
0,
272+
name,
273+
map_.getGlobalFrameID(),
274+
map_.getUUID(),
275+
timestamp
276+
)
277+
);
278+
}
279+
280+
void LayerManager::publish_cost_update(const lvr2::VertexMap<float>& costs, const float default_value, const std::string& name, const rclcpp::Time& timestamp)
281+
{
282+
cost_update_pub_->publish(
283+
mesh_msgs_conversions::toVertexCostsSparseStamped(
284+
costs,
285+
default_value,
286+
name,
287+
map_.getGlobalFrameID(),
288+
map_.getUUID(),
289+
timestamp
290+
)
291+
);
292+
}
293+
245294
} // namespace mesh_map;

mesh_map/src/mesh_map.cpp

Lines changed: 4 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -130,19 +130,7 @@ MeshMap::MeshMap(tf2_ros::Buffer& tf, const rclcpp::Node::SharedPtr& node)
130130

131131
marker_pub = node->create_publisher<visualization_msgs::msg::Marker>("~/marker", 100);
132132
mesh_geometry_pub = node->create_publisher<mesh_msgs::msg::MeshGeometryStamped>("~/mesh", rclcpp::QoS(1).transient_local());
133-
vertex_costs_pub = node->create_publisher<mesh_msgs::msg::MeshVertexCostsStamped>("~/vertex_costs", rclcpp::QoS(1).transient_local());
134-
// we dont want to publish static costs all the time.
135-
// therefore we have to check if someone newly subscribed to the topic
136-
vertex_costs_subscribe_checker_ = node->create_wall_timer(std::chrono::milliseconds(200), [this, node]{
137-
const size_t count = vertex_costs_pub->get_subscription_count() + vertex_costs_pub->get_intra_process_subscription_count();
138-
if (count > vertex_costs_sub_count_)
139-
{
140-
RCLCPP_INFO(node->get_logger(), "New cost layer subscriber detected. Publishing vertex costs once...");
141-
publishCostLayers(node->now());
142-
}
143-
vertex_costs_sub_count_ = count;
144-
});
145-
vertex_costs_update_pub_ = node->create_publisher<mesh_msgs::msg::MeshVertexCostsSparseStamped>(std::string(vertex_costs_pub->get_topic_name()) + "/updates", rclcpp::QoS(10).transient_local());
133+
146134
vertex_colors_pub = node->create_publisher<mesh_msgs::msg::MeshVertexColorsStamped>("~/vertex_colors", rclcpp::QoS(1).transient_local());
147135
vector_field_pub = node->create_publisher<visualization_msgs::msg::Marker>("~/vector_field", rclcpp::QoS(1).transient_local());
148136
edge_weights_text_pub = node->create_publisher<visualization_msgs::msg::MarkerArray>("~/edge_weights", rclcpp::QoS(1).transient_local());
@@ -434,7 +422,7 @@ bool MeshMap::readMap()
434422
}
435423
}
436424

437-
layer_manager_.read_configured_layers(node);
425+
layer_manager_.read_configured_layers();
438426

439427
RCLCPP_INFO_STREAM(node->get_logger(), "Load layer plugins...");
440428
if (!layer_manager_.load_layer_plugins(node->get_logger()))
@@ -444,7 +432,7 @@ bool MeshMap::readMap()
444432
}
445433

446434
RCLCPP_INFO_STREAM(node->get_logger(), "Initialize layer plugins...");
447-
if (!layer_manager_.initialize_layer_plugins(node, shared_from_this()))
435+
if (!layer_manager_.initialize_layer_plugins(shared_from_this()))
448436
{
449437
RCLCPP_FATAL_STREAM(node->get_logger(), "Could not initialize plugins!");
450438
return false;
@@ -456,7 +444,6 @@ bool MeshMap::readMap()
456444
return false;
457445
}
458446
computeEdgeWeights();
459-
publishCostLayers(map_stamp);
460447

461448
map_loaded = true;
462449
return true;
@@ -1320,44 +1307,9 @@ bool MeshMap::resetLayers()
13201307
return true; // TODO implement
13211308
}
13221309

1323-
void MeshMap::publishCostLayers(const rclcpp::Time& map_stamp)
1324-
{
1325-
for (const auto& [layer_name, layer_ptr] : layer_manager_.layer_instances())
1326-
{
1327-
vertex_costs_pub->publish(
1328-
mesh_msgs_conversions::toVertexCostsStamped(
1329-
layer_ptr->costs(),
1330-
mesh_ptr->numVertices(),
1331-
layer_ptr->defaultValue(),
1332-
layer_name,
1333-
global_frame,
1334-
uuid_str,
1335-
map_stamp
1336-
)
1337-
);
1338-
}
1339-
}
1340-
13411310
void MeshMap::publishVertexCosts(const lvr2::VertexMap<float>& costs, const std::string& name, const rclcpp::Time& map_stamp)
13421311
{
1343-
vertex_costs_pub->publish(
1344-
mesh_msgs_conversions::toVertexCostsStamped(costs, mesh_ptr->numVertices(), 0, name, global_frame, uuid_str, map_stamp));
1345-
// TODO: Should this be moved to the LayerManager? Publishing the layers and updates
1346-
// is part of managing the layers isnt it?
1347-
}
1348-
1349-
void MeshMap::publishVertexCostsUpdate(const lvr2::VertexMap<float>& costs, const float default_value, const std::string& name, const rclcpp::Time& map_stamp)
1350-
{
1351-
vertex_costs_update_pub_->publish(
1352-
mesh_msgs_conversions::toVertexCostsSparseStamped(
1353-
costs,
1354-
default_value,
1355-
name,
1356-
global_frame,
1357-
uuid_str,
1358-
map_stamp
1359-
)
1360-
);
1312+
layer_manager_.publish_cost_layer(costs, name, map_stamp);
13611313
}
13621314

13631315
void MeshMap::publishVertexColors(const rclcpp::Time& map_stamp)

mesh_map/test/mesh_map_test.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ TEST_F(MeshMapTest, loadsSinglePlugin)
4444
// The MeshMap requires that a map file is loaded to initialize, so we test the layer manager directly
4545
mesh_map::LayerManager manager(*mesh_map_ptr_, node_ptr_);
4646

47-
EXPECT_NO_THROW(manager.read_configured_layers(node_ptr_));
47+
EXPECT_NO_THROW(manager.read_configured_layers());
4848
EXPECT_TRUE(manager.load_layer_plugins(node_ptr_->get_logger()));
4949
// This calls back to the mesh map and segfaults because the MeshMap has its own internal LayerManager :(
5050
// EXPECT_TRUE(manager.initialize_layer_plugins(node_ptr_, mesh_map_ptr_));
@@ -65,7 +65,7 @@ TEST_F(MeshMapTest, loadsMultiplePlugins)
6565
// The MeshMap requires that a map file is loaded to initialize, so we test the layer manager directly
6666
mesh_map::LayerManager manager(*mesh_map_ptr_, node_ptr_);
6767

68-
EXPECT_NO_THROW(manager.read_configured_layers(node_ptr_));
68+
EXPECT_NO_THROW(manager.read_configured_layers());
6969
EXPECT_TRUE(manager.load_layer_plugins(node_ptr_->get_logger()));
7070

7171
EXPECT_NE(manager.get_layer("t1"), nullptr);

0 commit comments

Comments
 (0)