Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
8d36ded
[RSDK-12362] Provide Support for Orbbec Gemini 335LE Camera
SebastianMunozP Oct 24, 2025
18dcdaa
[[RSDK-12362] Add support for new Gemini in discovery and complete in…
SebastianMunozP Oct 27, 2025
540dd42
[[RSDK-12362] Supported devices are now not hardcoded but centralized…
SebastianMunozP Oct 27, 2025
40c5ac4
[[RSDK-12362] Improve handling for supported resolutions
SebastianMunozP Oct 27, 2025
e6e0e43
[[RSDK-12362] Throwing an error if the specified depth/color resoluti…
SebastianMunozP Oct 27, 2025
e66a3ce
[[RSDK-12362] Removing 16:9 support for now
SebastianMunozP Oct 27, 2025
c189d79
[[RSDK-12362] Removing support for firmware_update on Geminie camera …
SebastianMunozP Oct 27, 2025
da15895
Returning timeSinceFrameUs logic to previous logic of returning 0 whe…
SebastianMunozP Oct 27, 2025
f01134a
Reenabling checkFirmwareVersion in get_image()
SebastianMunozP Oct 27, 2025
9042e6b
In Update Firmware making sure the zip name is at least 4 characters
SebastianMunozP Oct 27, 2025
362f7a4
Actually performing the firmwareUpdate
SebastianMunozP Oct 27, 2025
c2f7cf5
[[RSDK-12362] Returning firmwareUpdate logic to its original state, b…
SebastianMunozP Oct 27, 2025
5e0be35
[[RSDK-12362] Improving firmware_update logging and responses
SebastianMunozP Oct 27, 2025
0b3c31e
[RSDK-12362] Enabled and positively tested firmware update on Gemini3…
SebastianMunozP Oct 27, 2025
260be47
[RSDK-12362] Updating README.md
SebastianMunozP Oct 27, 2025
a745de5
Update src/module/orbbec_firmware.cpp
SebastianMunozP Oct 27, 2025
a1ed509
Update src/module/orbbec_firmware.cpp
SebastianMunozP Oct 27, 2025
0caa622
Update src/module/orbbec_firmware.cpp
SebastianMunozP Oct 27, 2025
162a193
Update src/module/orbbec.cpp
SebastianMunozP Oct 27, 2025
767ce34
Update src/module/discovery.cpp
SebastianMunozP Oct 27, 2025
e8daae1
[RSDK-12362] Fixing Windows Build
SebastianMunozP Oct 27, 2025
4915a34
[RSDK-12362] Creating function distortionTypeToString
SebastianMunozP Oct 27, 2025
30ca885
[RSDK-12362] Making lint happy
SebastianMunozP Oct 27, 2025
d70a714
[RSDK-12362] some warn logs are now errors, removing raw pointers for…
SebastianMunozP Oct 29, 2025
6f978bb
[RSDK-12362] Take the fix the Orbbec name on the configs so that they…
SebastianMunozP Oct 29, 2025
fa15ab4
[RSDK-12362] Orbbec devices can have mutiple names, accounting for th…
SebastianMunozP Oct 29, 2025
7e9cbc7
[RSDK-12362] Making lint happy
SebastianMunozP Oct 29, 2025
bb6720a
[RSDK-12362] Improving logic of the code per feedback from PR
SebastianMunozP Oct 30, 2025
6ff60dd
[RSDK-12362] Modularizing the creation of Alignment config for SW and HW
SebastianMunozP Oct 30, 2025
ec79f87
[RSDK-12362] Modularizing startDevice and registerDevice by adding a …
SebastianMunozP Oct 30, 2025
605bb3a
[RSDK-12362] Fixing a bug to handle when return a nullptr, improving …
SebastianMunozP Oct 30, 2025
32087d0
[RSDK-12362] Making lint happy and adding the lint step to Makefile m…
SebastianMunozP Oct 30, 2025
0bf051b
[RSDK-12362] Disabling Gemini cameras for hosts other than Linux for …
SebastianMunozP Oct 30, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ else()
endif()

add_executable(orbbec-cli src/cli/main.cpp)
add_executable(orbbec-module src/module/main.cpp src/module/orbbec.cpp src/module/discovery.cpp src/module/encoding.cpp)
add_executable(orbbec-module src/module/main.cpp src/module/orbbec.cpp src/module/discovery.cpp src/module/encoding.cpp src/module/orbbec_firmware.cpp src/module/orbbec_windows_registry.cpp)

target_compile_features(orbbec-cli PRIVATE cxx_std_17)
target_compile_features(orbbec-module PRIVATE cxx_std_17)
Expand Down
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ else
--build=missing
endif

module.tar.gz: conan-pkg meta.json
module.tar.gz: lint conan-pkg meta.json
ifeq ($(OS),Windows_NT)
cmd /C "refreshenv && IF EXIST .\venv\Scripts\activate.bat call .\venv\Scripts\activate.bat && conan install --requires=viam-orbbec/0.0.1 -o:a "viam-cpp-sdk/*:shared=False" -s:a build_type=Release -s:a compiler.cppstd=17 --deployer-package "^&" --envs-generation false"
else
Expand Down
67 changes: 61 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ This module provides access to the color and depth sensors and creates pointclou

## Model viam:orbbec:astra2

Use [Orbbec cameras](https://www.orbbec.com/products/structured-light-camera/astra-2/).
[Official Orbbec Astra 2 Camera Webpage](https://www.orbbec.com/products/structured-light-camera/astra-2/).

### Configuration
The following attribute template can be used to configure this model:
Expand All @@ -35,7 +35,7 @@ The following attribute template can be used to configure this model:
```
#### Configuration Attributes

The following attributes are available for this model:
The following attributes are available for the Astra 2 model:

| Name | Type | Inclusion | Description |
|---------------|--------|-----------|----------------------------|
Expand All @@ -56,7 +56,7 @@ The following attributes are available for this model:
| `depth` | `Y16` |


#### `height`/`width` available combinations
#### `width`/`height` available combinations
| Color | Depth |
|-------|-------|
| `1920x1080` | `1600x1200`, `800X600`, `400X300` |
Expand All @@ -66,8 +66,63 @@ The following attributes are available for this model:
| `640X480` | `800X600`, `400X300` |
| `640X360` | `800X600`, `400X300` |

## Model viam:orbbec:gemini_335le

### Attributes
[Official Orbbec Gemini 335Le Camera Webpage](https://www.orbbec.com/gemini-335le/).

### Configuration
The following attribute template can be used to configure this model:

```json
{
"serial_number": "AARY14100EF",
"sensors": {
"depth": {
"height": 1200,
"width": 1600,
"format": "Y16"
},
"color": {
"width": 1920,
"height": 1080,
"format": "MJPG"
}
}
}
```
#### Configuration Attributes

The following attributes are available for the Gemini 335Le model:

| Name | Type | Inclusion | Description |
|---------------|--------|-----------|----------------------------|
| `serial_number` | string | **Required** | The serial number of the specific Orbbec camera to use. This number is printed on the device. The serial number of each plugged-in and available orbbec camera will be logged on module startup. |
|`sensors` | struct | **Optional** | The configuration of the color and depth sensors |

#### `sensor` attributes:
| Name | Type | Inclusion | Description |
|------|------|-----------|-------------|
| `height` | string | **Optional** | Native camera sensor height in pixels |
| `width` | string | **Optional** | Native camera sensor width in pixels |
| `format` | string | **Optional** | Native camera format |

#### `sensor` formats
| Sensor | Formats |
|--------|---------|
| `color` | `MJPG`|
| `depth` | `Y16` |


#### `width`/`height` available combinations
| Color | Depth |
|-------|-------|
| `1280X800` | `1280X800`, `848X530`, `640X400`, `424X266`, `320X200` |
| `848X530` | `640X400`, `424X266`, `320X200` |
| `640X400` | `640X400`, `424X266`, `320X200` |
| `640X480` | `640X480` |


## Attributes
A call to get_attributes will return the camera attributes in [this struct](https://github.com/viamrobotics/viam-cpp-sdk/blob/43deea420f572e6b61b6fbd519e09b2520f05676/src/viam/sdk/components/camera.hpp#L58)

Bear in mind that the distortion parameters contained in that struct are not named, i.e. they are contained in a vector of doubles. So they must be parsed following the order in which they are being stored, which is as follows:
Expand All @@ -83,10 +138,10 @@ Bear in mind that the distortion parameters contained in that struct are not nam
| 6 | k5 |
| 7 | k6 |

### DoCommand
## DoCommand
You can use DoCommand to upgrade the firmware of your device to the required version.

Update the firmware to v2.8.20. If running on macOS, you must unplug and replug the device after this returns.
Update the astra 2 firmware to v2.8.20 and gemini_335le to v1.5.55. If running on macOS, you must manually unplug and replug the device after this returns.
**WARNING**: Do not unplug the device while the firmware update is in progress.

{
Expand Down
29 changes: 28 additions & 1 deletion src/module/device_control.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,32 @@ inline std::string propertyTypeToString(OBPropertyType type) {
}
}

inline std::string distortionTypeToString(OBCameraDistortionModel model) {
switch (model) {
case OB_DISTORTION_NONE:
return "NONE";
break;
case OB_DISTORTION_MODIFIED_BROWN_CONRADY:
return "MODIFIED_BROWN_CONRADY";
break;
case OB_DISTORTION_INVERSE_BROWN_CONRADY:
return "INVERSE_BROWN_CONRADY";
break;
case OB_DISTORTION_BROWN_CONRADY:
return "BROWN_CONRADY";
break;
case OB_DISTORTION_BROWN_CONRADY_K6:
return "BROWN_CONRADY_K6";
break;
case OB_DISTORTION_KANNALA_BRANDT4:
return "KANNALA_BRANDT4";
break;
default:
return "UNKNOWN";
break;
}
}

viam::sdk::ProtoStruct getOrbbecSDKVersion(std::string const& command) {
viam::sdk::ProtoStruct resp;
std::stringstream ss;
Expand Down Expand Up @@ -539,6 +565,7 @@ viam::sdk::ProtoStruct getCameraParams(std::shared_ptr<PipelineT> pipe) {
distortion_struct["k6"] = static_cast<double>(distortion.k6);
distortion_struct["p1"] = static_cast<double>(distortion.p1);
distortion_struct["p2"] = static_cast<double>(distortion.p2);
distortion_struct["model"] = distortionTypeToString(distortion.model);
profile["distortion"] = distortion_struct;

result[sensorName] = profile;
Expand Down Expand Up @@ -630,7 +657,7 @@ viam::sdk::ProtoStruct createModuleConfig(std::unique_ptr<ViamDeviceT>& dev) {
}

viam::sdk::ProtoStruct result;
result["serial_number"] = dev->serial_number;
result["serial_number"] = dev->serialNumber;
result["sensors"] = sensors;
result["post_process_depth_filters"] =
getPostProcessDepthFilters(dev->postProcessDepthFilters, "create_module_config")["create_module_config"];
Expand Down
92 changes: 74 additions & 18 deletions src/module/discovery.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,35 +12,91 @@ OrbbecDiscovery::OrbbecDiscovery(vsdk::Dependencies dependencies, vsdk::Resource
std::vector<vsdk::ResourceConfig> OrbbecDiscovery::discover_resources(const vsdk::ProtoStruct& extra) {
std::vector<vsdk::ResourceConfig> configs;

std::shared_ptr<ob::DeviceList> devList = ob_ctx_->queryDeviceList();
int devCount = devList->getCount();

if (devCount == 0) {
VIAM_SDK_LOG(warn) << "No Orbbec devices found during discovery";
return {};
// Enable network device enumeration for Ethernet cameras (like Gemini 335Le)
try {
ob_ctx_->enableNetDeviceEnumeration(true);
VIAM_RESOURCE_LOG(info) << "Enabled network device enumeration for Ethernet cameras";
} catch (ob::Error& e) {
VIAM_RESOURCE_LOG(error) << "Failed to enable network device enumeration: " << e.what();
} catch (const std::exception& e) {
VIAM_RESOURCE_LOG(error) << "Failed to enable network device enumeration: " << e.what();
}

VIAM_SDK_LOG(info) << "Discovered " << devCount << " devices";
try {
// Use SDK's native device discovery (works for both USB and network devices)
std::shared_ptr<ob::DeviceList> devList = ob_ctx_->queryDeviceList();
int devCount = devList->getCount();

if (devCount == 0) {
VIAM_RESOURCE_LOG(warn) << "No Orbbec devices found during discovery";
return {};
}

VIAM_RESOURCE_LOG(info) << "Discovered " << devCount << " Orbbec devices";

for (size_t i = 0; i < devCount; i++) {
try {
std::string deviceName = devList->name(i);
std::string serialNumber = devList->serialNumber(i);
std::string connectionType = devList->connectionType(i);
std::string ipAddress = devList->ipAddress(i);

for (size_t i = 0; i < devCount; i++) {
std::shared_ptr<ob::Device> dev = devList->getDevice(i);
std::shared_ptr<ob::DeviceInfo> info = dev->getDeviceInfo();
std::stringstream deviceInfoString;
deviceInfoString << "Device " << (i + 1) << " - Name: " << deviceName << ", Serial: " << serialNumber
<< ", Connection: " << connectionType;
if (!ipAddress.empty()) {
deviceInfoString << ", IP: " << ipAddress;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For ethernet cameras does the IP address need to be in the config?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nope, the SDK takes care of that, it has its own "discovery service", it detects all Orbbec cameras reachable therough USB or the network

}

std::ostringstream name;
name << "orbbec-" << i + 1;
VIAM_RESOURCE_LOG(info) << deviceInfoString.str();

vsdk::ProtoStruct attributes;
attributes.emplace("serial_number", info->serialNumber());
std::ostringstream name;
name << "orbbec-" << i + 1;

vsdk::ResourceConfig config(
"camera", std::move(name.str()), "viam", attributes, "rdk:component:camera", orbbec::Orbbec::model, vsdk::log_level::info);
configs.push_back(config);
vsdk::ProtoStruct attributes;
attributes.emplace("serial_number", serialNumber);

// Detect model and create appropriate resource
std::string viamModelSuffix;
std::optional<orbbec::OrbbecModelConfig> modelConfig = orbbec::OrbbecModelConfig::forDevice(deviceName);
if (!modelConfig.has_value()) {
VIAM_RESOURCE_LOG(error) << "Failed to determine model configuration for device " << deviceName;
continue;
}
viamModelSuffix = modelConfig->viam_model_suffix;

vsdk::ResourceConfig config("camera",
std::move(name.str()),
"viam",
attributes,
"rdk:component:camera",
vsdk::Model("viam", "orbbec", viamModelSuffix),
vsdk::log_level::info);
configs.push_back(config);

VIAM_RESOURCE_LOG(info) << "Successfully configured device " << (i + 1) << " with serial: " << serialNumber;
} catch (ob::Error& deviceError) {
VIAM_RESOURCE_LOG(error) << "Failed to get device info for device " << (i + 1) << ": " << deviceError.what();
// Continue with other devices even if one fails
}
}
} catch (ob::Error& e) {
VIAM_RESOURCE_LOG(error) << "Failed to discover Orbbec devices: " << e.what() << " (function: " << e.getFunction()
<< ", args: " << e.getArgs() << ", name: " << e.getName() << ", type: " << e.getExceptionType() << ")";
VIAM_RESOURCE_LOG(error) << "Discovery failed - check network connectivity for Ethernet cameras or USB connection for USB cameras";
} catch (const std::exception& e) {
VIAM_RESOURCE_LOG(error) << "Failed to discover Orbbec devices: " << e.what();
VIAM_RESOURCE_LOG(error) << "Discovery failed - check network connectivity for Ethernet cameras or USB connection for USB cameras";
} catch (...) {
VIAM_RESOURCE_LOG(error) << "Failed to discover Orbbec devices: unknown error";
VIAM_RESOURCE_LOG(error) << "Discovery failed - check network connectivity for Ethernet cameras or USB connection for USB cameras";
}

return configs;
}

vsdk::ProtoStruct OrbbecDiscovery::do_command(const vsdk::ProtoStruct& command) {
VIAM_SDK_LOG(error) << "do_command not implemented";
VIAM_RESOURCE_LOG(error) << "do_command not implemented";
return vsdk::ProtoStruct{};
}

Expand Down
12 changes: 10 additions & 2 deletions src/module/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,17 +17,25 @@ std::vector<std::shared_ptr<vsdk::ModelRegistration>> create_all_model_registrat

registrations.push_back(std::make_shared<vsdk::ModelRegistration>(
vsdk::API::get<vsdk::Camera>(),
orbbec::Orbbec::model,
orbbec::Orbbec::model_astra2,
[ctx](vsdk::Dependencies deps, vsdk::ResourceConfig config) {
return std::make_unique<orbbec::Orbbec>(std::move(deps), std::move(config), ctx);
},
orbbec::Orbbec::validate));
orbbec::Orbbec::validateAstra2));
registrations.push_back(std::make_shared<vsdk::ModelRegistration>(
vsdk::API::get<vsdk::Camera>(),
orbbec::Orbbec::model_gemini_335le,
[ctx](vsdk::Dependencies deps, vsdk::ResourceConfig config) {
return std::make_unique<orbbec::Orbbec>(std::move(deps), std::move(config), ctx);
},
orbbec::Orbbec::validateGemini335Le));

registrations.push_back(std::make_shared<vsdk::ModelRegistration>(
vsdk::API::get<vsdk::Discovery>(), discovery::OrbbecDiscovery::model, [ctx](vsdk::Dependencies deps, vsdk::ResourceConfig config) {
return std::make_unique<discovery::OrbbecDiscovery>(std::move(deps), std::move(config), ctx);
}));

// Return the registrations
return registrations;
}

Expand Down
Loading