rclnodejs 1.3.0 → 1.4.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.
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "rosidl-generator",
3
- "version": "0.5.1",
4
- "description": "Generate JavaScript object from ROS IDL(.msg) files",
3
+ "version": "1.0.0",
4
+ "description": "Generate JavaScript object from ROS IDL(.msg/.srv/.action/.idl) files",
5
5
  "main": "index.js",
6
6
  "authors": [
7
7
  "Minggang Wang <minggang.wang@intel.com>",
@@ -18,18 +18,35 @@ const fse = require('fs-extra');
18
18
  const generateJSStructFromIDL = require('./idl_generator.js');
19
19
  const packages = require('./packages.js');
20
20
  const path = require('path');
21
-
21
+ const idlConvertor = require('../rosidl_convertor/idl_convertor.js');
22
22
  const generatedRoot = path.join(__dirname, '../generated/');
23
23
  const serviceMsgPath = path.join(generatedRoot, 'srv_msg');
24
+ const idlPath = path.join(generatedRoot, 'share');
25
+ const useIDL = !!process.argv.find((arg) => arg === '--idl');
24
26
 
25
27
  function getInstalledPackagePaths() {
26
28
  return process.env.AMENT_PREFIX_PATH.split(path.delimiter);
27
29
  }
28
30
 
29
31
  async function generateInPath(path) {
30
- const pkgs = await packages.findPackagesInDirectory(path);
31
-
32
- const pkgsInfo = Array.from(pkgs.values());
32
+ let pkgsInfo = null;
33
+ if (!useIDL) {
34
+ pkgsInfo = Array.from(
35
+ (await packages.findPackagesInDirectory(path)).values()
36
+ );
37
+ } else {
38
+ const idlPkgs = await packages.findPackagesInDirectory(path, useIDL);
39
+ await fse.ensureDir(idlPath);
40
+ const promises = [];
41
+ idlPkgs.forEach((pkg) => {
42
+ pkg.idls.forEach((idl) => {
43
+ promises.push(idlConvertor(idl.pkgName, idl.filePath, idlPath));
44
+ });
45
+ });
46
+ await Promise.all(promises);
47
+ const pkgsFromIdl = await packages.findPackagesInDirectory(idlPath, false);
48
+ pkgsInfo = Array.from(pkgsFromIdl.values());
49
+ }
33
50
 
34
51
  await Promise.all(
35
52
  pkgsInfo.map((pkgInfo) => generateJSStructFromIDL(pkgInfo, generatedRoot))
@@ -70,7 +70,13 @@ function grabInterfaceInfo(filePath, amentExecuted) {
70
70
  function addInterfaceInfo(info, type, pkgMap) {
71
71
  let pkgName = info.pkgName;
72
72
  if (!pkgMap.has(pkgName)) {
73
- pkgMap.set(pkgName, { messages: [], services: [], actions: [], pkgName });
73
+ pkgMap.set(pkgName, {
74
+ messages: [],
75
+ services: [],
76
+ actions: [],
77
+ idls: [],
78
+ pkgName,
79
+ });
74
80
  }
75
81
  let pkg = pkgMap.get(pkgName);
76
82
  pkg[type].push(info);
@@ -157,26 +163,32 @@ async function generateMsgForSrv(filePath, interfaceInfo, pkgMap) {
157
163
  }
158
164
  }
159
165
 
160
- async function addInterfaceInfos(filePath, dir, pkgMap) {
161
- const interfaceInfo = grabInterfaceInfo(filePath, true);
166
+ async function addInterfaceInfos(filePath, dir, pkgMap, useIDL) {
167
+ const interfaceInfo = grabInterfaceInfo(filePath, /*amentExecuted=*/ true);
162
168
  const ignore = pkgFilters.matchesAny(interfaceInfo);
163
169
  if (!ignore) {
164
- if (path.extname(filePath) === '.msg') {
165
- // Some .msg files were generated prior to 0.3.2 for .action files,
166
- // which has been disabled. So these files should be ignored here.
167
- if (path.dirname(dir).split(path.sep).pop() !== 'action') {
168
- addInterfaceInfo(interfaceInfo, 'messages', pkgMap);
169
- }
170
- } else if (path.extname(filePath) === '.srv') {
171
- const requestMsgName = `${path.parse(filePath).name}_Request.msg`;
172
- if (!fs.existsSync(path.join(path.dirname(filePath), requestMsgName))) {
173
- await generateMsgForSrv(filePath, interfaceInfo, pkgMap);
170
+ if (useIDL) {
171
+ if (path.extname(filePath) === '.idl') {
172
+ addInterfaceInfo(interfaceInfo, 'idls', pkgMap);
174
173
  }
175
- addInterfaceInfo(interfaceInfo, 'services', pkgMap);
176
- } else if (path.extname(filePath) === '.action') {
177
- addInterfaceInfo(interfaceInfo, 'actions', pkgMap);
178
174
  } else {
179
- // we ignore all other files
175
+ if (path.extname(filePath) === '.msg') {
176
+ // Some .msg files were generated prior to 0.3.2 for .action files,
177
+ // which has been disabled. So these files should be ignored here.
178
+ if (path.dirname(dir).split(path.sep).pop() !== 'action') {
179
+ addInterfaceInfo(interfaceInfo, 'messages', pkgMap);
180
+ }
181
+ } else if (path.extname(filePath) === '.srv') {
182
+ const requestMsgName = `${path.parse(filePath).name}_Request.msg`;
183
+ if (!fs.existsSync(path.join(path.dirname(filePath), requestMsgName))) {
184
+ await generateMsgForSrv(filePath, interfaceInfo, pkgMap);
185
+ }
186
+ addInterfaceInfo(interfaceInfo, 'services', pkgMap);
187
+ } else if (path.extname(filePath) === '.action') {
188
+ addInterfaceInfo(interfaceInfo, 'actions', pkgMap);
189
+ } else {
190
+ // we ignore all other files.
191
+ }
180
192
  }
181
193
  }
182
194
  }
@@ -186,7 +198,7 @@ async function addInterfaceInfos(filePath, dir, pkgMap) {
186
198
  * @param {string} dir - the directory to search in
187
199
  * @return {Promise<Map<string, object>>} A mapping from the package name to some info about it.
188
200
  */
189
- async function findAmentPackagesInDirectory(dir) {
201
+ async function findAmentPackagesInDirectory(dir, useIDL) {
190
202
  const pkgs = await getAmentPackages(dir);
191
203
  const files = await Promise.all(
192
204
  pkgs.map((pkg) => getPackageDefinitionsFiles(pkg, dir))
@@ -195,7 +207,7 @@ async function findAmentPackagesInDirectory(dir) {
195
207
  const rosFiles = files.flat();
196
208
  const pkgMap = new Map();
197
209
  await Promise.all(
198
- rosFiles.map((filePath) => addInterfaceInfos(filePath, dir, pkgMap))
210
+ rosFiles.map((filePath) => addInterfaceInfos(filePath, dir, pkgMap, useIDL))
199
211
  );
200
212
  return pkgMap;
201
213
  }
@@ -205,7 +217,7 @@ async function findAmentPackagesInDirectory(dir) {
205
217
  * @param {string} dir - the directory to search in
206
218
  * @return {Promise<Map<string, object>>} A mapping from the package name to some info about it.
207
219
  */
208
- async function findPackagesInDirectory(dir) {
220
+ async function findPackagesInDirectory(dir, useIDL) {
209
221
  return new Promise((resolve, reject) => {
210
222
  let amentExecuted = true;
211
223
 
@@ -217,30 +229,51 @@ async function findPackagesInDirectory(dir) {
217
229
  }
218
230
 
219
231
  if (amentExecuted) {
220
- return resolve(findAmentPackagesInDirectory(dir));
232
+ return resolve(findAmentPackagesInDirectory(dir, useIDL));
221
233
  }
222
234
 
223
235
  let walker = walk.walk(dir, { followLinks: true });
224
236
  let pkgMap = new Map();
225
- walker.on('file', (root, file, next) => {
237
+ walker.on('file', async (root, file, next) => {
226
238
  const interfaceInfo = grabInterfaceInfo(
227
239
  path.join(root, file.name),
228
240
  amentExecuted
229
241
  );
230
242
  const ignore = pkgFilters.matchesAny(interfaceInfo);
231
243
  if (!ignore) {
232
- if (path.extname(file.name) === '.msg') {
233
- // Some .msg files were generated prior to 0.3.2 for .action files,
234
- // which has been disabled. So these files should be ignored here.
235
- if (path.dirname(root).split(path.sep).pop() !== 'action') {
236
- addInterfaceInfo(interfaceInfo, 'messages', pkgMap);
244
+ if (useIDL) {
245
+ if (path.extname(file.name) === '.idl') {
246
+ addInterfaceInfo(interfaceInfo, 'idls', pkgMap);
237
247
  }
238
- } else if (path.extname(file.name) === '.srv') {
239
- addInterfaceInfo(interfaceInfo, 'services', pkgMap);
240
- } else if (path.extname(file.name) === '.action') {
241
- addInterfaceInfo(interfaceInfo, 'actions', pkgMap);
242
248
  } else {
243
- // we ignore all other files
249
+ if (path.extname(file.name) === '.msg') {
250
+ // Some .msg files were generated prior to 0.3.2 for .action files,
251
+ // which has been disabled. So these files should be ignored here.
252
+ if (path.dirname(root).split(path.sep).pop() !== 'action') {
253
+ addInterfaceInfo(interfaceInfo, 'messages', pkgMap);
254
+ }
255
+ } else if (path.extname(file.name) === '.srv') {
256
+ const requestMsgName = `${path.parse(interfaceInfo.filePath).name}_Request.msg`;
257
+ if (
258
+ !fs.existsSync(
259
+ path.join(
260
+ path.dirname(interfaceInfo.filePath),
261
+ requestMsgName
262
+ )
263
+ )
264
+ ) {
265
+ await generateMsgForSrv(
266
+ interfaceInfo.filePath,
267
+ interfaceInfo,
268
+ pkgMap
269
+ );
270
+ }
271
+ addInterfaceInfo(interfaceInfo, 'services', pkgMap);
272
+ } else if (path.extname(file.name) === '.action') {
273
+ addInterfaceInfo(interfaceInfo, 'actions', pkgMap);
274
+ } else {
275
+ // we ignore all other files
276
+ }
244
277
  }
245
278
  }
246
279
  next();
@@ -19,9 +19,15 @@
19
19
 
20
20
  const generator = require('../rosidl_gen/index.js');
21
21
  const tsdGenerator = require('../rostsd_gen/index.js');
22
+ const useIDL = !!process.argv.find((arg) => arg === '--idl');
22
23
 
23
24
  async function main() {
24
25
  console.log('Start generation of ROS2 JavaScript messages...');
26
+ if (!useIDL) {
27
+ console.log(
28
+ 'See details https://github.com/RobotWebTools/rclnodejs?tab=readme-ov-file#idl-message-generation for generating from .idl files'
29
+ );
30
+ }
25
31
 
26
32
  try {
27
33
  await generator.generateAll(true);
@@ -1312,6 +1312,20 @@ declare module 'rclnodejs' {
1312
1312
  export interface PolygonConstructor {
1313
1313
  new(other?: Polygon): Polygon;
1314
1314
  }
1315
+ export interface PolygonInstance {
1316
+ polygon: geometry_msgs.msg.Polygon;
1317
+ id: bigint;
1318
+ }
1319
+ export interface PolygonInstanceConstructor {
1320
+ new(other?: PolygonInstance): PolygonInstance;
1321
+ }
1322
+ export interface PolygonInstanceStamped {
1323
+ header: std_msgs.msg.Header;
1324
+ polygon: geometry_msgs.msg.PolygonInstance;
1325
+ }
1326
+ export interface PolygonInstanceStampedConstructor {
1327
+ new(other?: PolygonInstanceStamped): PolygonInstanceStamped;
1328
+ }
1315
1329
  export interface PolygonStamped {
1316
1330
  header: std_msgs.msg.Header;
1317
1331
  polygon: geometry_msgs.msg.Polygon;
@@ -1537,6 +1551,20 @@ declare module 'rclnodejs' {
1537
1551
  export interface PolygonConstructor {
1538
1552
  new(other?: Polygon): Polygon;
1539
1553
  }
1554
+ export interface PolygonInstance {
1555
+ polygon: 'geometry_msgs/msg/Polygon';
1556
+ id: 'int64';
1557
+ }
1558
+ export interface PolygonInstanceConstructor {
1559
+ new(other?: PolygonInstance): PolygonInstance;
1560
+ }
1561
+ export interface PolygonInstanceStamped {
1562
+ header: 'std_msgs/msg/Header';
1563
+ polygon: 'geometry_msgs/msg/PolygonInstance';
1564
+ }
1565
+ export interface PolygonInstanceStampedConstructor {
1566
+ new(other?: PolygonInstanceStamped): PolygonInstanceStamped;
1567
+ }
1540
1568
  export interface PolygonStamped {
1541
1569
  header: 'std_msgs/msg/Header';
1542
1570
  polygon: 'geometry_msgs/msg/Polygon';
@@ -7378,6 +7406,8 @@ declare module 'rclnodejs' {
7378
7406
  'geometry_msgs/msg/Point32': geometry_msgs.msg.Point32,
7379
7407
  'geometry_msgs/msg/PointStamped': geometry_msgs.msg.PointStamped,
7380
7408
  'geometry_msgs/msg/Polygon': geometry_msgs.msg.Polygon,
7409
+ 'geometry_msgs/msg/PolygonInstance': geometry_msgs.msg.PolygonInstance,
7410
+ 'geometry_msgs/msg/PolygonInstanceStamped': geometry_msgs.msg.PolygonInstanceStamped,
7381
7411
  'geometry_msgs/msg/PolygonStamped': geometry_msgs.msg.PolygonStamped,
7382
7412
  'geometry_msgs/msg/Pose': geometry_msgs.msg.Pose,
7383
7413
  'geometry_msgs/msg/Pose2D': geometry_msgs.msg.Pose2D,
@@ -7408,6 +7438,8 @@ declare module 'rclnodejs' {
7408
7438
  'geometry_msgs/msg/descriptor/Point32': geometry_msgs.msg.descriptor.Point32,
7409
7439
  'geometry_msgs/msg/descriptor/PointStamped': geometry_msgs.msg.descriptor.PointStamped,
7410
7440
  'geometry_msgs/msg/descriptor/Polygon': geometry_msgs.msg.descriptor.Polygon,
7441
+ 'geometry_msgs/msg/descriptor/PolygonInstance': geometry_msgs.msg.descriptor.PolygonInstance,
7442
+ 'geometry_msgs/msg/descriptor/PolygonInstanceStamped': geometry_msgs.msg.descriptor.PolygonInstanceStamped,
7411
7443
  'geometry_msgs/msg/descriptor/PolygonStamped': geometry_msgs.msg.descriptor.PolygonStamped,
7412
7444
  'geometry_msgs/msg/descriptor/Pose': geometry_msgs.msg.descriptor.Pose,
7413
7445
  'geometry_msgs/msg/descriptor/Pose2D': geometry_msgs.msg.descriptor.Pose2D,
@@ -8129,6 +8161,8 @@ declare module 'rclnodejs' {
8129
8161
  'geometry_msgs/msg/Point32': geometry_msgs.msg.Point32Constructor,
8130
8162
  'geometry_msgs/msg/PointStamped': geometry_msgs.msg.PointStampedConstructor,
8131
8163
  'geometry_msgs/msg/Polygon': geometry_msgs.msg.PolygonConstructor,
8164
+ 'geometry_msgs/msg/PolygonInstance': geometry_msgs.msg.PolygonInstanceConstructor,
8165
+ 'geometry_msgs/msg/PolygonInstanceStamped': geometry_msgs.msg.PolygonInstanceStampedConstructor,
8132
8166
  'geometry_msgs/msg/PolygonStamped': geometry_msgs.msg.PolygonStampedConstructor,
8133
8167
  'geometry_msgs/msg/Pose': geometry_msgs.msg.PoseConstructor,
8134
8168
  'geometry_msgs/msg/Pose2D': geometry_msgs.msg.Pose2DConstructor,
@@ -8159,6 +8193,8 @@ declare module 'rclnodejs' {
8159
8193
  'geometry_msgs/msg/descriptor/Point32': geometry_msgs.msg.descriptor.Point32Constructor,
8160
8194
  'geometry_msgs/msg/descriptor/PointStamped': geometry_msgs.msg.descriptor.PointStampedConstructor,
8161
8195
  'geometry_msgs/msg/descriptor/Polygon': geometry_msgs.msg.descriptor.PolygonConstructor,
8196
+ 'geometry_msgs/msg/descriptor/PolygonInstance': geometry_msgs.msg.descriptor.PolygonInstanceConstructor,
8197
+ 'geometry_msgs/msg/descriptor/PolygonInstanceStamped': geometry_msgs.msg.descriptor.PolygonInstanceStampedConstructor,
8162
8198
  'geometry_msgs/msg/descriptor/PolygonStamped': geometry_msgs.msg.descriptor.PolygonStampedConstructor,
8163
8199
  'geometry_msgs/msg/descriptor/Pose': geometry_msgs.msg.descriptor.PoseConstructor,
8164
8200
  'geometry_msgs/msg/descriptor/Pose2D': geometry_msgs.msg.descriptor.Pose2DConstructor,
@@ -1,39 +0,0 @@
1
- // Copyright (c) 2017 Intel Corporation. All rights reserved.
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 exec = require('child_process').exec;
18
-
19
- const cmd = 'wget -nc ';
20
- const cpplintUrl =
21
- 'https://raw.githubusercontent.com/cpplint/cpplint/refs/heads/develop/cpplint.py';
22
- const root = `${__dirname}/../src`;
23
- const args = `--filter=-build/include_subdir,-whitespace/indent_namespace --extensions=cpp,h,hpp,cc ${root}/*`;
24
-
25
- console.log('Downloading the cpplint...');
26
- exec(cmd + cpplintUrl, (err, stdout, stderr) => {
27
- if (err) {
28
- console.log(`Downloading failed: ${stderr}`);
29
- } else {
30
- console.log('Running the cpplint...');
31
- exec('python3 cpplint.py ' + args, (err, stdout, stderr) => {
32
- console.log(stdout);
33
- if (err) {
34
- console.log(stderr);
35
- throw Error('cpplint failed.');
36
- }
37
- });
38
- }
39
- });
@@ -1,38 +0,0 @@
1
- #!/bin/bash
2
- #
3
- # Copyright (c) 2017 Intel Corporation. All rights reserved.
4
-
5
- # Licensed under the Apache License, Version 2.0 (the "License");
6
- # you may not use this file except in compliance with the License.
7
- # You may obtain a copy of the License at
8
-
9
- # http://www.apache.org/licenses/LICENSE-2.0
10
-
11
- # Unless required by applicable law or agreed to in writing, software
12
- # distributed under the License is distributed on an "AS IS" BASIS,
13
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
- # See the License for the specific language governing permissions and
15
- # limitations under the License.
16
-
17
- #Usage: npm-pack.sh
18
-
19
- WORKDIR=`mktemp -d`
20
- RAWMODULEDIR="rclnodejs/"
21
- MODULEDIR="$WORKDIR/$RAWMODULEDIR"
22
-
23
- mkdir -p $MODULEDIR
24
- rsync -a . $MODULEDIR
25
-
26
- cp -f scripts/npmjs-readme.md $MODULEDIR/README.md
27
-
28
- pushd . > /dev/null
29
- cd $WORKDIR
30
- FILENAME=`npm pack $RAWMODULEDIR | awk '{for(i=1; i<=NF; i++) if ($i ~ /rclnodejs-.*\.tgz/) print $i}'`
31
- TARFILENAME="$WORKDIR/$FILENAME"
32
-
33
- popd > /dev/null
34
- mkdir -p dist
35
- cp -f $TARFILENAME ./dist/
36
- rm -rf $WORKDIR
37
-
38
- echo "Generated ./dist/$FILENAME"
@@ -1,169 +0,0 @@
1
- # rclnodejs [![Linux](https://github.com/RobotWebTools/rclnodejs/actions/workflows/linux-x64-build-and-test.yml/badge.svg?branch=develop)](https://github.com/RobotWebTools/rclnodejs/actions/workflows/linux-x64-build-and-test.yml?query=branch%3Adevelop)[![Linux](https://github.com/RobotWebTools/rclnodejs/actions/workflows/linux-arm64-build-and-test.yml/badge.svg?branch=develop)](https://github.com/RobotWebTools/rclnodejs/actions/workflows/linux-arm64-build-and-test.yml?query=branch%3Adevelop)
2
-
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
-
5
- Here's an example for how to create a ROS 2 node that publishes a string message in a few lines of JavaScript.
6
-
7
- ```JavaScript
8
- const rclnodejs = require('rclnodejs');
9
- rclnodejs.init().then(() => {
10
- const node = rclnodejs.createNode('publisher_example_node');
11
- const publisher = node.createPublisher('std_msgs/msg/String', 'topic');
12
- publisher.publish(`Hello ROS 2 from rclnodejs`);
13
- rclnodejs.spin(node);
14
- });
15
- ```
16
-
17
- ## Prerequisites
18
-
19
- **Node.js**
20
-
21
- - [Node.js](https://nodejs.org/en/) version >= 16.13.0.
22
-
23
- **ROS 2 SDK**
24
-
25
- - See the ROS 2 SDK [Installation Guide](https://docs.ros.org/en/kilted/Installation.html) for details.
26
- - **DON'T FORGET TO [SOURCE THE ROS 2 STARTUP FILES](https://docs.ros.org/en/kilted/Tutorials/Beginner-CLI-Tools/Configuring-ROS2-Environment.htmls)**
27
-
28
- ## Install rclnodejs
29
-
30
- Install the rclnodejs version that is compatible with your installed version of ROS 2 (see table below).
31
-
32
- Run the following command for the most current version of rclnodejs
33
-
34
- ```bash
35
- npm i rclnodejs
36
- ```
37
-
38
- or to install a specific version of rclnodejs use
39
-
40
- ```bash
41
- npm i rclnodejs@x.y.z
42
- ```
43
-
44
- #### RCLNODEJS - ROS 2 Version Compatibility
45
-
46
- | RCLNODEJS Version | Compatible ROS 2 LTS |
47
- | :----------------------------------------------------------------------------------------: | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: |
48
- | latest version (currently [v1.3.0](https://github.com/RobotWebTools/rclnodejs/tree/1.3.0)) | [Kilted](https://github.com/RobotWebTools/rclnodejs/tree/kilted)<br>[Jazzy](https://github.com/RobotWebTools/rclnodejs/tree/jazzy)<br>[Humble](https://github.com/RobotWebTools/rclnodejs/tree/humble-hawksbill) |
49
-
50
- ## Documentation
51
-
52
- API [documentation](https://robotwebtools.github.io/rclnodejs/docs/index.html) is available online.
53
-
54
- ## JavaScript Examples
55
-
56
- The source for the following examples and many others can be found [here](https://github.com/RobotWebTools/rclnodejs/tree/develop/example).
57
-
58
- Use complex message
59
-
60
- ```JavaScript
61
- const publisher = node.createPublisher('sensor_msgs/msg/JointState', 'topic');
62
- publisher.publish({
63
- header: {
64
- stamp: {
65
- sec: 123456,
66
- nanosec: 789,
67
- },
68
- frame_id: 'main frame',
69
- },
70
- name: ['Tom', 'Jerry'],
71
- position: [1, 2],
72
- velocity: [2, 3],
73
- effort: [4, 5, 6],
74
- });
75
-
76
- ```
77
-
78
- Create a subscription
79
-
80
- ```JavaScript
81
- const rclnodejs = require('../index.js');
82
-
83
- // Create a ROS node and then print out the string message received from publishers
84
- rclnodejs.init().then(() => {
85
- const node = rclnodejs.createNode('subscription_example_node');
86
-
87
- node.createSubscription('std_msgs/msg/String', 'topic', (msg) => {
88
- console.log(`Received message: ${typeof msg}`, msg);
89
- });
90
-
91
- rclnodejs.spin(node);
92
- });
93
- ```
94
-
95
- Create a service
96
-
97
- ```JavaScript
98
- node.createService('example_interfaces/srv/AddTwoInts', 'add_two_ints', (request, response) => {
99
- console.log(`Incoming request: ${typeof request}`, request);
100
- let result = response.template;
101
- result.sum = request.a + request.b;
102
- console.log(`Sending response: ${typeof result}`, result, '\n--');
103
- response.send(result);
104
- });
105
-
106
- ```
107
-
108
- Send a request in a client
109
-
110
- ```JavaScript
111
- const client = node.createClient('example_interfaces/srv/AddTwoInts', 'add_two_ints');
112
- const request = {
113
- a: Math.floor(Math.random() * 100),
114
- b: Math.floor(Math.random() * 100),
115
- };
116
-
117
- console.log(`Sending: ${typeof request}`, request);
118
- client.sendRequest(request, (response) => {
119
- console.log(`Result: ${typeof response}`, response);
120
- });
121
-
122
- ```
123
-
124
- ## Using rclnodejs with TypeScript
125
-
126
- In your node project install the rclnodejs package as described above. You will also need the TypeScript compiler and node typings installed.
127
-
128
- ```
129
- npm install typescript @types/node -D
130
- ```
131
-
132
- In your project's tsconfig.json file include the following compiler options:
133
-
134
- ```jsonc
135
- {
136
- "compilerOptions": {
137
- "module": "commonjs",
138
- "moduleResolution": "node",
139
- "target": "es6",
140
- ...
141
- }
142
- }
143
- ```
144
-
145
- Here's an earlier JavaScript example reimplemented in TypeScript.
146
-
147
- ```typescript
148
- import * as rclnodejs from 'rclnodejs';
149
- rclnodejs.init().then(() => {
150
- const node = rclnodejs.createNode('publisher_example_node');
151
- const publisher = node.createPublisher('std_msgs/msg/String', 'topic');
152
- publisher.publish(`Hello ROS 2 from rclnodejs`);
153
- rclnodejs.spin(node);
154
- });
155
- ```
156
-
157
- Type-aliases for the ROS2 messages can be found in the `types/interfaces.d.ts` file. To use a message type-alias follow the naming pattern <pkg_name>.[msg|srv].<type>, e.g., sensor_msgs.msg.LaserScan or the std_msgs.msg.String as shown below.
158
-
159
- ```typescript
160
- const msg: rclnodejs.std_msgs.msg.String = {
161
- data: 'hello ROS2 from rclnodejs',
162
- };
163
- ```
164
-
165
- **Note** that the interface.d.ts file is updated each time the generate_messages.js script is run.
166
-
167
- ## License
168
-
169
- Apache License Version 2.0
@@ -1,49 +0,0 @@
1
- // Copyright (c) 2017 Intel Corporation. All rights reserved.
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 fs = require('fs-extra');
18
- const Mocha = require('mocha');
19
- const os = require('os');
20
- const path = require('path');
21
-
22
- fs.remove(path.join(path.dirname(__dirname), 'generated'), (err) => {
23
- if (!err) {
24
- let mocha = new Mocha();
25
- const testDir = path.join(__dirname, '../test/');
26
- // eslint-disable-next-line
27
- const tests = fs.readdirSync(testDir).filter((file) => {
28
- return file.substr(0, 5) === 'test-';
29
- });
30
-
31
- // eslint-disable-next-line
32
- let blocklist = JSON.parse(
33
- fs.readFileSync(path.join(__dirname, '../test/blocklist.json'), 'utf8')
34
- );
35
- let ignoredCases = blocklist[os.type()];
36
-
37
- tests.forEach((test) => {
38
- if (ignoredCases.indexOf(test) === -1) {
39
- mocha.addFile(path.join(testDir, test));
40
- }
41
- });
42
-
43
- mocha.run(function (failures) {
44
- process.on('exit', () => {
45
- process.exit(failures);
46
- });
47
- });
48
- }
49
- });