JBotSim 1.0-beta has been released with some API changes. All examples have been updated accordingly. Please make sure you are using version 1.0 beta.

Look, Compute, Move

Look, Compute, Move is a distributed computing paradigm for mobile robots. In every round, each robot performs the following operations:

  1. Look around (e.g. for the position of other robots)
  2. Make some computation (e.g. deciding where to go next)
  3. Move to a new location

This model is often seen as an alternative to message passing, although both could be used in combination. A subtlety is that, in general, this model is synchronous. In particular, it is assumed that, in every round, all LOOK operations are completed before any MOVE operation takes place.

JBotSim offers primitives that enable the execution of such synchronous algorithms. When extending class Node, in addition to method onClock(), one can also override methods onPreClock() and onPostClock(), with the guarantee that in each round, all onPreClock() network-wide are executed before any onClock(), and all onClock() network-wide are executed before any onPostClock().

Below is an example of algorithm that performs a probabilistic gathering. The LOOK step consists of reading the location of all nodes within sensing range. Note that we might have considered all of the nodes in the network, if we wanted to, rather than only those within sensing range, by using the getTopology().getNodes() method. The COMPUTE step consists of picking a random location among the locations of these nodes. The MOVE step consists of moving towards this location, by one unit of distance (or by the missing amount, if smaller than one unit).

import jbotsim.Node;
import jbotsim.Point;

import java.util.ArrayList;
import java.util.Random;

public class LCMNode extends Node{
    ArrayList<Point> locations;
    Point target;

    @Override
    public void onPreClock() {  // LOOK
        locations = new ArrayList<Point>();
        for (Node node : getSensedNodes())
            locations.add(node.getLocation());
    }
    @Override
    public void onClock(){      // COMPUTE
        if(!locations.isEmpty())
            target = locations.get((new Random()).nextInt(locations.size()));
    }
    @Override
    public void onPostClock(){  // MOVE
        if(target == null)
            return;

        setDirection(target);
        move(Math.min(1, distance(target)));
    }
}

The corresponding main() is as follows.

public static void main(String[] args) {
    Topology tp = new Topology();
    tp.setDefaultNodeModel(LCMNode.class);
    tp.disableWireless();
    tp.setSensingRange(100);
    tp.setClockSpeed(100);
    for (int i = 0; i<20; i++)
        tp.addNode(-1,-1);
    new JViewer(tp);
    tp.start();
}

Wireless links are globally disabled because robots act based on vision (here, within a radius of 100). Finally, the duration of a round is set to 100ms and twenty nodes are added at random locations.