Swarm
Multi-threaded simulation of swarming and flocking behavior written in Java
Overview
Ever since I learned about Conway’s Game of Life, I have always been fascinated by simulations.
Complex behaviors emerging from a simple set of rules.
I wanted to explore multi-core processors with hyperthreading.
A simulation of thousands of independent agents following a set of behaviors is a great way to scratch that itch.
Java, AWT, and Eclipse to the rescue.
GitHub
Source code is available in the HC Swarm GitHub repository.
Inspiration
Boids is the primary inspiration for HC Swarm.
Around since 1986 (Go Mets!), Boids lays out three basic rules each independent agent follows:
- separation: steer to avoid crowding local flockmates
- alignment: steer towards the average heading of local flockmates
- cohesion: steer towards the average position (center of mass) of local flockmates
All you really need is some basic trigonometry and vector math, and some really fun behaviors emerge.
Download and Run
To run HC Swarm for yourself, simply clone the repository (or download the .zip) from GitHub.
Change directory to the top level of the repo.
Preferred: If you have maven
, run mvn compile
(there’s no dependencies or packaging, just a compile)
Alternate 1: Load the directory in as a project in Eclipse and let her do all the work. That’s how I usually run it since I frequently have Eclipse open for something else anyways.
Alternate 2: If you don’t have maven
, then javac
…
javac com/hedgecourt/swarm/*.java com/hedgecourt/swarm/impl/*.java com/hedgecourt/swarm/gui/*.java
Then to run the program…
java com.hedgecourt.swarm.gui.App
Configuration
Configuration is in com.hedgecourt.swarm.SwarmConfig.java
, you’ll need to recompile after changing it.
Most notable things to configure for a different machine than my PC:
- SWARM_PANEL_WIDTH - set to the pixel size you like on your monitor
- SWARM_PANEL_HEIGHT - ditto
- EXECUTION_THREAD_COUNT - You can fiddle with this, but good place to start is (number of CPU )* (number of cores) * (threads per core)
Rule Weights
For each agent, a set of rules is applied for each iteration of the simulation. The separation, alignment, and cohesion rules taken from Boids, and a few more described below.
Each rule is applied in isolation and generates a velocity vector based on that rule only. The final velocity that gets applied for the iteration is the weighted average of all the rules-based values.
Playing with the weights in the config lets you experiment with lots of fun different behaviors.
To keep things simple, the velocity is normalized (i.e. constant speed / magnitude) and only the direction is updated each round.
Field Boundaries
In HC Swarm, the agents live within a rectangular space. When the encounter a wall, they reflect off the wall using high school physics “angle in equals angle out”.
Very fun to watch as a lead member of a local pack encounters the wall, reflects off it, and effectively steers the remaining flock away from the wall entirely. OR sometimes not and the whole pack bounces off the wall. Love watching the various behaviors unfold.
Wall Flowers
Sometimes a single agent or small pack gets on a heading very close to a wall, nearly perfectly parallel to it. I call them wall flowers.
If there are enough agents in the simulation, eventually a wall flower will encounter someone else and shift course enough to break free.
I found myself not enjoying wall flowers so I built in a rule that if you spend too much time near the wall you get a boot up your fanny in the form of a random heading nudge away from the wall.
Predator
I added a predator to spice things up a little bit. One agent is designated as the predator.
Two new rules were added to avoid the predator. One steers you away from the predator’s position. The other steers you away from the heading (velocity direction) of the predator.
Just like the rules described above, these get averaged in using weights, very much like in real life how we take a whole variety of factors into making decisions.
Lots of fun watching a pack split apart as the predator goes down the middle, only to have the cohesion rule kick in and bring the pack together once the predator is past.
I was out in real life bird watching recently and saw exactly the same behavior in a flock of sea gulls as a bald eagle approached and passed by. Love it when real life and simulations align.
Future Considerations
Better Config
The current config is hardcoded in static fields in a config Java class. Works fine for my desktop tinkering, stinky for rolling out to other users. I’d like to replace it with something more robust. Even a simple properties file will do. I could scale it up to an editor class in the GUI for changes live on the fly, which would be fantastic for tweaking rule weights.
N-Body Algorithm
The main loop of HC Swarm brute forces its way through all the independent agents. For example, to figure out a new heading based on a local neighborhood, the distance to every other agent is calculated in order to determine who is in the local neighborhood. The performance is Big-O Squared, which is rubbish but works fine for my little simulation.
To increase the efficiency and therefore the upper limit of how many agents can be placed in the field, N-Body algorithm is suitable. Modifying the loop to use an N-Body approach is on the product backlog, should I open up development of this project again.
Speed, Momentum, and Acceleration
In the current implementation, there is no real world physics applied. For example, real swarm members have mass and momentum and limits on how fast they can turn or how much acceleration they can handle.
If I open up development, I’d like to put in at least some basic speed changes on top of the current direction changes. Bonus points for switching it over to force calculations rather than velocity calculations, and let each rule produce a weighted force to apply to a given agent, and then simply simulate basic physics of force applied to mass to build the resulting new velocity.
Conclusion
Super fun project. Got to play with Java, AWT, multithreading, rules-based simulation, object oriented programming.
And I get to relax, watching my little specks fly all around the screen, emerging lots of different behaviors.