Розробка AI-системи автономної навігації дронів без GPS

Політ у тунелі, між будівлями, всередині складу або під глушилками — стандартна ситуація, коли GPS ловить 2 супутники або нуль. Дрон без зовнішнього позиціонування йде в дрифт і через 10 секунд врізається в стіну. Особливо критично для дорогих комерційних апаратів. Ми вирішуємо такі завдання на кожн

Напрямки AI-розробки

Часті запитання

Останні роботи

  • image_website-b2b-advance_0.webp
    Розробка сайту компанії B2B ADVANCE
    1441
  • image_web-applications_feedme_466_0.webp
    Розробка веб-додатків для компанії FEEDME
    1301
  • image_websites_belfingroup_462_0.webp
    Розробка веб-сайту для компанії БЕЛФІНГРУП
    998
  • image_ecommerce_furnoro_435_0.webp
    Розробка інтернет магазину для компанії FURNORO
    1267
  • image_logo-advance_0.webp
    Розробка логотипу компанії B2B Advance
    714
  • image_crm_enviok_479_0.webp
    Розробка веб-додатків для компанії Enviok
    1006

Політ у тунелі, між будівлями, всередині складу або під глушилками — стандартна ситуація, коли GPS ловить 2 супутники або нуль. Дрон без зовнішнього позиціонування йде в дрифт і через 10 секунд врізається в стіну. Особливо критично для дорогих комерційних апаратів. Ми вирішуємо такі завдання на кожному другому проєкті: від інспекції мостів до логістики на складах 10000 м². Розробляємо системи автономної навігації під ключ — від вибору сенсорів до відмовостійкого софту. Оцінимо ваше завдання за 3 робочі дні.

Розробка AI-системи автономної навігації дронів: чому без GPS не обійтися?

VIO — це злиття даних з камери та IMU. Камера дає візуальні орієнтири, IMU — кутові швидкості та прискорення. Алгоритм (наприклад, VINS-Mono або ORB-SLAM3) оптимізує спільну помилку. На практиці це дає точність 5–15 см у горизонтальній площині при хорошому освітленні. Код нижче — спрощена ілюстрація циклу: детектуємо ORB-фічі, зіставляємо, відновлюємо рух через essential matrix та інтегруємо з IMU.

import numpy as np import cv2 from scipy.spatial.transform import Rotation class VisualInertialOdometry: """ VINS-Mono / ORB-SLAM3 логіка — спрощено. На практиці використовуємо готові бібліотеки з ROS2 інтеграцією. """ def __init__(self, camera_matrix: np.ndarray, imu_noise: dict): self.K = camera_matrix self.orb = cv2.ORB_create(nfeatures=500) self.matcher = cv2.BFMatcher(cv2.NORM_HAMMING, crossCheck=True) self.prev_frame = None self.prev_kp = None self.prev_desc = None # Стан: позиція + орієнтація self.position = np.zeros(3) self.rotation = np.eye(3) self.imu_noise = imu_noise def update(self, frame: np.ndarray, imu_data: dict) -> dict: """Оновлення оцінки позиції по кадру + IMU""" gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) kp, desc = self.orb.detectAndCompute(gray, None) if self.prev_frame is not None and desc is not None: matches = self.matcher.match(self.prev_desc, desc) matches = sorted(matches, key=lambda x: x.distance)[:100] if len(matches) > 20: pts1 = np.float32([self.prev_kp[m.queryIdx].pt for m in matches]) pts2 = np.float32([kp[m.trainIdx].pt for m in matches]) E, mask = cv2.findEssentialMat(pts1, pts2, self.K, method=cv2.RANSAC, prob=0.999, threshold=1.0) if E is not None: _, R, t, _ = cv2.recoverPose(E, pts1, pts2, self.K) # Інтеграція руху self.position += self.rotation @ t.flatten() self.rotation = R @ self.rotation self.prev_frame = gray self.prev_kp = kp self.prev_desc = desc if desc is not None else self.prev_desc return { 'position': self.position.copy(), 'rotation': self.rotation.copy(), 'tracked_features': len(kp) if kp else 0 } 

