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
Conway’s Game of Life, a.k.a., Life, is a cellular automaton developed by the mathematician, John Conway in 1970. Life consists of a 2D grid of cells, whith each cell having a state of alive or dead. A cell’s state may change from one generation to the next according to three simple rules.
- 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.
I’ve already mentioned that the program uses the ROS 2 OccupancyMap for modeling the cellular world. Let’s take a look at the OccupancyMap definition which is defined as part of the
info field of type
MapMetaData. MapMetaData (shown below) defines the grid dimensions on the
data field as well as cell orientation and scale.
The project will consist of the following:
- ROS 2 node, named
- 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 =
- rviz2 will provide visualization of the cellular world
Create the project folder and change directory into it:
mkdir -p 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.
- 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.
From the project root folder run the TypeScript compiler. The output will appear in the
Our game-of-life program runs in 2 processes that we will start individually.
First, launch the game-of-life node from a command shell:
Once the program starts you should see messages dribble to stdout with information about the current generation number and number of alive cells.
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’;
I hope you’ve had fun developing your version of Conway’s Game of Life. You may consider additional improvements to your version such as parameterizing the occupancy-map size or using a predefined grid of cells rather than random cell states.
2. Source code
Please consider liking this tutorial and following me here and on Twitter @ros2jsguy