2: Our 1st ROS 2 TypeScript Program

ROS2JsGuy
6 min readJun 11, 2020

--

Photo by Alex Knight on Unsplash

Join along as we develop a high level introduction of ROS while coding up our first ROS2 JavaScript program, a simple ROS node that sends ‘hello world’ messages using a Twitter style publish-subscribe model.

edited 20220211 — updated to use NodeJS 16, TypeScript 4.5 & rclnodejs-cli

ROS 2 Conceptual Overview

ROS 2 is a cool distributed computing platform. The unit of independent activity is the ROS node. ROS enables nodes to discover one another and coordinate their activities and exchange data by passing messages through an anonymous publish-subscribe mechanism. One or more nodes can reside within an OS process that may reside on the same computer or different computers. The group of nodes within a system and their communications is known as the ROS graph.

The ROS 2 api includes C, C++ and Python programming language bindings known as ROS Client Libraries (RCL). Additional community developed RCLs exists for JavaScript, Java, Rust, etc. Throughout all of the tutorials we will be using the open-source ROS 2 RCL known as rclnodejs for JavaScript and TypeScript.

When designing the interaction and data exchange between nodes we can choose between 3 styles of communications:

  • publisher-subscriber — anonymous asynchronous message passing, e.g., Twitter
  • client-server — synchronous request-reply communications, e.g., RCP, REST
  • actions — long running asynchronous client-server communications, e.g., Jobs

In this tutorial we use TypeScript and Nodejs to code a ROS 2 node that communicates using publisher-subscriber messaging.

Publisher-Subscriber (pub-sub) Communications

In a ROS 2 pub-sub communications model, messages are asynchronously broadcast, i.e., published, to the ROS 2 node graph on uniquely named channels. Nodes within the graph that are interested in receiving these messages create a subscription to the channel. ROS handles the network interface and message routing between nodes.

A ROS node wishing to broadcast a message creates a publisher that is configured with the type of message it will broadcast and the uniquely named topic to which it will broadcast. When ready, the node asks the publisher to publish, i.e., send, the message. Where upon ROS network services dispatch the message. To receive these messages a node creates a subscription that is configured with the type of messages and topic to listen and a handler that will process incoming messages. ROS network services route and deliver messages to awaiting subscriptions. Where upon each subscription’s handler is invoked to process the incoming message.

The ROS 2 rclnodejs JavaScript library that we will be using provides pub-sub messaging in an interoperable manner with nodes implemented in JavaScript and other languages such as C++ and Python.

Let’s Code

Some details about this project. It will consist of:

  • a ROS Node that manages the life-cycle of a publisher instance and all of it’s communications
  • a ROS publisher that broadcasts string messages to the topic msg
  • a timer that sends a time-stampedhello world message once every second
  • the program will run indefinitely until the process is manually terminated, e.g., Ctrl-C from shell

Prerequisites

Getting started you’ll need a dev environment with

  • Nodejs v10.22–17.x — I’m using Node 16.13.0 (LTS)
  • ROS 2 Foxy (LTS) or Galactic release

If you haven’t setup your ROS 2 JavaScript coding environment see this article.

Lastly if you would like to skip ahead and see the end result, you can find a link to a github project in the Resources section found at the end of this article.

Step-1: Project Setup

Let’s begin setting up a Nodejs project named ros2-js-examples with module dependencies for rclnodejs, the ROS 2 JavaScript client library and TypeScript. See Resources section below for jsdoc documentation.

Note: if you wish to code in JavaScript most of the examples are easily ported from TypeScript to JavaScript (ES6). I’ve chosen to use TypeScript due to it’s rising popularity and I just like using it especially when project complexity and size grows beyond the few examples presented on this site.

We will use rclnodejs-cli to create a working project that we will then evolve. From a command shell enter the following Unix/Linux commands (omit comment lines, e.g., any line starting with #):

# make project folder structure
npx rclnodejs-cli ros2-js-examples --typescript

The rclnodejs-cli tool generates a few more files and folders than we need for now. So let’s do a bit of quick clean up.

cd ros2-js-examples# clean up unused files and folders
rm -rf CMakeLists.txt include launch package.xml *.md src
# create src/example folder
mkdir -p src/example1
cd src/example1

Note that for all tutorials we will develop example code in the ros2-js-examples project. The code for each tutorial will reside in it’s on folder following this pattern:

ros2-js-examples
src/
example1/
example2/
...
exampleN/

Step-2: Code Node and Publisher

Now let’s code up a ROS 2 node that publishes a Hello World message.

  1. From the ros2-js-examples/src/example1folder create and open the file node-publisher.ts in your editor.
  2. Copy-paste the following code into the editor and save.

Here’s a quick explanation of the code:

line-5: Import the rclnodejs library

import * as rclnodejs from 'rclnodejs';

line-10: The rclnodejs library must be initialized and made ready to connecting with other ROS 2 nodes.

await rclnodejs.init();

line-13: Using rclnodejs, we create a node named node-publisher in the ros2_js_examples namespace.

let node = rclnodejs.createNode('node_publisher', 'ros2_js_examples');

line-14: Next we create a Publisher instance for the topic msg We must include the type of message that will be published. In this case it is a std_msgs String

let publisher = node.createPublisher();

line-16: Begin asynchronously listening for incoming messages.

rclnodejs.spin(node);

line-19, 22: Start a timer, i.e., setInterval(), that will publish a message every 1 second.

Step-3: Compile TypeScript

Invoke the TypeScript compiler tsc to transcode our node-publisher.ts file into JavaScript. The resulting JS file is created in the dist/ folder with the same name as it’s src TypeScript file.

npm run build 

Step-4: Run

Using the Nodejs runtime, let’s run our example1-publisher program. In your terminal shell enter this command:

node dist/example1/node-publisher.js

You should see messages begin dribbling to stdout as shown below.

Step-5: Using ros2 CLI Tools

Theros2 commandline interface (CLI) provides tools for launching and running ROS 2 nodes and messages. For example with our example1-publisher program running we can view it’s ROS 2 node as follows:

ros2 node list

Next let’s view the messages actively being published to the ‘msg’ topic.

Enter the following command.

ros2 topic echo /ros2_js_examples/msg

To view other ros2 cli commands enter:

ros2 -h

Or for help on a specific command enter:

ros2 <command> -h

Summary

ROS 2 pub-sub communications is very common. This tutorial introduced you to the steps for creating a node and publishing a message to a topic. In the next tutorial we will learn how to subscribe to a topic to receive published messages.

Resources

  1. Source code for this tutorial can be found here.
  2. ROS 2 concepts
  3. rclnodejs jsdoc

Please consider liking this tutorial and following me here and on Twitter @ros2jsguy

--

--

ROS2JsGuy

“ROS 2 for JavaScript & TypeScript Developers” tutorials from a guy named Wayne