Привет, Хабр! Сегодня мы погрузимся в увлекательный мир роевого интеллекта и децентрализованных систем. Я покажу, как простые правила, заложенные в каждый элемент системы, позволяют добиться сложного группового поведения без единого центра управления. В качестве полигона используем виртуальный рой автономных дронов.

*Код и симуляция: Python 3.8+, matplotlib, numpy

Проблема централизованного управления

Представьте, что вам нужно координировать движение 50 дронов. Первое, что приходит в голову — центральный контроллер с нейронной сетью, которая вычисляет оптимальные траектории для каждого аппарата. Но у этого подхода есть фундаментальные недостатки:

  • Единая точка отказа — выход контроллера из строя парализует всю систему

  • Вычислительная сложность — задача O(n²) и выше для n агентов

  • Низкая отказоустойчивость — потеря связи с одним дроном может нарушить весь план

  • Плохая масштабируемость

Альтернатива? Децентрализованное управление, где каждый дрон принимает решения самостоятельно, основываясь лишь на информации от ближайших соседей.

Три кита роевого интеллекта

В основе нашего подхода лежат три простых правила, вдохновленных поведением стай птиц и косяков рыб:

1. Избегание столкновений

Самый приоритетный rule: не врезаться в соседей.

# Упрощенная логика отталкивания

if dist < self.desired_distance:
    repulsion = True
    
    k = (self.desired_distance / dist)*3
    
    dx = drone.x - n.x
    dy = drone.y - n.y
    
    repulsion_x += (dx / dist) * k
    repulsion_y += (dy / dist) * k

Обратите внимание на кубическую зависимость (**3) — чем ближе сосед, тем сильнее отталкивание. Это создает "буфер безопасности" вокруг каждого дрона.

2. Сплочение группы

Если соседи слишком далеко — приближаемся к ним, поддерживая целостность группы:

# Упрощенная логика сплолчения группы

if dist > self.desired_distance * 1.2:
    k = k * self.desired_distance / (dist - self.desired_distance)
    
    dx = n.x - drone.x
    dy = n.y - drone.y
    
    attraction_x += k * dx / dist
    attraction_y += k * dy / dist

Ближайшие соседи более приоритетны, что обеспечивается знаменателем коэффициента.

3. Движение к цели

Каждый дрон знает общую цель (в нашем случае — координаты [0,0]) и постепенно смещается к ней:

dist = np.sqrt((drone.x- target.x) ** 2 + (drone.y - target.y) ** 2)

if dist > 0:
    striving_x = - drone.x * k 
    striving_y = - drone.y * k

Архитектура системы

Давайте разберем основные компоненты нашей симуляции:

Класс Drone — кирпичик роя

class Drone:
    def __init__(self, id, x=0, y=0):
        self.id = id
        
        self.x = x
        self.y = y
        
        self.vx = 0
        self.vy = 0
        
        self.radius = 0.3
        
        self.active = True

Каждый дрон знает только свою позицию и статус. Никакой информации о глобальной структуре!

Swarm — emergent intelligence

Класс Swarm не управляет дронами напрямую. Вместо этого он обеспечивает среду для их взаимодействия.

Дальность локально взаимодействия дронов ограничена параметром self.neighbor_radius:

def find_neighbors(self, drone):
    """Возвращает список ближайших активных дронов"""
    
    neighbors = []
    
    for d in self.drones:
        if d.active and d != drone:
            if drone.distance_to(d) < self.neighbor_radius:
                neighbors.append(d)
                
    return neighbors

В пределах этого радиуса соседние дроны считаются частью группы.

Эмерджентное поведение в действии

Что удивительно — из простых локальных правил рождается сложное глобальное поведение:

  • Самоорганизация — изначально случайное расположение быстро структурируется

  • Адаптивность — при потере дронов система автоматически перестраивается

  • Устойчивость — даже при выходе 30% дронов из строя группа продолжает движение

В коде выход из строя моделируется простым механизмом отказов:

def simulate_failure(self):
    for drone in self.drones:
        if drone.active and random.random() < self.failure_rate:
            drone.active = False

Визуализация: наблюдаем за происходящим

Класс Visio позволяет в реальном времени наблюдать ход моделирования:

