This fork of RWS supports ROS2 Humble and Zenoh RWS, is more performant because of JSON libraries, supports sending actions, but does not support various encodings. We use this internally at Innate and it works great.
RWS provides WebSocket interface to ROS2. It is partially* compatible with Rosbridge v2 protocol and can be used as a drop-in replacement. The main difference with Rosbridge is that RWS is written is C++, hence it's more fast and memory efficient, however ROS1 is not supported.
* Not all Rosbridge operations supported, check compatability section below for more information.
For general information regarding the protocol, check Rosbridge protocol description.
Clone RWS into your workspace source directory:
cd your_workspace_dir/src
git clone https://github.com/v-kiniv/rws.git
# Build your workspace using colcon, as usualLaunch using launch script provided by the package:
# source your workspace
ros2 launch rws rws_server_launch.pyOr add rws_server node to your own launch script:
rws_server_node = Node(
package='rws',
executable='rws_server',
name='rws_server',
output='screen',
parameters=[{
# ...
}]
)port- port to use for websocket server.9090by default.rosbridge_compatible- enable compatibility with rosbridge protocol. Currently the only difference is that stamp->nanosec field in all messages will be renamed to stamp->nsec.Trueby default.watchdog- use ping/pong to detect and drop unresponsive clients that keep TCP connection open.Trueby default.
| Operation | RWS | Rosbridge | Description |
|---|---|---|---|
| advertise | + | + | Advertise topic |
| unadvertise | + | + | Stop advertising topic |
| publish | + | + | Publish to topic |
| subscribe | + | + | Subscribe to topic |
| unsubscribe | + | + | Unsubscribe from topic |
| call_service | + | + | Call service (with timeout support) |
| advertise_service | + | + | Advertise external service |
| unadvertise_service | + | + | Stop advertising external service |
| service_request | - | + | Request to external service |
| service_response | + | + | Response from external service |
| send_action_goal | + | + | Send action goal (with feedback) |
| cancel_action_goal | + | + | Cancel action goal |
| advertise_action | - | + | Advertise action server |
| unadvertise_action | - | + | Stop advertising action server |
A subscribe message may include an optional qos object with a durability
field to explicitly set the subscriber's QoS durability:
| Value | Meaning |
|---|---|
"transient_local" |
Request latched delivery. The subscriber receives the publisher's retained sample even if it subscribes before the publisher is discovered. |
"volatile" |
Force volatile delivery (no retained samples). |
| (omitted) | Auto-match the durability of an already-discovered publisher (default, legacy behavior). |
{ "op": "subscribe", "topic": "/latched_topic", "type": "std_msgs/msg/String", "qos": { "durability": "transient_local" } }Only qos.durability is currently honored; other QoS fields are ignored.
Use "transient_local" for genuinely latched topics. Without it, a subscriber that
connects before the publisher is discovered is created volatile and silently misses
the retained sample (a discovery race). A "transient_local" request will not
connect to a volatile publisher, so only set it on topics that are actually latched.
Message fragmentation is not supported in RWS
| Format | RWS | Rosbridge | Notes |
|---|---|---|---|
| JSON | + | + | Default format |
| CBOR-RAW | - | + | Not supported |
| CBOR | - | + | Not supported |
| PNG | - | + | Not supported |
Note: RWS only supports JSON encoding. Binary formats (CBOR, CBOR-RAW, PNG compression) are not supported.
Unlike Rosbridge, RWS does not expose /rosapi node, all rosapi related API requests are handled internally in rws_server node.
RWS is using websocketpp, asio and RapidJSON. These 3 libraries will be fetched by CMake during configuration step.
In my experiece, Rosbridge does not work well with the second version of ROS. Seems like Rosbridge developers mainly focused on ROS1 support, and ROS2 is handled on a best effort basis(for example, check this issue). I'm experiencing severe memory leaks(~1 GB of memory per day), high CPU usage, on a device like Raspberry Pi it's a problem. It's also not very stable and sometimes crashes if multiple clients reconnect rapidly. My first intention was to fix ROS2 support in Rosbridge. I started by collecting all non-merged fixes from other people and trying to add my own, some progress was made, but the server was still CPU hungry(even though less leaky and more stable), so I decided that C++ is more appropriate than Python, for this kind of task.
Here is the data from htop command output from a Raspberry Pi 4B(4GB version) running the following stack:
- ROS2 Galactic
- Rosbridge(as of this commit) node
- iRobot Create 2 nodes
- Lidar driver node(RPLidar A1)
- IMU driver node(BNO055)
Client is a Mac running Ventura and Foxglove Studio(v1.32.0) subscibed to 7x20Hz and 3x1Hz topics(plots with IMU data, odometry, etc.).
| Process | CPU Usage | Memory Usage(initial) |
|---|---|---|
| rosbridge_server | 57.4% | 59 MB |
| rws_server | 12.8% | 18 MB |
This is not a benchmark by any means, and is intended to demostrate that there is a difference in performance with my setup. I encourage you to try RWS with your setup and draw conslusion based on that.