@@ -46,7 +46,7 @@ LifecycleManager::LifecycleManager(const rclcpp::NodeOptions & options)
4646  declare_parameter (" service_timeout" 5.0 );
4747  declare_parameter (" bond_respawn_max_duration" 10.0 );
4848  declare_parameter (" attempt_respawn_reconnection" true );
49-   declare_parameter (" parallel_state_transitions" rclcpp::ParameterValue (true ));
49+   declare_parameter (" parallel_state_transitions" rclcpp::ParameterValue (false ));
5050
5151  registerRclPreshutdownCallback ();
5252
@@ -285,101 +285,80 @@ bool
285285LifecycleManager::changeStateForAllNodes (std::uint8_t  transition, bool  hard_change)
286286{
287287  /*  Function partially created using claude */ 
288-   size_t  active_nodes_count = 0 ;
289-   std::string nodes_in_error_state = " " 
290-   std::string unconfigured_nodes = " " 
291-   std::string inactive_nodes = " " 
292-   std::string delimiter (" , " 
293- 
294-   if  (parallel_state_transitions_) {
295-     //  Parallel execution
288+   //  Hard change will continue even if a node fails
289+   if  (transition == Transition::TRANSITION_CONFIGURE ||
290+     transition == Transition::TRANSITION_ACTIVATE)
291+   {
296292    std::vector<std::future<bool >> futures;
297-     std::vector<std::string> processing_nodes;
298- 
299-     //  Hard change will continue even if a node fails
300-     if  (transition == Transition::TRANSITION_CONFIGURE ||
301-       transition == Transition::TRANSITION_ACTIVATE)
302-     {
303-       //  Launch all state changes in parallel
304-       for  (auto  & node_name : node_names_) {
305-         futures.emplace_back (std::async (std::launch::async, [this , node_name, transition]() {
306-             try  {
307-               return  changeStateForNode (node_name, transition);
308-             } catch  (const  std::runtime_error & e) {
309-               RCLCPP_ERROR (
310-               get_logger (),
311-               " Failed to change state for node: %s. Exception: %s." c_str (), e.what ());
312-               return  false ;
313-             }
314-         }));
315-         processing_nodes.push_back (node_name);
316-       }
317-     } else  {
318-       //  For deactivation/cleanup, process in reverse order but still in parallel
319-       std::vector<std::string> reverse_nodes (node_names_.rbegin (), node_names_.rend ());
320-       for  (auto  & node_name : reverse_nodes) {
321-         futures.emplace_back (std::async (std::launch::async, [this , node_name, transition]() {
322-             try  {
323-               return  changeStateForNode (node_name, transition);
324-             } catch  (const  std::runtime_error & e) {
325-               RCLCPP_ERROR (
293+     futures.reserve (node_names_.size ());
294+ 
295+     for  (auto  & node_name : node_names_) {
296+       auto  future = std::async (
297+         std::launch::async,
298+         [this , node_name, transition]() {
299+           try  {
300+             return  changeStateForNode (node_name, transition);
301+           } catch  (const  std::runtime_error & e) {
302+             RCLCPP_ERROR (
326303              get_logger (),
327304              " Failed to change state for node: %s. Exception: %s." c_str (), e.what ());
328-               return  false ;
329-             }
330-         }));
331-         processing_nodes.push_back (node_name);
305+             return  false ;
306+           }
307+         });
308+ 
309+       if  (!parallel_state_transitions_) {
310+         //  Sequential execution: wait for each future immediately
311+         if  (!future.get () && !hard_change) {
312+           return  false ;
313+         }
314+       } else  {
315+         //  Parallel execution: collect futures to wait later
316+         futures.push_back (std::move (future));
332317      }
333318    }
334319
335-     //  Wait for all futures and collect results
336-     for  (size_t  i = 0 ; i < futures.size (); ++i) {
337-       bool  success = futures[i].get ();
338-       const  std::string & node_name = processing_nodes[i];
339- 
340-       if  (!success && !hard_change) {
341-         uint8_t  state = node_map_[node_name]->get_state ();
342-         if  (!strcmp (reinterpret_cast <char  *>(&state), " Inactive" 
343-           inactive_nodes += node_name + delimiter;
344-         } else  {
345-           unconfigured_nodes += node_name + delimiter;
320+     //  If parallel execution, wait for all futures now
321+     if  (parallel_state_transitions_) {
322+       for  (auto  & future : futures) {
323+         if  (!future.get () && !hard_change) {
324+           return  false ;
346325        }
347-       } else  if  (success) {
348-         ++active_nodes_count;
349326      }
350327    }
351-     if  (active_nodes_count != node_names_.size ()) {
352-       return  false ;
353-     }
354- 
355328  } else  {
356-     //  Sequential execution (original behavior)
357-     if  (transition == Transition::TRANSITION_CONFIGURE ||
358-       transition == Transition::TRANSITION_ACTIVATE)
359-     {
360-       for  (auto  & node_name : node_names_) {
361-         try  {
362-           if  (!changeStateForNode (node_name, transition) && !hard_change) {
329+     std::vector<std::future<bool >> futures;
330+     futures.reserve (node_names_.size ());
331+ 
332+     std::vector<std::string>::reverse_iterator rit;
333+     for  (rit = node_names_.rbegin (); rit != node_names_.rend (); ++rit) {
334+       auto  future = std::async (
335+         std::launch::async,
336+         [this , rit, transition]() {
337+           try  {
338+             return  changeStateForNode (*rit, transition);
339+           } catch  (const  std::runtime_error & e) {
340+             RCLCPP_ERROR (
341+               get_logger (),
342+               " Failed to change state for node: %s. Exception: %s." c_str (), e.what ());
363343            return  false ;
364344          }
365-         } catch  (const  std::runtime_error & e) {
366-           RCLCPP_ERROR (
367-           get_logger (),
368-           " Failed to change state for node: %s. Exception: %s." c_str (), e.what ());
345+         });
346+ 
347+       if  (!parallel_state_transitions_) {
348+         //  Sequential execution: wait for each future immediately
349+         if  (!future.get () && !hard_change) {
369350          return  false ;
370351        }
352+       } else  {
353+         //  Parallel execution: collect futures to wait later
354+         futures.push_back (std::move (future));
371355      }
372-     } else  {
373-       std::vector<std::string>::reverse_iterator rit;
374-       for  (rit = node_names_.rbegin (); rit != node_names_.rend (); ++rit) {
375-         try  {
376-           if  (!changeStateForNode (*rit, transition) && !hard_change) {
377-             return  false ;
378-           }
379-         } catch  (const  std::runtime_error & e) {
380-           RCLCPP_ERROR (
381-           get_logger (),
382-           " Failed to change state for node: %s. Exception: %s." c_str (), e.what ());
356+     }
357+ 
358+     //  If parallel execution, wait for all futures now
359+     if  (parallel_state_transitions_) {
360+       for  (auto  & future : futures) {
361+         if  (!future.get () && !hard_change) {
383362          return  false ;
384363        }
385364      }
0 commit comments