From 2b8ca58bbcd05ce66be7f548dc3654017c13747e Mon Sep 17 00:00:00 2001 From: Minggang Wang Date: Thu, 6 Feb 2025 16:44:35 +0800 Subject: [PATCH 1/3] Add types to ParameterService Since ROS2 Jazzy, parameter services support a service type of rcl_interfaces/srv/GetParameterTypes, which can get a list of parameter types associated with the requested parameters. This patch implements: 1. Add service /node_name/get_parameters, which is used to get the parameter types. 2. Add unit test, Get_parameter_types, into test-parameter-service.js. Meanwhile, this patch fixes the timeout issue when executing: ros2 param list node_name because of absence of /node_name/get_parameters. Fix: #1024 --- lib/node.js | 20 ++++++++++++++++++++ lib/parameter_service.js | 27 +++++++++++++++++++++++++++ test/test-parameter-service.js | 30 ++++++++++++++++++++++++++++++ 3 files changed, 77 insertions(+) diff --git a/lib/node.js b/lib/node.js index fdc7da43..f76bdb43 100644 --- a/lib/node.js +++ b/lib/node.js @@ -1273,6 +1273,26 @@ class Node extends rclnodejs.ShadowNode { return params; } + /** + * Get the types of given parameters. + * + * Return the types of given parameters. + * + * @param {string[]} [names] - The names of the declared parameters. + * @return {Uint8Array} - The types. + */ + getParameterTypes(names = []) { + let types = []; + + for (const name of names) { + const descriptor = this._parameterDescriptors.get(name); + if (descriptor) { + types.push(descriptor.type); + } + } + return types; + } + /** * Get the names of all declared parameters. * diff --git a/lib/parameter_service.js b/lib/parameter_service.js index adaf989f..752d4665 100644 --- a/lib/parameter_service.js +++ b/lib/parameter_service.js @@ -110,6 +110,16 @@ class ParameterService { } ); + // Create GetParameterTypes service. + const getParameterTypesServiceName = nodeName + '/get_parameter_types'; + this._node.createService( + 'rcl_interfaces/srv/GetParameterTypes', + getParameterTypesServiceName, + (request, response) => { + this._handleGetParameterTypes(request, response); + } + ); + // create SetParametersAtomically service const setParametersAtomicallyServiceName = nodeName + '/set_parameters_atomically'; @@ -266,6 +276,23 @@ class ParameterService { response.send(msg); } + /** + * Get a list of parameter types. + * + * request.names identifies the parameter types to get. + * + * @param {GetParameterTypes_Request} request - The client request. + * @param {GetParameterTypes_Response} response - The service response with + * Uint8Array. + * @return {undefined} - + */ + _handleGetParameterTypes(request, response) { + const types = this._node.getParameterTypes(request.names); + const msg = response.template; + msg.types = types; + response.send(msg); + } + /** * Update a list of parameters atomically. * diff --git a/test/test-parameter-service.js b/test/test-parameter-service.js index b90140c6..507b0a6e 100644 --- a/test/test-parameter-service.js +++ b/test/test-parameter-service.js @@ -367,4 +367,34 @@ describe('Parameter_server tests', function () { `Expected 3 parameter-events, received ${eventCount} events.` ); }); + + it('Get_parameter_types', async function () { + const client = clientNode.createClient( + 'rcl_interfaces/srv/GetParameterTypes', + 'test_node/get_parameter_types' + ); + await client.waitForService(); + + const ParamTypes = rclnodejs.require('rcl_interfaces/msg/ParameterType'); + const request = new (rclnodejs.require( + 'rcl_interfaces/srv/GetParameterTypes' + ).Request)(); + request.names = ['p1', 'p2', 'A.p3']; + let success = false; + + client.sendRequest(request, (response) => { + assert.deepEqual(response.types.length, 3); + assert.deepEqual( + response.types, + Uint8Array.from([ + ParamTypes.PARAMETER_STRING, + ParamTypes.PARAMETER_INTEGER, + ParamTypes.PARAMETER_BOOL, + ]) + ); + success = true; + }); + await assertUtils.createDelay(STD_WAIT); + assert.ok(success); + }); }); From e62377434bb996a6808c806177e2737173908c6c Mon Sep 17 00:00:00 2001 From: Minggang Wang Date: Thu, 6 Feb 2025 17:24:42 +0800 Subject: [PATCH 2/3] Fix test failure of destoryService() --- test/test-extra-destroy-methods.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/test-extra-destroy-methods.js b/test/test-extra-destroy-methods.js index 9e3f5f91..aa4e5246 100644 --- a/test/test-extra-destroy-methods.js +++ b/test/test-extra-destroy-methods.js @@ -93,7 +93,7 @@ describe('Node extra destroy methods testing', function () { const AddTwoInts = 'example_interfaces/srv/AddTwoInts'; // const AddTwoInts = rclnodejs.require('example_interfaces/srv/AddTwoInts'); var service = node.createService(AddTwoInts, 'add_two_ints', () => {}); - assert.deepStrictEqual(node._services.length, 6); + assert.deepStrictEqual(node._services.length, 7); assertThrowsError( function () { From c426e1c071abbb5a60d61f34640e439c9c1df449 Mon Sep 17 00:00:00 2001 From: Minggang Wang Date: Fri, 7 Feb 2025 09:45:14 +0800 Subject: [PATCH 3/3] Fix test failure of destoryService() --- test/test-extra-destroy-methods.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/test-extra-destroy-methods.js b/test/test-extra-destroy-methods.js index aa4e5246..d2ecdc9d 100644 --- a/test/test-extra-destroy-methods.js +++ b/test/test-extra-destroy-methods.js @@ -105,7 +105,7 @@ describe('Node extra destroy methods testing', function () { ); node.destroyService(service); - assert.deepStrictEqual(node._services.length, 5); + assert.deepStrictEqual(node._services.length, 6); }); it('destroyTimer()', function () {