Dispersion
In this example of dispersion, we've used the Lennard Jones Potential to achieve a uniform dispersion of robots which are clustered. The potential used in this experiment utilizes virtual forces to either pull or push the robot towards or away from each other. As shown in the pictures below, dispersion is used in a cluster of 12 robots. Once the dispersion is applied, each robot is equidistant to one another due to the Lennard Jones Potential.
Lennard Jones Potential Calculation
function lj_magnitude(dist, target, epsilon) { return -(epsilon / dist) * ((target / dist)^4 - (target / dist)^2) }
The function lj_magnitude()
calculates the magnitude of the Lennard Jones Potential
using the distance of each neighbour, dist
, following the equation:
$$V(r) = frac{A}{r^{12}}- dfrac{B}{r^6}$$
TARGET = 500.0 EPSILON = 150.0 # Neighbor data to LJ interaction vector function lj_vector(rid, data) { return math.vec2.newp(lj_magnitude(data.distance, TARGET, EPSILON), data.azimuth) }
The function lj_vector()
creates a new vector from the magnitude calculated in lj_magnitude()
and the azimuth of the robot. The vector calculation is done using
math.vec2.newp()
.
function lj_sum(rid, data, accum) { return math.vec2.add(data, accum) }
The function lj_sum()
is a simple addition function which uses math.vec2.add()
to calculate
v1 + v2.
Dispersion()
function disperse() { # Calculate accumulator var accum = neighbors.map(lj_vector).reduce(lj_sum, math.vec2.new(0.0, 0.0)) if(neighbors.count() > 0) math.vec2.scale(accum, 1.0 / neighbors.count()) # Move according to vector goto(accum.x, accum.y) }
In the function disperse()
, neighbours.map()
calculates the magnitude of virtual force of each neighbour.
These values are then summed into an accumulator vector accum
using neighbours.reduce()
. After which, the accumulator vector is
scaled with math.vec2.scale()
before feeding it in to the goto()
function which translates the scaled accumulator vector to movement.