Safe, idiomatic Rust bindings for Orbbec depth cameras, built on the official OrbbecSDK v2 C API via FFI. It works with any OrbbecSDK-v2-compatible Orbbec device.
The crate gives you a type-safe, memory-safe interface to capture synchronized
RGB + depth streams, align them, read camera intrinsics, generate point clouds
and measure distances — without writing any C/C++ or unsafe in application
code.
- Device management — enumerate, inspect and open devices; list sensors.
- Frame capture — synchronized RGB + depth + IR streams over a Rust channel, with hardware timestamps.
- D2C alignment — align depth to the color frame (hardware or software) via
a dedicated
AlignFilter. - Camera model — intrinsics, distortion and depth↔RGB extrinsics with pixel-to-3D unprojection.
- Point clouds — RGB point cloud generation and distance-range outlier filtering.
- Distance measurement — robust region / detection-box distance in real time (used by the YOLO- and color-block examples).
- Stream profiles — query supported resolutions/formats and enable a specific profile.
A two-crate Cargo workspace:
orbbec/
├── Cargo.toml # workspace
├── orbbec-sys/ # low-level: bindgen-generated FFI bindings
│ ├── build.rs # locates the installed SDK, links libOrbbecSDK
│ ├── wrapper.h # #include <libobsensor/ObSensor.h>
│ └── src/lib.rs # generated bindings
└── orbbec/ # high-level: safe, idiomatic Rust API
├── src/
│ ├── context.rs # SDK context, device enumeration/opening
│ ├── device.rs # device info, sensor list
│ ├── pipeline.rs # capture pipeline, config, frames
│ ├── align.rs # D2C alignment filter
│ ├── camera.rs # intrinsics, distortion, extrinsics
│ ├── pointcloud.rs # point cloud generation & filtering
│ ├── frame.rs # typed DepthFrame / ColorFrame
│ ├── stream.rs # stream profile querying & matching
│ ├── filter.rs # generic SDK filter wrapper
│ └── error.rs # error type + FFI error handling
├── examples/ # runnable demos (see below)
└── tests/camera.rs # hardware-gated integration tests
orbbec-sys is generated with bindgen at build time and links the
system-installed libOrbbecSDK.so. orbbec wraps every raw pointer in an
RAII type and converts SDK ob_error** out-parameters into a typed [Error].
- Ubuntu 22.04+ x86_64 (other Linux should work)
- OrbbecSDK v2 installed — follow
docs/install-sdk.md(system packages, source build, udev rules, environment variables) - An OrbbecSDK-v2-compatible Orbbec depth camera connected on a USB 3.0 port
clang+libclang-dev(bindgen),cmake, C/C++ toolchain
# see docs/install-sdk.md for full details (udev rules, etc.)
sudo apt install -y build-essential git cmake pkg-config \
libusb-1.0-0-dev libgoogle-glog-dev libopencv-dev \
libgl1-mesa-dev libegl1-mesa-dev libgles2-mesa-dev libglew-dev \
clang libclang-devexport OB_SDK_ROOT=/opt/OrbbecSDK # where the SDK is installed
export LD_LIBRARY_PATH=/opt/OrbbecSDK/lib:$LD_LIBRARY_PATHcargo build --releaseuse orbbec::pipeline::{Config, FrameType, Pipeline, StreamType};
use orbbec::Context;
fn main() -> Result<(), Box<dyn std::error::Error>> {
let ctx = Context::new()?;
// 1. Make sure a camera is connected.
let devices = ctx.query_devices()?;
if devices.is_empty() {
panic!("no Orbbec device connected");
}
println!("found {}", devices[0].name);
// 2. Configure depth + color.
let mut config = Config::new()?;
config.enable_stream(StreamType::Depth)?;
config.enable_stream(StreamType::Color)?;
// 3. Start the pipeline and receive framesets over a channel.
let mut pipeline = Pipeline::new()?;
pipeline.enable_frame_sync()?;
let frames = pipeline.start_capture(Some(&config))?;
// 4. Read one frameset and inspect the depth frame.
let frameset = frames.recv_timeout(std::time::Duration::from_secs(2))?;
if let Some(depth) = frameset.frame(FrameType::Depth) {
println!(
"depth {}x{} bytes={}",
depth.width(),
depth.height(),
depth.data_size()
);
}
pipeline.stop()?;
Ok(())
}Run any example from the repo root with the environment set:
| Example | What it does |
|---|---|
enumerate |
Enumerate devices and print info |
frames |
Capture synchronized RGB + depth frames |
aligned |
D2C align depth to color, read intrinsics, pixel→3D |
pointcloud |
Generate an RGB point cloud, filter by range |
streams |
Query stream profiles, match and enable one |
distance |
Measure distance of a region / the whole frame (--center, --rect=) |
object_distance |
Measure distance of YOLO-style detection boxes |
color_block |
Track a colored block and measure its distance |
imu |
Stream accelerometer + gyroscope data in real time |
cargo run --release --example frames
cargo run --release --example aligned
cargo run --release --example pointcloud
cargo run --release --example distance -- --center
cargo run --release --example object_distance -- --box=100,80,300,220
cargo run --release --example color_block # green blockUnit tests and doc-tests always run. Integration tests exercise the real
camera and are gated behind ORBBEC_TEST=1 so the suite passes on machines
without hardware:
cargo test --release # unit + doc tests
export ORBBEC_TEST=1
cargo test -p orbbec --release --test camera # hardware integration testsThe 10 integration tests cover context creation, enumeration, opening devices, sensor lists, synchronized frame capture, camera intrinsics, D2C alignment, point cloud generation, typed depth frames and stream-profile matching.
docs/install-sdk.md— installing the Orbbec SDK (source or prebuilt), udev rules, verification and the build environment- Crate docs:
cargo doc --open
- Depth cameras have a model-dependent minimum working range; objects closer than it produce no reliable depth (the SDK emits garbage values).
- Default color profile is MJPG; use an uncompressed profile (e.g.
1280x720@30RGB) when you need per-pixel color access. - The binding targets the installed SDK ABI. Re-run
cargo buildafter an SDK upgrade soorbbec-sysregenerates the bindings.
MIT