|
53 | 53 | from rclpy.clock import ROSClock |
54 | 54 | from rclpy.constants import S_TO_NS |
55 | 55 | from rclpy.context import Context |
| 56 | +from rclpy.endpoint_info import ServiceEndpointInfo, TopicEndpointInfo |
56 | 57 | from rclpy.event_handler import PublisherEventCallbacks |
57 | 58 | from rclpy.event_handler import SubscriptionEventCallbacks |
58 | 59 | from rclpy.exceptions import InvalidHandle |
|
91 | 92 | from rclpy.timer import Rate |
92 | 93 | from rclpy.timer import Timer |
93 | 94 | from rclpy.timer import TimerCallbackType |
94 | | -from rclpy.topic_endpoint_info import TopicEndpointInfo |
95 | 95 | from rclpy.type_description_service import TypeDescriptionService |
96 | 96 | from rclpy.type_support import check_is_valid_msg_type |
97 | 97 | from rclpy.type_support import check_is_valid_srv_type |
@@ -2368,6 +2368,96 @@ def get_subscriptions_info_by_topic( |
2368 | 2368 | no_mangle, |
2369 | 2369 | _rclpy.rclpy_get_subscriptions_info_by_topic) |
2370 | 2370 |
|
| 2371 | + def _get_info_by_service( |
| 2372 | + self, |
| 2373 | + service_name: str, |
| 2374 | + no_mangle: bool, |
| 2375 | + func: Callable[[_rclpy.Node, str, bool], List['_rclpy.ServiceEndpointInfoDict']] |
| 2376 | + ) -> List[ServiceEndpointInfo]: |
| 2377 | + with self.handle: |
| 2378 | + if no_mangle: |
| 2379 | + fq_topic_name = service_name |
| 2380 | + else: |
| 2381 | + fq_topic_name = expand_topic_name( |
| 2382 | + service_name, self.get_name(), self.get_namespace()) |
| 2383 | + validate_full_topic_name(fq_topic_name) |
| 2384 | + fq_topic_name = _rclpy.rclpy_remap_topic_name(self.handle, fq_topic_name) |
| 2385 | + info_dicts = func(self.handle, fq_topic_name, no_mangle) |
| 2386 | + infos = [ServiceEndpointInfo(**x) for x in info_dicts] |
| 2387 | + return infos |
| 2388 | + |
| 2389 | + def get_clients_info_by_service( |
| 2390 | + self, |
| 2391 | + service_name: str, |
| 2392 | + no_mangle: bool = False |
| 2393 | + ) -> List[ServiceEndpointInfo]: |
| 2394 | + """ |
| 2395 | + Return a list of clients on a given service. |
| 2396 | +
|
| 2397 | + The returned parameter is a list of ServiceEndpointInfo objects, where each will contain |
| 2398 | + the node name, node namespace, service type, service endpoint's GIDs, and its QoS profiles. |
| 2399 | +
|
| 2400 | + When the ``no_mangle`` parameter is ``True``, the provided ``service_name`` should be a |
| 2401 | + valid service name for the middleware (useful when combining ROS with native middleware |
| 2402 | + apps). When the ``no_mangle`` parameter is ``False``,the provided |
| 2403 | + ``service_name`` should follow ROS service name conventions. |
| 2404 | + In DDS-based RMWs, services are implemented as topics with mangled |
| 2405 | + names (e.g., `rq/my_serviceRequest` and `rp/my_serviceReply`), so `no_mangle = true` is not |
| 2406 | + supported and will result in an error. Use `get_subscriptions_info_by_topic` or |
| 2407 | + get_publishers_info_by_topic` for unmangled topic queries in such cases. Other RMWs |
| 2408 | + (e.g., Zenoh) may support `no_mangle = true` if they natively handle |
| 2409 | + services without topic-based |
| 2410 | +
|
| 2411 | + ``service_name`` may be a relative, private, or fully qualified service name. |
| 2412 | + A relative or private service will be expanded using this node's namespace and name. |
| 2413 | + The queried ``service_name`` is not remapped. |
| 2414 | +
|
| 2415 | + :param service_name: The service_name on which to find the clients. |
| 2416 | + :param no_mangle: If ``True``, `service_name` needs to be a valid middleware service |
| 2417 | + name, otherwise it should be a valid ROS service name. Defaults to ``False``. |
| 2418 | + :return: A list of ServiceEndpointInfo for all the clients on this service. |
| 2419 | + """ |
| 2420 | + return self._get_info_by_service( |
| 2421 | + service_name, |
| 2422 | + no_mangle, |
| 2423 | + _rclpy.rclpy_get_clients_info_by_service) |
| 2424 | + |
| 2425 | + def get_servers_info_by_service( |
| 2426 | + self, |
| 2427 | + service_name: str, |
| 2428 | + no_mangle: bool = False |
| 2429 | + ) -> List[ServiceEndpointInfo]: |
| 2430 | + """ |
| 2431 | + Return a list of servers on a given service. |
| 2432 | +
|
| 2433 | + The returned parameter is a list of ServiceEndpointInfo objects, where each will contain |
| 2434 | + the node name, node namespace, service type, service endpoint's GIDs, and its QoS profiles. |
| 2435 | +
|
| 2436 | + When the ``no_mangle`` parameter is ``True``, the provided ``service_name`` should be a |
| 2437 | + valid service name for the middleware (useful when combining ROS with native middleware |
| 2438 | + apps). When the ``no_mangle`` parameter is ``False``,the provided |
| 2439 | + ``service_name`` should follow ROS service name conventions. |
| 2440 | + In DDS-based RMWs, services are implemented as topics with mangled |
| 2441 | + names (e.g., `rq/my_serviceRequest` and `rp/my_serviceReply`), so `no_mangle = true` is not |
| 2442 | + supported and will result in an error. Use `get_subscriptions_info_by_topic` or |
| 2443 | + get_publishers_info_by_topic` for unmangled topic queries in such cases. Other RMWs |
| 2444 | + (e.g., Zenoh) may support `no_mangle = true` if they natively handle |
| 2445 | + services without topic-based |
| 2446 | +
|
| 2447 | + ``service_name`` may be a relative, private, or fully qualified service name. |
| 2448 | + A relative or private service will be expanded using this node's namespace and name. |
| 2449 | + The queried ``service_name`` is not remapped. |
| 2450 | +
|
| 2451 | + :param service_name: The service_name on which to find the servers. |
| 2452 | + :param no_mangle: If ``True``, `service_name` needs to be a valid middleware service |
| 2453 | + name, otherwise it should be a valid ROS service name. Defaults to ``False``. |
| 2454 | + :return: A list of ServiceEndpointInfo for all the servers on this service. |
| 2455 | + """ |
| 2456 | + return self._get_info_by_service( |
| 2457 | + service_name, |
| 2458 | + no_mangle, |
| 2459 | + _rclpy.rclpy_get_servers_info_by_service) |
| 2460 | + |
2371 | 2461 | def wait_for_node( |
2372 | 2462 | self, |
2373 | 2463 | fully_qualified_node_name: str, |
|
0 commit comments