From d6fadd0b07110746e105bbfcedb59c4233d99519 Mon Sep 17 00:00:00 2001 From: Siddharth Kucheria Date: Tue, 2 Jul 2019 12:00:30 -0700 Subject: [PATCH 1/8] adding client_names_and_types_by_node Signed-off-by: Siddharth Kucheria --- rclpy/rclpy/node.py | 18 ++++++++++++++ rclpy/src/rclpy/_rclpy.c | 53 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 71 insertions(+) diff --git a/rclpy/rclpy/node.py b/rclpy/rclpy/node.py index 240835baa..5c6509e8f 100644 --- a/rclpy/rclpy/node.py +++ b/rclpy/rclpy/node.py @@ -1460,6 +1460,24 @@ def get_service_names_and_types_by_node( return _rclpy.rclpy_get_service_names_and_types_by_node( capsule, node_name, node_namespace) + def get_client_names_and_types_by_node( + self, + node_name: str, + node_namespace: str + ) -> List[Tuple[std, List[str]]]: + """ + Get a list of discovered service client topics for a remote node. + + :param node_name: Name of a remote node to get services for. + :param node_namespace: Namespace of the remode node. + :return: List of tuples. + The fist element of each tuple is the service name and the second element is a list of + service types. + """ + with self.handle as capsule: + return _rclpy.rclpy_get_client_names_and_types_by_node( + capsule, node_name, node_namespace) + def get_topic_names_and_types(self, no_demangle: bool = False) -> List[Tuple[str, List[str]]]: """ Get a list topic names and types for the node. diff --git a/rclpy/src/rclpy/_rclpy.c b/rclpy/src/rclpy/_rclpy.c index 9a881c7e1..38a1f46a1 100644 --- a/rclpy/src/rclpy/_rclpy.c +++ b/rclpy/src/rclpy/_rclpy.c @@ -3153,6 +3153,54 @@ rclpy_get_service_names_and_types_by_node(PyObject * Py_UNUSED(self), PyObject * return pyservice_names_and_types; } +/// Get a list of service client names and types associated with the given node name. +/** + * Raises ValueError if pynode is not a node capsule + * Raises RuntimeError if there is an rcl error + * + * \param[in] pynode Capsule pointing to the node + * \param[in] node_name of a remote node to get publishers for + * \return Python list of tuples. + * The first element of each tuple is the service name (string) and the second element + * is a list of service types (list of strings). +*/ +static PyObject * +rclpy_get_client_names_and_types_by_node(PyObject * Py_UNUSED(self), PyObject * args) +{ + PyObject * pynode; + char * node_name; + char * node_namespace; + + if (!PyArg_ParseTuple(args, "Oss", &pynode, &node_name, &node_namespace)) { + return NULL; + } + + rcl_node_t * node = (rcl_node_t *)PyCapsule_GetPointer(pynode, "rcl_node_t"); + if (!node) { + return NULL; + } + + rcl_names_and_types_t client_names_and_types = rcl_get_zero_initialized_names_and_types(); + rcl_allocator_t allocator = rcl_get_default_allocator(); + rcl_ret_t ret = + rcl_get_client_names_and_types_by_node(node, &allocator, node_name, node_namespace, + &client_names_and_types); + if (ret != RCL_RET_OK) { + PyErr_Format(PyExc_RuntimeError, + "Failed to get_client_names_and_types: %s", rcl_get_error_string().str); + rcl_reset_error(); + return NULL; + } + + PyObject * pyclient_names_and_types = rclpy_convert_to_py_names_and_types( + &client_names_and_types); + if (!rclpy_names_and_types_fini(&client_names_and_types)) { + Py_XDECREF(pyclient_names_and_types); + return NULL; + } + return pyclient_names_and_types; +} + /// Get a list of topic names and types having at least one subscription from the given node name. /** * Raises ValueError if pynode is not a node capsule @@ -4812,6 +4860,11 @@ static PyMethodDef rclpy_methods[] = { METH_VARARGS, "Get service list of specified node from graph API." }, + { + "rclpy_get_client_names_and_types_by_node", rclpy_get_client_names_and_types_by_node, + METH_VARARGS, + "Get a service client list of a specified node from graph API." + }, { "rclpy_get_topic_names_and_types", rclpy_get_topic_names_and_types, METH_VARARGS, "Get topic list from graph API." From 1c07b32402ab54a5952323a24462919501742754 Mon Sep 17 00:00:00 2001 From: Siddharth Kucheria Date: Tue, 2 Jul 2019 12:08:33 -0700 Subject: [PATCH 2/8] small fix Signed-off-by: Siddharth Kucheria --- rclpy/rclpy/node.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rclpy/rclpy/node.py b/rclpy/rclpy/node.py index 5c6509e8f..4b56d4daa 100644 --- a/rclpy/rclpy/node.py +++ b/rclpy/rclpy/node.py @@ -1464,7 +1464,7 @@ def get_client_names_and_types_by_node( self, node_name: str, node_namespace: str - ) -> List[Tuple[std, List[str]]]: + ) -> List[Tuple[str, List[str]]]: """ Get a list of discovered service client topics for a remote node. From b90941c447c160fa7d695b88842408f18b6ce78c Mon Sep 17 00:00:00 2001 From: Siddharth Kucheria Date: Wed, 3 Jul 2019 10:13:02 -0700 Subject: [PATCH 3/8] function description Signed-off-by: Siddharth Kucheria --- rclpy/rclpy/node.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/rclpy/rclpy/node.py b/rclpy/rclpy/node.py index 4b56d4daa..117ca0c68 100644 --- a/rclpy/rclpy/node.py +++ b/rclpy/rclpy/node.py @@ -1468,11 +1468,11 @@ def get_client_names_and_types_by_node( """ Get a list of discovered service client topics for a remote node. - :param node_name: Name of a remote node to get services for. + :param node_name: Name of a remote node to get service clients for. :param node_namespace: Namespace of the remode node. :return: List of tuples. - The fist element of each tuple is the service name and the second element is a list of - service types. + The fist element of each tuple is the service client name and the second element is a list of + service client types. """ with self.handle as capsule: return _rclpy.rclpy_get_client_names_and_types_by_node( From 701c84f1c4d6138cea20b44e438bfa34185ceb3b Mon Sep 17 00:00:00 2001 From: Siddharth Kucheria Date: Mon, 8 Jul 2019 10:41:31 -0700 Subject: [PATCH 4/8] Update rclpy/rclpy/node.py Co-Authored-By: Jacob Perron --- rclpy/rclpy/node.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rclpy/rclpy/node.py b/rclpy/rclpy/node.py index 117ca0c68..f88be9e4b 100644 --- a/rclpy/rclpy/node.py +++ b/rclpy/rclpy/node.py @@ -1469,7 +1469,7 @@ def get_client_names_and_types_by_node( Get a list of discovered service client topics for a remote node. :param node_name: Name of a remote node to get service clients for. - :param node_namespace: Namespace of the remode node. + :param node_namespace: Namespace of the remote node. :return: List of tuples. The fist element of each tuple is the service client name and the second element is a list of service client types. From 616f2418b72fbe8a728fe570a517b41699646835 Mon Sep 17 00:00:00 2001 From: Siddharth Kucheria Date: Mon, 8 Jul 2019 10:41:38 -0700 Subject: [PATCH 5/8] Update rclpy/src/rclpy/_rclpy.c Co-Authored-By: Jacob Perron --- rclpy/src/rclpy/_rclpy.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rclpy/src/rclpy/_rclpy.c b/rclpy/src/rclpy/_rclpy.c index 38a1f46a1..0f2671639 100644 --- a/rclpy/src/rclpy/_rclpy.c +++ b/rclpy/src/rclpy/_rclpy.c @@ -4858,7 +4858,7 @@ static PyMethodDef rclpy_methods[] = { { "rclpy_get_service_names_and_types_by_node", rclpy_get_service_names_and_types_by_node, METH_VARARGS, - "Get service list of specified node from graph API." + "Get service server list of specified node from graph API." }, { "rclpy_get_client_names_and_types_by_node", rclpy_get_client_names_and_types_by_node, From b225b98910a1366bcdac1d875f908cd1efdef397 Mon Sep 17 00:00:00 2001 From: Siddharth Kucheria Date: Mon, 8 Jul 2019 11:49:22 -0700 Subject: [PATCH 6/8] minor changes --- rclpy/rclpy/node.py | 10 +++++----- rclpy/src/rclpy/_rclpy.c | 2 ++ rclpy/test/test_node.py | 6 ++++++ 3 files changed, 13 insertions(+), 5 deletions(-) diff --git a/rclpy/rclpy/node.py b/rclpy/rclpy/node.py index f88be9e4b..45b575e97 100644 --- a/rclpy/rclpy/node.py +++ b/rclpy/rclpy/node.py @@ -1448,13 +1448,13 @@ def get_service_names_and_types_by_node( node_namespace: str ) -> List[Tuple[str, List[str]]]: """ - Get a list of discovered service topics for a remote node. + Get a list of discovered service sever topics for a remote node. :param node_name: Name of a remote node to get services for. :param node_namespace: Namespace of the remote node. :return: List of tuples. - The first element of each tuple is the service name and the second element is a list of - service types. + The first element of each tuple is the service server name + and the second element is a list of service types. """ with self.handle as capsule: return _rclpy.rclpy_get_service_names_and_types_by_node( @@ -1471,8 +1471,8 @@ def get_client_names_and_types_by_node( :param node_name: Name of a remote node to get service clients for. :param node_namespace: Namespace of the remote node. :return: List of tuples. - The fist element of each tuple is the service client name and the second element is a list of - service client types. + The fist element of each tuple is the service client name + and the second element is a list of service client types. """ with self.handle as capsule: return _rclpy.rclpy_get_client_names_and_types_by_node( diff --git a/rclpy/src/rclpy/_rclpy.c b/rclpy/src/rclpy/_rclpy.c index 0f2671639..b5c578753 100644 --- a/rclpy/src/rclpy/_rclpy.c +++ b/rclpy/src/rclpy/_rclpy.c @@ -3141,6 +3141,7 @@ rclpy_get_service_names_and_types_by_node(PyObject * Py_UNUSED(self), PyObject * PyErr_Format(PyExc_RuntimeError, "Failed to get_service_names_and_types: %s", rcl_get_error_string().str); rcl_reset_error(); + rclpy_names_and_types_fini(&service_names_and_types); return NULL; } @@ -3189,6 +3190,7 @@ rclpy_get_client_names_and_types_by_node(PyObject * Py_UNUSED(self), PyObject * PyErr_Format(PyExc_RuntimeError, "Failed to get_client_names_and_types: %s", rcl_get_error_string().str); rcl_reset_error(); + rclpy_names_and_types_fini(&client_names_and_types); return NULL; } diff --git a/rclpy/test/test_node.py b/rclpy/test/test_node.py index 22229d7cd..96496c8e3 100644 --- a/rclpy/test/test_node.py +++ b/rclpy/test/test_node.py @@ -176,6 +176,12 @@ def test_service_names_and_types(self): # test that it doesn't raise self.node.get_service_names_and_types() + def test_client_names_and_types_by_node(self): + # test that it doesnt raise + # node1 = rclpy.create_node( + # 'my_node', namespace='/my_ns', use_global_arguments=True, context=context) + self.node.get_client_names_and_types_by_node(TEST_NODE, TEST_NAMESPACE) + def test_topic_names_and_types(self): # test that it doesn't raise self.node.get_topic_names_and_types(no_demangle=True) From 16f480e72290dd6a5e64bf69e23391c20c242977 Mon Sep 17 00:00:00 2001 From: Siddharth Kucheria Date: Mon, 8 Jul 2019 14:41:49 -0700 Subject: [PATCH 7/8] Update node.py --- rclpy/rclpy/node.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rclpy/rclpy/node.py b/rclpy/rclpy/node.py index 45b575e97..697f13ac5 100644 --- a/rclpy/rclpy/node.py +++ b/rclpy/rclpy/node.py @@ -1448,7 +1448,7 @@ def get_service_names_and_types_by_node( node_namespace: str ) -> List[Tuple[str, List[str]]]: """ - Get a list of discovered service sever topics for a remote node. + Get a list of discovered service server topics for a remote node. :param node_name: Name of a remote node to get services for. :param node_namespace: Namespace of the remote node. From 5de23a565ea2ba884b012e57deaa9c0b0ccbce9c Mon Sep 17 00:00:00 2001 From: Siddharth Kucheria Date: Mon, 8 Jul 2019 15:54:45 -0700 Subject: [PATCH 8/8] Update test_node.py --- rclpy/test/test_node.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/rclpy/test/test_node.py b/rclpy/test/test_node.py index 96496c8e3..252f8e2e1 100644 --- a/rclpy/test/test_node.py +++ b/rclpy/test/test_node.py @@ -176,10 +176,12 @@ def test_service_names_and_types(self): # test that it doesn't raise self.node.get_service_names_and_types() + def test_service_names_and_types_by_node(self): + # test that it doesnt raise + self.node.get_service_names_and_types_by_node(TEST_NODE, TEST_NAMESPACE) + def test_client_names_and_types_by_node(self): # test that it doesnt raise - # node1 = rclpy.create_node( - # 'my_node', namespace='/my_ns', use_global_arguments=True, context=context) self.node.get_client_names_and_types_by_node(TEST_NODE, TEST_NAMESPACE) def test_topic_names_and_types(self):