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 > 90% в течение 2 мин → снизить разрешение/частоту;
- i/o\_backlog\_sec > 5 сек → увеличить NVMe/снизить компрессию;
- dropped\_frames\_pct > 1% → перераспределить сенсоры/кодеки;
- GPU util < 30% при CPU > 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 кадров > 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 < 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-сервер