@@ -42,7 +42,7 @@ using namespace std::placeholders;
4242namespace nav2_map_server
4343{
4444MapSaver::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