Demonstrates multi-device synchronization. This sample supports network devices, USB devices, and GMSL devices.
- The primary purpose of this repository is to demonstrate the multi-device synchronization functionality of different types of Orbbec devices, including detailed instructions for hardware connections and software configuration.
- The v2-main branch is based on the multi device sync sample and gmsl trigger sample provided by Orbbec SDK v2. If there are any updates or changes to the samples in Orbbec SDK v2, please refer to the official implementation in Orbbec SDK v2 as the authoritative version.
- The legacy main branch is based on Orbbec SDK v1 and only demonstrates multi-device synchronization for Femto Mega.
| Product Series | Product | Connection | Sync Documentation |
|---|---|---|---|
| Gemini 305 | Gemini 305 | USB | Gemini301Series.md |
| Gemini 305g | Gemini 305g | USB/GMSL | Gemini301Series.md |
| Gemini 435Le | Gemini 435Le | Ethernet | Gemini435Le.md |
| Gemini 330 | Gemini 335Le | Ethernet | Gemini330Series.md |
| Gemini 335/335L/336/336L | USB | Gemini330Series.md | |
| Gemini 335Lg | GMSL | Gemini330Series.md | |
| Gemini 2 | Gemini 2/2L/215/210 | USB | Gemini2Series.md |
| Astra | Astra 2 | USB | Astra2.md |
| Femto | Femto Bolt | USB | FemtoSeries.md |
| Femto Mega | USB/Ethernet | FemtoSeries.md | |
| Femto Mega I | Ethernet | FemtoSeries.md |
This project builds two standalone executables:
| Program | Connection | Platform | Function |
|---|---|---|---|
| MultiDeviceSync | USB / Ethernet /GMSL | Windows / Linux x64 / Linux ARM64 | Multi-device sync configuration, data stream acquisition, real-time preview |
| MultiDeviceSyncGmslTrigger | GMSL | Linux ARM64 (NVIDIA Jetson AGX Orin, NVIDIA Jetson Orin NX) | GMSL PWM hardware trigger signal source |
- Notes: GMSL devices require two applications: MultiDeviceSync and MultiDeviceSyncGmslTrigger. The MultiDeviceSyncGmslTrigger application is responsible for sending trigger signals, while USB and Ethernet devices only require the MultiDeviceSync application.
cd Multi-Device-Synchronization-Example
mkdir build && cd build
cmake ..
cmake --build . --config ReleaseBuild artifacts are in the build/bin/ directory:
- Windows:
MultiDeviceSync.exe - Linux:
MultiDeviceSync,MultiDeviceSyncGmslTrigger
The program reads ./MultiDeviceSyncConfig.json from the current working directory by default. Device serial numbers can be found using the OrbbecViewer tool or in the program log after connecting devices.
The following example includes all optional fields; use as needed based on your device series:
{
"version": "1.0.1",
"configTime": "2026/05/07",
"devices": [
{
"sn": "CP123456789",
"syncConfig": {
"syncMode": "OB_MULTI_DEVICE_SYNC_MODE_PRIMARY",
"depthDelayUs": 0,
"colorDelayUs": 0,
"trigger2ImageDelayUs": 0,
"triggerOutEnable": true,
"triggerOutDelayUs": 0,
"framesPerTrigger": 1
}
}
]
}Field descriptions:
| Field | Type | Required | Description |
|---|---|---|---|
sn |
string | Yes | Device serial number, used to match connected devices |
syncConfig.syncMode |
string | Yes | Sync mode, see table below for available values |
syncConfig.depthDelayUs |
int | Yes | IR/Depth/ToF trigger signal input delay (microseconds), increment by 160us per device to achieve staggered exposure |
syncConfig.colorDelayUs |
int | Yes | RGB trigger signal input delay (microseconds), typically 0 |
syncConfig.trigger2ImageDelayUs |
int | Yes | Delay from trigger signal input to image capture (microseconds), typically 0 |
syncConfig.triggerOutEnable |
bool | Yes | Device trigger signal output enable switch. Set to true for PRIMARY/SECONDARY mode, false for SOFTWARE_TRIGGERING and HARDWARE_TRIGGERING mode |
syncConfig.triggerOutDelayUs |
int | Yes | Device trigger signal output delay (microseconds), typically 0 |
syncConfig.framesPerTrigger |
int | Yes | Number of frames captured per trigger, only effective in software and hardware trigger modes |
syncMode available values:
| Mode | Description |
|---|---|
OB_MULTI_DEVICE_SYNC_MODE_PRIMARY |
Primary mode, outputs sync trigger signal |
OB_MULTI_DEVICE_SYNC_MODE_SECONDARY |
Secondary mode, receives trigger signal |
OB_MULTI_DEVICE_SYNC_MODE_SOFTWARE_TRIGGERING |
Software trigger mode, PC controls capture timing |
OB_MULTI_DEVICE_SYNC_MODE_HARDWARE_TRIGGERING |
Hardware trigger mode, triggered by external hardware signal |
OB_MULTI_DEVICE_SYNC_MODE_SECONDARY_SYNCED |
Secondary synced variant, starts capturing immediately, auto-aligns when trigger signal is received |
./MultiDeviceSync- Enter
0: Configure device sync mode and start streaming - Enter
1: Start streaming directly (use when devices are already configured)
Keyboard shortcuts:
| Key | Function |
|---|---|
S |
Sync device clocks |
T |
Software trigger capture |
ESC |
Stop streaming and exit |
Run without the OpenCV preview window, suitable for remote sessions (SSH) or headless servers:
./MultiDeviceSync --headless- Timestamp recording and sync monitor output run exactly as in normal mode
- No preview window is created
- Press
Ctrl+Cto stop: the program catches SIGINT, flushes all CSV data, and shuts down streams before exiting
For GMSL2 connections to NVIDIA Jetson platforms. Devices must be configured as HARDWARE_TRIGGERING mode.
./MultiDeviceSyncGmslTrigger- Enter
0: Set trigger frequency (FPS) - Enter
1: Start PWM trigger signal - Enter
2: Stop PWM trigger signal - Enter
3: Exit
During streaming, each device and each sensor (depth/color) records its own timestamp CSV file under ./output/:
output/
sync_depth_dev0_<SN>.csv
sync_color_dev0_<SN>.csv
sync_depth_dev1_<SN>.csv
sync_color_dev1_<SN>.csv
...
Each file contains one row per captured frame:
| Field | Description |
|---|---|
row_id |
Sequential row index |
sw_frame_num |
Software frame number from the SDK |
hw_frame_num |
Hardware frame number; -1 when the device does not support it |
system_ts_us |
Host system timestamp (microseconds) |
device_ts_us |
Device-side timestamp (microseconds) |
global_ts_us |
Global timestamp on the host clock domain (microseconds); 0 when unsupported |
Note: Some devices do not provide a global timestamp (
global_ts_usis all0) or a hardware frame number (hw_frame_numis-1). This is normal and expected.
A standalone Python script evaluates multi-device synchronization accuracy from the recorded CSV files:
- Script:
scripts/analyze_sync.py - No third-party dependencies (Python standard library only)
Run it from the directory containing the CSV files (typically output/):
cd build/bin/output
python analyze_sync.pyOr analyze any folder:
python analyze_sync.py /path/to/csv_dir [options]Options:
| Option | Default | Description |
|---|---|---|
[csv_dir] |
current directory | Directory with the sync_*.csv files |
--fps |
30 |
Frame rate used to compute the grouping tolerance (half-frame interval) |
--threshold |
2000 |
In-group timestamp range (us) above which a group is flagged abnormal |
--ts-source |
auto |
Time base for matching: global / device / auto |
--output |
<csv_dir> |
Directory for the report and matched CSV |
Time base selection:
global(recommended): usesglobal_ts_us, all devices share the host clock domain.device: usesdevice_ts_us, for devices that do not support a global timestamp.auto: usesglobalwhen valid; otherwise degrades todevice.
Output:
| File | Description |
|---|---|
sync_matched_<sensor>.csv |
Per-moment matched groups: each row is one matched moment with every device's frame number and timestamps |
- Femto series and Gemini 2 series sync configurations are written to Flash and persist after power-off; frequent configuration will reduce Flash lifespan. Gemini 305 and Gemini 330 sync configurations do not persist after power-off and must be reconfigured each time the device is powered on.
- MultiDeviceSyncGmslTrigger only provides PWM trigger signal source and does not include data stream acquisition or preview functionality.
- When exiting MultiDeviceSyncGmslTrigger, select
3to ensure the/dev/camsyncdevice is properly closed.
Multi-Device-Synchronization-Example/
|-- CMakeLists.txt # Build configuration
|-- MultiDeviceSync/ # Standard USB/Ethernet multi-device sync
| `-- MultiDeviceSync.cpp # Main program
|-- MultiDeviceSyncGmslTrigger/ # GMSL PWM hardware trigger
| `-- MultiDeviceSyncGmslTrigger.cpp # Main program
|-- common/ # Shared core modules
| |-- PipelineHolder.hpp/cpp # Per-device pipeline wrapper
| |-- FramePairingManager.hpp/cpp # Per-device per-sensor timestamp CSV logging
| `-- utils/ # Utility library
| |-- cJSON.c/h # JSON parser
| |-- utils.cpp/hpp # Basic utility functions
| |-- utils_c.c/h # C utility functions
| |-- utils_opencv.cpp/hpp # OpenCV visualization windows
| `-- utils_types.h # Common type definitions
|-- scripts/ # Sync accuracy analyzer
| `-- analyze_sync.py # Standalone, no third-party dependencies
|-- config/
| |-- OrbbecSDKConfig.xml # SDK device configuration
| `-- MultiDeviceSyncConfig.json # Current sync configuration
|-- docs/ # Per-series documentation
| |-- Astra2.md
| |-- FemtoSeries.md
| |-- Gemini2Series.md
| |-- Gemini301Series.md
| |-- Gemini330Series.md
| `-- Gemini435Le.md
|-- res/ # Documentation image resources
`-- 3rdparty/orbbecsdk/ # OrbbecSDK
|-- win_x64/
|-- linux_x86_64/
`-- linux_arm64/