Перейти к содержанию

Правила и допущения расчёта

Как Аэрозвено на самом деле строит план: какие правила действуют на каждом шаге, какие числа зашиты в расчёт и что сознательно не моделируется. Все значения сверены с кодом текущего выпуска. Если значение — умолчание, которое можно поменять в сценарии, указано поле.

Режимы расчёта на публичном стенде

Настройка Значение на стенде Что значит
Модель разворотов arc самолётные борта разворачиваются по дуге, мультироторы — на месте
Поиск угла галсов full, 8 процессов угол уточняется целыми планами, параллельно
Профиль взлёта и посадки legacy взлёт 30 с и посадка 60 с в точке площадки; катапульта, парашют, разбег по полосе и глиссада не строятся
Цифровая модель рельефа не подключена запас над рельефом не проверяется, в плане — предупреждение TERRAIN_UNKNOWN

Режимы переключаются настройками сервиса (PLANNER_TURN_MODEL, PLANNER_ANGLE_SEARCH, PLANNER_ANGLE_WORKERS, PLANNER_PROFILE_MODEL, PLANNER_DEM_DIR); ниже описано поведение кода во всех режимах.

Порядок расчёта

  1. Проверить сценарий по схеме и убедиться, что требуемый GSD достижим хотя бы одним бортом.
  2. Для каждого участка отобрать борта: подходящая нагрузка, допустимый ветер, заряд, температура.
  3. Рассчитать высоту съёмки из GSD и камеры, шаг галсов из перекрытий.
  4. Обрезать участок разрешённым пространством и бесполётными зонами на высоте съёмки.
  5. Выбрать угол галсов, построить галсы.
  6. Назначить галсы бортам по критерию и упорядочить обход.
  7. Нарезать работу на вылеты по запасу хода с резервом, проложить перелёты в обход зон.
  8. Посчитать метрики, учесть площадки и запасные АКБ, при запросе — развести борты.
  9. Уточнить угол галсов целыми планами и оставить лучший.

Схема конвейера — в Архитектуре.

Высота съёмки и GSD

Высота из GSD. Для камер (RGB, мультиспектр, ИК): H = GSD / k, где k — коэффициент нагрузки из справочника, а если его нет — ширина матрицы / (фокусное расстояние × ширина кадра в пикселях). Для камер со сменным объективом фокусное расстояние берётся из fleet[].focal_length_mm.

Нагрузка Высота при GSD 3 см
камера PF1B (Gemini) ≈ 153 м
камера борта 201 ≈ 233 м
  • Лидар: H = частота сканирования / (плотность точек × V × 2·tg(FOV/2)), V — крейсерская воздушная скорость. Геофизика: 50 м над землёй с ограничением пределами борта.

  • Если расчётная высота ниже минимальной или выше максимальной для борта, борт исключается из участка (ALTITUDE_BELOW_MIN, ALTITUDE_ABOVE_MAX, ALTITUDE_ASL_ABOVE_MAX) — высота не прижимается к пределу, чтобы не нарушить требуемый GSD. Если GSD недостижим ни одним бортом, расчёт отклоняется с GSD_UNREACHABLE.

  • Высота выше 150 м — не отказ, а флаг и предупреждение ALT_ABOVE_150M: для работ нужно разрешение на ИВП. Интерфейс предлагает ослабить GSD.

Покрытие и галсы

Отпечаток кадра: поперёк галса ширина матрицы × H / f, вдоль — высота матрицы × H / f (длинная сторона матрицы — поперёк галса).

Шаг галсов: отпечаток поперёк × (1 − поперечное перекрытие); для лидара — ширина полосы сканирования × (1 − перекрытие); для геофизики — quality.line_spacing_m. При боковом ветре шаг уменьшается в cos β раз, где sin β = W⊥ / Vₐ — угол сноса (краба), чтобы перекрытие сохранилось.

Интервал съёмки: отпечаток вдоль × (1 − продольное перекрытие) / путевая скорость.

Перекрытия по умолчанию (если в участке не заданы overlap_forward_frac / overlap_side_frac):

Тип съёмки Продольное Поперечное
RGB 70 % 60 %
Мультиспектр 80 % 75 %
ИК 80 % 75 %
Лидар — 30 %

