Skip to content

Commit 63bdf2a

Browse files
authored
add : get clients, servers info (#2569)
Signed-off-by: Minju, Lee <dlalswn531@naver.com>
1 parent ad019b9 commit 63bdf2a

File tree

9 files changed

+589
-1
lines changed

9 files changed

+589
-1
lines changed

rclcpp/include/rclcpp/node.hpp

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1388,6 +1388,66 @@ class Node : public std::enable_shared_from_this<Node>
13881388
std::vector<rclcpp::TopicEndpointInfo>
13891389
get_subscriptions_info_by_topic(const std::string & topic_name, bool no_mangle = false) const;
13901390

1391+
/// Return the service endpoint information about clients on a given service.
1392+
/**
1393+
* The returned parameter is a list of service endpoint information, where each item will contain
1394+
* the node name, node namespace, service type, endpoint type, endpoint count,
1395+
* service endpoint's GIDs, and its QoS profiles.
1396+
*
1397+
* When the `no_mangle` parameter is `true`, the provided `service_name` should be a valid service
1398+
* name for the middleware (useful when combining ROS with native middleware apps).
1399+
* When the `no_mangle` parameter is `false`, the provided `service_name` should follow
1400+
* ROS service name conventions. In DDS-based RMWs, services are implemented as topics with mangled
1401+
* names (e.g., `rq/my_serviceRequest` and `rp/my_serviceReply`), so `no_mangle = true` is not
1402+
* supported and will result in an error. Use `get_publishers_info_by_topic` or
1403+
* `get_subscriptions_info_by_topic` for unmangled topic queries in such cases. Other RMWs
1404+
* (e.g., Zenoh) may support `no_mangle = true` if they natively handle services without topic-based
1405+
*
1406+
* 'service_name` may be a relative, private, or fully qualified service name.
1407+
* A relative or private service will be expanded using this node's namespace and name.
1408+
* The queried `service_name` is not remapped.
1409+
*
1410+
* \param[in] service_name the actual service name used; it will not be automatically remapped.
1411+
* \param[in] no_mangle if `true`, `service_name` needs to be a valid middleware service name,
1412+
* otherwise it should be a valid ROS service name. Defaults to `false`.
1413+
* \return a list of SeviceEndpointInfo representing all the clients on this service.
1414+
* \throws InvalidServiceNameError if the given service_name is invalid.
1415+
* \throws std::runtime_error if internal error happens.
1416+
*/
1417+
RCLCPP_PUBLIC
1418+
std::vector<rclcpp::ServiceEndpointInfo>
1419+
get_clients_info_by_service(const std::string & service_name, bool no_mangle = false) const;
1420+
1421+
/// Return the service endpoint information about servers on a given service.
1422+
/**
1423+
* The returned parameter is a list of service endpoint information, where each item will contain
1424+
* the node name, node namespace, service type, endpoint type, endpoint count,
1425+
* service endpoint's GIDs, and its QoS profiles.
1426+
*
1427+
* When the `no_mangle` parameter is `true`, the provided `service_name` should be a valid service
1428+
* name for the middleware (useful when combining ROS with native middleware apps).
1429+
* When the `no_mangle` parameter is `false`, the provided `service_name` should follow
1430+
* ROS service name conventions. In DDS-based RMWs, services are implemented as topics with mangled
1431+
* names (e.g., `rq/my_serviceRequest` and `rp/my_serviceReply`), so `no_mangle = true` is not
1432+
* supported and will result in an error. Use `rcl_get_publishers_info_by_topic` or
1433+
* `rcl_get_subscriptions_info_by_topic` for unmangled topic queries in such cases. Other RMWs
1434+
* (e.g., Zenoh) may support `no_mangle = true` if they natively handle services without topic-based
1435+
*
1436+
* 'service_name` may be a relative, private, or fully qualified service name.
1437+
* A relative or private service will be expanded using this node's namespace and name.
1438+
* The queried `service_name` is not remapped.
1439+
*
1440+
* \param[in] service_name the actual service name used; it will not be automatically remapped.
1441+
* \param[in] no_mangle if `true`, `service_name` needs to be a valid middleware service name,
1442+
* otherwise it should be a valid ROS service name. Defaults to `false`.
1443+
* \return a list of SeviceEndpointInfo representing all the servers on this service.
1444+
* \throws InvalidServiceNameError if the given service_name is invalid.
1445+
* \throws std::runtime_error if internal error happens.
1446+
*/
1447+
RCLCPP_PUBLIC
1448+
std::vector<rclcpp::ServiceEndpointInfo>
1449+
get_servers_info_by_service(const std::string & service_name, bool no_mangle = false) const;
1450+
13911451
/// Return a graph event, which will be set anytime a graph change occurs.
13921452
/* The graph Event object is a loan which must be returned.
13931453
* The Event object is scoped and therefore to return the loan just let it go

rclcpp/include/rclcpp/node_interfaces/node_graph.hpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
#include "rclcpp/node_interfaces/node_base_interface.hpp"
3434
#include "rclcpp/node_interfaces/node_graph_interface.hpp"
3535
#include "rclcpp/visibility_control.hpp"
36+
#include "rmw/service_endpoint_info_array.h"
3637
#include "rmw/topic_endpoint_info_array.h"
3738

3839
namespace rclcpp
@@ -159,6 +160,18 @@ class NodeGraph : public NodeGraphInterface
159160
const std::string & topic_name,
160161
bool no_mangle = false) const override;
161162

163+
RCLCPP_PUBLIC
164+
std::vector<rclcpp::ServiceEndpointInfo>
165+
get_clients_info_by_service(
166+
const std::string & service_name,
167+
bool no_mangle = false) const override;
168+
169+
RCLCPP_PUBLIC
170+
std::vector<rclcpp::ServiceEndpointInfo>
171+
get_servers_info_by_service(
172+
const std::string & service_name,
173+
bool no_mangle = false) const override;
174+
162175
private:
163176
RCLCPP_DISABLE_COPY(NodeGraph)
164177

rclcpp/include/rclcpp/node_interfaces/node_graph_interface.hpp

Lines changed: 148 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818
#include <algorithm>
1919
#include <array>
2020
#include <chrono>
21+
#include <cstddef>
22+
#include <cstdint>
2123
#include <map>
2224
#include <string>
2325
#include <tuple>
@@ -40,7 +42,9 @@ enum class EndpointType
4042
{
4143
Invalid = RMW_ENDPOINT_INVALID,
4244
Publisher = RMW_ENDPOINT_PUBLISHER,
43-
Subscription = RMW_ENDPOINT_SUBSCRIPTION
45+
Subscription = RMW_ENDPOINT_SUBSCRIPTION,
46+
Client = RMW_ENDPOINT_CLIENT,
47+
Server = RMW_ENDPOINT_SERVER
4448
};
4549

4650
/**
@@ -143,6 +147,125 @@ class TopicEndpointInfo
143147
rosidl_type_hash_t topic_type_hash_;
144148
};
145149

150+
/**
151+
* Struct that contains service endpoint information like the associated node name, node namespace,
152+
* service type, endpoint type, endpoint count, endpoint GIDs, and its QoS profiles.
153+
*/
154+
class ServiceEndpointInfo
155+
{
156+
public:
157+
/// Construct a ServiceEndpointInfo from a rcl_service_endpoint_info_t.
158+
RCLCPP_PUBLIC
159+
explicit ServiceEndpointInfo(const rcl_service_endpoint_info_t & info)
160+
: node_name_(info.node_name),
161+
node_namespace_(info.node_namespace),
162+
service_type_(info.service_type),
163+
endpoint_type_(static_cast<rclcpp::EndpointType>(info.endpoint_type)),
164+
service_type_hash_(info.service_type_hash),
165+
endpoint_count_(info.endpoint_count)
166+
{
167+
for(size_t i = 0; i < endpoint_count_; i++) {
168+
std::array<uint8_t, RMW_GID_STORAGE_SIZE> gid;
169+
std::copy(info.endpoint_gids[i], info.endpoint_gids[i] + RMW_GID_STORAGE_SIZE, gid.begin());
170+
endpoint_gids_.push_back(gid);
171+
172+
rclcpp::QoS qos(
173+
{info.qos_profiles[i].history, info.qos_profiles[i].depth}, info.qos_profiles[i]);
174+
qos_profiles_.push_back(qos);
175+
}
176+
}
177+
178+
/// Get a mutable reference to the node name.
179+
RCLCPP_PUBLIC
180+
std::string &
181+
node_name();
182+
183+
/// Get a const reference to the node name.
184+
RCLCPP_PUBLIC
185+
const std::string &
186+
node_name() const;
187+
188+
/// Get a mutable reference to the node namespace.
189+
RCLCPP_PUBLIC
190+
std::string &
191+
node_namespace();
192+
193+
/// Get a const reference to the node namespace.
194+
RCLCPP_PUBLIC
195+
const std::string &
196+
node_namespace() const;
197+
198+
/// Get a mutable reference to the service type string.
199+
RCLCPP_PUBLIC
200+
std::string &
201+
service_type();
202+
203+
/// Get a const reference to the service type string.
204+
RCLCPP_PUBLIC
205+
const std::string &
206+
service_type() const;
207+
208+
/// Get a mutable reference to the service endpoint type.
209+
RCLCPP_PUBLIC
210+
rclcpp::EndpointType &
211+
endpoint_type();
212+
213+
/// Get a const reference to the service endpoint type.
214+
RCLCPP_PUBLIC
215+
const rclcpp::EndpointType &
216+
endpoint_type() const;
217+
218+
/// Get a mutable reference to the endpoint count.
219+
RCLCPP_PUBLIC
220+
size_t &
221+
endpoint_count();
222+
223+
/// Get a const reference to the endpoint count.
224+
RCLCPP_PUBLIC
225+
const size_t &
226+
endpoint_count() const;
227+
228+
/// Get a mutable reference to the GID of the service endpoint.
229+
RCLCPP_PUBLIC
230+
std::vector<std::array<uint8_t, RMW_GID_STORAGE_SIZE>> &
231+
endpoint_gids();
232+
233+
/// Get a const reference to the GID of the service endpoint.
234+
RCLCPP_PUBLIC
235+
const std::vector<std::array<uint8_t, RMW_GID_STORAGE_SIZE>> &
236+
endpoint_gids() const;
237+
238+
/// Get a mutable reference to the QoS profile of the service endpoint.
239+
RCLCPP_PUBLIC
240+
std::vector<rclcpp::QoS> &
241+
qos_profiles();
242+
243+
/// Get a const reference to the QoS profile of the service endpoint.
244+
RCLCPP_PUBLIC
245+
const std::vector<rclcpp::QoS> &
246+
qos_profiles() const;
247+
248+
/// Get a mutable reference to the type hash of the service endpoint.
249+
RCLCPP_PUBLIC
250+
rosidl_type_hash_t &
251+
service_type_hash();
252+
253+
/// Get a const reference to the type hash of the service endpoint.
254+
RCLCPP_PUBLIC
255+
const rosidl_type_hash_t &
256+
service_type_hash() const;
257+
258+
private:
259+
std::string node_name_;
260+
std::string node_namespace_;
261+
std::string service_type_;
262+
rclcpp::EndpointType endpoint_type_;
263+
std::vector<std::array<uint8_t, RMW_GID_STORAGE_SIZE>> endpoint_gids_;
264+
std::vector<rclcpp::QoS> qos_profiles_;
265+
rosidl_type_hash_t service_type_hash_;
266+
size_t endpoint_count_;
267+
};
268+
146269
namespace node_interfaces
147270
{
148271

@@ -408,6 +531,30 @@ class NodeGraphInterface
408531
virtual
409532
std::vector<rclcpp::TopicEndpointInfo>
410533
get_subscriptions_info_by_topic(const std::string & topic_name, bool no_mangle = false) const = 0;
534+
535+
/// Return the service endpoint information about clients on a given service.
536+
/**
537+
* \param[in] service_name the actual service name used; it will not be automatically remapped.
538+
* \param[in] no_mangle if `true`, `service_name` needs to be a valid middleware service name,
539+
* otherwise it should be a valid ROS service name.
540+
* \sa rclcpp::Node::get_clients_info_by_service
541+
*/
542+
RCLCPP_PUBLIC
543+
virtual
544+
std::vector<rclcpp::ServiceEndpointInfo>
545+
get_clients_info_by_service(const std::string & service_name, bool no_mangle = false) const = 0;
546+
547+
/// Return the service endpoint information about servers on a given service.
548+
/**
549+
* \param[in] service_name the actual service name used; it will not be automatically remapped.
550+
* \param[in] no_mangle if `true`, `service_name` needs to be a valid middleware service name,
551+
* otherwise it should be a valid ROS service name.
552+
* \sa rclcpp::Node::get_servers_info_by_service
553+
*/
554+
RCLCPP_PUBLIC
555+
virtual
556+
std::vector<rclcpp::ServiceEndpointInfo>
557+
get_servers_info_by_service(const std::string & service_name, bool no_mangle = false) const = 0;
411558
};
412559

413560
} // namespace node_interfaces

rclcpp/src/rclcpp/node.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -547,6 +547,18 @@ Node::get_subscriptions_info_by_topic(const std::string & topic_name, bool no_ma
547547
return node_graph_->get_subscriptions_info_by_topic(topic_name, no_mangle);
548548
}
549549

550+
std::vector<rclcpp::ServiceEndpointInfo>
551+
Node::get_clients_info_by_service(const std::string & service_name, bool no_mangle) const
552+
{
553+
return node_graph_->get_clients_info_by_service(service_name, no_mangle);
554+
}
555+
556+
std::vector<rclcpp::ServiceEndpointInfo>
557+
Node::get_servers_info_by_service(const std::string & service_name, bool no_mangle) const
558+
{
559+
return node_graph_->get_servers_info_by_service(service_name, no_mangle);
560+
}
561+
550562
void
551563
Node::for_each_callback_group(
552564
const node_interfaces::NodeBaseInterface::CallbackGroupFunction & func)

0 commit comments

Comments
 (0)