Skip to content

Commit 0764e5a

Browse files
authored
Reduce map saver nodes (#2454)
* reduce MapSaver nodes by using callback group/executor combo Signed-off-by: zhenpeng ge <zhenpeng.ge@qq.com> * set use_rclcpp_node false * a cleaner solution using a future and spin_until_future_complete() Signed-off-by: zhenpeng ge <zhenpeng.ge@qq.com>
1 parent 5ec3ab4 commit 0764e5a

File tree

1 file changed

+36
-38
lines changed

1 file changed

+36
-38
lines changed

‎nav2_map_server/src/map_saver/map_saver.cpp‎

Lines changed: 36 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ using namespace std::placeholders;
4242
namespace nav2_map_server
4343
{
4444
MapSaver::MapSaver()
45-
: nav2_util::LifecycleNode("map_saver", "", true)
45+
: nav2_util::LifecycleNode("map_saver", "")
4646
{
4747
RCLCPP_INFO(get_logger(), "Creating");
4848

@@ -149,12 +149,6 @@ bool MapSaver::saveMapTopicToFile(
149149
map_topic_loc.c_str(), save_parameters_loc.map_file_name.c_str());
150150

151151
try {
152-
// Pointer to map message received in the subscription callback
153-
nav_msgs::msg::OccupancyGrid::SharedPtr map_msg = nullptr;
154-
155-
// Mutex for handling map_msg shared resource
156-
std::recursive_mutex access;
157-
158152
// Correct map_topic_loc if necessary
159153
if (map_topic_loc == "") {
160154
map_topic_loc = "map";
@@ -179,47 +173,51 @@ bool MapSaver::saveMapTopicToFile(
179173
save_parameters_loc.occupied_thresh = occupied_thresh_default_;
180174
}
181175

176+
std::promise<nav_msgs::msg::OccupancyGrid::SharedPtr> prom;
177+
std::future<nav_msgs::msg::OccupancyGrid::SharedPtr> future_result = prom.get_future();
182178
// A callback function that receives map message from subscribed topic
183-
auto mapCallback = [&map_msg, &access](
179+
auto mapCallback = [&prom](
184180
const nav_msgs::msg::OccupancyGrid::SharedPtr msg) -> void {
185-
std::lock_guard<std::recursive_mutex> guard(access);
186-
map_msg = msg;
181+
prom.set_value(msg);
187182
};
188183

189-
// Add new subscription for incoming map topic.
190-
// Utilizing local rclcpp::Node (rclcpp_node_) from nav2_util::LifecycleNode
191-
// as a map listener.
192184
rclcpp::QoS map_qos(10); // initialize to default
193185
if (map_subscribe_transient_local_) {
194186
map_qos.transient_local();
195187
map_qos.reliable();
196188
map_qos.keep_last(1);
197189
}
198-
auto map_sub = rclcpp_node_->create_subscription<nav_msgs::msg::OccupancyGrid>(
199-
map_topic_loc, map_qos, mapCallback);
200-
201-
rclcpp::Time start_time = now();
202-
while (rclcpp::ok()) {
203-
if ((now() - start_time) > *save_map_timeout_) {
204-
RCLCPP_ERROR(get_logger(), "Failed to save the map: timeout");
205-
return false;
206-
}
207-
208-
if (map_msg) {
209-
std::lock_guard<std::recursive_mutex> guard(access);
210-
// map_sub is no more needed
211-
map_sub.reset();
212-
// Map message received. Saving it to file
213-
if (saveMapToFile(*map_msg, save_parameters_loc)) {
214-
RCLCPP_INFO(get_logger(), "Map saved successfully");
215-
return true;
216-
} else {
217-
RCLCPP_ERROR(get_logger(), "Failed to save the map");
218-
return false;
219-
}
220-
}
221-
222-
rclcpp::sleep_for(std::chrono::milliseconds(100));
190+
191+
// Create new CallbackGroup for map_sub
192+
auto callback_group = create_callback_group(
193+
rclcpp::CallbackGroupType::MutuallyExclusive,
194+
false);
195+
196+
auto option = rclcpp::SubscriptionOptions();
197+
option.callback_group = callback_group;
198+
auto map_sub = create_subscription<nav_msgs::msg::OccupancyGrid>(
199+
map_topic_loc, map_qos, mapCallback, option);
200+
201+
// Create SingleThreadedExecutor to spin map_sub in callback_group
202+
rclcpp::executors::SingleThreadedExecutor executor;
203+
executor.add_callback_group(callback_group, get_node_base_interface());
204+
// Spin until map message received
205+
auto timeout = save_map_timeout_->to_chrono<std::chrono::nanoseconds>();
206+
auto status = executor.spin_until_future_complete(future_result, timeout);
207+
if (status != rclcpp::FutureReturnCode::SUCCESS) {
208+
RCLCPP_ERROR(get_logger(), "Failed to spin map subscription");
209+
return false;
210+
}
211+
// map_sub is no more needed
212+
map_sub.reset();
213+
// Map message received. Saving it to file
214+
nav_msgs::msg::OccupancyGrid::SharedPtr map_msg = future_result.get();
215+
if (saveMapToFile(*map_msg, save_parameters_loc)) {
216+
RCLCPP_INFO(get_logger(), "Map saved successfully");
217+
return true;
218+
} else {
219+
RCLCPP_ERROR(get_logger(), "Failed to save the map");
220+
return false;
223221
}
224222
} catch (std::exception & e) {
225223
RCLCPP_ERROR(get_logger(), "Failed to save the map: %s", e.what());

0 commit comments

Comments
 (0)