Нарезка:

  • Участок = area ∩ разрешённое пространство − (зоны + буфер) на высоте съёмки; куски меньше 1 м² отбрасываются. Вырезы в полигоне учитываются.

  • Галсы параллельны, первый — на половине шага от края, направление чередуется «змейкой». Если участок уже половины шага — один галс посередине. Галс короче четверти шага не строится.

  • Добор покрытия: если полосы захвата покрывают меньше 99,5 % участка, добавляются короткие галсы (не короче 5 м), затем концы галсов выносятся за границу на 0,25 / 0,5 / 1 половины полосы — если это позволяют пространство и зоны.

  • Смешанный парк: борта группируются по шагу и высоте. Маленький участок (сторона меньше 6 шагов) целиком отдаётся одной группе с самым мелким шагом. Крупный режется на полосы поперёк галсов пропорционально производительности групп; группа берёт только то, до чего дотягивается (радиус — 70 % запаса хода туда и обратно), остаток — самой дальнобойной.

Угол галсов

Если в участке задан angle_deg, он используется как есть. Иначе угол выбирается в два шага.

1. Быстрая оценка. Для каждого угла оценивается время галсов с учётом ветра плюс время разворотов. При ≤ 4 участках перебирается каждый градус 0…179°, при большем числе — шаг 5° и уточнение по 1° в ±4° от лучшего. Выбирается минимум времени среди углов, у которых суммарная длина галсов не меньше 90 % максимальной.

2. Уточнение целыми планами. Быстрая оценка не видит подлёт к участку и нарезку на вылеты, поэтому после первого плана для каждого участка считаются полные планы по кандидатам угла:

Правило Значение
Кандидатов на участок до 8: направления 4 самых длинных сторон, 2 направления «площадка → участок», 3 лучших угла быстрой оценки (разнесённых не меньше чем на 10°)
Соседи лучшего ±5°
Совпадающие углы ближе 0,25° считаются одним
Принять кандидата план есть, нарушений не больше, покрытие не хуже более чем на 0,0005, выигрыш по критерию больше 0,1 %
Остановка по застою 4 отклонённых кандидата подряд
Бюджет времени уточнение — не больше 50 % лимита, весь расчёт — не больше 90 % лимита; не успели — ANGLE_SEARCH_TRUNCATED
Когда не уточняется угол задан вручную; участков больше 4; в первом плане больше 400 галсов на участке; пересчёт после выбытия борта
Параллельность кандидаты считаются пулом процессов (PLANNER_ANGLE_WORKERS, по умолчанию — по числу ядер, не больше 8); при сбое пула — последовательно

Выбранный угол и таблица всех кандидатов с их критерием, покрытием и числом вылетов видны в «Протоколе решений» на экране плана.

Развороты

Режим задаёт objective.turn_mode: lzp — с выходом на ЛЗП (по умолчанию) или flyby — пролётом.

Самолётные борты (201, Penguin B) разворачиваются по дуге — кратчайшей кривой Дубинса:

Правило Значение
Радиус R = (V + W)² / (g · tg φ) плюс запас 5 %; ветер прибавляется целиком, g = 9,81 м/с²
Крен φ 30° (допущение: в документации производителя не указан)
Пример борт 201 (крейсерская 27,8 м/с) в штиль — ≈ 143 м; при ветре 5 м/с — ≈ 199 м
Выравнивание перед галсом 4 с прямого полёта (в режиме lzp); у 201 ≈ 111 м
Время разворота длина дуги / крейсерская воздушная скорость
Через сколько галсов разворачиваться ceil(2R / шаг) — если шаг меньше диаметра, борт заходит на галс через один или несколько

Мультироторы (Gemini, 801) разворачиваются на месте: 8 с в режиме lzp, 5 с — пролётом; между галсами — прямая.

Развороты у зон и границы. Дуга не должна заходить в зону с буфером и за разрешённое пространство. Порядок попыток: кратчайшая кривая → другие виды кривой → вынос разворота от торцов шагом 50 м до 500 м → укорочение обоих галсов шагом 25 м до 300 м. Если остаток галса короче четверти шага — галс выбрасывается (TRANSECT_TOO_SHORT); если разворот не помещается — вылет завершается, галс уходит в следующий вылет (TURN_BLOCKED). Проверяются до 5 следующих галсов в очереди. Мультиротор не выносится и не укорачивается.

Вход на первый галс вылета и сход с последнего — по прямой перелёта, без дуги.

Перелёты, бесполётные зоны и граница пространства

