rclnodejs 1.9.0 → 2.0.0-beta.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/.prettierignore +4 -0
- package/README.md +2 -2
- package/binding.gyp +6 -5
- package/lib/action/client.js +5 -4
- package/lib/action/uuid.js +1 -1
- package/lib/client.js +0 -45
- package/lib/distro.js +11 -4
- package/lib/interface_loader.js +1 -1
- package/lib/message_introspector.js +1 -29
- package/lib/message_serialization.js +2 -2
- package/lib/native_loader.js +21 -9
- package/lib/node.js +2 -2
- package/lib/prebuilds.js +47 -0
- package/lib/rmw.js +6 -1
- package/lib/subscription.js +2 -2
- package/package.json +11 -6
- package/prebuilds/linux-arm64/humble-jammy-arm64-electron-rclnodejs.node +0 -0
- package/prebuilds/linux-arm64/humble-jammy-arm64-node-rclnodejs.node +0 -0
- package/prebuilds/linux-arm64/jazzy-noble-arm64-electron-rclnodejs.node +0 -0
- package/prebuilds/linux-arm64/jazzy-noble-arm64-node-rclnodejs.node +0 -0
- package/prebuilds/linux-arm64/kilted-noble-arm64-electron-rclnodejs.node +0 -0
- package/prebuilds/linux-arm64/kilted-noble-arm64-node-rclnodejs.node +0 -0
- package/prebuilds/linux-arm64/lyrical-resolute-arm64-electron-rclnodejs.node +0 -0
- package/prebuilds/linux-arm64/lyrical-resolute-arm64-node-rclnodejs.node +0 -0
- package/prebuilds/linux-x64/humble-jammy-x64-electron-rclnodejs.node +0 -0
- package/prebuilds/linux-x64/humble-jammy-x64-node-rclnodejs.node +0 -0
- package/prebuilds/linux-x64/jazzy-noble-x64-electron-rclnodejs.node +0 -0
- package/prebuilds/linux-x64/jazzy-noble-x64-node-rclnodejs.node +0 -0
- package/prebuilds/linux-x64/kilted-noble-x64-electron-rclnodejs.node +0 -0
- package/prebuilds/linux-x64/kilted-noble-x64-node-rclnodejs.node +0 -0
- package/prebuilds/linux-x64/lyrical-resolute-x64-electron-rclnodejs.node +0 -0
- package/prebuilds/linux-x64/lyrical-resolute-x64-node-rclnodejs.node +0 -0
- package/rosidl_gen/packages.js +4 -4
- package/rosidl_gen/templates/message-template.js +20 -6
- package/rosocket/README.md +152 -0
- package/rosocket/cli.js +168 -0
- package/rosocket/index.js +245 -0
- package/scripts/install.js +14 -3
- package/scripts/tag_prebuilds.js +26 -9
- package/src/rcl_action_client_bindings.cpp +4 -4
- package/src/rcl_graph_bindings.cpp +8 -8
- package/src/rcl_lifecycle_bindings.cpp +1 -1
- package/src/rcl_subscription_bindings.cpp +2 -2
- package/src/rcl_utilities.cpp +4 -4
- package/src/rcl_utilities.h +2 -2
- package/types/distro.d.ts +15 -1
- package/prebuilds/linux-arm64/humble-jammy-arm64-rclnodejs.node +0 -0
- package/prebuilds/linux-arm64/jazzy-noble-arm64-rclnodejs.node +0 -0
- package/prebuilds/linux-arm64/kilted-noble-arm64-rclnodejs.node +0 -0
- package/prebuilds/linux-x64/humble-jammy-x64-rclnodejs.node +0 -0
- package/prebuilds/linux-x64/jazzy-noble-x64-rclnodejs.node +0 -0
- package/prebuilds/linux-x64/kilted-noble-x64-rclnodejs.node +0 -0
- package/tools/jsdoc/Makefile +0 -5
- package/tools/jsdoc/README.md +0 -96
- package/tools/jsdoc/build-index.js +0 -610
- package/tools/jsdoc/publish.js +0 -854
- package/tools/jsdoc/regenerate-published-docs.js +0 -605
- package/tools/jsdoc/static/fonts/OpenSans-Bold-webfont.eot +0 -0
- package/tools/jsdoc/static/fonts/OpenSans-Bold-webfont.svg +0 -1830
- package/tools/jsdoc/static/fonts/OpenSans-Bold-webfont.woff +0 -0
- package/tools/jsdoc/static/fonts/OpenSans-BoldItalic-webfont.eot +0 -0
- package/tools/jsdoc/static/fonts/OpenSans-BoldItalic-webfont.svg +0 -1830
- package/tools/jsdoc/static/fonts/OpenSans-BoldItalic-webfont.woff +0 -0
- package/tools/jsdoc/static/fonts/OpenSans-Italic-webfont.eot +0 -0
- package/tools/jsdoc/static/fonts/OpenSans-Italic-webfont.svg +0 -1830
- package/tools/jsdoc/static/fonts/OpenSans-Italic-webfont.woff +0 -0
- package/tools/jsdoc/static/fonts/OpenSans-Light-webfont.eot +0 -0
- package/tools/jsdoc/static/fonts/OpenSans-Light-webfont.svg +0 -1831
- package/tools/jsdoc/static/fonts/OpenSans-Light-webfont.woff +0 -0
- package/tools/jsdoc/static/fonts/OpenSans-LightItalic-webfont.eot +0 -0
- package/tools/jsdoc/static/fonts/OpenSans-LightItalic-webfont.svg +0 -1835
- package/tools/jsdoc/static/fonts/OpenSans-LightItalic-webfont.woff +0 -0
- package/tools/jsdoc/static/fonts/OpenSans-Regular-webfont.eot +0 -0
- package/tools/jsdoc/static/fonts/OpenSans-Regular-webfont.svg +0 -1831
- package/tools/jsdoc/static/fonts/OpenSans-Regular-webfont.woff +0 -0
- package/tools/jsdoc/static/scripts/linenumber.js +0 -25
- package/tools/jsdoc/static/scripts/prettify/Apache-License-2.0.txt +0 -202
- package/tools/jsdoc/static/scripts/prettify/lang-css.js +0 -36
- package/tools/jsdoc/static/scripts/prettify/prettify.js +0 -738
- package/tools/jsdoc/static/styles/jsdoc-default.css +0 -1012
- package/tools/jsdoc/static/styles/prettify-jsdoc.css +0 -111
- package/tools/jsdoc/static/styles/prettify-tomorrow.css +0 -132
- package/tools/jsdoc/tmpl/augments.tmpl +0 -10
- package/tools/jsdoc/tmpl/container.tmpl +0 -193
- package/tools/jsdoc/tmpl/details.tmpl +0 -143
- package/tools/jsdoc/tmpl/example.tmpl +0 -2
- package/tools/jsdoc/tmpl/examples.tmpl +0 -13
- package/tools/jsdoc/tmpl/exceptions.tmpl +0 -17
- package/tools/jsdoc/tmpl/layout.tmpl +0 -83
- package/tools/jsdoc/tmpl/mainpage.tmpl +0 -163
- package/tools/jsdoc/tmpl/members.tmpl +0 -43
- package/tools/jsdoc/tmpl/method.tmpl +0 -124
- package/tools/jsdoc/tmpl/params.tmpl +0 -133
- package/tools/jsdoc/tmpl/properties.tmpl +0 -110
- package/tools/jsdoc/tmpl/returns.tmpl +0 -12
- package/tools/jsdoc/tmpl/source.tmpl +0 -8
- package/tools/jsdoc/tmpl/tutorial.tmpl +0 -19
- package/tools/jsdoc/tmpl/type.tmpl +0 -7
package/.prettierignore
ADDED
package/README.md
CHANGED
|
@@ -20,7 +20,7 @@ This example assumes your ROS 2 environment is already sourced.
|
|
|
20
20
|
|
|
21
21
|
### Prerequisites
|
|
22
22
|
|
|
23
|
-
- [Node.js](https://nodejs.org/en/) version >=
|
|
23
|
+
- [Node.js](https://nodejs.org/en/) version >= 20.20.2
|
|
24
24
|
- [ROS 2 SDK](https://docs.ros.org/en/jazzy/Installation.html)
|
|
25
25
|
|
|
26
26
|
Before installing or running rclnodejs, source your ROS 2 environment:
|
|
@@ -52,7 +52,7 @@ rclnodejs ships with prebuilt native binaries for common Linux configurations si
|
|
|
52
52
|
- **Ubuntu 22.04 (Jammy)** - ROS 2 Humble
|
|
53
53
|
- **Ubuntu 24.04 (Noble)** - ROS 2 Jazzy, Kilted
|
|
54
54
|
- **Architectures:** x64, arm64
|
|
55
|
-
- **Node.js:** >=
|
|
55
|
+
- **Node.js:** >= 20.20.2 (N-API compatible)
|
|
56
56
|
|
|
57
57
|
Installations outside this prebuilt matrix automatically fall back to building from source.
|
|
58
58
|
|
package/binding.gyp
CHANGED
|
@@ -12,7 +12,6 @@
|
|
|
12
12
|
'runtime%': 'node',
|
|
13
13
|
'ros_lib_dir': "<!(node -p \"require('./scripts/config.js').getROSLibPath()\")",
|
|
14
14
|
'ros_include_root': "<!(node -p \"require('./scripts/config.js').getROSIncludeRootPath()\")",
|
|
15
|
-
'node_major_version': '<!(node -p \"process.versions.node.split(\'.\')[0]\")',
|
|
16
15
|
},
|
|
17
16
|
'targets': [
|
|
18
17
|
{
|
|
@@ -85,14 +84,15 @@
|
|
|
85
84
|
],
|
|
86
85
|
'conditions': [
|
|
87
86
|
[
|
|
88
|
-
|
|
87
|
+
# Post-Kilted ROS distros require C++20.
|
|
88
|
+
'ros_version > 2505', {
|
|
89
89
|
'cflags_cc': [
|
|
90
90
|
'-std=c++20'
|
|
91
91
|
]
|
|
92
92
|
}
|
|
93
93
|
],
|
|
94
94
|
[
|
|
95
|
-
'
|
|
95
|
+
'ros_version <= 2505', {
|
|
96
96
|
'cflags_cc': [
|
|
97
97
|
'-std=c++17'
|
|
98
98
|
]
|
|
@@ -108,14 +108,15 @@
|
|
|
108
108
|
],
|
|
109
109
|
'conditions': [
|
|
110
110
|
[
|
|
111
|
-
|
|
111
|
+
# Post-Kilted ROS distros require C++20.
|
|
112
|
+
'ros_version > 2505', {
|
|
112
113
|
'cflags_cc': [
|
|
113
114
|
'-std=c++20'
|
|
114
115
|
]
|
|
115
116
|
}
|
|
116
117
|
],
|
|
117
118
|
[
|
|
118
|
-
'
|
|
119
|
+
'ros_version <= 2505', {
|
|
119
120
|
'cflags_cc': [
|
|
120
121
|
'-std=c++17'
|
|
121
122
|
]
|
package/lib/action/client.js
CHANGED
|
@@ -94,12 +94,13 @@ class ActionClient extends Entity {
|
|
|
94
94
|
};
|
|
95
95
|
|
|
96
96
|
// Enable feedback subscription content filter optimization.
|
|
97
|
-
// Only supported on ROS2
|
|
98
|
-
// binding provides the required functions AND the RMW
|
|
99
|
-
// actually supports content filtering on the feedback
|
|
97
|
+
// Only supported on ROS2 Lyrical or newer and only effective when the
|
|
98
|
+
// native binding provides the required functions AND the RMW
|
|
99
|
+
// implementation actually supports content filtering on the feedback
|
|
100
|
+
// subscription.
|
|
100
101
|
this._enableFeedbackMsgOptimization =
|
|
101
102
|
this._options.enableFeedbackMsgOptimization === true &&
|
|
102
|
-
DistroUtils.getDistroId() >= DistroUtils.DistroId.
|
|
103
|
+
DistroUtils.getDistroId() >= DistroUtils.DistroId.LYRICAL &&
|
|
103
104
|
typeof rclnodejs.actionConfigureFeedbackSubFilterAddGoalId === 'function';
|
|
104
105
|
|
|
105
106
|
let type = this.typeClass.type();
|
package/lib/action/uuid.js
CHANGED
package/lib/client.js
CHANGED
|
@@ -25,51 +25,6 @@ const {
|
|
|
25
25
|
const { assertValidMessage } = require('./message_validation.js');
|
|
26
26
|
const debug = require('debug')('rclnodejs:client');
|
|
27
27
|
|
|
28
|
-
// Polyfill for AbortSignal.any() for Node.js <= 20.3.0
|
|
29
|
-
// AbortSignal.any() was added in Node.js 20.3.0
|
|
30
|
-
// See https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal/any_static
|
|
31
|
-
if (!AbortSignal.any) {
|
|
32
|
-
AbortSignal.any = function (signals) {
|
|
33
|
-
// Filter out null/undefined values and validate inputs
|
|
34
|
-
const validSignals = Array.isArray(signals)
|
|
35
|
-
? signals.filter((signal) => signal != null)
|
|
36
|
-
: [];
|
|
37
|
-
|
|
38
|
-
// If no valid signals, return a never-aborting signal
|
|
39
|
-
if (validSignals.length === 0) {
|
|
40
|
-
return new AbortController().signal;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
const controller = new AbortController();
|
|
44
|
-
const listeners = [];
|
|
45
|
-
|
|
46
|
-
// Cleanup function to remove all event listeners
|
|
47
|
-
const cleanup = () => {
|
|
48
|
-
listeners.forEach(({ signal, listener }) => {
|
|
49
|
-
signal.removeEventListener('abort', listener);
|
|
50
|
-
});
|
|
51
|
-
};
|
|
52
|
-
|
|
53
|
-
for (const signal of validSignals) {
|
|
54
|
-
if (signal.aborted) {
|
|
55
|
-
cleanup();
|
|
56
|
-
controller.abort(signal.reason);
|
|
57
|
-
return controller.signal;
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
const listener = () => {
|
|
61
|
-
cleanup();
|
|
62
|
-
controller.abort(signal.reason);
|
|
63
|
-
};
|
|
64
|
-
|
|
65
|
-
signal.addEventListener('abort', listener);
|
|
66
|
-
listeners.push({ signal, listener });
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
return controller.signal;
|
|
70
|
-
};
|
|
71
|
-
}
|
|
72
|
-
|
|
73
28
|
/**
|
|
74
29
|
* @class - Class representing a Client in ROS
|
|
75
30
|
* @hideconstructor
|
package/lib/distro.js
CHANGED
|
@@ -26,7 +26,9 @@ const DistroId = {
|
|
|
26
26
|
IRON: 2305,
|
|
27
27
|
JAZZY: 2405,
|
|
28
28
|
KILTED: 2505,
|
|
29
|
+
LYRICAL: 2605,
|
|
29
30
|
ROLLING: 5000,
|
|
31
|
+
FUTURE: 9999, // unrecognized ROS_DISTRO assumed newer than Rolling
|
|
30
32
|
};
|
|
31
33
|
|
|
32
34
|
const DistroNameIdMap = new Map();
|
|
@@ -37,6 +39,7 @@ DistroNameIdMap.set('humble', DistroId.HUMBLE);
|
|
|
37
39
|
DistroNameIdMap.set('iron', DistroId.IRON);
|
|
38
40
|
DistroNameIdMap.set('jazzy', DistroId.JAZZY);
|
|
39
41
|
DistroNameIdMap.set('kilted', DistroId.KILTED);
|
|
42
|
+
DistroNameIdMap.set('lyrical', DistroId.LYRICAL);
|
|
40
43
|
DistroNameIdMap.set('rolling', DistroId.ROLLING);
|
|
41
44
|
|
|
42
45
|
const DistroUtils = {
|
|
@@ -48,11 +51,15 @@ const DistroUtils = {
|
|
|
48
51
|
* @return {number} Return the rclnodejs distro identifier
|
|
49
52
|
*/
|
|
50
53
|
getDistroId: function (distroName) {
|
|
51
|
-
const dname =
|
|
54
|
+
const dname =
|
|
55
|
+
(distroName || this.getDistroName() || '').toLowerCase() || undefined;
|
|
52
56
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
57
|
+
if (dname && DistroNameIdMap.has(dname)) {
|
|
58
|
+
return DistroNameIdMap.get(dname);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// Unrecognized but provided/resolved distro name → assume future; unset → unknown
|
|
62
|
+
return dname ? DistroId.FUTURE : DistroId.UNKNOWN;
|
|
56
63
|
},
|
|
57
64
|
|
|
58
65
|
/**
|
package/lib/interface_loader.js
CHANGED
|
@@ -57,7 +57,7 @@ let interfaceLoader = {
|
|
|
57
57
|
}
|
|
58
58
|
|
|
59
59
|
// TODO(Kenny): more checks of the string argument
|
|
60
|
-
if (name.
|
|
60
|
+
if (name.includes('/')) {
|
|
61
61
|
let [packageName, type, messageName] = name.split('/');
|
|
62
62
|
return this.loadInterface(packageName, type, messageName);
|
|
63
63
|
}
|
|
@@ -88,35 +88,7 @@ class MessageIntrospector {
|
|
|
88
88
|
const instance = new this.#typeClass();
|
|
89
89
|
this.#defaultsCache = toPlainObject(instance);
|
|
90
90
|
}
|
|
91
|
-
return
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
/**
|
|
95
|
-
* Deep clone an object.
|
|
96
|
-
* @param {any} obj - Object to clone
|
|
97
|
-
* @returns {any} Cloned object
|
|
98
|
-
* @private
|
|
99
|
-
*/
|
|
100
|
-
#deepClone(obj) {
|
|
101
|
-
if (obj === null || typeof obj !== 'object') {
|
|
102
|
-
return obj;
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
if (Array.isArray(obj)) {
|
|
106
|
-
return obj.map((item) => this.#deepClone(item));
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
if (ArrayBuffer.isView(obj) && !(obj instanceof DataView)) {
|
|
110
|
-
return obj.slice();
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
const cloned = {};
|
|
114
|
-
for (const key in obj) {
|
|
115
|
-
if (Object.prototype.hasOwnProperty.call(obj, key)) {
|
|
116
|
-
cloned[key] = this.#deepClone(obj[key]);
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
return cloned;
|
|
91
|
+
return structuredClone(this.#defaultsCache);
|
|
120
92
|
}
|
|
121
93
|
}
|
|
122
94
|
|
|
@@ -62,7 +62,7 @@ function toPlainArrays(obj) {
|
|
|
62
62
|
if (typeof obj === 'object' && obj !== null) {
|
|
63
63
|
const result = {};
|
|
64
64
|
for (const key in obj) {
|
|
65
|
-
if (Object.
|
|
65
|
+
if (Object.hasOwn(obj, key)) {
|
|
66
66
|
result[key] = toPlainArrays(obj[key]);
|
|
67
67
|
}
|
|
68
68
|
}
|
|
@@ -105,7 +105,7 @@ function toJSONSafe(obj) {
|
|
|
105
105
|
if (typeof obj === 'object' && obj !== null) {
|
|
106
106
|
const result = {};
|
|
107
107
|
for (const key in obj) {
|
|
108
|
-
if (Object.
|
|
108
|
+
if (Object.hasOwn(obj, key)) {
|
|
109
109
|
result[key] = toJSONSafe(obj[key]);
|
|
110
110
|
}
|
|
111
111
|
}
|
package/lib/native_loader.js
CHANGED
|
@@ -20,6 +20,10 @@ const { execSync } = require('child_process');
|
|
|
20
20
|
const { NativeError } = require('./errors.js');
|
|
21
21
|
const bindings = require('bindings');
|
|
22
22
|
const debug = require('debug')('rclnodejs');
|
|
23
|
+
const {
|
|
24
|
+
detectPrebuildRuntime,
|
|
25
|
+
getTaggedPrebuildFilename,
|
|
26
|
+
} = require('./prebuilds');
|
|
23
27
|
const { detectUbuntuCodename } = require('./utils');
|
|
24
28
|
|
|
25
29
|
let nativeModule = null;
|
|
@@ -35,6 +39,7 @@ function customFallbackLoader() {
|
|
|
35
39
|
|
|
36
40
|
const rosDistro = process.env.ROS_DISTRO;
|
|
37
41
|
const arch = process.arch;
|
|
42
|
+
const runtime = detectPrebuildRuntime();
|
|
38
43
|
const ubuntuCodename = detectUbuntuCodename();
|
|
39
44
|
|
|
40
45
|
// Require all three components for exact match
|
|
@@ -58,16 +63,22 @@ function customFallbackLoader() {
|
|
|
58
63
|
}
|
|
59
64
|
|
|
60
65
|
try {
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
66
|
+
const candidate = getTaggedPrebuildFilename({
|
|
67
|
+
rosDistro,
|
|
68
|
+
ubuntuCodename,
|
|
69
|
+
arch,
|
|
70
|
+
runtime,
|
|
71
|
+
});
|
|
72
|
+
const candidatePath = path.join(prebuildDir, candidate);
|
|
73
|
+
|
|
74
|
+
if (fs.existsSync(candidatePath)) {
|
|
75
|
+
debug(`Found ${runtime} prebuilt binary: ${candidate}`);
|
|
76
|
+
return require(candidatePath);
|
|
68
77
|
}
|
|
69
78
|
|
|
70
|
-
debug(
|
|
79
|
+
debug(
|
|
80
|
+
`No matching ${runtime} prebuilt binary found for ${rosDistro}-${ubuntuCodename}-${arch}`
|
|
81
|
+
);
|
|
71
82
|
return null;
|
|
72
83
|
} catch (e) {
|
|
73
84
|
debug('Error in simplified prebuilt loader:', e.message);
|
|
@@ -110,10 +121,11 @@ function loadNativeAddon() {
|
|
|
110
121
|
}
|
|
111
122
|
|
|
112
123
|
const rosDistro = process.env.ROS_DISTRO;
|
|
124
|
+
const runtime = detectPrebuildRuntime();
|
|
113
125
|
const ubuntuCodename = detectUbuntuCodename();
|
|
114
126
|
|
|
115
127
|
debug(
|
|
116
|
-
`Platform: ${process.platform}, Arch: ${process.arch}, Ubuntu: ${ubuntuCodename || 'unknown'}, ROS: ${rosDistro || 'unknown'}`
|
|
128
|
+
`Platform: ${process.platform}, Arch: ${process.arch}, Runtime: ${runtime}, Ubuntu: ${ubuntuCodename || 'unknown'}, ROS: ${rosDistro || 'unknown'}`
|
|
117
129
|
);
|
|
118
130
|
|
|
119
131
|
// Prebuilt binaries are only supported on Linux (Ubuntu)
|
package/lib/node.js
CHANGED
|
@@ -1587,7 +1587,7 @@ class Node extends rclnodejs.ShadowNode {
|
|
|
1587
1587
|
* @returns {Array} - list of clients
|
|
1588
1588
|
*/
|
|
1589
1589
|
getClientsInfoByService(service, noDemangle = false) {
|
|
1590
|
-
if (DistroUtils.getDistroId() < DistroUtils.DistroId.
|
|
1590
|
+
if (DistroUtils.getDistroId() < DistroUtils.DistroId.LYRICAL) {
|
|
1591
1591
|
console.warn(
|
|
1592
1592
|
'getClientsInfoByService is not supported by this version of ROS 2'
|
|
1593
1593
|
);
|
|
@@ -1621,7 +1621,7 @@ class Node extends rclnodejs.ShadowNode {
|
|
|
1621
1621
|
* @returns {Array} - list of servers
|
|
1622
1622
|
*/
|
|
1623
1623
|
getServersInfoByService(service, noDemangle = false) {
|
|
1624
|
-
if (DistroUtils.getDistroId() < DistroUtils.DistroId.
|
|
1624
|
+
if (DistroUtils.getDistroId() < DistroUtils.DistroId.LYRICAL) {
|
|
1625
1625
|
console.warn(
|
|
1626
1626
|
'getServersInfoByService is not supported by this version of ROS 2'
|
|
1627
1627
|
);
|
package/lib/prebuilds.js
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
// Copyright (c) 2026, The Robot Web Tools Contributors
|
|
2
|
+
//
|
|
3
|
+
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
// you may not use this file except in compliance with the License.
|
|
5
|
+
// You may obtain a copy of the License at
|
|
6
|
+
//
|
|
7
|
+
// http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
//
|
|
9
|
+
// Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
// See the License for the specific language governing permissions and
|
|
13
|
+
// limitations under the License.
|
|
14
|
+
|
|
15
|
+
'use strict';
|
|
16
|
+
|
|
17
|
+
const PREBUILD_PACKAGE_NAME = 'rclnodejs';
|
|
18
|
+
const SUPPORTED_PREBUILD_RUNTIMES = new Set(['node', 'electron']);
|
|
19
|
+
|
|
20
|
+
function detectPrebuildRuntime() {
|
|
21
|
+
if (process.env.npm_config_runtime === 'electron') {
|
|
22
|
+
return 'electron';
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
return process.versions.electron ? 'electron' : 'node';
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function getTaggedPrebuildFilename({
|
|
29
|
+
rosDistro,
|
|
30
|
+
ubuntuCodename,
|
|
31
|
+
arch,
|
|
32
|
+
runtime,
|
|
33
|
+
}) {
|
|
34
|
+
return `${rosDistro}-${ubuntuCodename}-${arch}-${runtime}-${PREBUILD_PACKAGE_NAME}.node`;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function getRuntimeFromGeneratedPrebuild(fileName) {
|
|
38
|
+
const runtime = fileName.split('.')[0];
|
|
39
|
+
return SUPPORTED_PREBUILD_RUNTIMES.has(runtime) ? runtime : null;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
module.exports = {
|
|
43
|
+
detectPrebuildRuntime,
|
|
44
|
+
getRuntimeFromGeneratedPrebuild,
|
|
45
|
+
getTaggedPrebuildFilename,
|
|
46
|
+
PREBUILD_PACKAGE_NAME,
|
|
47
|
+
};
|
package/lib/rmw.js
CHANGED
|
@@ -19,6 +19,7 @@ const RMWNames = {
|
|
|
19
19
|
CONNEXT: 'rmw_connext_cpp',
|
|
20
20
|
CYCLONEDDS: 'rmw_cyclonedds_cpp',
|
|
21
21
|
GURUMDDS: 'rmw_gurumdds_cpp',
|
|
22
|
+
ZENOH: 'rmw_zenoh_cpp',
|
|
22
23
|
};
|
|
23
24
|
|
|
24
25
|
const DefaultRosRMWNameMap = new Map();
|
|
@@ -26,6 +27,9 @@ DefaultRosRMWNameMap.set('eloquent', RMWNames.FASTRTPS);
|
|
|
26
27
|
DefaultRosRMWNameMap.set('foxy', RMWNames.FASTRTPS);
|
|
27
28
|
DefaultRosRMWNameMap.set('galactic', RMWNames.CYCLONEDDS);
|
|
28
29
|
DefaultRosRMWNameMap.set('humble', RMWNames.FASTRTPS);
|
|
30
|
+
DefaultRosRMWNameMap.set('iron', RMWNames.FASTRTPS);
|
|
31
|
+
DefaultRosRMWNameMap.set('jazzy', RMWNames.FASTRTPS);
|
|
32
|
+
DefaultRosRMWNameMap.set('kilted', RMWNames.FASTRTPS);
|
|
29
33
|
DefaultRosRMWNameMap.set('rolling', RMWNames.FASTRTPS);
|
|
30
34
|
|
|
31
35
|
const RMWUtils = {
|
|
@@ -34,7 +38,8 @@ const RMWUtils = {
|
|
|
34
38
|
getRMWName: function () {
|
|
35
39
|
return process.env.RMW_IMPLEMENTATION
|
|
36
40
|
? process.env.RMW_IMPLEMENTATION
|
|
37
|
-
: DefaultRosRMWNameMap.get(DistroUtils.getDistroName())
|
|
41
|
+
: DefaultRosRMWNameMap.get(DistroUtils.getDistroName()) ||
|
|
42
|
+
RMWNames.FASTRTPS;
|
|
38
43
|
},
|
|
39
44
|
};
|
|
40
45
|
|
package/lib/subscription.js
CHANGED
|
@@ -147,11 +147,11 @@ class Subscription extends Entity {
|
|
|
147
147
|
|
|
148
148
|
/**
|
|
149
149
|
* Check if content filtering is supported for this subscription.
|
|
150
|
-
* Requires ROS 2
|
|
150
|
+
* Requires ROS 2 Lyrical or later.
|
|
151
151
|
* @returns {boolean} True if the subscription instance supports content filtering; otherwise false.
|
|
152
152
|
*/
|
|
153
153
|
isContentFilterSupported() {
|
|
154
|
-
if (DistroUtils.getDistroId() < DistroUtils.DistroId.
|
|
154
|
+
if (DistroUtils.getDistroId() < DistroUtils.DistroId.LYRICAL) {
|
|
155
155
|
return false;
|
|
156
156
|
}
|
|
157
157
|
return rclnodejs.isContentFilterSupported(this.handle);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "rclnodejs",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.0-beta.0",
|
|
4
4
|
"description": "ROS2.0 JavaScript client with Node.js",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"types": "types/index.d.ts",
|
|
@@ -34,10 +34,14 @@
|
|
|
34
34
|
"format": "clang-format -i -style=file ./src/*.cpp ./src/*.h && npx --yes prettier --write \"{lib,rosidl_gen,rostsd_gen,rosidl_parser,types,example,test,scripts,benchmark,rostsd_gen}/**/*.{js,md,ts}\" ./*.{js,md,ts}",
|
|
35
35
|
"prepare": "husky",
|
|
36
36
|
"coverage": "cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js",
|
|
37
|
-
"prebuild": "prebuildify --napi --strip --
|
|
37
|
+
"prebuild:node": "prebuildify --napi --strip --name node --target 20.20.2",
|
|
38
|
+
"prebuild:electron": "prebuildify --napi --strip --name electron --target electron@34.0.0",
|
|
39
|
+
"prebuild": "npm run prebuild:node && npm run prebuild:electron && node scripts/tag_prebuilds.js",
|
|
40
|
+
"rosocket": "node ./rosocket/cli.js"
|
|
38
41
|
},
|
|
39
42
|
"bin": {
|
|
40
|
-
"generate-ros-messages": "./scripts/generate_messages.js"
|
|
43
|
+
"generate-ros-messages": "./scripts/generate_messages.js",
|
|
44
|
+
"rosocket": "./rosocket/cli.js"
|
|
41
45
|
},
|
|
42
46
|
"authors": [
|
|
43
47
|
"Minggang Wang <minggangw@gmail.com>",
|
|
@@ -67,7 +71,7 @@
|
|
|
67
71
|
"jsdoc": "^4.0.4",
|
|
68
72
|
"lint-staged": "^16.2.0",
|
|
69
73
|
"mocha": "^11.0.2",
|
|
70
|
-
"node-gyp": "^
|
|
74
|
+
"node-gyp": "^12.2.0",
|
|
71
75
|
"nyc": "^18.0.0",
|
|
72
76
|
"prebuildify": "^6.0.1",
|
|
73
77
|
"rimraf": "^6.0.1",
|
|
@@ -84,7 +88,8 @@
|
|
|
84
88
|
"json-bigint": "^1.0.0",
|
|
85
89
|
"node-addon-api": "^8.3.1",
|
|
86
90
|
"rxjs": "^7.8.1",
|
|
87
|
-
"walk": "^2.3.15"
|
|
91
|
+
"walk": "^2.3.15",
|
|
92
|
+
"ws": "^8.18.0"
|
|
88
93
|
},
|
|
89
94
|
"husky": {
|
|
90
95
|
"hooks": {
|
|
@@ -103,6 +108,6 @@
|
|
|
103
108
|
"directory": "test/types"
|
|
104
109
|
},
|
|
105
110
|
"engines": {
|
|
106
|
-
"node": ">=
|
|
111
|
+
"node": ">= 20.20.2"
|
|
107
112
|
}
|
|
108
113
|
}
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/rosidl_gen/packages.js
CHANGED
|
@@ -29,7 +29,7 @@ const serviceMsgPath = path.join(generatedRoot, 'srv_msg');
|
|
|
29
29
|
|
|
30
30
|
function getPackageName(filePath, amentExecuted) {
|
|
31
31
|
if (os.type() === 'Windows_NT') {
|
|
32
|
-
filePath = filePath.
|
|
32
|
+
filePath = filePath.replaceAll('\\', '/');
|
|
33
33
|
}
|
|
34
34
|
|
|
35
35
|
if (amentExecuted) {
|
|
@@ -41,14 +41,14 @@ function getPackageName(filePath, amentExecuted) {
|
|
|
41
41
|
|
|
42
42
|
// If |packageName| equals to the file's extension, e.g. msg/srv, one level
|
|
43
43
|
// up directory will be used as the package name.
|
|
44
|
-
return packageName === path.parse(filePath).ext.
|
|
44
|
+
return packageName === path.parse(filePath).ext.substring(1)
|
|
45
45
|
? folders.pop()
|
|
46
46
|
: packageName;
|
|
47
47
|
}
|
|
48
48
|
|
|
49
49
|
function getSubFolder(filePath, amentExecuted) {
|
|
50
50
|
if (os.type() === 'Windows_NT') {
|
|
51
|
-
filePath = filePath.
|
|
51
|
+
filePath = filePath.replaceAll('\\', '/');
|
|
52
52
|
}
|
|
53
53
|
|
|
54
54
|
if (amentExecuted) {
|
|
@@ -61,7 +61,7 @@ function getSubFolder(filePath, amentExecuted) {
|
|
|
61
61
|
}
|
|
62
62
|
// If the |amentExecuted| equals to false, the file's extension will be assigned as
|
|
63
63
|
// the name of sub folder.
|
|
64
|
-
return path.parse(filePath).ext.
|
|
64
|
+
return path.parse(filePath).ext.substring(1);
|
|
65
65
|
}
|
|
66
66
|
|
|
67
67
|
function grabInterfaceInfo(filePath, amentExecuted) {
|
|
@@ -156,15 +156,15 @@ const typedArrayType = [
|
|
|
156
156
|
];
|
|
157
157
|
|
|
158
158
|
function isPrimitivePackage(baseType) {
|
|
159
|
-
return primitiveBaseType.
|
|
159
|
+
return primitiveBaseType.includes(baseType.type);
|
|
160
160
|
}
|
|
161
161
|
|
|
162
162
|
function isTypedArrayType(type) {
|
|
163
|
-
return typedArrayType.
|
|
163
|
+
return typedArrayType.includes(type.type.toLowerCase());
|
|
164
164
|
}
|
|
165
165
|
|
|
166
166
|
function isBigInt(type) {
|
|
167
|
-
return ['int64', 'uint64'].
|
|
167
|
+
return ['int64', 'uint64'].includes(type.type.toLowerCase());
|
|
168
168
|
}
|
|
169
169
|
|
|
170
170
|
function getWrapperNameByType(type) {
|
|
@@ -265,6 +265,14 @@ function generateMessage(data) {
|
|
|
265
265
|
const currentTypedArray = getTypedArrayName(spec.baseType);
|
|
266
266
|
const currentTypedArrayElementType = getTypedArrayElementName(spec.baseType);
|
|
267
267
|
|
|
268
|
+
// ROS 2 Rolling (ros2/rosidl#941) added is_rosidl_buffer / owns_rosidl_buffer
|
|
269
|
+
// to every primitive sequence struct. Lyrical inherits the same ABI change.
|
|
270
|
+
// Emit the extra fields only for primitive-package types on Lyrical+.
|
|
271
|
+
const DistroUtils = require('../../lib/distro.js');
|
|
272
|
+
const needsRosidlBufferFields =
|
|
273
|
+
isPrimitivePackage(spec.baseType) &&
|
|
274
|
+
DistroUtils.getDistroId() >= DistroUtils.DistroId.LYRICAL;
|
|
275
|
+
|
|
268
276
|
// Track required modules
|
|
269
277
|
let existedModules = [];
|
|
270
278
|
function shouldRequire(baseType, fieldType) {
|
|
@@ -275,7 +283,7 @@ function generateMessage(data) {
|
|
|
275
283
|
!fieldType.isPrimitiveType ||
|
|
276
284
|
fieldType.type === 'string');
|
|
277
285
|
|
|
278
|
-
if (shouldReq && existedModules.
|
|
286
|
+
if (shouldReq && !existedModules.includes(requiredModule)) {
|
|
279
287
|
existedModules.push(requiredModule);
|
|
280
288
|
return true;
|
|
281
289
|
} else {
|
|
@@ -347,7 +355,13 @@ ${
|
|
|
347
355
|
: ` data: ${refArrayType},`
|
|
348
356
|
}
|
|
349
357
|
size: ref.types.size_t,
|
|
350
|
-
capacity: ref.types.size_t
|
|
358
|
+
capacity: ref.types.size_t,
|
|
359
|
+
${
|
|
360
|
+
needsRosidlBufferFields
|
|
361
|
+
? ` is_rosidl_buffer: ref.types.bool,
|
|
362
|
+
owns_rosidl_buffer: ref.types.bool,`
|
|
363
|
+
: ''
|
|
364
|
+
}
|
|
351
365
|
});
|
|
352
366
|
|
|
353
367
|
${generateWrapperClass()}
|
|
@@ -678,7 +692,7 @@ ${spec.fields
|
|
|
678
692
|
|
|
679
693
|
hasMember(name) {
|
|
680
694
|
let memberNames = ${extractMemberNames(spec.fields)};
|
|
681
|
-
return memberNames.
|
|
695
|
+
return memberNames.includes(name);
|
|
682
696
|
}
|
|
683
697
|
}`;
|
|
684
698
|
}
|