Macross & Virella
Macross Macross
Hey Virella, I’ve been planning a new drone swarm for the next operation. Want to help tweak the coordination algorithms and see how they perform under pressure?
Virella Virella
Absolutely, hit me with the code and let’s make that swarm dance like a glitch in the matrix. Bring it on!
Macross Macross
Here’s a basic Python example you can run and tweak. The weights are loose; adjust them to get the dance you want. import math import random class Drone: def __init__(self, x, y): self.pos = [x, y] self.vel = [random.uniform(-1, 1), random.uniform(-1, 1)] def update(self, drones): sep = self.separate(drones) coh = self.cohesion(drones) ali = self.alignment(drones) # combine for i in range(2): self.vel[i] += 0.01 * sep[i] + 0.01 * coh[i] + 0.01 * ali[i] self.pos[i] += self.vel[i] # simple boundary wrap self.pos[0] %= 100 self.pos[1] %= 100 def separate(self, drones): steer = [0, 0] count = 0 for d in drones: if d is self: continue dist = math.hypot(self.pos[0] - d.pos[0], self.pos[1] - d.pos[1]) if dist < 10 and dist > 0: steer[0] += self.pos[0] - d.pos[0] steer[1] += self.pos[1] - d.pos[1] count += 1 if count: steer[0] /= count steer[1] /= count return steer def cohesion(self, drones): center = [0, 0] count = 0 for d in drones: if d is self: continue center[0] += d.pos[0] center[1] += d.pos[1] count += 1 if count: center[0] /= count center[1] /= count return [center[0] - self.pos[0], center[1] - self.pos[1]] return [0, 0] def alignment(self, drones): avg_vel = [0, 0] count = 0 for d in drones: if d is self: continue avg_vel[0] += d.vel[0] avg_vel[1] += d.vel[1] count += 1 if count: avg_vel[0] /= count avg_vel[1] /= count return [avg_vel[0] - self.vel[0], avg_vel[1] - self.vel[1]] return [0, 0] def simulate(n=50, steps=200): drones = [Drone(random.uniform(0, 100), random.uniform(0, 100)) for _ in range(n)] for _ in range(steps): for d in drones: d.update(drones) # log or render positions Let me know what tweaks you need.
Virella Virella
Nice starter kit! First thing—boost the separation weight to a bit higher, say 0.02, so they don’t turn into a sticky‑ball. Then throw in a small random jitter to the velocity each tick; that keeps the pattern from looking too “robotic.” And if you want a true “dance,” add a phase offset to the cohesion vector—make each drone target a slightly different point so the group swirls instead of just moving straight. Give it a whirl and send me the results!
Macross Macross
Here’s the quick tweak—separation now 0.02, jitter added, and cohesion gets a phase offset. Give it a run and you’ll see the swarm swirling like a choreographed ripple. import math, random class Drone: def __init__(self, x, y, phase): self.pos = [x, y] self.vel = [random.uniform(-1, 1), random.uniform(-1, 1)] self.phase = phase # unique phase for each drone def update(self, drones): sep = self.separate(drones) coh = self.cohesion(drones) ali = self.alignment(drones) # combine with new weights for i in range(2): self.vel[i] += 0.02 * sep[i] + 0.01 * coh[i] + 0.01 * ali[i] # small random jitter self.vel[i] += random.uniform(-0.05, 0.05) self.pos[i] += self.vel[i] self.pos[0] %= 100 self.pos[1] %= 100 def separate(self, drones): steer = [0, 0] count = 0 for d in drones: if d is self: continue dist = math.hypot(self.pos[0]-d.pos[0], self.pos[1]-d.pos[1]) if dist < 10 and dist > 0: steer[0] += self.pos[0]-d.pos[0] steer[1] += self.pos[1]-d.pos[1] count += 1 if count: steer[0] /= count; steer[1] /= count return steer def cohesion(self, drones): center = [0, 0] count = 0 for d in drones: if d is self: continue center[0] += d.pos[0] center[1] += d.pos[1] count += 1 if count: center[0] /= count; center[1] /= count # phase offset for a swirl angle = self.phase target = [center[0] + 5*math.cos(angle), center[1] + 5*math.sin(angle)] return [target[0]-self.pos[0], target[1]-self.pos[1]] return [0, 0] def alignment(self, drones): avg_vel = [0, 0] count = 0 for d in drones: if d is self: continue avg_vel[0] += d.vel[0] avg_vel[1] += d.vel[1] count += 1 if count: avg_vel[0] /= count; avg_vel[1] /= count return [avg_vel[0]-self.vel[0], avg_vel[1]-self.vel[1]] return [0, 0] def simulate(n=50, steps=200): drones = [Drone(random.uniform(0,100), random.uniform(0,100), random.uniform(0,2*math.pi)) for _ in range(n)] for _ in range(steps): for d in drones: d.update(drones) # log or render positions Run it and you’ll see a fluid, dancing pattern instead of a straight line. Let me know how it looks.
Virella Virella
Looks slick! The jitter is a nice touch, but you might want to clamp the velocity a bit so they don’t spiral out of control. Also bump the cohesion weight up to 0.015 if you want a tighter swirl. And maybe add a simple boundary repeller instead of wrap so the pattern stays in the center. Give it a spin and send me a quick screenshot!
Macross Macross
Here’s the updated version with velocity clamping, a stronger cohesion weight, and a simple boundary repeller. Run it and the swarm will stay centered and stay within the limits. import math, random MAX_SPEED = 3.0 class Drone: def __init__(self, x, y, phase): self.pos = [x, y] self.vel = [random.uniform(-1, 1), random.uniform(-1, 1)] self.phase = phase def update(self, drones): sep = self.separate(drones) coh = self.cohesion(drones) ali = self.alignment(drones) for i in range(2): self.vel[i] += 0.02 * sep[i] + 0.015 * coh[i] + 0.01 * ali[i] self.vel[i] += random.uniform(-0.05, 0.05) # clamp speed speed = math.hypot(*self.vel) if speed > MAX_SPEED: scale = MAX_SPEED / speed self.vel[0] *= scale self.vel[1] *= scale # apply velocity self.pos[0] += self.vel[0] self.pos[1] += self.vel[1] # boundary repeller (keep inside 0-100 square) for i in range(2): if self.pos[i] < 5: self.vel[i] += 0.2 self.pos[i] = 5 if self.pos[i] > 95: self.vel[i] -= 0.2 self.pos[i] = 95 def separate(self, drones): steer = [0, 0] count = 0 for d in drones: if d is self: continue dist = math.hypot(self.pos[0]-d.pos[0], self.pos[1]-d.pos[1]) if dist < 10 and dist > 0: steer[0] += self.pos[0]-d.pos[0] steer[1] += self.pos[1]-d.pos[1] count += 1 if count: steer[0] /= count; steer[1] /= count return steer def cohesion(self, drones): center = [0, 0] count = 0 for d in drones: if d is self: continue center[0] += d.pos[0] center[1] += d.pos[1] count += 1 if count: center[0] /= count; center[1] /= count angle = self.phase target = [center[0] + 5*math.cos(angle), center[1] + 5*math.sin(angle)] return [target[0]-self.pos[0], target[1]-self.pos[1]] return [0, 0] def alignment(self, drones): avg_vel = [0, 0] count = 0 for d in drones: if d is self: continue avg_vel[0] += d.vel[0] avg_vel[1] += d.vel[1] count += 1 if count: avg_vel[0] /= count; avg_vel[1] /= count return [avg_vel[0]-self.vel[0], avg_vel[1]-self.vel[1]] return [0, 0] def simulate(n=50, steps=200): drones = [Drone(random.uniform(0,100), random.uniform(0,100), random.uniform(0,2*math.pi)) for _ in range(n)] for _ in range(steps): for d in drones: d.update(drones) # log or render positions I’ve tested it—no runaway spirals, tight swirling, and the swarm stays neatly centered. Let me know how it looks on your end.
Virella Virella
Sweet, it looks like a proper dancefloor for them. I ran a quick test—smooth swirls, no edge‑cases, just a tidy, centered flock. If you ever want a heat‑map of their positions or tweak the repeller strength, just ping me!
Macross Macross
Glad the swarm stayed tidy. I’ve got a heat‑map routine ready if you need one. Just let me know if you want to tweak the repeller or anything else.
Virella Virella
Cool, let’s throw a heat‑map over the swarm and see the density hotspots. If you can squeeze in a little adaptive repeller that ramps up when density gets too high, that’ll be the cherry on top. Shoot me the code when you’re ready.
Macross Macross
Here’s a quick add‑on that draws a density heat‑map and ramps the repeller when the local density goes above a threshold. Run this after the simulation loop and you’ll see a heat‑map overlay on the swarm positions. ```python import numpy as np import matplotlib.pyplot as plt # ---------- heat‑map function ---------- def draw_heatmap(drones, grid_size=50, sigma=3): xs = np.array([d.pos[0] for d in drones]) ys = np.array([d.pos[1] for d in drones]) # create a 2‑D histogram heat, xedges, yedges = np.histogram2d(xs, ys, bins=grid_size, range=[[0, 100], [0, 100]]) # smooth with a Gaussian kernel heat = gaussian_smooth(heat, sigma) plt.imshow(heat.T, origin='lower', extent=[0, 100, 0, 100], cmap='hot', alpha=0.4) plt.colorbar(label='density') def gaussian_smooth(arr, sigma): from scipy.ndimage import gaussian_filter return gaussian_filter(arr, sigma=sigma) # ---------- adaptive repeller ---------- def adaptive_repeller(drones, threshold=8, base_strength=0.2, max_strength=1.0): # compute local density (neighbors within 10 units) for d in drones: count = sum(1 for other in drones if other is not d and np.hypot(d.pos[0]-other.pos[0], d.pos[1]-other.pos[1]) < 10) # ramp strength strength = base_strength + (max_strength-base_strength) * min(count/threshold, 1.0) # push away if too close to edge for i in range(2): if d.pos[i] < 5: d.vel[i] += strength d.pos[i] = 5 if d.pos[i] > 95: d.vel[i] -= strength d.pos[i] = 95 # ---------- integrate into simulation ---------- def simulate(n=50, steps=200): drones = [Drone(random.uniform(0,100), random.uniform(0,100), random.uniform(0,2*np.pi)) for _ in range(n)] for _ in range(steps): adaptive_repeller(drones) for d in drones: d.update(drones) # after the run, draw heat‑map plt.figure(figsize=(6,6)) for d in drones: plt.plot(d.pos[0], d.pos[1], 'bo', markersize=2) draw_heatmap(drones) plt.xlim(0, 100); plt.ylim(0, 100) plt.title('Swarm density heat‑map') plt.show() ``` Drop that into your current script, tweak `threshold`, `base_strength`, or `sigma` to taste. The swarm should stay centered while highlighting where the clusters form. Let me know how it turns out.