ROS2/Gazebo на GPU: симуляция и реплеи

Задача страницы. Запустить и масштабировать симуляции ROS2/Gazebo на GPU в https://cloudcompute.ru для интерактива (SIL/HIL), генерации датасетов и детерминированных реплеев с понятной экономикой и наблюдаемостью.

TL;DR

  • GPU ускоряет визуальные сенсоры (RGB/Depth, семантика), радар/лидар трассировку и NVENC/AV1‑кодирование; физика — в основном CPU, поэтому балансируйте загрузку CPU↔GPU.
  • Два режима: On‑Demand (интерактив, SLA, низкая латентность) и Interruptible (массовая генерация/реплеи чанками ≤ 120 сек с ретраями и локальным NVMe‑кэшем).
  • Храните веса/миры/артефакты на NVMe, сырые бэги — «горячее», обработанные датасеты — «тёплое/холодное» (см. https://cloudcompute.ru/solutions/storage-data/).
  • Стриминг для операторов/дашбордов — SSE/WebSocket (пример ниже на FastAPI SSE, см. также https://cloudcompute.ru/solutions/gradio-fastapi/).
  • Наблюдаемость: p50/p95 кадра/снимка, FPS/FOV, drop rate, GPU util/HBM, NVENC latency, I/O backlog (см. https://cloudcompute.ru/solutions/monitoring-logging/).
  • Экономика: считайте Cost_per_1M_frames, Cost_per_1M_sweeps, Cost_per_camera от c_gpu, целевая загрузка U, скорость симуляции. Планируйте на https://cloudcompute.ru/solutions/cost-planner/.
  • Масштабирование: много сред на одной GPU, много GPU/нод с общим планировщиком и очередью задач (см. https://cloudcompute.ru/solutions/multi-gpu/).
  • Безопасность: ключи, приватные миры/карты/бэги, ретеншн, анонимизация (см. https://cloudcompute.ru/solutions/security/).

Сценарии

  • Интерактивная отладка алгоритмов восприятия/навигации: RViz/панель оператора, low‑latency поток камер/дальномеров.
  • SIL/HIL: подключение реальных контроллеров/драйверов к симу, эмуляция периферии, запись эталонных бэгов.
  • Генерация датасетов: массовые прогонки миров со стохастикой (погода, трафик, текстуры), экспорт в rosbag2 → конверсия в кадры/аннотации.
  • Регрессионные тесты: nightly реплеи критичных сцен (перекрёстки, узкие проходы, блеск/блики), сравнительные метрики.
  • Реалистичный рендер: глубина/нормали/семантика, мультимодальные пары (RGB‑Depth‑Seg).
  • Edge‑экспорт: сборка моделей и пакетов для целевых SoC (ONNX/TensorRT), см. https://cloudcompute.ru/solutions/triton-inference-server/.

Архитектуры/пайплайны A. Интерактивный контур (SIL/HIL, On‑Demand)

Оператор (RViz/Web) 
 ⇅ SSE/WebSocket
FastAPI Bridge (rclpy adapter)
 ⇅ ROS2 Topics/Services
Gazebo (GPU-сенсоры, рендер) ──> NVENC/AV1 ──> Видеопоток
 ⇅
rosbag2 (NVMe)

B. Массовая генерация/реплеи (Interruptible, чанки ≤ 120 сек)

Job Queue ──> N симуляторов (Docker)
 ├─ Gazebo headless + сенсоры
 ├─ rosbag2 write (NVMe "горячее")
 └─ Postprocess (кадры/аннотации) ──> "тёплое/холодное" хранилище
 ↑ (сводки метрик)
 Ретраи/резюме

C. Параллельные среды на нескольких GPU/нодах

Координатор/Планировщик
 ├─ Node1: GPU0 [Env×K] GPU1 [Env×K]
 ├─ Node2: GPU0 [Env×K] GPU1 [Env×K]
 └─ ...
Мониторинг: p50/p95, GPU util/HBM, I/O, drop rate

См. также общие принципы: https://cloudcompute.ru/solutions/performance-tuning/, https://cloudcompute.ru/solutions/throughput-vs-latency/, https://cloudcompute.ru/solutions/interruptible-patterns/.

Типовые профили GPU / VRAM / скорости

Ориентиры для одной GPU при целевой загрузке U≈0.7 и запасе VRAM ≥20%. Фактические цифры зависят от сцены/шейдеров/лидара.

**Профиль** **Видеопамять** **Типовая сцена** **Сенсорный пакет (пример)** **Типовая скорость** **Параллельные среды/GPU** **Режим**
**24 ГБ (Compact)** 24 ГБ город, 10–20 динамических акторов 2×RGB 1080p@60 + Depth 720p@60 + LiDAR 32‑beam@10Hz 55–60 FPS рендер; NVENC до 60 FPS 1–2 On‑Demand/Interruptible
**48 ГБ (Balanced)** 48 ГБ смешанные помещения/аутдор, сложные материалы 4×RGB 1080p@60 + 1×Seg 1080p@30 + 1×Depth 1080p@30 + 1×LiDAR 64‑beam@10Hz 50–60 FPS; кодирование 2–3 потоков 2–3 On‑Demand/Interruptible
**80 ГБ (HQ)** 80 ГБ насыщенные сцены, 4K рендер, много сенсоров 2×RGB 4K@30 + 2×RGB 1080p@60 + Depth 1080p@60 + 1×LiDAR 64‑beam@20Hz 30–45 FPS; кодирование 3–4 потоков 3–4 On‑Demand/Interruptible

Примечания:

  • Для headless‑пакетов (генерация) используйте offscreen‑рендер и запись напрямую в rosbag2 на NVMe.
  • Для NVENC учитывайте лимиты одновременных кодек‑сессий; распределяйте камеры по процессам.

Конфиги и скелеты кода

1) Docker Compose (ROS2 + Gazebo + rosbag2 + FastAPI Bridge)

version: "3.9"
services:
 sim:
 image: ghcr.io/your-org/ros2-gazebo:humble-cuda12
 # Замените на ваш образ с nvidia-container-toolkit
 runtime: nvidia
 deploy:
 resources:
 reservations:
 devices:
 - capabilities: [gpu]
 gpus: all
 environment:
 - RMW_IMPLEMENTATION=rmw_fastrtps_cpp
 - ROS_DOMAIN_ID=42
 - GZ_SIM_RESOURCE_PATH=/sim/worlds:/sim/models
 - USE_SIM_TIME=true
 volumes:
 - /data/nvme/bags:/bags
 - ./worlds:/sim/worlds:ro
 - ./models:/sim/models:ro
 - ./cfg:/cfg:ro
 command: >
 bash -lc "
 gz sim /sim/worlds/warehouse.sdf -r --headless-rendering &
 sleep 5 &&
 ros2 param load /camera /cfg/camera.yaml &&
 ros2 param load /lidar /cfg/lidar.yaml &&
 tail -f /dev/null
 "
 networks: [rosnet]
 bag:
 image: ghcr.io/your-org/ros2-tools:humble
 environment:
 - ROS_DOMAIN_ID=42
 volumes:
 - /data/nvme/bags:/bags
 command: >
 bash -lc "
 mkdir -p /bags/run_$(date +%F_%H-%M-%S) &&
 cd /bags/run_$(date +%F_%H-%M-%S) &&
 ros2 bag record
 /camera/left/image_raw
 /camera/right/image_raw
 /camera/depth
 /lidar/points
 --storage sqlite3 --max-bag-size 8192
 "
 networks: [rosnet]
 bridge:
 image: ghcr.io/your-org/fastapi-rclpy:py310
 environment:
 - ROS_DOMAIN_ID=42
 volumes:
 - ./bridge:/app
 command: uvicorn app.main:app --host 0.0.0.0 --port 8000
 ports: ["8000:8000"]
 networks: [rosnet]
networks:
 rosnet: {}

2) Пример параметров сенсоров (YAML)

# cfg/camera.yaml
camera:
 ros__parameters:
 width: 1920
 height: 1080
 fps: 60
 exposure_auto: true
 motion_blur: false
 hdr: false
 encoding: "rgb8"
# cfg/lidar.yaml
lidar:
 ros__parameters:
 channels: 64
 range: 120.0
 rotation_rate: 600.0 # rpm
 points_per_second: 1200000
 frame_id: "lidar_link"

3) Реплеи rosbag2

# Запись (уже в compose):
ros2 bag record /camera/left/image_raw /lidar/points --storage sqlite3
# Реплей (ускоренный/замедленный):
ros2 bag play /bags/run_2025-08-29_10-00-00 --rate 0.5 --clock --wait-for-all-acked

4) FastAPI SSE‑мост для ROS2

# bridge/app/main.py
import json, threading, queue
import rclpy
from rclpy.node import Node
from sensor_msgs.msg import Image, PointCloud2
from fastapi import FastAPI
from fastapi.responses import StreamingResponse
q = queue.Queue(maxsize=1024)
class Telemetry(Node):
 def __init__(self):
 super().__init__('telemetry_bridge')
 self.create_subscription(Image, '/camera/left/image_raw', self.on_image, 10)
 self.create_subscription(PointCloud2, '/lidar/points', self.on_lidar, 10)
 def on_image(self, msg):
 payload = {"topic": "image_left", "stamp": msg.header.stamp.sec, "w": msg.width, "h": msg.height}
 self._enqueue(payload)
 def on_lidar(self, msg):
 payload = {"topic": "lidar_points", "stamp": msg.header.stamp.sec, "points": msg.width * msg.height}
 self._enqueue(payload)
 def _enqueue(self, payload):
 try:
 q.put_nowait(json.dumps(payload))
 except queue.Full:
 self.get_logger().warn("SSE queue full, dropping message")
def ros_spin():
 rclpy.init()
 node = Telemetry()
 rclpy.spin(node)
 node.destroy_node()
 rclpy.shutdown()
app = FastAPI()
@app.get("/events")
def sse_events():
 def event_stream():
 while True:
 data = q.get()
 yield f"data: {data}nn"
 return StreamingResponse(event_stream(), media_type="text/event-stream")
t = threading.Thread(target=ros_spin, daemon=True)
t.start()
``` ## **Наблюдаемость, метрики, алерты**

Сводный набор (см. <https://cloudcompute.ru/solutions/monitoring-logging/> и <https://cloudcompute.ru/solutions/llm-inference/observability/>):

- **Производительность:
 
 - render\_fps (p50/p95), nvenc\_latency\_ms (p95), ros\_spin\_latency\_ms (p95)
 - bag\_write\_mb\_s, i/o\_backlog\_sec, dropped\_frames\_pct
- **GPU:** gpu\_util\_pct, gpu\_mem\_used\_gb, enc\_sessions, pcie\_tx\_mb\_s, sm\_efficiency\_pct
- **CPU/Физика:** physics\_step\_ms (p95), cpu\_load\_pct, runqueue\_len
- **Сенсоры:** camera\_fps, lidar\_hz, points\_per\_sweep, topic\_backlog
- **Сеть/Стриминг:** sse\_clients, stream\_rtt\_ms (p95), outbound\_mb\_s
- **Алерты (примеры):
 
 - VRAM &gt; 90% в течение 2 мин → снизить разрешение/частоту;
 - i/o\_backlog\_sec &gt; 5 сек → увеличить NVMe/снизить компрессию;
 - dropped\_frames\_pct &gt; 1% → перераспределить сенсоры/кодеки;
 - GPU util &lt; 30% при CPU &gt; 85% → CPU bottleneck (см. <https://cloudcompute.ru/solutions/performance-tuning/>).

## **Экономика и формулы**

Обозначения: c\_gpu — цена GPU/час; t\_sim\_h — длительность симуляции (часы); U — целевая загрузка GPU; F\_cam — кадры/сек/камера; N\_cam — количество камер; N\_env — параллельные среды; S\_lidar — свипы/сек/лидар; K\_retries — коэффициент ретраев (Interruptible).

**Кадры:**

Frames\_total = F\_cam \* N\_cam \* 3600 \* t\_sim\_h \* N\_env

Effective\_GPU\_cost = c\_gpu \* t\_sim\_h / U

Cost\_per\_1M\_frames = Effective\_GPU\_cost / (Frames\_total / 1\_000\_000)

**Лидар:**

Sweeps\_total = S\_lidar \* 3600 \* t\_sim\_h \* N\_env

Cost\_per\_1M\_sweeps = Effective\_GPU\_cost / (Sweeps\_total / 1\_000\_000)

**Стриминг одной камеры:**

Cost\_per\_camera\_hour ≈ (c\_gpu \* α\_render + c\_gpu \* α\_encode) / U

где α\_\* — доля загрузки GPU под рендер/кодек в профиле.

**Interruptible‑накладные:**

Cost\_interruptible ≈ Cost\_on\_demand \* (1 - δ\_price) \* (1 + K\_retries)

используйте https://cloudcompute.ru/solutions/cost-planner/ для подстановки ваших c\_gpu, U, N\_env, K\_retries.

**Безопасность и политики**

- **Ключи/токены** в переменных окружения/секретах контейнеров; не пишите их в бэги/логи (см. <https://cloudcompute.ru/solutions/security/>).
- **Приватные карты/модели/миры** — храните в отдельных приватных томах; ограничьте доступ командами/проектами.
- **PII/реальные бэги**: при микшировании с реальными данными — маскирование, ретеншн, аудит доступа.
- **Ретеншн**: бэги «горячие» ≤ 7–30 дней, затем выгрузка в «холодное» хранилище; хэши/манифесты — отдельно.
- **Политики прерывания**: для Interruptible — идемпотентные задачи, чекпоинты каждые ≤ 120 сек (см. <https://cloudcompute.ru/solutions/interruptible-patterns/>).

**Траблшутинг**

<table><tbody><tr><td>**Симптом**

</td><td>**Причина**

</td><td>**Решение**

</td></tr><tr><td>Черный экран при headless

</td><td>Неверный бэкенд рендеринга

</td><td>Включите offscreen/EGL в образе; проверьте переменные дисплея/драйвера.

</td></tr><tr><td>FPS «прыгает»

</td><td>CPU‑bottleneck физики

</td><td>Снизьте плотность акторов/частоту физики; увеличьте vCPU; разделите рендер/физику по контейнерам.

</td></tr><tr><td>Пики VRAM → вылеты

</td><td>Слишком много текстур/сенсоров

</td><td>Уменьшите разрешение/качество; держите запас VRAM ≥ 20%.

</td></tr><tr><td>NVENC не стартует

</td><td>Лимит сессий/кодеков

</td><td>Уменьшите число параллельных потоков; распределите кодирование по процессам.

</td></tr><tr><td>Drop кадров &gt; 1%

</td><td>I/O или кодек перегружены

</td><td>Снижайте FPS/битрейт; используйте NVMe; контролируйте i/o\_backlog\_sec.

</td></tr><tr><td>rosbag2 «тормозит»

</td><td>Компрессия/мелкие файлы

</td><td>Увеличьте max‑bag‑size; тюньте компрессию; пишите на локальный NVMe.

</td></tr><tr><td>Реплей «убегает» по времени

</td><td>clock не синхронизирован

</td><td>Запускайте с --clock и use\_sim\_time; ждите ack подписчиков.

</td></tr><tr><td>Нет сообщений в bridge

</td><td>ROS\_DOMAIN\_ID не совпадает

</td><td>Выставьте одинаковый ROS\_DOMAIN\_ID у всех сервисов.

</td></tr><tr><td>Веб‑клиент «замирает»

</td><td>SSE без heartbeats

</td><td>Периодически шлите keep‑alive; ограничьте размер очереди.

</td></tr><tr><td>CPU 100%, GPU &lt; 30%

</td><td>Перекос нагрузки

</td><td>Перенесите часть постпроцесса на GPU; уменьшите частоту физики.

</td></tr><tr><td>Лидар «молчит»

</td><td>Неверные параметры

</td><td>Проверьте channels, range, frame\_id; убедитесь в подписчиках.

</td></tr><tr><td>Память хоста растёт

</td><td>Бэги не ротируются

</td><td>Настройте ротацию по размеру/времени; джоб на зачистку.

</td></tr><tr><td>Коннекты RViz не видят топики

</td><td>Сеть/файрвол

</td><td>Разрешите порты DDS; проверьте multicast в VPC.

</td></tr><tr><td>Прерывания убивают прогон

</td><td>Нет чекпоинтов

</td><td>Режьте задачи на чанки до 120 сек; храните прогресс в манифестах.

</td></tr></tbody></table>

**Как запустить в cloudcompute.ru**

1. **Выберите шаблон** запуска (Docker/SSH/Jupyter) на <https://cloudcompute.ru/solutions/templates/>.
2. **Профиль GPU**: 24 ГБ (интерактив с 1–2 камерами), 48 ГБ (средний пакет сенсоров), 80 ГБ (4K/много сенсоров).
3. **Режим**: On‑Demand для отладки/демо; Interruptible для пакетной генерации (чанки ≤ 120 сек, локальный NVMe, ретраи).
4. **Сторадж**: подключите том /data/nvme для бэгов; настройте выгрузку в «тёплое/холодное» хранилище (см. <https://cloudcompute.ru/solutions/storage-data/>).
5. **Наблюдаемость**: добавьте экспорт метрик/логов по гайду <https://cloudcompute.ru/solutions/monitoring-logging/>.
6. **CI/CD**: сборка образов, промо из dev→prod через <https://cloudcompute.ru/solutions/containers-ci-cd/>.
7. **Тюнинг**: баланс FPS/латентности по <https://cloudcompute.ru/solutions/throughput-vs-latency/> и <https://cloudcompute.ru/solutions/performance-tuning/>.
8. **Секьюрити**: секреты/ретеншн — по <https://cloudcompute.ru/solutions/security/>.

**Чек‑лист перед продом**

- Целевая **U** (GPU util) 60–85%, запас VRAM ≥ 20%.
- p95 render\_fps и nvenc\_latency\_ms в нормах; drop rate ≤ 1%.
- rosbag2 ротация настроена, NVMe не переполняется.
- Реплеи детерминированы: одинаковые результаты на одинаковых seed/параметрах.
- SSE/WebSocket выдерживает N одновременных клиентов, есть heartbeats.
- Алёрты: VRAM, I/O backlog, CPU runqueue, dropped frames.
- Политики прерывания и чекпоинты выполнены, чанк ≤ 120 сек.
- Контейнеры со зашитым ROS\_DOMAIN\_ID, версия образов зафиксирована.
- Секреты и приватные миры/карты в отдельных томах, аудит включён.
- Экономика подтверждена через <https://cloudcompute.ru/solutions/cost-planner/>.

**Навигация**

- Хаб «Решения»: <https://cloudcompute.ru/solutions/>
- Шаблоны запусков: <https://cloudcompute.ru/solutions/templates/>
- Планирование стоимости: <https://cloudcompute.ru/solutions/cost-planner/>
- Тюнинг производительности: <https://cloudcompute.ru/solutions/performance-tuning/>
- Multi‑GPU/Multi‑node: <https://cloudcompute.ru/solutions/multi-gpu/>
- Хранилища и данные: <https://cloudcompute.ru/solutions/storage-data/>
- Наблюдаемость и логи: <https://cloudcompute.ru/solutions/monitoring-logging/>
- Observability для LLM/сервисов: <https://cloudcompute.ru/solutions/llm-inference/observability/>
- FP8/BF16 (общие подходы к mixed precision): <https://cloudcompute.ru/solutions/fp8-bf16/>
- Throughput vs Latency: <https://cloudcompute.ru/solutions/throughput-vs-latency/>
- Interruptible‑паттерны: <https://cloudcompute.ru/solutions/interruptible-patterns/>
- Gradio/FastAPI (стриминг UI): <https://cloudcompute.ru/solutions/gradio-fastapi/>
- Контейнеры и CI/CD: <https://cloudcompute.ru/solutions/containers-ci-cd/>

Готовы запустить?

Запустить GPU-сервер