Правило Значение
Буфер от зон 25 м (objective.safety_buffer_m); при нарезке и прокладке берётся с запасом буфер × 1,02 + 0,5 м
Вертикальный запас зона действует на высотах altitude_min − 50 м … altitude_max + 50 м (objective.zone_vertical_margin_m)
Обход стороной на любой высоте objective.avoid_zones_laterally = true
Прокладка перелёта кратчайший путь по графу видимости вокруг зон (вершины контура упрощены с допуском 10 м и отнесены на 5 м), в рамке ±5 км вокруг участков и площадок
Пути нет прямая и предупреждение NFZ_DETOUR_NOT_FOUND
Площадка внутри зоны на высоте борта вылет с неё невозможен (SITE_IN_NO_FLY_ZONE)
Часть участка вне разрешённого пространства не снимается, покрытие считается от доступной части; предупреждение TASK_OUTSIDE_AIRSPACE при доле ≥ 0,1 %

Граница разрешённого пространства на перелётах

Граница airspace.allowed вырезает площадь съёмки и проверяется у разворотов, но перелёты и возвраты её не обходят — обход строится только вокруг зон. Если перелёт вышел за границу, план получает нарушение airspace и статус «нерешаемо», а валидатор — G1-02. Помогает площадка внутри пространства или граница пошире.

Время действия зон (valid_from, valid_to), вид зоны (zone_kind) и общий пол и потолок пространства (floor_m, ceiling_m) в расчёте не используются: все зоны считаются запретными постоянно.

Энергия, вылеты и оборот

Бюджет вылета: запас хода × (1 − резерв) × холодовой коэффициент.

Составляющая Значение
Резерв 20 % (objective.energy_reserve)
Запас хода: борт 201 180 мин
Запас хода: Gemini, 801 40 мин
Запас хода: Penguin B (топливо) бак 7,5 л / расход 0,375 л/ч = 20 ч
Холод (только АКБ, ниже 0 °C) −1 % ёмкости на градус, но не меньше 50 % (weather.temperature_c); предупреждение BATTERY_COLD
Температура вне рабочего диапазона модели борт исключается
Заряд перед первым вылетом (fleet[].battery_left_frac) бюджет первого вылета × заряд; заряд не выше резерва — борт не участвует (UAV_LOW_CHARGE); не хватает на первый галс — борт заряжается перед первым вылетом

Длительность вылета = взлёт + перелёт + галсы и развороты + возврат + заход + посадка. Галсы считаются с ветром, перелёт, возврат и заход — по крейсерской воздушной скорости без ветра.

Нарезка на вылеты: галс берётся в вылет, если после него хватает бюджета на возврат, заход и посадку. Если первый галс вылета не помещается, он делится, когда помещается хотя бы 25 % его длины; иначе галс остаётся нераспределённым (endurance_exceeded). Возврат — к ближайшей подходящей площадке.

Где садиться между вылетами. Для каждого борта считаются два варианта — всегда «домой» и «на ближайшую подходящую площадку» — и берётся лучший по критерию. Борт взлетает оттуда, где сел. Резервная площадка (reserve: true) принимает только последнюю посадку.

Оборот между вылетами:

Ситуация Время на земле
Домашняя площадка turnaround_time_min площадки (по умолчанию 10 мин)
Другая площадка с запасной АКБ этой модели оборот площадки
Другая площадка без запасной АКБ большее из оборота и времени зарядки (Gemini — 105 мин)
Топливный борт большее из оборота и заправки (Penguin B — 15 мин)

Запасные АКБ (spare_batteries) и места обслуживания (service_slots) учитываются после раскладки: они только сдвигают вылеты по времени, если АКБ или места заняты. Каждые 50 запусков борта выдаётся предупреждение о ТО (MAINTENANCE_DUE).

Ветер

  • Ветер постоянный по району и высоте: weather.wind_speed_ms и wind_direction_deg (откуда дует).
  • Путевая скорость: Vg = √(Vₐ² − W⊥²) + W∥. Если поперечная составляющая не меньше воздушной скорости — CROSSWIND_EXCEEDS_AIRSPEED; если путевая скорость не положительна — HEADWIND_EXCEEDS_AIRSPEED.

  • Время галса = половина длины по ветру + половина против ветра — направление пролёта конкретного галса на время не влияет.

  • Предел ветра: борт с wind_max меньше ветра сценария в расчёт не идёт. Борт 201 — 12 м/с; Gemini, 801, Penguin B — 10 м/с.

  • Ветер учитывается в шаге галсов (снос), радиусе дуги, выборе курса полосы и в точке захода (с подветренной стороны).

  • Если ветер в сценарии не задан (0 м/с), интерфейс может подставить прогноз Open-Meteo на высоте 120 м над землёй; источник подписан под значением.