Як обходити перешкоди без лідара?

Для indoor-польотів стереокамера (Intel RealSense D435) дає щільну карту глибини з частотою 30 кадрів/с і споживає всього 2 Вт. LiDAR (наприклад, Velodyne Puck) дає точніше, але коштує $4000+ і важить 400 г — не кожен дрон підніме. Наш стек використовує стерео як базовий сенсор і опціонально додає ToF-камеру для outdoor. Алгоритм нижче ділить поле зору на 5 секторів і обчислює мінімальну відстань у кожному — цього достатньо для collision avoidance зі швидкістю до 2 м/с.

Сенсор Роздільна здатність по глибині Дальність Споживання Вага Вартість
Intel RealSense D435 1280x720 px до 10 м 2 Вт 72 г $300
Velodyne Puck (LiDAR) 360° x 30° до 100 м 8 Вт 400 г $4000
ToF-камера (L515) 1024x768 px до 9 м 3 Вт 100 г $350
class ObstacleAvoidance: def __init__(self, depth_camera, safety_distance: float = 1.5): self.depth_cam = depth_camera self.safety_dist = safety_distance # метри self.fov_h = 87 # градусів (RealSense D435) self.sectors = 5 # ділимо поле зору на 5 секторів def compute_clear_directions(self, depth_frame: np.ndarray) -> dict: """Знаходимо вільні напрямки польоту""" h, w = depth_frame.shape sector_width = w // self.sectors clearance = {} for i in range(self.sectors): sector = depth_frame[:, i*sector_width:(i+1)*sector_width] # Ігноруємо нульові значення (немає даних) valid = sector[sector > 0] if len(valid) == 0: clearance[i] = float('inf') continue # P10 — ближня границя перешкоди в секторі min_dist = float(np.percentile(valid, 10)) / 1000.0 # мм -> м clearance[i] = min_dist # Напрямок з максимальним clearance best_sector = max(clearance, key=clearance.get) angle = (best_sector - self.sectors // 2) * (self.fov_h / self.sectors) return { 'clearance_by_sector': clearance, 'best_direction_angle': angle, 'is_path_clear': clearance[self.sectors//2] > self.safety_dist } 

Планування маршруту: 3D Occupancy Grid vs. RRT*

Occupancy grid — детермінований метод: кожну комірку (0.2 м³) позначаємо як вільну або зайняту. A* гарантує найкоротший шлях у дискретному просторі. Для динамічних перешкод краще підходить RRT*, але він дає неоптимальне по довжині рішення. Ми комбінуємо: на етапі побудови карти — occupancy grid, а для перепланування в реальному часі — RRT* з limit на 100 ітерацій. Код нижче — класичний A* на sparse grid.

import heapq class OccupancyGridPlanner: def __init__(self, resolution: float = 0.2): self.resolution = resolution # метрів на комірку self.grid = {} # 3D sparse grid: (ix, iy, iz) -> occupancy def update_from_depth(self, depth_frame: np.ndarray, camera_pose: np.ndarray): """Оновлюємо карту перешкод""" # Конвертація depth в point cloud points = self._depth_to_pointcloud(depth_frame) # Трансформація в світові координати points_world = (camera_pose[:3, :3] @ points.T).T + camera_pose[:3, 3] for pt in points_world: ix, iy, iz = (int(pt[0] / self.resolution), int(pt[1] / self.resolution), int(pt[2] / self.resolution)) self.grid[(ix, iy, iz)] = 1 # occupied def astar_3d(self, start: tuple, goal: tuple) -> list: """A* в 3D occupancy grid""" def heuristic(a, b): return np.sqrt(sum((a[i]-b[i])**2 for i in range(3))) heap = [(0, start)] came_from = {start: None} cost = {start: 0} while heap: _, current = heapq.heappop(heap) if current == goal: break for dx, dy, dz in [(1,0,0),(-1,0,0),(0,1,0), (0,-1,0),(0,0,1),(0,0,-1)]: neighbor = (current[0]+dx, current[1]+dy, current[2]+dz) if self.grid.get(neighbor, 0) == 1: continue # перешкода new_cost = cost[current] + 1 if neighbor not in cost or new_cost < cost[neighbor]: cost[neighbor] = new_cost priority = new_cost + heuristic(neighbor, goal) heapq.heappush(heap, (priority, neighbor)) came_from[neighbor] = current # Відновлюємо шлях path = [] node = goal while node is not None: path.append(node) node = came_from.get(node) return list(reversed(path)) 

