rclnodejs 1.6.0 → 1.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/index.js +59 -0
- package/lib/action/client.js +55 -9
- package/lib/action/deferred.js +8 -2
- package/lib/action/server.js +10 -1
- package/lib/action/uuid.js +4 -1
- package/lib/client.js +152 -3
- package/lib/clock.js +4 -1
- package/lib/context.js +12 -2
- package/lib/duration.js +37 -12
- package/lib/errors.js +571 -0
- package/lib/event_handler.js +21 -4
- package/lib/interface_loader.js +52 -12
- package/lib/lifecycle.js +8 -2
- package/lib/logging.js +12 -3
- package/lib/message_serialization.js +10 -2
- package/lib/native_loader.js +9 -4
- package/lib/node.js +270 -49
- package/lib/parameter.js +172 -35
- package/lib/parameter_client.js +506 -0
- package/lib/parameter_watcher.js +309 -0
- package/lib/qos.js +22 -5
- package/lib/rate.js +6 -1
- package/lib/serialization.js +7 -2
- package/lib/time.js +136 -21
- package/lib/time_source.js +13 -4
- package/lib/utils.js +27 -1
- package/lib/validator.js +11 -12
- package/package.json +1 -1
- package/prebuilds/linux-x64/jazzy-noble-x64-rclnodejs.node +0 -0
- package/types/base.d.ts +3 -0
- package/types/client.d.ts +36 -0
- package/types/errors.d.ts +447 -0
- package/types/interfaces.d.ts +1910 -1
- package/types/node.d.ts +40 -0
- package/types/parameter_client.d.ts +252 -0
- package/types/parameter_watcher.d.ts +104 -0
package/lib/time_source.js
CHANGED
|
@@ -19,6 +19,7 @@ const { Clock, ROSClock } = require('./clock.js');
|
|
|
19
19
|
const { ClockType } = Clock;
|
|
20
20
|
const { Parameter, ParameterType } = require('./parameter.js');
|
|
21
21
|
const Time = require('./time.js');
|
|
22
|
+
const { TypeValidationError, OperationError } = require('./errors.js');
|
|
22
23
|
|
|
23
24
|
const USE_SIM_TIME_PARAM = 'use_sim_time';
|
|
24
25
|
const CLOCK_TOPIC = '/clock';
|
|
@@ -102,7 +103,9 @@ class TimeSource {
|
|
|
102
103
|
*/
|
|
103
104
|
attachNode(node) {
|
|
104
105
|
if ((!node) instanceof rclnodejs.ShadowNode) {
|
|
105
|
-
throw new
|
|
106
|
+
throw new TypeValidationError('node', node, 'Node', {
|
|
107
|
+
entityType: 'time source',
|
|
108
|
+
});
|
|
106
109
|
}
|
|
107
110
|
|
|
108
111
|
if (this._node) {
|
|
@@ -150,8 +153,12 @@ class TimeSource {
|
|
|
150
153
|
detachNode() {
|
|
151
154
|
if (this._clockSubscription) {
|
|
152
155
|
if (!this._node) {
|
|
153
|
-
throw new
|
|
154
|
-
'Unable to destroy previously created clock subscription'
|
|
156
|
+
throw new OperationError(
|
|
157
|
+
'Unable to destroy previously created clock subscription',
|
|
158
|
+
{
|
|
159
|
+
code: 'NO_NODE_ATTACHED',
|
|
160
|
+
entityType: 'time source',
|
|
161
|
+
}
|
|
155
162
|
);
|
|
156
163
|
}
|
|
157
164
|
this._node.destroySubscription(this._clockSubscription);
|
|
@@ -167,7 +174,9 @@ class TimeSource {
|
|
|
167
174
|
*/
|
|
168
175
|
attachClock(clock) {
|
|
169
176
|
if (!(clock instanceof ROSClock)) {
|
|
170
|
-
throw new
|
|
177
|
+
throw new TypeValidationError('clock', clock, 'ROSClock', {
|
|
178
|
+
entityType: 'time source',
|
|
179
|
+
});
|
|
171
180
|
}
|
|
172
181
|
clock.rosTimeOverride = this._lastTimeSet;
|
|
173
182
|
clock.isRosTimeActive = this._isRosTimeActive;
|
package/lib/utils.js
CHANGED
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
const fs = require('fs');
|
|
16
16
|
const fsPromises = require('fs/promises');
|
|
17
17
|
const path = require('path');
|
|
18
|
+
const { ValidationError } = require('./errors.js');
|
|
18
19
|
|
|
19
20
|
/**
|
|
20
21
|
* Ensure directory exists, create recursively if needed (async)
|
|
@@ -182,6 +183,25 @@ function detectUbuntuCodename() {
|
|
|
182
183
|
}
|
|
183
184
|
}
|
|
184
185
|
|
|
186
|
+
/**
|
|
187
|
+
* Normalize a ROS 2 node name by removing the leading slash if present.
|
|
188
|
+
*
|
|
189
|
+
* ROS 2 node names may be specified with or without a leading slash depending
|
|
190
|
+
* on the context. This utility ensures consistent representation without the
|
|
191
|
+
* leading slash, which is the standard format for most ROS 2 APIs.
|
|
192
|
+
*
|
|
193
|
+
* @param {string} nodeName - The node name to normalize
|
|
194
|
+
* @returns {string} The normalized node name without leading slash
|
|
195
|
+
*
|
|
196
|
+
* @example
|
|
197
|
+
* normalizeNodeName('my_node') // 'my_node'
|
|
198
|
+
* normalizeNodeName('/my_node') // 'my_node'
|
|
199
|
+
* normalizeNodeName('/ns/my_node') // 'ns/my_node'
|
|
200
|
+
*/
|
|
201
|
+
function normalizeNodeName(nodeName) {
|
|
202
|
+
return nodeName.startsWith('/') ? nodeName.substring(1) : nodeName;
|
|
203
|
+
}
|
|
204
|
+
|
|
185
205
|
/**
|
|
186
206
|
* Check if two numbers are equal within a given tolerance.
|
|
187
207
|
*
|
|
@@ -294,7 +314,12 @@ function compareVersions(version1, version2, operator) {
|
|
|
294
314
|
case '!==':
|
|
295
315
|
return cmp !== 0;
|
|
296
316
|
default:
|
|
297
|
-
throw new
|
|
317
|
+
throw new ValidationError(`Invalid operator: ${operator}`, {
|
|
318
|
+
code: 'INVALID_OPERATOR',
|
|
319
|
+
argumentName: 'operator',
|
|
320
|
+
providedValue: operator,
|
|
321
|
+
expectedType: "'eq' | 'ne' | 'lt' | 'lte' | 'gt' | 'gte'",
|
|
322
|
+
});
|
|
298
323
|
}
|
|
299
324
|
}
|
|
300
325
|
|
|
@@ -302,6 +327,7 @@ module.exports = {
|
|
|
302
327
|
// General utilities
|
|
303
328
|
detectUbuntuCodename,
|
|
304
329
|
isClose,
|
|
330
|
+
normalizeNodeName,
|
|
305
331
|
|
|
306
332
|
// File system utilities (async)
|
|
307
333
|
ensureDir,
|
package/lib/validator.js
CHANGED
|
@@ -15,16 +15,15 @@
|
|
|
15
15
|
'use strict';
|
|
16
16
|
|
|
17
17
|
const rclnodejs = require('./native_loader.js');
|
|
18
|
+
const { TypeValidationError, NameValidationError } = require('./errors.js');
|
|
18
19
|
|
|
19
20
|
/**
|
|
20
21
|
* An object - Representing a validator in ROS.
|
|
21
22
|
* @exports validator
|
|
22
23
|
*/
|
|
23
24
|
let validator = {
|
|
24
|
-
_createErrorFromValidation: function (result) {
|
|
25
|
-
|
|
26
|
-
err.invalidIndex = result[1];
|
|
27
|
-
return err;
|
|
25
|
+
_createErrorFromValidation: function (result, nameValue, nameType) {
|
|
26
|
+
return new NameValidationError(nameValue, nameType, result[0], result[1]);
|
|
28
27
|
},
|
|
29
28
|
|
|
30
29
|
/**
|
|
@@ -34,14 +33,14 @@ let validator = {
|
|
|
34
33
|
*/
|
|
35
34
|
validateFullTopicName(topic) {
|
|
36
35
|
if (typeof topic !== 'string') {
|
|
37
|
-
throw new
|
|
36
|
+
throw new TypeValidationError('topic', topic, 'string');
|
|
38
37
|
}
|
|
39
38
|
|
|
40
39
|
let result = rclnodejs.validateFullTopicName(topic);
|
|
41
40
|
if (result === null) {
|
|
42
41
|
return true;
|
|
43
42
|
}
|
|
44
|
-
throw this._createErrorFromValidation(result);
|
|
43
|
+
throw this._createErrorFromValidation(result, topic, 'topic');
|
|
45
44
|
},
|
|
46
45
|
|
|
47
46
|
/**
|
|
@@ -51,14 +50,14 @@ let validator = {
|
|
|
51
50
|
*/
|
|
52
51
|
validateNodeName(name) {
|
|
53
52
|
if (typeof name !== 'string') {
|
|
54
|
-
throw new
|
|
53
|
+
throw new TypeValidationError('name', name, 'string');
|
|
55
54
|
}
|
|
56
55
|
|
|
57
56
|
let result = rclnodejs.validateNodeName(name);
|
|
58
57
|
if (result === null) {
|
|
59
58
|
return true;
|
|
60
59
|
}
|
|
61
|
-
throw this._createErrorFromValidation(result);
|
|
60
|
+
throw this._createErrorFromValidation(result, name, 'node');
|
|
62
61
|
},
|
|
63
62
|
|
|
64
63
|
/**
|
|
@@ -68,14 +67,14 @@ let validator = {
|
|
|
68
67
|
*/
|
|
69
68
|
validateTopicName(topic) {
|
|
70
69
|
if (typeof topic !== 'string') {
|
|
71
|
-
throw new
|
|
70
|
+
throw new TypeValidationError('topic', topic, 'string');
|
|
72
71
|
}
|
|
73
72
|
|
|
74
73
|
let result = rclnodejs.validateTopicName(topic);
|
|
75
74
|
if (result === null) {
|
|
76
75
|
return true;
|
|
77
76
|
}
|
|
78
|
-
throw this._createErrorFromValidation(result);
|
|
77
|
+
throw this._createErrorFromValidation(result, topic, 'topic');
|
|
79
78
|
},
|
|
80
79
|
|
|
81
80
|
/**
|
|
@@ -85,14 +84,14 @@ let validator = {
|
|
|
85
84
|
*/
|
|
86
85
|
validateNamespace(namespace) {
|
|
87
86
|
if (typeof namespace !== 'string') {
|
|
88
|
-
throw new
|
|
87
|
+
throw new TypeValidationError('namespace', namespace, 'string');
|
|
89
88
|
}
|
|
90
89
|
|
|
91
90
|
let result = rclnodejs.validateNamespace(namespace);
|
|
92
91
|
if (result === null) {
|
|
93
92
|
return true;
|
|
94
93
|
}
|
|
95
|
-
throw this._createErrorFromValidation(result);
|
|
94
|
+
throw this._createErrorFromValidation(result, namespace, 'namespace');
|
|
96
95
|
},
|
|
97
96
|
};
|
|
98
97
|
|
package/package.json
CHANGED
|
File without changes
|
package/types/base.d.ts
CHANGED
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
/// <reference path="./distro.d.ts" />
|
|
9
9
|
/// <reference path="./duration.d.ts" />
|
|
10
10
|
/// <reference path="./entity.d.ts" />
|
|
11
|
+
/// <reference path="./errors.d.ts" />
|
|
11
12
|
/// <reference path="./guard_condition.d.ts" />
|
|
12
13
|
/// <reference path="./interfaces.d.ts" />
|
|
13
14
|
/// <reference path="./lifecycle.d.ts" />
|
|
@@ -16,6 +17,8 @@
|
|
|
16
17
|
/// <reference path="./node.d.ts" />
|
|
17
18
|
/// <reference path="./node_options.d.ts" />
|
|
18
19
|
/// <reference path="./parameter.d.ts" />
|
|
20
|
+
/// <reference path="./parameter_client.d.ts" />
|
|
21
|
+
/// <reference path="./parameter_watcher.d.ts" />
|
|
19
22
|
/// <reference path="./publisher.d.ts" />
|
|
20
23
|
/// <reference path="./qos.d.ts" />
|
|
21
24
|
/// <reference path="./rate.d.ts" />
|
package/types/client.d.ts
CHANGED
|
@@ -14,6 +14,21 @@ declare module 'rclnodejs' {
|
|
|
14
14
|
callback: Client.ResponseCallback<T>
|
|
15
15
|
): void;
|
|
16
16
|
|
|
17
|
+
/**
|
|
18
|
+
* Make a service request and return a Promise that resolves with the response.
|
|
19
|
+
*
|
|
20
|
+
* @param request - Request to be submitted.
|
|
21
|
+
* @param options - Optional parameters for the request.
|
|
22
|
+
* @returns Promise that resolves with the service response.
|
|
23
|
+
* @throws TimeoutError if the request times out (when options.timeout is exceeded).
|
|
24
|
+
* @throws AbortError if the request is manually aborted (via options.signal).
|
|
25
|
+
* @throws Error if the request fails for other reasons.
|
|
26
|
+
*/
|
|
27
|
+
sendRequestAsync(
|
|
28
|
+
request: ServiceRequestMessage<T>,
|
|
29
|
+
options?: Client.AsyncRequestOptions
|
|
30
|
+
): Promise<ServiceResponseMessage<T>>;
|
|
31
|
+
|
|
17
32
|
/**
|
|
18
33
|
* Checks if the service is ready.
|
|
19
34
|
*
|
|
@@ -74,5 +89,26 @@ declare module 'rclnodejs' {
|
|
|
74
89
|
export type ResponseCallback<T extends TypeClass<ServiceTypeClassName>> = (
|
|
75
90
|
response: ServiceResponseMessage<T>
|
|
76
91
|
) => void;
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Options for async service requests
|
|
95
|
+
*/
|
|
96
|
+
export interface AsyncRequestOptions {
|
|
97
|
+
/**
|
|
98
|
+
* Timeout in milliseconds for the request.
|
|
99
|
+
* Internally uses AbortSignal.timeout() for standards compliance.
|
|
100
|
+
*/
|
|
101
|
+
timeout?: number;
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* AbortSignal to cancel the request.
|
|
105
|
+
* When the signal is aborted, the request will be cancelled
|
|
106
|
+
* and the promise will reject with an AbortError.
|
|
107
|
+
*
|
|
108
|
+
* Can be combined with timeout parameter - whichever happens first
|
|
109
|
+
* will abort the request.
|
|
110
|
+
*/
|
|
111
|
+
signal?: AbortSignal;
|
|
112
|
+
}
|
|
77
113
|
}
|
|
78
114
|
}
|