rclnodejs 0.22.3 → 0.23.1
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/README.md +6 -7
- package/binding.gyp +2 -0
- package/index.js +4 -0
- package/lib/client.js +28 -0
- package/lib/lifecycle.js +4 -1
- package/lib/node_options.js +1 -1
- package/lib/service.js +38 -2
- package/lib/service_introspection.js +30 -0
- package/package.json +24 -24
- package/rosidl_gen/idl_generator.js +23 -3
- package/rosidl_gen/templates/service_event.dot +304 -0
- package/rostsd_gen/index.js +15 -12
- package/scripts/npmjs-readme.md +6 -7
- package/src/rcl_bindings.cpp +72 -1
- package/types/base.d.ts +1 -0
- package/types/client.d.ts +12 -0
- package/types/interfaces.d.ts +750 -0
- package/types/service.d.ts +12 -0
- package/types/service_introspection.d.ts +10 -0
- package/.github/workflows/identify-ros-distro.yml +0 -48
- package/.github/workflows/linux-build-and-test-compatibility.yml +0 -38
- package/.github/workflows/linux-build-and-test.yml +0 -53
- package/.github/workflows/windows-build-and-test-compatibility.yml +0 -54
- package/.github/workflows/windows-build-and-test.yml +0 -70
- package/.prettierrc.yml +0 -4
- package/.vscode/settings.json +0 -79
|
@@ -0,0 +1,304 @@
|
|
|
1
|
+
// This file is automatically generated by Intel rclnodejs
|
|
2
|
+
//
|
|
3
|
+
// *** DO NOT EDIT directly
|
|
4
|
+
//
|
|
5
|
+
'use strict';
|
|
6
|
+
|
|
7
|
+
{{
|
|
8
|
+
const interfaceName = it.serviceInfo.interfaceName;
|
|
9
|
+
const pkgName = it.serviceInfo.pkgName;
|
|
10
|
+
const subFolder = it.serviceInfo.subFolder;
|
|
11
|
+
|
|
12
|
+
const baseName = it.serviceInfo.pkgName + '__' + it.serviceInfo.subFolder + '__' + it.serviceInfo.interfaceName;
|
|
13
|
+
}}
|
|
14
|
+
|
|
15
|
+
const ref = require('@rclnodejs/ref-napi');
|
|
16
|
+
const StructType = require('@rclnodejs/ref-struct-di')(ref);
|
|
17
|
+
const ArrayType = require('@rclnodejs/ref-array-di')(ref);
|
|
18
|
+
const primitiveTypes = require('../../rosidl_gen/primitive_types.js');
|
|
19
|
+
const deallocator = require('../../rosidl_gen/deallocator.js');
|
|
20
|
+
const translator = require('../../rosidl_gen/message_translator.js');
|
|
21
|
+
const ServiceEventInfoWrapper = require('../service_msgs/service_msgs__msg__ServiceEventInfo.js');
|
|
22
|
+
const {{=interfaceName}}_RequestWrapper = require('./{{=pkgName}}__{{=subFolder}}__{{=interfaceName}}_Request.js');
|
|
23
|
+
const {{=interfaceName}}_ResponseWrapper = require('./{{=pkgName}}__{{=subFolder}}__{{=interfaceName}}_Response.js');
|
|
24
|
+
const {{=interfaceName}}_EventRefStruct = StructType({
|
|
25
|
+
info: ServiceEventInfoWrapper.refObjectType,
|
|
26
|
+
request: {{=interfaceName}}_RequestWrapper.refObjectArrayType,
|
|
27
|
+
response: {{=interfaceName}}_ResponseWrapper.refObjectArrayType,
|
|
28
|
+
});
|
|
29
|
+
const {{=interfaceName}}_EventRefArray = ArrayType({{=interfaceName}}_EventRefStruct);
|
|
30
|
+
const {{=interfaceName}}_EventRefStructArray = StructType({
|
|
31
|
+
data: {{=interfaceName}}_EventRefArray,
|
|
32
|
+
size: ref.types.size_t,
|
|
33
|
+
capacity: ref.types.size_t
|
|
34
|
+
});
|
|
35
|
+
// Define the wrapper class.
|
|
36
|
+
class {{=interfaceName}}_EventWrapper {
|
|
37
|
+
constructor(other) {
|
|
38
|
+
this._wrapperFields = {};
|
|
39
|
+
if (typeof other === 'object' && other._refObject) {
|
|
40
|
+
this._refObject = new {{=interfaceName}}_EventRefStruct(other._refObject.toObject());
|
|
41
|
+
this._wrapperFields.info = new ServiceEventInfoWrapper(other._wrapperFields.info);
|
|
42
|
+
this._wrapperFields.request = {{=interfaceName}}_RequestWrapper.createArray();
|
|
43
|
+
this._wrapperFields.request.copy(other._wrapperFields.request);
|
|
44
|
+
this._wrapperFields.response = {{=interfaceName}}_ResponseWrapper.createArray();
|
|
45
|
+
this._wrapperFields.response.copy(other._wrapperFields.response);
|
|
46
|
+
} else if (typeof other !== 'undefined') {
|
|
47
|
+
this._initMembers();
|
|
48
|
+
translator.constructFromPlanObject(this, other);
|
|
49
|
+
} else {
|
|
50
|
+
this._initMembers();
|
|
51
|
+
}
|
|
52
|
+
this.freeze();
|
|
53
|
+
}
|
|
54
|
+
_initMembers() {
|
|
55
|
+
this._refObject = new {{=interfaceName}}_EventRefStruct();
|
|
56
|
+
this._wrapperFields.info = new ServiceEventInfoWrapper();
|
|
57
|
+
this._wrapperFields.request = {{=interfaceName}}_RequestWrapper.createArray();
|
|
58
|
+
this._wrapperFields.response = {{=interfaceName}}_ResponseWrapper.createArray();
|
|
59
|
+
}
|
|
60
|
+
static createFromRefObject(refObject) {
|
|
61
|
+
let self = new {{=interfaceName}}_EventWrapper();
|
|
62
|
+
self.copyRefObject(refObject);
|
|
63
|
+
return self;
|
|
64
|
+
}
|
|
65
|
+
static createArray() {
|
|
66
|
+
return new {{=interfaceName}}_EventArrayWrapper;
|
|
67
|
+
}
|
|
68
|
+
static get ArrayType() {
|
|
69
|
+
return {{=interfaceName}}_EventArrayWrapper;
|
|
70
|
+
}
|
|
71
|
+
static get refObjectArrayType() {
|
|
72
|
+
return {{=interfaceName}}_EventRefStructArray
|
|
73
|
+
}
|
|
74
|
+
static get refObjectType() {
|
|
75
|
+
return {{=interfaceName}}_EventRefStruct;
|
|
76
|
+
}
|
|
77
|
+
toRawROS() {
|
|
78
|
+
this.freeze(true);
|
|
79
|
+
return this._refObject.ref();
|
|
80
|
+
}
|
|
81
|
+
freeze(own = false, checkConsistency = false) {
|
|
82
|
+
if (checkConsistency) {
|
|
83
|
+
}
|
|
84
|
+
this._wrapperFields.info.freeze(own, checkConsistency);
|
|
85
|
+
this._refObject.info = this._wrapperFields.info.refObject;
|
|
86
|
+
this._wrapperFields.request.freeze(own, checkConsistency);
|
|
87
|
+
this._refObject.request = this._wrapperFields.request.refObject;
|
|
88
|
+
this._wrapperFields.response.freeze(own, checkConsistency);
|
|
89
|
+
this._refObject.response = this._wrapperFields.response.refObject;
|
|
90
|
+
}
|
|
91
|
+
serialize() {
|
|
92
|
+
this.freeze(false, true);
|
|
93
|
+
return this._refObject.ref();
|
|
94
|
+
}
|
|
95
|
+
deserialize(refObject) {
|
|
96
|
+
this._wrapperFields.info.copyRefObject(refObject.info);
|
|
97
|
+
this._wrapperFields.request.copyRefObject(refObject.request);
|
|
98
|
+
this._wrapperFields.response.copyRefObject(refObject.response);
|
|
99
|
+
}
|
|
100
|
+
toPlainObject(enableTypedArray) {
|
|
101
|
+
return translator.toPlainObject(this, enableTypedArray);
|
|
102
|
+
}
|
|
103
|
+
static freeStruct(refObject) {
|
|
104
|
+
ServiceEventInfoWrapper.freeStruct(refObject.info);
|
|
105
|
+
if (refObject.request.size != 0) {
|
|
106
|
+
{{=interfaceName}}_RequestWrapper.ArrayType.freeArray(refObject.request);
|
|
107
|
+
if ({{=interfaceName}}_RequestWrapper.ArrayType.useTypedArray) {
|
|
108
|
+
// Do nothing, the v8 will take the ownership of the ArrayBuffer used by the typed array.
|
|
109
|
+
} else {
|
|
110
|
+
deallocator.freeStructMember(refObject.request, {{=interfaceName}}_RequestWrapper.refObjectArrayType, 'data');
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
if (refObject.response.size != 0) {
|
|
114
|
+
{{=interfaceName}}_ResponseWrapper.ArrayType.freeArray(refObject.response);
|
|
115
|
+
if ({{=interfaceName}}_ResponseWrapper.ArrayType.useTypedArray) {
|
|
116
|
+
// Do nothing, the v8 will take the ownership of the ArrayBuffer used by the typed array.
|
|
117
|
+
} else {
|
|
118
|
+
deallocator.freeStructMember(refObject.response, {{=interfaceName}}_ResponseWrapper.refObjectArrayType, 'data');
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
static destoryRawROS(msg) {
|
|
123
|
+
{{=interfaceName}}_EventWrapper.freeStruct(msg.refObject);
|
|
124
|
+
}
|
|
125
|
+
static type() {
|
|
126
|
+
return {pkgName: '{{=pkgName}}', subFolder: '{{=subFolder}}', interfaceName: '{{=interfaceName}}_Event'};
|
|
127
|
+
}
|
|
128
|
+
static isPrimitive() {
|
|
129
|
+
return false;
|
|
130
|
+
}
|
|
131
|
+
static get isROSArray() {
|
|
132
|
+
return false;
|
|
133
|
+
}
|
|
134
|
+
get refObject() {
|
|
135
|
+
return this._refObject;
|
|
136
|
+
}
|
|
137
|
+
get info() {
|
|
138
|
+
return this._wrapperFields.info;
|
|
139
|
+
}
|
|
140
|
+
set info(value) {
|
|
141
|
+
if (value instanceof ServiceEventInfoWrapper) {
|
|
142
|
+
this._wrapperFields.info.copy(value);
|
|
143
|
+
} else {
|
|
144
|
+
this._wrapperFields.info.copy(new ServiceEventInfoWrapper(value));
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
get request() {
|
|
148
|
+
return this._wrapperFields.request;
|
|
149
|
+
}
|
|
150
|
+
set request(value) {
|
|
151
|
+
if (value.length > 1) {
|
|
152
|
+
throw new RangeError('The length of array request must be <= 1.');
|
|
153
|
+
}
|
|
154
|
+
this._wrapperFields.request.fill(value);
|
|
155
|
+
}
|
|
156
|
+
get response() {
|
|
157
|
+
return this._wrapperFields.response;
|
|
158
|
+
}
|
|
159
|
+
set response(value) {
|
|
160
|
+
if (value.length > 1) {
|
|
161
|
+
throw new RangeError('The length of array response must be <= 1.');
|
|
162
|
+
}
|
|
163
|
+
this._wrapperFields.response.fill(value);
|
|
164
|
+
}
|
|
165
|
+
copyRefObject(refObject) {
|
|
166
|
+
this._refObject = new {{=interfaceName}}_EventRefStruct(refObject.toObject());
|
|
167
|
+
this._wrapperFields.info.copyRefObject(this._refObject.info);
|
|
168
|
+
this._wrapperFields.request.copyRefObject(this._refObject.request);
|
|
169
|
+
this._wrapperFields.response.copyRefObject(this._refObject.response);
|
|
170
|
+
}
|
|
171
|
+
copy(other) {
|
|
172
|
+
this._refObject = new {{=interfaceName}}_EventRefStruct(other._refObject.toObject());
|
|
173
|
+
this._wrapperFields.info.copy(other._wrapperFields.info);
|
|
174
|
+
this._wrapperFields.request.copy(other._wrapperFields.request);
|
|
175
|
+
this._wrapperFields.response.copy(other._wrapperFields.response);
|
|
176
|
+
}
|
|
177
|
+
static get classType() {
|
|
178
|
+
return {{=interfaceName}}_EventWrapper;
|
|
179
|
+
}
|
|
180
|
+
static get ROSMessageDef() {
|
|
181
|
+
return {"constants":[],"fields":[{"name":"info","type":{"isArray":false,"arraySize":null,"isUpperBound":false,"isDynamicArray":false,"isFixedSizeArray":false,"pkgName":"service_msgs","type":"ServiceEventInfo","stringUpperBound":null,"isPrimitiveType":false},"default_value":null},{"name":"request","type":{"isArray":true,"arraySize":1,"isUpperBound":true,"isDynamicArray":true,"isFixedSizeArray":false,"pkgName":"{{=pkgName}}","type":"{{=interfaceName}}_Request","stringUpperBound":null,"isPrimitiveType":false},"default_value":null},{"name":"response","type":{"isArray":true,"arraySize":1,"isUpperBound":true,"isDynamicArray":true,"isFixedSizeArray":false,"pkgName":"{{=pkgName}}","type":"{{=interfaceName}}_Response","stringUpperBound":null,"isPrimitiveType":false},"default_value":null}],"baseType":{"pkgName":"{{=pkgName}}","type":"{{=interfaceName}}_Event","stringUpperBound":null,"isPrimitiveType":false},"msgName":"{{=interfaceName}}_Event"};
|
|
182
|
+
}
|
|
183
|
+
hasMember(name) {
|
|
184
|
+
let memberNames = ["info","request","response"];
|
|
185
|
+
return memberNames.indexOf(name) !== -1;
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
// Define the wrapper of array class.
|
|
189
|
+
class {{=interfaceName}}_EventArrayWrapper {
|
|
190
|
+
constructor(size = 0) {
|
|
191
|
+
this._resize(size);
|
|
192
|
+
}
|
|
193
|
+
toRawROS() {
|
|
194
|
+
return this._refObject.ref();
|
|
195
|
+
}
|
|
196
|
+
fill(values) {
|
|
197
|
+
const length = values.length;
|
|
198
|
+
this._resize(length);
|
|
199
|
+
values.forEach((value, index) => {
|
|
200
|
+
if (value instanceof {{=interfaceName}}_EventWrapper) {
|
|
201
|
+
this._wrappers[index].copy(value);
|
|
202
|
+
} else {
|
|
203
|
+
this._wrappers[index] = new {{=interfaceName}}_EventWrapper(value);
|
|
204
|
+
}
|
|
205
|
+
});
|
|
206
|
+
}
|
|
207
|
+
// Put all data currently stored in `this._wrappers` into `this._refObject`
|
|
208
|
+
freeze(own) {
|
|
209
|
+
this._wrappers.forEach((wrapper, index) => {
|
|
210
|
+
wrapper.freeze(own);
|
|
211
|
+
this._refArray[index] = wrapper.refObject;
|
|
212
|
+
});
|
|
213
|
+
this._refObject.size = this._wrappers.length;
|
|
214
|
+
this._refObject.capacity = this._wrappers.length;
|
|
215
|
+
if (this._refObject.capacity === 0) {
|
|
216
|
+
this._refObject.data = null
|
|
217
|
+
} else {
|
|
218
|
+
this._refObject.data = this._refArray.buffer;
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
get refObject() {
|
|
222
|
+
return this._refObject;
|
|
223
|
+
}
|
|
224
|
+
get data() {
|
|
225
|
+
return this._wrappers;
|
|
226
|
+
}
|
|
227
|
+
get size() {
|
|
228
|
+
return this._wrappers.length;
|
|
229
|
+
}
|
|
230
|
+
set size(value) {
|
|
231
|
+
if (typeof value != 'number') {
|
|
232
|
+
throw new TypeError('Invalid argument: should provide a number to {{=interfaceName}}_EventArrayWrapper.size setter');
|
|
233
|
+
return;
|
|
234
|
+
}
|
|
235
|
+
return this._resize(value);
|
|
236
|
+
}
|
|
237
|
+
get capacity() {
|
|
238
|
+
return this._wrappers.length;
|
|
239
|
+
}
|
|
240
|
+
set capacity(value) {
|
|
241
|
+
if (typeof value != 'number') {
|
|
242
|
+
throw new TypeError('Invalid argument: should provide a number to {{=interfaceName}}_EventArrayWrapper.capacity setter');
|
|
243
|
+
}
|
|
244
|
+
return this._resize(value);
|
|
245
|
+
}
|
|
246
|
+
get refObject() {
|
|
247
|
+
return this._refObject;
|
|
248
|
+
}
|
|
249
|
+
_resize(size) {
|
|
250
|
+
if (size < 0) {
|
|
251
|
+
throw new RangeError('Invalid argument: should provide a positive number');
|
|
252
|
+
return;
|
|
253
|
+
}
|
|
254
|
+
this._refArray = new {{=interfaceName}}_EventRefArray(size);
|
|
255
|
+
this._refObject = new {{=interfaceName}}_EventRefStructArray();
|
|
256
|
+
this._refObject.size = size;
|
|
257
|
+
this._refObject.capacity = size;
|
|
258
|
+
this._wrappers = new Array();
|
|
259
|
+
for (let i = 0; i < size; i++) {
|
|
260
|
+
this._wrappers.push(new {{=interfaceName}}_EventWrapper());
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
// Copy all data from `this._refObject` into `this._wrappers`
|
|
264
|
+
copyRefObject(refObject) {
|
|
265
|
+
this._refObject = refObject;
|
|
266
|
+
let refObjectArray = this._refObject.data;
|
|
267
|
+
refObjectArray.length = this._refObject.size;
|
|
268
|
+
this._resize(this._refObject.size);
|
|
269
|
+
for (let index = 0; index < this._refObject.size; index++) {
|
|
270
|
+
this._wrappers[index].copyRefObject(refObjectArray[index]);
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
copy(other) {
|
|
274
|
+
if (! (other instanceof {{=interfaceName}}_EventArrayWrapper)) {
|
|
275
|
+
throw new TypeError('Invalid argument: should provide "{{=interfaceName}}_EventArrayWrapper".');
|
|
276
|
+
}
|
|
277
|
+
this._resize(other.size);
|
|
278
|
+
// Array deep copy
|
|
279
|
+
other._wrappers.forEach((wrapper, index) => {
|
|
280
|
+
this._wrappers[index].copy(wrapper);
|
|
281
|
+
});
|
|
282
|
+
}
|
|
283
|
+
static freeArray(refObject) {
|
|
284
|
+
let refObjectArray = refObject.data;
|
|
285
|
+
refObjectArray.length = refObject.size;
|
|
286
|
+
for (let index = 0; index < refObject.size; index++) {
|
|
287
|
+
{{=interfaceName}}_EventWrapper.freeStruct(refObjectArray[index]);
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
static get elementType() {
|
|
291
|
+
return {{=interfaceName}}_EventWrapper;
|
|
292
|
+
}
|
|
293
|
+
static get isROSArray() {
|
|
294
|
+
return true;
|
|
295
|
+
}
|
|
296
|
+
static get useTypedArray() {
|
|
297
|
+
return false;
|
|
298
|
+
}
|
|
299
|
+
get classType() {
|
|
300
|
+
return {{=interfaceName}}_EventArrayWrapper;
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
module.exports = {{=interfaceName}}_EventWrapper;
|
|
304
|
+
|
package/rostsd_gen/index.js
CHANGED
|
@@ -38,9 +38,9 @@ async function generateAll() {
|
|
|
38
38
|
const generatedPath = path.join(__dirname, '../generated/');
|
|
39
39
|
const pkgInfos = getPkgInfos(generatedPath);
|
|
40
40
|
|
|
41
|
-
// write
|
|
42
|
-
const
|
|
43
|
-
const fd = fs.openSync(
|
|
41
|
+
// write interfaces.d.ts file
|
|
42
|
+
const interfacesFilePath = path.join(__dirname, '../types/interfaces.d.ts');
|
|
43
|
+
const fd = fs.openSync(interfacesFilePath, 'w');
|
|
44
44
|
savePkgInfoAsTSD(pkgInfos, fd);
|
|
45
45
|
await wait(500); // hack to avoid random segfault
|
|
46
46
|
fs.closeSync(fd);
|
|
@@ -235,7 +235,9 @@ function saveMsgAsTSD(rosMsgInterface, fd) {
|
|
|
235
235
|
fd,
|
|
236
236
|
` export interface ${rosMsgInterface.type().interfaceName} {\n`
|
|
237
237
|
);
|
|
238
|
-
const useSamePkg =
|
|
238
|
+
const useSamePkg =
|
|
239
|
+
isInternalActionMsgInterface(rosMsgInterface) ||
|
|
240
|
+
isInternalServiceEventMsgInterface(rosMsgInterface);
|
|
239
241
|
saveMsgFieldsAsTSD(rosMsgInterface, fd, 8, ';', '', useSamePkg);
|
|
240
242
|
fs.writeSync(fd, ' }\n');
|
|
241
243
|
}
|
|
@@ -270,7 +272,6 @@ function saveMsgFieldsAsTSD(
|
|
|
270
272
|
useSamePackageSubFolder && field.type.pkgName === type.pkgName
|
|
271
273
|
? type.subFolder
|
|
272
274
|
: 'msg';
|
|
273
|
-
|
|
274
275
|
let fieldType = fieldType2JSName(field, subFolder);
|
|
275
276
|
let tp = field.type.isPrimitiveType ? '' : typePrefix;
|
|
276
277
|
if (typePrefix === 'rclnodejs.') {
|
|
@@ -346,13 +347,6 @@ function isMsgInterface(rosInterface) {
|
|
|
346
347
|
return rosInterface.hasOwnProperty('ROSMessageDef');
|
|
347
348
|
}
|
|
348
349
|
|
|
349
|
-
function isServiceMsgInterface(rosMsgInterface) {
|
|
350
|
-
if (!isMsgInterface(rosMsgInterface)) return false;
|
|
351
|
-
|
|
352
|
-
let name = rosMsgInterface.type().interfaceName;
|
|
353
|
-
return name.endsWith('_Request') || name.endsWith('_Response');
|
|
354
|
-
}
|
|
355
|
-
|
|
356
350
|
function isInternalActionMsgInterface(rosMsgInterface) {
|
|
357
351
|
let name = rosMsgInterface.type().interfaceName;
|
|
358
352
|
return (
|
|
@@ -364,6 +358,15 @@ function isInternalActionMsgInterface(rosMsgInterface) {
|
|
|
364
358
|
);
|
|
365
359
|
}
|
|
366
360
|
|
|
361
|
+
function isInternalServiceEventMsgInterface(rosMsgInterface) {
|
|
362
|
+
let name = rosMsgInterface.type().interfaceName;
|
|
363
|
+
let subFolder = rosMsgInterface.type().subFolder;
|
|
364
|
+
return (
|
|
365
|
+
(subFolder == 'srv' || subFolder == 'action')
|
|
366
|
+
&& name.endsWith('_Event')
|
|
367
|
+
);
|
|
368
|
+
}
|
|
369
|
+
|
|
367
370
|
function isSrvInterface(rosInterface) {
|
|
368
371
|
return (
|
|
369
372
|
rosInterface.hasOwnProperty('Request') &&
|
package/scripts/npmjs-readme.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# rclnodejs
|
|
1
|
+
# rclnodejs 
|
|
2
2
|
|
|
3
3
|
`rclnodejs` is a Node.js client for the Robot Operating System (ROS 2). It provides a simple and easy JavaScript API for ROS 2 programming. TypeScript declarations are included to support use of rclnodejs in TypeScript projects.
|
|
4
4
|
|
|
@@ -18,7 +18,7 @@ rclnodejs.init().then(() => {
|
|
|
18
18
|
|
|
19
19
|
**Node.js**
|
|
20
20
|
|
|
21
|
-
- [Node.js](https://nodejs.org/en/) version
|
|
21
|
+
- [Node.js](https://nodejs.org/en/) version >= 16.13.0.
|
|
22
22
|
|
|
23
23
|
**ROS 2 SDK**
|
|
24
24
|
|
|
@@ -43,14 +43,13 @@ npm i rclnodejs@x.y.z
|
|
|
43
43
|
|
|
44
44
|
#### RCLNODEJS - ROS 2 Version Compatibility
|
|
45
45
|
|
|
46
|
-
|
|
|
47
|
-
|
|
|
48
|
-
| [
|
|
49
|
-
| [0.10.3](https://github.com/RobotWebTools/rclnodejs/releases/tag/0.10.3) | [Dashing Diademata - Patch 4](https://github.com/ros2/ros2/releases/tag/release-dashing-20191018) |
|
|
46
|
+
| RCLNODEJS Version | Compatible ROS 2 LTS |
|
|
47
|
+
| :------------------------------------------------------------------------------------------: | :-----------------------------------------------------------------------------------------------------------------------------------------------: |
|
|
48
|
+
| latest version (currently [v0.22.3](https://github.com/RobotWebTools/rclnodejs/tree/0.22.3)) | [Humble](https://github.com/RobotWebTools/rclnodejs/tree/humble-hawksbill)<br>[Iron](https://github.com/RobotWebTools/rclnodejs/tree/iron-irwini) |
|
|
50
49
|
|
|
51
50
|
## Documentation
|
|
52
51
|
|
|
53
|
-
API [documentation](
|
|
52
|
+
API [documentation](https://robotwebtools.github.io/rclnodejs/docs/index.html) is available online.
|
|
54
53
|
|
|
55
54
|
## JavaScript Examples
|
|
56
55
|
|
package/src/rcl_bindings.cpp
CHANGED
|
@@ -36,6 +36,10 @@
|
|
|
36
36
|
#include <rosidl_generator_c/string_functions.h>
|
|
37
37
|
#endif
|
|
38
38
|
|
|
39
|
+
#if ROS_VERSION > 2205
|
|
40
|
+
#include <rcl/service_introspection.h>
|
|
41
|
+
#endif
|
|
42
|
+
|
|
39
43
|
#include <iostream>
|
|
40
44
|
#include <memory>
|
|
41
45
|
#include <string>
|
|
@@ -1120,6 +1124,68 @@ NAN_METHOD(SendResponse) {
|
|
|
1120
1124
|
RCL_RET_OK, rcl_get_error_string().str);
|
|
1121
1125
|
}
|
|
1122
1126
|
|
|
1127
|
+
#if ROS_VERSION > 2205 // 2205 == Humble
|
|
1128
|
+
NAN_METHOD(ConfigureServiceIntrospection) {
|
|
1129
|
+
v8::Local<v8::Context> currentContent = Nan::GetCurrentContext();
|
|
1130
|
+
|
|
1131
|
+
RclHandle* node_handle = RclHandle::Unwrap<RclHandle>(
|
|
1132
|
+
Nan::To<v8::Object>(info[1]).ToLocalChecked());
|
|
1133
|
+
rcl_node_t* node = reinterpret_cast<rcl_node_t*>(node_handle->ptr());
|
|
1134
|
+
|
|
1135
|
+
rcl_clock_t* clock = reinterpret_cast<rcl_clock_t*>(
|
|
1136
|
+
RclHandle::Unwrap<RclHandle>(
|
|
1137
|
+
Nan::To<v8::Object>(info[2]).ToLocalChecked())
|
|
1138
|
+
->ptr());
|
|
1139
|
+
|
|
1140
|
+
std::string interface_name(
|
|
1141
|
+
*Nan::Utf8String(info[3]->ToString(currentContent).ToLocalChecked()));
|
|
1142
|
+
std::string package_name(
|
|
1143
|
+
*Nan::Utf8String(info[4]->ToString(currentContent).ToLocalChecked()));
|
|
1144
|
+
const rosidl_service_type_support_t* ts =
|
|
1145
|
+
GetServiceTypeSupport(package_name, interface_name);
|
|
1146
|
+
|
|
1147
|
+
if (ts) {
|
|
1148
|
+
rcl_publisher_options_t publisher_ops = rcl_publisher_get_default_options();
|
|
1149
|
+
auto qos_profile = GetQoSProfile(info[5]);
|
|
1150
|
+
if (qos_profile) {
|
|
1151
|
+
publisher_ops.qos = *qos_profile;
|
|
1152
|
+
}
|
|
1153
|
+
|
|
1154
|
+
rcl_service_introspection_state_t state =
|
|
1155
|
+
static_cast<rcl_service_introspection_state_t>(
|
|
1156
|
+
Nan::To<uint32_t>(info[6]).ToChecked());
|
|
1157
|
+
|
|
1158
|
+
bool configureForService = Nan::To<bool>(info[7]).FromJust();
|
|
1159
|
+
|
|
1160
|
+
if (configureForService) {
|
|
1161
|
+
RclHandle* service_handle = RclHandle::Unwrap<RclHandle>(
|
|
1162
|
+
Nan::To<v8::Object>(info[0]).ToLocalChecked());
|
|
1163
|
+
rcl_service_t* service =
|
|
1164
|
+
reinterpret_cast<rcl_service_t*>(service_handle->ptr());
|
|
1165
|
+
|
|
1166
|
+
THROW_ERROR_IF_NOT_EQUAL(
|
|
1167
|
+
rcl_service_configure_service_introspection(service, node, clock, ts,
|
|
1168
|
+
publisher_ops, state),
|
|
1169
|
+
RCL_RET_OK, rcl_get_error_string().str);
|
|
1170
|
+
|
|
1171
|
+
} else {
|
|
1172
|
+
RclHandle* client_handle = RclHandle::Unwrap<RclHandle>(
|
|
1173
|
+
Nan::To<v8::Object>(info[0]).ToLocalChecked());
|
|
1174
|
+
rcl_client_t* client =
|
|
1175
|
+
reinterpret_cast<rcl_client_t*>(client_handle->ptr());
|
|
1176
|
+
|
|
1177
|
+
THROW_ERROR_IF_NOT_EQUAL(
|
|
1178
|
+
rcl_client_configure_service_introspection(client, node, clock, ts,
|
|
1179
|
+
publisher_ops, state),
|
|
1180
|
+
RCL_RET_OK, rcl_get_error_string().str);
|
|
1181
|
+
}
|
|
1182
|
+
|
|
1183
|
+
} else {
|
|
1184
|
+
Nan::ThrowError(GetErrorMessageAndClear().c_str());
|
|
1185
|
+
}
|
|
1186
|
+
}
|
|
1187
|
+
#endif
|
|
1188
|
+
|
|
1123
1189
|
NAN_METHOD(ValidateFullTopicName) {
|
|
1124
1190
|
v8::Local<v8::Context> currentContent = Nan::GetCurrentContext();
|
|
1125
1191
|
int validation_result;
|
|
@@ -2011,6 +2077,11 @@ std::vector<BindingMethod> binding_methods = {
|
|
|
2011
2077
|
{"serviceServerIsAvailable", ServiceServerIsAvailable},
|
|
2012
2078
|
{"publishRawMessage", PublishRawMessage},
|
|
2013
2079
|
{"rclTakeRaw", RclTakeRaw},
|
|
2014
|
-
{"", nullptr}
|
|
2080
|
+
{"", nullptr}
|
|
2081
|
+
#if ROS_VERSION > 2205 // 2205 == Humble
|
|
2082
|
+
,
|
|
2083
|
+
{"configureServiceIntrospection", ConfigureServiceIntrospection}
|
|
2084
|
+
#endif
|
|
2085
|
+
};
|
|
2015
2086
|
|
|
2016
2087
|
} // namespace rclnodejs
|
package/types/base.d.ts
CHANGED
|
@@ -21,6 +21,7 @@
|
|
|
21
21
|
/// <reference path="qos.d.ts" />
|
|
22
22
|
/// <reference path="rate.d.ts" />
|
|
23
23
|
/// <reference path="service.d.ts" />
|
|
24
|
+
/// <reference path="service_introspection.d.ts" />
|
|
24
25
|
/// <reference path="subscription.d.ts" />
|
|
25
26
|
/// <reference path="time_source.d.ts" />
|
|
26
27
|
/// <reference path="time.d.ts" />
|
package/types/client.d.ts
CHANGED
|
@@ -40,6 +40,18 @@ declare module 'rclnodejs' {
|
|
|
40
40
|
* Name of the service to which requests are made.
|
|
41
41
|
*/
|
|
42
42
|
readonly serviceName: string;
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Configure introspection.
|
|
46
|
+
* @param clock - Clock to use for service event timestamps
|
|
47
|
+
* @param QoSProfile - QOS profile for the service event publisher
|
|
48
|
+
* @param introspectionState - The state to set introspection to
|
|
49
|
+
*/
|
|
50
|
+
configureIntrospection(
|
|
51
|
+
clock: Clock,
|
|
52
|
+
serviceEventPubQOS: QoS,
|
|
53
|
+
introspectionState: ServiceIntrospectionStates
|
|
54
|
+
): void;
|
|
43
55
|
}
|
|
44
56
|
|
|
45
57
|
namespace Client {
|