Рельеф

Рельеф берётся из цифровой модели рельефа (сетка Copernicus GLO-30, модель поверхности — с лесом и постройками), с билинейной интерполяцией. Все высоты плана — над землёй (AGL).

Правило Значение
Галс идёт на постоянной высоте над рельефом: точки излома — по упрощению профиля с допуском 10 м, выборка 30 м
Перелёт, возврат, заход (правило TER-06) профиль проверяется шагом 10 м; если запас над рельефом меньше 50 м (с допуском 1 м), весь этап поднимается на недостающую величину
Глиссада (при расчётном профиле) запас не меньше min(50 м, половина высоты глиссады), шаг 30 м; иначе APPROACH_TERRAIN
Нет данных рельефа предупреждение TERRAIN_UNKNOWN; расчёт идёт без рельефа

Валидатор независимо проверяет запас 50 м над рельефом по всему маршруту (G2-04). Развороты между галсами, взлёт и посадка по рельефу не поднимаются; время набора на поднятых этапах не учитывается.

Площадки, взлёт, посадка и полосы

Профиль legacy (на стенде). Взлёт — 30 с в точке площадки, посадка — 60 с. Заход — через две точки с подветренной стороны в 200 м и 100 м от площадки на крейсерской скорости.

Расчётный профиль computed (включается настройкой сервиса):

Тип Взлёт Посадка
Мультиротор вертикальный набор с его скороподъёмностью вертикальное снижение (801, Gemini — 3 м/с)
Борт 201 с катапульты по курсу площадки (takeoff_heading_deg) или против ветра; если курс закрыт зоной — перебор ±5…±30° шагом 5°; весь сектор закрыт — TAKEOFF_SECTOR_BLOCKED на парашюте: спираль до 70 м, затем спуск 5 м/с; точка раскрытия смещена против ветра на снос
Penguin B разбег по полосе, набор по курсу полосы заход по глиссаде 3° на скорости 16,9 м/с, пробег 100 м

Полоса (launch_sites[].runway): длина и курс считаются по торцам. Направление взлёта и посадки — с большей встречной составляющей ветра; если заход закрыт зоной — обратное (APPROACH_REVERSED) или отказ (APPROACH_BLOCKED). Если полоса домашней площадки короче потребной для борта (у Penguin B — 45 м на взлёт и 150 м на посадку), борт в расчёт не идёт (RUNWAY_TOO_SHORT) — эта проверка работает в любом профиле.

Площадки фильтруют борта по типу (suitable_for: multirotor, fixed_wing).

Разведение бортов

Поле separation запроса POST /api/plans: none (по умолчанию), time или altitude.

Режим Как работает
Поиск сближений (всегда) два борта одновременно ближе 300 м по горизонтали и 50 м по высоте, выборка каждые 2 с, без взлёта и посадки → предупреждение UAV_ENCOUNTER
time каждый следующий борт сдвигается целиком шагом 30 с до 30 мин, пока сближения не исчезнут (иначе — вариант с минимумом сближений)
altitude k-й борт поднимает перелёт, возврат и заход на k × 50 м; съёмка остаётся на своей высоте; если выше потолка или в слое зоны — SEPARATION_ALTITUDE_UNAVAILABLE

Назначение галсов и критерии

Критерий (objective.criterion) Что минимизируется Как назначаются галсы
makespan — время работ (по умолчанию) время до окончания работы последнего борта эвристика балансировки: каждому галсу — самый «дешёвый» борт, затем переносы по одному галсу, пока уменьшается максимальная загрузка
total_flight_time — суммарный налёт сумма длительностей всех вылетов та же эвристика, но уменьшается сумма загрузок
pareto взвешенная сумма времени работ и налёта с весом lambda_frac смешанно-целочисленная модель (OR-Tools)

Для сравнения двух критериев используйте экран «Мультикритериальный анализ»: он строит фронт Парето между временем работ и суммарным налётом.

Порядок обхода галсов у борта: для самолётных — лучший из шаблонов («змейка», переходы через один и несколько галсов, зеркальные и обратные) и решения OR-Tools по длинам кривых Дубинса (до 150 галсов); для мультироторов — задача коммивояжёра в OR-Tools с двумя стартовыми стратегиями, каждый галс можно пройти в любом направлении.

makespan_s — максимум по бортам конца последнего вылета, включая обороты; total_flight_time_s — сумма длительностей вылетов.

