diff --git a/CMakeLists.txt b/CMakeLists.txt index 7075c69..e5464e4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -93,7 +93,7 @@ else() PROGRAMS first_run.sh install_udev_rules.sh - DESTINATION ${CMAKE_INSTALL_PREFIX} + DESTINATION . ) # The lib/extensions directory contains some shared libraries which are # mandatory for our use case but not picked up by the runtime dependency set @@ -109,6 +109,6 @@ install( FILES meta.json 99-obsensor-libusb.rules - DESTINATION ${CMAKE_INSTALL_PREFIX} + DESTINATION . ) diff --git a/conanfile.py b/conanfile.py index df16d49..86b0f03 100644 --- a/conanfile.py +++ b/conanfile.py @@ -70,7 +70,10 @@ def deploy(self): self.output.info("Creating module.tar.gz") with tarfile.open("module.tar.gz", "w|gz") as tar: - tar.add(tmp_dir, ".") + # Add individual files directly from the directory to avoid the ./ prefix + for item in os.listdir(tmp_dir): + item_path = os.path.join(tmp_dir, item) + tar.add(item_path, arcname=item) self.output.debug("module.tar.gz contents:") for mem in tar.getmembers(): diff --git a/meta.json b/meta.json index e91fae2..5a92c7d 100644 --- a/meta.json +++ b/meta.json @@ -11,6 +11,12 @@ "model": "viam:orbbec:astra2", "short_description": "Orbbec Astra2 driver return images, depth maps and pointclouds" }, + { + "api": "rdk:component:camera", + "markdown_link": "README.md#model-viamorbbecgemini335le", + "model": "viam:orbbec:gemini_335le", + "short_description": "Orbbec Gemini 335Le driver return images, depth maps and pointclouds" + }, { "api": "rdk:service:discovery", "markdown_link": "README.md#model-viamorbbecdiscovery", diff --git a/src/module/orbbec.cpp b/src/module/orbbec.cpp index 06086be..0ad3ad8 100644 --- a/src/module/orbbec.cpp +++ b/src/module/orbbec.cpp @@ -70,6 +70,7 @@ static const OrbbecModelConfig ASTRA2_CONFIG{ "astra2", // viam_model_suffix {1280, 720}, // default_color_resolution {1600, 1200}, // default_depth_resolution + {1600, 1200}, // default_infrared_resolution "https://orbbec-debian-repos-aws.s3.amazonaws.com/product/Astra2_Release_2.8.20.zip", // firmware_url "2.8.20", // min_firmware_version {{{1920, 1080}, {{1600, 1200}, {800, 600}, {400, 300}}}, // Supported resolutions, 16:9 aspect ratio @@ -78,10 +79,13 @@ static const OrbbecModelConfig ASTRA2_CONFIG{ {{800, 600}, {{800, 600}, {400, 300}}}, // Supported resolutions, 4:3 aspect ratio {{640, 480}, {{800, 600}, {400, 300}}}, // Supported resolutions, 4:3 aspect ratio {{640, 360}, {{800, 600}, {400, 300}}}}, // Supported resolutions, 4:3 aspect ratio + {{"MJPG", {{1600, 1200}, {800, 600}}}}, // Supported infrared formats, 16:9 aspect ratio {"RGB", "MJPG"}, // supported_color_formats {"Y16"}, // supported_depth_formats + {"MJPG"}, // supported_infrared_formats "MJPG", // default_color_format - "Y16" // default_depth_format + "Y16", // default_depth_format + "MJPG" // default_infrared_format }; static const OrbbecModelConfig GEMINI_335LE_CONFIG{ @@ -89,16 +93,20 @@ static const OrbbecModelConfig GEMINI_335LE_CONFIG{ "gemini_335le", // viam_model_suffix {1280, 800}, // default_color_resolution {1280, 800}, // default_depth_resolution + {1280, 800}, // default_infrared_resolution "https://orbbec-debian-repos-aws.s3.amazonaws.com/product/Gemini330_Release_1.5.55.zip", // firmware_url "1.5.55", // min_firmware_version {{{1280, 800}, {{1280, 800}, {848, 530}, {640, 400}, {424, 266}, {320, 200}}}, // Supported resolutions, 16:10 aspect ratio {{848, 530}, {{848, 530}, {640, 400}, {424, 266}, {320, 200}}}, // 16:10 aspect ratio {{640, 400}, {{640, 400}, {424, 266}, {320, 200}}}, // 16:10 aspect ratio {{640, 480}, {{640, 480}}}}, // 4:3 aspect ratio + {{"MJPG", {{1280, 800}, {848, 530}, {640, 400}, {424, 266}, {320, 200}}}}, // Supported infrared formats {"MJPG"}, // supported_color_formats {"Y16"}, // supported_depth_formats + {"MJPG"}, // supported_infrared_formats "MJPG", // default_color_format - "Y16" // default_depth_format + "Y16", // default_depth_format + "MJPG" // default_infrared_format }; static const std::vector all_model_configs = {ASTRA2_CONFIG, GEMINI_335LE_CONFIG}; @@ -213,6 +221,25 @@ std::string formatError(Args&&... args) { return buffer.str(); } +void validateInfraredFrame(std::shared_ptr infrared, + const std::optional& device_format_opt, + const OrbbecModelConfig& modelConfig) { + if (infrared == nullptr) { + throw std::runtime_error(formatError("no infrared frame")); + } + + // Format validation + std::string frameFormat = ob::TypeHelper::convertOBFormatTypeToString(infrared->getFormat()); + if (modelConfig.supported_infrared_formats.count(frameFormat) == 0) { + std::ostringstream buffer; + buffer << "unsupported infrared format: " << frameFormat << ", supported: "; + for (const auto& fmt : modelConfig.supported_infrared_formats) { + buffer << fmt << ", "; + } + throw std::runtime_error(formatError(buffer.str())); + } +} + // Validate color frame format and timestamp void validateColorFrame(std::shared_ptr color, const std::optional& device_format_opt, @@ -441,30 +468,34 @@ bool profileMatchesSpec(std::shared_ptr vsp, std::optional deviceFormat, const OrbbecModelConfig& modelConfig, bool isColor) { + std::string requestedFormat = ""; if (deviceFormat.has_value()) { - std::string requestedFormat = isColor ? (deviceFormat->color_format.has_value() ? deviceFormat->color_format.value() : "") - : (deviceFormat->depth_format.has_value() ? deviceFormat->depth_format.value() : ""); - if (!requestedFormat.empty() && ob::TypeHelper::convertOBFormatTypeToString(vsp->getFormat()) != requestedFormat) { - return false; - } - } else { - std::string defaultFormat = isColor ? modelConfig.default_color_format : modelConfig.default_depth_format; - if (ob::TypeHelper::convertOBFormatTypeToString(vsp->getFormat()) != defaultFormat) { - return false; - } + requestedFormat = isColor ? (deviceFormat->color_format.has_value() ? deviceFormat->color_format.value() : "") + : (deviceFormat->depth_format.has_value() ? deviceFormat->depth_format.value() : ""); + } + if (requestedFormat.empty()) { + requestedFormat = isColor ? modelConfig.default_color_format : modelConfig.default_depth_format; + } + if (ob::TypeHelper::convertOBFormatTypeToString(vsp->getFormat()) != requestedFormat) { + return false; } + Resolution requestedRes; + bool hasRequestedRes = false; if (deviceRes.has_value()) { - auto requestedRes = isColor ? deviceRes->color_resolution : deviceRes->depth_resolution; - if (requestedRes.has_value() && (vsp->getWidth() != requestedRes->width || vsp->getHeight() != requestedRes->height)) { - return false; - } - } else { - auto defaultRes = isColor ? modelConfig.default_color_resolution : modelConfig.default_depth_resolution; - if (vsp->getWidth() != defaultRes.width || vsp->getHeight() != defaultRes.height) { - return false; + auto resOpt = isColor ? deviceRes->color_resolution : deviceRes->depth_resolution; + if (resOpt.has_value()) { + requestedRes = *resOpt; + hasRequestedRes = true; } } + if (!hasRequestedRes) { + requestedRes = isColor ? modelConfig.default_color_resolution : modelConfig.default_depth_resolution; + } + + if (vsp->getWidth() != requestedRes.width || vsp->getHeight() != requestedRes.height) { + return false; + } return true; } @@ -636,8 +667,8 @@ std::shared_ptr createHwD2CAlignConfig(std::shared_ptr auto frameCallback(const std::string& serialNumber) { return [serialNumber](std::shared_ptr frameSet) { - if (frameSet->getCount() != 2) { - std::cerr << "got non 2 frame count: " << frameSet->getCount() << "\n"; + if (frameSet->getCount() < 2 || frameSet->getCount() > 3) { + std::cerr << "got invalid frame count: " << frameSet->getCount() << ", expected 2 or 3\n"; return; } std::shared_ptr color = frameSet->getFrame(OB_FRAME_COLOR); @@ -652,6 +683,14 @@ auto frameCallback(const std::string& serialNumber) { return; } + if (frameSet->getCount() == 3) { + std::shared_ptr infrared = frameSet->getFrame(OB_FRAME_IR); + if (infrared == nullptr) { + std::cerr << "no infrared frame\n"; + return; + } + } + std::lock_guard lock(frame_set_by_serial_mu()); uint64_t nowUs = getNowUs(); uint64_t diff = timeSinceFrameUs(nowUs, color->getSystemTimeStampUs()); @@ -667,7 +706,7 @@ auto frameCallback(const std::string& serialNumber) { auto it = frame_set_by_serial().find(serialNumber); if (it != frame_set_by_serial().end()) { - std::shared_ptr prevColor = it->second->getFrame(OB_FRAME_COLOR); + std::shared_ptr prevColor = it->second->getFrame(OB_FRAME_IR); std::shared_ptr prevDepth = it->second->getFrame(OB_FRAME_DEPTH); if (prevColor != nullptr && prevDepth != nullptr) { diff = timeSinceFrameUs(color->getSystemTimeStampUs(), prevColor->getSystemTimeStampUs()); @@ -777,6 +816,63 @@ void configureDevice(std::string serialNumber, OrbbecModelConfig const& modelCon buffer << service_name << ": unable to configure device " << serialNumber << " - no valid stream configuration found"; throw std::runtime_error(buffer.str()); } + + // Get enabled_sensors from the config stored in config_by_serial + std::unordered_set enabled_sensors; + { + std::lock_guard lock(config_by_serial_mu()); + if (config_by_serial().count(serialNumber) > 0) { + enabled_sensors = config_by_serial().at(serialNumber).enabled_sensors; + } else { + // Default: color and depth are always enabled + enabled_sensors = {"color", "depth"}; + } + } + + if (enabled_sensors.count("infrared") > 0) { + auto infraredStreamProfiles = my_dev->pipe->getStreamProfileList(OB_SENSOR_IR); + if (infraredStreamProfiles->getCount() > 0) { + VIAM_SDK_LOG(info) << "Amount of infrared stream profiles: " << infraredStreamProfiles->getCount() << "\n"; + std::shared_ptr bestProfile; + for (uint32_t i = 0; i < infraredStreamProfiles->getCount(); i++) { + auto infraredVsp = infraredStreamProfiles->getProfile(i)->as(); + VIAM_SDK_LOG(info) << "Checking infrared stream profile: format: " + << ob::TypeHelper::convertOBFormatTypeToString(infraredVsp->getFormat()) + << " width: " << infraredVsp->getWidth() << " height: " << infraredVsp->getHeight() + << " fps: " << infraredVsp->getFps() << "\n"; + + std::string targetFormat = + format_opt && format_opt->infrared_format ? *format_opt->infrared_format : modelConfig.default_infrared_format; + if (ob::TypeHelper::convertOBFormatTypeToString(infraredVsp->getFormat()) != targetFormat) { + continue; + } + + Resolution targetRes = resolution_opt && resolution_opt->infrared_resolution ? *resolution_opt->infrared_resolution + : modelConfig.default_infrared_resolution; + if (infraredVsp->getWidth() != targetRes.width || infraredVsp->getHeight() != targetRes.height) { + continue; + } + + VIAM_SDK_LOG(info) << "Found matching infrared stream profile: format: " + << ob::TypeHelper::convertOBFormatTypeToString(infraredVsp->getFormat()) + << " width: " << infraredVsp->getWidth() << " height: " << infraredVsp->getHeight() + << " fps: " << infraredVsp->getFps() << "\n"; + + // We want the profile with the highest FPS for the chosen resolution and format + if (!bestProfile || infraredVsp->getFps() > bestProfile->as()->getFps()) { + bestProfile = infraredStreamProfiles->getProfile(i); + } + } + if (bestProfile) { + auto vsp = bestProfile->as(); + VIAM_SDK_LOG(info) << "Enabling infrared stream profile: format: " + << ob::TypeHelper::convertOBFormatTypeToString(vsp->getFormat()) << " width: " << vsp->getWidth() + << " height: " << vsp->getHeight() << " fps: " << vsp->getFps() << "\n"; + config->enableStream(bestProfile); + } + } + } + my_dev->config = config; } @@ -895,8 +991,18 @@ void Orbbec::validate_sensor(std::pair const VIAM_SDK_LOG(error) << buffer.str(); throw std::invalid_argument(buffer.str()); } + } else if (sensor_type == "infrared") { + if (!modelConfig.supported_infrared_formats.count(*format)) { + std::ostringstream buffer; + buffer << "infrared sensor format must be one of: "; + for (const auto& type : modelConfig.supported_infrared_formats) { + buffer << type << " "; + } + VIAM_SDK_LOG(error) << buffer.str(); + throw std::invalid_argument(buffer.str()); + } } else { - throw std::invalid_argument("sensor type must be color or depth"); + throw std::invalid_argument("sensor type must be color, depth or infrared"); } } @@ -927,10 +1033,15 @@ std::vector Orbbec::validateOrbbecModel(vsdk::ResourceConfig cfg, O validate_sensor(sensor_pair, modelConfig); } } - auto color_width_uint32 = - static_cast(*sensors->at("color").get()->at("width").get()); - auto color_height_uint32 = - static_cast(*sensors->at("color").get()->at("height").get()); + + std::uint32_t color_width_uint32 = modelConfig.default_color_resolution.width; + std::uint32_t color_height_uint32 = modelConfig.default_color_resolution.height; + if (sensors->count("color")) { + auto const& color_struct = sensors->at("color").get_unchecked(); + color_width_uint32 = static_cast(color_struct.at("width").get_unchecked()); + color_height_uint32 = static_cast(color_struct.at("height").get_unchecked()); + } + if (modelConfig.color_to_depth_supported_resolutions.count({color_width_uint32, color_height_uint32}) == 0) { std::ostringstream buffer; buffer << "color resolution must be one of: "; @@ -940,10 +1051,15 @@ std::vector Orbbec::validateOrbbecModel(vsdk::ResourceConfig cfg, O VIAM_SDK_LOG(error) << buffer.str(); throw std::invalid_argument(buffer.str()); } - auto depth_width_uint32 = - static_cast(*sensors->at("depth").get()->at("width").get()); - auto depth_height_uint32 = - static_cast(*sensors->at("depth").get()->at("height").get()); + + std::uint32_t depth_width_uint32 = modelConfig.default_depth_resolution.width; + std::uint32_t depth_height_uint32 = modelConfig.default_depth_resolution.height; + if (sensors->count("depth")) { + auto const& depth_struct = sensors->at("depth").get_unchecked(); + depth_width_uint32 = static_cast(depth_struct.at("width").get_unchecked()); + depth_height_uint32 = static_cast(depth_struct.at("height").get_unchecked()); + } + if (modelConfig.color_to_depth_supported_resolutions.at({color_width_uint32, color_height_uint32}) .count({depth_width_uint32, depth_height_uint32}) == 0) { std::ostringstream buffer; @@ -1169,19 +1285,32 @@ vsdk::Camera::raw_image Orbbec::get_image(std::string mime_type, const vsdk::Pro } fs = search->second; } - std::shared_ptr color = fs->getFrame(OB_FRAME_COLOR); + std::shared_ptr image = nullptr; + bool is_infrared = false; + + // Get enabled_sensors from the config stored in config_by_serial + std::unordered_set enabled_sensors; std::optional res_format_opt; { std::lock_guard lock(config_by_serial_mu()); if (config_by_serial().count(serial_number) == 0) { throw std::invalid_argument("device with serial number " + serial_number + " is not in config_by_serial"); } + enabled_sensors = config_by_serial().at(serial_number).enabled_sensors; res_format_opt = config_by_serial().at(serial_number).device_format; } - validateColorFrame(color, res_format_opt, *model_config_); - vsdk::Camera::raw_image response = encodeColorFrame(color); + // Select frame based on enabled sensors: infrared takes priority if enabled, otherwise color + if (enabled_sensors.count("infrared") > 0) { + image = fs->getFrame(OB_FRAME_IR); + validateInfraredFrame(image, res_format_opt, *model_config_); + } else { + image = fs->getFrame(OB_FRAME_COLOR); + validateColorFrame(image, res_format_opt, *model_config_); + } + + vsdk::Camera::raw_image response = encodeColorFrame(image); VIAM_RESOURCE_LOG(debug) << "[get_image] end"; return response; } catch (const std::exception& e) { @@ -1280,42 +1409,66 @@ vsdk::Camera::image_collection Orbbec::get_images(std::vector filte throw std::runtime_error("no frameset"); } + // Get enabled_sensors and device_format from the config stored in config_by_serial + std::unordered_set enabled_sensors; + std::optional device_format_opt; + { + std::lock_guard lock(config_by_serial_mu()); + if (config_by_serial().count(serial_number) == 0) { + throw std::runtime_error("device with serial number " + serial_number + " is not in config_by_serial"); + } + enabled_sensors = config_by_serial().at(serial_number).enabled_sensors; + device_format_opt = config_by_serial().at(serial_number).device_format; + } + bool should_process_color = false; bool should_process_depth = false; + bool should_process_infrared = false; if (filter_source_names.empty()) { - should_process_color = true; - should_process_depth = true; + // If no filter, process all enabled sensors + if (enabled_sensors.count("infrared") > 0) { + should_process_infrared = true; + } else if (enabled_sensors.count("color") > 0) { + should_process_color = true; + } + should_process_depth = enabled_sensors.count("depth") > 0; } else { for (const auto& name : filter_source_names) { if (name == kColorSourceName) { - should_process_color = true; + if (enabled_sensors.count("infrared") > 0) { + should_process_infrared = true; + } else if (enabled_sensors.count("color") > 0) { + should_process_color = true; + } } - if (name == kDepthSourceName) { + if (name == kDepthSourceName && enabled_sensors.count("depth") > 0) { should_process_depth = true; } } } vsdk::Camera::image_collection response; - std::shared_ptr color = nullptr; + std::shared_ptr image = nullptr; std::shared_ptr depth = nullptr; uint64_t nowUs = getNowUs(); - std::optional device_format_opt; - { - std::lock_guard lock(config_by_serial_mu()); - if (config_by_serial().count(serial_number) == 0) { - throw std::runtime_error("device with serial number " + serial_number + " is not in config_by_serial"); - } - device_format_opt = config_by_serial().at(serial_number).device_format; + + if (should_process_infrared && should_process_color) { + throw std::runtime_error("infrared and color cannot be processed at the same time"); } if (should_process_color) { - color = fs->getFrame(OB_FRAME_COLOR); - validateColorFrame(color, device_format_opt, *model_config_); + image = fs->getFrame(OB_FRAME_COLOR); + validateColorFrame(image, device_format_opt, *model_config_); - vsdk::Camera::raw_image color_image = encodeColorFrame(color); - response.images.emplace_back(std::move(color_image)); + vsdk::Camera::raw_image image_image = encodeColorFrame(image); + response.images.emplace_back(std::move(image_image)); + } else if (should_process_infrared) { + image = fs->getFrame(OB_FRAME_IR); + validateInfraredFrame(image, device_format_opt, *model_config_); + + vsdk::Camera::raw_image image_image = encodeColorFrame(image); + response.images.emplace_back(std::move(image_image)); } if (should_process_depth) { @@ -1340,20 +1493,20 @@ vsdk::Camera::image_collection Orbbec::get_images(std::vector filte return response; } - uint64_t colorTS = color ? color->getSystemTimeStampUs() : 0; + uint64_t imageTS = image ? image->getSystemTimeStampUs() : 0; uint64_t depthTS = depth ? depth->getSystemTimeStampUs() : 0; uint64_t timestamp = 0; - if (colorTS > 0 && depthTS > 0) { - if (colorTS != depthTS) { + if (imageTS > 0 && depthTS > 0) { + if (imageTS != depthTS) { VIAM_RESOURCE_LOG(info) << "color and depth timestamps differ, defaulting to " "older of the two" - << "color timestamp was " << colorTS << " depth timestamp was " << depthTS; + << "image timestamp was " << imageTS << " depth timestamp was " << depthTS; } // use the older of the two timestamps - timestamp = (colorTS > depthTS) ? depthTS : colorTS; - } else if (colorTS > 0) { - timestamp = colorTS; + timestamp = (imageTS > depthTS) ? depthTS : imageTS; + } else if (imageTS > 0) { + timestamp = imageTS; } else { timestamp = depthTS; } @@ -1626,24 +1779,61 @@ std::unique_ptr Orbbec::configure(vsdk::Dependencies d VIAM_SDK_LOG(info) << "[configure] sensors specified in config"; auto sensors = attrs["sensors"].get(); - auto const color_height = sensors->at("color").get()->at("height").get_unchecked(); - auto const color_width = sensors->at("color").get()->at("width").get_unchecked(); - auto const color_res = Resolution{static_cast(color_width), static_cast(color_height)}; - auto const color_format = sensors->at("color").get()->at("format").get_unchecked(); + std::optional color_res = std::nullopt; + std::optional color_format = std::nullopt; + if (sensors->count("color")) { + auto const& color_struct = sensors->at("color").get_unchecked(); + color_res = Resolution{static_cast(color_struct.at("width").get_unchecked()), + static_cast(color_struct.at("height").get_unchecked())}; + color_format = color_struct.at("format").get_unchecked(); + } + + std::optional depth_res = std::nullopt; + std::optional depth_format = std::nullopt; + if (sensors->count("depth")) { + auto const& depth_struct = sensors->at("depth").get_unchecked(); + depth_res = Resolution{static_cast(depth_struct.at("width").get_unchecked()), + static_cast(depth_struct.at("height").get_unchecked())}; + depth_format = depth_struct.at("format").get_unchecked(); + } + + std::optional infrared_res = std::nullopt; + std::optional infrared_format = std::nullopt; - auto const depth_height = sensors->at("depth").get()->at("height").get_unchecked(); - auto const depth_width = sensors->at("depth").get()->at("width").get_unchecked(); - auto const depth_res = Resolution{static_cast(depth_width), static_cast(depth_height)}; - auto const depth_format = sensors->at("depth").get()->at("format").get_unchecked(); + // Build enabled_sensors dynamically: color and depth are always enabled, infrared if specified + std::unordered_set enabled_sensors{"color", "depth"}; + if (sensors->count("infrared")) { + auto infrared_struct = sensors->at("infrared").get(); + infrared_res = Resolution{static_cast(infrared_struct->at("width").get_unchecked()), + static_cast(infrared_struct->at("height").get_unchecked())}; + infrared_format = infrared_struct->at("format").get_unchecked(); + enabled_sensors.insert("infrared"); + } - dev_res = DeviceResolution{color_res, depth_res}; - dev_fmt = DeviceFormat{color_format, depth_format}; + if (color_res || depth_res || infrared_res) { + dev_res = DeviceResolution{color_res, depth_res, infrared_res}; + } + if (color_format || depth_format || infrared_format) { + dev_fmt = DeviceFormat{color_format, depth_format, infrared_format}; + } + + VIAM_SDK_LOG(info) << "[configure] enabled_sensors: "; + for (const auto& sensor : enabled_sensors) { + VIAM_SDK_LOG(info) << sensor << " "; + } + auto native_config = + std::make_unique(serial_number_from_config, configuration.name(), dev_res, dev_fmt, enabled_sensors); + VIAM_SDK_LOG(info) << "[configure] configured: " << native_config->to_string(); + return native_config; } else { VIAM_SDK_LOG(info) << "[configure] no sensors specified in config, using defaults"; + // Default: color and depth are always enabled + std::unordered_set enabled_sensors{"color", "depth"}; + auto native_config = + std::make_unique(serial_number_from_config, configuration.name(), dev_res, dev_fmt, enabled_sensors); + VIAM_SDK_LOG(info) << "[configure] configured: " << native_config->to_string(); + return native_config; } - auto native_config = std::make_unique(serial_number_from_config, configuration.name(), dev_res, dev_fmt); - VIAM_SDK_LOG(info) << "[configure] configured: " << native_config->to_string(); - return native_config; } // RESOURCE END diff --git a/src/module/orbbec.hpp b/src/module/orbbec.hpp index 1dff562..c54dbc8 100644 --- a/src/module/orbbec.hpp +++ b/src/module/orbbec.hpp @@ -29,7 +29,7 @@ struct Resolution { struct DeviceResolution { std::optional color_resolution{}; std::optional depth_resolution{}; - + std::optional infrared_resolution{}; std::string to_string() const { std::ostringstream os; os << "DeviceResolution("; @@ -41,6 +41,10 @@ struct DeviceResolution { os << ", depth_resolution=" << depth_resolution->width << "x" << depth_resolution->height; else os << ", depth_resolution=nullopt"; + if (infrared_resolution.has_value()) + os << ", infrared_resolution=" << infrared_resolution->width << "x" << infrared_resolution->height; + else + os << ", infrared_resolution=nullopt"; os << ")"; return os.str(); } @@ -49,7 +53,7 @@ struct DeviceResolution { struct DeviceFormat { std::optional color_format{}; std::optional depth_format{}; - + std::optional infrared_format{}; std::string to_string() const { std::ostringstream os; os << "("; @@ -61,6 +65,10 @@ struct DeviceFormat { os << ", depth_format=" << *depth_format; else os << ", depth_format=nullopt"; + if (infrared_format.has_value()) + os << ", infrared_format=" << *infrared_format; + else + os << ", infrared_format=nullopt"; os << ")"; return os.str(); } @@ -72,12 +80,18 @@ struct ObResourceConfig { std::string serial_number; std::optional device_resolution; std::optional device_format; + std::unordered_set enabled_sensors; explicit ObResourceConfig(std::string const& serial_number, std::string const& resource_name, std::optional device_resolution, - std::optional device_format) - : serial_number(serial_number), resource_name(resource_name), device_resolution(device_resolution), device_format(device_format) {} + std::optional device_format, + std::unordered_set enabled_sensors = {"color", "depth"}) + : serial_number(serial_number), + resource_name(resource_name), + device_resolution(device_resolution), + device_format(device_format), + enabled_sensors(enabled_sensors) {} std::string to_string() const { std::ostringstream os; os << "(resource_name=" << resource_name << ", serial_number=" << serial_number; @@ -101,13 +115,17 @@ struct OrbbecModelConfig { std::string viam_model_suffix; // "astra2" or "gemini_335le" Resolution default_color_resolution; Resolution default_depth_resolution; + Resolution default_infrared_resolution; std::optional firmware_url; std::string min_firmware_version; std::map>, std::greater> color_to_depth_supported_resolutions; + std::map>> infrared_format_to_resolutions; std::unordered_set supported_color_formats; std::unordered_set supported_depth_formats; + std::unordered_set supported_infrared_formats; std::string default_color_format; std::string default_depth_format; + std::string default_infrared_format; // Get config for a device name static std::optional forDevice(const std::string& device_name);