5: ROS 2 Version of Conway’s Game of Life in TypeScript

Implement Conway’s Game of Life using ROS 2 OccupancyMap and rviz2 for visualization.

As a fun project to help me get familiar with the ROS 2 OccupancyMap message, I coded up Conway’s Game of Life algorithm using an OccupancyMap to model the cellular automaton world. In this article I describe the high-level details of my Game of Life implementation.

The program is implemented using TypeScript and the Nodejs rclnodejs package. ROS 2 rviz2 is used to visualize the occupancy-maps published by the program. If you would like to jump straight to building and running my version, the source code is available here.

Game of Life Rules

  1. Any alive cell with two or three neighbors (adjacent cells) survives to the next generation.

2. Any dead cell with three neighbors becomes a live cell in the next generation.

3. All other live cells die in the next generation. Similarly, all other dead cells stay dead.

See the Resources section below for more info about Conway’s Game of Life.

OccupancyMap Message

Note the info field of typeMapMetaData. MapMetaData (shown below) defines the grid dimensions on the data field as well as cell orientation and scale.

Project Details

  • ROS 2 node, named /ros2_js_examples/game_of_life
  • ROS 2 100x100 OccupancyMap will represent the cellular world
  • ROS 2 Timer will provide a tick every 500 milliseconds (2 Hz) that initiates the transition of the current world to the next generation
  • ROS 2 publisher will broadcast the updated OccupancyMap for each generation, topic = game_of_life
  • rviz2 will provide visualization of the cellular world
  • This program is implemented as a Nodejs application coded using TypeScript and the ROS 2 rclnodejs JavaScript client library.

Code

mkdir -p src/example4
cd src/example4

The project consists of 2 TypeScript files: index.ts and game-of-life.ts. To minimize redundant code narration I’ve tried to include liberal comments throughout the code as shown below.

Some key things to notice in the code:

  • The occupancy-map cell states are ALIVE = 100, DEAD = 0.
  • A ROS2 Timer is used rather than the more common setInterval() JavaScript function. This is because the ROS2 Timer is based on it’s parent node’s clock which can be configured to use simulated time and controlled externally.
  • To minimize memory the program uses only 2 data arrays: an array to hold the previous generation of cell states and an array to hold for the current generation of cell states. Also a single occupancy-map instance is created and updated on each new generation with the current generation of cell state data.

index.ts

game-of-life.ts

Build

tsc

Running game-of-life

First, launch the game-of-life node from a command shell:

node dist/example4/index.js

Once the program starts you should see messages dribble to stdout with information about the current generation number and number of alive cells.

Next run rviz2 to view the occupancy-maps published by the game-of-life node:

rviz2 -d src/example4/game-of-life.rviz

You should see an rviz2 window appear similar to the following:

If you need to reconfigure the rviz2 display or use ros2 CLI tools you will need the following information:

NODE_NAME = ‘game_of_life_node’;
NODE_NAMESPACE = ‘ros2_js_examples’;
TOPIC = ‘game_of_life’;
FRAME_ID = ‘game_of_life_frame’;

Wrap-up

References

2. Source code

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

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