Точного решения задачи маршрутизации нет: планировщик — эвристика с локальным улучшением, гарантии оптимальности нет. Качество видно по сравнению с «наивным делением» на экране плана и по вариантам в «Протоколе решений».

Лимит времени расчёта и остановка

Правило Значение
Лимит по умолчанию 300 с (режим «Точно» в интерфейсе; «Быстро» — 30 с)
Максимум 1800 с (30 мин); больше — ошибка 400
Командная строка планировщика 30 с по умолчанию
Распределение времени назначение и порядок галсов — до 60 % лимита; уточнение угла — до 50 %, весь расчёт — до 90 %
Дедлайн внутреннего вызова лимит + 30 с

«Остановить и взять лучший план» (POST /api/plans/{id}/stop). Остановка срабатывает на этапе уточнения угла: расчёт возвращает лучший найденный к этому моменту план с предупреждением STOPPED_BY_OPERATOR. Первый план остановка не прерывает — он досчитывается. Если уточнения угла нет (угол задан, участков больше 4, пересчёт после выбытия борта), расчёт идёт до конца. Задание, ещё стоящее в очереди, завершается без плана.

Воспроизводимость. Одинаковые сценарий, критерий, лимит и зерно (solver.seed, по умолчанию 42) дают одинаковый план.

Когда план считается нерешённым

План получает статус infeasible (и в интерфейсе — ошибку расчёта), если:

  • покрытие меньше 99 %, или в каком-то участке не снято больше 10 000 м² (1 га);
  • маршрут заходит в зону или за границу разрешённого пространства больше чем на 0,01 м.

Нераспределённые галсы попадают в unassigned[] с кодом причины (см. Работа с файлами). Независимо от статуса планировщика план проверяет валидатор: 39 проверок, допуск — только без нарушений и без проверок fail.

Что не моделируется

Не учитывается Следствие
Порывы ветра, изменение ветра с высотой, турбулентность ветер постоянный; gust_ms сохраняется, но не влияет
Ветер на перелётах, возврате, заходе и в разворотах их время — по воздушной скорости
Реальная энергетика (Вт·ч), зависимость расхода от скорости, ветра, набора высоты и висения бюджет вылета — по паспортному времени полёта с резервом
Время набора на поднятых этапах (рельеф, разведение по высоте) этап поднимается целиком, время не меняется
Время действия и вид зон, общий пол и потолок пространства все зоны запретны постоянно
Обход границы разрешённого пространства на перелётах выход за границу — нарушение, не обход
available_from борта и временные окна участков в расчёте окна проверяет только валидатор (G5-05)
Боковой ветер на полосе проверяет только валидатор (G5-11)
Коридорная съёмка (ЛАФС) протяжённые объекты снимаются параллельными галсами
Подъём галсов над рельефом галс идёт на постоянной высоте над землёй
Лидар и геофизика в серийном парке в справочнике нет совместимых носителей; расчёт поддерживает эти типы для демо-нагрузок
Оптимальное решение задачи маршрутизации эвристика, без гарантии оптимума
NOTAM, зоны из внешних систем, подача плана зоны задаёт оператор; сервис только готовит полётные задания
Исполнение плана в полёте и телеметрия Аэрозвено — планировщик, не наземная станция

Какие поля сценария на что влияют

Стадия Поля
Высота, GSD, шаг, кадры tasks[].survey_type, quality, overlap_forward_frac, overlap_side_frac; fleet[].model, payload, focal_length_mm, enabled; launch_sites[].elevation_m
Участок, зоны, граница tasks[].area; airspace.allowed; airspace.no_fly[].geometry, altitude_min_m, altitude_max_m; objective.safety_buffer_m, zone_vertical_margin_m, avoid_zones_laterally
Угол галсов tasks[].angle_deg; objective.criterion, lambda_frac; положения площадок
Развороты objective.turn_mode; ветер
Энергия и вылеты objective.energy_reserve; weather.temperature_c; fleet[].battery_left_frac, home; launch_sites[].turnaround_time_min, spare_batteries, service_slots, suitable_for; landing_sites[].reserve
Взлёт и посадка launch_sites[].takeoff_heading_deg, runway (при расчётном профиле; длина полосы — всегда)
Назначение и порядок objective.criterion, lambda_frac; solver.seed
Время time_limit_s запроса или solver.time_limit_s; start_time (отметки времени вылетов)
Не влияют на план weather.gust_ms, airspace.floor_m, ceiling_m, no_fly[].zone_kind, valid_from, valid_to, fleet[].available_from, tasks[].time_window