Node-RED ROS 2 Plugin

License: MIT

This project is part of DIH^2. The main goal is provide Node-RED interoperability with ROS2 and FIWARE. The plugin introduces in the Node-RED palette new nodes dealing with:

Type definition

In order to transmit information it is necessary to precisely define the composition of the data delivered.

Node-RED approach is based on JSON which is versatile and user friendly but cannot be used to interoperate with industrial protocols that require language-independent type Description.

In order to provide this interoperability ROS2 introduced IDL. Which is a data type and interfaces descriptive language customary in industrial applications.

The new nodes make both: IDL type descriptions and well known ROS2 types available.

ROS2 Publisher-Subscriber interface

Publisher and Subscriber nodes are provided to directly access its ROS2 counterparts.

Different topics and QoS can be selected. Also a global configuration node allows to select the ROS domain to enforce.

FIWARE Context Broker Publisher-Subscriber interface

The Context Broker doesn't provide a Publisher-Subscriber interface (works more like a database) but a translation can be easily performed if:

  • Entities are understood as topics.
  • Creating or setting an entry is understood as publishing.
  • Notification callbacks on an entity are understood as subscribtion callbacks.

Contents

Background

The interoperability between the plugin and the ROS2 and FIWARE Broker environments is achieved using WebSocket bridges to them. This was the natural choice given that Node-RED relies on WebSocket for front-end/back-end communication.

These bridges are generated using Integration-Service an eProsima open-source tool.

