– FLOCKING ALGORITHM, in recipe format

output_ZrvG8i

.HOW IT WORKS:


(code is for processing and I used Daniel Shiffman’s Flocking example to brake it down; although the concept  and principles should be applicable in any of programming languages)

There are  three simple rules of flocking behaviors:
alignment,  cohesion, and separation, 
which when used in combination display the full flocking behavior.
Lets see what happens there.

.

ALIGMENT:

00 aligment

A behavior that causes a particular boid to line up with boids close by.
We iterate through all of the boids and find the ones within the neighbor radius – that is, those close enough to be considered neighbors of the specified boid. If boid is found within the radius, its velocity is added to the computation vector, and the neighbor count is incremented.

PVector align (ArrayList<Boid> boids) {
float neighbordist = 50;
PVector sum = new PVector(0, 0);
int count = 0;
for (Boid other : boids) {
float d = PVector.dist(location, other.location);
   if ((d > 0) && (d < neighbordist)) {                                    //why do we need (d > 0)?
      sum.add(other.velocity);
      count++;
}
}

Than we divide the computation vector by the neighbor count and normalize it (divide it by its length to get a vector of length, obtaining the final resultant vector. And of course, we will not do step above if there are no neighbors, and we will simply return zero vector (0,0).

if (count > 0) {
   sum.div((float)count);                                                  // why do we need to div if we use .setMag after?
   sum.setMag(maxspeed);
   PVector steer = PVector.sub(sum, velocity);
   steer.limit(maxforce);
   return steer;
   } else {
   return new PVector(0, 0);
}

01

0203040607

.

.

COHESION

00 cohesion

Cohesion is a behavior that causes boids to steer towards thecenter of mass” – that is, the average position of the boids within a certain radius.

The implementation is almost identical to that of the alignment behavior, but there are some key differences. First, instead of adding the velocity to the computation vector, the position is added instead.

Like before, the computation vector is divided by the neighbor count, resulting in the position that corresponds to the center of mass. However, we don’t want the center of mass itself, we want the direction towards the center of mass, so we recompute the vector as the distance from the boid to the center of mass. Finally, this value is normalized and returned.

PVector cohesion (ArrayList<Boid> boids) {
float neighbordist = 50;
PVector sum = new PVector(0, 0);            // Start with empty vector to accumulate all locations
int count = 0;
for (Boid other : boids) {
   float d = PVector.dist(location, other.location);
   if ((d > 0) && (d < neighbordist)) {
   sum.add(other.location);                     // Add location
   count++; }
}
   if (count > 0) {
   sum.div(count);
   return seek(sum);                                   // Steer towards the location
} else {
return new PVector(0, 0);
}}

.

.

SEPARATION

00 separation

Separation is the behavior that causes an boid to steer away from all of its neighbors.

The implementation of separation is very similar to that of alignment and cohesion. When a neighboring boid is found, the distance from the boid to the neighbor is added to the computation vector. The computation vector is divided by the corresponding neighbor count, but before normalizing, there is one more crucial step involved. The computed vector needs to be negated in order for the boid to steer away from its neighbors; and we do that by subtracting target location from our boid’s location.

PVector diff = PVector.sub(location, other.location);               //not  .sub(other.location ,location);

.

.

STEER VECTOR     // Steering = Desired minus Velocity

   PVector desired = PVector.sub(target, location);      // A vector pointing from the location to the target
   // Scale to maximum speed
   desired.setMag(maxspeed);

   PVector steer = PVector.sub(desired, velocity);
   steer.limit(maxforce);                                           // Limit to maximum steering force
   return steer;

.

.

.

After getting the principles of the algorithm, this is what we should do in processing to make it work:

00. MAKE OUR GUYS and Pvect variables

// The Flock (an array of Boid objects)
flock = new Flock();
// Add an initial set of boids into the system
   for (int i = 0; i < 150; i++) {
    flock.addBoid(new Boid(width/2,height/2));
}

PVector location;
PVector velocity;
PVector acceleration;
float r;

01. ASIGN THESE RULS TO EACH BOID with magic numbers :

void flock(ArrayList<Boid> boids) {
   PVector sep = separate(boids);    // Separation
   PVector ali = align(boids);              // Alignment
   PVector coh = cohesion(boids);   // Cohesion
   // Arbitrarily weight these forces            // magic numbers for forces to work nicely
   sep.mult(1.5);
   ali.mult(1.0);
   coh.mult(1.0);
   // Add the force vectors to acceleration
   applyForce(sep);
   applyForce(ali);
   applyForce(coh);
}

02. CONNECT THEM AND APPLY through acceleration vector:   

void applyForce(PVector force) {
acceleration.add(force);
}

// Method to update location
void update() {
   // Update velocity
   velocity.add(acceleration);
   // Limit speed
   velocity.limit(maxspeed);
   location.add(velocity);
   // Reset accelertion to 0 each cycle
   acceleration.mult(0);
}

.

.

.

complete Daniel Shiffman flocking example and code : here :

code for processing sketch that post begins with : here :

huge png presentation file here :

.

.

nema1.1393556708192

Advertisements

Comments are closed.