Мультикамерная система — самый дешёвый способ закрыть большое помещение глубиной: четыре камеры дают полный охват без слепых зон, где одной камере не хватает ни разрешения, ни геометрии. Но у новичков проект почти всегда умирает одинаково: «первая камера работает, добавляю вторую — обе сыплются кадрами». Причина всегда одна — полоса USB, поделенная без плана. Камера Orbbec — это одновременно два-три изохронных потока (depth, color, IR), и один контроллер держит одну-две камеры максимум. В этом гайде научимся читать USB-топологию, считать бюджет трафика, жёстко привязывать камеры к контроллерам и сериалам, и разберём, когда вместо насильственного уплотнения честнее разнести камеры по хостам или взять решение со встроенными вычислениями вроде Persee 2. Про синхронизацию кадров между камерами — отдельная тема, здесь отметим только место, где она становится обязательной.
По опыту типовых раскладок: две камеры — почти всегда помещаются на один хост без хитростей, если у десктопа два независимых контроллера. Четыре камеры — уже проектирование: два-четыре контроллера, профили понижены, каждый поток в своём процессе. Восемь и больше — это хост на границе разумного: дальше либо добавляется второй хост, либо архитектура переезжает на распределённые вычисления. Знать свою точку перехода полезно заранее: она наступает не в момент «камер стало много», а в момент, когда суммарный поток упёрся в шину или CPU перестал успевать в реальном времени.
Что понадобится
- хост с несколькими независимыми контроллерами USB 3.x (обычный десктоп на чипсете Intel — почти всегда подходит);
- несколько камер Orbbec (логика одинакова для всей линейки);
- отдельные USB-кабели до 3 м, без хабов;
- Linux (примеры для Ubuntu 22.04), пакет usbutils (
lsusb); - pyorbbecsdk или OrbbecSDK_ROS2 — любой стек, которым вы открываете камеры.
Пошаговая настройка
Шаг 1. Смотрим, какие контроллеры есть на хосте
Дерево USB показывает реальные контроллеры и концентраторы — это карта боевых действий:
lsusb -t
/: Bus 02.Port 1: Dev 1, Class=root_hub, Driver=xhci_hcd/4p, 10000M
|__ Port 2: Dev 3, If 0, Class=Video, Driver=uvcvideo, 5000M
/: Bus 01.Port 1: Dev 1, Class=root_hub, Driver=xhci_hcd/12p, 480M
|__ Port 4: Dev 5, If 0, Class=Video, Driver=uvcvideo, 480M
Читаем так: каждый Bus — отдельный контроллер (отдельный корневой концентратор), число после слэша — его пропускная способность (5000M — USB 3.x, 480M — USB 2.0). Камера, подключённая в синий порт, обязана показать 5000M; если показала 480M — кабель или порт плохие, дальше не идите, пока не исправите. Задача планирования — посадить каждую камеру на свой Bus. У десктопных плат чипсет даёт несколько корневых шин, и физические порты распределяются между ними неравномерно: эмпирический способ — втыкать камеру в каждый порт и смотреть, на какой Bus она попадает, сразу подписав порты стикером. Это пять минут, которые экономят недели.
Если встроенных шин не хватает, их добавляют платой расширения: PCIe-контроллер USB 3.x на одну-четыре линии — стандартный способ получить отдельные независимые шины. Выбирайте контроллеры на проверенных чипсетах и проверьте в lspci, что каждая линия платы видна как отдельный корневой хаб — дешёвые платы с внутренним делителем повторяют проблему хаба в другом разъёме. На серверных платформах обращайте внимание и на распределение линий PCIe между слотами в документации платы: два «пустых» слота могут делить одну линию.
Шаг 2. Считаем бюджет полосы
Каждый поток камеры — изохронная передача с гарантированным слотом, «лишнюю» полосу контроллер не найдёт. Прикиньте сумму по таблице и оставьте запас 20–30%: недогруз контроллера — это стабильность.
| Профиль камеры | Примерный поток | Камер на контроллер USB 3.x |
|---|---|---|
| depth 640×400@30 + color 640×400@30 | ~35 МБ/с | 2 (впритык), 1 с запасом |
| depth 1280×800@30 + color 1280×800@30 | ~160 МБ/с | 1 |
| depth 1280×800@30 + color 1280×800@30 + IR | ~200 МБ/с | 1, и то не всегда |
Ориентиры для планирования: точные значения зависят от форматов и настроек конкретной модели, поэтому финальный тест всегда делайте на своём профиле. Хост-контроллер USB 3.x обычно даёт реально доступные 350–400 МБ/с под изохронный трафик — отсюда и цифры в последней колонке.
Шаг 3. Привязываем камеры к местам по серийникам
Порядок перечисления USB-устройств не гарантирован: после перезагрузки «первая камера» может стать второй. Устраняем двусмысленность — в коде открываем камеры строго по серийным номерам:
from pyorbbecsdk import Pipeline, Config
def open_by_serial(serial: str) -> Pipeline:
config = Config()
config.set_serial_number(serial) # сверьте с examples вашей версии SDK
return Pipeline(config)
front = open_by_serial("AY3B...01") # серийники наклейте на корпуса
side = open_by_serial("AY3B...02")
front.start()
side.start()
Для системного уровня (логи, правила запуска, ROS) удобны udev-символьные ссылки по серийнику — правила пишутся один раз и переживают любые перетыкания:
# /etc/udev/rules.d/99-orbbec-map.rules
# vendor 2bc5 - устройства Orbbec; серийники свои
SUBSYSTEM=="tty", ATTRS{idVendor}=="2bc5", ATTRS{serial}=="AY3B...01", SYMLINK+="orbbec-front"
SUBSYSTEM=="tty", ATTRS{idVendor}=="2bc5", ATTRS{serial}=="AY3B...02", SYMLINK+="orbbec-side"
Для самих видеопотоков привязка по серийникам делается на уровне SDK (как выше); udev-ссылки нужны для служебных устройств и для единообразия логов. После правки правил — sudo udevadm control --reload-rules и переподключение камер.
Шаг 4. Программная разводка потоков
Каждая камера — свой Pipeline/узел со своим потоком или процессом. В ROS 2 это два экземпляра драйвера в разных namespace:
ros2 launch orbbec_camera gemini_330_series.launch.py \
camera_name:=front camera_namespace:=front
ros2 launch orbbec_camera gemini_330_series.launch.py \
camera_name:=side camera_namespace:=side
Имена параметров launch-файлов сверьте с README вашей ревизии драйвера — механика namespace в ROS 2 стандартная, а параметры запуска у драйвера периодически обновляются. В Python-стеке держите по Pipeline на поток (threading) — GIL не проблема: тяжесть в C-слое SDK, а не в питоновских объектах.
Шаг 5. Проверяем устойчивость часом, а не минутой
Прогоните все камеры полный час с логированием частоты. Провалы частоты в первые минуты — про полосу (пересадите камеру на другой контроллер); деградация к концу часа — про нагрев кабелей/хабов или приложение (рост очередей, утечка). Устойчивость против «работает на демо» — это и есть разница между макетом и изделием.
Шаг 6. Когда камер больше шести
На этом масштабе честнее спросить: зачем все потоки на одном хосте? Если задача каждой камеры локальна (порог, счётчик, детекция), обработка может жить у самой камеры — решения со встроенным компьютером отдают наружу уже результат, и хост получает метры вместо мегабайт. Если потоки всё же собираются в одном месте, ставьте второй хост и делите зоны, а сводите результаты на уровне логики. Транспорт между узлами — тоже проектное решение: для метрик хватит сети, для цельных облаков считайте трафик заранее, он кусается.
Разбор кода
Привязка по серийникам — центральная идея всего гайда, и её стоит закрепить. Серийник — единственный стабильный идентификатор камеры: он переживает перезагрузки, перестановку портов и обновления прошивки. Всё, что завязано на порядок перечисления, рано или поздно ломается в продакшене — обычно в самый неподходящий момент, когда «левая» камера внезапно стала «правой», и робот повернул не туда. Правило простое: серийник из конфига, открытый Pipeline пишет в лог, какой серийник он открыл; при старте системы проверяем, что все ожидаемые серийники на месте, и не стартуем частично.
Когда камер становится больше четырёх-шести, уплотнение USB упирается не в контроллеры, а в сложность: кабели, порты, зависимость от чипсета. Тогда честнее архитектурное решение — несколько хостов или смещение вычислений к камерам. Смещение к камерам — это семейство Persee: камера глубины со встроенным компьютером, где обработка происходит на борту и наружу идёт уже результат. Для распределённых мультикамерных систем это часто дешевле и надёжнее, чем один перегруженный хост, а связка по Ethernet решает и расстояния. Если камеры видят общую сцену и их данные будут сшиваться, не забудьте про синхронизацию кадров — программного старта недостаточно, мы разбирали аппаратную схему для Femto отдельно.
Закрепите архитектуру мониторингом: на каждый Pipeline заведите счётчик успешных wait_for_frames и таймаутов, и раз в секунду публикуйте частоту и возраст последнего кадра. Мультикамерная система без этого слепа: деградация одной камеры по полосе видна в цифрах задолго до того, как оператор заметит пропадание зоны. Порог тревоги задавайте от рабочей частоты: если камера обязана давать 30 Гц, тревога на устойчивых 25 — это ранняя стадия проблем с шиной, и лучше узнать о ней от метрики, чем от пропавшей зоны в продакшене.
Частые проблемы
Вторая камера роняет первую
Классика — обе камеры на одном корневом Bus (порты рядом на задней панели часто живут на одном контроллере). Проверьте lsusb -t, пересадите на другой Bus. Вторая причина — дешёвый внешний хаб, у которого все порты делят одну линию 5G: хабы для камер глубины практически бесполезны, камеры сажаются в порты хоста напрямую. Третья — просадка питания: каждая камера берёт ватты, и port multiplier-планшеты с одним блоком дают мигания; камеры требуют прямого питания хоста или нормальных активных решений.
Нужна ли камерам аппаратная синхронизация
Быстрая проверка: камеры смотрят в разные зоны и их результаты не сшиваются — синхронизация не нужна, каждый поток живёт своей жизнью. Камеры видят одну сцену, и данные объединяются в облако или объём — нужна, иначе движущиеся объекты двоятся. Промежуточные случаи (каждая камера сама детектирует, но результаты сравниваются во времени) — обходитесь программными штампами и допуском. Внедрять синхронизацию «на всякий случай» не стоит: это кабели, настройки и ещё один слой, который может ломаться; её место — там, где без неё данные физически не сойдутся.
Камеры работают, но частота плавает 30-25-28-30
Это пограничное состояние по полосе: контроллер выжимает максимум, и любой посторонний трафик (внешний диск на том же шине, сетевая карта на общем линии) отбирает слоты. Уберите с проблемного контроллера всё лишнее, снизьте профиль одной из камер на ступень (например, color 1280×800 вместо 1920×1080) — частота выровняется. Держите правило: контроллер, на котором камеры, больше ни для чего не используется.
После перезагрузки камеры «перепутались»
Приложение открывает устройства по порядку перечисления. Переводите открытие на серийные номера (шаг 3), у служб используйте udev-ссылки, а в логах печатайте открытые серийники. Для быстрой проверки соответствия «корпус — серийник» полезно наклеить серийник на корпус при расстановке и один раз проверить программой из SDK, что серийник читается именно с той камеры, что смотрит в нужную сторону.
Планируете мультикамерный контур? Посмотрите каталог Orbbec на luwam.ru. Рабочие связки — Persee 2 (камера плюс компьютер на борту, разгружает хост) и Gemini 335L для классических USB-узлов. Поможем рассчитать полосу и конфигурацию, дадим консультацию по SDK, выставим счёт для юрлица, гарантия 1 год.
Камеры Orbbec в наличии на LUWAM
- Orbbec Femto Bolt — iToF 4K, замена Azure Kinect — 99 900 ₽
- Orbbec Gemini 335L — стерео для роботов и SLAM — 99 900 ₽
- Orbbec Astra 2 — структурированный свет, сканирование помещений — 99 900 ₽
Весь каталог Orbbec · консультация по SDK · счёт для юрлица в день обращения · гарантия 1 год.