Кейс з нашої практики: автономна інспекція складу 8000 м²

Наш клієнт — логістичний оператор, якому потрібно було щомісяця перевіряти стан стелажів на 4 поверхах. Висота стелажів до 12 м, вузькі проходи 2 м, повна відсутність GPS. Ми розробили дрон на базі DJI F450 з кастомним польотним контролером, оснащеним Intel RealSense D435i (глибина + IMU). Стек: ROS2 Humble + PX4 Autopilot + форк ORB-SLAM3 з EKF-фільтром для злиття з барометром.

Результат: точність локалізації ±8 см по горизонталі, ±5 см по вертикалі. Швидкість обльоту — 0.5 м/с, один ряд стелажів (50 м) проходить за 110 секунд. Система працює без збоїв вже більше року — 50+ місій.

Процес впровадження

Детальніше про калібрування сенсорів Калібрування камери та IMU виконується за допомогою Kalibr або власного скрипта. Потрібно кілька статичних поз з різною орієнтацією. В результаті отримуємо матрицю камери та коефіцієнти дисторсії, а також матрицю обертання між камерою та IMU. Типова точність після калібрування — помилка reprojection < 0.5 пікселя.
  1. Аналіз сценарію: виміри освітлення, геометрії, матеріалів (метал/бетон — різна відбивна здатність). Вибір сенсорів.
  2. Прототипування VIO: калібрування камери+IMU, підбір параметрів ORB (кількість фіч, threshold).
  3. Обхід перешкод: налаштування safety_distance, інтеграція depth в польотний контролер через MAVSDK.
  4. Планувальник: вибір між occupancy grid та RRT* під динаміку завдання.
  5. Тести: політ у симуляторі (Gazebo + PX4 SITL), потім реальні вильоти з дублюючим пультом.

Терміни та орієнтовна вартість

Тип проєкту Термін Коментар
Базова VIO навігація 6–10 тижнів Включає калібрування, тести, польотний контролер
Повна autonomous navigation (VIO + obstacle avoidance + planning) 3–5 місяців + Occupancy grid, RRT*, ROS2 integration
Сертифікація для комерційних польотів (опціонально) +3–6 місяців Залежить від регулятора (EASA, FAA)

Вартість розраховується індивідуально — залежить від складності сценарію та кількості ітерацій тестів. Окупність проєкту зазвичай настає протягом 6 місяців за рахунок зниження витрат на ручний контроль. Отримайте консультацію — оцінимо ваше завдання за 3 дні.

Що ви отримуєте

  • Вихідний код VIO-модуля з коментарями (Python/C++).
  • Docker-образ з ROS2-воркспейсом для відтворюваності.
  • Калібрувальні файли камери та IMU.
  • Інтеграція з польотним контролером (PX4/ArduPilot).
  • Документація з налаштування та експлуатації.
  • 2 місяці підтримки після впровадження.

Чому обирають нашу розробку?

Ми займаємося AI-навігацією для дронів більше 5 років: 20+ реалізованих проєктів для складів, шахт, мостів та нафтових вишок. Використовуємо лише open-source стеки (ORB-SLAM3, ROS2, PX4) — жодного vendor lock-in. Всі рішення тестуємо в симуляторі на 100+ сценаріях перед першим польотом. Зв'яжіться з нами — розповімо, які сенсори та алгоритми підійдуть саме під ваше завдання.