class Visio:
    def __init__(self, swarm):
        self.swarm = swarm
        
        # Настройка визуализации
        self.fig, self.ax = plt.subplots(figsize=(12, 8))
        self.ax.set_xlim(-20, 20)
        self.ax.set_ylim(-20, 20)
        self.ax.set_title("Рой дронов: автономное перестроение")
        self.ax.set_xlabel("X")
        self.ax.set_ylabel("Y")

        self.drone_dots = self.ax.plot([], [], 'bp', 
                                       markersize=8, 
                                       alpha=0.6, 
                                       label='Активные дроны')[0]
        
        self.failed_dots = self.ax.plot([], [], 'ks', 
                                        markersize=4, 
                                        alpha=0.3, 
                                        label='Потерянные дроны')[0]

        self.obstacle_dots = self.ax.plot(
            [o[0] for o in swarm.obstacles],
            [o[1] for o in swarm.obstacles],
            'rx', markersize=10, label='Опасный район'
        )[0]
        
        self.target_dots = self.ax.plot([0], [0], 'gx', 
                                        markersize=10, 
                                        label='Целевой район')[0]
        
        self.ax.legend()

        self.ani = FuncAnimation(self.fig, 
                                 self.animate, 
                                 frames=2000, 
                                 init_func=self.start, 
                                 blit=True, 
                                 interval=1)

        
    def start(self):
            self.drone_dots.set_data([], [])
            self.failed_dots.set_data([], [])
            return self.drone_dots, self.failed_dots

          
    def animate(self, frame):
            self.swarm.update()

            active_x, active_y = [], []
            failed_x, failed_y = [], []

            for drone in self.swarm.drones:
                if drone.active:
                    active_x.append(drone.x)
                    active_y.append(drone.y)
                else:
                    failed_x.append(drone.x)
                    failed_y.append(drone.y)

            self.drone_dots.set_data(active_x, active_y)
            self.failed_dots.set_data(failed_x, failed_y)

            return self.drone_dots, self.failed_dots

self.swarm - объект класса Swarm

self.swarm.update() - метод, реализует логику трех правил, описанных выше.

На анимации вы увидите, как:

  • Дроны самоорганизуются из хаотичного облака в структурированную группу

  • Группа обтекает препятствия без централизованного планирования

  • Потерянные дроны (черные квадраты) остаются на месте, а живые продолжают движение

Рой двигается к цели, обходя опасные районы и сохраняя дистанции
Рой двигается к цели, обходя опасные районы и сохраняя дистанции
Рой соблюдает принципы своего построения и адаптируется даже после потери 30% дронов
Рой соблюдает принципы своего пос��роения и адаптируется даже после потери 30% дронов

Практическое применение

Описанный подход не просто академическое упражнение. Он может применяться в:

  • Сельском хозяйстве — рои дронов для мониторинга полей

  • Поисково-спасательных операциях — покрытие больших территорий

  • Логистике — доставка грузов группами дронов

  • Охрана и наблюдение — наблюдение на объекте с подвижных камер

Что можно улучшить?

Наша симуляция — лишь первый шаг. В реальных системах нужно учитывать:

  1. Коммуникационные задержки — в реальности информация передается не мгновенно

  2. Ограниченный обзор — дроны «видят» не идеально

  3. Энергетические ограничения — время автономной работы

  4. Динамические препятствия — движущиеся объекты

Заключение

Роевой интеллект демонстрирует удивительный принцип: сложное поведение не требует сложного управления. Простые правила, выполняемые на локальном уровне, создают робастные системы, устойчивые к сбоям и адаптивные к изменениям.

Код из статьи — упрощенная иллюстрация, но он позволяет уловить суть подхода. Главное — не конкретные коэффициенты (их нужно подбирать под задачу), а сам принцип децентрализованного управления.

А вы сталкивались с роевыми системами на практике? Делитесь опытом в комментариях!

Комментарии (7)


  1. Wizard_of_light
    24.11.2025 07:25

    Клеточные автоматы на физическом железе.


  1. aax
    24.11.2025 07:25

    Python, при всем его удобстве, да пригоден лишь для симуляции. Но никак для выполнения критичных по времени задач в системах реального времени, тем более с железом в виде типичного одноплатника на дроне.


  1. MAXH0
    24.11.2025 07:25

    Забавное приложение:

    «Системы оружия двадцать первого века, или Эволюция вверх ногами»

    хотя начинать стоит, конечно же с «Непобедимый»

    Но я настоятельно рекомендую к прочтению в нынешних реалиях именно "Системы..."


  1. VAF34
    24.11.2025 07:25

    Хотелось бы поиграть на своем ПК, но показаны только фрагменты. Класса Swarm не увидел.


  1. ncix
    24.11.2025 07:25

    сложное поведение не требует сложного управления.

    Верно, но сложное поведение само по себе не создает способности к решению сложных задач.


  1. shlmzl
    24.11.2025 07:25

    А вы сталкивались с роевыми системами на практике? Делитесь опытом в комментариях!

    Навряд ли у того, кто столкнулся с роевыми системами на практике, получится потом поделиться опытом в комментариях.


    1. MAXH0
      24.11.2025 07:25

      С биологическими - запросто...