mirror of
https://github.com/orbbec/OrbbecSDK_ROS2.git
synced 2026-09-12 11:10:19 +08:00
Merge branch 'merge/ros_2.9.3' into v2/develop
This commit is contained in:
@@ -78,6 +78,20 @@ typedef enum {
|
||||
*/
|
||||
OB_EXPORT ob_application_config *ob_device_get_application_config(ob_device *device, ob_error **error);
|
||||
|
||||
/**
|
||||
* @brief Get the application configuration carried by an externally imported preset, by preset name.
|
||||
*
|
||||
* @param[in] device The device object.
|
||||
* @param[in] preset_name The preset name to query.
|
||||
* @param[out] error Pointer to an error object that will be set if an error occurs.
|
||||
*
|
||||
* @return ob_application_config* The application configuration imported with the given preset, or NULL for
|
||||
* built-in presets or presets that carry no application configuration.
|
||||
* @attention The returned config is owned by the device; it should still be released by calling
|
||||
* @ref ob_delete_application_config (releasing the handle does not destroy the cached object).
|
||||
*/
|
||||
OB_EXPORT ob_application_config *ob_device_get_application_config_by_preset(ob_device *device, const char *preset_name, ob_error **error);
|
||||
|
||||
/**
|
||||
* @brief Delete an application configuration object.
|
||||
*
|
||||
|
||||
@@ -163,6 +163,76 @@ OB_EXPORT void ob_device_set_structured_data(ob_device *device, ob_property_id p
|
||||
*/
|
||||
OB_EXPORT void ob_device_get_structured_data(ob_device *device, ob_property_id property_id, uint8_t *data, uint32_t *data_size, ob_error **error);
|
||||
|
||||
/**
|
||||
* @brief Check whether the device supports license authorization.
|
||||
*
|
||||
* This function only reports whether the device provides the license authorization
|
||||
* capability. It does not read or validate the license information.
|
||||
*
|
||||
* @param[in] device The device object.
|
||||
* @param[out] error Log error messages.
|
||||
* @return true if the device supports license authorization, false otherwise.
|
||||
*/
|
||||
OB_EXPORT bool ob_device_is_license_authorization_supported(const ob_device *device, ob_error **error);
|
||||
|
||||
/**
|
||||
* @brief Write signed device license information.
|
||||
*
|
||||
* The license_info_json is a UTF-8 JSON string with the following structure. All
|
||||
* binary fields are lowercase hex strings without a "0x" prefix and with a fixed
|
||||
* length. Before writing, the SDK reads the currently connected device and compares
|
||||
* it against "devInfo" to prevent writing a license to the wrong device; it does NOT
|
||||
* verify the signature or recompute deviceHash (signature and device-binding checks
|
||||
* are performed by the consumer/filter at runtime).
|
||||
*
|
||||
* {
|
||||
* "formatVersion": 1, // license_info envelope version
|
||||
* "devInfo": { // plaintext, NOT signed; used only to
|
||||
* "deviceSn": "SN123456789", // guard against mis-writing to the
|
||||
* "vid": "2BC5", // wrong device. vid/pid are 4-char
|
||||
* "pid": "0660" // uppercase hex.
|
||||
* },
|
||||
* "licenseInfo": { // signed authorization credential
|
||||
* "schemaVersion": 1, // credential schema version
|
||||
* "keyVersion": 1, // 16-bit signing public key id
|
||||
* "featureFlags": "0000000000000001",// 8 bytes, 16-char lowercase hex
|
||||
* "expireDate": 4294967295, // YYYYMMDD; 0xFFFFFFFF = permanent
|
||||
* "deviceHash": "00112233445566778899aabbccddeeff", // 16 bytes, 32-char hex
|
||||
* "signature": "...", // ECDSA P-256 r||s, 64 bytes, 128-char hex
|
||||
* "vendorLicense": "..." // third-party vendor blob, lowercase hex (235 bytes)
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* @param[in] device The device object.
|
||||
* @param[in] license_info_json The SDK license_info JSON string described above.
|
||||
* @param[in] license_info_json_size The byte size of license_info_json, excluding any trailing null terminator.
|
||||
* @param[out] error Pointer to an error object that will be set if an error occurs.
|
||||
*/
|
||||
OB_EXPORT void ob_device_write_license_info(ob_device *device, const char *license_info_json, uint32_t license_info_json_size, ob_error **error);
|
||||
|
||||
/**
|
||||
* @brief Read signed device license information as SDK license_info JSON.
|
||||
*
|
||||
* @param[in] device The device object.
|
||||
* @param[out] license_info_json The output buffer for SDK license_info JSON, null-terminated on success.
|
||||
* @param[in] license_info_json_size Size of the output buffer in bytes. Must be large enough to hold the JSON string and a trailing null terminator; 512
|
||||
* bytes is sufficient for the current schema.
|
||||
* @param[out] error Pointer to an error object that will be set if an error occurs.
|
||||
*/
|
||||
OB_EXPORT void ob_device_read_license_info(const ob_device *device, char *license_info_json, uint32_t license_info_json_size, ob_error **error);
|
||||
|
||||
/**
|
||||
* @brief Clear license information stored on the device.
|
||||
*
|
||||
* Erases the device license storage area so that the device returns to the
|
||||
* "no license" state. Intended for internal repair, re-activation or debugging
|
||||
* builds and should be gated by caller-side confirmation.
|
||||
*
|
||||
* @param[in] device The device object.
|
||||
* @param[out] error Pointer to an error object that will be set if an error occurs.
|
||||
*/
|
||||
OB_EXPORT void ob_device_clear_license_info(ob_device *device, ob_error **error);
|
||||
|
||||
/**
|
||||
* @brief Get raw data of a device property.
|
||||
*
|
||||
@@ -286,6 +356,19 @@ OB_EXPORT void ob_device_update_firmware_from_data(ob_device *device, const uint
|
||||
OB_EXPORT void ob_device_update_optional_depth_presets(ob_device *device, const char file_path_list[][OB_PATH_MAX], uint8_t path_count,
|
||||
ob_device_fw_update_callback callback, void *user_data, ob_error **error);
|
||||
|
||||
/**
|
||||
* @brief Update the device optional depth presets from data loaded in memory.
|
||||
*
|
||||
* @param[in] device The device object.
|
||||
* @param[in] data_list A list of preset data blocks, each holding a data pointer and its size.
|
||||
* @param[in] count The number of the preset data blocks.
|
||||
* @param[in] callback The preset upgrade progress callback.
|
||||
* @param[in] user_data User-defined data that will be returned in the callback.
|
||||
* @param[out] error Pointer to an error object that will be set if an error occurs.
|
||||
*/
|
||||
OB_EXPORT void ob_device_update_optional_depth_presets_from_data(ob_device *device, const ob_data_view *data_list, uint8_t count,
|
||||
ob_device_fw_update_callback callback, void *user_data, ob_error **error);
|
||||
|
||||
/**
|
||||
* @brief Device reboot
|
||||
* @attention The device will be disconnected and reconnected. After the device is disconnected, the interface access to the device handle may be abnormal.
|
||||
@@ -337,6 +420,16 @@ OB_EXPORT void ob_device_enable_heartbeat(ob_device *device, bool enable, ob_err
|
||||
*/
|
||||
OB_EXPORT void ob_device_enable_firmware_log(ob_device *device, bool enable, ob_error **error);
|
||||
|
||||
/**
|
||||
* @brief Check whether the device firmware log is enabled.
|
||||
*
|
||||
* @param[in] device The device object.
|
||||
* @param[out] error Pointer to an error object that will be set if an error occurs.
|
||||
*
|
||||
* @return bool Whether the firmware log is enabled.
|
||||
*/
|
||||
OB_EXPORT bool ob_device_is_firmware_log_enabled(ob_device *device, ob_error **error);
|
||||
|
||||
/**
|
||||
* @brief Synchronize the device time (synchronize hardwarePPS time to device)
|
||||
*
|
||||
@@ -426,7 +519,7 @@ OB_EXPORT const char *ob_device_info_get_uid(const ob_device_info *info, ob_erro
|
||||
*
|
||||
* @param[in] info Device Information
|
||||
* @param[out] error Pointer to an error object that will be set if an error occurs.
|
||||
*
|
||||
*
|
||||
* @return const char* return device serial number
|
||||
*/
|
||||
OB_EXPORT const char *ob_device_info_get_serial_number(const ob_device_info *info, ob_error **error);
|
||||
@@ -436,7 +529,7 @@ OB_EXPORT const char *ob_device_info_get_serial_number(const ob_device_info *inf
|
||||
*
|
||||
* @param[in] info Device Information
|
||||
* @param[out] error Pointer to an error object that will be set if an error occurs.
|
||||
*
|
||||
*
|
||||
* @return int return the firmware version number
|
||||
*/
|
||||
OB_EXPORT const char *ob_device_info_get_firmware_version(const ob_device_info *info, ob_error **error);
|
||||
@@ -458,7 +551,7 @@ OB_EXPORT const char *ob_device_info_get_connection_type(const ob_device_info *i
|
||||
*
|
||||
* @param[in] info Device Information
|
||||
* @param[out] error Pointer to an error object that will be set if an error occurs.
|
||||
*
|
||||
*
|
||||
* @return const char* The IP address, such as "192.168.1.10"
|
||||
*/
|
||||
OB_EXPORT const char *ob_device_info_get_ip_address(const ob_device_info *info, ob_error **error);
|
||||
@@ -520,7 +613,7 @@ OB_EXPORT const char *ob_device_get_extension_info(const ob_device *device, cons
|
||||
*
|
||||
* @param[in] info Device Information
|
||||
* @param[out] error Pointer to an error object that will be set if an error occurs.
|
||||
*
|
||||
*
|
||||
* @return const char* The minimum SDK version number supported by the device
|
||||
*/
|
||||
OB_EXPORT const char *ob_device_info_get_supported_min_sdk_version(const ob_device_info *info, ob_error **error);
|
||||
@@ -530,7 +623,7 @@ OB_EXPORT const char *ob_device_info_get_supported_min_sdk_version(const ob_devi
|
||||
*
|
||||
* @param[in] info Device Information
|
||||
* @param[out] error Pointer to an error object that will be set if an error occurs.
|
||||
*
|
||||
*
|
||||
* @return const char* The ASIC name
|
||||
*/
|
||||
OB_EXPORT const char *ob_device_info_get_asicName(const ob_device_info *info, ob_error **error);
|
||||
@@ -540,7 +633,7 @@ OB_EXPORT const char *ob_device_info_get_asicName(const ob_device_info *info, ob
|
||||
*
|
||||
* @param[in] info Device Information
|
||||
* @param[out] error Pointer to an error object that will be set if an error occurs.
|
||||
*
|
||||
*
|
||||
* @return ob_device_type The device type
|
||||
*/
|
||||
OB_EXPORT ob_device_type ob_device_info_get_device_type(const ob_device_info *info, ob_error **error);
|
||||
@@ -558,7 +651,7 @@ OB_EXPORT void ob_delete_device_list(ob_device_list *list, ob_error **error);
|
||||
*
|
||||
* @param[in] list Device list object
|
||||
* @param[out] error Pointer to an error object that will be set if an error occurs.
|
||||
*
|
||||
*
|
||||
* @return uint32_t return the number of devices
|
||||
*/
|
||||
OB_EXPORT uint32_t ob_device_list_get_count(const ob_device_list *list, ob_error **error);
|
||||
@@ -569,7 +662,7 @@ OB_EXPORT uint32_t ob_device_list_get_count(const ob_device_list *list, ob_error
|
||||
* @param[in] list Device list object
|
||||
* @param[in] index Device index
|
||||
* @param[out] error Pointer to an error object that will be set if an error occurs.
|
||||
*
|
||||
*
|
||||
* @return const char* return device name
|
||||
*/
|
||||
OB_EXPORT const char *ob_device_list_get_device_name(const ob_device_list *list, uint32_t index, ob_error **error);
|
||||
@@ -580,7 +673,7 @@ OB_EXPORT const char *ob_device_list_get_device_name(const ob_device_list *list,
|
||||
* @param[in] list Device list object
|
||||
* @param[in] index Device index
|
||||
* @param[out] error Pointer to an error object that will be set if an error occurs.
|
||||
*
|
||||
*
|
||||
* @return int return the device pid
|
||||
*/
|
||||
OB_EXPORT int ob_device_list_get_device_pid(const ob_device_list *list, uint32_t index, ob_error **error);
|
||||
@@ -763,6 +856,46 @@ OB_EXPORT ob_ip_source_type ob_device_list_get_device_ip_source_type(const ob_de
|
||||
*/
|
||||
OB_EXPORT const char *ob_device_list_get_device_user_name(const ob_device_list *list, uint32_t index, ob_error **error);
|
||||
|
||||
/**
|
||||
* @brief Query the current device access state without opening the device.
|
||||
*
|
||||
* @attention This is a non-invasive GVCP CCP query for supported Ethernet devices. It reports device-side CCP state, not the owner process or host.
|
||||
* For non-Ethernet devices or Ethernet devices without CCP support, it returns OB_DEVICE_ACCESS_STATE_UNSUPPORTED.
|
||||
* CONTROLLED means monitor access may still be available, while default/control access may still fail.
|
||||
* This call is synchronous and blocks while waiting for the device's GVCP response over the network; querying an unreachable device blocks until the
|
||||
* underlying retry logic gives up, so prefer calling it off the UI thread when querying multiple devices.
|
||||
* The returned state reflects the device access state only at the moment of the query and does not guarantee that a subsequent access (such as creating or
|
||||
* opening the device) will succeed, as another client may change the state in between.
|
||||
*
|
||||
* @param[in] list Device list object.
|
||||
* @param[in] index The index of the device.
|
||||
* @param[out] error Pointer to an error object that will be set if an error occurs.
|
||||
*
|
||||
* @return The current access state of the device.
|
||||
*/
|
||||
OB_EXPORT ob_device_access_state ob_device_list_query_device_access_state(const ob_device_list *list, uint32_t index, ob_error **error);
|
||||
|
||||
/**
|
||||
* @brief Query the current device access state by serial number without opening the device.
|
||||
*
|
||||
* @attention This is a non-invasive GVCP CCP query for supported Ethernet devices. It reports device-side CCP state, not the owner process or host.
|
||||
* For non-Ethernet devices or Ethernet devices without CCP support, it returns OB_DEVICE_ACCESS_STATE_UNSUPPORTED.
|
||||
* CONTROLLED means monitor access may still be available, while default/control access may still fail.
|
||||
* This call is synchronous and blocks while waiting for the device's GVCP response over the network; querying an unreachable device blocks until the
|
||||
* underlying retry logic gives up, so prefer calling it off the UI thread when querying multiple devices.
|
||||
* The returned state reflects the device access state only at the moment of the query and does not guarantee that a subsequent access (such as creating or
|
||||
* opening the device) will succeed, as another client may change the state in between.
|
||||
* If no device in the list matches the given serial number, an error is set via the error parameter.
|
||||
*
|
||||
* @param[in] list Device list object.
|
||||
* @param[in] serial_number The serial number of the device.
|
||||
* @param[out] error Pointer to an error object that will be set if an error occurs.
|
||||
*
|
||||
* @return The current access state of the device.
|
||||
*/
|
||||
OB_EXPORT ob_device_access_state ob_device_list_query_device_access_state_by_serial_number(const ob_device_list *list, const char *serial_number,
|
||||
ob_error **error);
|
||||
|
||||
/**
|
||||
* @brief Create a device.
|
||||
*
|
||||
|
||||
@@ -56,6 +56,16 @@ OB_EXPORT const char *ob_filter_get_vendor_specific_code(const char *name, ob_er
|
||||
*/
|
||||
OB_EXPORT ob_filter *ob_create_private_filter(const char *name, const char *activation_key, ob_error **error);
|
||||
|
||||
/**
|
||||
* @brief Activate a private filter object with a specific device.
|
||||
*
|
||||
* @param[in] filter The private filter object.
|
||||
* @param[in] device The device to associate with the activation.
|
||||
* @param[in] options Optional extensible activation options (may be NULL). See @ref ob_priv_filter_activate_options.
|
||||
* @param[out] error Pointer to an error object that will be set if an error occurs.
|
||||
*/
|
||||
OB_EXPORT void ob_filter_activate_private_ex(ob_filter *filter, ob_device *device, const ob_priv_filter_activate_options *options, ob_error **error);
|
||||
|
||||
/**
|
||||
* @brief Delete the filter.
|
||||
*
|
||||
|
||||
@@ -397,6 +397,35 @@ OB_EXPORT ob_sensor *ob_frame_get_sensor(const ob_frame *frame, ob_error **error
|
||||
*/
|
||||
OB_EXPORT ob_device *ob_frame_get_device(const ob_frame *frame, ob_error **error);
|
||||
|
||||
/**
|
||||
* @brief Get the auth token carried by the frame.
|
||||
*
|
||||
* @param[in] frame Frame object.
|
||||
* @param[out] error Pointer to an error object that will be set if an error occurs.
|
||||
*
|
||||
* @return uint64_t The auth token value.
|
||||
*/
|
||||
OB_EXPORT uint64_t ob_frame_get_token(const ob_frame *frame, ob_error **error);
|
||||
|
||||
/**
|
||||
* @brief Set the auth token carried by the frame.
|
||||
*
|
||||
* @param[in] frame Frame object.
|
||||
* @param[in] token The auth token value.
|
||||
* @param[out] error Pointer to an error object that will be set if an error occurs.
|
||||
*/
|
||||
OB_EXPORT void ob_frame_set_token(ob_frame *frame, uint64_t token, ob_error **error);
|
||||
|
||||
/**
|
||||
* @brief Get the device information attached to the frame.
|
||||
*
|
||||
* @param[in] frame Frame object.
|
||||
* @param[out] error Pointer to an error object that will be set if an error occurs.
|
||||
*
|
||||
* @return ob_device_info* Return the attached device information, or NULL if not available.
|
||||
*/
|
||||
OB_EXPORT ob_device_info *ob_frame_get_device_info(const ob_frame *frame, ob_error **error);
|
||||
|
||||
/**
|
||||
* @brief Get video frame width
|
||||
*
|
||||
|
||||
@@ -152,6 +152,7 @@ typedef enum {
|
||||
OB_EXCEPTION_TYPE_INVALID_DATA, /**< Runtime data is invalid, check data content or size */
|
||||
OB_EXCEPTION_TYPE_NOT_FOUND, /**< The requested item was not found */
|
||||
OB_EXCEPTION_TYPE_RESOURCE_BUSY, /**< Resource is busy or locked by another operation */
|
||||
OB_EXCEPTION_TYPE_LICENSE_VERIFY_FAILED, /**< License verification failed, the device/feature license is missing, invalid or expired */
|
||||
} OBExceptionType,
|
||||
ob_exception_type;
|
||||
|
||||
@@ -384,6 +385,14 @@ typedef struct {
|
||||
uint32_t fullDataSize; ///< Size of full data
|
||||
} OBDataChunk, ob_data_chunk;
|
||||
|
||||
/**
|
||||
* @brief A read-only, non-owning view over a byte buffer (a data pointer plus its size)
|
||||
*/
|
||||
typedef struct {
|
||||
const uint8_t *data; ///< Pointer to the data
|
||||
uint32_t dataSize; ///< Size of the data in bytes
|
||||
} OBDataView, ob_data_view;
|
||||
|
||||
/**
|
||||
* @brief Structure for integer range
|
||||
*/
|
||||
@@ -1727,6 +1736,18 @@ typedef struct {
|
||||
const char *desc; ///< Description of the configuration item
|
||||
} OBFilterConfigSchemaItem, ob_filter_config_schema_item;
|
||||
|
||||
/**
|
||||
* @brief Extensible options for activating a private filter instance.
|
||||
* @brief Passed to @ref ob_filter_activate_private_ex / @ref ob_priv_filter_activate_ex. New fields must only be
|
||||
* appended at the end. The caller sets @ref struct_size to sizeof(ob_priv_filter_activate_options); the callee
|
||||
* uses it to detect which fields a (possibly older) caller actually provided, keeping the ABI compatible as the
|
||||
* struct grows. This is the single extension point for future activation parameters.
|
||||
*/
|
||||
typedef struct ob_priv_filter_activate_options {
|
||||
uint32_t struct_size; ///< Size of this struct in bytes, set by the caller to sizeof(ob_priv_filter_activate_options).
|
||||
const char *model_path; ///< Path to the inference model file. NULL or empty selects the filter's default model.
|
||||
}OBPrivFilterActivateOptions, ob_priv_filter_activate_options;
|
||||
|
||||
/**
|
||||
* @brief struct of serial number
|
||||
*/
|
||||
@@ -2025,6 +2046,20 @@ typedef enum {
|
||||
} ob_device_access_mode,
|
||||
OBDeviceAccessMode;
|
||||
|
||||
/**
|
||||
* @brief Device access state queried from GVCP CCP without opening the device.
|
||||
*/
|
||||
typedef enum {
|
||||
OB_DEVICE_ACCESS_STATE_UNKNOWN = 0, ///< The access state cannot be determined
|
||||
OB_DEVICE_ACCESS_STATE_UNSUPPORTED = 1, ///< The device or current build does not support access-state query
|
||||
OB_DEVICE_ACCESS_STATE_AVAILABLE = 2, ///< The device is available for control access
|
||||
OB_DEVICE_ACCESS_STATE_CONTROLLED = 3, ///< The device has a controller; monitor access may still be available
|
||||
OB_DEVICE_ACCESS_STATE_EXCLUSIVE = 4, ///< The device is held exclusively and cannot be accessed
|
||||
OB_DEVICE_ACCESS_STATE_UNREACHABLE = 5, ///< The device did not respond or the network path is unreachable
|
||||
OB_DEVICE_ACCESS_STATE_FW_NOT_SUPPORTED = 6, ///< The device supports CCP, but the firmware version is too old
|
||||
} ob_device_access_state,
|
||||
OBDeviceAccessState;
|
||||
|
||||
typedef enum {
|
||||
OB_IP_SOURCE_NONE = 0, ///< No IP configuration active (e.g. USB device).
|
||||
OB_IP_SOURCE_LLA = 1, ///< LLA (Link-Local Address / Auto IP).
|
||||
|
||||
@@ -672,6 +672,16 @@ typedef enum {
|
||||
*/
|
||||
OB_PROP_CURRENT_DISP_SEARCH_OFFSET_INT = 272,
|
||||
|
||||
/**
|
||||
* @brief Enable FPS boost in trigger mode
|
||||
*/
|
||||
OB_PROP_FPS_BOOST_BOOL = 275,
|
||||
|
||||
/**
|
||||
* @brief MJPEG encoding quality factor
|
||||
*/
|
||||
OB_PROP_MJPEG_QUALITY_INT = 277,
|
||||
|
||||
/**
|
||||
* @brief Baseline calibration parameters
|
||||
*/
|
||||
|
||||
@@ -184,6 +184,20 @@ public:
|
||||
return std::make_shared<ApplicationConfig>(handle);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the application config carried by an externally imported preset, by preset name.
|
||||
* @return nullptr for built-in presets or presets that carry no application config.
|
||||
*/
|
||||
static std::shared_ptr<ApplicationConfig> get(const std::shared_ptr<Device> &device, const std::string &presetName) {
|
||||
ob_error *error = nullptr;
|
||||
auto handle = ob_device_get_application_config_by_preset(device->getImpl(), presetName.c_str(), &error);
|
||||
Error::handle(&error);
|
||||
if(!handle) {
|
||||
return nullptr;
|
||||
}
|
||||
return std::make_shared<ApplicationConfig>(handle);
|
||||
}
|
||||
|
||||
explicit ApplicationConfig(ob_application_config *handle) : handle_(handle) {}
|
||||
|
||||
~ApplicationConfig() noexcept {
|
||||
|
||||
@@ -302,6 +302,51 @@ public:
|
||||
Error::handle(&error);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check whether the device supports license authorization.
|
||||
*
|
||||
* @return true if the device supports license authorization, false otherwise.
|
||||
*/
|
||||
bool isLicenseAuthorizationSupported() const {
|
||||
ob_error *error = nullptr;
|
||||
auto res = ob_device_is_license_authorization_supported(impl_, &error);
|
||||
Error::handle(&error);
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Write signed device license information.
|
||||
*
|
||||
* @param[in] licenseInfo SDK license_info JSON string
|
||||
*/
|
||||
void writeLicenseInfo(const std::string &licenseInfo) const {
|
||||
ob_error *error = nullptr;
|
||||
ob_device_write_license_info(impl_, licenseInfo.c_str(), static_cast<uint32_t>(licenseInfo.size()), &error);
|
||||
Error::handle(&error);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Clear license information stored on the device.
|
||||
*/
|
||||
void clearLicenseInfo() const {
|
||||
ob_error *error = nullptr;
|
||||
ob_device_clear_license_info(impl_, &error);
|
||||
Error::handle(&error);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Read signed device license information as SDK license_info JSON.
|
||||
*
|
||||
* @return std::string SDK license_info JSON string
|
||||
*/
|
||||
std::string readLicenseInfo() const {
|
||||
ob_error *error = nullptr;
|
||||
char buf[4096] = {};
|
||||
ob_device_read_license_info(impl_, buf, sizeof(buf), &error);
|
||||
Error::handle(&error);
|
||||
return std::string(buf);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set the customer data type of a device property
|
||||
*
|
||||
@@ -393,6 +438,8 @@ public:
|
||||
/**
|
||||
* @brief Update the device firmware
|
||||
*
|
||||
* @attention Only one firmware/preset update may run per device at a time
|
||||
*
|
||||
* @param[in] filePath Firmware path
|
||||
* @param[in] callback Firmware Update progress and status callback
|
||||
* @param[in] async Whether to execute asynchronously
|
||||
@@ -407,6 +454,8 @@ public:
|
||||
/**
|
||||
* @brief Update the device firmware from data
|
||||
*
|
||||
* @attention Only one firmware/preset update may run per device at a time
|
||||
*
|
||||
* @param[in] firmwareData Firmware data
|
||||
* @param[in] firmwareDataSize Firmware data size
|
||||
* @param[in] callback Firmware Update progress and status callback
|
||||
@@ -422,6 +471,8 @@ public:
|
||||
/**
|
||||
* @brief Update the device optional depth presets
|
||||
*
|
||||
* @attention Only one firmware/preset update may run per device at a time
|
||||
*
|
||||
* @param[in] filePathList A list(2D array) of preset file paths, each up to OB_PATH_MAX characters.
|
||||
* @param[in] pathCount The number of the preset file paths.
|
||||
* @param[in] callback Preset update progress and status callback
|
||||
@@ -433,6 +484,27 @@ public:
|
||||
Error::handle(&error);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Update the device optional depth presets from data loaded in memory
|
||||
*
|
||||
* @attention Only one firmware/preset update may run per device at a time
|
||||
*
|
||||
* @param[in] dataList A list of preset data blocks, each holding the raw bytes of one preset.
|
||||
* @param[in] callback Preset update progress and status callback
|
||||
*/
|
||||
void updateOptionalDepthPresets(const std::vector<std::vector<uint8_t>> &dataList, DeviceFwUpdateCallback callback) {
|
||||
ob_error *error = nullptr;
|
||||
std::vector<OBDataView> presets;
|
||||
presets.reserve(dataList.size());
|
||||
for(const auto &data: dataList) {
|
||||
presets.push_back({data.data(), static_cast<uint32_t>(data.size())});
|
||||
}
|
||||
fwUpdateCallback_ = callback;
|
||||
auto count = static_cast<uint8_t>(presets.size());
|
||||
ob_device_update_optional_depth_presets_from_data(impl_, presets.data(), count, &Device::firmwareUpdateCallback, this, &error);
|
||||
Error::handle(&error);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set the device state changed callbacks
|
||||
*
|
||||
@@ -620,6 +692,18 @@ public:
|
||||
Error::handle(&error);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check whether the device firmware log is enabled.
|
||||
*
|
||||
* @return bool Whether the firmware log is enabled.
|
||||
*/
|
||||
bool isFirmwareLogEnabled() const {
|
||||
ob_error *error = nullptr;
|
||||
bool enable = ob_device_is_firmware_log_enabled(impl_, &error);
|
||||
Error::handle(&error);
|
||||
return enable;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the supported multi device sync mode bitmap of the device.
|
||||
* @brief For example, if the return value is 0b00001100, it means the device supports @ref OB_MULTI_DEVICE_SYNC_MODE_PRIMARY and @ref
|
||||
@@ -1449,9 +1533,9 @@ public:
|
||||
*
|
||||
* @return const char* The host network interface name (e.g., "eth0", "en0").
|
||||
*/
|
||||
const char* getLocalNetInterfaceName(uint32_t index) const {
|
||||
ob_error *error = nullptr;
|
||||
auto netItfName = ob_device_list_get_device_local_net_if_name(impl_, index, &error);
|
||||
const char *getLocalNetInterfaceName(uint32_t index) const {
|
||||
ob_error *error = nullptr;
|
||||
auto netItfName = ob_device_list_get_device_local_net_if_name(impl_, index, &error);
|
||||
Error::handle(&error);
|
||||
return netItfName;
|
||||
}
|
||||
@@ -1488,6 +1572,49 @@ public:
|
||||
return userName;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Query the current device access state without opening the device.
|
||||
*
|
||||
* @attention This is a non-invasive GVCP CCP query for supported Ethernet devices. It reports device-side CCP state, not the owner process or host.
|
||||
* CONTROLLED means monitor access may still be available, while default/control access may still fail.
|
||||
* This call is synchronous and blocks while waiting for the device's GVCP response over the network; querying an unreachable device blocks until the
|
||||
* underlying retry logic gives up, so prefer calling it off the UI thread when querying multiple devices.
|
||||
* The returned state reflects the device access state only at the moment of the query and does not guarantee that a subsequent access (such as creating
|
||||
* or opening the device) will succeed, as another client may change the state in between.
|
||||
*
|
||||
* @param[in] index The index of the device.
|
||||
*
|
||||
* @return OBDeviceAccessState The current access state of the device.
|
||||
*/
|
||||
OBDeviceAccessState queryDeviceAccessState(uint32_t index) const {
|
||||
ob_error *error = nullptr;
|
||||
auto state = ob_device_list_query_device_access_state(impl_, index, &error);
|
||||
Error::handle(&error);
|
||||
return state;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Query the current device access state by serial number without opening the device.
|
||||
*
|
||||
* @attention This is a non-invasive GVCP CCP query for supported Ethernet devices. It reports device-side CCP state, not the owner process or host.
|
||||
* CONTROLLED means monitor access may still be available, while default/control access may still fail.
|
||||
* This call is synchronous and blocks while waiting for the device's GVCP response over the network; querying an unreachable device blocks until the
|
||||
* underlying retry logic gives up, so prefer calling it off the UI thread when querying multiple devices.
|
||||
* The returned state reflects the device access state only at the moment of the query and does not guarantee that a subsequent access (such as creating
|
||||
* or opening the device) will succeed, as another client may change the state in between.
|
||||
* If no device in the list matches the given serial number, this throws an ob::Error.
|
||||
*
|
||||
* @param[in] serialNumber The serial number of the device.
|
||||
*
|
||||
* @return OBDeviceAccessState The current access state of the device.
|
||||
*/
|
||||
OBDeviceAccessState queryDeviceAccessStateBySN(const char *serialNumber) const {
|
||||
ob_error *error = nullptr;
|
||||
auto state = ob_device_list_query_device_access_state_by_serial_number(impl_, serialNumber, &error);
|
||||
Error::handle(&error);
|
||||
return state;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the device object at the specified index
|
||||
*
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#include <typeinfo>
|
||||
#include <typeindex>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
#include <cstring>
|
||||
|
||||
namespace ob {
|
||||
@@ -2081,6 +2082,175 @@ public:
|
||||
~DisparityTransform() noexcept override = default;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Enhanced depth filter that requires a device for activation.
|
||||
*
|
||||
* @note The constructor is a template so that Filter.hpp does not need to include Device.hpp.
|
||||
* The template is instantiated at the call site where the device type is complete.
|
||||
*/
|
||||
class EnhancedDepthFilter : public Filter {
|
||||
public:
|
||||
/**
|
||||
* @brief Construct an EnhancedDepthFilter and activate it for the given device.
|
||||
*
|
||||
* @param[in] device The device the filter is bound to.
|
||||
* @param[in] modelPath Optional path to the inference model file used during activation. When empty, the
|
||||
* filter falls back to its default model file at extensions/filters/enhanced_depth_filter/model.sm4
|
||||
* (located next to the filter library).
|
||||
*/
|
||||
template <typename T> explicit EnhancedDepthFilter(std::shared_ptr<T> device, const std::string &modelPath = "") {
|
||||
if(!device) {
|
||||
throw std::invalid_argument("device is null");
|
||||
}
|
||||
ob_error *error = nullptr;
|
||||
auto impl = ob_create_private_filter("EnhancedDepthFilter", "", &error);
|
||||
Error::handle(&error);
|
||||
|
||||
// Only pass options when a model path is provided; otherwise hand down nullptr so the filter uses its default.
|
||||
ob_priv_filter_activate_options options{};
|
||||
ob_priv_filter_activate_options *optionsPtr = nullptr;
|
||||
if(!modelPath.empty()) {
|
||||
options.struct_size = sizeof(options);
|
||||
options.model_path = modelPath.c_str();
|
||||
optionsPtr = &options;
|
||||
}
|
||||
ob_filter_activate_private_ex(impl, device->getImpl(), optionsPtr, &error);
|
||||
Error::handle(&error);
|
||||
init(impl);
|
||||
}
|
||||
|
||||
~EnhancedDepthFilter() noexcept override = default;
|
||||
|
||||
/**
|
||||
* @brief Get the resolutions supported by the enhanced depth filter for the constrained (aligned-to) stream.
|
||||
*
|
||||
* @return The list of supported {width, height} pairs. This is the single source of truth used by
|
||||
* @ref isSupportedResolution.
|
||||
*/
|
||||
static const std::vector<std::pair<uint32_t, uint32_t>> &getSupportedResolutions() {
|
||||
static const std::vector<std::pair<uint32_t, uint32_t>> supportedResolutions = {
|
||||
{ 640, 480 },
|
||||
{ 1280, 720 },
|
||||
{ 1280, 800 },
|
||||
};
|
||||
return supportedResolutions;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the frame formats supported by the enhanced depth filter for a given stream type.
|
||||
*
|
||||
* @param[in] streamType The stream type. Only color and depth streams are supported.
|
||||
*
|
||||
* @return The list of supported formats (color: OB_FORMAT_RGB; depth: OB_FORMAT_Y10, OB_FORMAT_Y11,
|
||||
* OB_FORMAT_Y12, OB_FORMAT_Y14, OB_FORMAT_Y16, OB_FORMAT_Z16). Empty for unsupported stream types. This is the single
|
||||
* source of truth used by @ref isSupportedFormat.
|
||||
*/
|
||||
static std::vector<OBFormat> getSupportedFormats(OBStreamType streamType) {
|
||||
if(streamType == OB_STREAM_COLOR) {
|
||||
return { OB_FORMAT_RGB };
|
||||
}
|
||||
if(streamType == OB_STREAM_DEPTH) {
|
||||
return { OB_FORMAT_Y10, OB_FORMAT_Y11, OB_FORMAT_Y12, OB_FORMAT_Y14, OB_FORMAT_Y16, OB_FORMAT_Z16 };
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check whether a resolution is supported by the enhanced depth filter for a given stream alignment pair.
|
||||
*
|
||||
* @param[in] sourceStreamType The source stream type that provides the input frames.
|
||||
* @param[in] alignToStreamType The target stream type that the source stream is aligned to.
|
||||
* @param[in] width The frame width to validate.
|
||||
* @param[in] height The frame height to validate.
|
||||
*
|
||||
* @return true if the resolution is supported for the specified alignment combination, otherwise false.
|
||||
*/
|
||||
static bool isSupportedResolution(OBStreamType sourceStreamType, OBStreamType alignToStreamType, uint32_t width, uint32_t height) {
|
||||
if(sourceStreamType != alignToStreamType) {
|
||||
// If the source and target stream types are different, any resolution is supported.
|
||||
return true;
|
||||
}
|
||||
|
||||
for(const auto &res: getSupportedResolutions()) {
|
||||
if(res.first == width && res.second == height) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check whether a frame format is supported by the enhanced depth filter for a given stream type.
|
||||
*
|
||||
* @param[in] streamType The stream type to validate. Only color and depth streams are supported.
|
||||
* @param[in] format The frame format to validate.
|
||||
*
|
||||
* @return true if the format is supported for the given stream type, otherwise false.
|
||||
*/
|
||||
static bool isSupportedFormat(OBStreamType streamType, OBFormat format) {
|
||||
for(const auto &supported: getSupportedFormats(streamType)) {
|
||||
if(supported == format) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set the working resolution of the enhanced depth filter.
|
||||
*
|
||||
* @param[in] width The target frame width.
|
||||
* @param[in] height The target frame height.
|
||||
*/
|
||||
void setResolution(uint32_t width, uint32_t height) {
|
||||
setConfigValue("width", static_cast<double>(width));
|
||||
setConfigValue("height", static_cast<double>(height));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the current configured frame width.
|
||||
*
|
||||
* @return uint32_t The current width.
|
||||
*/
|
||||
uint32_t getCurrentWidth() const {
|
||||
return static_cast<uint32_t>(getConfigValue("width"));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the current configured frame height.
|
||||
*
|
||||
* @return uint32_t The current height.
|
||||
*/
|
||||
uint32_t getCurrentHeight() const {
|
||||
return static_cast<uint32_t>(getConfigValue("height"));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set the confidence threshold for depth values.
|
||||
*
|
||||
* @param value The confidence threshold.
|
||||
*/
|
||||
void setConfidenceThreshold(uint32_t value) {
|
||||
setConfigValue("confidence_threshold", static_cast<double>(value));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the property range of the confidence threshold range.
|
||||
*/
|
||||
OBIntPropertyRange getConfidenceThresholdRange() {
|
||||
OBIntPropertyRange range{};
|
||||
const auto &schemaVec = getConfigSchemaVec();
|
||||
for(const auto &item: schemaVec) {
|
||||
const char *name = "confidence_threshold";
|
||||
if(std::strcmp(item.name, name) == 0) {
|
||||
range = getPropertyRange<OBIntPropertyRange>(item, getConfigValue(name));
|
||||
break;
|
||||
}
|
||||
}
|
||||
return range;
|
||||
}
|
||||
};
|
||||
|
||||
class OBFilterList {
|
||||
private:
|
||||
ob_filter_list_t *impl_;
|
||||
@@ -2151,6 +2321,7 @@ inline const std::unordered_map<std::string, std::type_index> &getFilterTypeMap(
|
||||
{ "MgcNoiseRemovalFilter", typeid(MgcNoiseRemovalFilter) },
|
||||
{ "LutNoiseRemovalFilter", typeid(LutNoiseRemovalFilter) },
|
||||
{ "UnDistortionFilter", typeid(UnDistortionFilter) },
|
||||
{ "EnhancedDepthFilter", typeid(EnhancedDepthFilter) },
|
||||
};
|
||||
return filterTypeMap;
|
||||
}
|
||||
|
||||
@@ -123,6 +123,32 @@ public:
|
||||
return index;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the auth token carried by the frame.
|
||||
*
|
||||
* @return uint64_t The auth token value.
|
||||
*/
|
||||
uint64_t getToken() const {
|
||||
ob_error *error = nullptr;
|
||||
auto token = ob_frame_get_token(impl_, &error);
|
||||
Error::handle(&error);
|
||||
|
||||
return token;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set the auth token carried by the frame.
|
||||
*
|
||||
* @param token The auth token value.
|
||||
*/
|
||||
void setToken(uint64_t token) {
|
||||
ob_error *error = nullptr;
|
||||
auto unConstImpl = const_cast<ob_frame *>(impl_);
|
||||
|
||||
ob_frame_set_token(unConstImpl, token, &error);
|
||||
Error::handle(&error);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get frame data
|
||||
*
|
||||
|
||||
@@ -70,10 +70,19 @@ public:
|
||||
|
||||
class PlaybackDevice : public Device {
|
||||
public:
|
||||
explicit PlaybackDevice(const std::string &file) : Device(nullptr) {
|
||||
/**
|
||||
* @brief Constructs a PlaybackDevice for playing back recorded device data.
|
||||
* @param[in] file Path to the playback file.
|
||||
* @param[in] presetPath Path to a preset JSON file to load after device creation. If empty, no preset is loaded.
|
||||
*/
|
||||
explicit PlaybackDevice(const std::string &file, const std::string &presetPath = "") : Device(nullptr) {
|
||||
ob_error *error = nullptr;
|
||||
impl_ = ob_create_playback_device(file.c_str(), &error);
|
||||
Error::handle(&error);
|
||||
|
||||
if(!presetPath.empty()) {
|
||||
loadPresetFromJsonFile(presetPath.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
virtual ~PlaybackDevice() noexcept override = default;
|
||||
|
||||
@@ -8,12 +8,12 @@ set(CMAKE_IMPORT_FILE_VERSION 1)
|
||||
# Import target "ob::OrbbecSDK" for configuration "Release"
|
||||
set_property(TARGET ob::OrbbecSDK APPEND PROPERTY IMPORTED_CONFIGURATIONS RELEASE)
|
||||
set_target_properties(ob::OrbbecSDK PROPERTIES
|
||||
IMPORTED_LOCATION_RELEASE "${_IMPORT_PREFIX}/lib/libOrbbecSDK.so.2.9.1"
|
||||
IMPORTED_LOCATION_RELEASE "${_IMPORT_PREFIX}/lib/libOrbbecSDK.so.2.9.3"
|
||||
IMPORTED_SONAME_RELEASE "libOrbbecSDK.so.2"
|
||||
)
|
||||
|
||||
list(APPEND _cmake_import_check_targets ob::OrbbecSDK )
|
||||
list(APPEND _cmake_import_check_files_for_ob::OrbbecSDK "${_IMPORT_PREFIX}/lib/libOrbbecSDK.so.2.9.1" )
|
||||
list(APPEND _cmake_import_check_files_for_ob::OrbbecSDK "${_IMPORT_PREFIX}/lib/libOrbbecSDK.so.2.9.3" )
|
||||
|
||||
# Commands beyond this point should not need to know the version.
|
||||
set(CMAKE_IMPORT_FILE_VERSION)
|
||||
|
||||
@@ -9,19 +9,19 @@
|
||||
# The variable CVF_VERSION must be set before calling configure_file().
|
||||
|
||||
|
||||
set(PACKAGE_VERSION "2.9.1")
|
||||
set(PACKAGE_VERSION "2.9.3")
|
||||
|
||||
if(PACKAGE_VERSION VERSION_LESS PACKAGE_FIND_VERSION)
|
||||
set(PACKAGE_VERSION_COMPATIBLE FALSE)
|
||||
else()
|
||||
|
||||
if("2.9.1" MATCHES "^([0-9]+)\\.")
|
||||
if("2.9.3" MATCHES "^([0-9]+)\\.")
|
||||
set(CVF_VERSION_MAJOR "${CMAKE_MATCH_1}")
|
||||
if(NOT CVF_VERSION_MAJOR VERSION_EQUAL 0)
|
||||
string(REGEX REPLACE "^0+" "" CVF_VERSION_MAJOR "${CVF_VERSION_MAJOR}")
|
||||
endif()
|
||||
else()
|
||||
set(CVF_VERSION_MAJOR "2.9.1")
|
||||
set(CVF_VERSION_MAJOR "2.9.3")
|
||||
endif()
|
||||
|
||||
if(PACKAGE_FIND_VERSION_RANGE)
|
||||
|
||||
BIN
Binary file not shown.
BIN
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1 +1 @@
|
||||
libOrbbecSDK.so.2.9.1
|
||||
libOrbbecSDK.so.2.9.3
|
||||
BIN
Binary file not shown.
@@ -8,12 +8,12 @@ set(CMAKE_IMPORT_FILE_VERSION 1)
|
||||
# Import target "ob::OrbbecSDK" for configuration "Release"
|
||||
set_property(TARGET ob::OrbbecSDK APPEND PROPERTY IMPORTED_CONFIGURATIONS RELEASE)
|
||||
set_target_properties(ob::OrbbecSDK PROPERTIES
|
||||
IMPORTED_LOCATION_RELEASE "${_IMPORT_PREFIX}/lib/libOrbbecSDK.so.2.9.1"
|
||||
IMPORTED_LOCATION_RELEASE "${_IMPORT_PREFIX}/lib/libOrbbecSDK.so.2.9.3"
|
||||
IMPORTED_SONAME_RELEASE "libOrbbecSDK.so.2"
|
||||
)
|
||||
|
||||
list(APPEND _cmake_import_check_targets ob::OrbbecSDK )
|
||||
list(APPEND _cmake_import_check_files_for_ob::OrbbecSDK "${_IMPORT_PREFIX}/lib/libOrbbecSDK.so.2.9.1" )
|
||||
list(APPEND _cmake_import_check_files_for_ob::OrbbecSDK "${_IMPORT_PREFIX}/lib/libOrbbecSDK.so.2.9.3" )
|
||||
|
||||
# Commands beyond this point should not need to know the version.
|
||||
set(CMAKE_IMPORT_FILE_VERSION)
|
||||
|
||||
@@ -9,19 +9,19 @@
|
||||
# The variable CVF_VERSION must be set before calling configure_file().
|
||||
|
||||
|
||||
set(PACKAGE_VERSION "2.9.1")
|
||||
set(PACKAGE_VERSION "2.9.3")
|
||||
|
||||
if(PACKAGE_VERSION VERSION_LESS PACKAGE_FIND_VERSION)
|
||||
set(PACKAGE_VERSION_COMPATIBLE FALSE)
|
||||
else()
|
||||
|
||||
if("2.9.1" MATCHES "^([0-9]+)\\.")
|
||||
if("2.9.3" MATCHES "^([0-9]+)\\.")
|
||||
set(CVF_VERSION_MAJOR "${CMAKE_MATCH_1}")
|
||||
if(NOT CVF_VERSION_MAJOR VERSION_EQUAL 0)
|
||||
string(REGEX REPLACE "^0+" "" CVF_VERSION_MAJOR "${CVF_VERSION_MAJOR}")
|
||||
endif()
|
||||
else()
|
||||
set(CVF_VERSION_MAJOR "2.9.1")
|
||||
set(CVF_VERSION_MAJOR "2.9.3")
|
||||
endif()
|
||||
|
||||
if(PACKAGE_FIND_VERSION_RANGE)
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1 +1 @@
|
||||
libOrbbecSDK.so.2.9.1
|
||||
libOrbbecSDK.so.2.9.3
|
||||
BIN
Binary file not shown.
@@ -2028,8 +2028,8 @@
|
||||
</Misc>
|
||||
|
||||
<DepthPostProcessing>
|
||||
<HardwareNoiseRemoveFilter>false</HardwareNoiseRemoveFilter>
|
||||
<SoftwareNoiseRemoveFilter>true</SoftwareNoiseRemoveFilter>
|
||||
<HardwareNoiseRemoveFilter>true</HardwareNoiseRemoveFilter>
|
||||
<SoftwareNoiseRemoveFilter>false</SoftwareNoiseRemoveFilter>
|
||||
</DepthPostProcessing>
|
||||
|
||||
<!-- Whether to enable heartbeat by default -->
|
||||
|
||||
@@ -16,9 +16,9 @@ time_domain: "global" # global, device, system
|
||||
enable_sync_host_time: true
|
||||
|
||||
trigger_out_enabled: true
|
||||
frames_per_trigger: 0
|
||||
frames_per_trigger: 1
|
||||
software_trigger_period: 0
|
||||
|
||||
enable_fps_boost: false
|
||||
|
||||
# color params
|
||||
enable_color: true
|
||||
|
||||
@@ -16,9 +16,9 @@ time_domain: "global" # global, device, system
|
||||
enable_sync_host_time: true
|
||||
|
||||
trigger_out_enabled: false
|
||||
frames_per_trigger: 0
|
||||
frames_per_trigger: 1
|
||||
software_trigger_period: 0
|
||||
|
||||
enable_fps_boost: false
|
||||
|
||||
# color params
|
||||
enable_color: true
|
||||
|
||||
@@ -1,69 +1,7 @@
|
||||
# device
|
||||
device_type: camera
|
||||
camera_name: camera
|
||||
serial_number: ""
|
||||
usb_port: ""
|
||||
device_num: 1
|
||||
upgrade_firmware: ""
|
||||
preset_firmware_path: ""
|
||||
load_config_json_file_path: ""
|
||||
export_config_json_file_path: ""
|
||||
uvc_backend: libuvc
|
||||
connection_delay: 10
|
||||
publish_tf: true
|
||||
tf_publish_rate: 0.0
|
||||
ir_info_url: ""
|
||||
color_info_url: ""
|
||||
|
||||
# device_misc
|
||||
device_access_mode: Default
|
||||
exposure_range_mode: default
|
||||
log_level: info
|
||||
log_file_name: ""
|
||||
enable_publish_extrinsic: false
|
||||
enable_d2c_viewer: false
|
||||
disparity_to_depth_mode: ""
|
||||
align_mode: SW
|
||||
align_target_stream: COLOR
|
||||
diagnostic_period: 1.0
|
||||
# Gemini 305 dual-color preset. Other parameters inherit gemini_301_series.launch.py.
|
||||
device_preset: Dual Color Streams
|
||||
color_preset: Default
|
||||
retry_on_usb3_detection_failure: false
|
||||
enable_sync_host_time: true
|
||||
sync_io_voltage_level: -1
|
||||
time_sync_period: 6.0
|
||||
time_domain: global
|
||||
config_file_path: ""
|
||||
enable_heartbeat: false
|
||||
gmsl_trigger_fps: 3000
|
||||
enable_gmsl_trigger: false
|
||||
disparity_range_mode: -1
|
||||
disparity_search_offset: -1
|
||||
disparity_offset_config: false
|
||||
offset_index0: -1
|
||||
offset_index1: -1
|
||||
frame_aggregate_mode: ANY
|
||||
interleave_ae_mode: hdr
|
||||
interleave_frame_enable: false
|
||||
interleave_skip_enable: false
|
||||
interleave_skip_index: 1
|
||||
show_fps_enable: false
|
||||
|
||||
# color
|
||||
enable_color: false
|
||||
color_width: 0
|
||||
color_height: 0
|
||||
color_fps: 0
|
||||
color_format: ANY
|
||||
color_qos: default
|
||||
color_camera_info_qos: default
|
||||
color_rotation: -1
|
||||
color_flip: false
|
||||
color_mirror: false
|
||||
enable_color_decimation_filter: false
|
||||
color_decimation_filter_scale: -1
|
||||
|
||||
# left_color
|
||||
# left color
|
||||
enable_left_color: true
|
||||
left_color_width: 0
|
||||
left_color_height: 0
|
||||
@@ -77,8 +15,9 @@ left_color_mirror: false
|
||||
enable_left_color_decimation_filter: false
|
||||
left_color_decimation_filter_scale: -1
|
||||
enable_left_color_undistortion: false
|
||||
left_color.image_raw.enable_pub_plugins: ["image_transport/compressed", "image_transport/raw", "image_transport/theora"]
|
||||
|
||||
# right_color
|
||||
# right color
|
||||
enable_right_color: true
|
||||
right_color_width: 0
|
||||
right_color_height: 0
|
||||
@@ -92,187 +31,4 @@ right_color_mirror: false
|
||||
enable_right_color_decimation_filter: false
|
||||
right_color_decimation_filter_scale: -1
|
||||
enable_right_color_undistortion: false
|
||||
|
||||
# color_common
|
||||
enable_color_auto_exposure_priority: false
|
||||
enable_color_auto_white_balance: true
|
||||
enable_color_auto_exposure: true
|
||||
color_ae_roi_left: -1
|
||||
color_ae_roi_right: -1
|
||||
color_ae_roi_top: -1
|
||||
color_ae_roi_bottom: -1
|
||||
color_exposure: -1
|
||||
color_gain: -1
|
||||
color_white_balance: -1
|
||||
color_ae_max_exposure: -1
|
||||
color_brightness: -1
|
||||
color_sharpness: -1
|
||||
color_gamma: -1
|
||||
color_saturation: -1
|
||||
color_contrast: -1
|
||||
color_hue: -1
|
||||
color_backlight_compensation: -1
|
||||
color_powerline_freq: ""
|
||||
color_denoising_level: -1
|
||||
enable_color_undistortion: false
|
||||
enable_depth_undistortion: false
|
||||
enable_ir_undistortion: false
|
||||
enable_left_ir_undistortion: false
|
||||
enable_right_ir_undistortion: false
|
||||
|
||||
# hdr_params
|
||||
hdr_index1_depth_exposure: 1
|
||||
hdr_index1_depth_gain: 16
|
||||
hdr_index1_ir_brightness: 30
|
||||
hdr_index1_ir_ae_max_exposure: 30458
|
||||
hdr_index0_depth_exposure: 7500
|
||||
hdr_index0_depth_gain: 16
|
||||
hdr_index0_ir_brightness: 90
|
||||
hdr_index0_ir_ae_max_exposure: 30458
|
||||
|
||||
# publishers and transports
|
||||
left_color.image_raw.enable_pub_plugins: ["image_transport/compressed", "image_transport/raw", "image_transport/theora"]
|
||||
right_color.image_raw.enable_pub_plugins: ["image_transport/compressed", "image_transport/raw", "image_transport/theora"]
|
||||
|
||||
# In dual color mode, it is not recommended to change the following parameters
|
||||
# depth
|
||||
enable_depth: false
|
||||
depth_width: 0
|
||||
depth_height: 0
|
||||
depth_fps: 0
|
||||
depth_format: ANY
|
||||
depth_qos: default
|
||||
depth_camera_info_qos: default
|
||||
enable_depth_auto_exposure_priority: false
|
||||
depth_precision: ""
|
||||
depth_rotation: -1
|
||||
depth_flip: false
|
||||
depth_mirror: false
|
||||
depth_ae_roi_left: -1
|
||||
depth_ae_roi_right: -1
|
||||
depth_ae_roi_top: -1
|
||||
depth_ae_roi_bottom: -1
|
||||
mean_intensity_set_point: -1
|
||||
enable_depth_scale: false
|
||||
enable_decimation_filter: false
|
||||
decimation_filter_scale: -1
|
||||
enable_hdr_merge: false
|
||||
hdr_merge_exposure_1: -1
|
||||
hdr_merge_gain_1: -1
|
||||
hdr_merge_exposure_2: -1
|
||||
hdr_merge_gain_2: -1
|
||||
enable_sequence_id_filter: false
|
||||
sequence_id_filter_id: -1
|
||||
enable_threshold_filter: false
|
||||
threshold_filter_max: -1
|
||||
threshold_filter_min: -1
|
||||
enable_hardware_noise_removal_filter: false
|
||||
hardware_noise_removal_filter_threshold: -1.0
|
||||
enable_noise_removal_filter: false
|
||||
noise_removal_filter_min_diff: 256
|
||||
noise_removal_filter_max_size: 80
|
||||
enable_spatial_filter: false
|
||||
spatial_filter_alpha: -1.0
|
||||
spatial_filter_diff_threshold: -1
|
||||
spatial_filter_magnitude: -1
|
||||
spatial_filter_radius: -1
|
||||
enable_temporal_filter: false
|
||||
temporal_filter_diff_threshold: -1.0
|
||||
temporal_filter_weight: -1.0
|
||||
enable_disparity_to_depth: false
|
||||
hole_filling_filter_mode: ""
|
||||
enable_hole_filling_filter: false
|
||||
enable_spatial_fast_filter: false
|
||||
spatial_fast_filter_radius: -1
|
||||
enable_spatial_moderate_filter: false
|
||||
spatial_moderate_filter_diff_threshold: -1
|
||||
spatial_moderate_filter_magnitude: -1
|
||||
spatial_moderate_filter_radius: -1
|
||||
|
||||
# point_cloud
|
||||
depth_registration: false
|
||||
point_cloud_qos: default
|
||||
enable_point_cloud: false
|
||||
point_cloud_decimation_filter_factor: 1
|
||||
enable_colored_point_cloud: false
|
||||
cloud_frame_id: ""
|
||||
ordered_pc: false
|
||||
|
||||
# ldp
|
||||
enable_ldp: true
|
||||
ldp_power_level: -1
|
||||
|
||||
# left_ir
|
||||
enable_left_ir: false
|
||||
left_ir_width: 0
|
||||
left_ir_height: 0
|
||||
left_ir_fps: 0
|
||||
left_ir_format: ANY
|
||||
left_ir_qos: default
|
||||
left_ir_camera_info_qos: default
|
||||
left_ir_rotation: -1
|
||||
left_ir_flip: false
|
||||
left_ir_mirror: false
|
||||
enable_left_ir_sequence_id_filter: false
|
||||
left_ir_sequence_id_filter_id: -1
|
||||
|
||||
# right_ir
|
||||
enable_right_ir: false
|
||||
right_ir_width: 0
|
||||
right_ir_height: 0
|
||||
right_ir_fps: 0
|
||||
right_ir_format: ANY
|
||||
right_ir_qos: default
|
||||
right_ir_camera_info_qos: default
|
||||
right_ir_rotation: -1
|
||||
right_ir_flip: false
|
||||
right_ir_mirror: false
|
||||
enable_right_ir_sequence_id_filter: false
|
||||
right_ir_sequence_id_filter_id: -1
|
||||
|
||||
# ir_common
|
||||
enable_ir_auto_exposure: false
|
||||
ir_exposure: -1
|
||||
ir_gain: -1
|
||||
ir_ae_max_exposure: -1
|
||||
ir_brightness: -1
|
||||
|
||||
# imu
|
||||
enable_sync_output_accel_gyro: false
|
||||
enable_accel: false
|
||||
enable_accel_data_correction: false
|
||||
accel_rate: 200hz
|
||||
accel_range: 4g
|
||||
enable_gyro: false
|
||||
enable_gyro_data_correction: false
|
||||
gyro_rate: 200hz
|
||||
gyro_range: 1000dps
|
||||
linear_accel_cov: 0.01
|
||||
angular_vel_cov: 0.01
|
||||
|
||||
depth_delay_us: 0
|
||||
color_delay_us: 0
|
||||
trigger2image_delay_us: 0
|
||||
trigger_out_delay_us: 0
|
||||
trigger_out_enabled: true
|
||||
software_trigger_enabled: true
|
||||
frames_per_trigger: 2
|
||||
software_trigger_period: 33
|
||||
|
||||
enable_ptp_config: false
|
||||
enable_frame_sync: true
|
||||
|
||||
noise_removal_filter_min_diff: 256
|
||||
noise_removal_filter_max_size: 80
|
||||
|
||||
# laser_params
|
||||
laser_index1_laser_control: 0
|
||||
laser_index1_depth_exposure: 3000
|
||||
laser_index1_depth_gain: 16
|
||||
laser_index1_ir_brightness: 60
|
||||
laser_index1_ir_ae_max_exposure: 17000
|
||||
laser_index0_laser_control: 1
|
||||
laser_index0_depth_exposure: 3000
|
||||
laser_index0_depth_gain: 16
|
||||
laser_index0_ir_brightness: 60
|
||||
laser_index0_ir_ae_max_exposure: 30000
|
||||
|
||||
@@ -85,6 +85,7 @@ def generate_launch_description():
|
||||
DeclareLaunchArgument('color_ae_roi_bottom', default_value='-1'),
|
||||
DeclareLaunchArgument('color_exposure', default_value='-1'),
|
||||
DeclareLaunchArgument('color_gain', default_value='-1'),
|
||||
DeclareLaunchArgument('color_mjpeg_quality', default_value='-1'),
|
||||
DeclareLaunchArgument('enable_color_auto_white_balance', default_value='true'),
|
||||
DeclareLaunchArgument('color_white_balance', default_value='-1'),
|
||||
DeclareLaunchArgument('enable_color_auto_exposure', default_value='true'),
|
||||
@@ -180,7 +181,8 @@ def generate_launch_description():
|
||||
DeclareLaunchArgument('trigger2image_delay_us', default_value='0'),
|
||||
DeclareLaunchArgument('trigger_out_delay_us', default_value='0'),
|
||||
DeclareLaunchArgument('trigger_out_enabled', default_value='true'),
|
||||
DeclareLaunchArgument('frames_per_trigger', default_value='2'),
|
||||
DeclareLaunchArgument('enable_fps_boost', default_value='false'),
|
||||
DeclareLaunchArgument('frames_per_trigger', default_value='1'),
|
||||
DeclareLaunchArgument('software_trigger_period', default_value='33'), # ms
|
||||
DeclareLaunchArgument('enable_ptp_config', default_value='false'),#Only for Gemini 335Le
|
||||
DeclareLaunchArgument('enable_frame_sync', default_value='true'),
|
||||
|
||||
@@ -85,6 +85,7 @@ def generate_launch_description():
|
||||
DeclareLaunchArgument('color_ae_roi_bottom', default_value='-1'),
|
||||
DeclareLaunchArgument('color_exposure', default_value='-1'),
|
||||
DeclareLaunchArgument('color_gain', default_value='-1'),
|
||||
DeclareLaunchArgument('color_mjpeg_quality', default_value='-1'),
|
||||
DeclareLaunchArgument('enable_color_auto_white_balance', default_value='true'),
|
||||
DeclareLaunchArgument('color_white_balance', default_value='-1'),
|
||||
DeclareLaunchArgument('enable_color_auto_exposure', default_value='true'),
|
||||
@@ -180,7 +181,8 @@ def generate_launch_description():
|
||||
DeclareLaunchArgument('trigger2image_delay_us', default_value='0'),
|
||||
DeclareLaunchArgument('trigger_out_delay_us', default_value='0'),
|
||||
DeclareLaunchArgument('trigger_out_enabled', default_value='true'),
|
||||
DeclareLaunchArgument('frames_per_trigger', default_value='2'),
|
||||
DeclareLaunchArgument('enable_fps_boost', default_value='false'),
|
||||
DeclareLaunchArgument('frames_per_trigger', default_value='1'),
|
||||
DeclareLaunchArgument('software_trigger_period', default_value='33'), # ms
|
||||
DeclareLaunchArgument('enable_ptp_config', default_value='false'),#Only for Gemini 335Le
|
||||
DeclareLaunchArgument('enable_frame_sync', default_value='true'),
|
||||
|
||||
+3
-1
@@ -85,6 +85,7 @@ def generate_launch_description():
|
||||
DeclareLaunchArgument('color_ae_roi_bottom', default_value='-1'),
|
||||
DeclareLaunchArgument('color_exposure', default_value='-1'),
|
||||
DeclareLaunchArgument('color_gain', default_value='-1'),
|
||||
DeclareLaunchArgument('color_mjpeg_quality', default_value='-1'),
|
||||
DeclareLaunchArgument('enable_color_auto_white_balance', default_value='true'),
|
||||
DeclareLaunchArgument('color_white_balance', default_value='-1'),
|
||||
DeclareLaunchArgument('enable_color_auto_exposure', default_value='true'),
|
||||
@@ -180,7 +181,8 @@ def generate_launch_description():
|
||||
DeclareLaunchArgument('trigger2image_delay_us', default_value='0'),
|
||||
DeclareLaunchArgument('trigger_out_delay_us', default_value='0'),
|
||||
DeclareLaunchArgument('trigger_out_enabled', default_value='true'),
|
||||
DeclareLaunchArgument('frames_per_trigger', default_value='2'),
|
||||
DeclareLaunchArgument('enable_fps_boost', default_value='false'),
|
||||
DeclareLaunchArgument('frames_per_trigger', default_value='1'),
|
||||
DeclareLaunchArgument('software_trigger_period', default_value='33'), # ms
|
||||
DeclareLaunchArgument('enable_ptp_config', default_value='false'),#Only for Gemini 335Le
|
||||
DeclareLaunchArgument('enable_frame_sync', default_value='true'),
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
|
||||
#define OB_ROS_MAJOR_VERSION 2
|
||||
#define OB_ROS_MINOR_VERSION 9
|
||||
#define OB_ROS_PATCH_VERSION 1
|
||||
#define OB_ROS_PATCH_VERSION 3
|
||||
|
||||
#ifndef STRINGIFY
|
||||
#define STRINGIFY(arg) #arg
|
||||
|
||||
@@ -40,6 +40,7 @@ class FrameTimestampCsvLogger {
|
||||
|
||||
void recordPreImagePublish(OBStreamType stream_type, const std::shared_ptr<ob::Frame> &frame,
|
||||
int64_t publish_system_us, int64_t publish_steady_us);
|
||||
void recordImagePublishSkipped(OBStreamType stream_type, const std::shared_ptr<ob::Frame> &frame);
|
||||
|
||||
void shutdown();
|
||||
|
||||
@@ -112,9 +113,10 @@ class FrameTimestampCsvLogger {
|
||||
const std::shared_ptr<ob::Frame> &frame,
|
||||
int64_t arrival_system_us, int64_t arrival_steady_us,
|
||||
bool image_publish_expected);
|
||||
void recordPreImagePublishInternal(OBStreamType stream_type,
|
||||
const std::shared_ptr<ob::Frame> &frame,
|
||||
int64_t publish_system_us, int64_t publish_steady_us);
|
||||
void completeImagePublishInternal(OBStreamType stream_type,
|
||||
const std::shared_ptr<ob::Frame> &frame,
|
||||
std::optional<int64_t> publish_system_us,
|
||||
std::optional<int64_t> publish_steady_us);
|
||||
|
||||
void populateArrivalData(StreamState &state, TrackedStream stream,
|
||||
const std::shared_ptr<ob::Frame> &frame, int64_t arrival_system_us,
|
||||
|
||||
@@ -18,7 +18,9 @@
|
||||
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
#include <cstddef>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <rclcpp/rclcpp.hpp>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
@@ -37,9 +39,11 @@
|
||||
#include <std_srvs/srv/set_bool.hpp>
|
||||
#include <std_srvs/srv/empty.hpp>
|
||||
#include <diagnostic_updater/diagnostic_updater.hpp>
|
||||
#include <std_msgs/msg/int32.hpp>
|
||||
|
||||
#include <sensor_msgs/msg/camera_info.hpp>
|
||||
#include <sensor_msgs/msg/compressed_image.hpp>
|
||||
#include <sensor_msgs/msg/image.hpp>
|
||||
#include <camera_info_manager/camera_info_manager.hpp>
|
||||
|
||||
#include <image_publisher/image_publisher.hpp>
|
||||
@@ -63,6 +67,7 @@
|
||||
#include "orbbec_camera_msgs/srv/set_string.hpp"
|
||||
#include "orbbec_camera_msgs/srv/set_filter.hpp"
|
||||
#include "orbbec_camera_msgs/srv/set_arrays.hpp"
|
||||
#include "orbbec_camera_msgs/srv/set_stream_profile.hpp"
|
||||
#include "orbbec_camera_msgs/srv/get_user_calib_params.hpp"
|
||||
#include "orbbec_camera_msgs/srv/set_user_calib_params.hpp"
|
||||
#include "orbbec_camera/constants.h"
|
||||
@@ -122,6 +127,7 @@ using SetBool = std_srvs::srv::SetBool;
|
||||
using GetBool = orbbec_camera_msgs::srv::GetBool;
|
||||
using SetFilter = orbbec_camera_msgs::srv::SetFilter;
|
||||
using SetArrays = orbbec_camera_msgs::srv::SetArrays;
|
||||
using SetStreamProfile = orbbec_camera_msgs::srv::SetStreamProfile;
|
||||
using SetUserCalibParams = orbbec_camera_msgs::srv::SetUserCalibParams;
|
||||
using GetUserCalibParams = orbbec_camera_msgs::srv::GetUserCalibParams;
|
||||
using DepthFilterState = orbbec_camera_msgs::msg::DepthFilterState;
|
||||
@@ -238,6 +244,14 @@ class OBCameraNode {
|
||||
double timestamp_ = -1; // in nanoseconds
|
||||
};
|
||||
|
||||
struct PendingStreamProfile {
|
||||
stream_index_pair stream_index;
|
||||
int requested_width = 0;
|
||||
int requested_height = 0;
|
||||
int requested_fps = 0;
|
||||
std::shared_ptr<ob::VideoStreamProfile> profile;
|
||||
};
|
||||
|
||||
void setupDevices();
|
||||
|
||||
void loadConfigJson();
|
||||
@@ -267,6 +281,24 @@ class OBCameraNode {
|
||||
|
||||
void setupProfiles();
|
||||
|
||||
std::shared_ptr<ob::VideoStreamProfile> selectVideoStreamProfile(
|
||||
const stream_index_pair& stream_index, int width, int height, int fps, OBFormat format);
|
||||
|
||||
std::optional<stream_index_pair> getImageStreamByName(const std::string& stream_name) const;
|
||||
|
||||
bool validateStreamProfileRequest(const std::shared_ptr<SetStreamProfile::Request>& request,
|
||||
std::vector<PendingStreamProfile>& pending_profiles,
|
||||
std::string& message);
|
||||
|
||||
bool applyStreamProfiles(const std::vector<PendingStreamProfile>& pending_profiles,
|
||||
std::string& message);
|
||||
|
||||
void clearColorFrameQueues();
|
||||
|
||||
void stopColorFrameThreads();
|
||||
|
||||
void setupImageBuffers();
|
||||
|
||||
void updateImageConfig(const stream_index_pair& stream_index);
|
||||
|
||||
void printSensorProfiles(const std::shared_ptr<ob::Sensor>& sensor);
|
||||
@@ -277,6 +309,8 @@ class OBCameraNode {
|
||||
|
||||
void setupTopics();
|
||||
|
||||
void setupImagePublisher(const stream_index_pair& stream_index);
|
||||
|
||||
void setupPipelineConfig();
|
||||
|
||||
void setupDiagnosticUpdater();
|
||||
@@ -293,10 +327,15 @@ class OBCameraNode {
|
||||
|
||||
void setupPublishers();
|
||||
|
||||
void syncSoftwareAlignment();
|
||||
|
||||
void publishDepthFiltersStatus();
|
||||
|
||||
void publishLrmObstacleDistance();
|
||||
|
||||
DepthFilterState buildDepthFilterState(const std::string& filter_name, bool enabled,
|
||||
const std::shared_ptr<ob::Filter>& filter) const;
|
||||
DepthFilterState buildEnhancedDepthFilterState() const;
|
||||
|
||||
static std::string normalizeDepthFilterName(const std::string& filter_name);
|
||||
|
||||
@@ -308,6 +347,18 @@ class OBCameraNode {
|
||||
bool applyNamedDepthFilterConfig(
|
||||
const std::string& filter_name, bool enabled,
|
||||
const std::vector<orbbec_camera_msgs::msg::DepthFilterParam>& params, std::string& message);
|
||||
bool applyEnhancedDepthFilterConfig(
|
||||
bool enabled, const std::vector<float>& positional_params,
|
||||
const std::vector<orbbec_camera_msgs::msg::DepthFilterParam>& named_params,
|
||||
std::string& message);
|
||||
bool validateEnhancedDepthFilterConfig(std::string& message) const;
|
||||
bool ensureEnhancedDepthFilter(std::string& message);
|
||||
void applyEnhancedDepthConfidenceThreshold();
|
||||
std::shared_ptr<ob::FrameSet> processEnhancedDepthFilter(
|
||||
const std::shared_ptr<ob::FrameSet>& frame_set);
|
||||
bool convertEnhancedDepthColorFrame(const std::shared_ptr<ob::FrameSet>& frame_set);
|
||||
void setupConfidencePublishers();
|
||||
void publishConfidenceFrame(const std::shared_ptr<ob::Frame>& confidence_frame);
|
||||
|
||||
void setupCameraInfo();
|
||||
|
||||
@@ -328,6 +379,8 @@ class OBCameraNode {
|
||||
|
||||
void setStreamsEnableCallback(const std::shared_ptr<std_srvs::srv::SetBool::Request> request,
|
||||
std::shared_ptr<std_srvs::srv::SetBool::Response> response);
|
||||
void setImageRegistrationModeCallback(const std::shared_ptr<SetString::Request> request,
|
||||
std::shared_ptr<SetString::Response> response);
|
||||
|
||||
void getStreamsEnableCallback(
|
||||
const std::shared_ptr<orbbec_camera_msgs::srv::GetBool::Request> request,
|
||||
@@ -475,6 +528,9 @@ class OBCameraNode {
|
||||
void setAEStrategyCallback(const std::shared_ptr<SetString::Request>& request,
|
||||
std::shared_ptr<SetString::Response>& response);
|
||||
|
||||
void setStreamProfileCallback(const std::shared_ptr<SetStreamProfile::Request>& request,
|
||||
std::shared_ptr<SetStreamProfile::Response>& response);
|
||||
|
||||
void setUserCalibParamsCallback(const std::shared_ptr<SetUserCalibParams::Request>& request,
|
||||
std::shared_ptr<SetUserCalibParams::Response>& response);
|
||||
|
||||
@@ -699,6 +755,8 @@ class OBCameraNode {
|
||||
rclcpp::Service<SetInt32>::SharedPtr set_sync_io_voltage_level_srv_;
|
||||
rclcpp::Service<orbbec_camera_msgs::srv::GetBool>::SharedPtr get_streams_enable_srv_;
|
||||
rclcpp::Service<std_srvs::srv::SetBool>::SharedPtr set_streams_enable_srv_;
|
||||
rclcpp::Service<SetString>::SharedPtr set_image_registration_mode_srv_;
|
||||
rclcpp::Service<SetStreamProfile>::SharedPtr set_stream_profile_srv_;
|
||||
rclcpp::Service<GetUserCalibParams>::SharedPtr get_user_calib_params_srv_;
|
||||
rclcpp::Service<SetUserCalibParams>::SharedPtr set_user_calib_params_srv_;
|
||||
rclcpp::Service<SetString>::SharedPtr set_ae_reference_stream_srv_;
|
||||
@@ -755,6 +813,7 @@ class OBCameraNode {
|
||||
int color_ae_roi_bottom_ = -1;
|
||||
int color_exposure_ = -1;
|
||||
int color_gain_ = -1;
|
||||
int color_mjpeg_quality_ = -1;
|
||||
int color_white_balance_ = -1;
|
||||
int color_ae_max_exposure_ = -1;
|
||||
int color_ae_max_gain_ = -1;
|
||||
@@ -806,7 +865,7 @@ class OBCameraNode {
|
||||
int trigger_out_delay_us_ = 0;
|
||||
bool trigger_out_enabled_ = false;
|
||||
bool software_trigger_enabled_ = false;
|
||||
int frames_per_trigger_ = 2;
|
||||
int frames_per_trigger_ = 1;
|
||||
bool enable_ptp_config_ = false;
|
||||
std::string depth_precision_str_;
|
||||
OB_DEPTH_PRECISION_LEVEL depth_precision_ = OB_PRECISION_0MM8;
|
||||
@@ -832,6 +891,9 @@ class OBCameraNode {
|
||||
uint8_t* rgb_buffer_ = nullptr;
|
||||
uint8_t* rgb_buffer_left_ = nullptr;
|
||||
uint8_t* rgb_buffer_right_ = nullptr;
|
||||
size_t rgb_buffer_size_ = 0;
|
||||
size_t rgb_buffer_left_size_ = 0;
|
||||
size_t rgb_buffer_right_size_ = 0;
|
||||
bool is_left_color_frame_decoded_ = false;
|
||||
bool is_right_color_frame_decoded_ = false;
|
||||
bool is_color_frame_decoded_ = false;
|
||||
@@ -839,6 +901,7 @@ class OBCameraNode {
|
||||
// For color
|
||||
std::queue<std::shared_ptr<ob::FrameSet>> color_frame_queue_;
|
||||
std::shared_ptr<std::thread> colorFrameThread_ = nullptr;
|
||||
std::atomic_bool stop_color_frame_threads_{false};
|
||||
std::mutex color_frame_queue_lock_;
|
||||
std::condition_variable color_frame_queue_cv_;
|
||||
|
||||
@@ -913,6 +976,14 @@ class OBCameraNode {
|
||||
double diagnostic_period_ = 1.0;
|
||||
bool enable_laser_ = false;
|
||||
std::unique_ptr<ob::Align> align_filter_ = nullptr;
|
||||
std::shared_ptr<ob::EnhancedDepthFilter> enhanced_depth_filter_ = nullptr;
|
||||
ob::FormatConvertFilter enhanced_depth_format_convert_filter_;
|
||||
std::mutex enhanced_depth_filter_mutex_;
|
||||
std::atomic_bool enable_enhanced_depth_{false};
|
||||
std::string enhanced_depth_model_path_;
|
||||
int enhanced_depth_confidence_threshold_ = -1;
|
||||
rclcpp::Publisher<sensor_msgs::msg::Image>::SharedPtr confidence_image_publisher_;
|
||||
cv::Mat confidence_image_;
|
||||
OBStreamType align_target_stream_ = OB_STREAM_COLOR;
|
||||
bool retry_on_usb3_detection_failure_ = false;
|
||||
bool config_json_loaded_ = false;
|
||||
@@ -943,13 +1014,18 @@ class OBCameraNode {
|
||||
std::string export_config_json_file_path_ = "";
|
||||
// soft ware trigger
|
||||
rclcpp::TimerBase::SharedPtr software_trigger_timer_;
|
||||
rclcpp::TimerBase::SharedPtr lrm_obstacle_distance_timer_;
|
||||
rclcpp::TimerBase::SharedPtr diagnostic_timer_;
|
||||
rclcpp::Publisher<std_msgs::msg::Int32>::SharedPtr lrm_obstacle_distance_pub_;
|
||||
std::mutex diagnostic_mutex_;
|
||||
std::condition_variable diagnostic_cv_;
|
||||
bool diagnostic_running_ = false;
|
||||
std::chrono::milliseconds software_trigger_period_{33};
|
||||
bool enable_lrm_obstacle_distance_publish_ = false;
|
||||
double lrm_obstacle_distance_publish_rate_ = 10.0;
|
||||
bool enable_heartbeat_ = false;
|
||||
bool enable_firmware_log_ = false;
|
||||
bool enable_fps_boost_ = false;
|
||||
std::map<stream_index_pair, bool> enable_undistortion_;
|
||||
std::shared_ptr<ob::UnDistortionFilter> hw_d2c_color_undistortion_filter_;
|
||||
bool hw_d2c_color_undistortion_configured_ = false;
|
||||
|
||||
@@ -155,6 +155,7 @@ class OBCameraNodeDriver : public rclcpp::Node {
|
||||
std::atomic<bool> firmware_update_success_{false};
|
||||
std::atomic<bool> need_reupdate_{false};
|
||||
std::atomic<bool> is_reupdating_{false}; // Flag to track if we're in reupdate process
|
||||
std::atomic<bool> delay_stream_start_after_reconnect_{false};
|
||||
rclcpp::TimerBase::SharedPtr device_status_timer_ = nullptr;
|
||||
int device_status_interval_hz = 2; // 2Hz
|
||||
rclcpp::Publisher<orbbec_camera_msgs::msg::DeviceStatus>::SharedPtr device_status_pub_ = nullptr;
|
||||
|
||||
@@ -167,7 +167,7 @@ def generate_launch_description():
|
||||
DeclareLaunchArgument('trigger2image_delay_us', default_value='0'),
|
||||
DeclareLaunchArgument('trigger_out_delay_us', default_value='0'),
|
||||
DeclareLaunchArgument('trigger_out_enabled', default_value='true'),
|
||||
DeclareLaunchArgument('frames_per_trigger', default_value='2'),
|
||||
DeclareLaunchArgument('frames_per_trigger', default_value='1'),
|
||||
DeclareLaunchArgument('software_trigger_period', default_value='33'), # ms
|
||||
DeclareLaunchArgument('enable_frame_sync', default_value='true'),
|
||||
DeclareLaunchArgument('ordered_pc', default_value='false'),
|
||||
|
||||
@@ -167,7 +167,7 @@ def generate_launch_description():
|
||||
DeclareLaunchArgument('trigger2image_delay_us', default_value='0'),
|
||||
DeclareLaunchArgument('trigger_out_delay_us', default_value='0'),
|
||||
DeclareLaunchArgument('trigger_out_enabled', default_value='true'),
|
||||
DeclareLaunchArgument('frames_per_trigger', default_value='2'),
|
||||
DeclareLaunchArgument('frames_per_trigger', default_value='1'),
|
||||
DeclareLaunchArgument('software_trigger_period', default_value='33'), # ms
|
||||
DeclareLaunchArgument('enable_frame_sync', default_value='true'),
|
||||
DeclareLaunchArgument('ordered_pc', default_value='false'),
|
||||
|
||||
@@ -166,7 +166,7 @@ def generate_launch_description():
|
||||
DeclareLaunchArgument('trigger2image_delay_us', default_value='0'),
|
||||
DeclareLaunchArgument('trigger_out_delay_us', default_value='0'),
|
||||
DeclareLaunchArgument('trigger_out_enabled', default_value='true'),
|
||||
DeclareLaunchArgument('frames_per_trigger', default_value='2'),
|
||||
DeclareLaunchArgument('frames_per_trigger', default_value='1'),
|
||||
DeclareLaunchArgument('software_trigger_period', default_value='33'), # ms
|
||||
DeclareLaunchArgument('enable_frame_sync', default_value='true'),
|
||||
DeclareLaunchArgument('ordered_pc', default_value='false'),
|
||||
|
||||
@@ -167,7 +167,7 @@ def generate_launch_description():
|
||||
DeclareLaunchArgument('trigger2image_delay_us', default_value='0'),
|
||||
DeclareLaunchArgument('trigger_out_delay_us', default_value='0'),
|
||||
DeclareLaunchArgument('trigger_out_enabled', default_value='true'),
|
||||
DeclareLaunchArgument('frames_per_trigger', default_value='2'),
|
||||
DeclareLaunchArgument('frames_per_trigger', default_value='1'),
|
||||
DeclareLaunchArgument('software_trigger_period', default_value='33'), # ms
|
||||
DeclareLaunchArgument('enable_frame_sync', default_value='true'),
|
||||
DeclareLaunchArgument('ordered_pc', default_value='false'),
|
||||
|
||||
@@ -198,7 +198,7 @@ def generate_launch_description():
|
||||
DeclareLaunchArgument('trigger_out_delay_us', default_value='0'),
|
||||
DeclareLaunchArgument('trigger_out_enabled', default_value='true'),
|
||||
DeclareLaunchArgument('software_trigger_enabled', default_value='true'),
|
||||
DeclareLaunchArgument('frames_per_trigger', default_value='2'),
|
||||
DeclareLaunchArgument('frames_per_trigger', default_value='1'),
|
||||
DeclareLaunchArgument('software_trigger_period', default_value='33'), # ms
|
||||
DeclareLaunchArgument('enable_ptp_config', default_value='false'),
|
||||
DeclareLaunchArgument('enable_frame_sync', default_value='true'),
|
||||
|
||||
@@ -197,24 +197,11 @@ def generate_launch_description():
|
||||
DeclareLaunchArgument('ir_gain', default_value='-1'),
|
||||
DeclareLaunchArgument('ir_ae_max_exposure', default_value='-1'),
|
||||
DeclareLaunchArgument('ir_brightness', default_value='-1'),
|
||||
DeclareLaunchArgument('enable_sync_output_accel_gyro', default_value='false'),
|
||||
DeclareLaunchArgument('enable_accel', default_value='false'),
|
||||
DeclareLaunchArgument('enable_accel_data_correction', default_value='true'),
|
||||
DeclareLaunchArgument('accel_rate', default_value='200hz'),
|
||||
DeclareLaunchArgument('accel_range', default_value='4g'),
|
||||
DeclareLaunchArgument('enable_gyro', default_value='false'),
|
||||
DeclareLaunchArgument('enable_gyro_data_correction', default_value='true'),
|
||||
DeclareLaunchArgument('gyro_rate', default_value='200hz'),
|
||||
DeclareLaunchArgument('gyro_range', default_value='1000dps'),
|
||||
DeclareLaunchArgument('linear_accel_cov', default_value='0.01'),
|
||||
DeclareLaunchArgument('angular_vel_cov', default_value='0.01'),
|
||||
DeclareLaunchArgument('publish_tf', default_value='true'),
|
||||
DeclareLaunchArgument('tf_publish_rate', default_value='0.0'),
|
||||
DeclareLaunchArgument('ir_info_url', default_value=''),
|
||||
DeclareLaunchArgument('color_info_url', default_value=''),
|
||||
|
||||
DeclareLaunchArgument('device_access_mode', default_value='Default'), # Default, EA or CA . only for 335le
|
||||
DeclareLaunchArgument('exposure_range_mode', default_value='default'),#default, ultimate or regular
|
||||
DeclareLaunchArgument('log_level', default_value='info'),
|
||||
DeclareLaunchArgument('log_file_name', default_value=''),
|
||||
DeclareLaunchArgument('enable_publish_extrinsic', default_value='false'),
|
||||
@@ -227,7 +214,7 @@ def generate_launch_description():
|
||||
DeclareLaunchArgument('trigger_out_delay_us', default_value='0'),
|
||||
DeclareLaunchArgument('trigger_out_enabled', default_value='true'),
|
||||
DeclareLaunchArgument('software_trigger_enabled', default_value='true'),
|
||||
DeclareLaunchArgument('frames_per_trigger', default_value='2'),
|
||||
DeclareLaunchArgument('frames_per_trigger', default_value='1'),
|
||||
DeclareLaunchArgument('software_trigger_period', default_value='33'), # ms
|
||||
DeclareLaunchArgument('enable_frame_sync', default_value='true'),
|
||||
DeclareLaunchArgument('ordered_pc', default_value='false'),
|
||||
@@ -236,9 +223,8 @@ def generate_launch_description():
|
||||
DeclareLaunchArgument('enable_hdr_merge', default_value='false'),
|
||||
DeclareLaunchArgument('enable_sequence_id_filter', default_value='false'),
|
||||
DeclareLaunchArgument('enable_threshold_filter', default_value='false'),
|
||||
DeclareLaunchArgument('enable_hardware_noise_removal_filter', default_value='false'),
|
||||
DeclareLaunchArgument('enable_hardware_noise_removal_filter', default_value='true'),
|
||||
DeclareLaunchArgument('enable_noise_removal_filter', default_value='false'),
|
||||
DeclareLaunchArgument('enable_disp_outliers_filter', default_value='false'),
|
||||
DeclareLaunchArgument('enable_spatial_filter', default_value='false'),
|
||||
DeclareLaunchArgument('enable_temporal_filter', default_value='false'),
|
||||
DeclareLaunchArgument('enable_disparity_to_depth', default_value='true'),
|
||||
@@ -296,9 +282,6 @@ def generate_launch_description():
|
||||
DeclareLaunchArgument('frame_aggregate_mode', default_value='ANY'), # full_frame, color_frame, ANY or disable
|
||||
DeclareLaunchArgument('interleave_ae_mode', default_value='hdr'),
|
||||
DeclareLaunchArgument('interleave_frame_enable', default_value='false'),
|
||||
DeclareLaunchArgument('interleave_skip_enable', default_value='false'),
|
||||
DeclareLaunchArgument('interleave_skip_index', default_value='1'), # 0:skip pattern ir 1: skip flood ir
|
||||
|
||||
DeclareLaunchArgument('hdr_index1_depth_exposure', default_value='1'),
|
||||
DeclareLaunchArgument('hdr_index1_depth_gain', default_value='16'),
|
||||
DeclareLaunchArgument('hdr_index1_ir_brightness', default_value='30'),
|
||||
|
||||
@@ -42,7 +42,8 @@ def load_parameters(context, args):
|
||||
if config_file_path:
|
||||
yaml_params = load_yaml(config_file_path)
|
||||
default_params = merge_params(default_params, yaml_params)
|
||||
skip_convert = {'config_file_path', 'usb_port', 'serial_number', 'bag_record_filename', 'bag_filename'}
|
||||
skip_convert = {'config_file_path', 'usb_port', 'serial_number', 'bag_record_filename', 'bag_filename',
|
||||
'enhanced_depth_model_path'}
|
||||
|
||||
result = {}
|
||||
for key, value in default_params.items():
|
||||
@@ -108,6 +109,7 @@ def generate_launch_description():
|
||||
DeclareLaunchArgument('color_ae_roi_bottom', default_value='-1'),
|
||||
DeclareLaunchArgument('color_exposure', default_value='-1'),
|
||||
DeclareLaunchArgument('color_gain', default_value='-1'),
|
||||
DeclareLaunchArgument('color_mjpeg_quality', default_value='-1'),
|
||||
DeclareLaunchArgument('enable_color_auto_white_balance', default_value='true'),
|
||||
DeclareLaunchArgument('color_white_balance', default_value='-1'),
|
||||
DeclareLaunchArgument('enable_color_auto_exposure', default_value='true'),
|
||||
@@ -203,14 +205,17 @@ def generate_launch_description():
|
||||
DeclareLaunchArgument('disparity_to_depth_mode', default_value='HW'),
|
||||
DeclareLaunchArgument('enable_ldp', default_value='false'),
|
||||
DeclareLaunchArgument('ldp_power_level', default_value='-1'),
|
||||
DeclareLaunchArgument('enable_lrm_obstacle_distance_publish', default_value='false'),
|
||||
DeclareLaunchArgument('lrm_obstacle_distance_publish_rate', default_value='10.0'),
|
||||
DeclareLaunchArgument('sync_mode', default_value='standalone'),
|
||||
DeclareLaunchArgument('depth_delay_us', default_value='0'),
|
||||
DeclareLaunchArgument('color_delay_us', default_value='0'),
|
||||
DeclareLaunchArgument('trigger2image_delay_us', default_value='0'),
|
||||
DeclareLaunchArgument('trigger_out_delay_us', default_value='0'),
|
||||
DeclareLaunchArgument('trigger_out_enabled', default_value='true'),
|
||||
DeclareLaunchArgument('enable_fps_boost', default_value='false'),
|
||||
DeclareLaunchArgument('software_trigger_enabled', default_value='true'),
|
||||
DeclareLaunchArgument('frames_per_trigger', default_value='2'),
|
||||
DeclareLaunchArgument('frames_per_trigger', default_value='1'),
|
||||
DeclareLaunchArgument('software_trigger_period', default_value='33'), # ms
|
||||
DeclareLaunchArgument('enable_ptp_config', default_value='false'),#Only for Gemini 335Le
|
||||
DeclareLaunchArgument('enable_frame_sync', default_value='true'),
|
||||
@@ -230,6 +235,9 @@ def generate_launch_description():
|
||||
DeclareLaunchArgument('enable_spatial_fast_filter', default_value='false'),
|
||||
DeclareLaunchArgument('enable_spatial_moderate_filter', default_value='false'),
|
||||
DeclareLaunchArgument('enable_false_positive_filter', default_value='false'),
|
||||
DeclareLaunchArgument('enable_enhanced_depth', default_value='false'),
|
||||
DeclareLaunchArgument('enhanced_depth_model_path', default_value=''),
|
||||
DeclareLaunchArgument('enhanced_depth_confidence_threshold', default_value='51'),
|
||||
DeclareLaunchArgument('decimation_filter_scale', default_value='-1'),
|
||||
DeclareLaunchArgument('sequence_id_filter_id', default_value='-1'),
|
||||
DeclareLaunchArgument('threshold_filter_max', default_value='-1'),
|
||||
|
||||
@@ -42,7 +42,8 @@ def load_parameters(context, args):
|
||||
if config_file_path:
|
||||
yaml_params = load_yaml(config_file_path)
|
||||
default_params = merge_params(default_params, yaml_params)
|
||||
skip_convert = {'config_file_path', 'usb_port', 'serial_number', 'bag_record_filename', 'bag_filename'}
|
||||
skip_convert = {'config_file_path', 'usb_port', 'serial_number', 'bag_record_filename', 'bag_filename',
|
||||
'enhanced_depth_model_path'}
|
||||
|
||||
result = {}
|
||||
for key, value in default_params.items():
|
||||
@@ -106,6 +107,7 @@ def generate_launch_description():
|
||||
DeclareLaunchArgument('color_ae_roi_bottom', default_value='-1'),
|
||||
DeclareLaunchArgument('color_exposure', default_value='-1'),
|
||||
DeclareLaunchArgument('color_gain', default_value='-1'),
|
||||
DeclareLaunchArgument('color_mjpeg_quality', default_value='-1'),
|
||||
DeclareLaunchArgument('enable_color_auto_white_balance', default_value='true'),
|
||||
DeclareLaunchArgument('color_white_balance', default_value='-1'),
|
||||
DeclareLaunchArgument('enable_color_auto_exposure', default_value='true'),
|
||||
@@ -206,8 +208,9 @@ def generate_launch_description():
|
||||
DeclareLaunchArgument('trigger2image_delay_us', default_value='0'),
|
||||
DeclareLaunchArgument('trigger_out_delay_us', default_value='0'),
|
||||
DeclareLaunchArgument('trigger_out_enabled', default_value='true'),
|
||||
DeclareLaunchArgument('enable_fps_boost', default_value='false'),
|
||||
DeclareLaunchArgument('software_trigger_enabled', default_value='true'),
|
||||
DeclareLaunchArgument('frames_per_trigger', default_value='2'),
|
||||
DeclareLaunchArgument('frames_per_trigger', default_value='1'),
|
||||
DeclareLaunchArgument('software_trigger_period', default_value='33'), # ms
|
||||
DeclareLaunchArgument('enable_ptp_config', default_value='false'),#Only for Gemini 335Le
|
||||
DeclareLaunchArgument('enable_frame_sync', default_value='true'),
|
||||
@@ -227,6 +230,9 @@ def generate_launch_description():
|
||||
DeclareLaunchArgument('enable_spatial_fast_filter', default_value='false'),
|
||||
DeclareLaunchArgument('enable_spatial_moderate_filter', default_value='false'),
|
||||
DeclareLaunchArgument('enable_false_positive_filter', default_value='false'),
|
||||
DeclareLaunchArgument('enable_enhanced_depth', default_value='false'),
|
||||
DeclareLaunchArgument('enhanced_depth_model_path', default_value=''),
|
||||
DeclareLaunchArgument('enhanced_depth_confidence_threshold', default_value='51'),
|
||||
DeclareLaunchArgument('decimation_filter_scale', default_value='-1'),
|
||||
DeclareLaunchArgument('sequence_id_filter_id', default_value='-1'),
|
||||
DeclareLaunchArgument('threshold_filter_max', default_value='-1'),
|
||||
|
||||
@@ -125,7 +125,7 @@ def generate_launch_description():
|
||||
DeclareLaunchArgument('trigger2image_delay_us', default_value='0'),
|
||||
DeclareLaunchArgument('trigger_out_delay_us', default_value='0'),
|
||||
DeclareLaunchArgument('trigger_out_enabled', default_value='true'),
|
||||
DeclareLaunchArgument('frames_per_trigger', default_value='2'),
|
||||
DeclareLaunchArgument('frames_per_trigger', default_value='1'),
|
||||
DeclareLaunchArgument('software_trigger_period', default_value='33'), # ms
|
||||
DeclareLaunchArgument('enable_frame_sync', default_value='true'),
|
||||
DeclareLaunchArgument('ordered_pc', default_value='false'),
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<?xml-model href="http://download.ros.org/schema/package_format3.xsd" schematypens="http://www.w3.org/2001/XMLSchema"?>
|
||||
<package format="3">
|
||||
<name>orbbec_camera</name>
|
||||
<version>2.9.1</version>
|
||||
<version>2.9.3</version>
|
||||
<description>Orbbec Camera package</description>
|
||||
<maintainer email="yalian@orbbec.com">yalian</maintainer>
|
||||
<license>Apache-2.0</license>
|
||||
|
||||
@@ -109,7 +109,15 @@ void FrameTimestampCsvLogger::recordPreImagePublish(OBStreamType stream_type,
|
||||
if (!enabled_ || !frame || !isTrackedStream(stream_type)) {
|
||||
return;
|
||||
}
|
||||
recordPreImagePublishInternal(stream_type, frame, publish_system_us, publish_steady_us);
|
||||
completeImagePublishInternal(stream_type, frame, publish_system_us, publish_steady_us);
|
||||
}
|
||||
|
||||
void FrameTimestampCsvLogger::recordImagePublishSkipped(OBStreamType stream_type,
|
||||
const std::shared_ptr<ob::Frame> &frame) {
|
||||
if (!enabled_ || !frame || !isTrackedStream(stream_type)) {
|
||||
return;
|
||||
}
|
||||
completeImagePublishInternal(stream_type, frame, std::nullopt, std::nullopt);
|
||||
}
|
||||
|
||||
void FrameTimestampCsvLogger::shutdown() {
|
||||
@@ -257,10 +265,9 @@ void FrameTimestampCsvLogger::recordStandaloneFrameArrivalInternal(
|
||||
}
|
||||
}
|
||||
|
||||
void FrameTimestampCsvLogger::recordPreImagePublishInternal(OBStreamType stream_type,
|
||||
const std::shared_ptr<ob::Frame> &frame,
|
||||
int64_t publish_system_us,
|
||||
int64_t publish_steady_us) {
|
||||
void FrameTimestampCsvLogger::completeImagePublishInternal(
|
||||
OBStreamType stream_type, const std::shared_ptr<ob::Frame> &frame,
|
||||
std::optional<int64_t> publish_system_us, std::optional<int64_t> publish_steady_us) {
|
||||
std::optional<PendingRow> ready_row;
|
||||
const auto frame_index = frame->getIndex();
|
||||
|
||||
@@ -275,10 +282,12 @@ void FrameTimestampCsvLogger::recordPreImagePublishInternal(OBStreamType stream_
|
||||
: depth_frame_index_to_row_id_;
|
||||
auto row_id_it = row_map.find(frame_index);
|
||||
if (row_id_it == row_map.end()) {
|
||||
RCLCPP_WARN_STREAM(logger_,
|
||||
"Frame timestamp CSV logger missed row mapping for stream "
|
||||
<< (tracked_stream == TrackedStream::COLOR ? "color" : "depth")
|
||||
<< " frame index " << frame_index);
|
||||
if (publish_system_us.has_value()) {
|
||||
RCLCPP_WARN_STREAM(logger_,
|
||||
"Frame timestamp CSV logger missed row mapping for stream "
|
||||
<< (tracked_stream == TrackedStream::COLOR ? "color" : "depth")
|
||||
<< " frame index " << frame_index);
|
||||
}
|
||||
return;
|
||||
}
|
||||
const auto row_id = row_id_it->second;
|
||||
@@ -290,8 +299,16 @@ void FrameTimestampCsvLogger::recordPreImagePublishInternal(OBStreamType stream_
|
||||
|
||||
auto &state = tracked_stream == TrackedStream::COLOR ? pending_it->second.color
|
||||
: pending_it->second.depth;
|
||||
populatePublishData(state, tracked_stream, publish_system_us, publish_steady_us);
|
||||
state.final = true;
|
||||
if (state.final) {
|
||||
return;
|
||||
}
|
||||
if (publish_system_us.has_value() && publish_steady_us.has_value()) {
|
||||
populatePublishData(state, tracked_stream, publish_system_us.value(),
|
||||
publish_steady_us.value());
|
||||
state.final = true;
|
||||
} else {
|
||||
finalizeStreamWithoutPublish(state);
|
||||
}
|
||||
|
||||
if (isRowReady(pending_it->second)) {
|
||||
ready_row = pending_it->second;
|
||||
@@ -440,6 +457,8 @@ void FrameTimestampCsvLogger::flushPendingRowsLocked(std::vector<PendingRow> &ro
|
||||
row.depth.final = true;
|
||||
rows.push_back(std::move(row));
|
||||
}
|
||||
std::stable_sort(rows.begin(), rows.end(),
|
||||
[](const auto &lhs, const auto &rhs) { return lhs.row_id < rhs.row_id; });
|
||||
pending_rows_.clear();
|
||||
color_frame_index_to_row_id_.clear();
|
||||
depth_frame_index_to_row_id_.clear();
|
||||
|
||||
+1082
-127
File diff suppressed because it is too large
Load Diff
@@ -37,6 +37,8 @@
|
||||
std::string g_camera_name = "orbbec_camera"; // Assuming this is declared elsewhere
|
||||
std::string g_time_domain = "global"; // Assuming this is declared elsewhere
|
||||
namespace {
|
||||
constexpr auto kStreamStartDelayAfterReconnect = std::chrono::seconds(5);
|
||||
|
||||
std::string getLogDirectoryForCamera(const std::string &camera_name) {
|
||||
const char *log_dir_override = std::getenv("ORBBEC_LOG_DIR");
|
||||
if (log_dir_override && log_dir_override[0] != '\0') {
|
||||
@@ -77,7 +79,7 @@ void signalHandler(int sig) {
|
||||
_exit(sig);
|
||||
}
|
||||
|
||||
std::cout << "Received signal: " << sig << std::endl;
|
||||
std::cerr << "Received signal: " << sig << std::endl;
|
||||
if (sig == SIGINT || sig == SIGTERM) {
|
||||
static int signal_count = 0;
|
||||
signal_count++;
|
||||
@@ -111,7 +113,7 @@ void signalHandler(int sig) {
|
||||
std::filesystem::create_directories(log_dir);
|
||||
}
|
||||
|
||||
std::cout << "Log crash stack trace to " << log_file_path.string() << std::endl;
|
||||
std::cerr << "Log crash stack trace to " << log_file_path.string() << std::endl;
|
||||
std::ofstream log_file(log_file_path, std::ios::app);
|
||||
|
||||
if (log_file.is_open()) {
|
||||
@@ -475,6 +477,7 @@ void OBCameraNodeDriver::onDeviceDisconnected(const std::shared_ptr<ob::DeviceLi
|
||||
if (uid == device_unique_id_ || serial_number_ == serial_number) {
|
||||
RCLCPP_INFO_STREAM(logger_,
|
||||
"device with " << uid << " disconnected, notify reset device thread");
|
||||
delay_stream_start_after_reconnect_ = true;
|
||||
reset_device_flag_ = true;
|
||||
reset_device_cond_.notify_all();
|
||||
break;
|
||||
@@ -905,6 +908,7 @@ void OBCameraNodeDriver::rebootDeviceCallback(
|
||||
} else {
|
||||
std::string current_device_uid = device_unique_id_;
|
||||
RCLCPP_INFO_STREAM(logger_, "Rebooting device with UID: " << current_device_uid);
|
||||
delay_stream_start_after_reconnect_ = true;
|
||||
if (ob_lidar_node_) {
|
||||
ob_lidar_node_->rebootDevice();
|
||||
} else if (ob_camera_node_) {
|
||||
@@ -1329,6 +1333,12 @@ void OBCameraNodeDriver::initializeDevice(const std::shared_ptr<ob::Device> &dev
|
||||
}
|
||||
}
|
||||
|
||||
const bool should_delay_stream_start = delay_stream_start_after_reconnect_.exchange(false) &&
|
||||
isGemini305SeriesPID(device_info_->getPid());
|
||||
if (should_delay_stream_start) {
|
||||
std::this_thread::sleep_for(kStreamStartDelayAfterReconnect);
|
||||
}
|
||||
|
||||
if (ob_camera_node_) {
|
||||
ob_camera_node_->startIMU();
|
||||
ob_camera_node_->startStreams();
|
||||
@@ -1739,6 +1749,7 @@ void OBCameraNodeDriver::firmwareUpdateCallback(OBFwUpdateState state, const cha
|
||||
RCLCPP_WARN_STREAM(logger_, "Exception during sync timer cleanup in firmware update");
|
||||
}
|
||||
}
|
||||
delay_stream_start_after_reconnect_ = true;
|
||||
device_->reboot();
|
||||
} else if (ob_lidar_node_) {
|
||||
ob_lidar_node_.reset();
|
||||
|
||||
@@ -15,6 +15,8 @@
|
||||
*******************************************************************************/
|
||||
|
||||
#include "orbbec_camera/ob_camera_node.h"
|
||||
#include <algorithm>
|
||||
#include <cctype>
|
||||
#include <rclcpp/rclcpp.hpp>
|
||||
#include <nlohmann/json.hpp>
|
||||
#include <thread>
|
||||
@@ -72,6 +74,28 @@ std::string disparityToDepthModeToString(bool hardware_enabled, bool software_en
|
||||
return "disable";
|
||||
}
|
||||
|
||||
bool isPropertySupported(const std::shared_ptr<ob::Device>& device, OBPropertyID property_id,
|
||||
OBPermissionType permission) {
|
||||
if (!device) {
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
return device->isPropertySupported(property_id, permission);
|
||||
} catch (...) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool isPropertyReadable(const std::shared_ptr<ob::Device>& device, OBPropertyID property_id) {
|
||||
return isPropertySupported(device, property_id, OB_PERMISSION_READ) ||
|
||||
isPropertySupported(device, property_id, OB_PERMISSION_READ_WRITE);
|
||||
}
|
||||
|
||||
bool isPropertyWritable(const std::shared_ptr<ob::Device>& device, OBPropertyID property_id) {
|
||||
return isPropertySupported(device, property_id, OB_PERMISSION_WRITE) ||
|
||||
isPropertySupported(device, property_id, OB_PERMISSION_READ_WRITE);
|
||||
}
|
||||
|
||||
std::string OBSyncModeToString(const OBMultiDeviceSyncMode& mode) {
|
||||
switch (mode) {
|
||||
case OBMultiDeviceSyncMode::OB_MULTI_DEVICE_SYNC_MODE_FREE_RUN:
|
||||
@@ -178,56 +202,80 @@ void OBCameraNode::setupCameraCtrlServices() {
|
||||
setRotationCallback(request, response, stream_index);
|
||||
});
|
||||
}
|
||||
set_fan_work_mode_srv_ = node_->create_service<SetInt32>(
|
||||
"set_fan_work_mode", [this](const std::shared_ptr<SetInt32::Request> request,
|
||||
std::shared_ptr<SetInt32::Response> response) {
|
||||
setFanWorkModeCallback(request, response);
|
||||
});
|
||||
set_floor_enable_srv_ = node_->create_service<SetBool>(
|
||||
"set_floor_enable", [this](const std::shared_ptr<rmw_request_id_t> request_header,
|
||||
if (isPropertyWritable(device_, OB_PROP_FAN_WORK_MODE_INT)) {
|
||||
set_fan_work_mode_srv_ = node_->create_service<SetInt32>(
|
||||
"set_fan_work_mode", [this](const std::shared_ptr<SetInt32::Request> request,
|
||||
std::shared_ptr<SetInt32::Response> response) {
|
||||
setFanWorkModeCallback(request, response);
|
||||
});
|
||||
}
|
||||
if (isPropertyWritable(device_, OB_PROP_FLOOD_BOOL)) {
|
||||
set_floor_enable_srv_ = node_->create_service<SetBool>(
|
||||
"set_floor_enable", [this](const std::shared_ptr<rmw_request_id_t> request_header,
|
||||
const std::shared_ptr<SetBool::Request> request,
|
||||
std::shared_ptr<SetBool::Response> response) {
|
||||
setFloorEnableCallback(request_header, request, response);
|
||||
});
|
||||
}
|
||||
if (isPropertyWritable(device_, OB_PROP_LASER_CONTROL_INT) ||
|
||||
isPropertyWritable(device_, OB_PROP_LASER_BOOL)) {
|
||||
set_laser_enable_srv_ = node_->create_service<SetBool>(
|
||||
"set_laser_enable", [this](const std::shared_ptr<rmw_request_id_t> request_header,
|
||||
const std::shared_ptr<SetBool::Request> request,
|
||||
std::shared_ptr<SetBool::Response> response) {
|
||||
setLaserEnableCallback(request_header, request, response);
|
||||
});
|
||||
}
|
||||
if (isPropertyWritable(device_, OB_PROP_LDP_BOOL) &&
|
||||
((isPropertyReadable(device_, OB_PROP_LASER_CONTROL_INT) &&
|
||||
isPropertyWritable(device_, OB_PROP_LASER_CONTROL_INT)) ||
|
||||
(isPropertyReadable(device_, OB_PROP_LASER_BOOL) &&
|
||||
isPropertyWritable(device_, OB_PROP_LASER_BOOL)))) {
|
||||
set_ldp_enable_srv_ = node_->create_service<SetBool>(
|
||||
"set_ldp_enable", [this](const std::shared_ptr<rmw_request_id_t> request_header,
|
||||
const std::shared_ptr<SetBool::Request> request,
|
||||
std::shared_ptr<SetBool::Response> response) {
|
||||
setFloorEnableCallback(request_header, request, response);
|
||||
});
|
||||
set_laser_enable_srv_ = node_->create_service<SetBool>(
|
||||
"set_laser_enable", [this](const std::shared_ptr<rmw_request_id_t> request_header,
|
||||
const std::shared_ptr<SetBool::Request> request,
|
||||
std::shared_ptr<SetBool::Response> response) {
|
||||
setLaserEnableCallback(request_header, request, response);
|
||||
});
|
||||
set_ldp_enable_srv_ = node_->create_service<SetBool>(
|
||||
"set_ldp_enable", [this](const std::shared_ptr<rmw_request_id_t> request_header,
|
||||
const std::shared_ptr<SetBool::Request> request,
|
||||
std::shared_ptr<SetBool::Response> response) {
|
||||
setLdpEnableCallback(request_header, request, response);
|
||||
});
|
||||
get_ldp_status_srv_ = node_->create_service<GetBool>(
|
||||
"get_ldp_status", [this](const std::shared_ptr<rmw_request_id_t> request_header,
|
||||
const std::shared_ptr<GetBool::Request> request,
|
||||
std::shared_ptr<GetBool::Response> response) {
|
||||
(void)request_header;
|
||||
getLdpStatusCallback(request, response);
|
||||
});
|
||||
get_laser_status_srv_ = node_->create_service<GetBool>(
|
||||
"get_laser_status", [this](const std::shared_ptr<rmw_request_id_t> request_header,
|
||||
setLdpEnableCallback(request_header, request, response);
|
||||
});
|
||||
}
|
||||
if (isPropertyReadable(device_, OB_PROP_LDP_BOOL) &&
|
||||
isPropertyReadable(device_, OB_PROP_LDP_STATUS_BOOL)) {
|
||||
get_ldp_status_srv_ = node_->create_service<GetBool>(
|
||||
"get_ldp_status", [this](const std::shared_ptr<rmw_request_id_t> request_header,
|
||||
const std::shared_ptr<GetBool::Request> request,
|
||||
std::shared_ptr<GetBool::Response> response) {
|
||||
(void)request_header;
|
||||
getLaserStatusCallback(request, response);
|
||||
});
|
||||
set_ptp_config_srv_ = node_->create_service<SetBool>(
|
||||
"set_ptp_config", [this](const std::shared_ptr<rmw_request_id_t> request_header,
|
||||
const std::shared_ptr<SetBool::Request> request,
|
||||
std::shared_ptr<SetBool::Response> response) {
|
||||
setPtpConfigCallback(request_header, request, response);
|
||||
});
|
||||
get_ptp_config_srv_ = node_->create_service<GetBool>(
|
||||
"get_ptp_config", [this](const std::shared_ptr<rmw_request_id_t> request_header,
|
||||
const std::shared_ptr<GetBool::Request> request,
|
||||
std::shared_ptr<GetBool::Response> response) {
|
||||
(void)request_header;
|
||||
getPtpConfigCallback(request, response);
|
||||
});
|
||||
(void)request_header;
|
||||
getLdpStatusCallback(request, response);
|
||||
});
|
||||
}
|
||||
if (isPropertyReadable(device_, OB_PROP_LASER_CONTROL_INT) ||
|
||||
isPropertyReadable(device_, OB_PROP_LASER_BOOL)) {
|
||||
get_laser_status_srv_ = node_->create_service<GetBool>(
|
||||
"get_laser_status", [this](const std::shared_ptr<rmw_request_id_t> request_header,
|
||||
const std::shared_ptr<GetBool::Request> request,
|
||||
std::shared_ptr<GetBool::Response> response) {
|
||||
(void)request_header;
|
||||
getLaserStatusCallback(request, response);
|
||||
});
|
||||
}
|
||||
if (isPropertyReadable(device_, OB_DEVICE_PTP_CLOCK_SYNC_ENABLE_BOOL) &&
|
||||
isPropertyWritable(device_, OB_DEVICE_PTP_CLOCK_SYNC_ENABLE_BOOL)) {
|
||||
set_ptp_config_srv_ = node_->create_service<SetBool>(
|
||||
"set_ptp_config", [this](const std::shared_ptr<rmw_request_id_t> request_header,
|
||||
const std::shared_ptr<SetBool::Request> request,
|
||||
std::shared_ptr<SetBool::Response> response) {
|
||||
setPtpConfigCallback(request_header, request, response);
|
||||
});
|
||||
}
|
||||
if (isPropertyReadable(device_, OB_DEVICE_PTP_CLOCK_SYNC_ENABLE_BOOL)) {
|
||||
get_ptp_config_srv_ = node_->create_service<GetBool>(
|
||||
"get_ptp_config", [this](const std::shared_ptr<rmw_request_id_t> request_header,
|
||||
const std::shared_ptr<GetBool::Request> request,
|
||||
std::shared_ptr<GetBool::Response> response) {
|
||||
(void)request_header;
|
||||
getPtpConfigCallback(request, response);
|
||||
});
|
||||
}
|
||||
|
||||
get_white_balance_srv_ = node_->create_service<GetInt32>(
|
||||
"get_white_balance", [this](const std::shared_ptr<GetInt32::Request> request,
|
||||
@@ -279,31 +327,42 @@ void OBCameraNode::setupCameraCtrlServices() {
|
||||
std::shared_ptr<SetString::Response> response) {
|
||||
exportConfigJsonCallback(request, response);
|
||||
});
|
||||
switch_ir_camera_srv_ = node_->create_service<SetString>(
|
||||
"switch_ir", [this](const std::shared_ptr<SetString::Request> request,
|
||||
std::shared_ptr<SetString::Response> response) {
|
||||
switchIRCameraCallback(request, response);
|
||||
});
|
||||
set_ir_long_exposure_srv_ = node_->create_service<SetBool>(
|
||||
"set_ir_long_exposure", [this](const std::shared_ptr<SetBool::Request> request,
|
||||
std::shared_ptr<SetBool::Response> response) {
|
||||
setIRLongExposureCallback(request, response);
|
||||
});
|
||||
get_lrm_measure_distance_srv_ = node_->create_service<GetInt32>(
|
||||
"get_lrm_measure_distance", [this](const std::shared_ptr<GetInt32::Request> request,
|
||||
std::shared_ptr<GetInt32::Response> response) {
|
||||
getLrmMeasureDistanceCallback(request, response);
|
||||
});
|
||||
set_reset_timestamp_srv_ = node_->create_service<SetBool>(
|
||||
"set_reset_timestamp", [this](const std::shared_ptr<SetBool::Request> request,
|
||||
std::shared_ptr<SetBool::Response> response) {
|
||||
setRESETTimestampCallback(request, response);
|
||||
});
|
||||
set_interleaver_laser_sync_srv_ = node_->create_service<SetInt32>(
|
||||
"set_sync_interleaverlaser", [this](const std::shared_ptr<SetInt32::Request> request,
|
||||
std::shared_ptr<SetInt32::Response> response) {
|
||||
setSYNCInterleaveLaserCallback(request, response);
|
||||
});
|
||||
if (isPropertyWritable(device_, OB_PROP_IR_CHANNEL_DATA_SOURCE_INT)) {
|
||||
switch_ir_camera_srv_ = node_->create_service<SetString>(
|
||||
"switch_ir", [this](const std::shared_ptr<SetString::Request> request,
|
||||
std::shared_ptr<SetString::Response> response) {
|
||||
switchIRCameraCallback(request, response);
|
||||
});
|
||||
}
|
||||
if (isPropertyWritable(device_, OB_PROP_IR_LONG_EXPOSURE_BOOL)) {
|
||||
set_ir_long_exposure_srv_ = node_->create_service<SetBool>(
|
||||
"set_ir_long_exposure", [this](const std::shared_ptr<SetBool::Request> request,
|
||||
std::shared_ptr<SetBool::Response> response) {
|
||||
setIRLongExposureCallback(request, response);
|
||||
});
|
||||
}
|
||||
if (isPropertyReadable(device_, OB_PROP_LDP_MEASURE_DISTANCE_INT)) {
|
||||
get_lrm_measure_distance_srv_ = node_->create_service<GetInt32>(
|
||||
"get_lrm_measure_distance", [this](const std::shared_ptr<GetInt32::Request> request,
|
||||
std::shared_ptr<GetInt32::Response> response) {
|
||||
getLrmMeasureDistanceCallback(request, response);
|
||||
});
|
||||
}
|
||||
if (isPropertyWritable(device_, OB_PROP_TIMER_RESET_TRIGGER_OUT_ENABLE_BOOL) &&
|
||||
isPropertyWritable(device_, OB_PROP_TIMER_RESET_SIGNAL_BOOL)) {
|
||||
set_reset_timestamp_srv_ = node_->create_service<SetBool>(
|
||||
"set_reset_timestamp", [this](const std::shared_ptr<SetBool::Request> request,
|
||||
std::shared_ptr<SetBool::Response> response) {
|
||||
setRESETTimestampCallback(request, response);
|
||||
});
|
||||
}
|
||||
if (isPropertyWritable(device_, OB_PROP_FRAME_INTERLEAVE_LASER_PATTERN_SYNC_DELAY_INT)) {
|
||||
set_interleaver_laser_sync_srv_ = node_->create_service<SetInt32>(
|
||||
"set_sync_interleaverlaser", [this](const std::shared_ptr<SetInt32::Request> request,
|
||||
std::shared_ptr<SetInt32::Response> response) {
|
||||
setSYNCInterleaveLaserCallback(request, response);
|
||||
});
|
||||
}
|
||||
set_sync_host_time_srv_ = node_->create_service<SetBool>(
|
||||
"set_sync_hosttime", [this](const std::shared_ptr<SetBool::Request> request,
|
||||
std::shared_ptr<SetBool::Response> response) {
|
||||
@@ -351,6 +410,16 @@ void OBCameraNode::setupCameraCtrlServices() {
|
||||
std::shared_ptr<SetBool::Response> response) {
|
||||
setStreamsEnableCallback(request, response);
|
||||
});
|
||||
set_image_registration_mode_srv_ = node_->create_service<SetString>(
|
||||
"set_image_registration_mode", [this](const std::shared_ptr<SetString::Request> request,
|
||||
std::shared_ptr<SetString::Response> response) {
|
||||
setImageRegistrationModeCallback(request, response);
|
||||
});
|
||||
set_stream_profile_srv_ = node_->create_service<SetStreamProfile>(
|
||||
"set_stream_profile", [this](const std::shared_ptr<SetStreamProfile::Request> request,
|
||||
std::shared_ptr<SetStreamProfile::Response> response) {
|
||||
setStreamProfileCallback(request, response);
|
||||
});
|
||||
get_streams_enable_srv_ = node_->create_service<GetBool>(
|
||||
"get_streams_enable", [this](const std::shared_ptr<GetBool::Request> request,
|
||||
std::shared_ptr<GetBool::Response> response) {
|
||||
@@ -366,21 +435,27 @@ void OBCameraNode::setupCameraCtrlServices() {
|
||||
std::shared_ptr<GetInt32::Response> response) {
|
||||
getPointCloudDecimationCallback(request, response);
|
||||
});
|
||||
set_disparity_range_mode_srv_ = node_->create_service<SetInt32>(
|
||||
"set_disparity_range_mode", [this](const std::shared_ptr<SetInt32::Request> request,
|
||||
std::shared_ptr<SetInt32::Response> response) {
|
||||
setDisparityRangeModeCallback(request, response);
|
||||
});
|
||||
set_disparity_search_offset_srv_ = node_->create_service<SetInt32>(
|
||||
"set_disparity_search_offset", [this](const std::shared_ptr<SetInt32::Request> request,
|
||||
if (isPropertyWritable(device_, OB_PROP_DISP_SEARCH_RANGE_MODE_INT)) {
|
||||
set_disparity_range_mode_srv_ = node_->create_service<SetInt32>(
|
||||
"set_disparity_range_mode", [this](const std::shared_ptr<SetInt32::Request> request,
|
||||
std::shared_ptr<SetInt32::Response> response) {
|
||||
setDisparityRangeModeCallback(request, response);
|
||||
});
|
||||
}
|
||||
if (isPropertyWritable(device_, OB_PROP_DISP_SEARCH_OFFSET_INT)) {
|
||||
set_disparity_search_offset_srv_ = node_->create_service<SetInt32>(
|
||||
"set_disparity_search_offset", [this](const std::shared_ptr<SetInt32::Request> request,
|
||||
std::shared_ptr<SetInt32::Response> response) {
|
||||
setDisparitySearchOffsetCallback(request, response);
|
||||
});
|
||||
}
|
||||
if (isPropertyWritable(device_, OB_PROP_USB_SYNC_VOLTAGE_LEVEL_INT)) {
|
||||
set_sync_io_voltage_level_srv_ = node_->create_service<SetInt32>(
|
||||
"set_sync_io_voltage_level", [this](const std::shared_ptr<SetInt32::Request> request,
|
||||
std::shared_ptr<SetInt32::Response> response) {
|
||||
setDisparitySearchOffsetCallback(request, response);
|
||||
});
|
||||
set_sync_io_voltage_level_srv_ = node_->create_service<SetInt32>(
|
||||
"set_sync_io_voltage_level", [this](const std::shared_ptr<SetInt32::Request> request,
|
||||
std::shared_ptr<SetInt32::Response> response) {
|
||||
setSyncIoVoltageLevelCallback(request, response);
|
||||
});
|
||||
setSyncIoVoltageLevelCallback(request, response);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void OBCameraNode::getPointCloudDecimationCallback(
|
||||
@@ -632,6 +707,146 @@ void OBCameraNode::setStreamsEnableCallback(
|
||||
}
|
||||
}
|
||||
|
||||
void OBCameraNode::setImageRegistrationModeCallback(
|
||||
const std::shared_ptr<SetString::Request> request,
|
||||
std::shared_ptr<SetString::Response> response) {
|
||||
auto mode = request->data;
|
||||
std::transform(mode.begin(), mode.end(), mode.begin(),
|
||||
[](unsigned char ch) { return static_cast<char>(std::toupper(ch)); });
|
||||
if (mode != "OFF" && mode != "HW_D2C" && mode != "SW_D2C" && mode != "SW_C2D") {
|
||||
response->success = false;
|
||||
response->message = "Invalid image registration mode '" + request->data +
|
||||
"'. Valid values: OFF, HW_D2C, SW_D2C, SW_C2D";
|
||||
return;
|
||||
}
|
||||
|
||||
std::lock_guard<decltype(device_lock_)> lock(device_lock_);
|
||||
|
||||
if (mode != "OFF" && (!enable_stream_[COLOR] || !enable_stream_[DEPTH])) {
|
||||
response->success = false;
|
||||
response->message =
|
||||
"Image registration mode " + mode + " requires both color and depth streams to be enabled";
|
||||
return;
|
||||
}
|
||||
|
||||
const bool old_depth_registration = depth_registration_;
|
||||
const std::string old_align_mode = align_mode_;
|
||||
const OBStreamType old_align_target_stream = align_target_stream_;
|
||||
const bool was_running = pipeline_started_.load();
|
||||
|
||||
auto mode_from_state = [](bool depth_registration, const std::string& align_mode,
|
||||
OBStreamType align_target_stream) {
|
||||
if (!depth_registration) {
|
||||
return std::string("OFF");
|
||||
}
|
||||
if (align_mode == "HW") {
|
||||
return std::string("HW_D2C");
|
||||
}
|
||||
return align_target_stream == OB_STREAM_DEPTH ? std::string("SW_C2D") : std::string("SW_D2C");
|
||||
};
|
||||
const auto old_mode =
|
||||
mode_from_state(old_depth_registration, old_align_mode, old_align_target_stream);
|
||||
|
||||
auto apply_image_registration_mode = [this](const std::string& mode) {
|
||||
if (mode == "OFF") {
|
||||
depth_registration_ = false;
|
||||
align_mode_ = "HW";
|
||||
align_target_stream_ = OB_STREAM_COLOR;
|
||||
} else if (mode == "HW_D2C") {
|
||||
depth_registration_ = true;
|
||||
align_mode_ = "HW";
|
||||
align_target_stream_ = OB_STREAM_COLOR;
|
||||
} else {
|
||||
depth_registration_ = true;
|
||||
align_mode_ = "SW";
|
||||
align_target_stream_ = mode == "SW_C2D" ? OB_STREAM_DEPTH : OB_STREAM_COLOR;
|
||||
}
|
||||
align_filter_.reset();
|
||||
syncSoftwareAlignment();
|
||||
};
|
||||
|
||||
auto restore_old_mode = [this, old_depth_registration, old_align_mode,
|
||||
old_align_target_stream]() {
|
||||
depth_registration_ = old_depth_registration;
|
||||
align_mode_ = old_align_mode;
|
||||
align_target_stream_ = old_align_target_stream;
|
||||
align_filter_.reset();
|
||||
syncSoftwareAlignment();
|
||||
};
|
||||
|
||||
auto rollback_after_error = [&](const std::string& error_message) {
|
||||
try {
|
||||
restore_old_mode();
|
||||
if (was_running && !pipeline_started_.load()) {
|
||||
startStreams();
|
||||
}
|
||||
response->message = "Failed to set image registration mode to " + mode + ": " +
|
||||
error_message + ". Rolled back to " + old_mode;
|
||||
} catch (const std::exception& rollback_error) {
|
||||
response->message = "Failed to set image registration mode to " + mode + ": " +
|
||||
error_message + ". Rollback to " + old_mode +
|
||||
" also failed: " + rollback_error.what();
|
||||
} catch (...) {
|
||||
response->message = "Failed to set image registration mode to " + mode + ": " +
|
||||
error_message + ". Rollback to " + old_mode + " also failed";
|
||||
}
|
||||
response->success = false;
|
||||
};
|
||||
|
||||
try {
|
||||
if (was_running) {
|
||||
stopStreams();
|
||||
}
|
||||
|
||||
apply_image_registration_mode(mode);
|
||||
|
||||
if (was_running) {
|
||||
startStreams();
|
||||
response->message = "Image registration mode changed from " + old_mode + " to " + mode +
|
||||
"; streams restarted";
|
||||
} else {
|
||||
response->message = "Image registration mode set to " + mode + "; streams remain stopped";
|
||||
}
|
||||
response->success = true;
|
||||
} catch (const ob::Error& e) {
|
||||
rollback_after_error(orbbec_camera::formatObErrorWithStatus(e));
|
||||
} catch (const std::exception& e) {
|
||||
rollback_after_error(e.what());
|
||||
} catch (...) {
|
||||
rollback_after_error("unknown error");
|
||||
}
|
||||
}
|
||||
|
||||
void OBCameraNode::setStreamProfileCallback(
|
||||
const std::shared_ptr<SetStreamProfile::Request>& request,
|
||||
std::shared_ptr<SetStreamProfile::Response>& response) {
|
||||
try {
|
||||
std::vector<PendingStreamProfile> pending_profiles;
|
||||
std::string message;
|
||||
if (!validateStreamProfileRequest(request, pending_profiles, message)) {
|
||||
response->success = false;
|
||||
response->message = message;
|
||||
return;
|
||||
}
|
||||
if (!applyStreamProfiles(pending_profiles, message)) {
|
||||
response->success = false;
|
||||
response->message = message;
|
||||
return;
|
||||
}
|
||||
response->success = true;
|
||||
response->message = message;
|
||||
} catch (const ob::Error& e) {
|
||||
response->success = false;
|
||||
response->message = orbbec_camera::formatObErrorWithStatus(e);
|
||||
} catch (const std::exception& e) {
|
||||
response->success = false;
|
||||
response->message = e.what();
|
||||
} catch (...) {
|
||||
response->success = false;
|
||||
response->message = "unknown error";
|
||||
}
|
||||
}
|
||||
|
||||
void OBCameraNode::getStreamsEnableCallback(
|
||||
const std::shared_ptr<orbbec_camera_msgs::srv::GetBool::Request> request,
|
||||
std::shared_ptr<orbbec_camera_msgs::srv::GetBool::Response> response) {
|
||||
@@ -1089,10 +1304,10 @@ void OBCameraNode::setLaserEnableCallback(
|
||||
int laser_enable = request->data ? 1 : 0;
|
||||
try {
|
||||
bool property_modified = false;
|
||||
if (device_->isPropertySupported(OB_PROP_LASER_CONTROL_INT, OB_PERMISSION_READ_WRITE)) {
|
||||
if (isPropertyWritable(device_, OB_PROP_LASER_CONTROL_INT)) {
|
||||
device_->setIntProperty(OB_PROP_LASER_CONTROL_INT, laser_enable);
|
||||
property_modified = true;
|
||||
} else if (device_->isPropertySupported(OB_PROP_LASER_BOOL, OB_PERMISSION_READ_WRITE)) {
|
||||
} else if (isPropertyWritable(device_, OB_PROP_LASER_BOOL)) {
|
||||
device_->setIntProperty(OB_PROP_LASER_BOOL, laser_enable);
|
||||
property_modified = true;
|
||||
}
|
||||
@@ -1121,12 +1336,19 @@ void OBCameraNode::setLdpEnableCallback(
|
||||
bool ldp_enable = request->data;
|
||||
try {
|
||||
bool property_modified = false;
|
||||
if (device_->isPropertySupported(OB_PROP_LASER_CONTROL_INT, OB_PERMISSION_READ_WRITE)) {
|
||||
if (!isPropertyWritable(device_, OB_PROP_LDP_BOOL)) {
|
||||
response->success = false;
|
||||
response->message = "LDP property is not supported";
|
||||
return;
|
||||
}
|
||||
if (isPropertyReadable(device_, OB_PROP_LASER_CONTROL_INT) &&
|
||||
isPropertyWritable(device_, OB_PROP_LASER_CONTROL_INT)) {
|
||||
auto laser_enable = device_->getIntProperty(OB_PROP_LASER_CONTROL_INT);
|
||||
device_->setBoolProperty(OB_PROP_LDP_BOOL, ldp_enable);
|
||||
device_->setIntProperty(OB_PROP_LASER_CONTROL_INT, laser_enable);
|
||||
property_modified = true;
|
||||
} else if (device_->isPropertySupported(OB_PROP_LASER_BOOL, OB_PERMISSION_READ_WRITE)) {
|
||||
} else if (isPropertyReadable(device_, OB_PROP_LASER_BOOL) &&
|
||||
isPropertyWritable(device_, OB_PROP_LASER_BOOL)) {
|
||||
if (!ldp_enable) {
|
||||
auto laser_enable = device_->getIntProperty(OB_PROP_LASER_BOOL);
|
||||
device_->setBoolProperty(OB_PROP_LDP_BOOL, ldp_enable);
|
||||
@@ -1139,6 +1361,10 @@ void OBCameraNode::setLdpEnableCallback(
|
||||
}
|
||||
if (property_modified) {
|
||||
enable_ldp_ = ldp_enable;
|
||||
} else {
|
||||
response->success = false;
|
||||
response->message = "Laser property is not supported";
|
||||
return;
|
||||
}
|
||||
response->success = true;
|
||||
} catch (const ob::Error& e) {
|
||||
@@ -1598,10 +1824,14 @@ void OBCameraNode::getLaserStatusCallback(const std::shared_ptr<GetBool::Request
|
||||
std::shared_ptr<GetBool::Response>& response) {
|
||||
(void)request;
|
||||
try {
|
||||
if (device_->isPropertySupported(OB_PROP_LASER_CONTROL_INT, OB_PERMISSION_READ_WRITE)) {
|
||||
if (isPropertyReadable(device_, OB_PROP_LASER_CONTROL_INT)) {
|
||||
response->data = device_->getBoolProperty(OB_PROP_LASER_CONTROL_INT);
|
||||
} else if (device_->isPropertySupported(OB_PROP_LASER_BOOL, OB_PERMISSION_READ_WRITE)) {
|
||||
} else if (isPropertyReadable(device_, OB_PROP_LASER_BOOL)) {
|
||||
response->data = device_->getBoolProperty(OB_PROP_LASER_BOOL);
|
||||
} else {
|
||||
response->success = false;
|
||||
response->message = "Laser property is not supported";
|
||||
return;
|
||||
}
|
||||
response->success = true;
|
||||
} catch (const ob::Error& e) {
|
||||
@@ -1623,8 +1853,8 @@ void OBCameraNode::setPtpConfigCallback(
|
||||
(void)request_header;
|
||||
|
||||
try {
|
||||
if (!device_->isPropertySupported(OB_DEVICE_PTP_CLOCK_SYNC_ENABLE_BOOL,
|
||||
OB_PERMISSION_READ_WRITE)) {
|
||||
if (!isPropertyReadable(device_, OB_DEVICE_PTP_CLOCK_SYNC_ENABLE_BOOL) ||
|
||||
!isPropertyWritable(device_, OB_DEVICE_PTP_CLOCK_SYNC_ENABLE_BOOL)) {
|
||||
response->success = false;
|
||||
RCLCPP_ERROR(logger_, "PTP clock sync property is not supported or not writable");
|
||||
return;
|
||||
|
||||
@@ -93,6 +93,43 @@ std::string ipSourceTypeToString(int ip_source_type) {
|
||||
}
|
||||
}
|
||||
|
||||
std::string deviceAccessStateToString(OBDeviceAccessState state) {
|
||||
switch (state) {
|
||||
case OB_DEVICE_ACCESS_STATE_UNKNOWN:
|
||||
return "UNKNOWN";
|
||||
case OB_DEVICE_ACCESS_STATE_UNSUPPORTED:
|
||||
return "UNSUPPORTED";
|
||||
case OB_DEVICE_ACCESS_STATE_AVAILABLE:
|
||||
return "AVAILABLE";
|
||||
case OB_DEVICE_ACCESS_STATE_CONTROLLED:
|
||||
return "CONTROLLED";
|
||||
case OB_DEVICE_ACCESS_STATE_EXCLUSIVE:
|
||||
return "EXCLUSIVE";
|
||||
case OB_DEVICE_ACCESS_STATE_UNREACHABLE:
|
||||
return "UNREACHABLE";
|
||||
case OB_DEVICE_ACCESS_STATE_FW_NOT_SUPPORTED:
|
||||
return "FW_NOT_SUPPORTED";
|
||||
default:
|
||||
return "UNKNOWN(" + std::to_string(static_cast<int>(state)) + ")";
|
||||
}
|
||||
}
|
||||
|
||||
void printDeviceAccessState(const std::shared_ptr<ob::DeviceList> &list, uint32_t index) {
|
||||
auto logger = rclcpp::get_logger("list_device_node");
|
||||
try {
|
||||
const auto state = list->queryDeviceAccessState(index);
|
||||
RCLCPP_INFO_STREAM(
|
||||
logger, "device access state [serial: " << list->getSerialNumber(index)
|
||||
<< ", ip: " << list->getIpAddress(index)
|
||||
<< "]: " << deviceAccessStateToString(state));
|
||||
} catch (const ob::Error &e) {
|
||||
RCLCPP_WARN_STREAM(logger, "device access state: UNKNOWN ("
|
||||
<< orbbec_camera::formatObErrorWithStatus(e) << ")");
|
||||
} catch (const std::exception &e) {
|
||||
RCLCPP_WARN_STREAM(logger, "device access state: UNKNOWN (" << e.what() << ")");
|
||||
}
|
||||
}
|
||||
|
||||
std::string boolToString(bool value) { return value ? "true" : "false"; }
|
||||
|
||||
bool isPropertyReadable(const std::shared_ptr<ob::Device> &device, OBPropertyID property_id) {
|
||||
@@ -224,6 +261,9 @@ int main(int argc, char **argv) {
|
||||
bool firmware_log_enabled = false;
|
||||
for (size_t i = 0; i < list->deviceCount(); i++) {
|
||||
try {
|
||||
if (std::string(list->getConnectionType(i)) == "Ethernet") {
|
||||
printDeviceAccessState(list, static_cast<uint32_t>(i));
|
||||
}
|
||||
auto device_ = list->getDevice(i);
|
||||
if (isSdkLogEnabled(args.sdk_log_level)) {
|
||||
firmware_log_enabled = enableFirmwareLog(device_) || firmware_log_enabled;
|
||||
|
||||
@@ -25,6 +25,7 @@ rosidl_generate_interfaces(
|
||||
"msg/Metadata.msg"
|
||||
"msg/IMUInfo.msg"
|
||||
"msg/RGBD.msg"
|
||||
"msg/StreamProfile.msg"
|
||||
"srv/GetBool.srv"
|
||||
"srv/GetDeviceConfig.srv"
|
||||
"srv/GetDeviceInfo.srv"
|
||||
@@ -38,6 +39,7 @@ rosidl_generate_interfaces(
|
||||
"srv/GetUserCalibParams.srv"
|
||||
"srv/SetUserCalibParams.srv"
|
||||
"srv/SetBagRecording.srv"
|
||||
"srv/SetStreamProfile.srv"
|
||||
DEPENDENCIES
|
||||
sensor_msgs
|
||||
std_msgs
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
string stream_name
|
||||
int32 width
|
||||
int32 height
|
||||
int32 fps
|
||||
string format
|
||||
@@ -2,7 +2,7 @@
|
||||
<?xml-model href="http://download.ros.org/schema/package_format3.xsd" schematypens="http://www.w3.org/2001/XMLSchema"?>
|
||||
<package format="3">
|
||||
<name>orbbec_camera_msgs</name>
|
||||
<version>2.9.1</version>
|
||||
<version>2.9.3</version>
|
||||
<description>A package containing orbbec camera messages definitions.</description>
|
||||
<maintainer email="yalian@orbbec.com">yalian</maintainer>
|
||||
<license>Apache-2.0</license>
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
StreamProfile[] profiles
|
||||
---
|
||||
bool success
|
||||
string message
|
||||
@@ -2,7 +2,7 @@
|
||||
<?xml-model href="http://download.ros.org/schema/package_format3.xsd" schematypens="http://www.w3.org/2001/XMLSchema"?>
|
||||
<package format="3">
|
||||
<name>orbbec_description</name>
|
||||
<version>2.9.1</version>
|
||||
<version>2.9.3</version>
|
||||
<description>TODO: Package description</description>
|
||||
<maintainer email="yalian@orbbec.com">yalian</maintainer>
|
||||
<license>Apache-2.0</license>
|
||||
|
||||
Reference in New Issue
Block a user