Using Integration-Service directly from the plugin was possible, but it was considered a better choice to create another Node.js library (is-web-api, to abstract the bridge operation. This way:

  • The plugin can rely on any other bridge technology.
  • Development is simplified by enforcing separation of concerns.
  • Any other Node.js project (besides the plugin) can profit from the bridge library.

Install

A Dockerfile is provided to exemplify the set up on an argument provided ROS2 distro.

Dependencies

Some of the following installation steps can be skipped if the target system already fulfils some of the requirements:

  1. ROS2 installation. Follow the official ROS2 installation guide for the distro of choice. The Dockerfile is based on a ROS2 image, so this is not exemplified.

  2. Install Node.js. The usual OS package managers (like apt on Ubuntu or winget/chocolatey on windows) provide it. An exhaustive list is available here. Some package managers constrain the user to a specific version of Node.js. The Node.js site hints on how to install specific versions.

    For example, in apt is possible to add via location configuration file a new remote repository where all Node.js versions are available. This is the strategy that the Dockerfile uses:

    $ curl -sL https://deb.nodesource.com/setup_14.x -o nodesource_setup.sh
    $ chmod +x nodesource_setup.sh && sudo sh -c ./nodesource_setup.sh
    $ sudo apt-get install -y nodejs
  3. Install Node-RED. Follow the official Node-RED installation guide. The Dockerfile favors the easiest procedure which relies on npm (default Node.js package manager) which is available after Node.js installation step:

    $ npm install -g node-red
  4. Install Integration-Service. Follow the Integration-Service installation manual. This is exemplified in the Dockerfile, basically it is build from sources downloaded from github. Dependencies associated with the build and bridge environments are required:

    $ apt-get update
    $ apt-get install -y libyaml-cpp-dev libboost-program-options-dev libwebsocketpp-dev \
                       libboost-system-dev libboost-dev libssl-dev libcurlpp-dev \
                       libasio-dev libcurl4-openssl-dev git
    $ mkdir -p /is_ws/src && cd "$_"
    $ git clone https://github.com/eProsima/Integration-Service.git is
    $ git clone https://github.com/eProsima/WebSocket-SH.git
    $ git clone https://github.com/eProsima/ROS2-SH.git
    $ git clone https://github.com/eProsima/FIWARE-SH.git
    
    $ . /opt/ros/humble/setup.sh # customize the ROS2 distro: foxy, galactic, humble ...
    $ colcon build --cmake-args -DIS_ROS2_SH_MODE=DYNAMIC --install-base /opt/is

    Note that it uses the ROS2 build tool: colcon As ROS2 it is necessary to source and overlay. In order to simplify sourcing /opt/is was chosen as deployment dir. The overlay can be then sourced as:

    $ . /opt/is/setup.bash

    It will automatically load the ROS2 overlay too. After the overlay is sourced it must be possible to access the integration-service help as:

    $ integration-service --help

Plugin installation

Once all the dependencies are available we can deploy the plugin via npm:

  • From npm repo:

    $ npm install -g node-red-ros2-plugin
  • From sources. npm allows direct deployment from github repo:

    $ npm install -g https://github.com/eProsima/node-red-ros2-plugin

    Or, as in the Dockerfile, from a local sources directory. The docker favors this approach to allow tampering with the sources.

    $ git clone https://github.com/eProsima/node-red-ros2-plugin.git plugin_sources
    $ npm install -g  ./plugin_sources
    

Usage

In order to test the plugin there are two options: follow the installation steps above or run the test container provided here.

Node-RED palette

The main concepts associated with Node-RED operation are explained here. The plugin nodes are displayed on the Node-RED palette as shown in the image. From there, they can be dragged into the workspace.

Palette layout

The palette is the pane on the left where all available nodes are classified by sections. Plugin ones appear under ROS2 and FIWARE (figure's red frame). The worksplace is the central pane where different flows are associated to the upper tabs.

Note: the text that labels the node, changes from palette to workspace, and may change depending on the node configuration.

Definining a type

In order the publish or subscribe data we need first to specify the associated type. The plugin provides two options:

Choosing a predefined ROS2 type

This node represents a specific ROS2 Builtin Type. Once in the workspace, its set up dialog can be opened by doble clicking over it.
The dialog provides a Package drop-down control where all ROS2 msg packages are listed.
Once a package is selected the Message drop-down control allows selection of a package specific message. In this example the package selected is geometry_msgs. From this package the Point message is selected.
Once the dialog set up is saved, the node label changes to highligh the selected type in a package/message pattern.

Defining a new type via IDL

This node represents a type defined by means of an IDL. IDL is a language that allows unambiguous specification of the interfaces that may be used to define the data types.
The dialog provides an edit box where the desired IDL can be introduced
Note that in order to use the type in ROS2 it must follow several conventions:
  • There must be an outer module which should match the message package name.
  • There must be an inner module called msg.
  • The type name must follow PascalCase convention.
By default a dummy message that follows the above guidelines is provided.
Once the dialog set up is saved, the node label changes to highligh the selected type in a package/message pattern.

Injecting a type instance into the pipeline

Node-RED pipelines start in source nodes. The most popular one is the inject node which requires the user to manually defined each field associated to the type. In order to simplify this a specific node is introduced:

This node mimics the inject node behaviour but automatically populates the input dialog with the fields associated with any type node linked to it. For example, if we wire together a ROS Inject and a ROS Type or IDL Type nodes as shown in the figure:

The associated dialogs are populated with the linked type fields and types.

ROS2 nodes usage

In order to interact with a ROS2 environment we must specify the same domain id in use for that environment.

The domain id is a number in the range [0, 166] that provides isolation for ROS2 nodes. It defaults to 0 and its main advantage is reduce the incomming traffic for each ROS2 node, discharging them and speeding things up.

Another key concepts in the ROS2 environment are:

  • topic one. A topic is a text string ROS2 nodes use to notify all other nodes in which data they are interested. When a ROS2 node wants to send or receive data it must specify:
  • Which type is the data they want receive. For example the geometry_msgs/Pose we introduced above.
  • Topic associated with the data. For example /marker_pose, but in ROS2 topics are often decorated using namespaces to simplify identification, as in /eProsima/buildings/E3g1/room/F2h3/marker/4Rg1/pose.
  • Quality of Service (QoS). Those are policies that allow fine tunning of the communication between nodes. For example:
    • History QoS allows to discard messages if only the most recent one is meaningful for our purposes.
    • Reliable QoS enforces message reception by resending it until the receiver acknowledges it.
    • Durability QoS assures messages published before the receiver node creation would be delivered.

Note: ROS2 nodes can only communicate if their respective QoS are compatible. Information on QoS compatibility is available here.

ROS2 configuration node

A Node-RED config node is provided to set up the domain ID, which is a global selection:

ROS Config Node

Note: The ROS2 default domain value is 0

ROS2 Publisher

This node represents a ROS2 publisher. It is able to publish messages on a specific topic with specific QoS
The dialog provides controls to configure:
Topic
Note that the backslash / typical of ROS2 topics is not necessary
Domain ID
Selected globally via the configuration node explained above
QoS
The +add button at the bottom adds new combo-boxes to the control where the available options for each policy can be selected

ROS2 Subscriber

This node represents a ROS2 subscriber. It is able to subscribe on a specific topic and receive all messages published for it.
The dialog provides controls to configure:
Topic
Note that the backslash / typical of ROS2 topics is not necessary
Domain ID
Selected globally via the configuration node explained above
QoS
The +add button at the bottom adds new combo-boxes to the control where the available options for each policy can be selected

ROS2 Examples

ROS2 Basic Publication Example

Let's show how to use a custom type.

  1. Launch docker compose as explained here.

  2. Create and wire the following nodes:

    • An IDL Type node. Open the associated dialog and introduce the following idl:
    module custom_msgs {
        module msg {
            struct Message {
                string text;
                uint64 value;
            };
        };
    };
    • A ROS Publisher node. Open the associated dialog and set up the publisher:

      Topic : hope

      Domain : 42

    • A ROS Inject node. Open the associated dialog and fill in the fields:

      text : Hello World!

      value : 42

  3. Deploy the flow pressing the corresponding button. Once deployed, the custom type has been registered in the ROS2 distro.

  4. Let's launch a subscriber from the ROS2 cli.

$ docker exec -ti --env ROS_DOMAIN_ID=42 docker-visual-ros-1 /ros_entrypoint.sh ros2 topic echo /hope custom_msgs/msg/Message
  1. Now click on the inject node button within the editor and see how the terminal receives the data.

Note: In the example the ROS2 domain value selected is 42, different from the default value of 0.

ROS2 Publisher

ROS2 Basic Subscription Example

In this case, a builtin ROS2 type (geometry_msgs/Point) will be used.

  1. Launch docker compose as explained here.

  2. Create and wire the following nodes:

    • A ROS2 Type node. Open the associated dialog and select:

      Package : geometry_msgs

      Message : Point

    • A ROS2 Subscriber node. Open the associated dialog and set up the subscriber:

      Topic : hope

      Domain : 17

    • A debug node from the common palette section. Open the associated dialog and set it up to show the x coordinate of the point:

      Output : msg.x

  3. Deploy the flow pressing the corresponding button.

  4. Publish a message on that topic from the ROS2 cli. In this example we launch a new container connected to the same network using the standard ros:humble image.

$ docker run --rm -ti --env ROS_DOMAIN_ID=17 --network docker_visualros ros:humble \
         ros2 topic pub /hope geometry_msgs/msg/Point "{ x: 42, y: 0, z: 0 }"

turtlesim

ROS2 Mandatory Turtlesim Example

Turtlesim is an ad hoc package that ROS2 provides as GUI node example.

Set up

Unlike the previous examples turtlesim cannot work on terminal mode. There are several ways to workaround this:

  1. Run GUI application in a docker container as shown here.
  2. Share the container network stack with the host.
  3. Run Node-RED backend directly in your host (see installation steps).

Here we favour the second option as the most simple. This only requires:

  • A ROS2 installation in the host. Follow the official ROS2 installation guide for the distro of choice.
  • Launch the Visual-ROS container sharing host network stack:
    node-red-ros2-plugin/docker$ docker build --build-arg ROS_DISTRO=humble -t visualros:humble .
    $ docker run -ti --name turtledemo --network host --ipc host visualros:humble /node_entrypoint.sh node-red
Demo steps
  1. Launch turtlesim on the host by doing:
    $ . /opt/ros/humble/setup.sh
    $ ros2 run turtlesim turtlesim_node

A window should appear with a turtle in the middle.

  1. Open a web browser on http://localhost:1880.

  2. Create and wire the following nodes:

    • A ROS2 Type node. In the associated dialog set up the turtlesim pose type: geometry_msgs/Twist.
    • A couple of ROS2 Inject nodes: one to move the turtle forward and another to spin it. Wire both nodes to the ROS2 Type. Open the associated dialogs and take into account that:
      • mover forward means linear.x = 1
      • spin means angular.z = 1
    • A ROS2 Publisher node. Wire it to the ROS2 Type node. Open the associated dialog and set up as:
      • Topic the turtle/cmd_vel.
      • Use the default ROS2 domain 0.
  3. Click the Deploy button.

turtlesim

Now click on the inject nodes buttons within the editor and see how the turtle moves.

This json file can be imported to Node-RED in order to reproduce the flow.

FIWARE nodes usage

The FIWARE Context Broker uses a REST API to provide information. This interface do not exactly follows a Publisher/Subscriber model but can be adapted to do so:

  • Broker entities are mapped as Publisher/Subscriber topics.
  • Types are described using IDL which works as a subset of the NGSI type system.

FIWARE configuration node

A Node-RED config node is provided to set up the FIWARE Context Broker IPv4 address which is a global selection.

FIWARE Config Node

FIWARE Publisher

This node represents a FIWARE publisher able to publish messages on a specific topic.
The dialog provides controls to configure:
Topic
Element that acts as a bus for nodes to exhange messages. It matches the Context Broker entity concept.
Context Broker
Address of the FIWARE Context Broker this node will connect to. A specific config node dialog will be open in order to ease address and port selection.

FIWARE Subscriber

This node represents a FIWARE subscriber. It is able to subscribe on a specific topic and receive all messages published for it.
The dialog provides controls to configure:
Topic
Element that acts as a bus for nodes to exchange messages. It matches the Context Broker entity concept.
Context Broker
Address of the FIWARE Context Broker this node will connect to. A specific config node dialog will be open in order to ease address and port selection.

FIWARE Examples

FIWARE Basic Publication Example

Let's use a custom type.

  1. Launch docker compose as explained here.

  2. Create and wire the following nodes:

    • An IDL Type node. Open the associated dialog and introduce the following idl:
    module custom_msgs {
        module msg {
            struct Message {
                string text;
                uint64 value;
            };
        };
    };
    • A FIWARE Publisher node. Open the associated dialog and set up the publisher:

      Topic : hope

      Context Broker : 192.168.42.14:1026

      Note the address and port of the Context Broker was specified in the compose.yaml file.

    • A ROS Inject node. Open the associated dialog and fill in the fields:

      text : Hello World!

      value : 42

  3. Deploy the flow pressing the corresponding button.

  4. Once deployed, click on the inject node button within the editor. The Context Broker should have created an entity associated to the topic (hope) with the values provided in the inject node.

In order to check it, the FIWARE Context Broker can be directly queried using its REST API (note that in the compose.yaml file the Context Broker port 1026 is mapped to the host machine). Open a console on the host and type:

$ curl -G -X GET "http://localhost:1026/v2/entities" -d "type=custom_msgs::msg::Message" -d "id=hope"

It should return the following json:

[
    {
        "id": "hope",
        "type": "custom_msgs::msg::Message",
        "text": {
            "type": "Text",
            "value": "Hello World!",
            "metadata": {}
        },
        "value": {
            "type": "Number",
            "value": 42,
            "metadata": {}
        }
    }
]

FIWARE Publisher

FIWARE Basic Subscription Example

In this case, a builtin ROS2 type (geometry_msgs/Point) will be used.

  1. Launch docker compose as explained here.

  2. Create and wire the following nodes:

    • A ROS2 Type node. Open the associated dialog and select:

      Package : geometry_msgs

      Message : Point

    • A FIWARE Subscriber node. Open the associated dialog and set up the subscriber:

      Topic : position

      Context Broker : 192.168.42.14:1026

    • A debug node from the common palette section. Open the associated dialog and set it up to show the x coordinate of the point:

      Output : msg.x

  3. Deploy the flow pressing the corresponding button.

  4. Publish a message on that topic from the FIWARE REST API. Because the compose.yaml maps the FIWARE Context Broker port to a host one (1026) is possible to reach it from the host machine. Open a console on the host and type:

$ curl http://localhost:1026/v2/entities -H 'Content-Type: application/json' -d @- <<EOF
{
    "id": "position",
    "type": "geometry_msgs::msg::Point",
    "x": {"value": 42, "type":"Text"},
    "y": {"value": 4, "type":"Text"},
    "z": {"value": 2, "type":"Text"}
}
EOF

The debug pan should log an output. In order to update the entity value, further http queries should follow:

$ curl -X PUT http://localhost:1026/v2/entities/position/attrs?type=geometry_msgs::msg::Point \
    -H 'Content-Type: application/json' -d @- <<EOF
{
    "x": {"value": 3, "type":"Text"},
    "y": {"value": 2, "type":"Text"},
    "z": {"value": 1, "type":"Text"}
}
EOF

turtlesim


eu_flag

This project (DIH² - A Pan‐European Network of Robotics DIHs for Agile Production) has received funding from the European Union’s Horizon 2020 research and innovation programme under grant agreement No 824964