1313# limitations under the License.
1414
1515
16- from rcl_interfaces .srv import ListParameters
1716import rclpy
17+ from rclpy .parameter_client import AsyncParameterClient
1818from ros2cli .node .direct import DirectNode
1919from ros2cli .node .strategy import NodeStrategy
2020from ros2doctor .api import DoctorCheck
2424from ros2doctor .api .format import doctor_warn
2525
2626
27- def call_list_parameters (node , node_name , namespace = '/' ):
28- """Call the list_parameters service for a specific node."""
27+ def call_list_parameters (node , node_name ):
28+ """Call the list_parameters service for a specific node using AsyncParameterClient ."""
2929 try :
30- # Create service name and client for the target node's list_parameters service
31- service_name = f"{ namespace .rstrip ('/' )} /{ node_name } /list_parameters"
32- if service_name .startswith ('//' ):
33- service_name = service_name [1 :]
34-
35- client = node .create_client (ListParameters , service_name )
36-
37- if not client .wait_for_service (timeout_sec = 1.0 ):
30+ client = AsyncParameterClient (node , node_name )
31+ ready = client .wait_for_services (timeout_sec = 2.0 )
32+ if not ready :
3833 return None
39-
40- request = ListParameters .Request ()
41- future = client .call_async (request )
42-
43- # Spin until the service call completes or times out
34+ future = client .list_parameters ()
4435 rclpy .spin_until_future_complete (node , future , timeout_sec = 2.0 )
45-
46- if future .done ():
47- response = future .result ()
48- node .destroy_client (client )
49- return response
50- else :
51- node .destroy_client (client )
52- return None
53-
36+ if future .done () and future .result () is not None :
37+ # Return the parameter names list
38+ return future .result ().result .names
39+ return None
5440 except Exception :
5541 return None
5642
@@ -70,9 +56,9 @@ def check(self):
7056 node_names_and_namespaces = []
7157 with DirectNode (None ) as param_node :
7258 for node_name , namespace in node_names_and_namespaces :
73- response = call_list_parameters ( param_node . node , node_name , namespace )
74- if response is None :
75- full_name = f" { namespace . rstrip ( '/' ) } / { node_name } "
59+ full_name = f" { namespace . rstrip ( '/' ) } / { node_name } "
60+ param_names = call_list_parameters ( param_node . node , full_name )
61+ if param_names is None :
7662 doctor_warn (f'Node { full_name } has no parameter services.' )
7763 result .add_warning ()
7864 return result
@@ -103,17 +89,14 @@ def report(self):
10389 with DirectNode (None ) as param_node :
10490 for node_name , namespace in sorted (node_names_and_namespaces ):
10591 nodes_checked += 1
106- response = call_list_parameters (param_node .node , node_name , namespace )
107- if response and hasattr (response , 'result' ) and response .result :
108- result = response .result
109- param_names = result .names if hasattr (result , 'names' ) else []
110- if param_names :
111- total_param_count += len (param_names )
112- full_name = f"{ namespace .rstrip ('/' )} /{ node_name } "
113-
114- report .add_to_report ('node' , full_name )
115- for param_name in sorted (param_names ):
116- report .add_to_report ('parameter' , param_name )
92+ full_name = f"{ namespace .rstrip ('/' )} /{ node_name } "
93+ param_names = call_list_parameters (param_node .node , full_name )
94+
95+ if param_names :
96+ total_param_count += len (param_names )
97+ report .add_to_report ('node' , full_name )
98+ for param_name in sorted (param_names ):
99+ report .add_to_report ('parameter' , param_name )
117100
118101 report .add_to_report ('total nodes checked' , nodes_checked )
119102 report .add_to_report ('total parameter count' , total_param_count )
0 commit comments