Update orbbec_camera package to be compatible with cuvslam
@@ -217,7 +217,7 @@ add_orbbec_executable(list_camera_profile_mode_node tools/list_camera_profile.cp
|
||||
add_orbbec_executable(topic_statistics_node tools/topic_statistics.cpp)
|
||||
add_orbbec_executable(metadata_save_files_node tools/metadata_save_files.cpp)
|
||||
add_orbbec_executable(metadata_export_files_node tools/metadata_export_files.cpp)
|
||||
add_orbbec_executable(ob_benchmark_node tools/ob_benchmark.cpp)
|
||||
add_orbbec_executable(multi_save_cloud_node tools/multi_save_cloud_node.cpp)
|
||||
|
||||
add_library(frame_latency SHARED tools/frame_latency.cpp)
|
||||
target_include_directories(frame_latency PUBLIC ${COMMON_INCLUDE_DIRS})
|
||||
@@ -229,16 +229,6 @@ rclcpp_components_register_node(frame_latency
|
||||
EXECUTABLE frame_latency_node
|
||||
)
|
||||
|
||||
add_library(start_benchmark SHARED tools/start_benchmark.cpp)
|
||||
target_include_directories(start_benchmark PUBLIC ${COMMON_INCLUDE_DIRS})
|
||||
target_link_libraries(start_benchmark ${COMMON_LIBRARIES})
|
||||
ament_target_dependencies(start_benchmark ${dependencies})
|
||||
|
||||
rclcpp_components_register_node(start_benchmark
|
||||
PLUGIN "orbbec_camera::tools::StartBenchmark"
|
||||
EXECUTABLE start_benchmark_node
|
||||
)
|
||||
|
||||
add_library(multi_save_rgbir SHARED tools/multi_save_rgbir.cpp)
|
||||
target_include_directories(multi_save_rgbir PUBLIC ${COMMON_INCLUDE_DIRS} )
|
||||
target_link_libraries(multi_save_rgbir ${COMMON_LIBRARIES})
|
||||
@@ -248,10 +238,8 @@ rclcpp_components_register_node(multi_save_rgbir
|
||||
PLUGIN "orbbec_camera::tools::MultiCameraSubscriber"
|
||||
EXECUTABLE multi_save_rgbir_node
|
||||
)
|
||||
|
||||
# Install rules
|
||||
install(TARGETS ${PROJECT_NAME} frame_latency
|
||||
start_benchmark
|
||||
multi_save_rgbir
|
||||
ARCHIVE DESTINATION lib
|
||||
LIBRARY DESTINATION lib
|
||||
@@ -261,7 +249,6 @@ install(TARGETS ${PROJECT_NAME} frame_latency
|
||||
install(DIRECTORY include/ DESTINATION include)
|
||||
install(DIRECTORY launch DESTINATION share/${PROJECT_NAME}/)
|
||||
install(DIRECTORY config DESTINATION share/${PROJECT_NAME}/)
|
||||
install(DIRECTORY examples DESTINATION share/${PROJECT_NAME}/)
|
||||
install(DIRECTORY ${ORBBEC_INCLUDE_DIR} DESTINATION include)
|
||||
install(DIRECTORY ${ORBBEC_LIBS_DIR}/ DESTINATION lib/ FILES_MATCHING PATTERN "*.so*")
|
||||
install(DIRECTORY ${ORBBEC_LIBS_DIR}/extensions DESTINATION lib/)
|
||||
@@ -278,7 +265,7 @@ install(TARGETS list_devices_node
|
||||
topic_statistics_node
|
||||
metadata_save_files_node
|
||||
metadata_export_files_node
|
||||
ob_benchmark_node
|
||||
multi_save_cloud_node
|
||||
DESTINATION lib/${PROJECT_NAME}/)
|
||||
|
||||
if (BUILD_TESTING)
|
||||
@@ -290,4 +277,4 @@ ament_export_include_directories(include ${ORBBEC_INCLUDE_DIR})
|
||||
ament_export_libraries(${PROJECT_NAME})
|
||||
ament_export_dependencies(${dependencies} ${ORBBEC_LIBS})
|
||||
|
||||
ament_package()
|
||||
ament_package()
|
||||
@@ -20,4 +20,4 @@
|
||||
#include <libobsensor/h/StreamProfile.h>
|
||||
#include <libobsensor/h/Version.h>
|
||||
#include <libobsensor/h/TypeHelper.h>
|
||||
#include <libobsensor/h/RecordPlayback.h>
|
||||
|
||||
|
||||
@@ -14,8 +14,9 @@
|
||||
#include <libobsensor/hpp/Filter.hpp>
|
||||
#include <libobsensor/hpp/Frame.hpp>
|
||||
#include <libobsensor/hpp/Pipeline.hpp>
|
||||
#include <libobsensor/hpp/RecordPlayback.hpp>
|
||||
// #include <libobsensor/hpp/RecordPlayback.hpp>
|
||||
#include <libobsensor/hpp/Sensor.hpp>
|
||||
#include <libobsensor/hpp/StreamProfile.hpp>
|
||||
#include <libobsensor/hpp/Version.hpp>
|
||||
#include <libobsensor/hpp/TypeHelper.hpp>
|
||||
|
||||
|
||||
@@ -155,7 +155,7 @@ OB_EXPORT void ob_set_logger_to_console(ob_log_severity severity, ob_error **err
|
||||
|
||||
/**
|
||||
* @brief Set the extensions directory
|
||||
* @brief The extensions directory is used to search for dynamic libraries that provide additional functionality to the SDK, such as the Frame filters.
|
||||
* @brief The extensions directory is used to search for dynamic libraries that provide additional functionality to the SDK, such as the Frame filters.
|
||||
*
|
||||
* @attention Should be called before creating the context and pipeline, otherwise the default extensions directory (./extensions) will be used.
|
||||
*
|
||||
|
||||
@@ -388,7 +388,7 @@ OB_EXPORT const char *ob_device_info_get_firmware_version(const ob_device_info *
|
||||
*
|
||||
* @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 connection type, currently supports: "USB", "USB1.0", "USB1.1", "USB2.0", "USB2.1", "USB3.0", "USB3.1", "USB3.2", "Ethernet"
|
||||
* @return const char* The connection type,currently supports:"USB", "USB1.0", "USB1.1", "USB2.0", "USB2.1", "USB3.0", "USB3.1", "USB3.2", "Ethernet"
|
||||
*/
|
||||
OB_EXPORT const char *ob_device_info_get_connection_type(const ob_device_info *info, ob_error **error);
|
||||
|
||||
@@ -399,7 +399,7 @@ OB_EXPORT const char *ob_device_info_get_connection_type(const ob_device_info *i
|
||||
*
|
||||
* @param info Device Information
|
||||
* @param 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"
|
||||
* @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);
|
||||
|
||||
@@ -533,7 +533,7 @@ OB_EXPORT const char *ob_device_list_get_device_serial_number(const ob_device_li
|
||||
* @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* returns the device connection type, currently supports: "USB", "USB1.0", "USB1.1", "USB2.0", "USB2.1", "USB3.0", "USB3.1", "USB3.2",
|
||||
* @return const char* returns the device connection type,currently supports:"USB", "USB1.0", "USB1.1", "USB2.0", "USB2.1", "USB3.0", "USB3.1", "USB3.2",
|
||||
* "Ethernet"
|
||||
*/
|
||||
OB_EXPORT const char *ob_device_list_get_device_connection_type(const ob_device_list *list, uint32_t index, ob_error **error);
|
||||
@@ -546,22 +546,10 @@ OB_EXPORT const char *ob_device_list_get_device_connection_type(const ob_device_
|
||||
* @param list Device list object
|
||||
* @param index Device index
|
||||
* @param error Pointer to an error object that will be set if an error occurs.
|
||||
* @return const char* returns the device ip address, such as "192.168.1.10"
|
||||
* @return const char* returns the device ip address,such as "192.168.1.10"
|
||||
*/
|
||||
OB_EXPORT const char *ob_device_list_get_device_ip_address(const ob_device_list *list, uint32_t index, ob_error **error);
|
||||
|
||||
/**
|
||||
* @brief Get device local mac address
|
||||
*
|
||||
* @attention Only valid for network devices, otherwise it will return "0:0:0:0:0:0".
|
||||
*
|
||||
* @param list Device list object
|
||||
* @param index Device index
|
||||
* @param error Pointer to an error object that will be set if an error occurs.
|
||||
* @return const char* returns the device mac address
|
||||
*/
|
||||
OB_EXPORT const char *ob_device_list_get_device_local_mac(const ob_device_list *list, uint32_t index, ob_error **error);
|
||||
|
||||
/**
|
||||
* @brief Create a device.
|
||||
*
|
||||
@@ -592,7 +580,7 @@ OB_EXPORT ob_device *ob_device_list_get_device_by_serial_number(const ob_device_
|
||||
* @brief On Linux platform, for usb device, the uid of the device is composed of bus-port-dev, for example 1-1.2-1. But the SDK will remove the dev number and
|
||||
* only keep the bus-port as the uid to create the device, for example 1-1.2, so that we can create a device connected to the specified USB port. Similarly,
|
||||
* users can also directly pass in bus-port as uid to create device.
|
||||
* @brief For GMSL device, the uid is GMSL port with "gmsl2-" prefix, for example gmsl2-1.
|
||||
* @brief For GMSL device,the uid is GMSL port with “gmsl2-” prefix, for example gmsl2-1.
|
||||
*
|
||||
* @attention If the device has already been acquired and created elsewhere, repeated acquisitions will return an error.
|
||||
*
|
||||
|
||||
@@ -68,7 +68,7 @@ OB_EXPORT ob_exception_type ob_error_get_exception_type(const ob_error *error);
|
||||
/**
|
||||
* @brief Delete the error object.
|
||||
*
|
||||
* @param[in] error The error object to delete, you should set the pointer to NULL after calling this function.
|
||||
* @param[in] error The error object to delete.
|
||||
*/
|
||||
OB_EXPORT void ob_delete_error(ob_error *error);
|
||||
|
||||
|
||||
@@ -148,7 +148,7 @@ OB_EXPORT void ob_delete_frame(const ob_frame *frame, ob_error **error);
|
||||
|
||||
/**
|
||||
* @brief Copy the information of the source frame object to the destination frame object.
|
||||
* @brief Including the index, timestamp, system timestamp, global timestamp and metadata will be copied.
|
||||
* @brief Including the index,timestamp,system timestamp,global timestamp and metadata will be copied.
|
||||
*
|
||||
* @param[in] src_frame Source frame object to copy the information from.
|
||||
* @param[in] dst_frame Destination frame object to copy the information to.
|
||||
@@ -224,7 +224,7 @@ OB_EXPORT void ob_frame_set_system_timestamp_us(ob_frame *frame, uint64_t system
|
||||
|
||||
/**
|
||||
* @brief Get the global timestamp of the frame in microseconds.
|
||||
* @brief The global timestamp is the time point when the frame was captured by the device, and has been converted to the host clock domain. The
|
||||
* @brief The global timestamp is the time point when the frame was was captured by the device, and has been converted to the host clock domain. The
|
||||
* conversion process base on the frame timestamp and can eliminate the timer drift of the device
|
||||
*
|
||||
* @attention The global timestamp is disabled by default. If global timestamp is not enabled, the function will return 0. To enable it, call @ref
|
||||
@@ -603,24 +603,6 @@ OB_EXPORT ob_frame *ob_frameset_get_frame_by_index(const ob_frame *frameset, uin
|
||||
*/
|
||||
OB_EXPORT void ob_frameset_push_frame(ob_frame *frameset, const ob_frame *frame, ob_error **error);
|
||||
|
||||
/**
|
||||
* @brief Get point cloud frame width
|
||||
*
|
||||
* @param[in] frame point cloud Frame object
|
||||
* @param[out] error Pointer to an error object that will be set if an error occurs.
|
||||
* @return uint32_t return the point cloud frame width
|
||||
*/
|
||||
OB_EXPORT uint32_t ob_point_cloud_frame_get_width(const ob_frame *frame, ob_error **error);
|
||||
|
||||
/**
|
||||
* @brief Get point cloud frame height
|
||||
*
|
||||
* @param[in] frame point cloud Frame object
|
||||
* @param[out] error Pointer to an error object that will be set if an error occurs.
|
||||
* @return uint32_t return the point cloud frame height
|
||||
*/
|
||||
OB_EXPORT uint32_t ob_point_cloud_frame_get_height(const ob_frame *frame, ob_error **error);
|
||||
|
||||
// The following interfaces are deprecated and are retained here for compatibility purposes.
|
||||
#define ob_frame_index ob_frame_get_index
|
||||
#define ob_frame_format ob_frame_get_format
|
||||
|
||||
@@ -62,7 +62,7 @@ OB_EXPORT ob_multi_device_sync_config ob_device_get_multi_device_sync_config(con
|
||||
*
|
||||
* @attention The frequency of the user call this function multiplied by the number of frames per trigger should be less than the frame rate of the stream. The
|
||||
* number of frames per trigger can be set by @ref framesPerTrigger.
|
||||
* @attention For some models, receive and execute the capture command will have a certain delay and performance consumption, so the frequency of calling this
|
||||
* @attention For some models,receive and execute the capture command will have a certain delay and performance consumption, so the frequency of calling this
|
||||
* function should not be too high, please refer to the product manual for the specific supported frequency.
|
||||
* @attention If the device is not in the @ref OB_MULTI_DEVICE_SYNC_MODE_HARDWARE_TRIGGERING mode, device will ignore the capture command.
|
||||
*
|
||||
|
||||
@@ -23,8 +23,6 @@ typedef struct ob_context_t ob_context;
|
||||
typedef struct ob_device_t ob_device;
|
||||
typedef struct ob_device_info_t ob_device_info;
|
||||
typedef struct ob_device_list_t ob_device_list;
|
||||
typedef struct ob_record_device_t ob_record_device;
|
||||
typedef struct ob_playback_device_t ob_playback_device;
|
||||
typedef struct ob_camera_param_list_t ob_camera_param_list;
|
||||
typedef struct ob_sensor_t ob_sensor;
|
||||
typedef struct ob_sensor_list_t ob_sensor_list;
|
||||
@@ -497,15 +495,6 @@ typedef enum {
|
||||
} OBAlignMode,
|
||||
ob_align_mode;
|
||||
|
||||
/**
|
||||
* @brief Camera performance mode
|
||||
*/
|
||||
typedef enum {
|
||||
ADAPTIVE_PERFORMANCE_MODE, /**< Camera adaptive mode */
|
||||
HIGH_PERFORMANCE_MODE, /**< High Performance Mode */
|
||||
} OBCameraPerformanceMode,
|
||||
ob_camera_performance_mode;
|
||||
|
||||
/**
|
||||
* @brief Rectangle
|
||||
*/
|
||||
@@ -725,14 +714,14 @@ typedef struct {
|
||||
double zpps; // zpps=z0/fx
|
||||
float baseline; // baseline length, for monocular camera,it means the distance of laser to the center of IR-CMOS
|
||||
double fx; // focus
|
||||
uint8_t bitSize; // disparity bit size (raw disp bit size, for example: MX6000 is 12, MX6600 is 14)
|
||||
float unit; // reference units: unit=10 denote 1cm; unit=1 denote 1mm; unit=0.5 denote 0.5mm; and so on
|
||||
uint8_t bitSize; // disparity bit size(raw disp bit size,for example: MX6000 is 12, MX6600 is 14)
|
||||
float unit; // reference units:unit=10 denote 1cm; unit=1 denote 1mm; unit=0.5 denote 0.5mm; and so on
|
||||
float minDisparity; // dual disparity coefficient
|
||||
uint8_t packMode; // data pack mode
|
||||
float dispOffset; // disparity offset, actual disp=chip disp + disp_offset
|
||||
int32_t invalidDisp; // invalid disparity, usually is 0, dual IR add a auxiliary value.
|
||||
int32_t dispIntPlace; // disp integer digits, default is 8, Gemini2 XL is 10
|
||||
uint8_t isDualCamera; // 0 monocular camera, 1 dual camera
|
||||
float dispOffset; // disparity offset,actual disp=chip disp + disp_offset
|
||||
int32_t invalidDisp; // invalid disparity,usually is 0,dual IR add a auxiliary value.
|
||||
int32_t dispIntPlace; // disp integer digits,default is 8,Gemini2 XL is 10
|
||||
uint8_t isDualCamera; // 0 monocular camera,1 dual camera
|
||||
} OBDisparityParam, ob_disparity_param;
|
||||
|
||||
/**
|
||||
@@ -837,7 +826,7 @@ typedef enum {
|
||||
/**
|
||||
* @brief Secondary synchronize mode
|
||||
* @brief Secondary device. Both process input trigger signal and output trigger signal to other devices.
|
||||
* @brief Different sensors in a single devices receive trigger signals respectively: ext trigger -> RGB && ext trigger -> IR/Depth/TOF
|
||||
* @brief Different sensors in a single devices receive trigger signals respectively:ext trigger -> RGB && ext trigger -> IR/Depth/TOF
|
||||
*
|
||||
* @attention With the current Gemini 2 device set to this mode, each Sensor receives the first external trigger signal
|
||||
* after the stream is turned on and starts timing self-triggering at the set frame rate until the stream is turned off
|
||||
@@ -871,7 +860,7 @@ typedef enum {
|
||||
* @brief Software trigger synchronize mode as secondary device
|
||||
* @brief The slave receives the external trigger signal (the external trigger signal comes from the soft trigger host) and outputs the trigger signal to
|
||||
* the external relay.
|
||||
* @brief Different sensors in a single machine receive trigger signals respectively: ext trigger -> RGB && ext trigger -> IR/Depth/TOF
|
||||
* @brief Different sensors in a single machine receive trigger signals respectively:ext trigger -> RGB && ext trigger -> IR/Depth/TOF
|
||||
*/
|
||||
OB_SYNC_MODE_SECONDARY_SOFT_TRIGGER = 0x07,
|
||||
|
||||
@@ -1306,14 +1295,14 @@ typedef struct {
|
||||
/**
|
||||
* @brief The delay time of the depth image capture after receiving the capture command or trigger signal in microseconds.
|
||||
*
|
||||
* @attention This parameter is only valid for some models, please refer to the product manual for details.
|
||||
* @attention This parameter is only valid for some models, please refer to the product manual for details.
|
||||
*/
|
||||
int depthDelayUs;
|
||||
|
||||
/**
|
||||
* @brief The delay time of the color image capture after receiving the capture command or trigger signal in microseconds.
|
||||
*
|
||||
* @attention This parameter is only valid for some models, please refer to the product manual for details.
|
||||
* @attention This parameter is only valid for some models, please refer to the product manual for details.
|
||||
*/
|
||||
int colorDelayUs;
|
||||
|
||||
@@ -1559,14 +1548,14 @@ typedef enum {
|
||||
|
||||
/**
|
||||
* @brief Power line frequency
|
||||
* @brief For anti-flickering, 0: Close, 1: 50Hz, 2: 60Hz, 3: Auto
|
||||
* @brief For anti-flickering, 0:Close, 1: 50Hz, 2: 60Hz, 3: Auto
|
||||
*/
|
||||
OB_FRAME_METADATA_TYPE_POWER_LINE_FREQUENCY = 15,
|
||||
|
||||
/**
|
||||
* @brief Low light compensation
|
||||
*
|
||||
* @attention The low light compensation is a feature inside the device, and can not manually control it.
|
||||
* @attention The low light compensation is a feature inside the device,and can not manually control it.
|
||||
*/
|
||||
OB_FRAME_METADATA_TYPE_LOW_LIGHT_COMPENSATION = 16,
|
||||
|
||||
@@ -1689,26 +1678,9 @@ typedef enum {
|
||||
*
|
||||
*/
|
||||
OB_UVC_BACKEND_TYPE_V4L2,
|
||||
|
||||
/**
|
||||
* @brief Use MSMF backend to access the UVC device
|
||||
*/
|
||||
OB_UVC_BACKEND_TYPE_MSMF,
|
||||
} ob_uvc_backend_type,
|
||||
OBUvcBackendType;
|
||||
|
||||
|
||||
/**
|
||||
* @brief The playback status of the media
|
||||
*/
|
||||
typedef enum {
|
||||
OB_PLAYBACK_UNKNOWN ,
|
||||
OB_PLAYBACK_PLAYING, /**< The media is playing */
|
||||
OB_PLAYBACK_PAUSED, /**< The media is paused */
|
||||
OB_PLAYBACK_STOPPED, /**< The media is stopped */
|
||||
OB_PLAYBACK_COUNT,
|
||||
} ob_playback_status, OBPlaybackStatus;
|
||||
|
||||
// For compatibility
|
||||
#define OB_FRAME_METADATA_TYPE_LASER_POWER_MODE OB_FRAME_METADATA_TYPE_LASER_POWER_LEVEL
|
||||
#define OB_FRAME_METADATA_TYPE_EMITTER_MODE OB_FRAME_METADATA_TYPE_LASER_STATUS
|
||||
@@ -1815,7 +1787,6 @@ typedef void(ob_frame_destroy_callback)(uint8_t *buffer, void *user_data);
|
||||
*/
|
||||
typedef void(ob_log_callback)(ob_log_severity severity, const char *message, void *user_data);
|
||||
|
||||
typedef void(*ob_playback_status_changed_callback)(ob_playback_status status, void *user_data);
|
||||
/**
|
||||
* @brief Check if the sensor_type is a video sensor
|
||||
*
|
||||
|
||||
@@ -306,7 +306,7 @@ typedef enum {
|
||||
OB_PROP_DEPTH_ROTATE_INT = 118,
|
||||
|
||||
/**
|
||||
* @brief Get hardware laser power actual level which real state of laser element. OB_PROP_LASER_POWER_LEVEL_CONTROL_INT99 will effect this command
|
||||
* @brief Get hardware laser power actual level which real state of laser element. OB_PROP_LASER_POWER_LEVEL_CONTROL_INT99)will effect this command
|
||||
* which it setting and changed the hardware laser energy level.
|
||||
*/
|
||||
OB_PROP_LASER_POWER_ACTUAL_LEVEL_INT = 119,
|
||||
@@ -501,14 +501,6 @@ typedef enum {
|
||||
* @brief hardware noise remove filter threshold ,range [0.0 - 1.0]
|
||||
*/
|
||||
OB_PROP_HW_NOISE_REMOVE_FILTER_THRESHOLD_FLOAT = 212,
|
||||
/**
|
||||
* @brief soft trigger auto capture enable, use in OB_MULTI_DEVICE_SYNC_MODE_SOFTWARE_TRIGGERING mode
|
||||
*/
|
||||
OB_DEVICE_AUTO_CAPTURE_ENABLE_BOOL = 216,
|
||||
/**
|
||||
* @brief soft trigger auto capture interval time, use in OB_MULTI_DEVICE_SYNC_MODE_SOFTWARE_TRIGGERING mode
|
||||
*/
|
||||
OB_DEVICE_AUTO_CAPTURE_INTERVAL_TIME_INT = 217,
|
||||
/**
|
||||
* @brief Baseline calibration parameters
|
||||
*/
|
||||
@@ -561,7 +553,7 @@ typedef enum {
|
||||
|
||||
/**
|
||||
* @brief Device network static ip config record
|
||||
* @brief Using for get last static ip config, witch is record in device flash when user set static ip config
|
||||
* @brief Using for get last static ip config,witch is record in device flash when user set static ip config
|
||||
*
|
||||
* @attention read only
|
||||
*/
|
||||
@@ -808,11 +800,6 @@ typedef enum {
|
||||
*/
|
||||
OB_PROP_NETWORK_BANDWIDTH_TYPE_INT = 3027,
|
||||
|
||||
/**
|
||||
* @brief Switch device performance mode, currently available in Adaptive Mode and High Performance Mode, such as G335LE.
|
||||
*/
|
||||
OB_PROP_DEVICE_PERFORMANCE_MODE_INT = 3028,
|
||||
|
||||
/**
|
||||
* @brief Calibration JSON file read from device (Femto Mega, read only)
|
||||
*/
|
||||
|
||||
@@ -1,135 +0,0 @@
|
||||
// Copyright (c) Orbbec Inc. All Rights Reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
/**
|
||||
* @file RecordPlayback.hpp
|
||||
* @brief Record and playback device-related types, including interfaces to create recording and playback devices,
|
||||
record and playback streaming data, etc.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "Device.h"
|
||||
|
||||
/**
|
||||
* @brief Create a recording device for the specified device with a specified file path and compression enabled.
|
||||
*
|
||||
* @param[in] device The device to record.
|
||||
* @param[in] file_path The file path to record to.
|
||||
* @param[in] compression_enabled Whether to enable compression for the recording.
|
||||
* @param[out] error Pointer to an error object that will be set if an error occurs.
|
||||
* @return A pointer to the newly created recording device, or NULL if an error occurred.
|
||||
*/
|
||||
OB_EXPORT ob_record_device *ob_create_record_device(ob_device *device, const char *file_path, bool compression_enabled, ob_error **error);
|
||||
|
||||
/**
|
||||
* @brief Delete a recording device.
|
||||
*
|
||||
* @param[in] recorder The recording device to delete.
|
||||
* @param[out] error Pointer to an error object that will be set if an error occurs.
|
||||
*/
|
||||
OB_EXPORT void ob_delete_record_device(ob_record_device *recorder, ob_error **error);
|
||||
|
||||
/**
|
||||
* @brief Pause recording on the specified recording device.
|
||||
*
|
||||
* @param[in] recorder The recording device to pause.
|
||||
* @param[out] error Pointer to an error object that will be set if an error occurs.
|
||||
*/
|
||||
OB_EXPORT void ob_record_device_pause(ob_record_device *recorder, ob_error **error);
|
||||
|
||||
/**
|
||||
* @brief Resume recording on the specified recording device.
|
||||
*
|
||||
* @param[in] recorder The recording device to resume.
|
||||
* @param[out] error Pointer to an error object that will be set if an error occurs.
|
||||
*/
|
||||
OB_EXPORT void ob_record_device_resume(ob_record_device *recorder, ob_error **error);
|
||||
|
||||
/**
|
||||
* @brief Create a playback device for the specified file path.
|
||||
*
|
||||
* @param[in] file_path The file path to playback from.
|
||||
* @param[out] error Pointer to an error object that will be set if an error occurs.
|
||||
* @return A pointer to the newly created playback device, or NULL if an error occurred.
|
||||
*/
|
||||
OB_EXPORT ob_device *ob_create_playback_device(const char *file_path, ob_error **error);
|
||||
|
||||
/**
|
||||
* @brief Pause playback on the specified playback device.
|
||||
*
|
||||
* @param[in] player The playback device to pause.
|
||||
* @param[out] error Pointer to an error object that will be set if an error occurs.
|
||||
*/
|
||||
OB_EXPORT void ob_playback_device_pause(ob_device *player, ob_error **error);
|
||||
|
||||
/**
|
||||
* @brief Resume playback on the specified playback device.
|
||||
*
|
||||
* @param[in] player The playback device to resume.
|
||||
* @param[out] error Pointer to an error object that will be set if an error occurs.
|
||||
*/
|
||||
OB_EXPORT void ob_playback_device_resume(ob_device *player, ob_error **error);
|
||||
|
||||
/**
|
||||
* @brief Set the playback to a specified time point of the played data.
|
||||
*
|
||||
* @param[in] player The playback device to set the position for.
|
||||
* @param[in] timestamp The position to set the playback to, in milliseconds.
|
||||
* @param[out] error Pointer to an error object that will be set if an error occurs.
|
||||
*/
|
||||
OB_EXPORT void ob_playback_device_seek(ob_device *player, const uint64_t timestamp, ob_error **error);
|
||||
|
||||
/**
|
||||
* @brief Set the playback to a specified time point of the played data.
|
||||
*
|
||||
* @param[in] player The playback device to set the position for.
|
||||
* @param[in] rate The playback rate to set.
|
||||
* @param[out] error Pointer to an error object that will be set if an error occurs.
|
||||
*/
|
||||
OB_EXPORT void ob_playback_device_set_playback_rate(ob_device *player, const float rate, ob_error **error);
|
||||
|
||||
/**
|
||||
* @brief Get the current playback status of the played data.
|
||||
*
|
||||
* @param[in] player The playback device to get the status for.
|
||||
* @param[out] error Pointer to an error object that will be set if an error occurs.
|
||||
* @return The current playback status of the played data.
|
||||
*/
|
||||
OB_EXPORT ob_playback_status ob_playback_device_get_current_playback_status(ob_device *player, ob_error **error);
|
||||
|
||||
/**
|
||||
* @brief Set a callback function to receive playback status updates.
|
||||
*
|
||||
* @param[in] player The playback device to set the callback for.
|
||||
* @param[in] callback The callback function to receive playback status updates.
|
||||
* @param[out] error Pointer to an error object that will be set if an error occurs.
|
||||
*/
|
||||
OB_EXPORT void ob_playback_device_set_playback_status_changed_callback(ob_device *player, ob_playback_status_changed_callback callback, void *user_data,
|
||||
ob_error **error);
|
||||
|
||||
/**
|
||||
* @brief Get the current playback position of the played data.
|
||||
*
|
||||
* @param[in] player The playback device to get the position for.
|
||||
* @param[out] error Pointer to an error object that will be set if an error occurs.
|
||||
* @return The current playback position of the played data, in milliseconds.
|
||||
*/
|
||||
OB_EXPORT uint64_t ob_playback_device_get_position(ob_device *player, ob_error **error);
|
||||
|
||||
/**
|
||||
* @brief Get the duration of the played data.
|
||||
*
|
||||
* @param[in] player The playback device to get the duration for.
|
||||
* @param[out] error Pointer to an error object that will be set if an error occurs.
|
||||
* @return The duration of the played data, in milliseconds.
|
||||
*/
|
||||
OB_EXPORT uint64_t ob_playback_device_get_duration(ob_device *player, ob_error **error);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
@@ -19,7 +19,8 @@ extern "C" {
|
||||
*
|
||||
* @return bool Transform result
|
||||
*/
|
||||
OB_EXPORT bool ob_transformation_3d_to_3d(const OBPoint3f source_point3f, OBExtrinsic extrinsic, OBPoint3f *target_point3f, ob_error **error);
|
||||
OB_EXPORT bool ob_transformation_3d_to_3d(const OBPoint3f source_point3f, OBExtrinsic extrinsic, OBPoint3f *target_point3f, ob_error **error) ;
|
||||
|
||||
|
||||
/**
|
||||
* @brief Transform a 2d pixel coordinate with an associated depth value of the source camera into a 3d point of the target coordinate system.
|
||||
@@ -34,8 +35,9 @@ OB_EXPORT bool ob_transformation_3d_to_3d(const OBPoint3f source_point3f, OBExtr
|
||||
*
|
||||
* @return bool Transform result
|
||||
*/
|
||||
OB_EXPORT bool ob_transformation_2d_to_3d(const OBPoint2f source_point2f, const float source_depth_pixel_value, const OBCameraIntrinsic source_intrinsic,
|
||||
OBExtrinsic extrinsic, OBPoint3f *target_point3f, ob_error **error);
|
||||
OB_EXPORT bool ob_transformation_2d_to_3d(const OBPoint2f source_point2f, const float source_depth_pixel_value, const OBCameraIntrinsic source_intrinsic,
|
||||
OBExtrinsic extrinsic, OBPoint3f *target_point3f, ob_error **error);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Transform a 3d point of a source coordinate system into a 2d pixel coordinate of the target camera.
|
||||
@@ -67,59 +69,46 @@ OB_EXPORT bool ob_transformation_3d_to_2d(const OBPoint3f source_point3f, const
|
||||
*
|
||||
* @return bool Transform result
|
||||
*/
|
||||
OB_EXPORT bool ob_transformation_2d_to_2d(const OBPoint2f source_point2f, const float source_depth_pixel_value, const OBCameraIntrinsic source_intrinsic,
|
||||
const OBCameraDistortion source_distortion, const OBCameraIntrinsic target_intrinsic,
|
||||
const OBCameraDistortion target_distortion, OBExtrinsic extrinsic, OBPoint2f *target_point2f, ob_error **error);
|
||||
OB_EXPORT bool ob_transformation_2d_to_2d(const OBPoint2f source_point2f, const float source_depth_pixel_value, const OBCameraIntrinsic source_intrinsic,
|
||||
const OBCameraDistortion source_distortion, const OBCameraIntrinsic target_intrinsic, const OBCameraDistortion target_distortion,
|
||||
OBExtrinsic extrinsic, OBPoint2f *target_point2f, ob_error **error);
|
||||
|
||||
// \deprecated This function is deprecated and will be removed in a future version.
|
||||
// \deprecated This function is deprecated and will be removed in a future version.
|
||||
OB_EXPORT ob_frame *transformation_depth_frame_to_color_camera(ob_device *device, ob_frame *depth_frame, uint32_t target_color_camera_width,
|
||||
uint32_t target_color_camera_height, ob_error **error);
|
||||
uint32_t target_color_camera_height, ob_error **error);
|
||||
|
||||
// \deprecated This function is deprecated and will be removed in a future version.
|
||||
// \deprecated This function is deprecated and will be removed in a future version.
|
||||
OB_EXPORT bool transformation_init_xy_tables(const ob_calibration_param calibration_param, const ob_sensor_type sensor_type, float *data, uint32_t *data_size,
|
||||
ob_xy_tables *xy_tables, ob_error **error);
|
||||
ob_xy_tables *xy_tables, ob_error **error);
|
||||
|
||||
// \deprecated This function is deprecated and will be removed in a future version.
|
||||
// \deprecated This function is deprecated and will be removed in a future version.
|
||||
OB_EXPORT void transformation_depth_to_pointcloud(ob_xy_tables *xy_tables, const void *depth_image_data, void *pointcloud_data, ob_error **error);
|
||||
|
||||
// \deprecated This function is deprecated and will be removed in a future version.
|
||||
OB_EXPORT void transformation_depth_to_rgbd_pointcloud(ob_xy_tables *xy_tables, const void *depth_image_data, const void *color_image_data,
|
||||
void *pointcloud_data, ob_error **error);
|
||||
// \deprecated This function is deprecated and will be removed in a future version.
|
||||
OB_EXPORT void transformation_depth_to_rgbd_pointcloud(ob_xy_tables *xy_tables, const void *depth_image_data, const void *color_image_data, void *pointcloud_data,
|
||||
ob_error **error);
|
||||
|
||||
// \deprecated This function is deprecated and will be removed in a future version.
|
||||
// \deprecated This function is deprecated and will be removed in a future version.
|
||||
// Use the ob_transformation_3d_to_3d instead.
|
||||
OB_EXPORT bool ob_calibration_3d_to_3d(const ob_calibration_param calibration_param, const ob_point3f source_point3f, const ob_sensor_type source_sensor_type,
|
||||
const ob_sensor_type target_sensor_type, ob_point3f *target_point3f, ob_error **error);
|
||||
const ob_sensor_type target_sensor_type, ob_point3f *target_point3f, ob_error **error);
|
||||
|
||||
// \deprecated This function is deprecated and will be removed in a future version.
|
||||
// \deprecated This function is deprecated and will be removed in a future version.
|
||||
// Use the ob_transformation_2d_to_3d instead.
|
||||
OB_EXPORT bool ob_calibration_2d_to_3d(const ob_calibration_param calibration_param, const ob_point2f source_point2f, const float source_depth_pixel_value,
|
||||
const ob_sensor_type source_sensor_type, const ob_sensor_type target_sensor_type, ob_point3f *target_point3f,
|
||||
ob_error **error);
|
||||
const ob_sensor_type source_sensor_type, const ob_sensor_type target_sensor_type, ob_point3f *target_point3f, ob_error **error);
|
||||
|
||||
// \deprecated This function is deprecated and will be removed in a future version.
|
||||
// \deprecated This function is deprecated and will be removed in a future version.
|
||||
// Use the ob_transformation_3d_to_2d instead.
|
||||
OB_EXPORT bool ob_calibration_3d_to_2d(const ob_calibration_param calibration_param, const ob_point3f source_point3f, const ob_sensor_type source_sensor_type,
|
||||
const ob_sensor_type target_sensor_type, ob_point2f *target_point2f, ob_error **error);
|
||||
const ob_sensor_type target_sensor_type, ob_point2f *target_point2f, ob_error **error);
|
||||
|
||||
// \deprecated This function is deprecated and will be removed in a future version.
|
||||
// \deprecated This function is deprecated and will be removed in a future version.
|
||||
// Use the ob_transformation_2d_to_2d instead.
|
||||
OB_EXPORT bool ob_calibration_2d_to_2d(const ob_calibration_param calibration_param, const ob_point2f source_point2f, const float source_depth_pixel_value,
|
||||
const ob_sensor_type source_sensor_type, const ob_sensor_type target_sensor_type, ob_point2f *target_point2f,
|
||||
ob_error **error);
|
||||
/**
|
||||
* @brief save point cloud to ply file.
|
||||
*
|
||||
* @param[in] file_name Point cloud save path
|
||||
* @param[in] frame Point cloud frame
|
||||
* @param[in] save_binary Binary or textual,true: binary, false: textual
|
||||
* @param[in] use_mesh Save mesh or not, true: save as mesh, false: not save as mesh
|
||||
* @param[in] mesh_threshold Distance threshold for creating faces in point cloud,default value :50
|
||||
* @param[out] error Pointer to an error object that will be set if an error occurs.
|
||||
*
|
||||
* @return bool save point cloud result
|
||||
*/
|
||||
OB_EXPORT bool ob_save_pointcloud_to_ply(const char *file_name, ob_frame *frame, bool save_binary, bool use_mesh, float mesh_threshold, ob_error **error);
|
||||
const ob_sensor_type source_sensor_type, const ob_sensor_type target_sensor_type, ob_point2f *target_point2f, ob_error **error);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -101,7 +101,7 @@ public:
|
||||
* @brief Creates a network device with the specified IP address and port.
|
||||
*
|
||||
* @param[in] address The IP address, ipv4 only. such as "192.168.1.10"
|
||||
* @param[in] port The port number, currently only support 8090
|
||||
* @param[in] port The port number, currently only support 8090
|
||||
* @return std::shared_ptr<Device> The created device object.
|
||||
*/
|
||||
std::shared_ptr<Device> createNetDevice(const char *address, uint16_t port) const {
|
||||
@@ -210,7 +210,7 @@ public:
|
||||
|
||||
/**
|
||||
* @brief Set the extensions directory
|
||||
* @brief The extensions directory is used to search for dynamic libraries that provide additional functionality to the SDK, such as the Frame filters.
|
||||
* @brief The extensions directory is used to search for dynamic libraries that provide additional functionality to the SDK, such as the Frame filters.
|
||||
*
|
||||
* @attention Should be called before creating the context and pipeline, otherwise the default extensions directory (./extensions) will be used.
|
||||
*
|
||||
|
||||
@@ -491,7 +491,7 @@ public:
|
||||
* Please delete the object directly and obtain it again after the device is reconnected.
|
||||
* Support devices: Gemini2 L
|
||||
*
|
||||
* @param[in] delayMs Time unit: ms. delayMs == 0: No delay; delayMs > 0, Delay millisecond connect to host device after reboot
|
||||
* @param[in] delayMs Time unit:ms。delayMs == 0:No delay;delayMs > 0, Delay millisecond connect to host device after reboot
|
||||
*/
|
||||
void reboot(uint32_t delayMs) const {
|
||||
setIntProperty(OB_PROP_DEVICE_REBOOT_DELAY_INT, delayMs);
|
||||
@@ -564,7 +564,7 @@ public:
|
||||
*
|
||||
* @attention The frequency of the user call this function multiplied by the number of frames per trigger should be less than the frame rate of the stream.
|
||||
* The number of frames per trigger can be set by @ref framesPerTrigger.
|
||||
* @attention For some models, receive and execute the capture command will have a certain delay and performance consumption, so the frequency of calling
|
||||
* @attention For some models,receive and execute the capture command will have a certain delay and performance consumption, so the frequency of calling
|
||||
* this function should not be too high, please refer to the product manual for the specific supported frequency.
|
||||
* @attention If the device is not in the @ref OB_MULTI_DEVICE_SYNC_MODE_HARDWARE_TRIGGERING mode, device will ignore the capture command.
|
||||
*/
|
||||
@@ -919,7 +919,7 @@ public:
|
||||
/**
|
||||
* @brief Get the connection type of the device
|
||||
*
|
||||
* @return const char* the connection type of the device, currently supports: "USB", "USB1.0", "USB1.1", "USB2.0", "USB2.1", "USB3.0", "USB3.1",
|
||||
* @return const char* the connection type of the device,currently supports:"USB", "USB1.0", "USB1.1", "USB2.0", "USB2.1", "USB3.0", "USB3.1",
|
||||
* "USB3.2", "Ethernet"
|
||||
*/
|
||||
const char *getConnectionType() const {
|
||||
@@ -1141,7 +1141,7 @@ public:
|
||||
* @brief Get device connection type
|
||||
*
|
||||
* @param index device index
|
||||
* @return const char* returns connection type, currently supports: "USB", "USB1.0", "USB1.1", "USB2.0", "USB2.1", "USB3.0", "USB3.1", "USB3.2", "Ethernet"
|
||||
* @return const char* returns connection type,currently supports:"USB", "USB1.0", "USB1.1", "USB2.0", "USB2.1", "USB3.0", "USB3.1", "USB3.2", "Ethernet"
|
||||
*/
|
||||
const char *getConnectionType(uint32_t index) const {
|
||||
ob_error *error = nullptr;
|
||||
@@ -1165,21 +1165,6 @@ public:
|
||||
return ip;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief get the local mac address of the device at the specified index
|
||||
*
|
||||
* @attention Only valid for network devices, otherwise it will return "0:0:0:0:0:0".
|
||||
*
|
||||
* @param index the index of the device
|
||||
* @return const char* the local mac address of the device
|
||||
*/
|
||||
const char *getLocalMacAddress(uint32_t index) const {
|
||||
ob_error *error = nullptr;
|
||||
auto mac = ob_device_list_get_device_local_mac(impl_, index, &error);
|
||||
Error::handle(&error);
|
||||
return mac;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the device object at the specified index
|
||||
*
|
||||
@@ -1215,7 +1200,7 @@ public:
|
||||
* @brief On Linux platform, for usb device, the uid of the device is composed of bus-port-dev, for example 1-1.2-1. But the SDK will remove the dev number
|
||||
* and only keep the bus-port as the uid to create the device, for example 1-1.2, so that we can create a device connected to the specified USB port.
|
||||
* Similarly, users can also directly pass in bus-port as uid to create device.
|
||||
* @brief For GMSL device, the uid is GMSL port with "gmsl2-" prefix, for example gmsl2-1.
|
||||
* @brief For GMSL device,the uid is GMSL port with “gmsl2-” prefix, for example gmsl2-1.
|
||||
*
|
||||
* @attention If the device has been acquired and created elsewhere, repeated acquisition will throw an exception
|
||||
*
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
#include <functional>
|
||||
|
||||
/**
|
||||
* Frame classis inheritance hierarchy:
|
||||
* Frame classis inheritance hierarchy:
|
||||
* Frame
|
||||
* |
|
||||
* +-----------+----------+----------+-----------+
|
||||
@@ -181,7 +181,7 @@ public:
|
||||
|
||||
/**
|
||||
* @brief Get the global timestamp of the frame in microseconds.
|
||||
* @brief The global timestamp is the time point when the frame was captured by the device, and has been converted to the host clock domain. The
|
||||
* @brief The global timestamp is the time point when the frame was was captured by the device, and has been converted to the host clock domain. The
|
||||
* conversion process base on the device timestamp and can eliminate the timer drift of the device
|
||||
*
|
||||
* @attention The global timestamp disable by default. If global timestamp is not enabled, the function will return 0. To enable the global timestamp,
|
||||
@@ -593,33 +593,6 @@ public:
|
||||
return scale;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the width of the frame.
|
||||
*
|
||||
* @return uint32_t The width of the frame.
|
||||
*/
|
||||
uint32_t getWidth() const {
|
||||
ob_error *error = nullptr;
|
||||
// TODO
|
||||
auto width = ob_point_cloud_frame_get_width(impl_, &error);
|
||||
Error::handle(&error);
|
||||
|
||||
return width;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the height of the frame.
|
||||
*
|
||||
* @return uint32_t The height of the frame.
|
||||
*/
|
||||
uint32_t getHeight() const {
|
||||
ob_error *error = nullptr;
|
||||
auto height = ob_point_cloud_frame_get_height(impl_, &error);
|
||||
Error::handle(&error);
|
||||
|
||||
return height;
|
||||
}
|
||||
|
||||
public:
|
||||
// The following interfaces are deprecated and are retained here for compatibility purposes.
|
||||
#define getPositionValueScale getCoordinateValueScale
|
||||
@@ -984,7 +957,7 @@ private:
|
||||
|
||||
static void BufferDestroy(uint8_t *buffer, void *context) {
|
||||
auto *ctx = static_cast<BufferDestroyContext *>(context);
|
||||
if(ctx->callback) {
|
||||
if (ctx->callback) {
|
||||
ctx->callback(buffer);
|
||||
}
|
||||
delete ctx;
|
||||
|
||||
@@ -1,188 +0,0 @@
|
||||
// Copyright (c) Orbbec Inc. All Rights Reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
/**
|
||||
* @file RecordPlayback.hpp
|
||||
* @brief Record and playback device-related types, including interfaces to create recording and playback devices,
|
||||
record and playback streaming data, etc.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Types.hpp"
|
||||
#include "Error.hpp"
|
||||
#include "libobsensor/h/RecordPlayback.h"
|
||||
#include "libobsensor/hpp/Device.hpp"
|
||||
|
||||
namespace ob {
|
||||
|
||||
typedef std::function<void(OBPlaybackStatus status)> PlaybackStatusChangeCallback;
|
||||
|
||||
class RecordDevice {
|
||||
private:
|
||||
ob_record_device_t *impl_;
|
||||
|
||||
public:
|
||||
explicit RecordDevice(std::shared_ptr<Device> device, const std::string &file, bool compressionEnabled = true) {
|
||||
ob_error *error = nullptr;
|
||||
impl_ = ob_create_record_device(device->getImpl(), file.c_str(), compressionEnabled, &error);
|
||||
Error::handle(&error);
|
||||
}
|
||||
|
||||
virtual ~RecordDevice() noexcept {
|
||||
ob_error *error = nullptr;
|
||||
ob_delete_record_device(impl_, &error);
|
||||
Error::handle(&error, false);
|
||||
}
|
||||
|
||||
RecordDevice(RecordDevice &&other) {
|
||||
if(this != &other) {
|
||||
impl_ = other.impl_;
|
||||
other.impl_ = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
RecordDevice &operator=(RecordDevice &&other) {
|
||||
if(this != &other) {
|
||||
impl_ = other.impl_;
|
||||
other.impl_ = nullptr;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
RecordDevice(const RecordDevice &) = delete;
|
||||
RecordDevice &operator=(const RecordDevice &) = delete;
|
||||
|
||||
public:
|
||||
void pause() {
|
||||
ob_error *error = nullptr;
|
||||
ob_record_device_pause(impl_, &error);
|
||||
Error::handle(&error);
|
||||
}
|
||||
|
||||
void resume() {
|
||||
ob_error *error = nullptr;
|
||||
ob_record_device_resume(impl_, &error);
|
||||
Error::handle(&error);
|
||||
}
|
||||
};
|
||||
|
||||
class PlaybackDevice : public Device {
|
||||
public:
|
||||
explicit PlaybackDevice(const std::string &file) : Device(nullptr) {
|
||||
ob_error *error = nullptr;
|
||||
impl_ = ob_create_playback_device(file.c_str(), &error);
|
||||
Error::handle(&error);
|
||||
}
|
||||
|
||||
virtual ~PlaybackDevice() noexcept = default;
|
||||
|
||||
PlaybackDevice(PlaybackDevice &&other) : Device(std::move(other)) {}
|
||||
|
||||
PlaybackDevice &operator=(PlaybackDevice &&other) {
|
||||
Device::operator=(std::move(other));
|
||||
return *this;
|
||||
}
|
||||
|
||||
PlaybackDevice(const PlaybackDevice &) = delete;
|
||||
PlaybackDevice &operator=(const PlaybackDevice &) = delete;
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief Pause the streaming data from the playback device.
|
||||
*/
|
||||
void pause() {
|
||||
ob_error *error = nullptr;
|
||||
ob_playback_device_pause(impl_, &error);
|
||||
Error::handle(&error);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Resume the streaming data from the playback device.
|
||||
*/
|
||||
void resume() {
|
||||
ob_error *error = nullptr;
|
||||
ob_playback_device_resume(impl_, &error);
|
||||
Error::handle(&error);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Seek to a specific timestamp when playing back a recording.
|
||||
* @param[in] timestamp The timestamp to seek to, in milliseconds.
|
||||
*/
|
||||
void seek(const int64_t timestamp) {
|
||||
ob_error *error = nullptr;
|
||||
ob_playback_device_seek(impl_, timestamp, &error);
|
||||
Error::handle(&error);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set the playback rate of the playback device.
|
||||
* @param[in] rate The playback rate to set.
|
||||
*/
|
||||
void setPlaybackRate(const float rate) {
|
||||
ob_error *error = nullptr;
|
||||
ob_playback_device_set_playback_rate(impl_, rate, &error);
|
||||
Error::handle(&error);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set a callback function to be called when the playback status changes.
|
||||
* @param[in] callback The callback function to set.
|
||||
*/
|
||||
void setPlaybackStatusChangeCallback(PlaybackStatusChangeCallback callback) {
|
||||
callback_ = callback;
|
||||
ob_error *error = nullptr;
|
||||
ob_playback_device_set_playback_status_changed_callback(impl_, &PlaybackDevice::playbackStatusCallback, this, &error);
|
||||
Error::handle(&error);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the current playback status of the playback device.
|
||||
* @return The current playback status.
|
||||
*/
|
||||
OBPlaybackStatus getPlaybackStatus() const {
|
||||
ob_error *error = nullptr;
|
||||
OBPlaybackStatus status = ob_playback_device_get_current_playback_status(impl_, &error);
|
||||
Error::handle(&error);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the current position of the playback device.
|
||||
* @return The current position of the playback device, in milliseconds.
|
||||
*/
|
||||
uint64_t getPosition() const {
|
||||
ob_error *error = nullptr;
|
||||
uint64_t position = ob_playback_device_get_position(impl_, &error);
|
||||
Error::handle(&error);
|
||||
|
||||
return position;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the duration of the playback device.
|
||||
* @return The duration of the playback device, in milliseconds.
|
||||
*/
|
||||
uint64_t getDuration() const {
|
||||
ob_error *error = nullptr;
|
||||
uint64_t duration = ob_playback_device_get_duration(impl_, &error);
|
||||
Error::handle(&error);
|
||||
|
||||
return duration;
|
||||
}
|
||||
|
||||
private:
|
||||
static void playbackStatusCallback(OBPlaybackStatus status, void *userData) {
|
||||
auto *playbackDevice = static_cast<PlaybackDevice *>(userData);
|
||||
if(playbackDevice && playbackDevice->callback_) {
|
||||
playbackDevice->callback_(status);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
PlaybackStatusChangeCallback callback_;
|
||||
};
|
||||
} // namespace ob
|
||||
@@ -128,7 +128,7 @@ public:
|
||||
* OB_STREAM_VIDEO,
|
||||
* OB_STREAM_DEPTH,
|
||||
* OB_STREAM_COLOR,
|
||||
* OB_STREAM_IR,
|
||||
* OB_STREAM_IR,
|
||||
* OB_STREAM_IR_LEFT,
|
||||
* OB_STREAM_IR_RIGHT,
|
||||
*
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
namespace ob {
|
||||
class Device;
|
||||
|
||||
class CoordinateTransformHelper {
|
||||
class CoordinateTransformHelper {
|
||||
public:
|
||||
/**
|
||||
* @brief Transform a 3d point of a source coordinate system into a 3d point of the target coordinate system.
|
||||
@@ -29,8 +29,8 @@ public:
|
||||
* @return bool Transform result
|
||||
*/
|
||||
static bool transformation3dto3d(const OBPoint3f source_point3f, OBExtrinsic extrinsic, OBPoint3f *target_point3f) {
|
||||
ob_error *error = NULL;
|
||||
bool result = ob_transformation_3d_to_3d(source_point3f, extrinsic, target_point3f, &error);
|
||||
ob_error *error = NULL;
|
||||
bool result = ob_transformation_3d_to_3d(source_point3f, extrinsic, target_point3f, &error);
|
||||
Error::handle(&error);
|
||||
return result;
|
||||
}
|
||||
@@ -48,8 +48,8 @@ public:
|
||||
*/
|
||||
static bool transformation2dto3d(const OBPoint2f source_point2f, const float source_depth_pixel_value, const OBCameraIntrinsic source_intrinsic,
|
||||
OBExtrinsic extrinsic, OBPoint3f *target_point3f) {
|
||||
ob_error *error = NULL;
|
||||
bool result = ob_transformation_2d_to_3d(source_point2f, source_depth_pixel_value, source_intrinsic, extrinsic, target_point3f, &error);
|
||||
ob_error *error = NULL;
|
||||
bool result = ob_transformation_2d_to_3d(source_point2f, source_depth_pixel_value, source_intrinsic, extrinsic, target_point3f, &error);
|
||||
Error::handle(&error);
|
||||
return result;
|
||||
}
|
||||
@@ -66,9 +66,9 @@ public:
|
||||
* @return bool Transform result
|
||||
*/
|
||||
static bool transformation3dto2d(const OBPoint3f source_point3f, const OBCameraIntrinsic target_intrinsic, const OBCameraDistortion target_distortion,
|
||||
OBExtrinsic extrinsic, OBPoint2f *target_point2f) {
|
||||
ob_error *error = NULL;
|
||||
bool result = ob_transformation_3d_to_2d(source_point3f, target_intrinsic, target_distortion, extrinsic, target_point2f, &error);
|
||||
OBExtrinsic extrinsic, OBPoint2f *target_point2f) {
|
||||
ob_error *error = NULL;
|
||||
bool result = ob_transformation_3d_to_2d(source_point3f, target_intrinsic, target_distortion, extrinsic, target_point2f, &error);
|
||||
Error::handle(&error);
|
||||
return result;
|
||||
}
|
||||
@@ -90,7 +90,7 @@ public:
|
||||
static bool transformation2dto2d(const OBPoint2f source_point2f, const float source_depth_pixel_value, const OBCameraIntrinsic source_intrinsic,
|
||||
const OBCameraDistortion source_distortion, const OBCameraIntrinsic target_intrinsic,
|
||||
const OBCameraDistortion target_distortion, OBExtrinsic extrinsic, OBPoint2f *target_point2f) {
|
||||
ob_error *error = NULL;
|
||||
ob_error *error = NULL;
|
||||
bool result = ob_transformation_2d_to_2d(source_point2f, source_depth_pixel_value, source_intrinsic, source_distortion, target_intrinsic,
|
||||
target_distortion, extrinsic, target_point2f, &error);
|
||||
Error::handle(&error);
|
||||
@@ -101,8 +101,8 @@ public:
|
||||
// The following interfaces are deprecated and are retained here for compatibility purposes.
|
||||
static bool calibration3dTo3d(const OBCalibrationParam calibrationParam, const OBPoint3f sourcePoint3f, const OBSensorType sourceSensorType,
|
||||
const OBSensorType targetSensorType, OBPoint3f *targetPoint3f) {
|
||||
ob_error *error = NULL;
|
||||
bool result = ob_calibration_3d_to_3d(calibrationParam, sourcePoint3f, sourceSensorType, targetSensorType, targetPoint3f, &error);
|
||||
ob_error *error = NULL;
|
||||
bool result = ob_calibration_3d_to_3d(calibrationParam, sourcePoint3f, sourceSensorType, targetSensorType, targetPoint3f, &error);
|
||||
Error::handle(&error);
|
||||
return result;
|
||||
}
|
||||
@@ -110,16 +110,15 @@ public:
|
||||
static bool calibration2dTo3d(const OBCalibrationParam calibrationParam, const OBPoint2f sourcePoint2f, const float sourceDepthPixelValue,
|
||||
const OBSensorType sourceSensorType, const OBSensorType targetSensorType, OBPoint3f *targetPoint3f) {
|
||||
ob_error *error = NULL;
|
||||
bool result =
|
||||
ob_calibration_2d_to_3d(calibrationParam, sourcePoint2f, sourceDepthPixelValue, sourceSensorType, targetSensorType, targetPoint3f, &error);
|
||||
bool result = ob_calibration_2d_to_3d(calibrationParam, sourcePoint2f, sourceDepthPixelValue, sourceSensorType, targetSensorType, targetPoint3f, &error);
|
||||
Error::handle(&error);
|
||||
return result;
|
||||
}
|
||||
|
||||
static bool calibration3dTo2d(const OBCalibrationParam calibrationParam, const OBPoint3f sourcePoint3f, const OBSensorType sourceSensorType,
|
||||
const OBSensorType targetSensorType, OBPoint2f *targetPoint2f) {
|
||||
ob_error *error = NULL;
|
||||
bool result = ob_calibration_3d_to_2d(calibrationParam, sourcePoint3f, sourceSensorType, targetSensorType, targetPoint2f, &error);
|
||||
ob_error *error = NULL;
|
||||
bool result = ob_calibration_3d_to_2d(calibrationParam, sourcePoint3f, sourceSensorType, targetSensorType, targetPoint2f, &error);
|
||||
Error::handle(&error);
|
||||
return result;
|
||||
}
|
||||
@@ -127,8 +126,7 @@ public:
|
||||
static bool calibration2dTo2d(const OBCalibrationParam calibrationParam, const OBPoint2f sourcePoint2f, const float sourceDepthPixelValue,
|
||||
const OBSensorType sourceSensorType, const OBSensorType targetSensorType, OBPoint2f *targetPoint2f) {
|
||||
ob_error *error = NULL;
|
||||
bool result =
|
||||
ob_calibration_2d_to_2d(calibrationParam, sourcePoint2f, sourceDepthPixelValue, sourceSensorType, targetSensorType, targetPoint2f, &error);
|
||||
bool result = ob_calibration_2d_to_2d(calibrationParam, sourcePoint2f, sourceDepthPixelValue, sourceSensorType, targetSensorType, targetPoint2f, &error);
|
||||
Error::handle(&error);
|
||||
return result;
|
||||
}
|
||||
@@ -140,15 +138,15 @@ public:
|
||||
// unsafe operation, need to cast const to non-const
|
||||
auto unConstImpl = const_cast<ob_frame *>(depthFrame->getImpl());
|
||||
|
||||
auto result = transformation_depth_frame_to_color_camera(device->getImpl(), unConstImpl, targetColorCameraWidth, targetColorCameraHeight, &error);
|
||||
auto result = transformation_depth_frame_to_color_camera(device->getImpl() , unConstImpl, targetColorCameraWidth, targetColorCameraHeight, &error);
|
||||
Error::handle(&error);
|
||||
return std::make_shared<ob::Frame>(result);
|
||||
}
|
||||
|
||||
static bool transformationInitXYTables(const OBCalibrationParam calibrationParam, const OBSensorType sensorType, float *data, uint32_t *dataSize,
|
||||
OBXYTables *xyTables) {
|
||||
ob_error *error = NULL;
|
||||
bool result = transformation_init_xy_tables(calibrationParam, sensorType, data, dataSize, xyTables, &error);
|
||||
ob_error *error = NULL;
|
||||
bool result = transformation_init_xy_tables(calibrationParam, sensorType, data, dataSize, xyTables, &error);
|
||||
Error::handle(&error);
|
||||
return result;
|
||||
}
|
||||
@@ -159,32 +157,11 @@ public:
|
||||
Error::handle(&error, false);
|
||||
}
|
||||
|
||||
static void transformationDepthToRGBDPointCloud(OBXYTables *xyTables, const void *depthImageData, const void *colorImageData, void *pointCloudData) {
|
||||
static void transformationDepthToRGBDPointCloud(OBXYTables *xyTables, const void *depthImageData, const void *colorImageData, void *pointCloudData){
|
||||
ob_error *error = NULL;
|
||||
transformation_depth_to_rgbd_pointcloud(xyTables, depthImageData, colorImageData, pointCloudData, &error);
|
||||
Error::handle(&error, false);
|
||||
}
|
||||
};
|
||||
|
||||
class PointCloudHelper {
|
||||
public:
|
||||
/**
|
||||
* @brief save point cloud to ply file.
|
||||
*
|
||||
* @param[in] fileName Point cloud save path
|
||||
* @param[in] frame Point cloud frame
|
||||
* @param[in] saveBinary Binary or textual,true: binary, false: textual
|
||||
* @param[in] useMesh Save mesh or not, true: save as mesh, false: not save as mesh
|
||||
* @param[in] meshThreshold Distance threshold for creating faces in point cloud,default value :50
|
||||
*
|
||||
* @return bool save point cloud result
|
||||
*/
|
||||
static bool savePointcloudToPly(const char *fileName, std::shared_ptr<ob::Frame> frame, bool saveBinary, bool useMesh, float meshThreshold) {
|
||||
ob_error *error = NULL;
|
||||
auto unConstImpl = const_cast<ob_frame *>(frame->getImpl());
|
||||
bool result = ob_save_pointcloud_to_ply(fileName, unConstImpl, saveBinary, useMesh, meshThreshold, &error);
|
||||
Error::handle(&error, false);
|
||||
return result;
|
||||
}
|
||||
};
|
||||
} // namespace ob
|
||||
|
||||
|
||||
@@ -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.3.5"
|
||||
IMPORTED_LOCATION_RELEASE "${_IMPORT_PREFIX}/lib/libOrbbecSDK.so.2.2.8"
|
||||
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.3.5" )
|
||||
list(APPEND _cmake_import_check_files_for_ob::OrbbecSDK "${_IMPORT_PREFIX}/lib/libOrbbecSDK.so.2.2.8" )
|
||||
|
||||
# Commands beyond this point should not need to know the version.
|
||||
set(CMAKE_IMPORT_FILE_VERSION)
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
libdepthengine.so.2.0
|
||||
@@ -1 +0,0 @@
|
||||
libOrbbecSDK.so.2
|
||||
@@ -1 +0,0 @@
|
||||
libOrbbecSDK.so.2.3.5
|
||||
@@ -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.3.5"
|
||||
IMPORTED_LOCATION_RELEASE "${_IMPORT_PREFIX}/lib/libOrbbecSDK.so.2.2.8"
|
||||
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.3.5" )
|
||||
list(APPEND _cmake_import_check_files_for_ob::OrbbecSDK "${_IMPORT_PREFIX}/lib/libOrbbecSDK.so.2.2.8" )
|
||||
|
||||
# Commands beyond this point should not need to know the version.
|
||||
set(CMAKE_IMPORT_FILE_VERSION)
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
libdepthengine.so.2.0
|
||||
@@ -1 +0,0 @@
|
||||
libOrbbecSDK.so.2
|
||||
@@ -1 +0,0 @@
|
||||
libOrbbecSDK.so.2.3.5
|
||||
@@ -9,78 +9,103 @@ orbbec_ros:
|
||||
config_file_path: "astra2.yaml"
|
||||
|
||||
deivce:
|
||||
# camera name, usually overwritten by launch file
|
||||
camera_name: "camera"
|
||||
# camera serial number, usually overwritten by launch file
|
||||
serial_number: ""
|
||||
# The USB port of the camera. This parameter is required when using multiple cameras.
|
||||
usb_port: ""
|
||||
# Number of devices. If multiple cameras are required, this parameter must be filled in launch file
|
||||
device_num: 1
|
||||
uvc_backend: "libuvc"
|
||||
vendor_id: "0x2bc5"
|
||||
product_id: ""
|
||||
# The delay time for reopening the device, in milliseconds. Usually, there is no need to modify by default.
|
||||
connection_delay: 100
|
||||
time_domain: "global"
|
||||
enable_heartbeat: false
|
||||
enable_ldp: true
|
||||
|
||||
color:
|
||||
# If true, the color image will be enabled
|
||||
enable_color: true
|
||||
color_qos: "default"
|
||||
color_camera_info_qos: "default"
|
||||
# Width of the color image. If 0, the default width will be used
|
||||
color_width: 1280
|
||||
# Height of the color image. If 0, the default height will be used
|
||||
color_height: 720
|
||||
# Fps of the color image. If 0, the default FPS will be used
|
||||
color_fps: 30
|
||||
color_format: "MJPG"
|
||||
enable_color_auto_white_balance: true
|
||||
color_white_balance: -1
|
||||
color_auto_ae:
|
||||
enable_color_auto_exposure: true
|
||||
color_ae_max_exposure: -1
|
||||
color_manual_ae:
|
||||
color_exposure: -1
|
||||
color_gain: -1
|
||||
color_brightness: -1
|
||||
|
||||
depth:
|
||||
# If true, the depth image will be enabled
|
||||
enable_depth: true
|
||||
depth_qos: "default"
|
||||
depth_camera_info_qos: "default"
|
||||
# Width of the depth image. If 0, the default width will be used
|
||||
depth_width: 800
|
||||
# Height of the depth image. If 0, the default height will be used
|
||||
depth_height: 600
|
||||
# Fps of the depth image. If 0, the default FPS will be used
|
||||
depth_fps: 30
|
||||
# Format of the depth image.
|
||||
depth_format: "RLE"
|
||||
# Depth registration mode.
|
||||
depth_registration: false
|
||||
# The alignment mode to be used.
|
||||
align_mode: "HW"
|
||||
|
||||
ir:
|
||||
# If false, the left IR image will not be enabled
|
||||
enable_ir: true
|
||||
ir_qos: "default"
|
||||
ir_camera_info_qos: "default"
|
||||
# Width of the left IR image. If 0, the default width will be used
|
||||
ir_width: 800
|
||||
# Height of the left IR image. If 0, the default height will be used
|
||||
ir_height: 600
|
||||
# Fps of the ir image. If 0, the default FPS will be used
|
||||
ir_fps: 30
|
||||
# Format of the left IR image. Supported formats are 'Y8'
|
||||
ir_format: "Y8"
|
||||
|
||||
ir_parameters:
|
||||
enable_ir_auto_exposure: true
|
||||
ir_ae_max_exposure: -1
|
||||
ir_exposure: -1
|
||||
ir_gain: -1
|
||||
ir_brightness: -1
|
||||
|
||||
imu:
|
||||
# If true, the IMU accelerometer data will be enabled
|
||||
enable_accel: false
|
||||
# Rate of the
|
||||
accel_rate: "100hz"
|
||||
# Range of the accelerometer.
|
||||
accel_range: "4g"
|
||||
# If true, the IMU gyroscope data will be enabled
|
||||
enable_gyro: false
|
||||
# Rate of the gyroscope.
|
||||
gyro_rate: "100hz"
|
||||
# Range of the gyroscope.
|
||||
gyro_range: "1000dps"
|
||||
enable_sync_output_accel_gyro: true
|
||||
liner_accel_cov: 0.01
|
||||
angular_vel_cov: 0.01
|
||||
|
||||
point_cloud:
|
||||
# If true, the point cloud will be enabled
|
||||
enable_point_cloud: true
|
||||
# enable color point cloud. {fase:disable, true:enable}
|
||||
enable_colored_point_cloud: false
|
||||
|
||||
advanced:
|
||||
# If true, the extrinsics publish will be enabled
|
||||
enable_publish_extrinsic: false
|
||||
# If true, the frame synchronization will be enabled
|
||||
enable_frame_sync: true
|
||||
# Publish D2C superimposed image (only for testing).
|
||||
enable_d2c_viewer: false
|
||||
# If false, the hardware time will not be used
|
||||
use_hardware_time: false
|
||||
# If false, the host time will not be synchronized with the device time
|
||||
enable_sync_host_time: false
|
||||
|
||||
device_sync:
|
||||
# Device synchronization mode. supports: {1.FREE_RUN 2.STANDALONE 3.PRIMARY 4.SECONDARY 5.SECONDARY_SYNCED 6.SOFTWARE_TRIGGERING 7.HARDWARE_TRIGGERING}.
|
||||
# For details, Please refer to the OBMultiDeviceSyncMode-related comments in SDK/include/libobsensor/ObTypes.h for a detailed explanation of each mode.
|
||||
sync_mode: "STANDALONE"
|
||||
# The delay time of the depth image capture after receiving the capture command or trigger signal in microseconds.
|
||||
# For details, Please refer to the OBMultiDeviceSyncConfig-related comments in SDK/include/libobsensor/ObTypes.h
|
||||
depth_delay_us: 0
|
||||
# The delay time of the color image capture after receiving the capture command or trigger signal in microseconds.
|
||||
color_delay_us: 0
|
||||
# The delay time of the image capture after receiving the capture command or trigger signal in microseconds.
|
||||
trigger2image_delay_us: 0
|
||||
# Trigger signal output enable flag.
|
||||
trigger_out_enabled: true
|
||||
# The delay time of the trigger signal output after receiving the capture command or trigger signal in microseconds.
|
||||
trigger_out_delay_us: 0
|
||||
# The frame number of each stream after each trigger in triggering mode.
|
||||
frames_per_trigger: 2
|
||||
# software trigger period in ms
|
||||
software_trigger_period: 33
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
orbbec_ros:
|
||||
camera_parameters:
|
||||
general:
|
||||
# Camera model. support product models by referencing config/*.yaml
|
||||
# Camera model. upport product models by referencing config/*.yaml
|
||||
camera_model: "gemini330_series"
|
||||
# The configuration file for yaml params.
|
||||
config_file_path: "gemini330_series.yaml"
|
||||
@@ -21,6 +21,8 @@ orbbec_ros:
|
||||
device_num: 1
|
||||
# Optional values: v4l2, libuvc
|
||||
uvc_backend: "libuvc"
|
||||
# Usually no need to change
|
||||
vendor_id: "0x2bc5"
|
||||
# Usually no need to change,will be read from the device
|
||||
product_id: ""
|
||||
# The delay time for reopening the device, in milliseconds. Usually, there is no need to modify by default.
|
||||
@@ -366,6 +368,8 @@ orbbec_ros:
|
||||
ir_info_url: ""
|
||||
# URL of the color image info
|
||||
color_info_url: ""
|
||||
# If true, the 3D reconstruction mode will be enabled
|
||||
enable_3d_reconstruction_mode: false
|
||||
# Diagnostic period in seconds
|
||||
diagnostic_period: 1.0
|
||||
|
||||
|
||||
@@ -9,77 +9,121 @@ orbbec_ros:
|
||||
config_file_path: "femto.yaml"
|
||||
|
||||
deivce:
|
||||
# camera name, usually overwritten by launch file
|
||||
camera_name: "camera"
|
||||
# camera serial number, usually overwritten by launch file
|
||||
serial_number: ""
|
||||
# The USB port of the camera. This parameter is required when using multiple cameras.
|
||||
usb_port: ""
|
||||
# Number of devices. If multiple cameras are required, this parameter must be filled in launch file
|
||||
device_num: 1
|
||||
uvc_backend: "libuvc"
|
||||
product_id: ""
|
||||
# The delay time for reopening the device, in milliseconds. Usually, there is no need to modify by default.
|
||||
connection_delay: 100
|
||||
time_domain: "global"
|
||||
# If true, the heartbeat will be enabled
|
||||
enable_heartbeat: false
|
||||
# If true, the LDP will be enabled
|
||||
enable_ldp: true
|
||||
|
||||
network_device:
|
||||
# Whether to enable the function of enumerating network devices. True means enabled and false means disabled. This function is only supported by Femto Mega and Gemini 2 XL devices.
|
||||
# When accessing these devices through the network, the IP address of the device needs to be preconfigured. The enable switch needs to be set to true.
|
||||
enumerate_net_device: false
|
||||
# Port number of the network device. If 0, a random port will be used
|
||||
net_device_port: 0
|
||||
# IP address of the network device.
|
||||
net_device_ip: ""
|
||||
|
||||
color:
|
||||
# If true, the color image will be enabled
|
||||
enable_color: true
|
||||
color_qos: "default"
|
||||
color_camera_info_qos: "default"
|
||||
# Width of the color image. If 0, the default width will be used
|
||||
color_width: 640
|
||||
# Height of the color image. If 0, the default height will be used
|
||||
color_height: 480
|
||||
# If 0, the default FPS will be used
|
||||
color_fps: 30
|
||||
# Format of the color image.
|
||||
color_format: "MJPG"
|
||||
enable_color_auto_white_balance: true
|
||||
color_white_balance: -1
|
||||
color_auto_ae:
|
||||
enable_color_auto_exposure: true
|
||||
color_ae_max_exposure: -1
|
||||
color_manual_ae:
|
||||
color_exposure: -1
|
||||
color_gain: -1
|
||||
color_brightness: -1
|
||||
|
||||
depth:
|
||||
# If true, the depth image will be enabled
|
||||
enable_depth: true
|
||||
depth_qos: "default"
|
||||
depth_camera_info_qos: "default"
|
||||
# Width of the depth image. If 0, the default width will be used
|
||||
depth_width: 640
|
||||
depth_height: 576
|
||||
# Height of the depth image. If 0, the default height will be used
|
||||
depth_height: 480
|
||||
# fps of the depth image. If 0, the default FPS will be used
|
||||
depth_fps: 30
|
||||
# Format of the depth image.
|
||||
depth_format: "Y16"
|
||||
# Depth registration enable
|
||||
depth_registration: false
|
||||
|
||||
# The alignment mode to be used. Options are "HW" for hardware alignment and "SW" for software alignment
|
||||
align_mode: "HW"
|
||||
|
||||
ir:
|
||||
# If false, the left IR image will not be enabled
|
||||
enable_ir: true
|
||||
ir_qos: "default"
|
||||
ir_camera_info_qos: "default"
|
||||
# Width of the left IR image. If 0, the default width will be used
|
||||
ir_width: 640
|
||||
ir_height: 576
|
||||
# Height of the left IR image. If 0, the default height will be used
|
||||
ir_height: 480
|
||||
# Fps of the left IR image. If 0, the default FPS will be used
|
||||
ir_fps: 30
|
||||
# Format of the left IR image. Supported formats are 'Y8'
|
||||
ir_format: "Y16"
|
||||
|
||||
ir_parameters:
|
||||
enable_ir_auto_exposure: true
|
||||
ir_ae_max_exposure: -1
|
||||
ir_exposure: -1
|
||||
ir_gain: -1
|
||||
ir_brightness: -1
|
||||
|
||||
imu:
|
||||
# If true, the IMU accelerometer data will be enabled
|
||||
enable_accel: false
|
||||
# Rate of the
|
||||
accel_rate: "100hz"
|
||||
# Range of the accelerometer.
|
||||
accel_range: "4g"
|
||||
# If true, the IMU gyroscope data will be enabled
|
||||
enable_gyro: false
|
||||
# Rate of the gyroscope.
|
||||
gyro_rate: "100hz"
|
||||
# Range of the gyroscope.
|
||||
gyro_range: "1000dps"
|
||||
# enable_sync_output_accel_gyro
|
||||
enable_sync_output_accel_gyro: true
|
||||
liner_accel_cov: 0.01
|
||||
angular_vel_cov: 0.01
|
||||
|
||||
point_cloud:
|
||||
# If true, the point cloud will be enabled
|
||||
enable_point_cloud: true
|
||||
# enable color point cloud. {fase:disable, true:enable}
|
||||
enable_colored_point_cloud: false
|
||||
|
||||
advanced:
|
||||
enable_frame_sync: true
|
||||
# If true, the extrinsics publish will be enabled
|
||||
enable_publish_extrinsic: false
|
||||
# If true, the frame synchronization will be enabled
|
||||
enable_frame_sync: false
|
||||
# If true, Overlay display of color image and depth image after D2C processing will be enabled
|
||||
enable_d2c_viewer: false
|
||||
# If false, the hardware time will not be used
|
||||
use_hardware_time: false
|
||||
# If false, the host time will not be synchronized with the device time
|
||||
enable_sync_host_time: false
|
||||
|
||||
device_sync:
|
||||
# Device synchronization mode. supports: {1.FREE_RUN 2.STANDALONE 3.PRIMARY 4.SECONDARY 5.SECONDARY_SYNCED 6.SOFTWARE_TRIGGERING 7.HARDWARE_TRIGGERING}.
|
||||
# For details, Please refer to the OBMultiDeviceSyncMode-related comments in SDK/include/libobsensor/ObTypes.h for a detailed explanation of each mode.
|
||||
sync_mode: "STANDALONE"
|
||||
# The delay time of the depth image capture after receiving the capture command or trigger signal in microseconds.
|
||||
# For details, Please refer to the OBMultiDeviceSyncConfig-related comments in SDK/include/libobsensor/ObTypes.h
|
||||
depth_delay_us: 0
|
||||
# The delay time of the color image capture after receiving the capture command or trigger signal in microseconds.
|
||||
color_delay_us: 0
|
||||
# The delay time of the image capture after receiving the capture command or trigger signal in microseconds.
|
||||
trigger2image_delay_us: 0
|
||||
# Trigger signal output enable flag.
|
||||
trigger_out_enabled: true
|
||||
# The delay time of the trigger signal output after receiving the capture command or trigger signal in microseconds.
|
||||
trigger_out_delay_us: 0
|
||||
# The frame number of each stream after each trigger in triggering mode.
|
||||
frames_per_trigger: 2
|
||||
# software trigger period in ms
|
||||
software_trigger_period: 33
|
||||
|
||||
@@ -1,85 +0,0 @@
|
||||
# config/*.yaml files are used to configure the camera parameters
|
||||
---
|
||||
orbbec_ros:
|
||||
camera_parameters:
|
||||
general:
|
||||
# Camera model. upport product models by referencing config/*.yaml
|
||||
camera_model: "femto_bolt"
|
||||
# Path to the configuration file. If empty, default parameters will be used
|
||||
config_file_path: "femto_bolt.yaml"
|
||||
|
||||
deivce:
|
||||
camera_name: "camera"
|
||||
serial_number: ""
|
||||
usb_port: ""
|
||||
device_num: 1
|
||||
uvc_backend: "libuvc"
|
||||
product_id: ""
|
||||
connection_delay: 100
|
||||
time_domain: "global"
|
||||
enable_heartbeat: false
|
||||
enable_ldp: true
|
||||
|
||||
color:
|
||||
enable_color: true
|
||||
color_qos: "default"
|
||||
color_camera_info_qos: "default"
|
||||
color_width: 1280
|
||||
color_height: 720
|
||||
color_fps: 30
|
||||
color_format: "MJPG"
|
||||
enable_color_auto_white_balance: true
|
||||
color_white_balance: -1
|
||||
color_auto_ae:
|
||||
enable_color_auto_exposure: true
|
||||
color_ae_max_exposure: -1
|
||||
color_manual_ae:
|
||||
color_exposure: -1
|
||||
color_gain: -1
|
||||
color_brightness: -1
|
||||
|
||||
depth:
|
||||
enable_depth: true
|
||||
depth_qos: "default"
|
||||
depth_camera_info_qos: "default"
|
||||
depth_width: 640
|
||||
depth_height: 576
|
||||
depth_fps: 30
|
||||
depth_format: "Y16"
|
||||
depth_registration: false
|
||||
align_mode: "SW"
|
||||
ir:
|
||||
enable_ir: true
|
||||
ir_qos: "default"
|
||||
ir_camera_info_qos: "default"
|
||||
ir_width: 640
|
||||
ir_height: 576
|
||||
ir_fps: 30
|
||||
ir_format: "Y16"
|
||||
|
||||
ir_parameters:
|
||||
enable_ir_auto_exposure: true
|
||||
ir_ae_max_exposure: -1
|
||||
ir_exposure: -1
|
||||
ir_gain: -1
|
||||
ir_brightness: -1
|
||||
|
||||
imu:
|
||||
enable_accel: false
|
||||
accel_rate: "200hz"
|
||||
accel_range: "4g"
|
||||
enable_gyro: false
|
||||
gyro_rate: "200hz"
|
||||
gyro_range: "1000dps"
|
||||
enable_sync_output_accel_gyro: true
|
||||
liner_accel_cov: 0.01
|
||||
angular_vel_cov: 0.01
|
||||
|
||||
point_cloud:
|
||||
enable_point_cloud: false
|
||||
enable_colored_point_cloud: false
|
||||
|
||||
advanced:
|
||||
enable_frame_sync: true
|
||||
enable_d2c_viewer: false
|
||||
|
||||
@@ -1,85 +0,0 @@
|
||||
# config/*.yaml files are used to configure the camera parameters
|
||||
---
|
||||
orbbec_ros:
|
||||
camera_parameters:
|
||||
general:
|
||||
# Camera model. upport product models by referencing config/*.yaml
|
||||
camera_model: "femto_mega"
|
||||
# Path to the configuration file. If empty, default parameters will be used
|
||||
config_file_path: "femto_mega.yaml"
|
||||
|
||||
deivce:
|
||||
camera_name: "camera"
|
||||
serial_number: ""
|
||||
usb_port: ""
|
||||
device_num: 1
|
||||
uvc_backend: "libuvc"
|
||||
product_id: ""
|
||||
connection_delay: 100
|
||||
time_domain: "global"
|
||||
enable_heartbeat: false
|
||||
enable_ldp: true
|
||||
|
||||
color:
|
||||
enable_color: true
|
||||
color_qos: "default"
|
||||
color_camera_info_qos: "default"
|
||||
color_width: 1280
|
||||
color_height: 720
|
||||
color_fps: 30
|
||||
color_format: "MJPG"
|
||||
enable_color_auto_white_balance: true
|
||||
color_white_balance: -1
|
||||
color_auto_ae:
|
||||
enable_color_auto_exposure: true
|
||||
color_ae_max_exposure: -1
|
||||
color_manual_ae:
|
||||
color_exposure: -1
|
||||
color_gain: -1
|
||||
color_brightness: -1
|
||||
|
||||
depth:
|
||||
enable_depth: true
|
||||
depth_qos: "default"
|
||||
depth_camera_info_qos: "default"
|
||||
depth_width: 640
|
||||
depth_height: 576
|
||||
depth_fps: 30
|
||||
depth_format: "Y16"
|
||||
depth_registration: false
|
||||
align_mode: "HW"
|
||||
ir:
|
||||
enable_ir: true
|
||||
ir_qos: "default"
|
||||
ir_camera_info_qos: "default"
|
||||
ir_width: 640
|
||||
ir_height: 576
|
||||
ir_fps: 30
|
||||
ir_format: "Y16"
|
||||
|
||||
ir_parameters:
|
||||
enable_ir_auto_exposure: true
|
||||
ir_ae_max_exposure: -1
|
||||
ir_exposure: -1
|
||||
ir_gain: -1
|
||||
ir_brightness: -1
|
||||
|
||||
imu:
|
||||
enable_accel: false
|
||||
accel_rate: "100hz"
|
||||
accel_range: "4g"
|
||||
enable_gyro: false
|
||||
gyro_rate: "100hz"
|
||||
gyro_range: "1000dps"
|
||||
enable_sync_output_accel_gyro: true
|
||||
liner_accel_cov: 0.01
|
||||
angular_vel_cov: 0.01
|
||||
|
||||
point_cloud:
|
||||
enable_point_cloud: true
|
||||
enable_colored_point_cloud: false
|
||||
|
||||
advanced:
|
||||
enable_frame_sync: true
|
||||
enable_d2c_viewer: false
|
||||
|
||||
@@ -0,0 +1,129 @@
|
||||
# config/*.yaml files are used to configure the camera parameters
|
||||
#
|
||||
# For Femto Mega and Femto Bolt devices, Configuration of depth NFOV and WFOV modes.
|
||||
# NFOV and WFOV modes are achieved by configuring the resolution of Depth and IR in the startup file.
|
||||
# In the startup file, depth_width, depth_height, ir_width, ir_height represent the resolution of depth and the resolution of IR, respectively.
|
||||
# The frame rate and resolution of IR must be consistent with depth. The corresponding relationship between different modes and resolution is as follows:
|
||||
# • NFOV unbinned: 640 x 576.
|
||||
# • NFOV binned: 320 x 288.
|
||||
# • WFOV unbinned: 1024 x 1024.
|
||||
# • WFOV binned: 512 x 512.
|
||||
#
|
||||
---
|
||||
orbbec_ros:
|
||||
camera_parameters:
|
||||
general:
|
||||
# Camera model. upport product models by referencing config/*.yaml
|
||||
camera_model: "femtobolt"
|
||||
# Path to the configuration file. If empty, default parameters will be used
|
||||
config_file_path: "femtobolt.yaml"
|
||||
|
||||
deivce:
|
||||
# camera name, usually overwritten by launch file
|
||||
camera_name: "camera"
|
||||
# camera serial number, usually overwritten by launch file
|
||||
serial_number: ""
|
||||
# The USB port of the camera. This parameter is required when using multiple cameras.
|
||||
usb_port: ""
|
||||
# Number of devices. If multiple cameras are required, this parameter must be filled in launch file
|
||||
device_num: 1
|
||||
# The delay time for reopening the device, in milliseconds. Usually, there is no need to modify by default.
|
||||
connection_delay: 100
|
||||
|
||||
color:
|
||||
# If true, the color image will be enabled
|
||||
enable_color: true
|
||||
# Width of the color image. If 0, the default width will be used
|
||||
color_width: 1280
|
||||
# Height of the color image. If 0, the default height will be used
|
||||
color_height: 720
|
||||
# If 0, the default FPS will be used
|
||||
color_fps: 30
|
||||
# Format of the color image.
|
||||
color_format: "MJPG"
|
||||
|
||||
depth:
|
||||
# If true, the depth image will be enabled
|
||||
enable_depth: true
|
||||
# Width of the depth image. If 0, the default width will be used
|
||||
depth_width: 640
|
||||
# Height of the depth image. If 0, the default height will be used
|
||||
depth_height: 576
|
||||
# If 0, the default FPS will be used
|
||||
depth_fps: 30
|
||||
# Format of the depth image.
|
||||
depth_format: "Y16"
|
||||
# If false, the depth scale will not be enabled
|
||||
enable_depth_scale: true
|
||||
# Depth registration mode.
|
||||
depth_registration: false
|
||||
# The alignment mode to be used. Options are "HW" for hardware alignment and "SW" for software alignment
|
||||
align_mode: "SW"
|
||||
filter:
|
||||
soft_filter:
|
||||
# If false, the soft filter will not be enabled
|
||||
enable_soft_filter: true
|
||||
# The maximum difference between the current and previous depth frame to be considered valid
|
||||
soft_filter_max_diff: -1
|
||||
# The size of the speckle to be filtered out
|
||||
soft_filter_speckle_size: -1
|
||||
|
||||
ir:
|
||||
# If false, the left IR image will not be enabled
|
||||
enable_ir: true
|
||||
# Width of the left IR image. If 0, the default width will be used
|
||||
ir_width: 640
|
||||
# Height of the left IR image. If 0, the default height will be used
|
||||
ir_height: 576
|
||||
# If 0, the default FPS will be used
|
||||
ir_fps: 30
|
||||
# Format of the left IR image. Supported formats are 'Y8'
|
||||
ir_format: "Y16"
|
||||
|
||||
imu:
|
||||
# If true, the IMU accelerometer data will be enabled
|
||||
enable_accel: false
|
||||
# Rate of the
|
||||
accel_rate: "200hz"
|
||||
# Range of the accelerometer.
|
||||
accel_range: "4g"
|
||||
# If true, the IMU gyroscope data will be enabled
|
||||
enable_gyro: false
|
||||
# Rate of the gyroscope.
|
||||
gyro_rate: "200hz"
|
||||
# Range of the gyroscope.
|
||||
gyro_range: "1000dps"
|
||||
# enable_sync_output_accel_gyro
|
||||
enable_sync_output_accel_gyro: true
|
||||
|
||||
advanced:
|
||||
# If true, the extrinsics publish will be enabled
|
||||
enable_publish_extrinsic: false
|
||||
# If true, the frame synchronization will be enabled
|
||||
enable_frame_sync: true
|
||||
# If true, Overlay display of color image and depth image after D2C processing will be enabled
|
||||
enable_d2c_viewer: false
|
||||
# If false, the hardware time will not be used
|
||||
use_hardware_time: true
|
||||
# If false, the host time will not be synchronized with the device time
|
||||
enable_sync_host_time: false
|
||||
|
||||
device_sync:
|
||||
# Device synchronization mode. supports: {1.FREE_RUN 2.STANDALONE 3.PRIMARY 4.SECONDARY 5.SECONDARY_SYNCED 6.SOFTWARE_TRIGGERING 7.HARDWARE_TRIGGERING}.
|
||||
# For details, Please refer to the OBMultiDeviceSyncMode-related comments in SDK/include/libobsensor/ObTypes.h for a detailed explanation of each mode.
|
||||
sync_mode: "STANDALONE"
|
||||
# The delay time of the depth image capture after receiving the capture command or trigger signal in microseconds.
|
||||
# For details, Please refer to the OBMultiDeviceSyncConfig-related comments in SDK/include/libobsensor/ObTypes.h
|
||||
depth_delay_us: 0
|
||||
# The delay time of the color image capture after receiving the capture command or trigger signal in microseconds.
|
||||
color_delay_us: 0
|
||||
# The delay time of the image capture after receiving the capture command or trigger signal in microseconds.
|
||||
trigger2image_delay_us: 0
|
||||
# Trigger signal output enable flag.
|
||||
trigger_out_enabled: true
|
||||
# The delay time of the trigger signal output after receiving the capture command or trigger signal in microseconds.
|
||||
trigger_out_delay_us: 0
|
||||
# The frame number of each stream after each trigger in triggering mode.
|
||||
frames_per_trigger: 2
|
||||
# software trigger period in ms
|
||||
software_trigger_period: 33
|
||||
@@ -0,0 +1,134 @@
|
||||
# config/*.yaml files are used to configure the camera parameters
|
||||
#
|
||||
# For Femto Mega and Femto Bolt devices, Configuration of depth NFOV and WFOV modes.
|
||||
# NFOV and WFOV modes are achieved by configuring the resolution of Depth and IR in the startup file.
|
||||
# In the startup file, depth_width, depth_height, ir_width, ir_height represent the resolution of depth and the resolution of IR, respectively.
|
||||
# The frame rate and resolution of IR must be consistent with depth. The corresponding relationship between different modes and resolution is as follows:
|
||||
# • NFOV unbinned: 640 x 576.
|
||||
# • NFOV binned: 320 x 288.
|
||||
# • WFOV unbinned: 1024 x 1024.
|
||||
# • WFOV binned: 512 x 512.
|
||||
#
|
||||
---
|
||||
orbbec_ros:
|
||||
camera_parameters:
|
||||
general:
|
||||
# Camera model. upport product models by referencing config/*.yaml
|
||||
camera_model: "femtomega"
|
||||
# Path to the configuration file. If empty, default parameters will be used
|
||||
config_file_path: "femtomega.yaml"
|
||||
|
||||
deivce:
|
||||
# camera name, usually overwritten by launch file
|
||||
camera_name: "camera"
|
||||
# camera serial number, usually overwritten by launch file
|
||||
serial_number: ""
|
||||
# The USB port of the camera. This parameter is required when using multiple cameras.
|
||||
usb_port: ""
|
||||
# Number of devices. If multiple cameras are required, this parameter must be filled in launch file
|
||||
device_num: 1
|
||||
# The delay time for reopening the device, in milliseconds. Usually, there is no need to modify by default.
|
||||
connection_delay: 100
|
||||
|
||||
network_device:
|
||||
# Whether to enable the function of enumerating network devices. True means enabled and false means disabled. This function is only supported by Femto Mega and Gemini 2 XL devices.
|
||||
# When accessing these devices through the network, the IP address of the device needs to be preconfigured. The enable switch needs to be set to true.
|
||||
enumerate_net_device: false
|
||||
# Port number of the network device. If 0, a random port will be used
|
||||
net_device_port: 0
|
||||
# IP address of the network device.
|
||||
net_device_ip: ""
|
||||
|
||||
color:
|
||||
# If true, the color image will be enabled
|
||||
enable_color: true
|
||||
# Width of the color image. If 0, the default width will be used
|
||||
color_width: 1280
|
||||
# Height of the color image. If 0, the default height will be used
|
||||
color_height: 720
|
||||
# If 0, the default FPS will be used
|
||||
color_fps: 30
|
||||
|
||||
depth:
|
||||
# If true, the depth image will be enabled
|
||||
enable_depth: true
|
||||
# Width of the depth image. If 0, the default width will be used
|
||||
depth_width: 640
|
||||
# Height of the depth image. If 0, the default height will be used
|
||||
depth_height: 576
|
||||
# If 0, the default FPS will be used
|
||||
depth_fps: 30
|
||||
# Format of the depth image.
|
||||
depth_format: "Y16"
|
||||
# If false, the depth scale will not be enabled
|
||||
enable_depth_scale: true
|
||||
# Depth registration mode.
|
||||
depth_registration: false
|
||||
# The alignment mode to be used. Options are "HW" for hardware alignment and "SW" for software alignment
|
||||
align_mode: "HW"
|
||||
|
||||
ir:
|
||||
# If false, the left IR image will not be enabled
|
||||
enable_ir: true
|
||||
# Width of the left IR image. If 0, the default width will be used
|
||||
ir_width: 640
|
||||
# Height of the left IR image. If 0, the default height will be used
|
||||
ir_height: 576
|
||||
# If 0, the default FPS will be used
|
||||
ir_fps: 30
|
||||
# Format of the left IR image. Supported formats are 'Y8'
|
||||
ir_format: "Y16"
|
||||
|
||||
imu:
|
||||
# If true, the IMU accelerometer data will be enabled
|
||||
enable_accel: false
|
||||
# Rate of the
|
||||
accel_rate: "100hz"
|
||||
# Range of the accelerometer.
|
||||
accel_range: "4g"
|
||||
# If true, the IMU gyroscope data will be enabled
|
||||
enable_gyro: false
|
||||
# Rate of the gyroscope.
|
||||
gyro_rate: "100hz"
|
||||
# Range of the gyroscope.
|
||||
gyro_range: "1000dps"
|
||||
# enable_sync_output_accel_gyro
|
||||
enable_sync_output_accel_gyro: true
|
||||
|
||||
point_cloud:
|
||||
# If true, the point cloud will be enabled
|
||||
enable_point_cloud: true
|
||||
# enable color point cloud. {fase:disable, true:enable}
|
||||
enable_colored_point_cloud: false
|
||||
|
||||
advanced:
|
||||
# If true, the extrinsics publish will be enabled
|
||||
enable_publish_extrinsic: false
|
||||
# If true, the frame synchronization will be enabled
|
||||
enable_frame_sync: true
|
||||
# Publish D2C superimposed image (only for testing).
|
||||
enable_d2c_viewer: false
|
||||
# If false, the hardware time will not be used
|
||||
use_hardware_time: false
|
||||
# If false, the host time will not be synchronized with the device time
|
||||
enable_sync_host_time: false
|
||||
|
||||
device_sync:
|
||||
# Device synchronization mode. supports: {1.FREE_RUN 2.STANDALONE 3.PRIMARY 4.SECONDARY 5.SECONDARY_SYNCED 6.SOFTWARE_TRIGGERING 7.HARDWARE_TRIGGERING}.
|
||||
# For details, Please refer to the OBMultiDeviceSyncMode-related comments in SDK/include/libobsensor/ObTypes.h for a detailed explanation of each mode.
|
||||
sync_mode: "STANDALONE"
|
||||
# The delay time of the depth image capture after receiving the capture command or trigger signal in microseconds.
|
||||
# For details, Please refer to the OBMultiDeviceSyncConfig-related comments in SDK/include/libobsensor/ObTypes.h
|
||||
depth_delay_us: 0
|
||||
# The delay time of the color image capture after receiving the capture command or trigger signal in microseconds.
|
||||
color_delay_us: 0
|
||||
# The delay time of the image capture after receiving the capture command or trigger signal in microseconds.
|
||||
trigger2image_delay_us: 0
|
||||
# Trigger signal output enable flag.
|
||||
trigger_out_enabled: true
|
||||
# The delay time of the trigger signal output after receiving the capture command or trigger signal in microseconds.
|
||||
trigger_out_delay_us: 0
|
||||
# The frame number of each stream after each trigger in triggering mode.
|
||||
frames_per_trigger: 2
|
||||
# software trigger period in ms
|
||||
software_trigger_period: 33
|
||||
@@ -9,78 +9,140 @@ orbbec_ros:
|
||||
config_file_path: "gemini2.yaml"
|
||||
|
||||
deivce:
|
||||
# camera name, usually overwritten by launch file
|
||||
camera_name: "camera"
|
||||
# camera serial number, usually overwritten by launch file
|
||||
serial_number: ""
|
||||
# The USB port of the camera. This parameter is required when using multiple cameras.
|
||||
usb_port: ""
|
||||
# Number of devices. If multiple cameras are required, this parameter must be filled in launch file
|
||||
device_num: 1
|
||||
uvc_backend: "libuvc"
|
||||
product_id: ""
|
||||
# The delay time for reopening the device, in milliseconds. Usually, there is no need to modify by default.
|
||||
connection_delay: 100
|
||||
time_domain: "global"
|
||||
retry_on_usb3_detection_failure: false
|
||||
# If true, the heartbeat will be enabled
|
||||
enable_heartbeat: false
|
||||
# If true, the LDP will be enabled
|
||||
enable_ldp: true
|
||||
|
||||
network_device:
|
||||
# Whether to enable the function of enumerating network devices. True means enabled and false means disabled. This function is only supported by Femto Mega and Gemini 2 XL devices.
|
||||
# When accessing these devices through the network, the IP address of the device needs to be preconfigured. The enable switch needs to be set to true.
|
||||
enumerate_net_device: false
|
||||
# Port number of the network device. If 0, a random port will be used
|
||||
net_device_port: 0
|
||||
# IP address of the network device.
|
||||
net_device_ip: ""
|
||||
|
||||
color:
|
||||
# If true, the color image will be enabled
|
||||
enable_color: true
|
||||
color_qos: "default"
|
||||
color_camera_info_qos: "default"
|
||||
# Width of the color image. If 0, the default width will be used
|
||||
color_width: 640
|
||||
# Height of the color image. If 0, the default height will be used
|
||||
color_height: 360
|
||||
# If 0, the default FPS will be used
|
||||
color_fps: 15
|
||||
# Format of the color image.
|
||||
color_format: "MJPG"
|
||||
enable_color_auto_white_balance: true
|
||||
color_white_balance: -1
|
||||
color_auto_ae:
|
||||
enable_color_auto_exposure: true
|
||||
color_ae_max_exposure: -1
|
||||
color_manual_ae:
|
||||
color_exposure: -1
|
||||
color_gain: -1
|
||||
color_brightness: -1
|
||||
|
||||
depth:
|
||||
# If true, the depth image will be enabled
|
||||
enable_depth: true
|
||||
depth_qos: "default"
|
||||
depth_camera_info_qos: "default"
|
||||
# Width of the depth image. If 0, the default width will be used
|
||||
depth_width: 640
|
||||
# Height of the depth image. If 0, the default height will be used
|
||||
depth_height: 400
|
||||
# If 0, the default FPS will be used
|
||||
depth_fps: 15
|
||||
# Format of the depth image.
|
||||
depth_format: "Y14"
|
||||
# If false, the depth scale will not be enabled
|
||||
enable_depth_scale: true
|
||||
|
||||
# D2C Depth registration mode.
|
||||
# Enables hardware that aligns depth frames to color frames. This field is required when setting enable_colored_point_cloud to true
|
||||
depth_registration: true
|
||||
# The alignment mode to be used. Options are "HW" for hardware alignment and "SW" for software alignment
|
||||
align_mode: "HW"
|
||||
|
||||
# Gemini 2, Gemini 2 L, and Gemini 2 XL cameras support deep working mode switching
|
||||
# Specific camera deep working mode support types can be found in the deep mode comments.
|
||||
# Deep working mode support is as follows:{"Unbinned Dense Default","Unbinned Sparse Default","Binned Sparse Default","Obstacle Avoidance"}
|
||||
# Depth work mode. #For details, Please refer to the comments in SDK/include/libobsensor/Advanced.h for a detailed explanation.
|
||||
depth_work_mode: ""
|
||||
|
||||
# Configure the loading path of the deep filtering configuration file. By default, the deep filtering configuration file is located in the /config/depthfilter directory and is only supported by Gemini2.
|
||||
depth_filter_config: ""
|
||||
|
||||
filter:
|
||||
soft_filter:
|
||||
# If false, the soft filter will not be enabled
|
||||
enable_soft_filter: true
|
||||
# The maximum difference between the current and previous depth frame to be considered valid
|
||||
soft_filter_max_diff: -1
|
||||
# The size of the speckle to be filtered out
|
||||
soft_filter_speckle_size: -1
|
||||
|
||||
ir:
|
||||
# enable the ir camera stream
|
||||
enable_ir: true
|
||||
ir_qos: "default"
|
||||
ir_camera_info_qos: "default"
|
||||
# Width of the left IR image. If 0, the default width will be used
|
||||
ir_width: 640
|
||||
# Height of the left IR image. If 0, the default height will be used
|
||||
ir_height: 400
|
||||
# If 0, the default FPS will be used
|
||||
ir_fps: 15
|
||||
# Format of the left IR image. Supported formats are 'Y8'
|
||||
ir_format: "Y8"
|
||||
|
||||
ir_parameters:
|
||||
enable_ir_auto_exposure: true
|
||||
ir_ae_max_exposure: -1
|
||||
ir_exposure: -1
|
||||
ir_gain: -1
|
||||
ir_brightness: -1
|
||||
|
||||
imu:
|
||||
# If true, enable the IMU accelerometer data
|
||||
enable_accel: false
|
||||
# Rate of the accelerometer
|
||||
accel_rate: "100hz"
|
||||
# Range of the accelerometer.
|
||||
accel_range: "4g"
|
||||
# If true, enable the IMU gyroscope data
|
||||
enable_gyro: false
|
||||
# Rate of the gyroscope.
|
||||
gyro_rate: "100hz"
|
||||
# Range of the gyroscope.
|
||||
gyro_range: "1000dps"
|
||||
# enable_sync_output_accel_gyro
|
||||
enable_sync_output_accel_gyro: true
|
||||
liner_accel_cov: 0.01
|
||||
angular_vel_cov: 0.01
|
||||
|
||||
point_cloud:
|
||||
# If true, the depth point cloud will be enabled
|
||||
enable_point_cloud: true
|
||||
# enable color point cloud. {fase:disable, true:enable}
|
||||
enable_colored_point_cloud: false
|
||||
|
||||
advanced:
|
||||
# If true, the extrinsics publish will be enabled
|
||||
enable_publish_extrinsic: false
|
||||
# If true, the frame synchronization will be enabled
|
||||
enable_frame_sync: true
|
||||
# If true, Overlay display of color image and depth image after D2C processing will be enabled
|
||||
enable_d2c_viewer: false
|
||||
# If false, the hardware time will not be used
|
||||
use_hardware_time: true
|
||||
|
||||
device_sync:
|
||||
# Device synchronization mode. supports: {1.FREE_RUN 2.STANDALONE 3.PRIMARY 4.SECONDARY 5.SECONDARY_SYNCED 6.SOFTWARE_TRIGGERING 7.HARDWARE_TRIGGERING}.
|
||||
# For details, Please refer to the OBMultiDeviceSyncMode-related comments in SDK/include/libobsensor/ObTypes.h for a detailed explanation of each mode.
|
||||
sync_mode: "STANDALONE"
|
||||
# The delay time of the depth image capture after receiving the capture command or trigger signal in microseconds.
|
||||
# For details, Please refer to the OBMultiDeviceSyncConfig-related comments in SDK/include/libobsensor/ObTypes.h
|
||||
depth_delay_us: 0
|
||||
# The delay time of the color image capture after receiving the capture command or trigger signal in microseconds.
|
||||
color_delay_us: 0
|
||||
# The delay time of the image capture after receiving the capture command or trigger signal in microseconds.
|
||||
trigger2image_delay_us: 0
|
||||
# Trigger signal output enable flag.
|
||||
trigger_out_enabled: true
|
||||
# The delay time of the trigger signal output after receiving the capture command or trigger signal in microseconds.
|
||||
trigger_out_delay_us: 0
|
||||
# The frame number of each stream after each trigger in triggering mode.
|
||||
frames_per_trigger: 2
|
||||
# software trigger period in ms
|
||||
software_trigger_period: 33
|
||||
|
||||
@@ -9,78 +9,113 @@ orbbec_ros:
|
||||
config_file_path: "gemini2L.yaml"
|
||||
|
||||
deivce:
|
||||
# camera name, usually overwritten by launch file
|
||||
camera_name: "camera"
|
||||
# camera serial number, usually overwritten by launch file
|
||||
serial_number: ""
|
||||
# The USB port of the camera. This parameter is required when using multiple cameras.
|
||||
usb_port: ""
|
||||
# Number of devices. If multiple cameras are required, this parameter must be filled in launch file
|
||||
device_num: 1
|
||||
uvc_backend: "libuvc"
|
||||
product_id: ""
|
||||
# The delay time for reopening the device, in milliseconds. Usually, there is no need to modify by default.
|
||||
connection_delay: 100
|
||||
time_domain: "global"
|
||||
retry_on_usb3_detection_failure: false
|
||||
enable_heartbeat: false
|
||||
enable_ldp: true
|
||||
|
||||
network_device:
|
||||
# Whether to enable the function of enumerating network devices. True means enabled and false means disabled. This function is only supported by Femto Mega and Gemini 2 XL devices.
|
||||
# When accessing these devices through the network, the IP address of the device needs to be preconfigured. The enable switch needs to be set to true.
|
||||
enumerate_net_device: false
|
||||
# Port number of the network device. If 0, a random port will be used
|
||||
net_device_port: 0
|
||||
# IP address of the network device.
|
||||
net_device_ip: ""
|
||||
|
||||
color:
|
||||
# If true, the color image will be enabled
|
||||
enable_color: true
|
||||
color_qos: "default"
|
||||
color_camera_info_qos: "default"
|
||||
# Width of the color image. If 0, the default width will be used
|
||||
color_width: 1280
|
||||
# Height of the color image. If 0, the default height will be used
|
||||
color_height: 800
|
||||
# fps of the color image. If 0, the default FPS will be used
|
||||
color_fps: 30
|
||||
# Format of the color image.
|
||||
color_format: "MJPG"
|
||||
enable_color_auto_white_balance: true
|
||||
color_white_balance: -1
|
||||
color_auto_ae:
|
||||
enable_color_auto_exposure: true
|
||||
color_ae_max_exposure: -1
|
||||
color_manual_ae:
|
||||
color_exposure: -1
|
||||
color_gain: -1
|
||||
color_brightness: -1
|
||||
|
||||
depth:
|
||||
# If true, the depth image will be enabled
|
||||
enable_depth: true
|
||||
depth_qos: "default"
|
||||
depth_camera_info_qos: "default"
|
||||
# Width of the depth image. If 0, the default width will be used
|
||||
depth_width: 1280
|
||||
# Height of the depth image. If 0, the default height will be used
|
||||
depth_height: 800
|
||||
# If 0, the default FPS will be used
|
||||
depth_fps: 30
|
||||
# Format of the depth image.
|
||||
depth_format: "Y16"
|
||||
# If false, the depth scale will not be enabled
|
||||
enable_depth_scale: true
|
||||
|
||||
# Depth registration mode.
|
||||
depth_registration: false
|
||||
# The alignment mode to be used. Options are "HW" for hardware alignment and "SW" for software alignment
|
||||
align_mode: "HW"
|
||||
|
||||
# Gemini 2, Gemini 2 L, and Gemini 2 XL cameras support deep working mode switching
|
||||
# Specific camera deep working mode support types can be found in the deep mode comments.
|
||||
# Deep working mode support is as follows:{"Unbinned Dense Default","Unbinned Sparse Default","Binned Sparse Default","Obstacle Avoidance"}
|
||||
# Depth work mode. #For details, Please refer to the comments in SDK/include/libobsensor/Advanced.h for a detailed explanation.
|
||||
depth_work_mode: ""
|
||||
|
||||
# Configure the loading path of the deep filtering configuration file. By default, the deep filtering configuration file is located in the /config/depthfilter directory and is only supported by Gemini2.
|
||||
depth_filter_config: ""
|
||||
|
||||
filter:
|
||||
soft_filter:
|
||||
# If true, the soft filter will be enabled
|
||||
enable_soft_filter: true
|
||||
# soft_filter_max_diff, If -1, the default value will be used
|
||||
soft_filter_max_diff: -1
|
||||
# soft_filter_speckle_size, If -1, the default value will be used
|
||||
soft_filter_speckle_size: -1
|
||||
|
||||
noise_removal_filter:
|
||||
# If true, the noise removal filter will be enabled
|
||||
enable_noise_removal_filter: true
|
||||
|
||||
ir:
|
||||
# enable the ir camera stream
|
||||
enable_ir: true
|
||||
ir_qos: "default"
|
||||
ir_camera_info_qos: "default"
|
||||
# Width of the left IR image. If 0, the default width will be used
|
||||
ir_width: 640
|
||||
# Height of the left IR image. If 0, the default height will be used
|
||||
ir_height: 400
|
||||
# If 0, the default FPS will be used
|
||||
ir_fps: 15
|
||||
# Format of the left IR image.
|
||||
ir_format: "Y8"
|
||||
|
||||
ir_parameters:
|
||||
enable_ir_auto_exposure: true
|
||||
ir_ae_max_exposure: -1
|
||||
ir_exposure: -1
|
||||
ir_gain: -1
|
||||
ir_brightness: -1
|
||||
|
||||
imu:
|
||||
# If true, enable the IMU accelerometer data will be enabled
|
||||
enable_accel: false
|
||||
# Rate of the accelerometer
|
||||
accel_rate: "100hz"
|
||||
# Range of the accelerometer.
|
||||
accel_range: "4g"
|
||||
# If true, enable the IMU gyroscope data will be enabled
|
||||
enable_gyro: false
|
||||
# Rate of the gyroscope.
|
||||
gyro_rate: "100hz"
|
||||
# Range of the gyroscope.
|
||||
gyro_range: "1000dps"
|
||||
# enable_sync_output_accel_gyro
|
||||
enable_sync_output_accel_gyro: false
|
||||
liner_accel_cov: 0.01
|
||||
angular_vel_cov: 0.01
|
||||
|
||||
point_cloud:
|
||||
# If true, the depth point cloud will be enabled
|
||||
enable_point_cloud: true
|
||||
# enable color point cloud. {fase:disable, true:enable}
|
||||
enable_colored_point_cloud: false
|
||||
|
||||
advanced:
|
||||
enable_frame_sync: true
|
||||
enable_d2c_viewer: false
|
||||
|
||||
# If false, the hardware time will not be used
|
||||
use_hardware_time: true
|
||||
|
||||
@@ -4,95 +4,159 @@ orbbec_ros:
|
||||
camera_parameters:
|
||||
general:
|
||||
# Camera model. upport product models by referencing config/*.yaml
|
||||
camera_model: "gemini330_series"
|
||||
camera_model: "gemini330Lg_series"
|
||||
# Path to the configuration file. If empty, default parameters will be used
|
||||
config_file_path: "gemini330_series.yaml"
|
||||
config_file_path: "gemini330Lg_series.yaml"
|
||||
|
||||
deivce:
|
||||
# camera name, usually overwritten by launch file
|
||||
camera_name: "camera"
|
||||
# camera serial number, usually overwritten by launch file
|
||||
serial_number: ""
|
||||
# The USB port of the camera. This parameter is required when using multiple cameras.
|
||||
usb_port: ""
|
||||
# Number of devices. If multiple cameras are required, this parameter must be filled in launch file
|
||||
device_num: 1
|
||||
uvc_backend: "libuvc"
|
||||
product_id: ""
|
||||
# The delay time for reopening the device, in milliseconds. Usually, there is no need to modify by default.
|
||||
connection_delay: 10
|
||||
time_domain: "global"
|
||||
retry_on_usb3_detection_failure: false
|
||||
# If true, the heartbeat will be enabled
|
||||
enable_heartbeat: false
|
||||
# If true, the camera will be reset
|
||||
enable_hardware_reset: false
|
||||
# If true, the LDP will be enabled
|
||||
enable_ldp: true
|
||||
# The preset of the device. #For details, Please refer to the comments in SDK/include/libobsensor/Advanced.h for a detailed explanation
|
||||
# Predefined presets doc reference: docs/source/2_installation/package_description.md
|
||||
# Deep working mode support is as follows:{"Default","Hand","High Accuracy","High Density","Medium Density","Custom"}
|
||||
device_preset: "Default"
|
||||
|
||||
color:
|
||||
# If true, the color image will be enabled
|
||||
enable_color: true
|
||||
color_qos: "default"
|
||||
color_camera_info_qos: "default"
|
||||
# Width of the color image. If 0, the default width will be used
|
||||
color_width: 0
|
||||
# Height of the color image. If 0, the default height will be used
|
||||
color_height: 0
|
||||
# Fps of the color image. If 0, the default FPS will be used
|
||||
color_fps: 0
|
||||
color_format: "ANY"
|
||||
# Format of the color image. note: GMSL device dont't support MJPG format. need modify to YUYV format
|
||||
color_format: "YUYV"
|
||||
# enable auto exposure for the color image
|
||||
enable_color_auto_exposure: true
|
||||
# enable auto white balance for the color image
|
||||
enable_color_auto_white_balance: true
|
||||
color_white_balance: -1
|
||||
color_auto_ae:
|
||||
enable_color_auto_exposure: true
|
||||
color_ae_max_exposure: -1
|
||||
color_manual_ae:
|
||||
color_exposure: -1
|
||||
color_gain: -1
|
||||
color_brightness: -1
|
||||
# If true, the color image will be undistorted
|
||||
enable_color_undistortion: false
|
||||
|
||||
depth:
|
||||
# If true, the depth image will be enabled
|
||||
enable_depth: true
|
||||
depth_qos: "default"
|
||||
depth_camera_info_qos: "default"
|
||||
# Width of the depth image. If 0, the default width will be used
|
||||
depth_width: 0
|
||||
# Height of the depth image. If 0, the default height will be used
|
||||
depth_height: 0
|
||||
# Fps of the depth image. If 0, the default FPS will be used
|
||||
depth_fps: 0
|
||||
depth_format: "ANY"
|
||||
# default Format of the depth image.
|
||||
depth_format: "Y16"
|
||||
# If false, the depth scale will not be enabled
|
||||
enable_depth_scale: true
|
||||
# D2C Depth registration mode.
|
||||
# Enables hardware that aligns depth frames to color frames. This field is required when setting enable_colored_point_cloud to true
|
||||
depth_registration: true
|
||||
# The alignment mode to be used. Options are "HW" for hardware alignment and "SW" for software alignment
|
||||
align_mode: "SW"
|
||||
|
||||
laser:
|
||||
enable_laser: true
|
||||
# If true, the laser data will be enabled
|
||||
enable_laser: false
|
||||
# Laser On/Off mode.
|
||||
laser_on_off_mode: 0
|
||||
|
||||
filter:
|
||||
# -enable_decimation_filter
|
||||
enable_decimation_filter: false
|
||||
# -enable_hdr_merge
|
||||
enable_hdr_merge: false
|
||||
# -enable_sequence_id_filter
|
||||
enable_sequence_id_filter: false
|
||||
# -enable_threshold_filter
|
||||
enable_threshold_filter: false
|
||||
# -enable_noise_removal_filter
|
||||
enable_noise_removal_filter: true
|
||||
# -enable_spatial_filter
|
||||
enable_spatial_filter: false
|
||||
# -enable_temporal_filter
|
||||
enable_temporal_filter: false
|
||||
# -enable_hole_filling_filter
|
||||
enable_hole_filling_filter: false
|
||||
# -noise_removal_filter_min_diff
|
||||
noise_removal_filter_min_diff: 256
|
||||
# -noise_removal_filter_max_size
|
||||
noise_removal_filter_max_size: 80
|
||||
# -enable_soft_filter
|
||||
enable_soft_filter: true
|
||||
|
||||
leftir:
|
||||
enable_left_ir: false
|
||||
left_ir_qos: "default"
|
||||
left_ir_camera_info_qos: "default"
|
||||
left_ir_width: 0
|
||||
left_ir_height: 0
|
||||
left_ir_fps: 0
|
||||
left_ir_format: "ANY"
|
||||
# the left IR image will not be enabled
|
||||
enable_left_ir: true
|
||||
|
||||
rightir:
|
||||
enable_right_ir: false
|
||||
right_ir_camera_info_qos: "default"
|
||||
right_ir_width: 0
|
||||
right_ir_height: 0
|
||||
right_ir_fps: 0
|
||||
right_ir_format: "ANY"
|
||||
|
||||
ir_parameters:
|
||||
enable_ir_auto_exposure: true
|
||||
ir_ae_max_exposure: -1
|
||||
ir_exposure: -1
|
||||
ir_gain: -1
|
||||
ir_brightness: -1
|
||||
# the right IR image will not be enabled
|
||||
enable_right_ir: true
|
||||
|
||||
imu:
|
||||
# If true, the IMU accelerometer data will be enabled
|
||||
enable_accel: false
|
||||
# The frequency of the accelerometer can be selected as 1.5625Hz, 3.125Hz, 6.25Hz, 12.5Hz, 25Hz, 50Hz, 100Hz, 200Hz, 500Hz, 1kHz, 2kHz, 4kHz, 8kHz, 16kHz, 32kHz.
|
||||
# The specific value depends on the current camera.
|
||||
accel_rate: "200hz"
|
||||
# The range of the accelerometer, the optional values are 2g, 4g, 8g, 16g. The specific value depends on the current camera.
|
||||
accel_range: "4g"
|
||||
# If true, the IMU gyroscope data will be enabled
|
||||
enable_gyro: false
|
||||
# The frequency of the gyroscope can be selected as 1.5625hz, 3.125hz, 6.25hz, 12.5hz, 25hz, 50hz, 100hz, 200hz, 500hz, 1kHz, 2kHz, 4kHz, 8kHz, 16kHz, 32kHz.
|
||||
# The specific value depends on the current camera.
|
||||
gyro_rate: "200hz"
|
||||
# The range of the gyroscope, the optional values are 16dps, 31dps, 62dps, 125dps, 250dps, 500dps, 1000dps, 2000dps. The specific value depends on the current camera.
|
||||
gyro_range: "1000dps"
|
||||
# enable_sync_output_accel_gyro
|
||||
enable_sync_output_accel_gyro: false
|
||||
liner_accel_cov: 0.01
|
||||
angular_vel_cov: 0.01
|
||||
|
||||
point_cloud:
|
||||
enable_point_cloud: true
|
||||
# enable point cloud. {fase:disable, true:enable}
|
||||
enable_point_cloud: false
|
||||
# enable color point cloud. {fase:disable, true:enable}
|
||||
enable_colored_point_cloud: false
|
||||
|
||||
advanced:
|
||||
# If true, the extrinsics publish will be enabled
|
||||
enable_publish_extrinsic: false
|
||||
# If true, the frame synchronization will be enabled
|
||||
enable_frame_sync: true
|
||||
# Publish D2C superimposed image (only for testing).
|
||||
enable_d2c_viewer: false
|
||||
# If false, the hardware time will not be used, true:devicetime, false:systemtime
|
||||
use_hardware_time: true
|
||||
# the host time will be synchronized with the device time
|
||||
enable_sync_host_time: true
|
||||
|
||||
device_sync:
|
||||
# Device synchronization mode. supports: {1.FREE_RUN 2.STANDALONE 3.PRIMARY 4.SECONDARY 5.SECONDARY_SYNCED 6.SOFTWARE_TRIGGERING 7.HARDWARE_TRIGGERING}.
|
||||
# For details, Please refer to the OBMultiDeviceSyncMode-related comments in SDK/include/libobsensor/ObTypes.h for a detailed explanation of each mode.
|
||||
sync_mode: "STANDALONE"
|
||||
# The delay time of the depth image capture after receiving the capture command or trigger signal in microseconds.
|
||||
# For details, Please refer to the OBMultiDeviceSyncConfig-related comments in SDK/include/libobsensor/ObTypes.h
|
||||
depth_delay_us: 0
|
||||
# The delay time of the color image capture after receiving the capture command or trigger signal in microseconds.
|
||||
color_delay_us: 0
|
||||
# The delay time of the image capture after receiving the capture command or trigger signal in microseconds.
|
||||
trigger2image_delay_us: 0
|
||||
# Trigger signal output enable flag.
|
||||
trigger_out_enabled: true
|
||||
# The delay time of the trigger signal output after receiving the capture command or trigger signal in microseconds.
|
||||
trigger_out_delay_us: 0
|
||||
# The frame number of each stream after each trigger in triggering mode.
|
||||
frames_per_trigger: 2
|
||||
# software trigger period in ms
|
||||
software_trigger_period: 33
|
||||
|
||||
@@ -14,11 +14,13 @@ orbbec_ros:
|
||||
usb_port: ""
|
||||
device_num: 1
|
||||
uvc_backend: "libuvc"
|
||||
vendor_id: "0x2bc5"
|
||||
product_id: ""
|
||||
connection_delay: 10
|
||||
time_domain: "global"
|
||||
time_domain: "device"
|
||||
retry_on_usb3_detection_failure: false
|
||||
enable_heartbeat: false
|
||||
enable_hardware_reset: false
|
||||
enable_ldp: true
|
||||
device_preset: "Default"
|
||||
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
# config/*.yaml files are used to configure the camera parameters
|
||||
---
|
||||
orbbec_ros:
|
||||
multi_camera_parameters:
|
||||
|
||||
launch_device_camera1:
|
||||
config_file_path: "multicamera_test/gemini330_series_test1.yaml"
|
||||
# default period 0.0; unit: second
|
||||
period: 0.0
|
||||
camera_name: "camera1"
|
||||
usb_port: "2-2-4"
|
||||
device_num: "2"
|
||||
sync_mode: "standalone"
|
||||
|
||||
launch_device_camera2:
|
||||
config_file_path: "multicamera_test/gemini330_series_test2.yaml"
|
||||
# default period 0.0; unit: second
|
||||
period: 3.0
|
||||
camera_name: "camera2"
|
||||
usb_port: "2-1-2"
|
||||
device_num: "2"
|
||||
sync_mode: "standalone"
|
||||
@@ -0,0 +1,40 @@
|
||||
# config/*.yaml files are used to configure the camera parameters
|
||||
---
|
||||
orbbec_ros:
|
||||
multi_camera_parameters:
|
||||
|
||||
launch_device_camera1:
|
||||
config_file_path: "multicamera_test/gemini330_series_sync_front_camera.yaml"
|
||||
# default period 0.0; unit: second
|
||||
period: 3.0
|
||||
camera_name: "front_camera"
|
||||
usb_port: "2-5"
|
||||
device_num: "3"
|
||||
sync_mode: "hardware_triggering"
|
||||
|
||||
launch_device_camera2:
|
||||
config_file_path: "multicamera_test/gemini330_series_sync_left_camera.yaml"
|
||||
# default period 0.0; unit: second
|
||||
period: 0.0
|
||||
camera_name: "left_camera"
|
||||
usb_port: "2-1"
|
||||
device_num: "3"
|
||||
sync_mode: "hardware_triggering"
|
||||
|
||||
launch_device_camera3:
|
||||
config_file_path: "multicamera_test/gemini330_series_sync_rear_camera.yaml"
|
||||
# default period 0.0; unit: second
|
||||
period: 0.0
|
||||
camera_name: "rear_camera"
|
||||
usb_port: "2-3"
|
||||
device_num: "3"
|
||||
sync_mode: "hardware_triggering"
|
||||
|
||||
launch_device_camera4:
|
||||
config_file_path: "multicamera_test/gemini330_series_sync_right_camera.yaml"
|
||||
# default period 0.0; unit: second
|
||||
period: 0.0
|
||||
camera_name: "right_camera"
|
||||
usb_port: "2-7"
|
||||
device_num: "3"
|
||||
sync_mode: "hardware_triggering"
|
||||
@@ -0,0 +1,161 @@
|
||||
# config/*.yaml files are used to configure the camera parameters
|
||||
---
|
||||
orbbec_ros:
|
||||
camera_parameters:
|
||||
general:
|
||||
# Camera model. upport product models by referencing config/*.yaml
|
||||
camera_model: "gemini330_series"
|
||||
# Path to the configuration file. If empty, default parameters will be used
|
||||
config_file_path: "gemini330_series.yaml"
|
||||
|
||||
deivce:
|
||||
# camera name, usually overwritten by launch file
|
||||
camera_name: "front_camera"
|
||||
# camera serial number, usually overwritten by launch file
|
||||
serial_number: ""
|
||||
# The USB port of the camera. This parameter is required when using multiple cameras.
|
||||
usb_port: "2-5"
|
||||
# Number of devices. If multiple cameras are required, this parameter must be filled in launch file
|
||||
device_num: 3
|
||||
# The delay time for reopening the device, in milliseconds. Usually, there is no need to modify by default.
|
||||
connection_delay: 10
|
||||
# If true, the heartbeat will be enabled
|
||||
enable_heartbeat: false
|
||||
# If true, the camera will be reset
|
||||
enable_hardware_reset: false
|
||||
# If true, the LDP will be enabled
|
||||
enable_ldp: true
|
||||
# The preset of the device. #For details, Please refer to the comments in SDK/include/libobsensor/Advanced.h for a detailed explanation
|
||||
# Predefined presets doc reference: docs/source/2_installation/package_description.md
|
||||
# Deep working mode support is as follows:{"Default","Hand","High Accuracy","High Density","Medium Density","Custom"}
|
||||
device_preset: "Default"
|
||||
|
||||
color:
|
||||
# If true, the color image will be enabled
|
||||
enable_color: true
|
||||
# Width of the color image. If 0, the default width will be used
|
||||
color_width: 0
|
||||
# Height of the color image. If 0, the default height will be used
|
||||
color_height: 0
|
||||
# Fps of the color image. If 0, the default FPS will be used
|
||||
color_fps: 0
|
||||
# default Format of the color image.
|
||||
color_format: "MJPG"
|
||||
# enable auto exposure for the color image
|
||||
enable_color_auto_exposure: true
|
||||
# enable auto white balance for the color image
|
||||
enable_color_auto_white_balance: true
|
||||
# If true, the color image will be undistorted
|
||||
enable_color_undistortion: false
|
||||
|
||||
depth:
|
||||
# If true, the depth image will be enabled
|
||||
enable_depth: true
|
||||
# Width of the depth image. If 0, the default width will be used
|
||||
depth_width: 0
|
||||
# Height of the depth image. If 0, the default height will be used
|
||||
depth_height: 0
|
||||
# Fps of the depth image. If 0, the default FPS will be used
|
||||
depth_fps: 0
|
||||
# default Format of the depth image.
|
||||
depth_format: "Y16"
|
||||
# If false, the depth scale will not be enabled
|
||||
enable_depth_scale: true
|
||||
|
||||
# D2C Depth registration mode.
|
||||
# Enables hardware that aligns depth frames to color frames. This field is required when setting enable_colored_point_cloud to true
|
||||
depth_registration: true
|
||||
# The alignment mode to be used. Options are "HW" for hardware alignment and "SW" for software alignment
|
||||
align_mode: "SW"
|
||||
|
||||
laser:
|
||||
# Whether to enable the laser. Default value is true
|
||||
enable_laser: false
|
||||
# Laser Switch Alternate Mode, 0: Off, 1: On-Off Alternate, 2: Off-On Alternate. Default value is 0.
|
||||
laser_on_off_mode: 0
|
||||
|
||||
filter:
|
||||
# -enable_decimation_filter
|
||||
enable_decimation_filter: false
|
||||
# -enable_hdr_merge
|
||||
enable_hdr_merge: false
|
||||
# -enable_sequence_id_filter
|
||||
enable_sequence_id_filter: false
|
||||
# -enable_threshold_filter
|
||||
enable_threshold_filter: false
|
||||
# -enable_noise_removal_filter
|
||||
enable_noise_removal_filter: true
|
||||
# -enable_spatial_filter
|
||||
enable_spatial_filter: false
|
||||
# -enable_temporal_filter
|
||||
enable_temporal_filter: false
|
||||
# -enable_hole_filling_filter
|
||||
enable_hole_filling_filter: false
|
||||
# -noise_removal_filter_min_diff
|
||||
noise_removal_filter_min_diff: 256
|
||||
# -noise_removal_filter_max_size
|
||||
noise_removal_filter_max_size: 80
|
||||
# -enable_soft_filter
|
||||
enable_soft_filter: true
|
||||
|
||||
leftir:
|
||||
# the left IR image will not be enabled
|
||||
enable_left_ir: true
|
||||
|
||||
rightir:
|
||||
# the right IR image will not be enabled
|
||||
enable_right_ir: true
|
||||
|
||||
imu:
|
||||
# If true, the IMU accelerometer data will be enabled
|
||||
enable_accel: false
|
||||
# The frequency of the accelerometer can be selected as 1.5625Hz, 3.125Hz, 6.25Hz, 12.5Hz, 25Hz, 50Hz, 100Hz, 200Hz, 500Hz, 1kHz, 2kHz, 4kHz, 8kHz, 16kHz, 32kHz.
|
||||
# The specific value depends on the current camera.
|
||||
accel_rate: "200hz"
|
||||
# The range of the accelerometer, the optional values are 2g, 4g, 8g, 16g. The specific value depends on the current camera.
|
||||
accel_range: "4g"
|
||||
# If true, the IMU gyroscope data will be enabled
|
||||
enable_gyro: false
|
||||
# The frequency of the gyroscope can be selected as 1.5625hz, 3.125hz, 6.25hz, 12.5hz, 25hz, 50hz, 100hz, 200hz, 500hz, 1kHz, 2kHz, 4kHz, 8kHz, 16kHz, 32kHz.
|
||||
# The specific value depends on the current camera.
|
||||
gyro_rate: "200hz"
|
||||
# The range of the gyroscope, the optional values are 16dps, 31dps, 62dps, 125dps, 250dps, 500dps, 1000dps, 2000dps. The specific value depends on the current camera.
|
||||
gyro_range: "1000dps"
|
||||
# enable_sync_output_accel_gyro
|
||||
enable_sync_output_accel_gyro: false
|
||||
|
||||
point_cloud:
|
||||
# enable point cloud. {fase:disable, true:enable}
|
||||
enable_point_cloud: false
|
||||
|
||||
advanced:
|
||||
# If true, the extrinsics publish will be enabled
|
||||
enable_publish_extrinsic: false
|
||||
# If true, the frame synchronization will be enabled
|
||||
enable_frame_sync: true
|
||||
# Publish D2C superimposed image (only for testing).
|
||||
enable_d2c_viewer: false
|
||||
# If false, the hardware time will not be used, true:devicetime, false:systemtime
|
||||
use_hardware_time: true
|
||||
# the host time will be synchronized with the device time
|
||||
enable_sync_host_time: true
|
||||
|
||||
device_sync:
|
||||
# Device synchronization mode. supports: {1.FREE_RUN 2.STANDALONE 3.PRIMARY 4.SECONDARY 5.SECONDARY_SYNCED 6.SOFTWARE_TRIGGERING 7.HARDWARE_TRIGGERING}.
|
||||
# For details, Please refer to the OBMultiDeviceSyncMode-related comments in SDK/include/libobsensor/ObTypes.h for a detailed explanation of each mode.
|
||||
sync_mode: "SECONDARY_SYNCED"
|
||||
# The delay time of the depth image capture after receiving the capture command or trigger signal in microseconds.
|
||||
# For details, Please refer to the OBMultiDeviceSyncConfig-related comments in SDK/include/libobsensor/ObTypes.h
|
||||
depth_delay_us: 0
|
||||
# The delay time of the color image capture after receiving the capture command or trigger signal in microseconds.
|
||||
color_delay_us: 0
|
||||
# The delay time of the image capture after receiving the capture command or trigger signal in microseconds.
|
||||
trigger2image_delay_us: 0
|
||||
# Trigger signal output enable flag.
|
||||
trigger_out_enabled: true
|
||||
# The delay time of the trigger signal output after receiving the capture command or trigger signal in microseconds.
|
||||
trigger_out_delay_us: 0
|
||||
# The frame number of each stream after each trigger in triggering mode.
|
||||
frames_per_trigger: 2
|
||||
# software trigger period in ms
|
||||
software_trigger_period: 33
|
||||
@@ -0,0 +1,161 @@
|
||||
# config/*.yaml files are used to configure the camera parameters
|
||||
---
|
||||
orbbec_ros:
|
||||
camera_parameters:
|
||||
general:
|
||||
# Camera model. upport product models by referencing config/*.yaml
|
||||
camera_model: "gemini330_series"
|
||||
# Path to the configuration file. If empty, default parameters will be used
|
||||
config_file_path: "gemini330_series.yaml"
|
||||
|
||||
deivce:
|
||||
# camera name, usually overwritten by launch file
|
||||
camera_name: "left_camera"
|
||||
# camera serial number, usually overwritten by launch file
|
||||
serial_number: ""
|
||||
# The USB port of the camera. This parameter is required when using multiple cameras.
|
||||
usb_port: "2-1"
|
||||
# Number of devices. If multiple cameras are required, this parameter must be filled in launch file
|
||||
device_num: 3
|
||||
# The delay time for reopening the device, in milliseconds. Usually, there is no need to modify by default.
|
||||
connection_delay: 10
|
||||
# If true, the heartbeat will be enabled
|
||||
enable_heartbeat: false
|
||||
# If true, the camera will be reset
|
||||
enable_hardware_reset: false
|
||||
# If true, the LDP will be enabled
|
||||
enable_ldp: true
|
||||
# The preset of the device. #For details, Please refer to the comments in SDK/include/libobsensor/Advanced.h for a detailed explanation
|
||||
# Predefined presets doc reference: docs/source/2_installation/package_description.md
|
||||
# Deep working mode support is as follows:{"Default","Hand","High Accuracy","High Density","Medium Density","Custom"}
|
||||
device_preset: "Default"
|
||||
|
||||
color:
|
||||
# If true, the color image will be enabled
|
||||
enable_color: true
|
||||
# Width of the color image. If 0, the default width will be used
|
||||
color_width: 0
|
||||
# Height of the color image. If 0, the default height will be used
|
||||
color_height: 0
|
||||
# Fps of the color image. If 0, the default FPS will be used
|
||||
color_fps: 0
|
||||
# default Format of the color image.
|
||||
color_format: "MJPG"
|
||||
# enable auto exposure for the color image
|
||||
enable_color_auto_exposure: true
|
||||
# enable auto white balance for the color image
|
||||
enable_color_auto_white_balance: true
|
||||
# If true, the color image will be undistorted
|
||||
enable_color_undistortion: false
|
||||
|
||||
depth:
|
||||
# If true, the depth image will be enabled
|
||||
enable_depth: true
|
||||
# Width of the depth image. If 0, the default width will be used
|
||||
depth_width: 0
|
||||
# Height of the depth image. If 0, the default height will be used
|
||||
depth_height: 0
|
||||
# Fps of the depth image. If 0, the default FPS will be used
|
||||
depth_fps: 0
|
||||
# default Format of the depth image.
|
||||
depth_format: "Y16"
|
||||
# If false, the depth scale will not be enabled
|
||||
enable_depth_scale: true
|
||||
|
||||
# D2C Depth registration mode.
|
||||
# Enables hardware that aligns depth frames to color frames. This field is required when setting enable_colored_point_cloud to true
|
||||
depth_registration: true
|
||||
# The alignment mode to be used. Options are "HW" for hardware alignment and "SW" for software alignment
|
||||
align_mode: "SW"
|
||||
|
||||
laser:
|
||||
# Whether to enable the laser. Default value is true
|
||||
enable_laser: false
|
||||
# Laser Switch Alternate Mode, 0: Off, 1: On-Off Alternate, 2: Off-On Alternate. Default value is 0.
|
||||
laser_on_off_mode: 0
|
||||
|
||||
filter:
|
||||
# -enable_decimation_filter
|
||||
enable_decimation_filter: false
|
||||
# -enable_hdr_merge
|
||||
enable_hdr_merge: false
|
||||
# -enable_sequence_id_filter
|
||||
enable_sequence_id_filter: false
|
||||
# -enable_threshold_filter
|
||||
enable_threshold_filter: false
|
||||
# -enable_noise_removal_filter
|
||||
enable_noise_removal_filter: true
|
||||
# -enable_spatial_filter
|
||||
enable_spatial_filter: false
|
||||
# -enable_temporal_filter
|
||||
enable_temporal_filter: false
|
||||
# -enable_hole_filling_filter
|
||||
enable_hole_filling_filter: false
|
||||
# -noise_removal_filter_min_diff
|
||||
noise_removal_filter_min_diff: 256
|
||||
# -noise_removal_filter_max_size
|
||||
noise_removal_filter_max_size: 80
|
||||
# -enable_soft_filter
|
||||
enable_soft_filter: true
|
||||
|
||||
leftir:
|
||||
# the left IR image will not be enabled
|
||||
enable_left_ir: true
|
||||
|
||||
rightir:
|
||||
# the right IR image will not be enabled
|
||||
enable_right_ir: true
|
||||
|
||||
imu:
|
||||
# If true, the IMU accelerometer data will be enabled
|
||||
enable_accel: false
|
||||
# The frequency of the accelerometer can be selected as 1.5625Hz, 3.125Hz, 6.25Hz, 12.5Hz, 25Hz, 50Hz, 100Hz, 200Hz, 500Hz, 1kHz, 2kHz, 4kHz, 8kHz, 16kHz, 32kHz.
|
||||
# The specific value depends on the current camera.
|
||||
accel_rate: "200hz"
|
||||
# The range of the accelerometer, the optional values are 2g, 4g, 8g, 16g. The specific value depends on the current camera.
|
||||
accel_range: "4g"
|
||||
# If true, the IMU gyroscope data will be enabled
|
||||
enable_gyro: false
|
||||
# The frequency of the gyroscope can be selected as 1.5625hz, 3.125hz, 6.25hz, 12.5hz, 25hz, 50hz, 100hz, 200hz, 500hz, 1kHz, 2kHz, 4kHz, 8kHz, 16kHz, 32kHz.
|
||||
# The specific value depends on the current camera.
|
||||
gyro_rate: "200hz"
|
||||
# The range of the gyroscope, the optional values are 16dps, 31dps, 62dps, 125dps, 250dps, 500dps, 1000dps, 2000dps. The specific value depends on the current camera.
|
||||
gyro_range: "1000dps"
|
||||
# enable_sync_output_accel_gyro
|
||||
enable_sync_output_accel_gyro: false
|
||||
|
||||
point_cloud:
|
||||
# enable point cloud. {fase:disable, true:enable}
|
||||
enable_point_cloud: false
|
||||
|
||||
advanced:
|
||||
# If true, the extrinsics publish will be enabled
|
||||
enable_publish_extrinsic: false
|
||||
# If true, the frame synchronization will be enabled
|
||||
enable_frame_sync: true
|
||||
# Publish D2C superimposed image (only for testing).
|
||||
enable_d2c_viewer: false
|
||||
# If false, the hardware time will not be used, true:devicetime, false:systemtime
|
||||
use_hardware_time: true
|
||||
# the host time will be synchronized with the device time
|
||||
enable_sync_host_time: true
|
||||
|
||||
device_sync:
|
||||
# Device synchronization mode. supports: {1.FREE_RUN 2.STANDALONE 3.PRIMARY 4.SECONDARY 5.SECONDARY_SYNCED 6.SOFTWARE_TRIGGERING 7.HARDWARE_TRIGGERING}.
|
||||
# For details, Please refer to the OBMultiDeviceSyncMode-related comments in SDK/include/libobsensor/ObTypes.h for a detailed explanation of each mode.
|
||||
sync_mode: "SECONDARY_SYNCED"
|
||||
# The delay time of the depth image capture after receiving the capture command or trigger signal in microseconds.
|
||||
# For details, Please refer to the OBMultiDeviceSyncConfig-related comments in SDK/include/libobsensor/ObTypes.h
|
||||
depth_delay_us: 0
|
||||
# The delay time of the color image capture after receiving the capture command or trigger signal in microseconds.
|
||||
color_delay_us: 0
|
||||
# The delay time of the image capture after receiving the capture command or trigger signal in microseconds.
|
||||
trigger2image_delay_us: 0
|
||||
# Trigger signal output enable flag.
|
||||
trigger_out_enabled: true
|
||||
# The delay time of the trigger signal output after receiving the capture command or trigger signal in microseconds.
|
||||
trigger_out_delay_us: 0
|
||||
# The frame number of each stream after each trigger in triggering mode.
|
||||
frames_per_trigger: 2
|
||||
# software trigger period in ms
|
||||
software_trigger_period: 33
|
||||
@@ -0,0 +1,161 @@
|
||||
# config/*.yaml files are used to configure the camera parameters
|
||||
---
|
||||
orbbec_ros:
|
||||
camera_parameters:
|
||||
general:
|
||||
# Camera model. upport product models by referencing config/*.yaml
|
||||
camera_model: "gemini330_series"
|
||||
# Path to the configuration file. If empty, default parameters will be used
|
||||
config_file_path: "gemini330_series.yaml"
|
||||
|
||||
deivce:
|
||||
# camera name, usually overwritten by launch file
|
||||
camera_name: "rear_camera"
|
||||
# camera serial number, usually overwritten by launch file
|
||||
serial_number: ""
|
||||
# The USB port of the camera. This parameter is required when using multiple cameras.
|
||||
usb_port: "2-3"
|
||||
# Number of devices. If multiple cameras are required, this parameter must be filled in launch file
|
||||
device_num: 3
|
||||
# The delay time for reopening the device, in milliseconds. Usually, there is no need to modify by default.
|
||||
connection_delay: 10
|
||||
# If true, the heartbeat will be enabled
|
||||
enable_heartbeat: false
|
||||
# If true, the camera will be reset
|
||||
enable_hardware_reset: false
|
||||
# If true, the LDP will be enabled
|
||||
enable_ldp: true
|
||||
# The preset of the device. #For details, Please refer to the comments in SDK/include/libobsensor/Advanced.h for a detailed explanation
|
||||
# Predefined presets doc reference: docs/source/2_installation/package_description.md
|
||||
# Deep working mode support is as follows:{"Default","Hand","High Accuracy","High Density","Medium Density","Custom"}
|
||||
device_preset: "Default"
|
||||
|
||||
color:
|
||||
# If true, the color image will be enabled
|
||||
enable_color: true
|
||||
# Width of the color image. If 0, the default width will be used
|
||||
color_width: 0
|
||||
# Height of the color image. If 0, the default height will be used
|
||||
color_height: 0
|
||||
# Fps of the color image. If 0, the default FPS will be used
|
||||
color_fps: 0
|
||||
# default Format of the color image.
|
||||
color_format: "MJPG"
|
||||
# enable auto exposure for the color image
|
||||
enable_color_auto_exposure: true
|
||||
# enable auto white balance for the color image
|
||||
enable_color_auto_white_balance: true
|
||||
# If true, the color image will be undistorted
|
||||
enable_color_undistortion: false
|
||||
|
||||
depth:
|
||||
# If true, the depth image will be enabled
|
||||
enable_depth: true
|
||||
# Width of the depth image. If 0, the default width will be used
|
||||
depth_width: 0
|
||||
# Height of the depth image. If 0, the default height will be used
|
||||
depth_height: 0
|
||||
# Fps of the depth image. If 0, the default FPS will be used
|
||||
depth_fps: 0
|
||||
# default Format of the depth image.
|
||||
depth_format: "Y16"
|
||||
# If false, the depth scale will not be enabled
|
||||
enable_depth_scale: true
|
||||
|
||||
# D2C Depth registration mode.
|
||||
# Enables hardware that aligns depth frames to color frames. This field is required when setting enable_colored_point_cloud to true
|
||||
depth_registration: true
|
||||
# The alignment mode to be used. Options are "HW" for hardware alignment and "SW" for software alignment
|
||||
align_mode: "SW"
|
||||
|
||||
laser:
|
||||
# Whether to enable the laser. Default value is true
|
||||
enable_laser: false
|
||||
# Laser Switch Alternate Mode, 0: Off, 1: On-Off Alternate, 2: Off-On Alternate. Default value is 0.
|
||||
laser_on_off_mode: 0
|
||||
|
||||
filter:
|
||||
# -enable_decimation_filter
|
||||
enable_decimation_filter: false
|
||||
# -enable_hdr_merge
|
||||
enable_hdr_merge: false
|
||||
# -enable_sequence_id_filter
|
||||
enable_sequence_id_filter: false
|
||||
# -enable_threshold_filter
|
||||
enable_threshold_filter: false
|
||||
# -enable_noise_removal_filter
|
||||
enable_noise_removal_filter: true
|
||||
# -enable_spatial_filter
|
||||
enable_spatial_filter: false
|
||||
# -enable_temporal_filter
|
||||
enable_temporal_filter: false
|
||||
# -enable_hole_filling_filter
|
||||
enable_hole_filling_filter: false
|
||||
# -noise_removal_filter_min_diff
|
||||
noise_removal_filter_min_diff: 256
|
||||
# -noise_removal_filter_max_size
|
||||
noise_removal_filter_max_size: 80
|
||||
# -enable_soft_filter
|
||||
enable_soft_filter: true
|
||||
|
||||
leftir:
|
||||
# the left IR image will not be enabled
|
||||
enable_left_ir: true
|
||||
|
||||
rightir:
|
||||
# the right IR image will not be enabled
|
||||
enable_right_ir: true
|
||||
|
||||
imu:
|
||||
# If true, the IMU accelerometer data will be enabled
|
||||
enable_accel: false
|
||||
# The frequency of the accelerometer can be selected as 1.5625Hz, 3.125Hz, 6.25Hz, 12.5Hz, 25Hz, 50Hz, 100Hz, 200Hz, 500Hz, 1kHz, 2kHz, 4kHz, 8kHz, 16kHz, 32kHz.
|
||||
# The specific value depends on the current camera.
|
||||
accel_rate: "200hz"
|
||||
# The range of the accelerometer, the optional values are 2g, 4g, 8g, 16g. The specific value depends on the current camera.
|
||||
accel_range: "4g"
|
||||
# If true, the IMU gyroscope data will be enabled
|
||||
enable_gyro: false
|
||||
# The frequency of the gyroscope can be selected as 1.5625hz, 3.125hz, 6.25hz, 12.5hz, 25hz, 50hz, 100hz, 200hz, 500hz, 1kHz, 2kHz, 4kHz, 8kHz, 16kHz, 32kHz.
|
||||
# The specific value depends on the current camera.
|
||||
gyro_rate: "200hz"
|
||||
# The range of the gyroscope, the optional values are 16dps, 31dps, 62dps, 125dps, 250dps, 500dps, 1000dps, 2000dps. The specific value depends on the current camera.
|
||||
gyro_range: "1000dps"
|
||||
# enable_sync_output_accel_gyro
|
||||
enable_sync_output_accel_gyro: false
|
||||
|
||||
point_cloud:
|
||||
# enable point cloud. {fase:disable, true:enable}
|
||||
enable_point_cloud: false
|
||||
|
||||
advanced:
|
||||
# If true, the extrinsics publish will be enabled
|
||||
enable_publish_extrinsic: false
|
||||
# If true, the frame synchronization will be enabled
|
||||
enable_frame_sync: true
|
||||
# Publish D2C superimposed image (only for testing).
|
||||
enable_d2c_viewer: false
|
||||
# If false, the hardware time will not be used, true:devicetime, false:systemtime
|
||||
use_hardware_time: true
|
||||
# the host time will be synchronized with the device time
|
||||
enable_sync_host_time: true
|
||||
|
||||
device_sync:
|
||||
# Device synchronization mode. supports: {1.FREE_RUN 2.STANDALONE 3.PRIMARY 4.SECONDARY 5.SECONDARY_SYNCED 6.SOFTWARE_TRIGGERING 7.HARDWARE_TRIGGERING}.
|
||||
# For details, Please refer to the OBMultiDeviceSyncMode-related comments in SDK/include/libobsensor/ObTypes.h for a detailed explanation of each mode.
|
||||
sync_mode: "SECONDARY_SYNCED"
|
||||
# The delay time of the depth image capture after receiving the capture command or trigger signal in microseconds.
|
||||
# For details, Please refer to the OBMultiDeviceSyncConfig-related comments in SDK/include/libobsensor/ObTypes.h
|
||||
depth_delay_us: 0
|
||||
# The delay time of the color image capture after receiving the capture command or trigger signal in microseconds.
|
||||
color_delay_us: 0
|
||||
# The delay time of the image capture after receiving the capture command or trigger signal in microseconds.
|
||||
trigger2image_delay_us: 0
|
||||
# Trigger signal output enable flag.
|
||||
trigger_out_enabled: true
|
||||
# The delay time of the trigger signal output after receiving the capture command or trigger signal in microseconds.
|
||||
trigger_out_delay_us: 0
|
||||
# The frame number of each stream after each trigger in triggering mode.
|
||||
frames_per_trigger: 2
|
||||
# software trigger period in ms
|
||||
software_trigger_period: 33
|
||||
@@ -0,0 +1,161 @@
|
||||
# config/*.yaml files are used to configure the camera parameters
|
||||
---
|
||||
orbbec_ros:
|
||||
camera_parameters:
|
||||
general:
|
||||
# Camera model. upport product models by referencing config/*.yaml
|
||||
camera_model: "gemini330_series"
|
||||
# Path to the configuration file. If empty, default parameters will be used
|
||||
config_file_path: "gemini330_series.yaml"
|
||||
|
||||
deivce:
|
||||
# camera name, usually overwritten by launch file
|
||||
camera_name: "right_camera"
|
||||
# camera serial number, usually overwritten by launch file
|
||||
serial_number: ""
|
||||
# The USB port of the camera. This parameter is required when using multiple cameras.
|
||||
usb_port: "2-7"
|
||||
# Number of devices. If multiple cameras are required, this parameter must be filled in launch file
|
||||
device_num: 3
|
||||
# The delay time for reopening the device, in milliseconds. Usually, there is no need to modify by default.
|
||||
connection_delay: 10
|
||||
# If true, the heartbeat will be enabled
|
||||
enable_heartbeat: false
|
||||
# If true, the camera will be reset
|
||||
enable_hardware_reset: false
|
||||
# If true, the LDP will be enabled
|
||||
enable_ldp: true
|
||||
# The preset of the device. #For details, Please refer to the comments in SDK/include/libobsensor/Advanced.h for a detailed explanation
|
||||
# Predefined presets doc reference: docs/source/2_installation/package_description.md
|
||||
# Deep working mode support is as follows:{"Default","Hand","High Accuracy","High Density","Medium Density","Custom"}
|
||||
device_preset: "Default"
|
||||
|
||||
color:
|
||||
# If true, the color image will be enabled
|
||||
enable_color: true
|
||||
# Width of the color image. If 0, the default width will be used
|
||||
color_width: 0
|
||||
# Height of the color image. If 0, the default height will be used
|
||||
color_height: 0
|
||||
# Fps of the color image. If 0, the default FPS will be used
|
||||
color_fps: 0
|
||||
# default Format of the color image.
|
||||
color_format: "MJPG"
|
||||
# enable auto exposure for the color image
|
||||
enable_color_auto_exposure: true
|
||||
# enable auto white balance for the color image
|
||||
enable_color_auto_white_balance: true
|
||||
# If true, the color image will be undistorted
|
||||
enable_color_undistortion: false
|
||||
|
||||
depth:
|
||||
# If true, the depth image will be enabled
|
||||
enable_depth: true
|
||||
# Width of the depth image. If 0, the default width will be used
|
||||
depth_width: 0
|
||||
# Height of the depth image. If 0, the default height will be used
|
||||
depth_height: 0
|
||||
# Fps of the depth image. If 0, the default FPS will be used
|
||||
depth_fps: 0
|
||||
# default Format of the depth image.
|
||||
depth_format: "Y16"
|
||||
# If false, the depth scale will not be enabled
|
||||
enable_depth_scale: true
|
||||
|
||||
# D2C Depth registration mode.
|
||||
# Enables hardware that aligns depth frames to color frames. This field is required when setting enable_colored_point_cloud to true
|
||||
depth_registration: true
|
||||
# The alignment mode to be used. Options are "HW" for hardware alignment and "SW" for software alignment
|
||||
align_mode: "SW"
|
||||
|
||||
laser:
|
||||
# Whether to enable the laser. Default value is true
|
||||
enable_laser: false
|
||||
# Laser Switch Alternate Mode, 0: Off, 1: On-Off Alternate, 2: Off-On Alternate. Default value is 0.
|
||||
laser_on_off_mode: 0
|
||||
|
||||
filter:
|
||||
# -enable_decimation_filter
|
||||
enable_decimation_filter: false
|
||||
# -enable_hdr_merge
|
||||
enable_hdr_merge: false
|
||||
# -enable_sequence_id_filter
|
||||
enable_sequence_id_filter: false
|
||||
# -enable_threshold_filter
|
||||
enable_threshold_filter: false
|
||||
# -enable_noise_removal_filter
|
||||
enable_noise_removal_filter: true
|
||||
# -enable_spatial_filter
|
||||
enable_spatial_filter: false
|
||||
# -enable_temporal_filter
|
||||
enable_temporal_filter: false
|
||||
# -enable_hole_filling_filter
|
||||
enable_hole_filling_filter: false
|
||||
# -noise_removal_filter_min_diff
|
||||
noise_removal_filter_min_diff: 256
|
||||
# -noise_removal_filter_max_size
|
||||
noise_removal_filter_max_size: 80
|
||||
# -enable_soft_filter
|
||||
enable_soft_filter: true
|
||||
|
||||
leftir:
|
||||
# the left IR image will not be enabled
|
||||
enable_left_ir: true
|
||||
|
||||
rightir:
|
||||
# the right IR image will not be enabled
|
||||
enable_right_ir: true
|
||||
|
||||
imu:
|
||||
# If true, the IMU accelerometer data will be enabled
|
||||
enable_accel: false
|
||||
# The frequency of the accelerometer can be selected as 1.5625Hz, 3.125Hz, 6.25Hz, 12.5Hz, 25Hz, 50Hz, 100Hz, 200Hz, 500Hz, 1kHz, 2kHz, 4kHz, 8kHz, 16kHz, 32kHz.
|
||||
# The specific value depends on the current camera.
|
||||
accel_rate: "200hz"
|
||||
# The range of the accelerometer, the optional values are 2g, 4g, 8g, 16g. The specific value depends on the current camera.
|
||||
accel_range: "4g"
|
||||
# If true, the IMU gyroscope data will be enabled
|
||||
enable_gyro: false
|
||||
# The frequency of the gyroscope can be selected as 1.5625hz, 3.125hz, 6.25hz, 12.5hz, 25hz, 50hz, 100hz, 200hz, 500hz, 1kHz, 2kHz, 4kHz, 8kHz, 16kHz, 32kHz.
|
||||
# The specific value depends on the current camera.
|
||||
gyro_rate: "200hz"
|
||||
# The range of the gyroscope, the optional values are 16dps, 31dps, 62dps, 125dps, 250dps, 500dps, 1000dps, 2000dps. The specific value depends on the current camera.
|
||||
gyro_range: "1000dps"
|
||||
# enable_sync_output_accel_gyro
|
||||
enable_sync_output_accel_gyro: false
|
||||
|
||||
point_cloud:
|
||||
# enable point cloud. {fase:disable, true:enable}
|
||||
enable_point_cloud: false
|
||||
|
||||
advanced:
|
||||
# If true, the extrinsics publish will be enabled
|
||||
enable_publish_extrinsic: false
|
||||
# If true, the frame synchronization will be enabled
|
||||
enable_frame_sync: true
|
||||
# Publish D2C superimposed image (only for testing).
|
||||
enable_d2c_viewer: false
|
||||
# If false, the hardware time will not be used, true:devicetime, false:systemtime
|
||||
use_hardware_time: true
|
||||
# the host time will be synchronized with the device time
|
||||
enable_sync_host_time: true
|
||||
|
||||
device_sync:
|
||||
# Device synchronization mode. supports: {1.FREE_RUN 2.STANDALONE 3.PRIMARY 4.SECONDARY 5.SECONDARY_SYNCED 6.SOFTWARE_TRIGGERING 7.HARDWARE_TRIGGERING}.
|
||||
# For details, Please refer to the OBMultiDeviceSyncMode-related comments in SDK/include/libobsensor/ObTypes.h for a detailed explanation of each mode.
|
||||
sync_mode: "SECONDARY_SYNCED"
|
||||
# The delay time of the depth image capture after receiving the capture command or trigger signal in microseconds.
|
||||
# For details, Please refer to the OBMultiDeviceSyncConfig-related comments in SDK/include/libobsensor/ObTypes.h
|
||||
depth_delay_us: 0
|
||||
# The delay time of the color image capture after receiving the capture command or trigger signal in microseconds.
|
||||
color_delay_us: 0
|
||||
# The delay time of the image capture after receiving the capture command or trigger signal in microseconds.
|
||||
trigger2image_delay_us: 0
|
||||
# Trigger signal output enable flag.
|
||||
trigger_out_enabled: true
|
||||
# The delay time of the trigger signal output after receiving the capture command or trigger signal in microseconds.
|
||||
trigger_out_delay_us: 0
|
||||
# The frame number of each stream after each trigger in triggering mode.
|
||||
frames_per_trigger: 2
|
||||
# software trigger period in ms
|
||||
software_trigger_period: 33
|
||||
@@ -0,0 +1,161 @@
|
||||
# config/*.yaml files are used to configure the camera parameters
|
||||
---
|
||||
orbbec_ros:
|
||||
camera_parameters:
|
||||
general:
|
||||
# Camera model. upport product models by referencing config/*.yaml
|
||||
camera_model: "gemini330_series"
|
||||
# Path to the configuration file. If empty, default parameters will be used
|
||||
config_file_path: "gemini330_series.yaml"
|
||||
|
||||
deivce:
|
||||
# camera name, usually overwritten by launch file
|
||||
camera_name: "camera_test1"
|
||||
# camera serial number, usually overwritten by launch file
|
||||
serial_number: ""
|
||||
# The USB port of the camera. This parameter is required when using multiple cameras.
|
||||
usb_port: "2-2-3"
|
||||
# Number of devices. If multiple cameras are required, this parameter must be filled in launch file
|
||||
device_num: 2
|
||||
# The delay time for reopening the device, in milliseconds. Usually, there is no need to modify by default.
|
||||
connection_delay: 10
|
||||
# If true, the heartbeat will be enabled
|
||||
enable_heartbeat: false
|
||||
# If true, the camera will be reset
|
||||
enable_hardware_reset: false
|
||||
# If true, the LDP will be enabled
|
||||
enable_ldp: true
|
||||
# The preset of the device. #For details, Please refer to the comments in SDK/include/libobsensor/Advanced.h for a detailed explanation
|
||||
# Predefined presets doc reference: docs/source/2_installation/package_description.md
|
||||
# Deep working mode support is as follows:{"Default","Hand","High Accuracy","High Density","Medium Density","Custom"}
|
||||
device_preset: "Default"
|
||||
|
||||
color:
|
||||
# If true, the color image will be enabled
|
||||
enable_color: true
|
||||
# Width of the color image. If 0, the default width will be used
|
||||
color_width: 0
|
||||
# Height of the color image. If 0, the default height will be used
|
||||
color_height: 0
|
||||
# Fps of the color image. If 0, the default FPS will be used
|
||||
color_fps: 0
|
||||
# default Format of the color image.
|
||||
color_format: "MJPG"
|
||||
# enable auto exposure for the color image
|
||||
enable_color_auto_exposure: true
|
||||
# enable auto white balance for the color image
|
||||
enable_color_auto_white_balance: true
|
||||
# If true, the color image will be undistorted
|
||||
enable_color_undistortion: false
|
||||
|
||||
depth:
|
||||
# If true, the depth image will be enabled
|
||||
enable_depth: true
|
||||
# Width of the depth image. If 0, the default width will be used
|
||||
depth_width: 0
|
||||
# Height of the depth image. If 0, the default height will be used
|
||||
depth_height: 0
|
||||
# Fps of the depth image. If 0, the default FPS will be used
|
||||
depth_fps: 0
|
||||
# default Format of the depth image.
|
||||
depth_format: "Y16"
|
||||
# If false, the depth scale will not be enabled
|
||||
enable_depth_scale: true
|
||||
|
||||
# D2C Depth registration mode.
|
||||
# Enables hardware that aligns depth frames to color frames. This field is required when setting enable_colored_point_cloud to true
|
||||
depth_registration: true
|
||||
# The alignment mode to be used. Options are "HW" for hardware alignment and "SW" for software alignment
|
||||
align_mode: "SW"
|
||||
|
||||
laser:
|
||||
# Whether to enable the laser. Default value is true
|
||||
enable_laser: false
|
||||
# Laser Switch Alternate Mode, 0: Off, 1: On-Off Alternate, 2: Off-On Alternate. Default value is 0.
|
||||
laser_on_off_mode: 0
|
||||
|
||||
filter:
|
||||
# -enable_decimation_filter
|
||||
enable_decimation_filter: false
|
||||
# -enable_hdr_merge
|
||||
enable_hdr_merge: false
|
||||
# -enable_sequence_id_filter
|
||||
enable_sequence_id_filter: false
|
||||
# -enable_threshold_filter
|
||||
enable_threshold_filter: false
|
||||
# -enable_noise_removal_filter
|
||||
enable_noise_removal_filter: true
|
||||
# -enable_spatial_filter
|
||||
enable_spatial_filter: false
|
||||
# -enable_temporal_filter
|
||||
enable_temporal_filter: false
|
||||
# -enable_hole_filling_filter
|
||||
enable_hole_filling_filter: false
|
||||
# -noise_removal_filter_min_diff
|
||||
noise_removal_filter_min_diff: 256
|
||||
# -noise_removal_filter_max_size
|
||||
noise_removal_filter_max_size: 80
|
||||
# -enable_soft_filter
|
||||
enable_soft_filter: true
|
||||
|
||||
leftir:
|
||||
# the left IR image will not be enabled
|
||||
enable_left_ir: true
|
||||
|
||||
rightir:
|
||||
# the right IR image will not be enabled
|
||||
enable_right_ir: true
|
||||
|
||||
imu:
|
||||
# If true, the IMU accelerometer data will be enabled
|
||||
enable_accel: false
|
||||
# The frequency of the accelerometer can be selected as 1.5625Hz, 3.125Hz, 6.25Hz, 12.5Hz, 25Hz, 50Hz, 100Hz, 200Hz, 500Hz, 1kHz, 2kHz, 4kHz, 8kHz, 16kHz, 32kHz.
|
||||
# The specific value depends on the current camera.
|
||||
accel_rate: "200hz"
|
||||
# The range of the accelerometer, the optional values are 2g, 4g, 8g, 16g. The specific value depends on the current camera.
|
||||
accel_range: "4g"
|
||||
# If true, the IMU gyroscope data will be enabled
|
||||
enable_gyro: false
|
||||
# The frequency of the gyroscope can be selected as 1.5625hz, 3.125hz, 6.25hz, 12.5hz, 25hz, 50hz, 100hz, 200hz, 500hz, 1kHz, 2kHz, 4kHz, 8kHz, 16kHz, 32kHz.
|
||||
# The specific value depends on the current camera.
|
||||
gyro_rate: "200hz"
|
||||
# The range of the gyroscope, the optional values are 16dps, 31dps, 62dps, 125dps, 250dps, 500dps, 1000dps, 2000dps. The specific value depends on the current camera.
|
||||
gyro_range: "1000dps"
|
||||
# enable_sync_output_accel_gyro
|
||||
enable_sync_output_accel_gyro: false
|
||||
|
||||
point_cloud:
|
||||
# enable point cloud. {fase:disable, true:enable}
|
||||
enable_point_cloud: false
|
||||
|
||||
advanced:
|
||||
# If true, the extrinsics publish will be enabled
|
||||
enable_publish_extrinsic: false
|
||||
# If true, the frame synchronization will be enabled
|
||||
enable_frame_sync: true
|
||||
# Publish D2C superimposed image (only for testing).
|
||||
enable_d2c_viewer: false
|
||||
# If false, the hardware time will not be used, true:devicetime, false:systemtime
|
||||
use_hardware_time: true
|
||||
# the host time will be synchronized with the device time
|
||||
enable_sync_host_time: true
|
||||
|
||||
device_sync:
|
||||
# Device synchronization mode. supports: {1.FREE_RUN 2.STANDALONE 3.PRIMARY 4.SECONDARY 5.SECONDARY_SYNCED 6.SOFTWARE_TRIGGERING 7.HARDWARE_TRIGGERING}.
|
||||
# For details, Please refer to the OBMultiDeviceSyncMode-related comments in SDK/include/libobsensor/ObTypes.h for a detailed explanation of each mode.
|
||||
sync_mode: "STANDALONE"
|
||||
# The delay time of the depth image capture after receiving the capture command or trigger signal in microseconds.
|
||||
# For details, Please refer to the OBMultiDeviceSyncConfig-related comments in SDK/include/libobsensor/ObTypes.h
|
||||
depth_delay_us: 0
|
||||
# The delay time of the color image capture after receiving the capture command or trigger signal in microseconds.
|
||||
color_delay_us: 0
|
||||
# The delay time of the image capture after receiving the capture command or trigger signal in microseconds.
|
||||
trigger2image_delay_us: 0
|
||||
# Trigger signal output enable flag.
|
||||
trigger_out_enabled: true
|
||||
# The delay time of the trigger signal output after receiving the capture command or trigger signal in microseconds.
|
||||
trigger_out_delay_us: 0
|
||||
# The frame number of each stream after each trigger in triggering mode.
|
||||
frames_per_trigger: 2
|
||||
# software trigger period in ms
|
||||
software_trigger_period: 33
|
||||
@@ -0,0 +1,161 @@
|
||||
# config/*.yaml files are used to configure the camera parameters
|
||||
---
|
||||
orbbec_ros:
|
||||
camera_parameters:
|
||||
general:
|
||||
# Camera model. upport product models by referencing config/*.yaml
|
||||
camera_model: "gemini330_series"
|
||||
# Path to the configuration file. If empty, default parameters will be used
|
||||
config_file_path: "gemini330_series.yaml"
|
||||
|
||||
deivce:
|
||||
# camera name, usually overwritten by launch file
|
||||
camera_name: "camera_test2"
|
||||
# camera serial number, usually overwritten by launch file
|
||||
serial_number: ""
|
||||
# The USB port of the camera. This parameter is required when using multiple cameras.
|
||||
usb_port: "2-1-12"
|
||||
# Number of devices. If multiple cameras are required, this parameter must be filled in launch file
|
||||
device_num: 2
|
||||
# The delay time for reopening the device, in milliseconds. Usually, there is no need to modify by default.
|
||||
connection_delay: 10
|
||||
# If true, the heartbeat will be enabled
|
||||
enable_heartbeat: false
|
||||
# If true, the camera will be reset
|
||||
enable_hardware_reset: false
|
||||
# If true, the LDP will be enabled
|
||||
enable_ldp: true
|
||||
# The preset of the device. #For details, Please refer to the comments in SDK/include/libobsensor/Advanced.h for a detailed explanation
|
||||
# Predefined presets doc reference: docs/source/2_installation/package_description.md
|
||||
# Deep working mode support is as follows:{"Default","Hand","High Accuracy","High Density","Medium Density","Custom"}
|
||||
device_preset: "Default"
|
||||
|
||||
color:
|
||||
# If true, the color image will be enabled
|
||||
enable_color: true
|
||||
# Width of the color image. If 0, the default width will be used
|
||||
color_width: 0
|
||||
# Height of the color image. If 0, the default height will be used
|
||||
color_height: 0
|
||||
# Fps of the color image. If 0, the default FPS will be used
|
||||
color_fps: 0
|
||||
# default Format of the color image.
|
||||
color_format: "MJPG"
|
||||
# enable auto exposure for the color image
|
||||
enable_color_auto_exposure: true
|
||||
# enable auto white balance for the color image
|
||||
enable_color_auto_white_balance: true
|
||||
# If true, the color image will be undistorted
|
||||
enable_color_undistortion: false
|
||||
|
||||
depth:
|
||||
# If true, the depth image will be enabled
|
||||
enable_depth: true
|
||||
# Width of the depth image. If 0, the default width will be used
|
||||
depth_width: 0
|
||||
# Height of the depth image. If 0, the default height will be used
|
||||
depth_height: 0
|
||||
# Fps of the depth image. If 0, the default FPS will be used
|
||||
depth_fps: 0
|
||||
# default Format of the depth image.
|
||||
depth_format: "Y16"
|
||||
# If false, the depth scale will not be enabled
|
||||
enable_depth_scale: true
|
||||
|
||||
# D2C Depth registration mode.
|
||||
# Enables hardware that aligns depth frames to color frames. This field is required when setting enable_colored_point_cloud to true
|
||||
depth_registration: true
|
||||
# The alignment mode to be used. Options are "HW" for hardware alignment and "SW" for software alignment
|
||||
align_mode: "SW"
|
||||
|
||||
laser:
|
||||
# Whether to enable the laser. Default value is true
|
||||
enable_laser: false
|
||||
# Laser Switch Alternate Mode, 0: Off, 1: On-Off Alternate, 2: Off-On Alternate. Default value is 0.
|
||||
laser_on_off_mode: 0
|
||||
|
||||
filter:
|
||||
# -enable_decimation_filter
|
||||
enable_decimation_filter: false
|
||||
# -enable_hdr_merge
|
||||
enable_hdr_merge: false
|
||||
# -enable_sequence_id_filter
|
||||
enable_sequence_id_filter: false
|
||||
# -enable_threshold_filter
|
||||
enable_threshold_filter: false
|
||||
# -enable_noise_removal_filter
|
||||
enable_noise_removal_filter: true
|
||||
# -enable_spatial_filter
|
||||
enable_spatial_filter: false
|
||||
# -enable_temporal_filter
|
||||
enable_temporal_filter: false
|
||||
# -enable_hole_filling_filter
|
||||
enable_hole_filling_filter: false
|
||||
# -noise_removal_filter_min_diff
|
||||
noise_removal_filter_min_diff: 256
|
||||
# -noise_removal_filter_max_size
|
||||
noise_removal_filter_max_size: 80
|
||||
# -enable_soft_filter
|
||||
enable_soft_filter: true
|
||||
|
||||
leftir:
|
||||
# the left IR image will not be enabled
|
||||
enable_left_ir: true
|
||||
|
||||
rightir:
|
||||
# the right IR image will not be enabled
|
||||
enable_right_ir: true
|
||||
|
||||
imu:
|
||||
# If true, the IMU accelerometer data will be enabled
|
||||
enable_accel: false
|
||||
# The frequency of the accelerometer can be selected as 1.5625Hz, 3.125Hz, 6.25Hz, 12.5Hz, 25Hz, 50Hz, 100Hz, 200Hz, 500Hz, 1kHz, 2kHz, 4kHz, 8kHz, 16kHz, 32kHz.
|
||||
# The specific value depends on the current camera.
|
||||
accel_rate: "200hz"
|
||||
# The range of the accelerometer, the optional values are 2g, 4g, 8g, 16g. The specific value depends on the current camera.
|
||||
accel_range: "4g"
|
||||
# If true, the IMU gyroscope data will be enabled
|
||||
enable_gyro: false
|
||||
# The frequency of the gyroscope can be selected as 1.5625hz, 3.125hz, 6.25hz, 12.5hz, 25hz, 50hz, 100hz, 200hz, 500hz, 1kHz, 2kHz, 4kHz, 8kHz, 16kHz, 32kHz.
|
||||
# The specific value depends on the current camera.
|
||||
gyro_rate: "200hz"
|
||||
# The range of the gyroscope, the optional values are 16dps, 31dps, 62dps, 125dps, 250dps, 500dps, 1000dps, 2000dps. The specific value depends on the current camera.
|
||||
gyro_range: "1000dps"
|
||||
# enable_sync_output_accel_gyro
|
||||
enable_sync_output_accel_gyro: false
|
||||
|
||||
point_cloud:
|
||||
# enable point cloud. {fase:disable, true:enable}
|
||||
enable_point_cloud: false
|
||||
|
||||
advanced:
|
||||
# If true, the extrinsics publish will be enabled
|
||||
enable_publish_extrinsic: false
|
||||
# If true, the frame synchronization will be enabled
|
||||
enable_frame_sync: true
|
||||
# Publish D2C superimposed image (only for testing).
|
||||
enable_d2c_viewer: false
|
||||
# If false, the hardware time will not be used, true:devicetime, false:systemtime
|
||||
use_hardware_time: true
|
||||
# the host time will be synchronized with the device time
|
||||
enable_sync_host_time: true
|
||||
|
||||
device_sync:
|
||||
# Device synchronization mode. supports: {1.FREE_RUN 2.STANDALONE 3.PRIMARY 4.SECONDARY 5.SECONDARY_SYNCED 6.SOFTWARE_TRIGGERING 7.HARDWARE_TRIGGERING}.
|
||||
# For details, Please refer to the OBMultiDeviceSyncMode-related comments in SDK/include/libobsensor/ObTypes.h for a detailed explanation of each mode.
|
||||
sync_mode: "STANDALONE"
|
||||
# The delay time of the depth image capture after receiving the capture command or trigger signal in microseconds.
|
||||
# For details, Please refer to the OBMultiDeviceSyncConfig-related comments in SDK/include/libobsensor/ObTypes.h
|
||||
depth_delay_us: 0
|
||||
# The delay time of the color image capture after receiving the capture command or trigger signal in microseconds.
|
||||
color_delay_us: 0
|
||||
# The delay time of the image capture after receiving the capture command or trigger signal in microseconds.
|
||||
trigger2image_delay_us: 0
|
||||
# Trigger signal output enable flag.
|
||||
trigger_out_enabled: true
|
||||
# The delay time of the trigger signal output after receiving the capture command or trigger signal in microseconds.
|
||||
trigger_out_delay_us: 0
|
||||
# The frame number of each stream after each trigger in triggering mode.
|
||||
frames_per_trigger: 2
|
||||
# software trigger period in ms
|
||||
software_trigger_period: 33
|
||||
@@ -1,14 +0,0 @@
|
||||
{
|
||||
"start_benchmark_params": {
|
||||
"camera_name": [
|
||||
"camera_01",
|
||||
"camera_02",
|
||||
"camera_03",
|
||||
"camera_04"
|
||||
],
|
||||
"process_name": "component_conta",
|
||||
"switch_cycle": 60,
|
||||
"test_cycle": 1,
|
||||
"skip_number": 30
|
||||
}
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
# [benchmark](./benchmark)
|
||||
|
||||
The goal of this tool is to benchmark the performance of various OrbbecSDK_ROS2 camera configurations. The benchmark results depend on the camera and settings used.(Currently only works with ROS2 Humble).
|
||||
|
||||
# [disparity_search_offset](./disparity_search_offset)
|
||||
|
||||
How to use disparity_search_offset in OrbbecSDK_ROS2.
|
||||
|
||||
# [gmsl_camera](./gmsl_camera)
|
||||
|
||||
How to use gmsl_camera in OrbbecSDK_ROS2.Show how to start Single GMSL camera ,Multi GMSL camera , and Multi GMSL camera synced.
|
||||
|
||||
# [interleave_ae_mode](./interleave_ae_mode)
|
||||
|
||||
How to use interleave_ae in OrbbecSDK_ROS2.Show how to use interleave_ae in Gemini 330 series cameras.
|
||||
|
||||
# [lower_cpu_usage](./lower_cpu_usage)
|
||||
|
||||
How to reduce CPU usage of one or more cameras in OrbbecSDK_ROS2.
|
||||
|
||||
# [multi_camera_synced](./multi_camera_synced)
|
||||
|
||||
How to use multi-camera synced in OrbbecSDK_ROS2.
|
||||
|
||||
# [multi_camera_synced_verification_tool](./multi_camera_synced_verification_tool)
|
||||
|
||||
How to verify the synchronization accuracy of multi-camera synced.Show how to use the save_rgbir tool and Python script to analyze the synchronization between cameras and between different cameras.
|
||||
|
||||
# [net_camera](./net_camera)
|
||||
|
||||
How to use net_camera in OrbbecSDK_ROS2.Show how to start Single Net camera ,Multi Net camera.
|
||||
@@ -1,51 +0,0 @@
|
||||
# Ob_benchmark tool
|
||||
|
||||
> The goal of this tool is to benchmark the performance of various OrbbecSDK_ROS2 camera configurations. The benchmark results depend on the camera and settings used.(Currently only works with ROS2 Humble)
|
||||
|
||||
## Usage Instructions
|
||||
|
||||
### Tool Configuration ([start_benchmark_params.json](../../config/tools/startbenchmark/start_benchmark_params.json))
|
||||
|
||||
```json
|
||||
{
|
||||
"start_benchmark_params": {
|
||||
"camera_name": [
|
||||
"camera_01",
|
||||
"camera_02",
|
||||
"camera_03",
|
||||
"camera_04"
|
||||
],
|
||||
"process_name": "component_conta",
|
||||
"switch_cycle": 300,
|
||||
"test_cycle": 1,
|
||||
"skip_number": 30
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
* `camera_name`: Names of the cameras to be configured. Example: `"camera_01"`, `"camera_02"`, etc.
|
||||
* `process_name`: The name of the process to be monitored. For example, `"component_conta"` will monitor the data of the container process.
|
||||
* `switch_cycle`: The cycle time for switching configurations, in seconds. For example, setting it to `300` means the configuration will switch every 300 seconds.
|
||||
* `test_cycle`: The testing cycle, in seconds. For example, setting it to `1` means the tool will collect data for the monitored process every 1 second.
|
||||
* `skip_number`: The number of data points to skip. For example, setting it to `30` means that the first 30 data points will be ignored.
|
||||
|
||||
### Camera configuration (launch files)
|
||||
|
||||
In the launch folder, there are multiple\.launch.py files (`ob_benchmark_0.launch.py`, `ob_benchmark_1.launch.py`, ..., `ob_benchmark_19.launch.py`). Each file corresponds to a different camera configuration.
|
||||
|
||||
### Running the ob_benchmark tool
|
||||
|
||||
To run the tool, use the following commands:
|
||||
|
||||
```bash
|
||||
source install/setup.bash
|
||||
ros2 run orbbec_camera ob_benchmark_node
|
||||
```
|
||||
|
||||
### Output Data Files
|
||||
|
||||
The output data files will be stored in the ob_benchmark folder with filenames like `0.csv`, `1.csv`, ..., 19.csv. For example:
|
||||
|
||||
* `0.csv` contains data from the `ob_benchmark_0.launch.py` configuration.
|
||||
* `1.csv` contains data from the `ob_benchmark_1.launch.py` configuration.
|
||||
@@ -1,265 +0,0 @@
|
||||
import os
|
||||
import yaml
|
||||
from launch import LaunchDescription
|
||||
from launch.actions import DeclareLaunchArgument, OpaqueFunction, GroupAction
|
||||
from launch.substitutions import LaunchConfiguration
|
||||
from launch_ros.actions import PushRosNamespace, ComposableNodeContainer, Node
|
||||
from launch_ros.descriptions import ComposableNode
|
||||
from launch.conditions import UnlessCondition
|
||||
from launch_ros.actions import LoadComposableNodes
|
||||
|
||||
def load_yaml(file_path):
|
||||
with open(file_path, 'r') as f:
|
||||
return yaml.safe_load(f)
|
||||
|
||||
|
||||
def merge_params(default_params, yaml_params):
|
||||
for key, value in yaml_params.items():
|
||||
if key in default_params:
|
||||
default_params[key] = value
|
||||
return default_params
|
||||
|
||||
|
||||
def convert_value(value):
|
||||
if isinstance(value, str):
|
||||
try:
|
||||
return int(value)
|
||||
except ValueError:
|
||||
pass
|
||||
try:
|
||||
return float(value)
|
||||
except ValueError:
|
||||
pass
|
||||
if value.lower() == 'true':
|
||||
return True
|
||||
elif value.lower() == 'false':
|
||||
return False
|
||||
return value
|
||||
|
||||
|
||||
def load_parameters(context, args):
|
||||
default_params = {arg.name: LaunchConfiguration(arg.name).perform(context) for arg in args}
|
||||
config_file_path = LaunchConfiguration('config_file_path').perform(context)
|
||||
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'}
|
||||
return {
|
||||
key: (value if key in skip_convert else convert_value(value))
|
||||
for key, value in default_params.items()
|
||||
}
|
||||
|
||||
|
||||
def generate_launch_description():
|
||||
args = [
|
||||
DeclareLaunchArgument('camera_name', default_value='camera'),
|
||||
DeclareLaunchArgument('depth_registration', default_value='true'),
|
||||
DeclareLaunchArgument('serial_number', default_value=''),
|
||||
DeclareLaunchArgument('usb_port', default_value=''),
|
||||
DeclareLaunchArgument('device_num', default_value='1'),
|
||||
DeclareLaunchArgument('uvc_backend', default_value='libuvc'),#libuvc or v4l2
|
||||
DeclareLaunchArgument('point_cloud_qos', default_value='default'),
|
||||
DeclareLaunchArgument('enable_point_cloud', default_value='true'),
|
||||
DeclareLaunchArgument('enable_colored_point_cloud', default_value='false'),
|
||||
DeclareLaunchArgument('cloud_frame_id', default_value=''),
|
||||
DeclareLaunchArgument('connection_delay', default_value='10'),
|
||||
DeclareLaunchArgument('color_width', default_value='0'),
|
||||
DeclareLaunchArgument('color_height', default_value='0'),
|
||||
DeclareLaunchArgument('color_fps', default_value='0'),
|
||||
DeclareLaunchArgument('color_format', default_value='ANY'),
|
||||
DeclareLaunchArgument('enable_color', default_value='true'),
|
||||
DeclareLaunchArgument('color_qos', default_value='default'),
|
||||
DeclareLaunchArgument('color_camera_info_qos', default_value='default'),
|
||||
DeclareLaunchArgument('enable_color_auto_exposure', default_value='true'),
|
||||
DeclareLaunchArgument('color_exposure', default_value='-1'),
|
||||
DeclareLaunchArgument('color_gain', default_value='-1'),
|
||||
DeclareLaunchArgument('enable_color_auto_white_balance', default_value='true'),
|
||||
DeclareLaunchArgument('color_white_balance', default_value='-1'),
|
||||
DeclareLaunchArgument('color_ae_max_exposure', default_value='-1'),
|
||||
DeclareLaunchArgument('color_brightness', default_value='-1'),
|
||||
DeclareLaunchArgument('depth_width', default_value='0'),
|
||||
DeclareLaunchArgument('depth_height', default_value='0'),
|
||||
DeclareLaunchArgument('depth_fps', default_value='0'),
|
||||
DeclareLaunchArgument('depth_format', default_value='ANY'),
|
||||
DeclareLaunchArgument('enable_depth', default_value='true'),
|
||||
DeclareLaunchArgument('depth_qos', default_value='default'),
|
||||
DeclareLaunchArgument('depth_camera_info_qos', default_value='default'),
|
||||
DeclareLaunchArgument('left_ir_width', default_value='0'),
|
||||
DeclareLaunchArgument('left_ir_height', default_value='0'),
|
||||
DeclareLaunchArgument('left_ir_fps', default_value='0'),
|
||||
DeclareLaunchArgument('left_ir_format', default_value='ANY'),
|
||||
DeclareLaunchArgument('enable_left_ir', default_value='false'),
|
||||
DeclareLaunchArgument('left_ir_qos', default_value='default'),
|
||||
DeclareLaunchArgument('left_ir_camera_info_qos', default_value='default'),
|
||||
DeclareLaunchArgument('right_ir_width', default_value='0'),
|
||||
DeclareLaunchArgument('right_ir_height', default_value='0'),
|
||||
DeclareLaunchArgument('right_ir_fps', default_value='0'),
|
||||
DeclareLaunchArgument('right_ir_format', default_value='ANY'),
|
||||
DeclareLaunchArgument('enable_right_ir', default_value='false'),
|
||||
DeclareLaunchArgument('right_ir_qos', default_value='default'),
|
||||
DeclareLaunchArgument('right_ir_camera_info_qos', default_value='default'),
|
||||
DeclareLaunchArgument('enable_ir_auto_exposure', default_value='true'),
|
||||
DeclareLaunchArgument('ir_exposure', default_value='-1'),
|
||||
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('accel_rate', default_value='200hz'),
|
||||
DeclareLaunchArgument('accel_range', default_value='4g'),
|
||||
DeclareLaunchArgument('enable_gyro', default_value='false'),
|
||||
DeclareLaunchArgument('gyro_rate', default_value='200hz'),
|
||||
DeclareLaunchArgument('gyro_range', default_value='1000dps'),
|
||||
DeclareLaunchArgument('liner_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('log_level', default_value='none'),
|
||||
DeclareLaunchArgument('enable_publish_extrinsic', default_value='false'),
|
||||
DeclareLaunchArgument('enable_d2c_viewer', default_value='false'),
|
||||
DeclareLaunchArgument('enable_hardware_d2d', default_value='true'),
|
||||
DeclareLaunchArgument('enable_ldp', default_value='true'),
|
||||
DeclareLaunchArgument('enable_soft_filter', default_value='true'),
|
||||
DeclareLaunchArgument('soft_filter_max_diff', default_value='-1'),
|
||||
DeclareLaunchArgument('soft_filter_speckle_size', default_value='-1'),
|
||||
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('frames_per_trigger', default_value='2'),
|
||||
DeclareLaunchArgument('software_trigger_period', default_value='33'), # ms
|
||||
DeclareLaunchArgument('enable_frame_sync', default_value='true'),
|
||||
DeclareLaunchArgument('ordered_pc', default_value='false'),
|
||||
DeclareLaunchArgument('enable_depth_scale', default_value='true'),
|
||||
DeclareLaunchArgument('enable_decimation_filter', default_value='false'),
|
||||
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='true'),
|
||||
DeclareLaunchArgument('enable_noise_removal_filter', default_value='true'),
|
||||
DeclareLaunchArgument('enable_spatial_filter', default_value='false'),
|
||||
DeclareLaunchArgument('enable_temporal_filter', default_value='false'),
|
||||
DeclareLaunchArgument('enable_hole_filling_filter', default_value='false'),
|
||||
DeclareLaunchArgument('decimation_filter_scale', default_value='-1'),
|
||||
DeclareLaunchArgument('sequence_id_filter_id', default_value='-1'),
|
||||
DeclareLaunchArgument('threshold_filter_max', default_value='-1'),
|
||||
DeclareLaunchArgument('threshold_filter_min', default_value='-1'),
|
||||
DeclareLaunchArgument('noise_removal_filter_min_diff', default_value='256'),
|
||||
DeclareLaunchArgument('noise_removal_filter_max_size', default_value='80'),
|
||||
DeclareLaunchArgument('spatial_filter_alpha', default_value='-1.0'),
|
||||
DeclareLaunchArgument('spatial_filter_diff_threshold', default_value='-1'),
|
||||
DeclareLaunchArgument('spatial_filter_magnitude', default_value='-1'),
|
||||
DeclareLaunchArgument('spatial_filter_radius', default_value='-1'),
|
||||
DeclareLaunchArgument('temporal_filter_diff_threshold', default_value='-1.0'),
|
||||
DeclareLaunchArgument('temporal_filter_weight', default_value='-1.0'),
|
||||
DeclareLaunchArgument('hole_filling_filter_mode', default_value=''),
|
||||
DeclareLaunchArgument('hdr_merge_exposure_1', default_value='-1'),
|
||||
DeclareLaunchArgument('hdr_merge_gain_1', default_value='-1'),
|
||||
DeclareLaunchArgument('hdr_merge_exposure_2', default_value='-1'),
|
||||
DeclareLaunchArgument('hdr_merge_gain_2', default_value='-1'),
|
||||
DeclareLaunchArgument('align_mode', default_value='SW'),
|
||||
DeclareLaunchArgument('diagnostic_period', default_value='1.0'),
|
||||
DeclareLaunchArgument('enable_laser', default_value='true'),
|
||||
DeclareLaunchArgument('depth_precision', default_value=''),
|
||||
DeclareLaunchArgument('device_preset', default_value='Default'),
|
||||
DeclareLaunchArgument('retry_on_usb3_detection_failure', default_value='false'),
|
||||
DeclareLaunchArgument('laser_energy_level', default_value='-1'),
|
||||
DeclareLaunchArgument('enable_sync_host_time', default_value='true'),
|
||||
DeclareLaunchArgument('time_domain', default_value='global'),# global, device, system
|
||||
DeclareLaunchArgument('enable_color_undistortion', default_value='false'),
|
||||
DeclareLaunchArgument('config_file_path', default_value=''),
|
||||
DeclareLaunchArgument('enable_heartbeat', default_value='false'),
|
||||
DeclareLaunchArgument('gmsl_trigger_fps', default_value='3000'),
|
||||
DeclareLaunchArgument('enable_gmsl_trigger', default_value='false'),
|
||||
DeclareLaunchArgument('disparity_range_mode', default_value='-1'),
|
||||
DeclareLaunchArgument('disparity_search_offset', default_value='-1'),
|
||||
DeclareLaunchArgument('disparity_offset_config', default_value='false'),
|
||||
DeclareLaunchArgument('offset_index0', default_value='-1'),
|
||||
DeclareLaunchArgument('offset_index1', default_value='-1'),
|
||||
DeclareLaunchArgument('frame_aggregate_mode', default_value='ANY'), # full_frame、color_frame、ANY or disable
|
||||
DeclareLaunchArgument('interleave_ae_mode', default_value='laser'), # 'hdr' or 'laser'
|
||||
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_laser_control', default_value='1'),#interleave_hdr_param
|
||||
DeclareLaunchArgument('hdr_index1_depth_exposure', default_value='1'),
|
||||
DeclareLaunchArgument('hdr_index1_depth_gain', default_value='16'),
|
||||
DeclareLaunchArgument('hdr_index1_ir_brightness', default_value='20'),
|
||||
DeclareLaunchArgument('hdr_index1_ir_ae_max_exposure', default_value='2000'),
|
||||
DeclareLaunchArgument('hdr_index0_laser_control', default_value='1'),
|
||||
DeclareLaunchArgument('hdr_index0_depth_exposure', default_value='7500'),
|
||||
DeclareLaunchArgument('hdr_index0_depth_gain', default_value='16'),
|
||||
DeclareLaunchArgument('hdr_index0_ir_brightness', default_value='60'),
|
||||
DeclareLaunchArgument('hdr_index0_ir_ae_max_exposure', default_value='10000'),
|
||||
|
||||
DeclareLaunchArgument('laser_index1_laser_control', default_value='0'),#interleave_laser_param
|
||||
DeclareLaunchArgument('laser_index1_depth_exposure', default_value='3000'),
|
||||
DeclareLaunchArgument('laser_index1_depth_gain', default_value='16'),
|
||||
DeclareLaunchArgument('laser_index1_ir_brightness', default_value='60'),
|
||||
DeclareLaunchArgument('laser_index1_ir_ae_max_exposure', default_value='17000'),
|
||||
DeclareLaunchArgument('laser_index0_laser_control', default_value='1'),
|
||||
DeclareLaunchArgument('laser_index0_depth_exposure', default_value='3000'),
|
||||
DeclareLaunchArgument('laser_index0_depth_gain', default_value='16'),
|
||||
DeclareLaunchArgument('laser_index0_ir_brightness', default_value='60'),
|
||||
DeclareLaunchArgument('laser_index0_ir_ae_max_exposure', default_value='30000'),
|
||||
DeclareLaunchArgument('use_intra_process_comms', default_value='false'),
|
||||
DeclareLaunchArgument('attach_component_container_enable', default_value='false'),
|
||||
DeclareLaunchArgument('attach_component_container_name', default_value='orbbec_container'),
|
||||
|
||||
]
|
||||
|
||||
def get_params(context, args):
|
||||
return [load_parameters(context, args)]
|
||||
|
||||
def create_node_action(context, args):
|
||||
params = get_params(context, args)
|
||||
ros_distro = os.environ.get("ROS_DISTRO", "humble")
|
||||
if ros_distro == "foxy":
|
||||
return [
|
||||
Node(
|
||||
package="orbbec_camera",
|
||||
executable="orbbec_camera_node",
|
||||
name="ob_camera_node",
|
||||
namespace=LaunchConfiguration("camera_name"),
|
||||
parameters=params,
|
||||
output="screen",
|
||||
)
|
||||
]
|
||||
else:
|
||||
attach_to_shared_component_container_arg = LaunchConfiguration('attach_to_shared_component_container', default=False)
|
||||
component_container_name_arg = LaunchConfiguration('component_container_name', default='orbbec_container')
|
||||
|
||||
orbbec_container = Node(
|
||||
name=component_container_name_arg,
|
||||
package='rclcpp_components',
|
||||
executable='component_container_mt',
|
||||
output='screen',
|
||||
condition=UnlessCondition(attach_to_shared_component_container_arg)
|
||||
)
|
||||
return [
|
||||
orbbec_container,
|
||||
LoadComposableNodes(
|
||||
target_container=component_container_name_arg,
|
||||
composable_node_descriptions=[
|
||||
ComposableNode(
|
||||
namespace=LaunchConfiguration("camera_name"),
|
||||
name=LaunchConfiguration("camera_name"),
|
||||
package='orbbec_camera',
|
||||
plugin='orbbec_camera::OBCameraNodeDriver',
|
||||
parameters=params,
|
||||
extra_arguments=[{'use_intra_process_comms': LaunchConfiguration("use_intra_process_comms")}],
|
||||
)
|
||||
]
|
||||
)
|
||||
]
|
||||
|
||||
return LaunchDescription(
|
||||
args + [
|
||||
OpaqueFunction(function=lambda context: create_node_action(context, args))
|
||||
]
|
||||
)
|
||||
@@ -1,197 +0,0 @@
|
||||
import os
|
||||
from ament_index_python.packages import get_package_share_directory
|
||||
from launch import LaunchDescription
|
||||
from launch_ros.actions import Node,LoadComposableNodes
|
||||
from launch.actions import IncludeLaunchDescription, GroupAction, TimerAction
|
||||
from launch.launch_description_sources import PythonLaunchDescriptionSource
|
||||
from launch.actions import DeclareLaunchArgument
|
||||
from launch.conditions import UnlessCondition, IfCondition
|
||||
from launch.substitutions import LaunchConfiguration
|
||||
from launch.substitutions import TextSubstitution
|
||||
from launch_ros.descriptions import ComposableNode
|
||||
|
||||
def load_yaml(file_path):
|
||||
with open(file_path, 'r') as f:
|
||||
return yaml.safe_load(f)
|
||||
|
||||
|
||||
def merge_params(default_params, yaml_params):
|
||||
for key, value in yaml_params.items():
|
||||
if key in default_params:
|
||||
default_params[key] = value
|
||||
return default_params
|
||||
|
||||
|
||||
def convert_value(value):
|
||||
if isinstance(value, str):
|
||||
try:
|
||||
return int(value)
|
||||
except ValueError:
|
||||
pass
|
||||
try:
|
||||
return float(value)
|
||||
except ValueError:
|
||||
pass
|
||||
if value.lower() == 'true':
|
||||
return True
|
||||
elif value.lower() == 'false':
|
||||
return False
|
||||
return value
|
||||
|
||||
|
||||
def load_parameters(context, args):
|
||||
default_params = {arg.name: LaunchConfiguration(arg.name).perform(context) for arg in args}
|
||||
config_file_path = LaunchConfiguration('config_file_path').perform(context)
|
||||
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'}
|
||||
return {
|
||||
key: (value if key in skip_convert else convert_value(value))
|
||||
for key, value in default_params.items()
|
||||
}
|
||||
def generate_launch_description():
|
||||
# Include launch files
|
||||
package_dir = get_package_share_directory("orbbec_camera")
|
||||
launch_file_dir = os.path.join(package_dir, "examples/benchmark")
|
||||
|
||||
attach_to_shared_component_container_arg = LaunchConfiguration('attach_to_shared_component_container', default=False)
|
||||
component_container_name_arg = LaunchConfiguration('component_container_name', default='shared_orbbec_container')
|
||||
|
||||
shared_orbbec_container = Node(
|
||||
name=component_container_name_arg,
|
||||
package="rclcpp_components",
|
||||
executable="component_container_mt",
|
||||
output="screen",
|
||||
condition=UnlessCondition(attach_to_shared_component_container_arg),
|
||||
)
|
||||
start_benchmark = LoadComposableNodes(
|
||||
target_container=component_container_name_arg,
|
||||
composable_node_descriptions=[
|
||||
ComposableNode(
|
||||
namespace="start_benchmark",
|
||||
name="start_benchmark",
|
||||
package='orbbec_camera',
|
||||
plugin='orbbec_camera::tools::StartBenchmark',
|
||||
)
|
||||
]
|
||||
)
|
||||
|
||||
attach_to_shared_component_container_arg = TextSubstitution(text="true")
|
||||
|
||||
args = [
|
||||
DeclareLaunchArgument('uvc_backend', default_value='libuvc'),
|
||||
DeclareLaunchArgument('depth_registration', default_value='false'),
|
||||
DeclareLaunchArgument('color_width', default_value='848'),
|
||||
DeclareLaunchArgument('color_height', default_value='480'),
|
||||
DeclareLaunchArgument('color_fps', default_value='30'),
|
||||
DeclareLaunchArgument('color_format', default_value='MJPG'),
|
||||
DeclareLaunchArgument('enable_color', default_value='true'),
|
||||
DeclareLaunchArgument('depth_width', default_value='848'),
|
||||
DeclareLaunchArgument('depth_height', default_value='480'),
|
||||
DeclareLaunchArgument('depth_fps', default_value='30'),
|
||||
DeclareLaunchArgument('depth_format', default_value='ANY'),
|
||||
DeclareLaunchArgument('enable_depth', default_value='true'),
|
||||
DeclareLaunchArgument('left_ir_width', default_value='848'),
|
||||
DeclareLaunchArgument('left_ir_height', default_value='480'),
|
||||
DeclareLaunchArgument('left_ir_fps', default_value='30'),
|
||||
DeclareLaunchArgument('left_ir_format', default_value='ANY'),
|
||||
DeclareLaunchArgument('enable_left_ir', default_value='true'),
|
||||
DeclareLaunchArgument('right_ir_width', default_value='848'),
|
||||
DeclareLaunchArgument('right_ir_height', default_value='480'),
|
||||
DeclareLaunchArgument('right_ir_fps', default_value='30'),
|
||||
DeclareLaunchArgument('right_ir_format', default_value='ANY'),
|
||||
DeclareLaunchArgument('enable_right_ir', default_value='true'),
|
||||
DeclareLaunchArgument('enable_point_cloud', default_value='false'),
|
||||
DeclareLaunchArgument('enable_colored_point_cloud', default_value='false'),
|
||||
DeclareLaunchArgument('enable_decimation_filter', default_value='false'),
|
||||
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_noise_removal_filter', default_value='false'),
|
||||
DeclareLaunchArgument('enable_spatial_filter', default_value='false'),
|
||||
DeclareLaunchArgument('enable_temporal_filter', default_value='false'),
|
||||
DeclareLaunchArgument('enable_hole_filling_filter', default_value='false'),
|
||||
]
|
||||
launch1_include = IncludeLaunchDescription(
|
||||
PythonLaunchDescriptionSource(
|
||||
os.path.join(launch_file_dir, "gemini_330_series_benchmark.launch.py")
|
||||
),
|
||||
launch_arguments={
|
||||
"camera_name": "camera_01",
|
||||
"usb_port": "2-7",
|
||||
"device_num": "4",
|
||||
"sync_mode": "standalone",
|
||||
"attach_to_shared_component_container": attach_to_shared_component_container_arg,
|
||||
"component_container_name": component_container_name_arg,
|
||||
}.items(),
|
||||
)
|
||||
launch2_include = IncludeLaunchDescription(
|
||||
PythonLaunchDescriptionSource(
|
||||
os.path.join(launch_file_dir, "gemini_330_series_benchmark.launch.py")
|
||||
),
|
||||
launch_arguments={
|
||||
"camera_name": "camera_02",
|
||||
"usb_port": "2-2",
|
||||
"device_num": "4",
|
||||
"sync_mode": "standalone",
|
||||
"attach_to_shared_component_container": attach_to_shared_component_container_arg,
|
||||
"component_container_name": component_container_name_arg,
|
||||
}.items(),
|
||||
)
|
||||
launch3_include = IncludeLaunchDescription(
|
||||
PythonLaunchDescriptionSource(
|
||||
os.path.join(launch_file_dir, "gemini_330_series_benchmark.launch.py")
|
||||
),
|
||||
launch_arguments={
|
||||
"camera_name": "camera_03",
|
||||
"usb_port": "2-1",
|
||||
"device_num": "4",
|
||||
"sync_mode": "standalone",
|
||||
"attach_to_shared_component_container": attach_to_shared_component_container_arg,
|
||||
"component_container_name": component_container_name_arg,
|
||||
}.items(),
|
||||
)
|
||||
launch4_include = IncludeLaunchDescription(
|
||||
PythonLaunchDescriptionSource(
|
||||
os.path.join(launch_file_dir, "gemini_330_series_benchmark.launch.py")
|
||||
),
|
||||
launch_arguments={
|
||||
"camera_name": "camera_04",
|
||||
"usb_port": "2-3",
|
||||
"device_num": "4",
|
||||
"sync_mode": "standalone",
|
||||
"attach_to_shared_component_container": attach_to_shared_component_container_arg,
|
||||
"component_container_name": component_container_name_arg,
|
||||
}.items(),
|
||||
)
|
||||
|
||||
delayed_left_camera = TimerAction(
|
||||
period=2.0,
|
||||
actions=args+[launch1_include],
|
||||
)
|
||||
delayed_right_camera = TimerAction(
|
||||
period=4.0,
|
||||
actions=args+[launch2_include],
|
||||
)
|
||||
delayed_rear_camera = TimerAction(
|
||||
period=6.0,
|
||||
actions=args+[launch3_include],
|
||||
)
|
||||
delayed_front_camera = TimerAction(
|
||||
period=8.0,
|
||||
actions=args+[launch4_include],
|
||||
)
|
||||
ld = LaunchDescription(
|
||||
[
|
||||
shared_orbbec_container,
|
||||
start_benchmark,
|
||||
delayed_left_camera,
|
||||
delayed_right_camera,
|
||||
delayed_rear_camera,
|
||||
delayed_front_camera,
|
||||
]
|
||||
)
|
||||
|
||||
return ld
|
||||
@@ -1,197 +0,0 @@
|
||||
import os
|
||||
from ament_index_python.packages import get_package_share_directory
|
||||
from launch import LaunchDescription
|
||||
from launch_ros.actions import Node,LoadComposableNodes
|
||||
from launch.actions import IncludeLaunchDescription, GroupAction, TimerAction
|
||||
from launch.launch_description_sources import PythonLaunchDescriptionSource
|
||||
from launch.actions import DeclareLaunchArgument
|
||||
from launch.conditions import UnlessCondition, IfCondition
|
||||
from launch.substitutions import LaunchConfiguration
|
||||
from launch.substitutions import TextSubstitution
|
||||
from launch_ros.descriptions import ComposableNode
|
||||
|
||||
def load_yaml(file_path):
|
||||
with open(file_path, 'r') as f:
|
||||
return yaml.safe_load(f)
|
||||
|
||||
|
||||
def merge_params(default_params, yaml_params):
|
||||
for key, value in yaml_params.items():
|
||||
if key in default_params:
|
||||
default_params[key] = value
|
||||
return default_params
|
||||
|
||||
|
||||
def convert_value(value):
|
||||
if isinstance(value, str):
|
||||
try:
|
||||
return int(value)
|
||||
except ValueError:
|
||||
pass
|
||||
try:
|
||||
return float(value)
|
||||
except ValueError:
|
||||
pass
|
||||
if value.lower() == 'true':
|
||||
return True
|
||||
elif value.lower() == 'false':
|
||||
return False
|
||||
return value
|
||||
|
||||
|
||||
def load_parameters(context, args):
|
||||
default_params = {arg.name: LaunchConfiguration(arg.name).perform(context) for arg in args}
|
||||
config_file_path = LaunchConfiguration('config_file_path').perform(context)
|
||||
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'}
|
||||
return {
|
||||
key: (value if key in skip_convert else convert_value(value))
|
||||
for key, value in default_params.items()
|
||||
}
|
||||
def generate_launch_description():
|
||||
# Include launch files
|
||||
package_dir = get_package_share_directory("orbbec_camera")
|
||||
launch_file_dir = os.path.join(package_dir, "examples/benchmark")
|
||||
|
||||
attach_to_shared_component_container_arg = LaunchConfiguration('attach_to_shared_component_container', default=False)
|
||||
component_container_name_arg = LaunchConfiguration('component_container_name', default='shared_orbbec_container')
|
||||
|
||||
shared_orbbec_container = Node(
|
||||
name=component_container_name_arg,
|
||||
package="rclcpp_components",
|
||||
executable="component_container_mt",
|
||||
output="screen",
|
||||
condition=UnlessCondition(attach_to_shared_component_container_arg),
|
||||
)
|
||||
start_benchmark = LoadComposableNodes(
|
||||
target_container=component_container_name_arg,
|
||||
composable_node_descriptions=[
|
||||
ComposableNode(
|
||||
namespace="start_benchmark",
|
||||
name="start_benchmark",
|
||||
package='orbbec_camera',
|
||||
plugin='orbbec_camera::tools::StartBenchmark',
|
||||
)
|
||||
]
|
||||
)
|
||||
|
||||
attach_to_shared_component_container_arg = TextSubstitution(text="true")
|
||||
|
||||
args = [
|
||||
DeclareLaunchArgument('uvc_backend', default_value='libuvc'),
|
||||
DeclareLaunchArgument('depth_registration', default_value='false'),
|
||||
DeclareLaunchArgument('color_width', default_value='848'),
|
||||
DeclareLaunchArgument('color_height', default_value='480'),
|
||||
DeclareLaunchArgument('color_fps', default_value='30'),
|
||||
DeclareLaunchArgument('color_format', default_value='MJPG'),
|
||||
DeclareLaunchArgument('enable_color', default_value='true'),
|
||||
DeclareLaunchArgument('depth_width', default_value='848'),
|
||||
DeclareLaunchArgument('depth_height', default_value='480'),
|
||||
DeclareLaunchArgument('depth_fps', default_value='30'),
|
||||
DeclareLaunchArgument('depth_format', default_value='ANY'),
|
||||
DeclareLaunchArgument('enable_depth', default_value='true'),
|
||||
DeclareLaunchArgument('left_ir_width', default_value='848'),
|
||||
DeclareLaunchArgument('left_ir_height', default_value='480'),
|
||||
DeclareLaunchArgument('left_ir_fps', default_value='30'),
|
||||
DeclareLaunchArgument('left_ir_format', default_value='ANY'),
|
||||
DeclareLaunchArgument('enable_left_ir', default_value='true'),
|
||||
DeclareLaunchArgument('right_ir_width', default_value='848'),
|
||||
DeclareLaunchArgument('right_ir_height', default_value='480'),
|
||||
DeclareLaunchArgument('right_ir_fps', default_value='30'),
|
||||
DeclareLaunchArgument('right_ir_format', default_value='ANY'),
|
||||
DeclareLaunchArgument('enable_right_ir', default_value='true'),
|
||||
DeclareLaunchArgument('enable_point_cloud', default_value='false'),
|
||||
DeclareLaunchArgument('enable_colored_point_cloud', default_value='false'),
|
||||
DeclareLaunchArgument('enable_decimation_filter', default_value='false'),
|
||||
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='true'),
|
||||
DeclareLaunchArgument('enable_noise_removal_filter', default_value='false'),
|
||||
DeclareLaunchArgument('enable_spatial_filter', default_value='false'),
|
||||
DeclareLaunchArgument('enable_temporal_filter', default_value='false'),
|
||||
DeclareLaunchArgument('enable_hole_filling_filter', default_value='false'),
|
||||
]
|
||||
launch1_include = IncludeLaunchDescription(
|
||||
PythonLaunchDescriptionSource(
|
||||
os.path.join(launch_file_dir, "gemini_330_series_benchmark.launch.py")
|
||||
),
|
||||
launch_arguments={
|
||||
"camera_name": "camera_01",
|
||||
"usb_port": "2-7",
|
||||
"device_num": "4",
|
||||
"sync_mode": "standalone",
|
||||
"attach_to_shared_component_container": attach_to_shared_component_container_arg,
|
||||
"component_container_name": component_container_name_arg,
|
||||
}.items(),
|
||||
)
|
||||
launch2_include = IncludeLaunchDescription(
|
||||
PythonLaunchDescriptionSource(
|
||||
os.path.join(launch_file_dir, "gemini_330_series_benchmark.launch.py")
|
||||
),
|
||||
launch_arguments={
|
||||
"camera_name": "camera_02",
|
||||
"usb_port": "2-2",
|
||||
"device_num": "4",
|
||||
"sync_mode": "standalone",
|
||||
"attach_to_shared_component_container": attach_to_shared_component_container_arg,
|
||||
"component_container_name": component_container_name_arg,
|
||||
}.items(),
|
||||
)
|
||||
launch3_include = IncludeLaunchDescription(
|
||||
PythonLaunchDescriptionSource(
|
||||
os.path.join(launch_file_dir, "gemini_330_series_benchmark.launch.py")
|
||||
),
|
||||
launch_arguments={
|
||||
"camera_name": "camera_03",
|
||||
"usb_port": "2-1",
|
||||
"device_num": "4",
|
||||
"sync_mode": "standalone",
|
||||
"attach_to_shared_component_container": attach_to_shared_component_container_arg,
|
||||
"component_container_name": component_container_name_arg,
|
||||
}.items(),
|
||||
)
|
||||
launch4_include = IncludeLaunchDescription(
|
||||
PythonLaunchDescriptionSource(
|
||||
os.path.join(launch_file_dir, "gemini_330_series_benchmark.launch.py")
|
||||
),
|
||||
launch_arguments={
|
||||
"camera_name": "camera_04",
|
||||
"usb_port": "2-3",
|
||||
"device_num": "4",
|
||||
"sync_mode": "standalone",
|
||||
"attach_to_shared_component_container": attach_to_shared_component_container_arg,
|
||||
"component_container_name": component_container_name_arg,
|
||||
}.items(),
|
||||
)
|
||||
|
||||
delayed_left_camera = TimerAction(
|
||||
period=2.0,
|
||||
actions=args+[launch1_include],
|
||||
)
|
||||
delayed_right_camera = TimerAction(
|
||||
period=4.0,
|
||||
actions=args+[launch2_include],
|
||||
)
|
||||
delayed_rear_camera = TimerAction(
|
||||
period=6.0,
|
||||
actions=args+[launch3_include],
|
||||
)
|
||||
delayed_front_camera = TimerAction(
|
||||
period=8.0,
|
||||
actions=args+[launch4_include],
|
||||
)
|
||||
ld = LaunchDescription(
|
||||
[
|
||||
shared_orbbec_container,
|
||||
start_benchmark,
|
||||
delayed_left_camera,
|
||||
delayed_right_camera,
|
||||
delayed_rear_camera,
|
||||
delayed_front_camera,
|
||||
]
|
||||
)
|
||||
|
||||
return ld
|
||||
@@ -1,47 +0,0 @@
|
||||
# Disparity_search_offset
|
||||
|
||||
> This section describes how to use the disparity_search_offset function in the Gemini330 series cameras (minimum camera firmware version [1.4.60](https://www.orbbec.com/docs/g330-firmware-release/)).Disparity_search_offset is effective only for1280×720, 1280×800 and 640×400 resolutions of depth stream.
|
||||
|
||||
## Function Introduction
|
||||
|
||||
The definition of disparity search range: For any pixel *(u_l, v)* in the left image, by default, the corresponding disparity search range in the right image is *[ (u_l - 255, v)*, *(u_l, v) ]*, where the disparity search length is 256 and the maximum integer disparity is 255. If the starting point of the search is adjusted to *[ (u_l - 255 - offset, v)*, *(u_l - offset, v) ]*, the offset is defined as the disparity shift. Therefore, our disparity search range configuration includes both the disparity search length and the search position offset (which can also be referred to as the disparity shift).
|
||||
|
||||

|
||||
|
||||
## Parameter Introduction
|
||||
|
||||
The disparity_search_offset related parameters are set in [gemini_330_series.launch.py](../../launch/gemini_330_series.launch.py)
|
||||
|
||||
* `disparity_range_mode` : Disparity search length,can only be set to 64, 128 and 256.
|
||||
|
||||
* `disparity_search_offset` : Disparity search offset value,Disparity search offset value, can be set from 0 to 127.
|
||||
|
||||
* `disparity_offset_config` : Disparity search offset interleave frames.
|
||||
|
||||
* `offset_index0` : Frame 0 disparity search offset value.
|
||||
|
||||
* `offset_index1` : Frame 1 disparity search offset value.
|
||||
|
||||
| disparity range mode | disparity search offset | Minimum depth of inclined wall (mm) |
|
||||
| :------------------: | :---------------------: | :---------------------------------: |
|
||||
| 64 | 85 | Gemini 335L 388-406 |
|
||||
| 64 | 127 | Gemini 335L 302-317 |
|
||||
|
||||
| disparity range mode | disparity search offset | Minimum depth of inclined wall (mm) |
|
||||
| :------------------: | :---------------------: | :---------------------------------------------: |
|
||||
| 128 | 0 | Gemini 335 233-249<br />Gemini 335L 453-475 |
|
||||
| 128 | 45 | Gemini 335 172-184<br />Gemini 335L 334-349 |
|
||||
| 128 | 127 | Gemini 335 117-125<br />Gemini 335L 226-236 |
|
||||
|
||||
| disparity range mode | disparity search offset | Minimum depth of inclined wall (mm) |
|
||||
| :------------------: | :---------------------: | :---------------------------------: |
|
||||
| 256 | 85 | Gemini 335L 169-178 |
|
||||
| 256 | 127 | Gemini 335L 151-158 |
|
||||
|
||||
## Run the launch
|
||||
|
||||
Setting the disparity_search_offset parameter,`colcon build` again and run launch
|
||||
|
||||
```bash
|
||||
ros2 launch orbbec_camera gemini_330_series.launch.py
|
||||
```
|
||||
|
Before Width: | Height: | Size: 11 KiB |
@@ -1,47 +0,0 @@
|
||||
# GMSL_camera
|
||||
|
||||
> This section describes how to use GMSL camera in OrbbecSDK_ROS2.Currently, only G335Lg GMSL devices are supported, and other GMSL devices will be supported in the near future.
|
||||
|
||||
## Single GMSL camera
|
||||
|
||||
The usage of GMSL camera in OrbbecSDK_ROS2 is the same as that of Gemini 330 series camera via USB.
|
||||
|
||||
```bash
|
||||
ros2 launch orbbec_camera gemini_330_series.launch.py
|
||||
```
|
||||
|
||||
## Multi GMSL camera
|
||||
|
||||
To get the `usb_port` of the GMSL camera, plug in the camera and run the following command in the terminal:
|
||||
|
||||
```bash
|
||||
ros2 run orbbec_camera list_devices_node
|
||||
```
|
||||
|
||||
For example, the obtained gmsl camera `usb_port`: `gmsl2-1`
|
||||
|
||||
Go to the [multi_camera.launch.py](../../launch/multi_camera.launch.py) file and change the `usb_port`.
|
||||
|
||||
```bash
|
||||
ros2 launch orbbec_camera multi_camera.launch.py
|
||||
```
|
||||
|
||||
## Multi GMSL camera synced
|
||||
|
||||
First, please see how to use [multi_camera_synced](../multi_camera_synced/README.MD).
|
||||
|
||||
In addition, GMSL multi-camera synced does not require Multi-Camera Sync Hub Pro, so there is no need to set the `primary` mode. Each GMSL camera is `secondary`.
|
||||
|
||||
### Additional Parameter Settings
|
||||
|
||||
* `gmsl_trigger_fps` : set hardware soc trigger source frame rate.
|
||||
|
||||
* `enable_gmsl_trigger` : enable hardware soc trigger.
|
||||
|
||||
### Run the launch
|
||||
|
||||
Please refer to the configuration in [multi_gmsl_camera_synced.launch.py.](multi_gmsl_camera_synced.launch.py)
|
||||
|
||||
```bash
|
||||
ros2 launch orbbec_camera multi_gmsl_camera_synced.launch.py
|
||||
```
|
||||
@@ -1,57 +0,0 @@
|
||||
import os
|
||||
from ament_index_python.packages import get_package_share_directory
|
||||
from launch import LaunchDescription
|
||||
from launch_ros.actions import Node
|
||||
from launch.actions import IncludeLaunchDescription, GroupAction, TimerAction
|
||||
from launch.launch_description_sources import PythonLaunchDescriptionSource
|
||||
|
||||
|
||||
def generate_launch_description():
|
||||
# Include launch files
|
||||
package_dir = get_package_share_directory("orbbec_camera")
|
||||
launch_file_dir = os.path.join(package_dir, "launch")
|
||||
config_file_dir = os.path.join(package_dir, "config")
|
||||
config_file_path = os.path.join(config_file_dir, "camera_params.yaml")
|
||||
|
||||
launch1_include = IncludeLaunchDescription(
|
||||
PythonLaunchDescriptionSource(
|
||||
os.path.join(launch_file_dir, "gemini_330_series.launch.py")
|
||||
),
|
||||
launch_arguments={
|
||||
"camera_name": "camera_01",
|
||||
"usb_port": "gmsl2-1",
|
||||
"device_num": "2",
|
||||
"sync_mode": "secondary_synced",
|
||||
"config_file_path": config_file_path,
|
||||
"trigger_out_enabled": "false",
|
||||
"gmsl_trigger_fps": "3000",
|
||||
"enable_gmsl_trigger": "true",
|
||||
}.items(),
|
||||
)
|
||||
|
||||
launch2_include = IncludeLaunchDescription(
|
||||
PythonLaunchDescriptionSource(
|
||||
os.path.join(launch_file_dir, "gemini_330_series.launch.py")
|
||||
),
|
||||
launch_arguments={
|
||||
"camera_name": "camera_02",
|
||||
"usb_port": "gmsl2-3",
|
||||
"device_num": "2",
|
||||
"sync_mode": "secondary_synced",
|
||||
"config_file_path": config_file_path,
|
||||
"trigger_out_enabled": "false",
|
||||
"enable_gmsl_trigger": "false",
|
||||
}.items(),
|
||||
)
|
||||
|
||||
|
||||
# Launch description
|
||||
ld = LaunchDescription(
|
||||
[
|
||||
# The sending the gmsl_trigger signal gsml camera should be launched at lfirst
|
||||
TimerAction(period=0.0, actions=[GroupAction([launch1_include])]),
|
||||
TimerAction(period=2.0, actions=[GroupAction([launch2_include])]),
|
||||
]
|
||||
)
|
||||
|
||||
return ld
|
||||
@@ -1,81 +0,0 @@
|
||||
# Using interleave_ae with Gemini330 series cameras
|
||||
|
||||
> This section describes how to use interleave_ae in Gemini 330 series cameras (minimum camera firmware version [1.4.00](https://www.orbbec.com/docs/g330-firmware-release/))
|
||||
|
||||
## Parameter Introduction
|
||||
|
||||
The interleave_ae related parameters are set in [gemini_330_series.launch.py](../../launch/gemini_330_series.launch.py)
|
||||
|
||||
* `interleave_ae_mode` : Set laser or hdr interleave.
|
||||
|
||||
* `interleave_frame_enable` : enable interleave frame mode.
|
||||
|
||||
* `interleave_skip_enable` : enable skip frame mode.
|
||||
|
||||
* `interleave_skip_index` : Set 0 for skip pattern ir, set 1 for skip flood ir.
|
||||
|
||||
### interleave hdr
|
||||
|
||||
When the `interleave_ae_mode` parameter is set to `hdr` and `interleave_frame_enable `is set to `true`, interleave hdr will be enabled
|
||||
|
||||
* `hdr_index1_laser_control` : Frame 1 laser switch settings.
|
||||
|
||||
* `hdr_index1_depth_exposure` : Frame 1 depth exposure value setting, not in AE mode.
|
||||
|
||||
* `hdr_index1_depth_gain` : Frame 1 depth gain value setting, not in AE mode.
|
||||
|
||||
* `hdr_index1_ir_brightness` : Frame 1 ir gain value setting.
|
||||
|
||||
* `hdr_index1_ir_ae_max_exposure` : Frame 1 ir maximum exposure value setting in AE (auto exposure).
|
||||
|
||||
* `hdr_index0_laser_control`: Frame 0 laser switch settings.
|
||||
|
||||
* `hdr_index0_depth_exposure`: Frame 0 depth exposure value setting, not in AE mode.
|
||||
|
||||
* `hdr_index0_depth_gain` : Frame 0 depth gain value setting, not in AE mode.
|
||||
|
||||
* `hdr_index0_ir_brightness` : Frame 0 ir gain value setting.
|
||||
|
||||
* `hdr_index0_ir_ae_max_exposure` : Frame 0 ir maximum exposure value setting in AE (auto exposure).
|
||||
|
||||
### interleave laser
|
||||
|
||||
When the `interleave_ae_mode` parameter is set to `laser` and `interleave_frame_enable `is set to `true`, interleave laser will be enabled
|
||||
|
||||
* `laser_index1_laser_control` : Frame 1 laser switch settings.
|
||||
|
||||
* `laser_index1_depth_exposure` : Frame 1 depth exposure value setting, not in AE mode.
|
||||
|
||||
* `laser_index1_depth_gain` : Frame 1 depth gain value setting, not in AE mode.
|
||||
|
||||
* `laser_index1_ir_brightness` : Frame 1 ir gain value setting.
|
||||
|
||||
* `laser_index1_ir_ae_max_exposure` : Frame 1 ir maximum exposure value setting in AE (auto exposure).
|
||||
|
||||
* `laser_index0_laser_control` : Frame 0 laser switch settings.
|
||||
|
||||
* `laser_index0_depth_exposure` : Frame 0 depth exposure value setting, not in AE mode.
|
||||
|
||||
* `laser_index0_depth_gain` : Frame 0 depth gain value setting, not in AE mode.
|
||||
|
||||
* `laser_index0_ir_brightness` : Frame 0 ir gain value setting.
|
||||
|
||||
* `laser_index0_ir_ae_max_exposure` : Frame 0 ir maximum exposure value setting in AE (auto exposure).
|
||||
|
||||
## Run the launch
|
||||
|
||||
Setting the interleave_ae parameter,`colcon build` again and run launch
|
||||
|
||||
```bash
|
||||
ros2 launch orbbec_camera gemini_330_series.launch.py
|
||||
```
|
||||
|
||||
#### Example Visualization
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
## Multi_camera_synced + Interleave_ae
|
||||
|
||||
Please refer to [multi_camera_synced](../multi_camera_synced/README.MD) and [Parameter Introduction](#parameter-introduction)
|
||||
|
Before Width: | Height: | Size: 56 KiB |
|
Before Width: | Height: | Size: 234 KiB |
@@ -1,99 +0,0 @@
|
||||
## Using the Orbbec ROS package to get lower CPU usage
|
||||
|
||||
This section shows you how to reduce CPU usage for one or more cameras in a ROS 2 environment. This method only works with Gemini 330 series cameras, and the firmware version needs to be above 1.4.10(`device_preset `is set to Default).
|
||||
|
||||
The example launch files used in this section are `gemini_330_series_lower_cpu_usage.launch.py` and `multi_camera_lower_cpu_usage.launch.py`.
|
||||
|
||||
### Parameters that affect CPU usage
|
||||
|
||||
* `uvc_backend`:Global UVC Backend select on Linux,optional values: libuvc, v4l2.(v4l2 is lower)
|
||||
|
||||
* `color_format`:Color Stream coding format.(RGB is lower)
|
||||
|
||||
* `depth_registration`: Enables alignment of the depth frame to the color frame.(align_mode is set to HW lower)
|
||||
|
||||
* `enable_point_cloud`:Disables the point cloud
|
||||
|
||||
* `enable_colored_point_cloud`:Disables the RGB point cloud
|
||||
|
||||
* `filter`:decimation_filter,hdr_merge,sequenced_filter,threshold_filter,hardware_noise_removal_filter,noise_removal_filter,spatial_filter,temporal_filter,hole_filling_filter.(hardware_noise_removal_filter is lower)
|
||||
|
||||
### Data comparison
|
||||
|
||||
> Since different machines and different software environments will result in different CPU usage, the CPU improvement rate is calculated based on the device's CPU benchmark.
|
||||
> A comparing B:
|
||||
> `CPU improvement rate=(CPUA-CPUB)/CPUB*100`
|
||||
|
||||
In this example, we used two different video stream resolutions as test benchmarks to provide a performance comparison between lower and higher resolutions.(Currently, data is only provided for `uvc_backend`, `color_format`, and some `filter`)
|
||||
|
||||
#### Depth&Left_ir&Right_ir 424 * 266 15fps,Color 848 * 480 15fps
|
||||
|
||||
##### uvc_backend
|
||||
|
||||
libuvc comparing v4l2 In the same environment, CPU improvement rate is ***13.1%***
|
||||
|
||||
* libuvc is ***72.3%***
|
||||
* v4l2 is ***62.8%***
|
||||
|
||||
##### color_format
|
||||
|
||||
ROS2 color stream sets MJPG encoding format and decodes it to RGB comparing RGB encoding format (including YUYV format to RGB conversion operation cost).The CPU improvement rate under the libuvc protocol is ***14.2%*** the CPU improvement rate under the v4l2 protocol is ***30.8%***
|
||||
|
||||
* libuvc:RGB encoding format is ***63.3%***,MJPG encoding format and decoded into RGB is ***72.3%***
|
||||
* v4l2:RGB encoding format is ***48%***,MJPG encoding format and decoded into RGB is ***62.8%***
|
||||
|
||||
##### filter
|
||||
|
||||
The color stream setting RGB encoding and MJPG have no effect on filtering and are basically the same. The CPU usage of the depth stream is basically the same under the configuration of 424*266 15fps.
|
||||
|
||||
| Filter Configuration | libuvc(CPU improvement rate) | v4l2(CPU improvement rate) |
|
||||
| :------------------------------------------: | :--------------------------: | :------------------------: |
|
||||
| No filter | 63.3%(0%) | 48.0%(0%) |
|
||||
| hardware_noise_removal_filter | 61.2%(-3.3%) | 47.9%(-0.2%) |
|
||||
| hardware_noise_removal_filter+spatial_filter | 65.3%(3.2%) | 51.2%(6.7%) |
|
||||
| noise_removal_filter | 77.0%(21.6%) | 53.3%(11.0%) |
|
||||
| noise_removal_filter+spatial_filter | 78.4%(23.9%) | 54.8%(14.2%) |
|
||||
|
||||
#### Depth&Left_ir&Right_ir 848 * 480 30fps,Color 848 * 480 30fps
|
||||
|
||||
##### uvc_backend
|
||||
|
||||
libuvc comparing v4l2 In the same environment, CPU improvement rate is ***53.9%***
|
||||
|
||||
* libuvc is ***182.8%***
|
||||
* v4l2 is ***118.8%***
|
||||
|
||||
##### color_format
|
||||
|
||||
ROS2 color stream sets MJPG encoding format and decodes it to RGB comparing RGB encoding format (including YUYV format to RGB conversion operation cost).The CPU improvement rate under the libuvc protocol is ***90.2%*** the CPU improvement rate under the v4l2 protocol is ***43.1%***
|
||||
|
||||
* libuvc:RGB encoding format is ***182.8%***,MJPG encoding format and decoded into RGB is ***347.7%***
|
||||
* v4l2:RGB encoding format is ***118.8%***,MJPG encoding format and decoded into RGB is ***170.0%***
|
||||
|
||||
##### filter
|
||||
|
||||
When the depth stream is configured at 848*480 30fps, the CPU usage is significantly different.
|
||||
|
||||
| Filter Configuration | libuvc(CPU improvement rate) | v4l2(CPU improvement rate) |
|
||||
| :------------------------------------------: | :--------------------------: | :------------------------: |
|
||||
| No filter | 182.8%(0%) | 118.8%(0%) |
|
||||
| hardware_noise_removal_filter | 186.3%(1.9%) | 115.4%(-2.9%) |
|
||||
| hardware_noise_removal_filter+spatial_filter | 251.3%(37.5%) | 152.5%(28.4%) |
|
||||
| noise_removal_filter | 218.0%(16.1%) | 128.5%(8.2%) |
|
||||
| noise_removal_filter+spatial_filter | 469.6%(156.9%) | 336.7%(183.4%) |
|
||||
|
||||
### Example launch
|
||||
|
||||
This is the current example file for running the camera to achieve the lowest CPU usage, excluding the impact of filters.
|
||||
|
||||
Use the following command to start the single-camera configuration:
|
||||
|
||||
```bash
|
||||
ros2 launch orbbec_camera gemini_330_series_lower_cpu_usage.launch.py
|
||||
```
|
||||
|
||||
Use the following command to start the multi-camera configuration:
|
||||
|
||||
```bash
|
||||
roslaunch orbbec_camera multi_camera_lower_cpu_usage.launch.py
|
||||
```
|
||||
@@ -1,265 +0,0 @@
|
||||
import os
|
||||
import yaml
|
||||
from launch import LaunchDescription
|
||||
from launch.actions import DeclareLaunchArgument, OpaqueFunction, GroupAction
|
||||
from launch.substitutions import LaunchConfiguration
|
||||
from launch_ros.actions import PushRosNamespace, ComposableNodeContainer, Node
|
||||
from launch_ros.descriptions import ComposableNode
|
||||
from launch.conditions import UnlessCondition
|
||||
from launch_ros.actions import LoadComposableNodes
|
||||
|
||||
def load_yaml(file_path):
|
||||
with open(file_path, 'r') as f:
|
||||
return yaml.safe_load(f)
|
||||
|
||||
|
||||
def merge_params(default_params, yaml_params):
|
||||
for key, value in yaml_params.items():
|
||||
if key in default_params:
|
||||
default_params[key] = value
|
||||
return default_params
|
||||
|
||||
|
||||
def convert_value(value):
|
||||
if isinstance(value, str):
|
||||
try:
|
||||
return int(value)
|
||||
except ValueError:
|
||||
pass
|
||||
try:
|
||||
return float(value)
|
||||
except ValueError:
|
||||
pass
|
||||
if value.lower() == 'true':
|
||||
return True
|
||||
elif value.lower() == 'false':
|
||||
return False
|
||||
return value
|
||||
|
||||
|
||||
def load_parameters(context, args):
|
||||
default_params = {arg.name: LaunchConfiguration(arg.name).perform(context) for arg in args}
|
||||
config_file_path = LaunchConfiguration('config_file_path').perform(context)
|
||||
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'}
|
||||
return {
|
||||
key: (value if key in skip_convert else convert_value(value))
|
||||
for key, value in default_params.items()
|
||||
}
|
||||
|
||||
|
||||
def generate_launch_description():
|
||||
args = [
|
||||
DeclareLaunchArgument('camera_name', default_value='camera'),
|
||||
DeclareLaunchArgument('depth_registration', default_value='false'),
|
||||
DeclareLaunchArgument('serial_number', default_value=''),
|
||||
DeclareLaunchArgument('usb_port', default_value=''),
|
||||
DeclareLaunchArgument('device_num', default_value='1'),
|
||||
DeclareLaunchArgument('uvc_backend', default_value='v4l2'),#libuvc or v4l2
|
||||
DeclareLaunchArgument('point_cloud_qos', default_value='default'),
|
||||
DeclareLaunchArgument('enable_point_cloud', default_value='false'),
|
||||
DeclareLaunchArgument('enable_colored_point_cloud', default_value='false'),
|
||||
DeclareLaunchArgument('cloud_frame_id', default_value=''),
|
||||
DeclareLaunchArgument('connection_delay', default_value='10'),
|
||||
DeclareLaunchArgument('color_width', default_value='0'),
|
||||
DeclareLaunchArgument('color_height', default_value='0'),
|
||||
DeclareLaunchArgument('color_fps', default_value='0'),
|
||||
DeclareLaunchArgument('color_format', default_value='RGB'),
|
||||
DeclareLaunchArgument('enable_color', default_value='true'),
|
||||
DeclareLaunchArgument('color_qos', default_value='default'),
|
||||
DeclareLaunchArgument('color_camera_info_qos', default_value='default'),
|
||||
DeclareLaunchArgument('enable_color_auto_exposure', default_value='true'),
|
||||
DeclareLaunchArgument('color_exposure', default_value='-1'),
|
||||
DeclareLaunchArgument('color_gain', default_value='-1'),
|
||||
DeclareLaunchArgument('enable_color_auto_white_balance', default_value='true'),
|
||||
DeclareLaunchArgument('color_white_balance', default_value='-1'),
|
||||
DeclareLaunchArgument('color_ae_max_exposure', default_value='-1'),
|
||||
DeclareLaunchArgument('color_brightness', default_value='-1'),
|
||||
DeclareLaunchArgument('depth_width', default_value='0'),
|
||||
DeclareLaunchArgument('depth_height', default_value='0'),
|
||||
DeclareLaunchArgument('depth_fps', default_value='0'),
|
||||
DeclareLaunchArgument('depth_format', default_value='ANY'),
|
||||
DeclareLaunchArgument('enable_depth', default_value='true'),
|
||||
DeclareLaunchArgument('depth_qos', default_value='default'),
|
||||
DeclareLaunchArgument('depth_camera_info_qos', default_value='default'),
|
||||
DeclareLaunchArgument('left_ir_width', default_value='0'),
|
||||
DeclareLaunchArgument('left_ir_height', default_value='0'),
|
||||
DeclareLaunchArgument('left_ir_fps', default_value='0'),
|
||||
DeclareLaunchArgument('left_ir_format', default_value='ANY'),
|
||||
DeclareLaunchArgument('enable_left_ir', default_value='false'),
|
||||
DeclareLaunchArgument('left_ir_qos', default_value='default'),
|
||||
DeclareLaunchArgument('left_ir_camera_info_qos', default_value='default'),
|
||||
DeclareLaunchArgument('right_ir_width', default_value='0'),
|
||||
DeclareLaunchArgument('right_ir_height', default_value='0'),
|
||||
DeclareLaunchArgument('right_ir_fps', default_value='0'),
|
||||
DeclareLaunchArgument('right_ir_format', default_value='ANY'),
|
||||
DeclareLaunchArgument('enable_right_ir', default_value='false'),
|
||||
DeclareLaunchArgument('right_ir_qos', default_value='default'),
|
||||
DeclareLaunchArgument('right_ir_camera_info_qos', default_value='default'),
|
||||
DeclareLaunchArgument('enable_ir_auto_exposure', default_value='true'),
|
||||
DeclareLaunchArgument('ir_exposure', default_value='-1'),
|
||||
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('accel_rate', default_value='200hz'),
|
||||
DeclareLaunchArgument('accel_range', default_value='4g'),
|
||||
DeclareLaunchArgument('enable_gyro', default_value='false'),
|
||||
DeclareLaunchArgument('gyro_rate', default_value='200hz'),
|
||||
DeclareLaunchArgument('gyro_range', default_value='1000dps'),
|
||||
DeclareLaunchArgument('liner_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('log_level', default_value='none'),
|
||||
DeclareLaunchArgument('enable_publish_extrinsic', default_value='false'),
|
||||
DeclareLaunchArgument('enable_d2c_viewer', default_value='false'),
|
||||
DeclareLaunchArgument('enable_hardware_d2d', default_value='true'),
|
||||
DeclareLaunchArgument('enable_ldp', default_value='true'),
|
||||
DeclareLaunchArgument('enable_soft_filter', default_value='true'),
|
||||
DeclareLaunchArgument('soft_filter_max_diff', default_value='-1'),
|
||||
DeclareLaunchArgument('soft_filter_speckle_size', default_value='-1'),
|
||||
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('frames_per_trigger', default_value='2'),
|
||||
DeclareLaunchArgument('software_trigger_period', default_value='33'), # ms
|
||||
DeclareLaunchArgument('enable_frame_sync', default_value='true'),
|
||||
DeclareLaunchArgument('ordered_pc', default_value='false'),
|
||||
DeclareLaunchArgument('enable_depth_scale', default_value='true'),
|
||||
DeclareLaunchArgument('enable_decimation_filter', default_value='false'),
|
||||
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='true'),
|
||||
DeclareLaunchArgument('enable_noise_removal_filter', default_value='false'),
|
||||
DeclareLaunchArgument('enable_spatial_filter', default_value='false'),
|
||||
DeclareLaunchArgument('enable_temporal_filter', default_value='false'),
|
||||
DeclareLaunchArgument('enable_hole_filling_filter', default_value='false'),
|
||||
DeclareLaunchArgument('decimation_filter_scale', default_value='-1'),
|
||||
DeclareLaunchArgument('sequence_id_filter_id', default_value='-1'),
|
||||
DeclareLaunchArgument('threshold_filter_max', default_value='-1'),
|
||||
DeclareLaunchArgument('threshold_filter_min', default_value='-1'),
|
||||
DeclareLaunchArgument('noise_removal_filter_min_diff', default_value='256'),
|
||||
DeclareLaunchArgument('noise_removal_filter_max_size', default_value='80'),
|
||||
DeclareLaunchArgument('spatial_filter_alpha', default_value='-1.0'),
|
||||
DeclareLaunchArgument('spatial_filter_diff_threshold', default_value='-1'),
|
||||
DeclareLaunchArgument('spatial_filter_magnitude', default_value='-1'),
|
||||
DeclareLaunchArgument('spatial_filter_radius', default_value='-1'),
|
||||
DeclareLaunchArgument('temporal_filter_diff_threshold', default_value='-1.0'),
|
||||
DeclareLaunchArgument('temporal_filter_weight', default_value='-1.0'),
|
||||
DeclareLaunchArgument('hole_filling_filter_mode', default_value=''),
|
||||
DeclareLaunchArgument('hdr_merge_exposure_1', default_value='-1'),
|
||||
DeclareLaunchArgument('hdr_merge_gain_1', default_value='-1'),
|
||||
DeclareLaunchArgument('hdr_merge_exposure_2', default_value='-1'),
|
||||
DeclareLaunchArgument('hdr_merge_gain_2', default_value='-1'),
|
||||
DeclareLaunchArgument('align_mode', default_value='SW'),
|
||||
DeclareLaunchArgument('diagnostic_period', default_value='1.0'),
|
||||
DeclareLaunchArgument('enable_laser', default_value='true'),
|
||||
DeclareLaunchArgument('depth_precision', default_value=''),
|
||||
DeclareLaunchArgument('device_preset', default_value='Default'),
|
||||
DeclareLaunchArgument('retry_on_usb3_detection_failure', default_value='false'),
|
||||
DeclareLaunchArgument('laser_energy_level', default_value='-1'),
|
||||
DeclareLaunchArgument('enable_sync_host_time', default_value='true'),
|
||||
DeclareLaunchArgument('time_domain', default_value='global'),# global, device, system
|
||||
DeclareLaunchArgument('enable_color_undistortion', default_value='false'),
|
||||
DeclareLaunchArgument('config_file_path', default_value=''),
|
||||
DeclareLaunchArgument('enable_heartbeat', default_value='false'),
|
||||
DeclareLaunchArgument('gmsl_trigger_fps', default_value='3000'),
|
||||
DeclareLaunchArgument('enable_gmsl_trigger', default_value='false'),
|
||||
DeclareLaunchArgument('disparity_range_mode', default_value='-1'),
|
||||
DeclareLaunchArgument('disparity_search_offset', default_value='-1'),
|
||||
DeclareLaunchArgument('disparity_offset_config', default_value='false'),
|
||||
DeclareLaunchArgument('offset_index0', default_value='-1'),
|
||||
DeclareLaunchArgument('offset_index1', default_value='-1'),
|
||||
DeclareLaunchArgument('frame_aggregate_mode', default_value='ANY'), # full_frame、color_frame、ANY or disable
|
||||
DeclareLaunchArgument('interleave_ae_mode', default_value='laser'), # 'hdr' or 'laser'
|
||||
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_laser_control', default_value='1'),#interleave_hdr_param
|
||||
DeclareLaunchArgument('hdr_index1_depth_exposure', default_value='1'),
|
||||
DeclareLaunchArgument('hdr_index1_depth_gain', default_value='16'),
|
||||
DeclareLaunchArgument('hdr_index1_ir_brightness', default_value='20'),
|
||||
DeclareLaunchArgument('hdr_index1_ir_ae_max_exposure', default_value='2000'),
|
||||
DeclareLaunchArgument('hdr_index0_laser_control', default_value='1'),
|
||||
DeclareLaunchArgument('hdr_index0_depth_exposure', default_value='7500'),
|
||||
DeclareLaunchArgument('hdr_index0_depth_gain', default_value='16'),
|
||||
DeclareLaunchArgument('hdr_index0_ir_brightness', default_value='60'),
|
||||
DeclareLaunchArgument('hdr_index0_ir_ae_max_exposure', default_value='10000'),
|
||||
|
||||
DeclareLaunchArgument('laser_index1_laser_control', default_value='0'),#interleave_laser_param
|
||||
DeclareLaunchArgument('laser_index1_depth_exposure', default_value='3000'),
|
||||
DeclareLaunchArgument('laser_index1_depth_gain', default_value='16'),
|
||||
DeclareLaunchArgument('laser_index1_ir_brightness', default_value='60'),
|
||||
DeclareLaunchArgument('laser_index1_ir_ae_max_exposure', default_value='17000'),
|
||||
DeclareLaunchArgument('laser_index0_laser_control', default_value='1'),
|
||||
DeclareLaunchArgument('laser_index0_depth_exposure', default_value='3000'),
|
||||
DeclareLaunchArgument('laser_index0_depth_gain', default_value='16'),
|
||||
DeclareLaunchArgument('laser_index0_ir_brightness', default_value='60'),
|
||||
DeclareLaunchArgument('laser_index0_ir_ae_max_exposure', default_value='30000'),
|
||||
DeclareLaunchArgument('use_intra_process_comms', default_value='false'),
|
||||
DeclareLaunchArgument('attach_component_container_enable', default_value='false'),
|
||||
DeclareLaunchArgument('attach_component_container_name', default_value='orbbec_container'),
|
||||
|
||||
]
|
||||
|
||||
def get_params(context, args):
|
||||
return [load_parameters(context, args)]
|
||||
|
||||
def create_node_action(context, args):
|
||||
params = get_params(context, args)
|
||||
ros_distro = os.environ.get("ROS_DISTRO", "humble")
|
||||
if ros_distro == "foxy":
|
||||
return [
|
||||
Node(
|
||||
package="orbbec_camera",
|
||||
executable="orbbec_camera_node",
|
||||
name="ob_camera_node",
|
||||
namespace=LaunchConfiguration("camera_name"),
|
||||
parameters=params,
|
||||
output="screen",
|
||||
)
|
||||
]
|
||||
else:
|
||||
attach_to_shared_component_container_arg = LaunchConfiguration('attach_to_shared_component_container', default=False)
|
||||
component_container_name_arg = LaunchConfiguration('component_container_name', default='orbbec_container')
|
||||
|
||||
orbbec_container = Node(
|
||||
name=component_container_name_arg,
|
||||
package='rclcpp_components',
|
||||
executable='component_container_mt',
|
||||
output='screen',
|
||||
condition=UnlessCondition(attach_to_shared_component_container_arg)
|
||||
)
|
||||
return [
|
||||
orbbec_container,
|
||||
LoadComposableNodes(
|
||||
target_container=component_container_name_arg,
|
||||
composable_node_descriptions=[
|
||||
ComposableNode(
|
||||
namespace=LaunchConfiguration("camera_name"),
|
||||
name=LaunchConfiguration("camera_name"),
|
||||
package='orbbec_camera',
|
||||
plugin='orbbec_camera::OBCameraNodeDriver',
|
||||
parameters=params,
|
||||
extra_arguments=[{'use_intra_process_comms': LaunchConfiguration("use_intra_process_comms")}],
|
||||
)
|
||||
]
|
||||
)
|
||||
]
|
||||
|
||||
return LaunchDescription(
|
||||
args + [
|
||||
OpaqueFunction(function=lambda context: create_node_action(context, args))
|
||||
]
|
||||
)
|
||||
@@ -1,150 +0,0 @@
|
||||
import os
|
||||
from ament_index_python.packages import get_package_share_directory
|
||||
from launch import LaunchDescription
|
||||
from launch_ros.actions import Node,LoadComposableNodes
|
||||
from launch.actions import IncludeLaunchDescription, GroupAction, TimerAction
|
||||
from launch.launch_description_sources import PythonLaunchDescriptionSource
|
||||
from launch.actions import DeclareLaunchArgument
|
||||
from launch.conditions import UnlessCondition, IfCondition
|
||||
from launch.substitutions import LaunchConfiguration
|
||||
from launch.substitutions import TextSubstitution
|
||||
from launch_ros.descriptions import ComposableNode
|
||||
|
||||
def load_yaml(file_path):
|
||||
with open(file_path, 'r') as f:
|
||||
return yaml.safe_load(f)
|
||||
|
||||
|
||||
def merge_params(default_params, yaml_params):
|
||||
for key, value in yaml_params.items():
|
||||
if key in default_params:
|
||||
default_params[key] = value
|
||||
return default_params
|
||||
|
||||
|
||||
def convert_value(value):
|
||||
if isinstance(value, str):
|
||||
try:
|
||||
return int(value)
|
||||
except ValueError:
|
||||
pass
|
||||
try:
|
||||
return float(value)
|
||||
except ValueError:
|
||||
pass
|
||||
if value.lower() == 'true':
|
||||
return True
|
||||
elif value.lower() == 'false':
|
||||
return False
|
||||
return value
|
||||
|
||||
|
||||
def load_parameters(context, args):
|
||||
default_params = {arg.name: LaunchConfiguration(arg.name).perform(context) for arg in args}
|
||||
config_file_path = LaunchConfiguration('config_file_path').perform(context)
|
||||
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'}
|
||||
return {
|
||||
key: (value if key in skip_convert else convert_value(value))
|
||||
for key, value in default_params.items()
|
||||
}
|
||||
def generate_launch_description():
|
||||
# Include launch files
|
||||
package_dir = get_package_share_directory("orbbec_camera")
|
||||
launch_file_dir = os.path.join(package_dir, "examples/lower_cpu_usage")
|
||||
|
||||
attach_to_shared_component_container_arg = LaunchConfiguration('attach_to_shared_component_container', default=False)
|
||||
component_container_name_arg = LaunchConfiguration('component_container_name', default='shared_orbbec_container')
|
||||
|
||||
shared_orbbec_container = Node(
|
||||
name=component_container_name_arg,
|
||||
package="rclcpp_components",
|
||||
executable="component_container_mt",
|
||||
output="screen",
|
||||
condition=UnlessCondition(attach_to_shared_component_container_arg),
|
||||
)
|
||||
|
||||
attach_to_shared_component_container_arg = TextSubstitution(text="true")
|
||||
|
||||
launch1_include = IncludeLaunchDescription(
|
||||
PythonLaunchDescriptionSource(
|
||||
os.path.join(launch_file_dir, "gemini_330_series_lower_cpu_usage.launch.py")
|
||||
),
|
||||
launch_arguments={
|
||||
"camera_name": "camera_01",
|
||||
"usb_port": "2-7",
|
||||
"device_num": "4",
|
||||
"sync_mode": "standalone",
|
||||
"attach_to_shared_component_container": attach_to_shared_component_container_arg,
|
||||
"component_container_name": component_container_name_arg,
|
||||
}.items(),
|
||||
)
|
||||
launch2_include = IncludeLaunchDescription(
|
||||
PythonLaunchDescriptionSource(
|
||||
os.path.join(launch_file_dir, "gemini_330_series_lower_cpu_usage.launch.py")
|
||||
),
|
||||
launch_arguments={
|
||||
"camera_name": "camera_02",
|
||||
"usb_port": "2-2",
|
||||
"device_num": "4",
|
||||
"sync_mode": "standalone",
|
||||
"attach_to_shared_component_container": attach_to_shared_component_container_arg,
|
||||
"component_container_name": component_container_name_arg,
|
||||
}.items(),
|
||||
)
|
||||
launch3_include = IncludeLaunchDescription(
|
||||
PythonLaunchDescriptionSource(
|
||||
os.path.join(launch_file_dir, "gemini_330_series_lower_cpu_usage.launch.py")
|
||||
),
|
||||
launch_arguments={
|
||||
"camera_name": "camera_03",
|
||||
"usb_port": "2-6",
|
||||
"device_num": "4",
|
||||
"sync_mode": "standalone",
|
||||
"attach_to_shared_component_container": attach_to_shared_component_container_arg,
|
||||
"component_container_name": component_container_name_arg,
|
||||
}.items(),
|
||||
)
|
||||
launch4_include = IncludeLaunchDescription(
|
||||
PythonLaunchDescriptionSource(
|
||||
os.path.join(launch_file_dir, "gemini_330_series_lower_cpu_usage.launch.py")
|
||||
),
|
||||
launch_arguments={
|
||||
"camera_name": "camera_04",
|
||||
"usb_port": "2-3",
|
||||
"device_num": "4",
|
||||
"sync_mode": "standalone",
|
||||
"attach_to_shared_component_container": attach_to_shared_component_container_arg,
|
||||
"component_container_name": component_container_name_arg,
|
||||
}.items(),
|
||||
)
|
||||
|
||||
delayed_left_camera = TimerAction(
|
||||
period=2.0,
|
||||
actions=[launch1_include],
|
||||
)
|
||||
delayed_right_camera = TimerAction(
|
||||
period=4.0,
|
||||
actions=[launch2_include],
|
||||
)
|
||||
delayed_rear_camera = TimerAction(
|
||||
period=6.0,
|
||||
actions=[launch3_include],
|
||||
)
|
||||
delayed_front_camera = TimerAction(
|
||||
period=8.0,
|
||||
actions=[launch4_include],
|
||||
)
|
||||
ld = LaunchDescription(
|
||||
[
|
||||
shared_orbbec_container,
|
||||
TimerAction(period=0.0, actions=[GroupAction([delayed_left_camera])]),
|
||||
TimerAction(period=2.0, actions=[GroupAction([delayed_right_camera])]),
|
||||
TimerAction(period=4.0, actions=[GroupAction([delayed_rear_camera])]),
|
||||
TimerAction(period=6.0, actions=[GroupAction([delayed_front_camera])]),
|
||||
]
|
||||
)
|
||||
|
||||
return ld
|
||||
@@ -1,55 +0,0 @@
|
||||
# Multi_camera synced Instructions
|
||||
|
||||
> The purpose of this document is to explain how to use multi-camera synced with OrbbecSDK_ROS2
|
||||
|
||||
## Setup instructions
|
||||
|
||||
* Please read the Multi-Camera Synchronization Setup Guide:[Multi-Camera Synchronization Setup](https://www.orbbec.com/docs/set-up-cameras-for-external-synchronization_v1-2/)
|
||||
* Make sure the camera is correctly connected to the multi-camera synchronizer.
|
||||
|
||||

|
||||
|
||||
### Checking camera port with OrbbecSDK_ROS2
|
||||
|
||||
```bash
|
||||
ros2 run orbbec_camera list_devices_node
|
||||
```
|
||||
|
||||
### OrbbecSDK_ROS2 multi-camera synced configuration
|
||||
|
||||
Open multi_camera_synced.launch.py, and configure the camera settings as shown below:
|
||||
|
||||

|
||||
|
||||
1. `gemini_330_series.launch.py` is the launch file for starting the camera.
|
||||
|
||||
2. Set `camera_name` to `G330_0`. For example, the published color image topic will be `/G330_0/color/image_raw`.
|
||||
|
||||
3. Set `usb_port` to `2-2`, indicating that the camera device on port `2-2` is being used. This value can be found in the output of the `ros2 run orbbec_camera list_devices_node` command.
|
||||
|
||||
4. Set `device_num` to `2`, meaning two cameras will be used.
|
||||
|
||||
5. Set `sync_mode` to `primary` to indicate that the `2-7` camera device is in primary mode. The multi-camera sync mode options can be found in the figure below.
|
||||
|
||||
6. Parameters from the `config_file_path` can override the parameters set in `gemini_330_series.launch.py` (optional).
|
||||
|
||||
7. For slave cameras, set `trigger_out_enabled` to false.
|
||||
|
||||
| **Pattern Nam**e | **Setting effect description** |
|
||||
| ---------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| free_run | -Support different frame rate settings<br />The -8-pin synchronization interface does not support external output of synchronization-related signals |
|
||||
| standalone(default) | ● Same as Primary by default<br />● Built-in RGBD frame synchronization<br />● 8-pin synchronous interface does not output signals to the outside by default |
|
||||
| primary | ● Set as primary camera<br />● 8-pin synchronous interface output signal to external device |
|
||||
| secondary | ● Set as secondary (passive synchronization; When there is a hardware continuous trigger signal input from the outside and the continuous trigger signal matches the currently set frame rate, the image is collected according to the external trigger signal; When there is no external trigger signal, the flow is stopped)<br />● 8-pin synchronous interface output signal to external device |
|
||||
| secondary_synced | ● Set to secondary synchronization (passive synchronization; When there is a hardware continuous trigger signal input from the outside and the continuous trigger signal matches the currently set frame rate, the image is collected according to the external trigger signal; When there is no external trigger signal, the image is collected according to the internal trigger signal at the set frame rate)<br />● 8-pin synchronous interface output signal to external device |
|
||||
| hardware_triggering | ● Set as hardware trigger (passive trigger; When there is a hardware trigger signal input from the outside and the trigger signal time interval is not less than the current upper limit, the image is collected according to the external trigger signal; When there is no external trigger signal, the image is not collected)<br />● 8-pin synchronous interface output signal to external device |
|
||||
| software_triggering | ● Set as software trigger (passive trigger; When there is a trigger command input from the host computer and the trigger command time interval is not less than the current upper limit, the image is collected according to the trigger command; When there is no trigger command, the image is not collected)<br />● 8-pin synchronous interface output signal to external device |
|
||||
|
||||
* The master camera should be launched last.
|
||||
* Ideally, there should be a 2-second delay between starting each camera.
|
||||
|
||||
### Run the following command to start the multi-camera synced
|
||||
|
||||
```bash
|
||||
ros2 launch orbbec_camera multi_camera_synced.launch.py
|
||||
```
|
||||
|
Before Width: | Height: | Size: 23 KiB |
|
Before Width: | Height: | Size: 87 KiB |
@@ -1,155 +0,0 @@
|
||||
# Multi_camera_synced_verification_tool
|
||||
|
||||
> This article will introduce how to verify the synchronization accuracy of multi-camera synchronization.
|
||||
>
|
||||
> First, please see how to use [multi_camera_synced](../multi_camera_synced/README.MD).
|
||||
|
||||
## Directory Structure
|
||||
|
||||
```plaintext
|
||||
.
|
||||
├── multicamera_sync/
|
||||
│ ├── output/
|
||||
│ ├──20250218102900/
|
||||
│ ├──DevicesInfo.txt
|
||||
│ ├──StreamProfileInfo.txt
|
||||
│ ├── Python/
|
||||
│ ├──Config.ini
|
||||
├── gemini_330_series_synced_verify.launch.py
|
||||
├── multi_camera_synced_verify.launch.py
|
||||
```
|
||||
|
||||
### multicamera_sync
|
||||
|
||||
* `gemini_330_series_synced_verify.launch.py` : Single camera runs launch, which provides the camera running node for multi_camera_synced_verify.launch.py.
|
||||
* `multi_camera_synced_verify.launch.py` : Multi camer synced + launch of save_rgbir tool.
|
||||
|
||||
#### output
|
||||
|
||||
> The `ouput` folder is the folder where the camera pictures are output
|
||||
|
||||
In the output example provided
|
||||
|
||||
* `20250218102900` : Represents the camera image information collected at 10:29:00 on February 18, 2025.
|
||||
* `TotalModeFrames` : Camera image information storage directory.
|
||||
* `results-2025-02-25_163648` : The result after analyzing and matching the image information of TotalModeFrames.
|
||||
* `DevicesInfo.txt` : Camera equipment basic information (need to be modified).
|
||||
* `StreamProfileInfo.txt` : Camera video stream information (no need to modify).
|
||||
|
||||
#### Python
|
||||
|
||||
* `Config.ini` : Configuration file for Python analysis script (need to be modified).
|
||||
|
||||
## Preparation for operation
|
||||
|
||||
### save_rgbir node
|
||||
|
||||
Edit multi_camera_synced_verify.launch.py and fill in the activated camera device,we can find that save_rgbir is started at the end.
|
||||
|
||||
```python
|
||||
# Launch description
|
||||
ld = LaunchDescription(
|
||||
[
|
||||
shared_orbbec_container,
|
||||
TimerAction(period=0.0, actions=[GroupAction([launch2_include])]),
|
||||
TimerAction(period=2.0, actions=[GroupAction([launch1_include])]),
|
||||
# The primary camera should be launched at last
|
||||
TimerAction(period=6.0, actions=[GroupAction([save_rgbir])]),
|
||||
# save_rgbir is synced verification tool
|
||||
]
|
||||
)
|
||||
|
||||
return ld
|
||||
```
|
||||
|
||||
save_rgbir is a tool for saving images. The configuration file of this tool is in [multi_save_rgbir_params.json](../../config/tools/multisavergbir/multi_save_rgbir_params.json).
|
||||
|
||||
```json
|
||||
{
|
||||
"save_rgbir_params": {
|
||||
"time_domain": "global",
|
||||
"usb_ports": [
|
||||
"2-1",
|
||||
"2-3"
|
||||
],
|
||||
"camera_name": [
|
||||
"camera_01",
|
||||
"camera_02"
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
* `time_domain` : Timestamp Type
|
||||
* `usb_ports` : "primary", "secondary 1", "secondary 2", "secondary 3", fill in as many usb_ports as there are cameras
|
||||
* `camera_name` : The name of the camera setting, for example: camera_01
|
||||
|
||||
### DevicesInfo.txt
|
||||
|
||||
Edit DevicesInfo.txt. Only the `primarySerialNumber`, `index` and `serialNumber` parameters need to be changed. Other parameters do not need to be changed.Refer to the example of [20250218102900](./multicamera_sync/output/20250218102900).
|
||||
|
||||
* `primarySerialNumber` : The SN serial number of the primary camera
|
||||
* `index` : Camera index
|
||||
* `serialNumber` : The SN serial number of the camera
|
||||
|
||||
### Config.ini
|
||||
|
||||
Edit Config.ini.Modify `frameRate` and `tspRangeThreshold`.
|
||||
|
||||
## Run this example
|
||||
|
||||
### Run launch and save camera pictures
|
||||
|
||||
* Frst terminal
|
||||
|
||||
```bash
|
||||
ros2 launch orbbec_camera multi_camera_synced_verify.launch.py
|
||||
```
|
||||
|
||||
* Second terminal
|
||||
|
||||
```bash
|
||||
ros2 service call /save_rgbir/start_capture orbbec_camera_msgs/srv/SetInt32 '{data: 100}'
|
||||
```
|
||||
|
||||
When the terminal displays "over", the image is saved.A new multicamera_sync folder will be generated under the workspace.
|
||||
|
||||
#### Camera pictures naming format
|
||||
|
||||
Take [color_SNCP1E5420006D_Index0_g1739874543227_f0_s1739874543327_e50_d16_.jpg](./multicamera_sync/output/20250218102900/TotalModeFrames/SNCP1E5420006D_Index0/color_SNCP1E5420006D_Index0_g1739874543227_f0_s1739874543327_e50_d16_.jpg) as an example
|
||||
|
||||
* `color` : This image is a snapshot of the color stream.
|
||||
* `SNCP1E5420006D` : The camera's SN serial number is CP1E5420006D.
|
||||
* `Index0` : Camera 0 (usually referred to primary camera).
|
||||
* `g1739874543227` : “g” represents the global timestamp, which means the global timestamp of this frame is 1739874543227.
|
||||
* `f0` : The 0th picture of the color stream acquisition of this camera.
|
||||
* `s1739874543327` : "s" represents the timestamp of the current system, which means the current system timestamp of this frame is 1739874543327.
|
||||
* `e50` : The exposure of this frame is 50.
|
||||
* `d16` : The gain of this frame is 16.
|
||||
|
||||
### Analyzing camera image data
|
||||
|
||||
You need to copy the modified [Pyhotn folder](./multicamera_sync/Python) to the new multi_camera_synced subdirectory, and copy the modified [DevicesInfo.txt ](./multicamera_sync/output/20250218102900/DevicesInfo.txt)and [StreamProfileInfo.txt](./multicamera_sync/output/20250218102900/StreamProfileInfo.txt) to the same level directory as the TotalModeFrames folder.
|
||||
|
||||
* Finally everything is ready, run the python script
|
||||
|
||||
```bash
|
||||
cd multicamera_sync/Python
|
||||
python3 SyncFramesMain.py
|
||||
```
|
||||
|
||||
After the operation is successful, you can view the synchronization effect in the r `esults folder`
|
||||
|
||||
## Files that need to be changed
|
||||
|
||||
### Analysis tools
|
||||
|
||||
* [multi_save_rgbir_params.json](../../config/tools/multisavergbir/multi_save_rgbir_params.json)
|
||||
* [DevicesInfo.txt ](./multicamera_sync/output/20250218102900/DevicesInfo.txt)
|
||||
* [Config.ini](./multicamera_sync/Python/Config.ini)
|
||||
|
||||
### Camera Configuration
|
||||
|
||||
[camera_params.yaml](../../config/camera_params.yaml)(Camera startup parameter settings)
|
||||
|
||||
[multi_camera_synced_verify.launch.py](./multi_camera_synced_verify.launch.py)
|
||||
@@ -1,265 +0,0 @@
|
||||
import os
|
||||
import yaml
|
||||
from launch import LaunchDescription
|
||||
from launch.actions import DeclareLaunchArgument, OpaqueFunction, GroupAction
|
||||
from launch.substitutions import LaunchConfiguration
|
||||
from launch_ros.actions import PushRosNamespace, ComposableNodeContainer, Node
|
||||
from launch_ros.descriptions import ComposableNode
|
||||
from launch.conditions import UnlessCondition
|
||||
from launch_ros.actions import LoadComposableNodes
|
||||
|
||||
def load_yaml(file_path):
|
||||
with open(file_path, 'r') as f:
|
||||
return yaml.safe_load(f)
|
||||
|
||||
|
||||
def merge_params(default_params, yaml_params):
|
||||
for key, value in yaml_params.items():
|
||||
if key in default_params:
|
||||
default_params[key] = value
|
||||
return default_params
|
||||
|
||||
|
||||
def convert_value(value):
|
||||
if isinstance(value, str):
|
||||
try:
|
||||
return int(value)
|
||||
except ValueError:
|
||||
pass
|
||||
try:
|
||||
return float(value)
|
||||
except ValueError:
|
||||
pass
|
||||
if value.lower() == 'true':
|
||||
return True
|
||||
elif value.lower() == 'false':
|
||||
return False
|
||||
return value
|
||||
|
||||
|
||||
def load_parameters(context, args):
|
||||
default_params = {arg.name: LaunchConfiguration(arg.name).perform(context) for arg in args}
|
||||
config_file_path = LaunchConfiguration('config_file_path').perform(context)
|
||||
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'}
|
||||
return {
|
||||
key: (value if key in skip_convert else convert_value(value))
|
||||
for key, value in default_params.items()
|
||||
}
|
||||
|
||||
|
||||
def generate_launch_description():
|
||||
args = [
|
||||
DeclareLaunchArgument('camera_name', default_value='camera'),
|
||||
DeclareLaunchArgument('depth_registration', default_value='true'),
|
||||
DeclareLaunchArgument('serial_number', default_value=''),
|
||||
DeclareLaunchArgument('usb_port', default_value=''),
|
||||
DeclareLaunchArgument('device_num', default_value='1'),
|
||||
DeclareLaunchArgument('uvc_backend', default_value='libuvc'),#libuvc or v4l2
|
||||
DeclareLaunchArgument('point_cloud_qos', default_value='default'),
|
||||
DeclareLaunchArgument('enable_point_cloud', default_value='true'),
|
||||
DeclareLaunchArgument('enable_colored_point_cloud', default_value='false'),
|
||||
DeclareLaunchArgument('cloud_frame_id', default_value=''),
|
||||
DeclareLaunchArgument('connection_delay', default_value='10'),
|
||||
DeclareLaunchArgument('color_width', default_value='0'),
|
||||
DeclareLaunchArgument('color_height', default_value='0'),
|
||||
DeclareLaunchArgument('color_fps', default_value='0'),
|
||||
DeclareLaunchArgument('color_format', default_value='ANY'),
|
||||
DeclareLaunchArgument('enable_color', default_value='true'),
|
||||
DeclareLaunchArgument('color_qos', default_value='default'),
|
||||
DeclareLaunchArgument('color_camera_info_qos', default_value='default'),
|
||||
DeclareLaunchArgument('enable_color_auto_exposure', default_value='true'),
|
||||
DeclareLaunchArgument('color_exposure', default_value='-1'),
|
||||
DeclareLaunchArgument('color_gain', default_value='-1'),
|
||||
DeclareLaunchArgument('enable_color_auto_white_balance', default_value='true'),
|
||||
DeclareLaunchArgument('color_white_balance', default_value='-1'),
|
||||
DeclareLaunchArgument('color_ae_max_exposure', default_value='-1'),
|
||||
DeclareLaunchArgument('color_brightness', default_value='-1'),
|
||||
DeclareLaunchArgument('depth_width', default_value='0'),
|
||||
DeclareLaunchArgument('depth_height', default_value='0'),
|
||||
DeclareLaunchArgument('depth_fps', default_value='0'),
|
||||
DeclareLaunchArgument('depth_format', default_value='ANY'),
|
||||
DeclareLaunchArgument('enable_depth', default_value='true'),
|
||||
DeclareLaunchArgument('depth_qos', default_value='default'),
|
||||
DeclareLaunchArgument('depth_camera_info_qos', default_value='default'),
|
||||
DeclareLaunchArgument('left_ir_width', default_value='0'),
|
||||
DeclareLaunchArgument('left_ir_height', default_value='0'),
|
||||
DeclareLaunchArgument('left_ir_fps', default_value='0'),
|
||||
DeclareLaunchArgument('left_ir_format', default_value='ANY'),
|
||||
DeclareLaunchArgument('enable_left_ir', default_value='false'),
|
||||
DeclareLaunchArgument('left_ir_qos', default_value='default'),
|
||||
DeclareLaunchArgument('left_ir_camera_info_qos', default_value='default'),
|
||||
DeclareLaunchArgument('right_ir_width', default_value='0'),
|
||||
DeclareLaunchArgument('right_ir_height', default_value='0'),
|
||||
DeclareLaunchArgument('right_ir_fps', default_value='0'),
|
||||
DeclareLaunchArgument('right_ir_format', default_value='ANY'),
|
||||
DeclareLaunchArgument('enable_right_ir', default_value='false'),
|
||||
DeclareLaunchArgument('right_ir_qos', default_value='default'),
|
||||
DeclareLaunchArgument('right_ir_camera_info_qos', default_value='default'),
|
||||
DeclareLaunchArgument('enable_ir_auto_exposure', default_value='true'),
|
||||
DeclareLaunchArgument('ir_exposure', default_value='-1'),
|
||||
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('accel_rate', default_value='200hz'),
|
||||
DeclareLaunchArgument('accel_range', default_value='4g'),
|
||||
DeclareLaunchArgument('enable_gyro', default_value='false'),
|
||||
DeclareLaunchArgument('gyro_rate', default_value='200hz'),
|
||||
DeclareLaunchArgument('gyro_range', default_value='1000dps'),
|
||||
DeclareLaunchArgument('liner_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('log_level', default_value='none'),
|
||||
DeclareLaunchArgument('enable_publish_extrinsic', default_value='false'),
|
||||
DeclareLaunchArgument('enable_d2c_viewer', default_value='false'),
|
||||
DeclareLaunchArgument('enable_hardware_d2d', default_value='true'),
|
||||
DeclareLaunchArgument('enable_ldp', default_value='true'),
|
||||
DeclareLaunchArgument('enable_soft_filter', default_value='true'),
|
||||
DeclareLaunchArgument('soft_filter_max_diff', default_value='-1'),
|
||||
DeclareLaunchArgument('soft_filter_speckle_size', default_value='-1'),
|
||||
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('frames_per_trigger', default_value='2'),
|
||||
DeclareLaunchArgument('software_trigger_period', default_value='33'), # ms
|
||||
DeclareLaunchArgument('enable_frame_sync', default_value='true'),
|
||||
DeclareLaunchArgument('ordered_pc', default_value='false'),
|
||||
DeclareLaunchArgument('enable_depth_scale', default_value='true'),
|
||||
DeclareLaunchArgument('enable_decimation_filter', default_value='false'),
|
||||
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='true'),
|
||||
DeclareLaunchArgument('enable_noise_removal_filter', default_value='true'),
|
||||
DeclareLaunchArgument('enable_spatial_filter', default_value='false'),
|
||||
DeclareLaunchArgument('enable_temporal_filter', default_value='false'),
|
||||
DeclareLaunchArgument('enable_hole_filling_filter', default_value='false'),
|
||||
DeclareLaunchArgument('decimation_filter_scale', default_value='-1'),
|
||||
DeclareLaunchArgument('sequence_id_filter_id', default_value='-1'),
|
||||
DeclareLaunchArgument('threshold_filter_max', default_value='-1'),
|
||||
DeclareLaunchArgument('threshold_filter_min', default_value='-1'),
|
||||
DeclareLaunchArgument('noise_removal_filter_min_diff', default_value='256'),
|
||||
DeclareLaunchArgument('noise_removal_filter_max_size', default_value='80'),
|
||||
DeclareLaunchArgument('spatial_filter_alpha', default_value='-1.0'),
|
||||
DeclareLaunchArgument('spatial_filter_diff_threshold', default_value='-1'),
|
||||
DeclareLaunchArgument('spatial_filter_magnitude', default_value='-1'),
|
||||
DeclareLaunchArgument('spatial_filter_radius', default_value='-1'),
|
||||
DeclareLaunchArgument('temporal_filter_diff_threshold', default_value='-1.0'),
|
||||
DeclareLaunchArgument('temporal_filter_weight', default_value='-1.0'),
|
||||
DeclareLaunchArgument('hole_filling_filter_mode', default_value=''),
|
||||
DeclareLaunchArgument('hdr_merge_exposure_1', default_value='-1'),
|
||||
DeclareLaunchArgument('hdr_merge_gain_1', default_value='-1'),
|
||||
DeclareLaunchArgument('hdr_merge_exposure_2', default_value='-1'),
|
||||
DeclareLaunchArgument('hdr_merge_gain_2', default_value='-1'),
|
||||
DeclareLaunchArgument('align_mode', default_value='SW'),
|
||||
DeclareLaunchArgument('diagnostic_period', default_value='1.0'),
|
||||
DeclareLaunchArgument('enable_laser', default_value='true'),
|
||||
DeclareLaunchArgument('depth_precision', default_value=''),
|
||||
DeclareLaunchArgument('device_preset', default_value='Default'),
|
||||
DeclareLaunchArgument('retry_on_usb3_detection_failure', default_value='false'),
|
||||
DeclareLaunchArgument('laser_energy_level', default_value='-1'),
|
||||
DeclareLaunchArgument('enable_sync_host_time', default_value='true'),
|
||||
DeclareLaunchArgument('time_domain', default_value='global'),# global, device, system
|
||||
DeclareLaunchArgument('enable_color_undistortion', default_value='false'),
|
||||
DeclareLaunchArgument('config_file_path', default_value=''),
|
||||
DeclareLaunchArgument('enable_heartbeat', default_value='false'),
|
||||
DeclareLaunchArgument('gmsl_trigger_fps', default_value='3000'),
|
||||
DeclareLaunchArgument('enable_gmsl_trigger', default_value='false'),
|
||||
DeclareLaunchArgument('disparity_range_mode', default_value='-1'),
|
||||
DeclareLaunchArgument('disparity_search_offset', default_value='-1'),
|
||||
DeclareLaunchArgument('disparity_offset_config', default_value='false'),
|
||||
DeclareLaunchArgument('offset_index0', default_value='-1'),
|
||||
DeclareLaunchArgument('offset_index1', default_value='-1'),
|
||||
DeclareLaunchArgument('frame_aggregate_mode', default_value='ANY'), # full_frame、color_frame、ANY or disable
|
||||
DeclareLaunchArgument('interleave_ae_mode', default_value='laser'), # 'hdr' or 'laser'
|
||||
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_laser_control', default_value='1'),#interleave_hdr_param
|
||||
DeclareLaunchArgument('hdr_index1_depth_exposure', default_value='1'),
|
||||
DeclareLaunchArgument('hdr_index1_depth_gain', default_value='16'),
|
||||
DeclareLaunchArgument('hdr_index1_ir_brightness', default_value='20'),
|
||||
DeclareLaunchArgument('hdr_index1_ir_ae_max_exposure', default_value='2000'),
|
||||
DeclareLaunchArgument('hdr_index0_laser_control', default_value='1'),
|
||||
DeclareLaunchArgument('hdr_index0_depth_exposure', default_value='7500'),
|
||||
DeclareLaunchArgument('hdr_index0_depth_gain', default_value='16'),
|
||||
DeclareLaunchArgument('hdr_index0_ir_brightness', default_value='60'),
|
||||
DeclareLaunchArgument('hdr_index0_ir_ae_max_exposure', default_value='10000'),
|
||||
|
||||
DeclareLaunchArgument('laser_index1_laser_control', default_value='0'),#interleave_laser_param
|
||||
DeclareLaunchArgument('laser_index1_depth_exposure', default_value='3000'),
|
||||
DeclareLaunchArgument('laser_index1_depth_gain', default_value='16'),
|
||||
DeclareLaunchArgument('laser_index1_ir_brightness', default_value='60'),
|
||||
DeclareLaunchArgument('laser_index1_ir_ae_max_exposure', default_value='17000'),
|
||||
DeclareLaunchArgument('laser_index0_laser_control', default_value='1'),
|
||||
DeclareLaunchArgument('laser_index0_depth_exposure', default_value='3000'),
|
||||
DeclareLaunchArgument('laser_index0_depth_gain', default_value='16'),
|
||||
DeclareLaunchArgument('laser_index0_ir_brightness', default_value='60'),
|
||||
DeclareLaunchArgument('laser_index0_ir_ae_max_exposure', default_value='30000'),
|
||||
DeclareLaunchArgument('use_intra_process_comms', default_value='false'),
|
||||
DeclareLaunchArgument('attach_component_container_enable', default_value='false'),
|
||||
DeclareLaunchArgument('attach_component_container_name', default_value='orbbec_container'),
|
||||
|
||||
]
|
||||
|
||||
def get_params(context, args):
|
||||
return [load_parameters(context, args)]
|
||||
|
||||
def create_node_action(context, args):
|
||||
params = get_params(context, args)
|
||||
ros_distro = os.environ.get("ROS_DISTRO", "humble")
|
||||
if ros_distro == "foxy":
|
||||
return [
|
||||
Node(
|
||||
package="orbbec_camera",
|
||||
executable="orbbec_camera_node",
|
||||
name="ob_camera_node",
|
||||
namespace=LaunchConfiguration("camera_name"),
|
||||
parameters=params,
|
||||
output="screen",
|
||||
)
|
||||
]
|
||||
else:
|
||||
attach_to_shared_component_container_arg = LaunchConfiguration('attach_to_shared_component_container', default=False)
|
||||
component_container_name_arg = LaunchConfiguration('component_container_name', default='orbbec_container')
|
||||
|
||||
orbbec_container = Node(
|
||||
name=component_container_name_arg,
|
||||
package='rclcpp_components',
|
||||
executable='component_container_mt',
|
||||
output='screen',
|
||||
condition=UnlessCondition(attach_to_shared_component_container_arg)
|
||||
)
|
||||
return [
|
||||
orbbec_container,
|
||||
LoadComposableNodes(
|
||||
target_container=component_container_name_arg,
|
||||
composable_node_descriptions=[
|
||||
ComposableNode(
|
||||
namespace=LaunchConfiguration("camera_name"),
|
||||
name=LaunchConfiguration("camera_name"),
|
||||
package='orbbec_camera',
|
||||
plugin='orbbec_camera::OBCameraNodeDriver',
|
||||
parameters=params,
|
||||
extra_arguments=[{'use_intra_process_comms': LaunchConfiguration("use_intra_process_comms")}],
|
||||
)
|
||||
]
|
||||
)
|
||||
]
|
||||
|
||||
return LaunchDescription(
|
||||
args + [
|
||||
OpaqueFunction(function=lambda context: create_node_action(context, args))
|
||||
]
|
||||
)
|
||||
@@ -1,126 +0,0 @@
|
||||
import os
|
||||
from ament_index_python.packages import get_package_share_directory
|
||||
from launch import LaunchDescription
|
||||
from launch_ros.actions import Node, LoadComposableNodes
|
||||
from launch.actions import IncludeLaunchDescription, GroupAction, TimerAction
|
||||
from launch.launch_description_sources import PythonLaunchDescriptionSource
|
||||
from launch.actions import DeclareLaunchArgument
|
||||
from launch.conditions import UnlessCondition, IfCondition
|
||||
from launch.substitutions import LaunchConfiguration
|
||||
from launch.substitutions import TextSubstitution
|
||||
from launch_ros.descriptions import ComposableNode
|
||||
|
||||
|
||||
def load_yaml(file_path):
|
||||
with open(file_path, "r") as f:
|
||||
return yaml.safe_load(f)
|
||||
|
||||
|
||||
def merge_params(default_params, yaml_params):
|
||||
for key, value in yaml_params.items():
|
||||
if key in default_params:
|
||||
default_params[key] = value
|
||||
return default_params
|
||||
|
||||
|
||||
def convert_value(value):
|
||||
if isinstance(value, str):
|
||||
try:
|
||||
return int(value)
|
||||
except ValueError:
|
||||
pass
|
||||
try:
|
||||
return float(value)
|
||||
except ValueError:
|
||||
pass
|
||||
if value.lower() == "true":
|
||||
return True
|
||||
elif value.lower() == "false":
|
||||
return False
|
||||
return value
|
||||
|
||||
|
||||
def generate_launch_description():
|
||||
# Include launch files
|
||||
package_dir = get_package_share_directory("orbbec_camera")
|
||||
launch_file_dir = os.path.join(
|
||||
package_dir, "examples/multi_camera_synced_verification_tool"
|
||||
)
|
||||
config_file_dir = os.path.join(package_dir, "config")
|
||||
config_file_path = os.path.join(config_file_dir, "camera_params.yaml")
|
||||
secondary_config_file_path = os.path.join(config_file_dir, "camera_secondary_params.yaml")
|
||||
|
||||
attach_to_shared_component_container_arg = LaunchConfiguration(
|
||||
"attach_to_shared_component_container", default=False
|
||||
)
|
||||
component_container_name_arg = LaunchConfiguration(
|
||||
"component_container_name", default="shared_orbbec_container"
|
||||
)
|
||||
|
||||
shared_orbbec_container = Node(
|
||||
name=component_container_name_arg,
|
||||
package="rclcpp_components",
|
||||
executable="component_container_mt",
|
||||
output="screen",
|
||||
condition=UnlessCondition(attach_to_shared_component_container_arg),
|
||||
)
|
||||
|
||||
save_rgbir = LoadComposableNodes(
|
||||
target_container=component_container_name_arg,
|
||||
composable_node_descriptions=[
|
||||
ComposableNode(
|
||||
namespace="save_rgbir",
|
||||
name="save_rgbir",
|
||||
package="orbbec_camera",
|
||||
plugin="orbbec_camera::tools::MultiCameraSubscriber",
|
||||
)
|
||||
],
|
||||
)
|
||||
|
||||
attach_to_shared_component_container_arg = TextSubstitution(text="true")
|
||||
|
||||
launch1_include = IncludeLaunchDescription(
|
||||
PythonLaunchDescriptionSource(
|
||||
os.path.join(launch_file_dir, "gemini_330_series_synced_verify.launch.py")
|
||||
),
|
||||
launch_arguments={
|
||||
"camera_name": "camera_01",
|
||||
"usb_port": "2-1",
|
||||
"device_num": "2",
|
||||
"sync_mode": "primary",
|
||||
"config_file_path": config_file_path,
|
||||
"trigger_out_enabled": "true",
|
||||
"attach_to_shared_component_container": attach_to_shared_component_container_arg,
|
||||
"component_container_name": component_container_name_arg,
|
||||
}.items(),
|
||||
)
|
||||
|
||||
launch2_include = IncludeLaunchDescription(
|
||||
PythonLaunchDescriptionSource(
|
||||
os.path.join(launch_file_dir, "gemini_330_series_synced_verify.launch.py")
|
||||
),
|
||||
launch_arguments={
|
||||
"camera_name": "camera_02",
|
||||
"usb_port": "2-3",
|
||||
"device_num": "2",
|
||||
"sync_mode": "secondary_synced",
|
||||
"config_file_path": secondary_config_file_path,
|
||||
"trigger_out_enabled": "false",
|
||||
"attach_to_shared_component_container": attach_to_shared_component_container_arg,
|
||||
"component_container_name": component_container_name_arg,
|
||||
}.items(),
|
||||
)
|
||||
|
||||
# Launch description
|
||||
ld = LaunchDescription(
|
||||
[
|
||||
shared_orbbec_container,
|
||||
TimerAction(period=0.0, actions=[GroupAction([launch2_include])]),
|
||||
TimerAction(period=2.0, actions=[GroupAction([launch1_include])]),
|
||||
# The primary camera should be launched at last
|
||||
TimerAction(period=6.0, actions=[GroupAction([save_rgbir])]),
|
||||
# save_rgbir is synced verification tool
|
||||
]
|
||||
)
|
||||
|
||||
return ld
|
||||
@@ -1,6 +0,0 @@
|
||||
## config_frameMatch.py
|
||||
|
||||
Definition of 3 folders:
|
||||
matchFrames: data with card control within half frame.
|
||||
notMatchFrames: data with card control not within half frame, not matched.
|
||||
abnormal: data within the group that exceeds tspRangeThreshold setting
|
||||
@@ -1,5 +0,0 @@
|
||||
[Parameter]
|
||||
# Unit: FPS, please fill in according to the actual frame rate of the dataset, otherwise it will lead to inaccurate matching
|
||||
frameRate=30
|
||||
# Unit: ms. When the timestamp range of a group of data frames after matching is greater than or equal to tspRangeThreshold, the file name will be marked
|
||||
tspRangeThreshold=4
|
||||
@@ -1,97 +0,0 @@
|
||||
import os
|
||||
import subprocess
|
||||
import json
|
||||
import platform
|
||||
|
||||
def list_subdirectories(path):
|
||||
# 遍历指定目录
|
||||
for f in os.listdir(path):
|
||||
# 判断是否是子目录
|
||||
if os.path.isdir(os.path.join(path, f)):
|
||||
yield f
|
||||
|
||||
def read_pid_from_device_json(frames_dir):
|
||||
file_path = frames_dir + "/DevicesInfo.txt"
|
||||
if not os.path.exists(file_path):
|
||||
print(file_path + " not exists. Please check it")
|
||||
return ""
|
||||
|
||||
with open(file_path, 'r') as f:
|
||||
data = json.load(f)
|
||||
|
||||
if not 'devicePid' in data:
|
||||
print("Not found 'devicePid' in " + file_path)
|
||||
return ""
|
||||
|
||||
return data['devicePid']
|
||||
|
||||
def execute_sync_width_pid(frames_dir, pid):
|
||||
sync_script_file=""
|
||||
if pid.lower() == "0x0675":
|
||||
sync_script_file="script/config_frameMatch_Gemini2VL.py"
|
||||
elif pid.lower() == "0x0670" or pid.lower() == "0x0701":
|
||||
sync_script_file="script/config_frameMatch-systemTimestamp.py"
|
||||
elif pid.lower() == "0x0660":
|
||||
sync_script_file="script/config_frameMatch-Astra2_new.py"
|
||||
elif pid.lower() == "0x0803" or pid.lower() == "0x0807" or pid.lower() == "0x0801" or pid.lower() == "0x0805" or pid.lower() == "0x080b" or pid.lower() == "0x080e":
|
||||
sync_script_file="script/config_frameMatch_g330.py"
|
||||
else:
|
||||
sync_script_file="script/config_frameMatch.py"
|
||||
|
||||
if len(sync_script_file) > 0:
|
||||
print(f"execute synchronize frames. script_file={sync_script_file}, frames_dir={frames_dir}")
|
||||
if platform.system() == "Windows":
|
||||
output = subprocess.check_output(["python", sync_script_file, os.path.abspath(f"{frames_dir}"), os.getcwd()])
|
||||
print(output.decode("gbk"))
|
||||
else:
|
||||
output = subprocess.check_output(["python3", sync_script_file, os.path.abspath(f"{frames_dir}"), os.getcwd()])
|
||||
print(output.decode("utf-8"))
|
||||
else:
|
||||
print("Invalid pid=" + pid + ", not match sync frame script")
|
||||
|
||||
def sync_frames(frames_dir):
|
||||
pid = read_pid_from_device_json(frames_dir)
|
||||
if len(pid) <= 0:
|
||||
print("Get pid failed.")
|
||||
return
|
||||
|
||||
execute_sync_width_pid(frames_dir, pid)
|
||||
|
||||
def main():
|
||||
# 指定目录路径
|
||||
frames_output_path = os.path.abspath("../output")
|
||||
|
||||
# 获取所有子目录
|
||||
subdirectories = list(list_subdirectories(frames_output_path))
|
||||
|
||||
if not subdirectories:
|
||||
print("No subdirectories found in the specified directory.")
|
||||
|
||||
# 打印子目录列表并让用户选择
|
||||
for i, subdir in enumerate(subdirectories):
|
||||
print(f"{i + 1}. {subdir}")
|
||||
|
||||
# 获取用户输入
|
||||
choice = input("Please select a subdirectory by number (or 'q' to quit): ")
|
||||
|
||||
if choice.lower() == 'q':
|
||||
return
|
||||
|
||||
# 验证用户输入
|
||||
is_index_valid = False
|
||||
try:
|
||||
index = int(choice) - 1
|
||||
if 0 <= index < len(subdirectories):
|
||||
is_index_valid = True
|
||||
else:
|
||||
print(f"Invalid choice. index={index}. Please enter a number between 1 and the total number of subdirectories.")
|
||||
except ValueError:
|
||||
print("Invalid choice(ValueException). Please enter a number between 1 and the total number of subdirectories")
|
||||
if is_index_valid:
|
||||
selected_subdir = subdirectories[index]
|
||||
print(f"You selected the subdirectory: {selected_subdir}")
|
||||
sync_frames(f"{frames_output_path }/{selected_subdir}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -1,385 +0,0 @@
|
||||
import os.path
|
||||
import argparse
|
||||
import sys
|
||||
import json
|
||||
import shutil
|
||||
import configparser
|
||||
|
||||
from pathlib import Path
|
||||
from datetime import datetime
|
||||
|
||||
## Config.ini中配置
|
||||
# 单位:FPS,请依据数据集实际帧率填写,否则会导致匹配不准确
|
||||
frameRate = -1
|
||||
# 单位:ms,当匹配后某组数据帧的时间戳极差大于等于tspRangeThreshold,文件名会增加标注
|
||||
tspRangeThreshold = -1
|
||||
|
||||
## Python脚本自动解析, 不要修改
|
||||
primaryId = '-1' #主机ID
|
||||
mainPythonWorkPath = "" # SyncFramesMain.py的工作目录
|
||||
sourceFramesPath = "" # 请勿修改,固定值,TotalMode目录路径
|
||||
sourceRootPath = "" # 存放TotalMode的根目录
|
||||
resultPath = "" # 保存sync分析结果
|
||||
streamProfileDict = dict() # 保存Python结果
|
||||
|
||||
class PictureInfo(object):
|
||||
class Struct(object):
|
||||
def __init__(self, deviceId, sensorType, syncTimeStamp, picturePath, deviceIdFull, fileExt):
|
||||
self.deviceId = deviceId
|
||||
self.sensorType = sensorType
|
||||
self.syncTimeStamp = syncTimeStamp
|
||||
self.picturePath = picturePath
|
||||
self.deviceIdFull = deviceIdFull
|
||||
self.fileExt = fileExt
|
||||
|
||||
def make_struct(self, deviceId, sensorType, syncTimeStamp, picturePath, deviceIdFull, fileExt):
|
||||
return self.Struct(deviceId, sensorType, syncTimeStamp, picturePath, deviceIdFull, fileExt)
|
||||
|
||||
class StreamProfileInfo:
|
||||
def __init__(self, sensorType, width, height, format, fps):
|
||||
self.sensorType = sensorType
|
||||
self.width = width
|
||||
self.height = height
|
||||
self.format = format
|
||||
self.fps = fps
|
||||
|
||||
def initPrimaryId():
|
||||
global primaryId
|
||||
|
||||
deviceInfoPath = f"{sourceRootPath}/DevicesInfo.txt"
|
||||
if not os.path.exists(deviceInfoPath):
|
||||
print(f"Initialize primaryId failed. {deviceInfoPath} not exists")
|
||||
return False
|
||||
|
||||
with open(deviceInfoPath, 'r') as f:
|
||||
data = json.load(f)
|
||||
|
||||
if not 'devices' in data:
|
||||
print(f"Initialize primaryId failed. {deviceInfoPath} not contain item 'devices'")
|
||||
return False
|
||||
|
||||
for item in data['devices']:
|
||||
if 'isPrimaryDevice' in item and 'index' in item and item['isPrimaryDevice']:
|
||||
primaryId = str(item['index'])
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
def initSyncConfigParams():
|
||||
global frameRate, tspRangeThreshold
|
||||
|
||||
configPath = f"{mainPythonWorkPath}/Config.ini"
|
||||
if not os.path.exists(configPath):
|
||||
print(f"Initliaze synchronized config parameter failed. {configPath} not exists.")
|
||||
return False
|
||||
|
||||
# 创建ConfigParser对象
|
||||
config = configparser.ConfigParser()
|
||||
|
||||
# 读取ini文件
|
||||
config.read(configPath, 'utf-8')
|
||||
|
||||
if not config.has_option('Parameter', 'frameRate'):
|
||||
print(f"Initliaze synchronized config parameter failed. Not define 'frameRate' in ${configPath}")
|
||||
return False
|
||||
|
||||
if not config.has_option('Parameter', 'tspRangeThreshold'):
|
||||
print(f"Initliaze synchronized config parameter failed. Not define 'tspRangeThreshold' in ${configPath}")
|
||||
return False
|
||||
|
||||
frameRate = config.getfloat('Parameter', 'frameRate')
|
||||
if frameRate <= 0 or frameRate >= 1000:
|
||||
print(f"Initliaze synchronized config parameter failed. Invalid frameRate={frameRate}")
|
||||
return False
|
||||
|
||||
tspRangeThreshold = config.getfloat('Parameter', 'tspRangeThreshold')
|
||||
if tspRangeThreshold <= 0:
|
||||
print(f"Initliaze synchronized config parameter failed. Invalid tspRangeThreshold={tspRangeThreshold}")
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
def getDeviceCount():
|
||||
deviceInfoPath = f"{sourceRootPath}/DevicesInfo.txt"
|
||||
if not os.path.exists(deviceInfoPath):
|
||||
print(f"Get device count failed. {deviceInfoPath} not exists")
|
||||
return 0
|
||||
|
||||
with open(deviceInfoPath, 'r') as f:
|
||||
data = json.load(f)
|
||||
|
||||
if not 'devices' in data:
|
||||
print(f"Get device count failed. {deviceInfoPath} not contain item 'devices'")
|
||||
return 0
|
||||
|
||||
return len(data['devices'])
|
||||
|
||||
def initProfileInfoDict():
|
||||
global streamProfileDict
|
||||
|
||||
streamProfileDict = dict()
|
||||
profilePath = f"{sourceRootPath}/StreamProfileInfo.txt"
|
||||
if not os.path.exists(profilePath):
|
||||
print(f"Initialize profile information dictionary failed. {profilePath} not exists")
|
||||
return False
|
||||
|
||||
with open(profilePath, 'r') as f:
|
||||
data = json.load(f)
|
||||
|
||||
if not 'streamProfiles' in data:
|
||||
print(f"Initialize profile information dictionary failed. {profilePath} not contain item 'streamProfiles'")
|
||||
return False
|
||||
|
||||
for item in data['streamProfiles']:
|
||||
if 'sensorType' in item and 'width' in item and 'height' in item and 'format' in item and 'fps' in item:
|
||||
profileInfo = StreamProfileInfo(item['sensorType'], item['width'], item['height'], item['format'], item['fps'])
|
||||
streamProfileDict.setdefault(item['sensorType'], profileInfo)
|
||||
else:
|
||||
print(f"Initialize profile information dictionary. Error invalid StreamProfile, {item}")
|
||||
|
||||
return len(streamProfileDict.items()) > 0
|
||||
|
||||
def initResultDir():
|
||||
global resultPath
|
||||
timeText = datetime.now().strftime("%Y-%m-%d_%H%M%S")
|
||||
resultPath = f"{sourceRootPath}/results-{timeText}"
|
||||
if not os.path.exists(resultPath):
|
||||
os.makedirs(resultPath)
|
||||
|
||||
def isFrameFile(fileName):
|
||||
fileExt = os.path.splitext(fileName)
|
||||
if len(fileExt) < 2:
|
||||
return False
|
||||
|
||||
frameExts = {".jpeg", ".jpg", ".png", ".raw", "bmp"}
|
||||
return fileExt[1] in frameExts
|
||||
|
||||
def initPictureInfoDictionary(rootFilePath, pictureInfoDict):
|
||||
frameFileCount = 0
|
||||
for dirpath, dirnames, filenames in os.walk(rootFilePath):
|
||||
# print(f"dirpath={dirpath}, dirpath.basename=" + os.path.basename(dirpath))
|
||||
for fileName in filenames:
|
||||
filePath = os.path.join(dirpath, fileName)
|
||||
if not isFrameFile(fileName):
|
||||
continue
|
||||
|
||||
frameFileCount += 1
|
||||
fileNameNoExt = os.path.splitext(fileName)[0]
|
||||
pictureNameList = fileNameNoExt.split('_')
|
||||
deviceId = pictureNameList[2][5:]
|
||||
sensorType = pictureNameList[0].replace('#', '_')
|
||||
syncTimeStamp = int(pictureNameList[3][1:])
|
||||
|
||||
# 创建结构体
|
||||
pictureInfo = PictureInfo()
|
||||
info = pictureInfo.make_struct(deviceId, sensorType, syncTimeStamp, filePath, os.path.basename(dirpath), os.path.splitext(fileName)[1])
|
||||
|
||||
# 格式化字典一个key对应一个数组
|
||||
pictureInfoDict.setdefault(deviceId, []).append(info)
|
||||
|
||||
if 0 == frameFileCount:
|
||||
print("initialize pictureInfoDict failed. Not found frame file")
|
||||
|
||||
def matchFrame(pictureInfoDict):
|
||||
global primaryId, frameRate
|
||||
global streamProfileDict
|
||||
|
||||
# 获取比较图像数组,取第一个设备的Color数组来进行比较
|
||||
compareList = []
|
||||
for key in pictureInfoDict:
|
||||
listTmp = list(pictureInfoDict[key])
|
||||
for info in listTmp:
|
||||
if info.deviceId == primaryId and info.sensorType == 'color':
|
||||
compareList.append(info)
|
||||
|
||||
sorted_dict = dict(sorted(pictureInfoDict.items(), key=lambda x: x[1], reverse=False))
|
||||
pictureInfoDict = sorted_dict
|
||||
|
||||
# 根据开流情况动态分析,减少循环次数
|
||||
hasColorProfile = 'OB_SENSOR_COLOR' in streamProfileDict
|
||||
hasDepthProfile = 'OB_SENSOR_DEPTH' in streamProfileDict
|
||||
hasIRProfile = 'OB_SENSOR_IR' in streamProfileDict
|
||||
|
||||
# 匹配相邻帧
|
||||
resultDict = {}
|
||||
consumedList = []
|
||||
dictIndex = 0
|
||||
frameTspGap = int(1000.0/frameRate+0.5)
|
||||
for comparePic in compareList:
|
||||
resultDict.setdefault(dictIndex, []).append(comparePic)
|
||||
for key in pictureInfoDict:
|
||||
listTmp = list(pictureInfoDict[key])
|
||||
# 对比彩色
|
||||
if hasColorProfile:
|
||||
for info in listTmp:
|
||||
if info.deviceId == primaryId and info.sensorType == comparePic.sensorType:
|
||||
continue
|
||||
|
||||
if info in consumedList:
|
||||
continue
|
||||
|
||||
if info.sensorType == 'color' and info.syncTimeStamp >= comparePic.syncTimeStamp and info.syncTimeStamp - comparePic.syncTimeStamp <= frameTspGap:
|
||||
resultDict.setdefault(dictIndex, []).append(info)
|
||||
consumedList.append(info)
|
||||
break
|
||||
|
||||
# 对Depth
|
||||
if hasDepthProfile:
|
||||
for info in listTmp:
|
||||
if info.deviceId == primaryId and info.sensorType == comparePic.sensorType:
|
||||
continue
|
||||
|
||||
if info in consumedList:
|
||||
continue
|
||||
|
||||
if info.sensorType == 'depth' and info.syncTimeStamp >= comparePic.syncTimeStamp and info.syncTimeStamp - comparePic.syncTimeStamp <= frameTspGap:
|
||||
resultDict.setdefault(dictIndex, []).append(info)
|
||||
consumedList.append(info)
|
||||
break
|
||||
|
||||
# IR
|
||||
if hasIRProfile:
|
||||
for info in listTmp:
|
||||
if info.deviceId == primaryId and info.sensorType == comparePic.sensorType:
|
||||
continue
|
||||
|
||||
if info in consumedList:
|
||||
continue
|
||||
|
||||
if info.sensorType == 'ir' and info.syncTimeStamp >= comparePic.syncTimeStamp and info.syncTimeStamp - comparePic.syncTimeStamp <= frameTspGap:
|
||||
resultDict.setdefault(dictIndex, []).append(info)
|
||||
consumedList.append(info)
|
||||
break
|
||||
|
||||
# 计算偏差
|
||||
for info in resultDict[dictIndex]:
|
||||
info.tspDiff = info.syncTimeStamp - comparePic.syncTimeStamp
|
||||
|
||||
dictIndex += 1
|
||||
|
||||
return resultDict
|
||||
|
||||
|
||||
def safe_make_dir(path):
|
||||
if not os.path.exists(path):
|
||||
os.makedirs(path)
|
||||
|
||||
|
||||
def handleSyncFrames():
|
||||
global resultPath
|
||||
global sourceFramesPath
|
||||
global streamProfileDict
|
||||
|
||||
fp = open(f"{resultPath}/frameMatchLog.txt", "w")
|
||||
|
||||
if not initProfileInfoDict():
|
||||
print("Initialize stream profile dictionary failed. exit")
|
||||
return
|
||||
print(f"Stream profiles: {streamProfileDict}")
|
||||
streamProfileCount = len(streamProfileDict.items())
|
||||
|
||||
pictureInfoDict = {}
|
||||
|
||||
initPictureInfoDictionary(Path(sourceFramesPath), pictureInfoDict)
|
||||
if len(pictureInfoDict) <= 0:
|
||||
print("init pictureInfoDict failed. pictureInfoDict.len = 0")
|
||||
return
|
||||
|
||||
# # Dump pictureInfoDict
|
||||
# for key in pictureInfoDict:
|
||||
# print("===================key:%s" % key)
|
||||
# listTmp = list(pictureInfoDict[key])
|
||||
# for info in listTmp:
|
||||
# print("=====================value : deviceId:%s\tsensorType:%s\tsyncTimeStamp:%s\tpicturePath:%s" % (info.deviceId,info.sensorType,info.syncTimeStamp,info.picturePath))
|
||||
|
||||
deviceCount = getDeviceCount()
|
||||
print("=================device count:%d" % deviceCount)
|
||||
|
||||
resultDict = {}
|
||||
resultDict = matchFrame(pictureInfoDict)
|
||||
|
||||
for key in resultDict:
|
||||
fp.write("===================result key:%s\n" % key)
|
||||
print("===================result key:%s" % key)
|
||||
listTmp = list(resultDict[key])
|
||||
for info in listTmp:
|
||||
fp.write("=====================result value : deviceId:%s\tsensorType:%s\tsyncTimeStamp:%s\tpicturePath:%s\n" % (
|
||||
info.deviceId, info.sensorType, info.syncTimeStamp, info.picturePath))
|
||||
print("=====================result value : deviceId:%s\tsensorType:%s\tsyncTimeStamp:%s\tpicturePath:%s" % (
|
||||
info.deviceId, info.sensorType, info.syncTimeStamp, info.picturePath))
|
||||
|
||||
matchPath = f"{resultPath}/matchFrames/"
|
||||
safe_make_dir(matchPath)
|
||||
notMatchPath = f"{resultPath}/notMatchFrames/"
|
||||
abnormalPath = f"{resultPath}/abnormal/"
|
||||
|
||||
for key in resultDict:
|
||||
listTmp = list(resultDict[key])
|
||||
if (len(listTmp) == (deviceCount * streamProfileCount)):
|
||||
haveAbnormalData = False
|
||||
for info in listTmp:
|
||||
if info.tspDiff >= tspRangeThreshold:
|
||||
path = matchPath + str(key) + "_" + info.sensorType + "_" + info.deviceIdFull + "_" + str(
|
||||
info.syncTimeStamp) + "_[" + str(info.tspDiff) + "]" + "_xxxxxx" + info.fileExt
|
||||
shutil.copy(info.picturePath, path)
|
||||
haveAbnormalData = True
|
||||
else:
|
||||
path = matchPath + str(key) + "_" + info.sensorType + "_" + info.deviceIdFull + "_" + str(
|
||||
info.syncTimeStamp) + "_[" + str(info.tspDiff) + "]" + info.fileExt
|
||||
shutil.copy(info.picturePath, path)
|
||||
|
||||
if haveAbnormalData:
|
||||
safe_make_dir(abnormalPath)
|
||||
for info in listTmp:
|
||||
if info.tspDiff >= tspRangeThreshold:
|
||||
path = abnormalPath + str(key) + "_" + info.sensorType + "_" + info.deviceIdFull + "_" + str(
|
||||
info.syncTimeStamp) + "_[" + str(info.tspDiff) + "]" + "_xxxxxx" + info.fileExt
|
||||
shutil.copy(info.picturePath, path)
|
||||
else:
|
||||
path = abnormalPath + str(key) + "_" + info.sensorType + "_" + info.deviceIdFull + "_" + str(
|
||||
info.syncTimeStamp) + "_[" + str(info.tspDiff) + "]" + info.fileExt
|
||||
shutil.copy(info.picturePath, path)
|
||||
else:
|
||||
safe_make_dir(notMatchPath)
|
||||
for info in listTmp:
|
||||
newFilePath = notMatchPath + str(key) + "_" + info.sensorType + "_" + info.deviceIdFull + "_" + str(
|
||||
info.syncTimeStamp) + "_[" + str(info.tspDiff) + "]" + info.fileExt
|
||||
shutil.copy(info.picturePath, newFilePath)
|
||||
|
||||
def main():
|
||||
if not initPrimaryId():
|
||||
print("Initialize primaryId failed. exit.")
|
||||
return
|
||||
|
||||
if not initSyncConfigParams():
|
||||
print("Initialized Sync config parameter failed. exit.")
|
||||
return
|
||||
|
||||
initResultDir()
|
||||
|
||||
print(f"PrimaryId={primaryId}, frameRate={frameRate}, tspRangeThreshold={tspRangeThreshold}")
|
||||
handleSyncFrames()
|
||||
|
||||
return
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
parser = argparse.ArgumentParser(description="Synchronize frames support for 'Orbbec Astra2'")
|
||||
parser.add_argument('frames_dir', type=str, help="Frames directory")
|
||||
parser.add_argument('main_script_root_dir', type=str, help="SyncFramesMain.py working directory")
|
||||
args = parser.parse_args()
|
||||
|
||||
sourceRootPath = args.frames_dir
|
||||
sourceFramesPath = f"{args.frames_dir}/TotalModeFrames"
|
||||
mainPythonWorkPath = args.main_script_root_dir
|
||||
print(f"Start of Astra2 synchronize frame. sourceRootPath={sourceRootPath}")
|
||||
|
||||
main()
|
||||
|
||||
print("Finish of Astra2 synchronize frame.")
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,408 +0,0 @@
|
||||
import os.path
|
||||
import argparse
|
||||
import sys
|
||||
import json
|
||||
import shutil
|
||||
import configparser
|
||||
|
||||
from pathlib import Path
|
||||
from datetime import datetime
|
||||
|
||||
## Config.ini中配置
|
||||
# 单位:FPS,请依据数据集实际帧率填写,否则会导致匹配不准确
|
||||
frameRate = -1
|
||||
# 单位:ms,当匹配后某组数据帧的时间戳极差大于等于tspRangeThreshold,文件名会增加标注
|
||||
tspRangeThreshold = -1
|
||||
|
||||
## Python脚本自动解析, 不要修改
|
||||
primaryId = '-1' #主机ID
|
||||
mainPythonWorkPath = "" # SyncFramesMain.py的工作目录
|
||||
sourceFramesPath = "" # 请勿修改,固定值,TotalMode目录路径
|
||||
sourceRootPath = "" # 存放TotalMode的根目录
|
||||
resultPath = "" # 保存sync分析结果
|
||||
streamProfileDict = dict() # 保存Python结果
|
||||
|
||||
class PictureInfo(object):
|
||||
class Struct(object):
|
||||
def __init__(self, deviceId, sensorType, syncTimeStamp, picturePath, deviceIdFull, fileExt):
|
||||
self.deviceId = deviceId
|
||||
self.sensorType = sensorType
|
||||
self.syncTimeStamp = syncTimeStamp
|
||||
self.picturePath = picturePath
|
||||
self.deviceIdFull = deviceIdFull
|
||||
self.fileExt = fileExt
|
||||
|
||||
def make_struct(self, deviceId, sensorType, syncTimeStamp, picturePath, deviceIdFull, fileExt):
|
||||
return self.Struct(deviceId, sensorType, syncTimeStamp, picturePath, deviceIdFull, fileExt)
|
||||
|
||||
class StreamProfileInfo:
|
||||
def __init__(self, sensorType, width, height, format, fps):
|
||||
self.sensorType = sensorType
|
||||
self.width = width
|
||||
self.height = height
|
||||
self.format = format
|
||||
self.fps = fps
|
||||
|
||||
def initPrimaryId():
|
||||
global primaryId
|
||||
|
||||
deviceInfoPath = f"{sourceRootPath}/DevicesInfo.txt"
|
||||
if not os.path.exists(deviceInfoPath):
|
||||
print(f"Initialize primaryId failed. {deviceInfoPath} not exists")
|
||||
return False
|
||||
|
||||
with open(deviceInfoPath, 'r') as f:
|
||||
data = json.load(f)
|
||||
|
||||
if not 'devices' in data:
|
||||
print(f"Initialize primaryId failed. {deviceInfoPath} not contain item 'devices'")
|
||||
return False
|
||||
|
||||
for item in data['devices']:
|
||||
if 'isPrimaryDevice' in item and 'index' in item and item['isPrimaryDevice']:
|
||||
primaryId = str(item['index'])
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
def initSyncConfigParams():
|
||||
global frameRate, tspRangeThreshold
|
||||
|
||||
configPath = f"{mainPythonWorkPath}/Config.ini"
|
||||
if not os.path.exists(configPath):
|
||||
print(f"Initliaze synchronized config parameter failed. {configPath} not exists.")
|
||||
return False
|
||||
|
||||
# 创建ConfigParser对象
|
||||
config = configparser.ConfigParser()
|
||||
|
||||
# 读取ini文件
|
||||
config.read(configPath, 'utf-8')
|
||||
|
||||
if not config.has_option('Parameter', 'frameRate'):
|
||||
print(f"Initliaze synchronized config parameter failed. Not define 'frameRate' in ${configPath}")
|
||||
return False
|
||||
|
||||
if not config.has_option('Parameter', 'tspRangeThreshold'):
|
||||
print(f"Initliaze synchronized config parameter failed. Not define 'tspRangeThreshold' in ${configPath}")
|
||||
return False
|
||||
|
||||
frameRate = config.getfloat('Parameter', 'frameRate')
|
||||
if frameRate <= 0 or frameRate >= 1000:
|
||||
print(f"Initliaze synchronized config parameter failed. Invalid frameRate={frameRate}")
|
||||
return False
|
||||
|
||||
tspRangeThreshold = config.getfloat('Parameter', 'tspRangeThreshold')
|
||||
if tspRangeThreshold <= 0:
|
||||
print(f"Initliaze synchronized config parameter failed. Invalid tspRangeThreshold={tspRangeThreshold}")
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
def getDeviceCount():
|
||||
deviceInfoPath = f"{sourceRootPath}/DevicesInfo.txt"
|
||||
if not os.path.exists(deviceInfoPath):
|
||||
print(f"Get device count failed. {deviceInfoPath} not exists")
|
||||
return 0
|
||||
|
||||
with open(deviceInfoPath, 'r') as f:
|
||||
data = json.load(f)
|
||||
|
||||
if not 'devices' in data:
|
||||
print(f"Get device count failed. {deviceInfoPath} not contain item 'devices'")
|
||||
return 0
|
||||
|
||||
return len(data['devices'])
|
||||
|
||||
def initProfileInfoDict():
|
||||
global streamProfileDict
|
||||
|
||||
streamProfileDict = dict()
|
||||
profilePath = f"{sourceRootPath}/StreamProfileInfo.txt"
|
||||
if not os.path.exists(profilePath):
|
||||
print(f"Initialize profile information dictionary failed. {profilePath} not exists")
|
||||
return False
|
||||
|
||||
with open(profilePath, 'r') as f:
|
||||
data = json.load(f)
|
||||
|
||||
if not 'streamProfiles' in data:
|
||||
print(f"Initialize profile information dictionary failed. {profilePath} not contain item 'streamProfiles'")
|
||||
return False
|
||||
|
||||
for item in data['streamProfiles']:
|
||||
if 'sensorType' in item and 'width' in item and 'height' in item and 'format' in item and 'fps' in item:
|
||||
profileInfo = StreamProfileInfo(item['sensorType'], item['width'], item['height'], item['format'], item['fps'])
|
||||
streamProfileDict.setdefault(item['sensorType'], profileInfo)
|
||||
else:
|
||||
print(f"Initialize profile information dictionary. Error invalid StreamProfile, {item}")
|
||||
|
||||
return len(streamProfileDict.items()) > 0
|
||||
|
||||
def initResultDir():
|
||||
global resultPath
|
||||
timeText = datetime.now().strftime("%Y-%m-%d_%H%M%S")
|
||||
resultPath = f"{sourceRootPath}/results-{timeText}"
|
||||
if not os.path.exists(resultPath):
|
||||
os.makedirs(resultPath)
|
||||
|
||||
def isFrameFile(fileName):
|
||||
fileExt = os.path.splitext(fileName)
|
||||
if len(fileExt) < 2:
|
||||
return False
|
||||
|
||||
frameExts = {".jpeg", ".jpg", ".png", ".raw", "bmp"}
|
||||
return fileExt[1] in frameExts
|
||||
|
||||
def initPictureInfoDictionary(rootFilePath, pictureInfoDict):
|
||||
frameFileCount = 0
|
||||
for dirpath, dirnames, filenames in os.walk(rootFilePath):
|
||||
# print(f"dirpath={dirpath}, dirpath.basename=" + os.path.basename(dirpath))
|
||||
for fileName in filenames:
|
||||
filePath = os.path.join(dirpath, fileName)
|
||||
if not isFrameFile(fileName):
|
||||
continue
|
||||
|
||||
frameFileCount += 1
|
||||
fileNameNoExt = os.path.splitext(fileName)[0]
|
||||
pictureNameList = fileNameNoExt.split('_')
|
||||
deviceId = pictureNameList[2][5:]
|
||||
sensorType = pictureNameList[0].replace('#', '_')
|
||||
syncTimeStamp = int(pictureNameList[5][1:])
|
||||
|
||||
# 创建结构体
|
||||
pictureInfo = PictureInfo()
|
||||
info = pictureInfo.make_struct(deviceId, sensorType, syncTimeStamp, filePath, os.path.basename(dirpath), os.path.splitext(fileName)[1])
|
||||
|
||||
# 格式化字典一个key对应一个数组
|
||||
pictureInfoDict.setdefault(deviceId, []).append(info)
|
||||
|
||||
if 0 == frameFileCount:
|
||||
print("initialize pictureInfoDict failed. Not found frame file")
|
||||
|
||||
|
||||
def matchFrame(pictureInfoDict):
|
||||
global primaryId, frameRate
|
||||
global streamProfileDict
|
||||
|
||||
# 获取比较图像数组,取第一个设备的Color数组来进行比较
|
||||
compareList = []
|
||||
for key in pictureInfoDict:
|
||||
listTmp = list(pictureInfoDict[key])
|
||||
for info in listTmp:
|
||||
if info.deviceId == primaryId and info.sensorType == 'color':
|
||||
compareList.append(info)
|
||||
|
||||
# 根据开流情况动态分析,减少循环次数
|
||||
hasColorProfile = 'OB_SENSOR_COLOR' in streamProfileDict
|
||||
hasDepthProfile = 'OB_SENSOR_DEPTH' in streamProfileDict
|
||||
hasIRProfile = 'OB_SENSOR_IR' in streamProfileDict
|
||||
hasIRLeftProfile = 'OB_SENSOR_IR_LEFT' in streamProfileDict
|
||||
hasIRRightProfile = 'OB_SENSOR_IR_RIGHT' in streamProfileDict
|
||||
|
||||
# 匹配相邻帧
|
||||
resultDict = {}
|
||||
consumedList = []
|
||||
dictIndex = 0
|
||||
frameTspHalfGap = int(1000.0/frameRate/2.0+0.5)
|
||||
for comparePic in compareList:
|
||||
resultDict.setdefault(dictIndex, []).append(comparePic)
|
||||
for key in pictureInfoDict:
|
||||
listTmp = list(pictureInfoDict[key])
|
||||
# 对比彩色
|
||||
if hasColorProfile:
|
||||
for info in listTmp:
|
||||
if info.deviceId == primaryId and info.sensorType == comparePic.sensorType:
|
||||
continue
|
||||
|
||||
if info in consumedList:
|
||||
continue
|
||||
|
||||
if info.sensorType == 'color' and abs(info.syncTimeStamp - comparePic.syncTimeStamp) < frameTspHalfGap:
|
||||
resultDict.setdefault(dictIndex, []).append(info)
|
||||
consumedList.append(info)
|
||||
break
|
||||
|
||||
# 对Depth
|
||||
if hasDepthProfile:
|
||||
for info in listTmp:
|
||||
if info.deviceId == primaryId and info.sensorType == comparePic.sensorType:
|
||||
continue
|
||||
|
||||
if info in consumedList:
|
||||
continue
|
||||
|
||||
if info.sensorType == 'depth' and abs(info.syncTimeStamp - comparePic.syncTimeStamp) < frameTspHalfGap:
|
||||
resultDict.setdefault(dictIndex, []).append(info)
|
||||
consumedList.append(info)
|
||||
break
|
||||
|
||||
# IR
|
||||
if hasIRProfile:
|
||||
for info in listTmp:
|
||||
if info.deviceId == primaryId and info.sensorType == comparePic.sensorType:
|
||||
continue
|
||||
|
||||
if info in consumedList:
|
||||
continue
|
||||
|
||||
if info.sensorType == 'ir' and abs(info.syncTimeStamp - comparePic.syncTimeStamp) < frameTspHalfGap:
|
||||
resultDict.setdefault(dictIndex, []).append(info)
|
||||
consumedList.append(info)
|
||||
break
|
||||
|
||||
# 左IR
|
||||
if hasIRLeftProfile:
|
||||
for info in listTmp:
|
||||
if info.deviceId == primaryId and info.sensorType == comparePic.sensorType:
|
||||
continue
|
||||
|
||||
if info in consumedList:
|
||||
continue
|
||||
|
||||
if info.sensorType == 'ir_left' and abs(info.syncTimeStamp - comparePic.syncTimeStamp) < frameTspHalfGap:
|
||||
resultDict.setdefault(dictIndex, []).append(info)
|
||||
consumedList.append(info)
|
||||
break
|
||||
|
||||
# 右IR
|
||||
if hasIRRightProfile:
|
||||
for info in listTmp:
|
||||
if info.deviceId == primaryId and info.sensorType == comparePic.sensorType:
|
||||
continue
|
||||
|
||||
if info in consumedList:
|
||||
continue
|
||||
|
||||
if info.sensorType == 'ir_right' and abs(info.syncTimeStamp - comparePic.syncTimeStamp) < frameTspHalfGap:
|
||||
resultDict.setdefault(dictIndex, []).append(info)
|
||||
consumedList.append(info)
|
||||
break
|
||||
|
||||
# 计算偏差
|
||||
minTsp = min(resultDict[dictIndex], key=lambda x: x.syncTimeStamp)
|
||||
for info in resultDict[dictIndex]:
|
||||
info.tspDiff = info.syncTimeStamp - minTsp.syncTimeStamp
|
||||
|
||||
dictIndex += 1
|
||||
|
||||
return resultDict
|
||||
|
||||
|
||||
def safe_make_dir(path):
|
||||
if not os.path.exists(path):
|
||||
os.makedirs(path)
|
||||
|
||||
|
||||
def handleSyncFrames():
|
||||
global resultPath
|
||||
global sourceFramesPath
|
||||
global streamProfileDict
|
||||
|
||||
fp = open(f"{resultPath}/frameMatchLog.txt", "w")
|
||||
|
||||
if not initProfileInfoDict():
|
||||
print("Initialize stream profile dictionary failed. exit")
|
||||
return
|
||||
print(f"Stream profiles: {streamProfileDict}")
|
||||
streamProfileCount = len(streamProfileDict.items())
|
||||
|
||||
pictureInfoDict = {}
|
||||
|
||||
initPictureInfoDictionary(Path(sourceFramesPath), pictureInfoDict)
|
||||
if len(pictureInfoDict) <= 0:
|
||||
print("init pictureInfoDict failed. pictureInfoDict.len = 0")
|
||||
return
|
||||
|
||||
# # Dump pictureInfoDict
|
||||
# for key in pictureInfoDict:
|
||||
# print("===================key:%s" % key)
|
||||
# listTmp = list(pictureInfoDict[key])
|
||||
# for info in listTmp:
|
||||
# print("=====================value : deviceId:%s\tsensorType:%s\tsyncTimeStamp:%s\tpicturePath:%s" % (info.deviceId,info.sensorType,info.syncTimeStamp,info.picturePath))
|
||||
|
||||
deviceCount = getDeviceCount()
|
||||
print("=================device count:%d" % deviceCount)
|
||||
|
||||
resultDict = {}
|
||||
resultDict = matchFrame(pictureInfoDict)
|
||||
|
||||
for key in resultDict:
|
||||
fp.write("===================result key:%s\n" % key)
|
||||
print("===================result key:%s" % key)
|
||||
listTmp = list(resultDict[key])
|
||||
for info in listTmp:
|
||||
fp.write("=====================result value : deviceId:%s\tsensorType:%s\tsyncTimeStamp:%s\tpicturePath:%s\n" % (
|
||||
info.deviceId, info.sensorType, info.syncTimeStamp, info.picturePath))
|
||||
print("=====================result value : deviceId:%s\tsensorType:%s\tsyncTimeStamp:%s\tpicturePath:%s" % (
|
||||
info.deviceId, info.sensorType, info.syncTimeStamp, info.picturePath))
|
||||
|
||||
matchPath = f"{resultPath}/matchFrames/"
|
||||
safe_make_dir(matchPath)
|
||||
notMatchPath = f"{resultPath}/notMatchFrames/"
|
||||
abnormalPath = f"{resultPath}/abnormal/"
|
||||
|
||||
for key in resultDict:
|
||||
listTmp = list(resultDict[key])
|
||||
if (len(listTmp) == (deviceCount * streamProfileCount)):
|
||||
haveAbnormalData = False
|
||||
for info in listTmp:
|
||||
if info.tspDiff >= tspRangeThreshold:
|
||||
path = matchPath + str(key) + "_" + info.sensorType + "_" + info.deviceIdFull + "_" + str(
|
||||
info.syncTimeStamp) + "_[" + str(info.tspDiff) + "]" + "_xxxxxx" + info.fileExt
|
||||
shutil.copy(info.picturePath, path)
|
||||
haveAbnormalData = True
|
||||
else:
|
||||
path = matchPath + str(key) + "_" + info.sensorType + "_" + info.deviceIdFull + "_" + str(
|
||||
info.syncTimeStamp) + "_[" + str(info.tspDiff) + "]" + info.fileExt
|
||||
shutil.copy(info.picturePath, path)
|
||||
|
||||
if haveAbnormalData:
|
||||
safe_make_dir(abnormalPath)
|
||||
for info in listTmp:
|
||||
if info.tspDiff >= tspRangeThreshold:
|
||||
path = abnormalPath + str(key) + "_" + info.sensorType + "_" + info.deviceIdFull + "_" + str(
|
||||
info.syncTimeStamp) + "_[" + str(info.tspDiff) + "]" + "_xxxxxx" + info.fileExt
|
||||
shutil.copy(info.picturePath, path)
|
||||
else:
|
||||
path = abnormalPath + str(key) + "_" + info.sensorType + "_" + info.deviceIdFull + "_" + str(
|
||||
info.syncTimeStamp) + "_[" + str(info.tspDiff) + "]" + info.fileExt
|
||||
shutil.copy(info.picturePath, path)
|
||||
else:
|
||||
safe_make_dir(notMatchPath)
|
||||
for info in listTmp:
|
||||
newFilePath = notMatchPath + str(key) + "_" + info.sensorType + "_" + info.deviceIdFull + "_" + str(
|
||||
info.syncTimeStamp) + "_[" + str(info.tspDiff) + "]" + info.fileExt
|
||||
shutil.copy(info.picturePath, newFilePath)
|
||||
|
||||
def main():
|
||||
if not initPrimaryId():
|
||||
print("Initialize primaryId failed. exit.")
|
||||
return
|
||||
|
||||
if not initSyncConfigParams():
|
||||
print("Initialized Sync config parameter failed. exit.")
|
||||
return
|
||||
|
||||
initResultDir()
|
||||
|
||||
print(f"PrimaryId={primaryId}, frameRate={frameRate}, tspRangeThreshold={tspRangeThreshold}")
|
||||
handleSyncFrames()
|
||||
|
||||
return
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
parser = argparse.ArgumentParser(description="Synchronize frames support for 'Orbbec Gemini 2'")
|
||||
parser.add_argument('frames_dir', type=str, help="Frames directory")
|
||||
parser.add_argument('main_script_root_dir', type=str, help="SyncFramesMain.py working directory")
|
||||
args = parser.parse_args()
|
||||
|
||||
sourceRootPath = args.frames_dir
|
||||
sourceFramesPath = f"{args.frames_dir}/TotalModeFrames"
|
||||
mainPythonWorkPath = args.main_script_root_dir
|
||||
print(f"Start of Gemini2 synchronize frame. sourceRootPath={sourceRootPath}")
|
||||
|
||||
main()
|
||||
|
||||
print("Finish of Gemini2 synchronize frame.")
|
||||
@@ -1,430 +0,0 @@
|
||||
import os.path
|
||||
import argparse
|
||||
import sys
|
||||
import json
|
||||
import shutil
|
||||
import configparser
|
||||
|
||||
from pathlib import Path
|
||||
from datetime import datetime
|
||||
|
||||
import os
|
||||
import re
|
||||
|
||||
## Config.ini中配置
|
||||
# 单位:FPS,请依据数据集实际帧率填写,否则会导致匹配不准确
|
||||
frameRate = -1
|
||||
# 单位:ms,当匹配后某组数据帧的时间戳极差大于等于tspRangeThreshold,文件名会增加标注
|
||||
tspRangeThreshold = -1
|
||||
|
||||
## Python脚本自动解析, 不要修改
|
||||
primaryId = '-1' #主机ID
|
||||
mainPythonWorkPath = "" # SyncFramesMain.py的工作目录
|
||||
sourceFramesPath = "" # 请勿修改,固定值,TotalMode目录路径
|
||||
sourceRootPath = "" # 存放TotalMode的根目录
|
||||
resultPath = "" # 保存sync分析结果
|
||||
streamProfileDict = dict() # 保存Python结果
|
||||
|
||||
class PictureInfo(object):
|
||||
class Struct(object):
|
||||
def __init__(self, deviceId, sensorType, syncTimeStamp, picturePath, deviceIdFull, fileExt):
|
||||
self.deviceId = deviceId
|
||||
self.sensorType = sensorType
|
||||
self.syncTimeStamp = syncTimeStamp
|
||||
self.picturePath = picturePath
|
||||
self.deviceIdFull = deviceIdFull
|
||||
self.fileExt = fileExt
|
||||
|
||||
def make_struct(self, deviceId, sensorType, syncTimeStamp, picturePath, deviceIdFull, fileExt):
|
||||
return self.Struct(deviceId, sensorType, syncTimeStamp, picturePath, deviceIdFull, fileExt)
|
||||
|
||||
class StreamProfileInfo:
|
||||
def __init__(self, sensorType, width, height, format, fps):
|
||||
self.sensorType = sensorType
|
||||
self.width = width
|
||||
self.height = height
|
||||
self.format = format
|
||||
self.fps = fps
|
||||
|
||||
def initPrimaryId():
|
||||
global primaryId
|
||||
|
||||
deviceInfoPath = f"{sourceRootPath}/DevicesInfo.txt"
|
||||
if not os.path.exists(deviceInfoPath):
|
||||
print(f"Initialize primaryId failed. {deviceInfoPath} not exists")
|
||||
return False
|
||||
|
||||
with open(deviceInfoPath, 'r') as f:
|
||||
data = json.load(f)
|
||||
|
||||
if not 'devices' in data:
|
||||
print(f"Initialize primaryId failed. {deviceInfoPath} not contain item 'devices'")
|
||||
return False
|
||||
|
||||
for item in data['devices']:
|
||||
if 'isPrimaryDevice' in item and 'index' in item and item['isPrimaryDevice']:
|
||||
primaryId = str(item['index'])
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
def initSyncConfigParams():
|
||||
global frameRate, tspRangeThreshold
|
||||
|
||||
configPath = f"{mainPythonWorkPath}/Config.ini"
|
||||
if not os.path.exists(configPath):
|
||||
print(f"Initliaze synchronized config parameter failed. {configPath} not exists.")
|
||||
return False
|
||||
|
||||
# 创建ConfigParser对象
|
||||
config = configparser.ConfigParser()
|
||||
|
||||
# 读取ini文件
|
||||
config.read(configPath, 'utf-8')
|
||||
|
||||
if not config.has_option('Parameter', 'frameRate'):
|
||||
print(f"Initliaze synchronized config parameter failed. Not define 'frameRate' in ${configPath}")
|
||||
return False
|
||||
|
||||
if not config.has_option('Parameter', 'tspRangeThreshold'):
|
||||
print(f"Initliaze synchronized config parameter failed. Not define 'tspRangeThreshold' in ${configPath}")
|
||||
return False
|
||||
|
||||
frameRate = config.getfloat('Parameter', 'frameRate')
|
||||
if frameRate <= 0 or frameRate >= 1000:
|
||||
print(f"Initliaze synchronized config parameter failed. Invalid frameRate={frameRate}")
|
||||
return False
|
||||
|
||||
tspRangeThreshold = config.getfloat('Parameter', 'tspRangeThreshold')
|
||||
if tspRangeThreshold <= 0:
|
||||
print(f"Initliaze synchronized config parameter failed. Invalid tspRangeThreshold={tspRangeThreshold}")
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
def getDeviceCount():
|
||||
deviceInfoPath = f"{sourceRootPath}/DevicesInfo.txt"
|
||||
if not os.path.exists(deviceInfoPath):
|
||||
print(f"Get device count failed. {deviceInfoPath} not exists")
|
||||
return 0
|
||||
|
||||
with open(deviceInfoPath, 'r') as f:
|
||||
data = json.load(f)
|
||||
|
||||
if not 'devices' in data:
|
||||
print(f"Get device count failed. {deviceInfoPath} not contain item 'devices'")
|
||||
return 0
|
||||
|
||||
return len(data['devices'])
|
||||
|
||||
def initProfileInfoDict():
|
||||
global streamProfileDict
|
||||
|
||||
streamProfileDict = dict()
|
||||
profilePath = f"{sourceRootPath}/StreamProfileInfo.txt"
|
||||
if not os.path.exists(profilePath):
|
||||
print(f"Initialize profile information dictionary failed. {profilePath} not exists")
|
||||
return False
|
||||
|
||||
with open(profilePath, 'r') as f:
|
||||
data = json.load(f)
|
||||
|
||||
if not 'streamProfiles' in data:
|
||||
print(f"Initialize profile information dictionary failed. {profilePath} not contain item 'streamProfiles'")
|
||||
return False
|
||||
|
||||
for item in data['streamProfiles']:
|
||||
if 'sensorType' in item and 'width' in item and 'height' in item and 'format' in item and 'fps' in item:
|
||||
profileInfo = StreamProfileInfo(item['sensorType'], item['width'], item['height'], item['format'], item['fps'])
|
||||
streamProfileDict.setdefault(item['sensorType'], profileInfo)
|
||||
else:
|
||||
print(f"Initialize profile information dictionary. Error invalid StreamProfile, {item}")
|
||||
|
||||
return len(streamProfileDict.items()) > 0
|
||||
|
||||
def initResultDir():
|
||||
global resultPath
|
||||
timeText = datetime.now().strftime("%Y-%m-%d_%H%M%S")
|
||||
resultPath = f"{sourceRootPath}/results-{timeText}"
|
||||
if not os.path.exists(resultPath):
|
||||
os.makedirs(resultPath)
|
||||
|
||||
def isFrameFile(fileName):
|
||||
fileExt = os.path.splitext(fileName)
|
||||
if len(fileExt) < 2:
|
||||
return False
|
||||
|
||||
frameExts = {".jpeg", ".jpg", ".png", ".raw", "bmp"}
|
||||
return fileExt[1] in frameExts
|
||||
|
||||
def extract_d_number(filename):
|
||||
"""提取文件名中以'd'开头的数字部分"""
|
||||
match_d = re.search(r'd(\d+)', filename)
|
||||
if match_d:
|
||||
return int(match_d.group(1))
|
||||
|
||||
match_g = re.search(r'g(\d+)', filename)
|
||||
if match_g:
|
||||
return int(match_g.group(1))
|
||||
|
||||
return float('inf')
|
||||
|
||||
def initPictureInfoDictionary(rootFilePath, pictureInfoDict):
|
||||
frameFileCount = 0
|
||||
for dirpath, dirnames, filenames in os.walk(rootFilePath):
|
||||
filenames.sort(key=extract_d_number) # 排序,按文件名中的'd'后面的数字从小到大排序
|
||||
for fileName in filenames:
|
||||
filePath = os.path.join(dirpath, fileName)
|
||||
if not isFrameFile(fileName):
|
||||
continue
|
||||
|
||||
frameFileCount += 1
|
||||
fileNameNoExt = os.path.splitext(fileName)[0]
|
||||
pictureNameList = fileNameNoExt.split('_')
|
||||
deviceId = pictureNameList[2][5:]
|
||||
sensorType = pictureNameList[0].replace('#', '_')
|
||||
syncTimeStamp = int(pictureNameList[3][1:])
|
||||
|
||||
# 创建结构体
|
||||
pictureInfo = PictureInfo()
|
||||
info = pictureInfo.make_struct(deviceId, sensorType, syncTimeStamp, filePath, os.path.basename(dirpath), os.path.splitext(fileName)[1])
|
||||
|
||||
# 格式化字典一个key对应一个数组
|
||||
pictureInfoDict.setdefault(deviceId, []).append(info)
|
||||
|
||||
if 0 == frameFileCount:
|
||||
print("initialize pictureInfoDict failed. Not found frame file")
|
||||
|
||||
|
||||
def matchFrame(pictureInfoDict):
|
||||
global primaryId, frameRate
|
||||
global streamProfileDict
|
||||
|
||||
# 获取比较图像数组,取第一个设备的Color数组来进行比较
|
||||
compareList = []
|
||||
for key in pictureInfoDict:
|
||||
listTmp = list(pictureInfoDict[key])
|
||||
for info in listTmp:
|
||||
if info.deviceId == primaryId and info.sensorType == 'ir_left':
|
||||
compareList.append(info)
|
||||
|
||||
# 根据开流情况动态分析,减少循环次数
|
||||
hasColorProfile = 'OB_SENSOR_COLOR' in streamProfileDict
|
||||
hasDepthProfile = 'OB_SENSOR_DEPTH' in streamProfileDict
|
||||
hasIRProfile = 'OB_SENSOR_IR' in streamProfileDict
|
||||
hasIRLeftProfile = 'OB_SENSOR_IR_LEFT' in streamProfileDict
|
||||
hasIRRightProfile = 'OB_SENSOR_IR_RIGHT' in streamProfileDict
|
||||
|
||||
# 匹配相邻帧
|
||||
resultDict = {}
|
||||
consumedList = []
|
||||
dictIndex = 0
|
||||
frameTspHalfGap = int(1000.0/frameRate/2.0+0.5)
|
||||
for comparePic in compareList:
|
||||
resultDict.setdefault(dictIndex, []).append(comparePic)
|
||||
for key in pictureInfoDict:
|
||||
listTmp = list(pictureInfoDict[key])
|
||||
# 对比彩色
|
||||
if hasColorProfile:
|
||||
for info in listTmp:
|
||||
if info.deviceId == primaryId and info.sensorType == comparePic.sensorType:
|
||||
continue
|
||||
|
||||
if info in consumedList:
|
||||
continue
|
||||
|
||||
if info.sensorType == 'color' and abs(info.syncTimeStamp - comparePic.syncTimeStamp) < frameTspHalfGap:
|
||||
resultDict.setdefault(dictIndex, []).append(info)
|
||||
consumedList.append(info)
|
||||
break
|
||||
|
||||
# 对Depth
|
||||
if hasDepthProfile:
|
||||
for info in listTmp:
|
||||
if info.deviceId == primaryId and info.sensorType == comparePic.sensorType:
|
||||
continue
|
||||
|
||||
if info in consumedList:
|
||||
continue
|
||||
|
||||
if info.sensorType == 'depth' and abs(info.syncTimeStamp - comparePic.syncTimeStamp) < frameTspHalfGap:
|
||||
resultDict.setdefault(dictIndex, []).append(info)
|
||||
consumedList.append(info)
|
||||
print("=====================result value : jjjjjjjjjjjjjjj:%s" % (info.syncTimeStamp))
|
||||
break
|
||||
|
||||
# IR
|
||||
if hasIRProfile:
|
||||
for info in listTmp:
|
||||
if info.deviceId == primaryId and info.sensorType == comparePic.sensorType:
|
||||
continue
|
||||
|
||||
if info in consumedList:
|
||||
continue
|
||||
|
||||
if info.sensorType == 'ir' and abs(info.syncTimeStamp - comparePic.syncTimeStamp) < frameTspHalfGap:
|
||||
resultDict.setdefault(dictIndex, []).append(info)
|
||||
consumedList.append(info)
|
||||
break
|
||||
|
||||
# 对左IR
|
||||
if hasIRLeftProfile:
|
||||
for info in listTmp:
|
||||
if info.deviceId == primaryId and info.sensorType == comparePic.sensorType:
|
||||
continue
|
||||
|
||||
if info in consumedList:
|
||||
continue
|
||||
|
||||
if info.sensorType == 'ir_left' and abs(info.syncTimeStamp - comparePic.syncTimeStamp) < frameTspHalfGap:
|
||||
resultDict.setdefault(dictIndex, []).append(info)
|
||||
consumedList.append(info)
|
||||
break
|
||||
|
||||
# 对右IR
|
||||
if hasIRRightProfile:
|
||||
for info in listTmp:
|
||||
if info.deviceId == primaryId and info.sensorType == comparePic.sensorType:
|
||||
continue
|
||||
|
||||
if info in consumedList:
|
||||
continue
|
||||
|
||||
if info.sensorType == 'ir_right' and abs(info.syncTimeStamp - comparePic.syncTimeStamp) < frameTspHalfGap:
|
||||
resultDict.setdefault(dictIndex, []).append(info)
|
||||
consumedList.append(info)
|
||||
break
|
||||
|
||||
# 计算偏差
|
||||
minTsp = min(resultDict[dictIndex], key=lambda x: x.syncTimeStamp)
|
||||
for info in resultDict[dictIndex]:
|
||||
info.tspDiff = info.syncTimeStamp - minTsp.syncTimeStamp
|
||||
|
||||
dictIndex += 1
|
||||
|
||||
return resultDict
|
||||
|
||||
|
||||
def safe_make_dir(path):
|
||||
if not os.path.exists(path):
|
||||
os.makedirs(path)
|
||||
|
||||
|
||||
def handleSyncFrames():
|
||||
global resultPath
|
||||
global sourceFramesPath
|
||||
global streamProfileDict
|
||||
|
||||
fp = open(f"{resultPath}/frameMatchLog.txt", "w")
|
||||
|
||||
if not initProfileInfoDict():
|
||||
print("Initialize stream profile dictionary failed. exit")
|
||||
return
|
||||
print(f"Stream profiles: {streamProfileDict}")
|
||||
streamProfileCount = len(streamProfileDict.items())
|
||||
|
||||
pictureInfoDict = {}
|
||||
|
||||
initPictureInfoDictionary(Path(sourceFramesPath), pictureInfoDict)
|
||||
if len(pictureInfoDict) <= 0:
|
||||
print("init pictureInfoDict failed. pictureInfoDict.len = 0")
|
||||
return
|
||||
|
||||
# # Dump pictureInfoDict
|
||||
# for key in pictureInfoDict:
|
||||
# print("===================key:%s" % key)
|
||||
# listTmp = list(pictureInfoDict[key])
|
||||
# for info in listTmp:
|
||||
# print("=====================value : deviceId:%s\tsensorType:%s\tsyncTimeStamp:%s\tpicturePath:%s" % (info.deviceId,info.sensorType,info.syncTimeStamp,info.picturePath))
|
||||
|
||||
deviceCount = getDeviceCount()
|
||||
print("=================device count:%d" % deviceCount)
|
||||
|
||||
resultDict = {}
|
||||
resultDict = matchFrame(pictureInfoDict)
|
||||
|
||||
for key in resultDict:
|
||||
fp.write("===================result key:%s\n" % key)
|
||||
print("===================result key:%s" % key)
|
||||
listTmp = list(resultDict[key])
|
||||
for info in listTmp:
|
||||
fp.write("=====================result value : deviceId:%s\tsensorType:%s\tsyncTimeStamp:%s\tpicturePath:%s\n" % (
|
||||
info.deviceId, info.sensorType, info.syncTimeStamp, info.picturePath))
|
||||
print("=====================result value : deviceId:%s\tsensorType:%s\tsyncTimeStamp:%s\tpicturePath:%s" % (
|
||||
info.deviceId, info.sensorType, info.syncTimeStamp, info.picturePath))
|
||||
|
||||
matchPath = f"{resultPath}/matchFrames/"
|
||||
safe_make_dir(matchPath)
|
||||
notMatchPath = f"{resultPath}/notMatchFrames/"
|
||||
abnormalPath = f"{resultPath}/abnormal/"
|
||||
|
||||
for key in resultDict:
|
||||
listTmp = list(resultDict[key])
|
||||
# print("***********")
|
||||
# print(listTmp)
|
||||
if (len(listTmp) == (deviceCount * streamProfileCount)):
|
||||
haveAbnormalData = False
|
||||
for info in listTmp:
|
||||
if info.tspDiff >= tspRangeThreshold:
|
||||
path = matchPath + str(key) + "_" + info.sensorType + "_" + info.deviceIdFull + "_" + str(
|
||||
info.syncTimeStamp) + "_[" + str(info.tspDiff) + "]" + "_xxxxxx" + info.fileExt
|
||||
shutil.copy(info.picturePath, path)
|
||||
haveAbnormalData = True
|
||||
else:
|
||||
# print("***********")
|
||||
# print(info.picturePath)
|
||||
# print("###########")
|
||||
path = matchPath + str(key) + "_" + info.sensorType + "_" + info.deviceIdFull + "_" + str(
|
||||
info.syncTimeStamp) + "_[" + str(info.tspDiff) + "]" + info.fileExt
|
||||
shutil.copy(info.picturePath, path)
|
||||
# print(path)
|
||||
|
||||
if haveAbnormalData:
|
||||
safe_make_dir(abnormalPath)
|
||||
for info in listTmp:
|
||||
if info.tspDiff >= tspRangeThreshold:
|
||||
path = abnormalPath + str(key) + "_" + info.sensorType + "_" + info.deviceIdFull + "_" + str(
|
||||
info.syncTimeStamp) + "_[" + str(info.tspDiff) + "]" + "_xxxxxx" + info.fileExt
|
||||
shutil.copy(info.picturePath, path)
|
||||
else:
|
||||
path = abnormalPath + str(key) + "_" + info.sensorType + "_" + info.deviceIdFull + "_" + str(
|
||||
info.syncTimeStamp) + "_[" + str(info.tspDiff) + "]" + info.fileExt
|
||||
shutil.copy(info.picturePath, path)
|
||||
else:
|
||||
safe_make_dir(notMatchPath)
|
||||
for info in listTmp:
|
||||
newFilePath = notMatchPath + str(key) + "_" + info.sensorType + "_" + info.deviceIdFull + "_" + str(
|
||||
info.syncTimeStamp) + "_[" + str(info.tspDiff) + "]" + info.fileExt
|
||||
shutil.copy(info.picturePath, newFilePath)
|
||||
|
||||
def main():
|
||||
if not initPrimaryId():
|
||||
print("Initialize primaryId failed. exit.")
|
||||
return
|
||||
|
||||
if not initSyncConfigParams():
|
||||
print("Initialized Sync config parameter failed. exit.")
|
||||
return
|
||||
|
||||
initResultDir()
|
||||
|
||||
print(f"PrimaryId={primaryId}, frameRate={frameRate}, tspRangeThreshold={tspRangeThreshold}")
|
||||
handleSyncFrames()
|
||||
|
||||
return
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
parser = argparse.ArgumentParser(description="Synchronize frames support for 'Orbbec Devices'")
|
||||
parser.add_argument('frames_dir', type=str, help="Frames directory")
|
||||
parser.add_argument('main_script_root_dir', type=str, help="SyncFramesMain.py working directory")
|
||||
args = parser.parse_args()
|
||||
|
||||
sourceRootPath = args.frames_dir
|
||||
sourceFramesPath = f"{args.frames_dir}/TotalModeFrames"
|
||||
mainPythonWorkPath = args.main_script_root_dir
|
||||
print(f"Start of CommonFrameMatch synchronize frame. sourceRootPath={sourceRootPath}")
|
||||
|
||||
main()
|
||||
|
||||
print("Finish of CommonFrameMatch synchronize frame.")
|
||||
@@ -1,408 +0,0 @@
|
||||
import os.path
|
||||
import argparse
|
||||
import sys
|
||||
import json
|
||||
import shutil
|
||||
import configparser
|
||||
|
||||
from pathlib import Path
|
||||
from datetime import datetime
|
||||
|
||||
## Config.ini中配置
|
||||
# 单位:FPS,请依据数据集实际帧率填写,否则会导致匹配不准确
|
||||
frameRate = -1
|
||||
# 单位:ms,当匹配后某组数据帧的时间戳极差大于等于tspRangeThreshold,文件名会增加标注
|
||||
tspRangeThreshold = -1
|
||||
|
||||
## Python脚本自动解析, 不要修改
|
||||
primaryId = '-1' #主机ID
|
||||
mainPythonWorkPath = "" # SyncFramesMain.py的工作目录
|
||||
sourceFramesPath = "" # 请勿修改,固定值,TotalMode目录路径
|
||||
sourceRootPath = "" # 存放TotalMode的根目录
|
||||
resultPath = "" # 保存sync分析结果
|
||||
streamProfileDict = dict() # 保存Python结果
|
||||
|
||||
class PictureInfo(object):
|
||||
class Struct(object):
|
||||
def __init__(self, deviceId, sensorType, syncTimeStamp, picturePath, deviceIdFull, fileExt):
|
||||
self.deviceId = deviceId
|
||||
self.sensorType = sensorType
|
||||
self.syncTimeStamp = syncTimeStamp
|
||||
self.picturePath = picturePath
|
||||
self.deviceIdFull = deviceIdFull
|
||||
self.fileExt = fileExt
|
||||
|
||||
def make_struct(self, deviceId, sensorType, syncTimeStamp, picturePath, deviceIdFull, fileExt):
|
||||
return self.Struct(deviceId, sensorType, syncTimeStamp, picturePath, deviceIdFull, fileExt)
|
||||
|
||||
class StreamProfileInfo:
|
||||
def __init__(self, sensorType, width, height, format, fps):
|
||||
self.sensorType = sensorType
|
||||
self.width = width
|
||||
self.height = height
|
||||
self.format = format
|
||||
self.fps = fps
|
||||
|
||||
def initPrimaryId():
|
||||
global primaryId
|
||||
|
||||
deviceInfoPath = f"{sourceRootPath}/DevicesInfo.txt"
|
||||
if not os.path.exists(deviceInfoPath):
|
||||
print(f"Initialize primaryId failed. {deviceInfoPath} not exists")
|
||||
return False
|
||||
|
||||
with open(deviceInfoPath, 'r') as f:
|
||||
data = json.load(f)
|
||||
|
||||
if not 'devices' in data:
|
||||
print(f"Initialize primaryId failed. {deviceInfoPath} not contain item 'devices'")
|
||||
return False
|
||||
|
||||
for item in data['devices']:
|
||||
if 'isPrimaryDevice' in item and 'index' in item and item['isPrimaryDevice']:
|
||||
primaryId = str(item['index'])
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
def initSyncConfigParams():
|
||||
global frameRate, tspRangeThreshold
|
||||
|
||||
configPath = f"{mainPythonWorkPath}/Config.ini"
|
||||
if not os.path.exists(configPath):
|
||||
print(f"Initliaze synchronized config parameter failed. {configPath} not exists.")
|
||||
return False
|
||||
|
||||
# 创建ConfigParser对象
|
||||
config = configparser.ConfigParser()
|
||||
|
||||
# 读取ini文件
|
||||
config.read(configPath, 'utf-8')
|
||||
|
||||
if not config.has_option('Parameter', 'frameRate'):
|
||||
print(f"Initliaze synchronized config parameter failed. Not define 'frameRate' in ${configPath}")
|
||||
return False
|
||||
|
||||
if not config.has_option('Parameter', 'tspRangeThreshold'):
|
||||
print(f"Initliaze synchronized config parameter failed. Not define 'tspRangeThreshold' in ${configPath}")
|
||||
return False
|
||||
|
||||
frameRate = config.getfloat('Parameter', 'frameRate')
|
||||
if frameRate <= 0 or frameRate >= 1000:
|
||||
print(f"Initliaze synchronized config parameter failed. Invalid frameRate={frameRate}")
|
||||
return False
|
||||
|
||||
tspRangeThreshold = config.getfloat('Parameter', 'tspRangeThreshold')
|
||||
if tspRangeThreshold <= 0:
|
||||
print(f"Initliaze synchronized config parameter failed. Invalid tspRangeThreshold={tspRangeThreshold}")
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
def getDeviceCount():
|
||||
deviceInfoPath = f"{sourceRootPath}/DevicesInfo.txt"
|
||||
if not os.path.exists(deviceInfoPath):
|
||||
print(f"Get device count failed. {deviceInfoPath} not exists")
|
||||
return 0
|
||||
|
||||
with open(deviceInfoPath, 'r') as f:
|
||||
data = json.load(f)
|
||||
|
||||
if not 'devices' in data:
|
||||
print(f"Get device count failed. {deviceInfoPath} not contain item 'devices'")
|
||||
return 0
|
||||
|
||||
return len(data['devices'])
|
||||
|
||||
def initProfileInfoDict():
|
||||
global streamProfileDict
|
||||
|
||||
streamProfileDict = dict()
|
||||
profilePath = f"{sourceRootPath}/StreamProfileInfo.txt"
|
||||
if not os.path.exists(profilePath):
|
||||
print(f"Initialize profile information dictionary failed. {profilePath} not exists")
|
||||
return False
|
||||
|
||||
with open(profilePath, 'r') as f:
|
||||
data = json.load(f)
|
||||
|
||||
if not 'streamProfiles' in data:
|
||||
print(f"Initialize profile information dictionary failed. {profilePath} not contain item 'streamProfiles'")
|
||||
return False
|
||||
|
||||
for item in data['streamProfiles']:
|
||||
if 'sensorType' in item and 'width' in item and 'height' in item and 'format' in item and 'fps' in item:
|
||||
profileInfo = StreamProfileInfo(item['sensorType'], item['width'], item['height'], item['format'], item['fps'])
|
||||
streamProfileDict.setdefault(item['sensorType'], profileInfo)
|
||||
else:
|
||||
print(f"Initialize profile information dictionary. Error invalid StreamProfile, {item}")
|
||||
|
||||
return len(streamProfileDict.items()) > 0
|
||||
|
||||
def initResultDir():
|
||||
global resultPath
|
||||
timeText = datetime.now().strftime("%Y-%m-%d_%H%M%S")
|
||||
resultPath = f"{sourceRootPath}/results-{timeText}"
|
||||
if not os.path.exists(resultPath):
|
||||
os.makedirs(resultPath)
|
||||
|
||||
def isFrameFile(fileName):
|
||||
fileExt = os.path.splitext(fileName)
|
||||
if len(fileExt) < 2:
|
||||
return False
|
||||
|
||||
frameExts = {".jpeg", ".jpg", ".png", ".raw", "bmp"}
|
||||
return fileExt[1] in frameExts
|
||||
|
||||
def initPictureInfoDictionary(rootFilePath, pictureInfoDict):
|
||||
frameFileCount = 0
|
||||
for dirpath, dirnames, filenames in os.walk(rootFilePath):
|
||||
# print(f"dirpath={dirpath}, dirpath.basename=" + os.path.basename(dirpath))
|
||||
for fileName in filenames:
|
||||
filePath = os.path.join(dirpath, fileName)
|
||||
if not isFrameFile(fileName):
|
||||
continue
|
||||
|
||||
frameFileCount += 1
|
||||
fileNameNoExt = os.path.splitext(fileName)[0]
|
||||
pictureNameList = fileNameNoExt.split('_')
|
||||
deviceId = pictureNameList[2][5:]
|
||||
sensorType = pictureNameList[0].replace('#', '_')
|
||||
syncTimeStamp = int(pictureNameList[3][1:])
|
||||
|
||||
# 创建结构体
|
||||
pictureInfo = PictureInfo()
|
||||
info = pictureInfo.make_struct(deviceId, sensorType, syncTimeStamp, filePath, os.path.basename(dirpath), os.path.splitext(fileName)[1])
|
||||
|
||||
# 格式化字典一个key对应一个数组
|
||||
pictureInfoDict.setdefault(deviceId, []).append(info)
|
||||
|
||||
if 0 == frameFileCount:
|
||||
print("initialize pictureInfoDict failed. Not found frame file")
|
||||
|
||||
|
||||
def matchFrame(pictureInfoDict):
|
||||
global primaryId, frameRate
|
||||
global streamProfileDict
|
||||
|
||||
# 获取比较图像数组,取第一个设备的Color数组来进行比较
|
||||
compareList = []
|
||||
for key in pictureInfoDict:
|
||||
listTmp = list(pictureInfoDict[key])
|
||||
for info in listTmp:
|
||||
if info.deviceId == primaryId and info.sensorType == 'color':
|
||||
compareList.append(info)
|
||||
|
||||
# 根据开流情况动态分析,减少循环次数
|
||||
hasColorProfile = 'OB_SENSOR_COLOR' in streamProfileDict
|
||||
hasDepthProfile = 'OB_SENSOR_DEPTH' in streamProfileDict
|
||||
hasIRProfile = 'OB_SENSOR_IR' in streamProfileDict
|
||||
hasIRLeftProfile = 'OB_SENSOR_IR_LEFT' in streamProfileDict
|
||||
hasIRRightProfile = 'OB_SENSOR_IR_RIGHT' in streamProfileDict
|
||||
|
||||
# 匹配相邻帧
|
||||
resultDict = {}
|
||||
consumedList = []
|
||||
dictIndex = 0
|
||||
frameTspHalfGap = int(1000.0/frameRate/2.0+0.5)
|
||||
for comparePic in compareList:
|
||||
resultDict.setdefault(dictIndex, []).append(comparePic)
|
||||
for key in pictureInfoDict:
|
||||
listTmp = list(pictureInfoDict[key])
|
||||
# 对比彩色
|
||||
if hasColorProfile:
|
||||
for info in listTmp:
|
||||
if info.deviceId == primaryId and info.sensorType == comparePic.sensorType:
|
||||
continue
|
||||
|
||||
if info in consumedList:
|
||||
continue
|
||||
|
||||
if info.sensorType == 'color' and abs(info.syncTimeStamp - comparePic.syncTimeStamp) < frameTspHalfGap:
|
||||
resultDict.setdefault(dictIndex, []).append(info)
|
||||
consumedList.append(info)
|
||||
break
|
||||
|
||||
# 对Depth
|
||||
if hasDepthProfile:
|
||||
for info in listTmp:
|
||||
if info.deviceId == primaryId and info.sensorType == comparePic.sensorType:
|
||||
continue
|
||||
|
||||
if info in consumedList:
|
||||
continue
|
||||
|
||||
if info.sensorType == 'depth' and abs(info.syncTimeStamp - comparePic.syncTimeStamp) < frameTspHalfGap:
|
||||
resultDict.setdefault(dictIndex, []).append(info)
|
||||
consumedList.append(info)
|
||||
break
|
||||
|
||||
# IR
|
||||
if hasIRProfile:
|
||||
for info in listTmp:
|
||||
if info.deviceId == primaryId and info.sensorType == comparePic.sensorType:
|
||||
continue
|
||||
|
||||
if info in consumedList:
|
||||
continue
|
||||
|
||||
if info.sensorType == 'ir' and abs(info.syncTimeStamp - comparePic.syncTimeStamp) < frameTspHalfGap:
|
||||
resultDict.setdefault(dictIndex, []).append(info)
|
||||
consumedList.append(info)
|
||||
break
|
||||
|
||||
# 对左IR
|
||||
if hasIRLeftProfile:
|
||||
for info in listTmp:
|
||||
if info.deviceId == primaryId and info.sensorType == comparePic.sensorType:
|
||||
continue
|
||||
|
||||
if info in consumedList:
|
||||
continue
|
||||
|
||||
if info.sensorType == 'ir_left' and abs(info.syncTimeStamp - comparePic.syncTimeStamp) < frameTspHalfGap:
|
||||
resultDict.setdefault(dictIndex, []).append(info)
|
||||
consumedList.append(info)
|
||||
break
|
||||
|
||||
# 对右IR
|
||||
if hasIRRightProfile:
|
||||
for info in listTmp:
|
||||
if info.deviceId == primaryId and info.sensorType == comparePic.sensorType:
|
||||
continue
|
||||
|
||||
if info in consumedList:
|
||||
continue
|
||||
|
||||
if info.sensorType == 'ir_right' and abs(info.syncTimeStamp - comparePic.syncTimeStamp) < frameTspHalfGap:
|
||||
resultDict.setdefault(dictIndex, []).append(info)
|
||||
consumedList.append(info)
|
||||
break
|
||||
|
||||
# 计算偏差
|
||||
minTsp = min(resultDict[dictIndex], key=lambda x: x.syncTimeStamp)
|
||||
for info in resultDict[dictIndex]:
|
||||
info.tspDiff = info.syncTimeStamp - minTsp.syncTimeStamp
|
||||
|
||||
dictIndex += 1
|
||||
|
||||
return resultDict
|
||||
|
||||
|
||||
def safe_make_dir(path):
|
||||
if not os.path.exists(path):
|
||||
os.makedirs(path)
|
||||
|
||||
|
||||
def handleSyncFrames():
|
||||
global resultPath
|
||||
global sourceFramesPath
|
||||
global streamProfileDict
|
||||
|
||||
fp = open(f"{resultPath}/frameMatchLog.txt", "w")
|
||||
|
||||
if not initProfileInfoDict():
|
||||
print("Initialize stream profile dictionary failed. exit")
|
||||
return
|
||||
print(f"Stream profiles: {streamProfileDict}")
|
||||
streamProfileCount = len(streamProfileDict.items())
|
||||
|
||||
pictureInfoDict = {}
|
||||
|
||||
initPictureInfoDictionary(Path(sourceFramesPath), pictureInfoDict)
|
||||
if len(pictureInfoDict) <= 0:
|
||||
print("init pictureInfoDict failed. pictureInfoDict.len = 0")
|
||||
return
|
||||
|
||||
# # Dump pictureInfoDict
|
||||
# for key in pictureInfoDict:
|
||||
# print("===================key:%s" % key)
|
||||
# listTmp = list(pictureInfoDict[key])
|
||||
# for info in listTmp:
|
||||
# print("=====================value : deviceId:%s\tsensorType:%s\tsyncTimeStamp:%s\tpicturePath:%s" % (info.deviceId,info.sensorType,info.syncTimeStamp,info.picturePath))
|
||||
|
||||
deviceCount = getDeviceCount()
|
||||
print("=================device count:%d" % deviceCount)
|
||||
|
||||
resultDict = {}
|
||||
resultDict = matchFrame(pictureInfoDict)
|
||||
|
||||
for key in resultDict:
|
||||
fp.write("===================result key:%s\n" % key)
|
||||
print("===================result key:%s" % key)
|
||||
listTmp = list(resultDict[key])
|
||||
for info in listTmp:
|
||||
fp.write("=====================result value : deviceId:%s\tsensorType:%s\tsyncTimeStamp:%s\tpicturePath:%s\n" % (
|
||||
info.deviceId, info.sensorType, info.syncTimeStamp, info.picturePath))
|
||||
print("=====================result value : deviceId:%s\tsensorType:%s\tsyncTimeStamp:%s\tpicturePath:%s" % (
|
||||
info.deviceId, info.sensorType, info.syncTimeStamp, info.picturePath))
|
||||
|
||||
matchPath = f"{resultPath}/matchFrames/"
|
||||
safe_make_dir(matchPath)
|
||||
notMatchPath = f"{resultPath}/notMatchFrames/"
|
||||
abnormalPath = f"{resultPath}/abnormal/"
|
||||
|
||||
for key in resultDict:
|
||||
listTmp = list(resultDict[key])
|
||||
if (len(listTmp) == (deviceCount * streamProfileCount)):
|
||||
haveAbnormalData = False
|
||||
for info in listTmp:
|
||||
if info.tspDiff >= tspRangeThreshold:
|
||||
path = matchPath + str(key) + "_" + info.sensorType + "_" + info.deviceIdFull + "_" + str(
|
||||
info.syncTimeStamp) + "_[" + str(info.tspDiff) + "]" + "_xxxxxx" + info.fileExt
|
||||
shutil.copy(info.picturePath, path)
|
||||
haveAbnormalData = True
|
||||
else:
|
||||
path = matchPath + str(key) + "_" + info.sensorType + "_" + info.deviceIdFull + "_" + str(
|
||||
info.syncTimeStamp) + "_[" + str(info.tspDiff) + "]" + info.fileExt
|
||||
shutil.copy(info.picturePath, path)
|
||||
|
||||
if haveAbnormalData:
|
||||
safe_make_dir(abnormalPath)
|
||||
for info in listTmp:
|
||||
if info.tspDiff >= tspRangeThreshold:
|
||||
path = abnormalPath + str(key) + "_" + info.sensorType + "_" + info.deviceIdFull + "_" + str(
|
||||
info.syncTimeStamp) + "_[" + str(info.tspDiff) + "]" + "_xxxxxx" + info.fileExt
|
||||
shutil.copy(info.picturePath, path)
|
||||
else:
|
||||
path = abnormalPath + str(key) + "_" + info.sensorType + "_" + info.deviceIdFull + "_" + str(
|
||||
info.syncTimeStamp) + "_[" + str(info.tspDiff) + "]" + info.fileExt
|
||||
shutil.copy(info.picturePath, path)
|
||||
else:
|
||||
safe_make_dir(notMatchPath)
|
||||
for info in listTmp:
|
||||
newFilePath = notMatchPath + str(key) + "_" + info.sensorType + "_" + info.deviceIdFull + "_" + str(
|
||||
info.syncTimeStamp) + "_[" + str(info.tspDiff) + "]" + info.fileExt
|
||||
shutil.copy(info.picturePath, newFilePath)
|
||||
|
||||
def main():
|
||||
if not initPrimaryId():
|
||||
print("Initialize primaryId failed. exit.")
|
||||
return
|
||||
|
||||
if not initSyncConfigParams():
|
||||
print("Initialized Sync config parameter failed. exit.")
|
||||
return
|
||||
|
||||
initResultDir()
|
||||
|
||||
print(f"PrimaryId={primaryId}, frameRate={frameRate}, tspRangeThreshold={tspRangeThreshold}")
|
||||
handleSyncFrames()
|
||||
|
||||
return
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
parser = argparse.ArgumentParser(description="Synchronize frames support for 'Orbbec Gemini 2 VL'")
|
||||
parser.add_argument('frames_dir', type=str, help="Frames directory")
|
||||
parser.add_argument('main_script_root_dir', type=str, help="SyncFramesMain.py working directory")
|
||||
args = parser.parse_args()
|
||||
|
||||
sourceRootPath = args.frames_dir
|
||||
sourceFramesPath = f"{args.frames_dir}/TotalModeFrames"
|
||||
mainPythonWorkPath = args.main_script_root_dir
|
||||
print(f"Start of Gemini2VL synchronize frame. sourceRootPath={sourceRootPath}")
|
||||
|
||||
main()
|
||||
|
||||
print("Finish of Gemini2VL synchronize frame.")
|
||||
@@ -1,412 +0,0 @@
|
||||
import os.path
|
||||
import argparse
|
||||
import sys
|
||||
import json
|
||||
import shutil
|
||||
import configparser
|
||||
|
||||
from pathlib import Path
|
||||
from datetime import datetime
|
||||
|
||||
## Config.ini中配置
|
||||
# 单位:FPS,请依据数据集实际帧率填写,否则会导致匹配不准确
|
||||
frameRate = -1
|
||||
# 单位:ms,当匹配后某组数据帧的时间戳极差大于等于tspRangeThreshold,文件名会增加标注
|
||||
tspRangeThreshold = -1
|
||||
|
||||
## Python脚本自动解析, 不要修改
|
||||
primaryId = '-1' #主机ID
|
||||
mainPythonWorkPath = "" # SyncFramesMain.py的工作目录
|
||||
sourceFramesPath = "" # 请勿修改,固定值,TotalMode目录路径
|
||||
sourceRootPath = "" # 存放TotalMode的根目录
|
||||
resultPath = "" # 保存sync分析结果
|
||||
streamProfileDict = dict() # 保存Python结果
|
||||
|
||||
class PictureInfo(object):
|
||||
class Struct(object):
|
||||
def __init__(self, deviceId, sensorType, syncTimeStamp, picturePath, deviceIdFull, fileExt, exp, gain):
|
||||
self.deviceId = deviceId
|
||||
self.sensorType = sensorType
|
||||
self.syncTimeStamp = syncTimeStamp
|
||||
self.picturePath = picturePath
|
||||
self.deviceIdFull = deviceIdFull
|
||||
self.fileExt = fileExt
|
||||
self.exp = exp
|
||||
self.gain = gain
|
||||
|
||||
def make_struct(self, deviceId, sensorType, syncTimeStamp, picturePath, deviceIdFull, fileExt, exp, gain):
|
||||
return self.Struct(deviceId, sensorType, syncTimeStamp, picturePath, deviceIdFull, fileExt, exp, gain)
|
||||
|
||||
class StreamProfileInfo:
|
||||
def __init__(self, sensorType, width, height, format, fps):
|
||||
self.sensorType = sensorType
|
||||
self.width = width
|
||||
self.height = height
|
||||
self.format = format
|
||||
self.fps = fps
|
||||
|
||||
def initPrimaryId():
|
||||
global primaryId
|
||||
|
||||
deviceInfoPath = f"{sourceRootPath}/DevicesInfo.txt"
|
||||
if not os.path.exists(deviceInfoPath):
|
||||
print(f"Initialize primaryId failed. {deviceInfoPath} not exists")
|
||||
return False
|
||||
|
||||
with open(deviceInfoPath, 'r') as f:
|
||||
data = json.load(f)
|
||||
|
||||
if not 'devices' in data:
|
||||
print(f"Initialize primaryId failed. {deviceInfoPath} not contain item 'devices'")
|
||||
return False
|
||||
|
||||
for item in data['devices']:
|
||||
if 'isPrimaryDevice' in item and 'index' in item and item['isPrimaryDevice']:
|
||||
primaryId = str(item['index'])
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
def initSyncConfigParams():
|
||||
global frameRate, tspRangeThreshold
|
||||
|
||||
configPath = f"{mainPythonWorkPath}/Config.ini"
|
||||
if not os.path.exists(configPath):
|
||||
print(f"Initliaze synchronized config parameter failed. {configPath} not exists.")
|
||||
return False
|
||||
|
||||
# 创建ConfigParser对象
|
||||
config = configparser.ConfigParser()
|
||||
|
||||
# 读取ini文件
|
||||
config.read(configPath, 'utf-8')
|
||||
|
||||
if not config.has_option('Parameter', 'frameRate'):
|
||||
print(f"Initliaze synchronized config parameter failed. Not define 'frameRate' in ${configPath}")
|
||||
return False
|
||||
|
||||
if not config.has_option('Parameter', 'tspRangeThreshold'):
|
||||
print(f"Initliaze synchronized config parameter failed. Not define 'tspRangeThreshold' in ${configPath}")
|
||||
return False
|
||||
|
||||
frameRate = config.getfloat('Parameter', 'frameRate')
|
||||
if frameRate <= 0 or frameRate >= 1000:
|
||||
print(f"Initliaze synchronized config parameter failed. Invalid frameRate={frameRate}")
|
||||
return False
|
||||
|
||||
tspRangeThreshold = config.getfloat('Parameter', 'tspRangeThreshold')
|
||||
if tspRangeThreshold <= 0:
|
||||
print(f"Initliaze synchronized config parameter failed. Invalid tspRangeThreshold={tspRangeThreshold}")
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
def getDeviceCount():
|
||||
deviceInfoPath = f"{sourceRootPath}/DevicesInfo.txt"
|
||||
if not os.path.exists(deviceInfoPath):
|
||||
print(f"Get device count failed. {deviceInfoPath} not exists")
|
||||
return 0
|
||||
|
||||
with open(deviceInfoPath, 'r') as f:
|
||||
data = json.load(f)
|
||||
|
||||
if not 'devices' in data:
|
||||
print(f"Get device count failed. {deviceInfoPath} not contain item 'devices'")
|
||||
return 0
|
||||
|
||||
return len(data['devices'])
|
||||
|
||||
def initProfileInfoDict():
|
||||
global streamProfileDict
|
||||
|
||||
streamProfileDict = dict()
|
||||
profilePath = f"{sourceRootPath}/StreamProfileInfo.txt"
|
||||
if not os.path.exists(profilePath):
|
||||
print(f"Initialize profile information dictionary failed. {profilePath} not exists")
|
||||
return False
|
||||
|
||||
with open(profilePath, 'r') as f:
|
||||
data = json.load(f)
|
||||
|
||||
if not 'streamProfiles' in data:
|
||||
print(f"Initialize profile information dictionary failed. {profilePath} not contain item 'streamProfiles'")
|
||||
return False
|
||||
|
||||
for item in data['streamProfiles']:
|
||||
if 'sensorType' in item and 'width' in item and 'height' in item and 'format' in item and 'fps' in item:
|
||||
profileInfo = StreamProfileInfo(item['sensorType'], item['width'], item['height'], item['format'], item['fps'])
|
||||
streamProfileDict.setdefault(item['sensorType'], profileInfo)
|
||||
else:
|
||||
print(f"Initialize profile information dictionary. Error invalid StreamProfile, {item}")
|
||||
|
||||
return len(streamProfileDict.items()) > 0
|
||||
|
||||
def initResultDir():
|
||||
global resultPath
|
||||
timeText = datetime.now().strftime("%Y-%m-%d_%H%M%S")
|
||||
resultPath = f"{sourceRootPath}/results-{timeText}"
|
||||
if not os.path.exists(resultPath):
|
||||
os.makedirs(resultPath)
|
||||
|
||||
def isFrameFile(fileName):
|
||||
fileExt = os.path.splitext(fileName)
|
||||
if len(fileExt) < 2:
|
||||
return False
|
||||
|
||||
frameExts = {".jpeg", ".jpg", ".png", ".raw", "bmp"}
|
||||
return fileExt[1] in frameExts
|
||||
|
||||
def initPictureInfoDictionary(rootFilePath, pictureInfoDict):
|
||||
frameFileCount = 0
|
||||
for dirpath, dirnames, filenames in os.walk(rootFilePath):
|
||||
# print(f"dirpath={dirpath}, dirpath.basename=" + os.path.basename(dirpath))
|
||||
for fileName in filenames:
|
||||
filePath = os.path.join(dirpath, fileName)
|
||||
if not isFrameFile(fileName):
|
||||
continue
|
||||
|
||||
frameFileCount += 1
|
||||
fileNameNoExt = os.path.splitext(fileName)[0]
|
||||
pictureNameList = fileNameNoExt.split('_')
|
||||
deviceId = pictureNameList[2][5:]
|
||||
sensorType = pictureNameList[0].replace('#', '_')
|
||||
syncTimeStamp = int(pictureNameList[3][1:])
|
||||
exp = str(pictureNameList[6][0:])
|
||||
gain = str(pictureNameList[7][0:])
|
||||
|
||||
# 创建结构体
|
||||
pictureInfo = PictureInfo()
|
||||
info = pictureInfo.make_struct(deviceId, sensorType, syncTimeStamp, filePath, os.path.basename(dirpath), os.path.splitext(fileName)[1],exp,gain)
|
||||
|
||||
# 格式化字典一个key对应一个数组
|
||||
pictureInfoDict.setdefault(deviceId, []).append(info)
|
||||
|
||||
if 0 == frameFileCount:
|
||||
print("initialize pictureInfoDict failed. Not found frame file")
|
||||
|
||||
|
||||
def matchFrame(pictureInfoDict):
|
||||
global primaryId, frameRate
|
||||
global streamProfileDict
|
||||
|
||||
# 获取比较图像数组,取第一个设备的Color数组来进行比较
|
||||
compareList = []
|
||||
for key in pictureInfoDict:
|
||||
listTmp = list(pictureInfoDict[key])
|
||||
for info in listTmp:
|
||||
if info.deviceId == primaryId and info.sensorType == 'color':
|
||||
compareList.append(info)
|
||||
|
||||
# 根据开流情况动态分析,减少循环次数
|
||||
hasColorProfile = 'OB_SENSOR_COLOR' in streamProfileDict
|
||||
hasDepthProfile = 'OB_SENSOR_DEPTH' in streamProfileDict
|
||||
hasIRProfile = 'OB_SENSOR_IR' in streamProfileDict
|
||||
hasIRLeftProfile = 'OB_SENSOR_IR_LEFT' in streamProfileDict
|
||||
hasIRRightProfile = 'OB_SENSOR_IR_RIGHT' in streamProfileDict
|
||||
|
||||
# 匹配相邻帧
|
||||
resultDict = {}
|
||||
consumedList = []
|
||||
dictIndex = 0
|
||||
frameTspHalfGap = int(1000.0/frameRate/2.0+0.5)
|
||||
for comparePic in compareList:
|
||||
resultDict.setdefault(dictIndex, []).append(comparePic)
|
||||
for key in pictureInfoDict:
|
||||
listTmp = list(pictureInfoDict[key])
|
||||
# 对比彩色
|
||||
if hasColorProfile:
|
||||
for info in listTmp:
|
||||
if info.deviceId == primaryId and info.sensorType == comparePic.sensorType:
|
||||
continue
|
||||
|
||||
if info in consumedList:
|
||||
continue
|
||||
|
||||
if info.sensorType == 'color' and abs(info.syncTimeStamp - comparePic.syncTimeStamp) < frameTspHalfGap:
|
||||
resultDict.setdefault(dictIndex, []).append(info)
|
||||
consumedList.append(info)
|
||||
break
|
||||
|
||||
# 对Depth
|
||||
if hasDepthProfile:
|
||||
for info in listTmp:
|
||||
if info.deviceId == primaryId and info.sensorType == comparePic.sensorType:
|
||||
continue
|
||||
|
||||
if info in consumedList:
|
||||
continue
|
||||
|
||||
if info.sensorType == 'depth' and abs(info.syncTimeStamp - comparePic.syncTimeStamp) < frameTspHalfGap:
|
||||
resultDict.setdefault(dictIndex, []).append(info)
|
||||
consumedList.append(info)
|
||||
break
|
||||
|
||||
# IR
|
||||
if hasIRProfile:
|
||||
for info in listTmp:
|
||||
if info.deviceId == primaryId and info.sensorType == comparePic.sensorType:
|
||||
continue
|
||||
|
||||
if info in consumedList:
|
||||
continue
|
||||
|
||||
if info.sensorType == 'ir' and abs(info.syncTimeStamp - comparePic.syncTimeStamp) < frameTspHalfGap:
|
||||
resultDict.setdefault(dictIndex, []).append(info)
|
||||
consumedList.append(info)
|
||||
break
|
||||
|
||||
# 对左IR
|
||||
if hasIRLeftProfile:
|
||||
for info in listTmp:
|
||||
if info.deviceId == primaryId and info.sensorType == comparePic.sensorType:
|
||||
continue
|
||||
|
||||
if info in consumedList:
|
||||
continue
|
||||
|
||||
if info.sensorType == 'ir_left' and abs(info.syncTimeStamp - comparePic.syncTimeStamp) < frameTspHalfGap:
|
||||
resultDict.setdefault(dictIndex, []).append(info)
|
||||
consumedList.append(info)
|
||||
break
|
||||
|
||||
# 对右IR
|
||||
if hasIRRightProfile:
|
||||
for info in listTmp:
|
||||
if info.deviceId == primaryId and info.sensorType == comparePic.sensorType:
|
||||
continue
|
||||
|
||||
if info in consumedList:
|
||||
continue
|
||||
|
||||
if info.sensorType == 'ir_right' and abs(info.syncTimeStamp - comparePic.syncTimeStamp) < frameTspHalfGap:
|
||||
resultDict.setdefault(dictIndex, []).append(info)
|
||||
consumedList.append(info)
|
||||
break
|
||||
|
||||
# 计算偏差
|
||||
minTsp = min(resultDict[dictIndex], key=lambda x: x.syncTimeStamp)
|
||||
for info in resultDict[dictIndex]:
|
||||
info.tspDiff = info.syncTimeStamp - minTsp.syncTimeStamp
|
||||
|
||||
dictIndex += 1
|
||||
|
||||
return resultDict
|
||||
|
||||
|
||||
def safe_make_dir(path):
|
||||
if not os.path.exists(path):
|
||||
os.makedirs(path)
|
||||
|
||||
|
||||
def handleSyncFrames():
|
||||
global resultPath
|
||||
global sourceFramesPath
|
||||
global streamProfileDict
|
||||
|
||||
fp = open(f"{resultPath}/frameMatchLog.txt", "w")
|
||||
|
||||
if not initProfileInfoDict():
|
||||
print("Initialize stream profile dictionary failed. exit")
|
||||
return
|
||||
print(f"Stream profiles: {streamProfileDict}")
|
||||
streamProfileCount = len(streamProfileDict.items())
|
||||
|
||||
pictureInfoDict = {}
|
||||
|
||||
initPictureInfoDictionary(Path(sourceFramesPath), pictureInfoDict)
|
||||
if len(pictureInfoDict) <= 0:
|
||||
print("init pictureInfoDict failed. pictureInfoDict.len = 0")
|
||||
return
|
||||
|
||||
# # Dump pictureInfoDict
|
||||
# for key in pictureInfoDict:
|
||||
# print("===================key:%s" % key)
|
||||
# listTmp = list(pictureInfoDict[key])
|
||||
# for info in listTmp:
|
||||
# print("=====================value : deviceId:%s\tsensorType:%s\tsyncTimeStamp:%s\tpicturePath:%s" % (info.deviceId,info.sensorType,info.syncTimeStamp,info.picturePath))
|
||||
|
||||
deviceCount = getDeviceCount()
|
||||
print("=================device count:%d" % deviceCount)
|
||||
|
||||
resultDict = {}
|
||||
resultDict = matchFrame(pictureInfoDict)
|
||||
|
||||
for key in resultDict:
|
||||
fp.write("===================result key:%s\n" % key)
|
||||
print("===================result key:%s" % key)
|
||||
listTmp = list(resultDict[key])
|
||||
for info in listTmp:
|
||||
fp.write("=====================result value : deviceId:%s\tsensorType:%s\tsyncTimeStamp:%s\tpicturePath:%s\n" % (
|
||||
info.deviceId, info.sensorType, info.syncTimeStamp, info.picturePath))
|
||||
print("=====================result value : deviceId:%s\tsensorType:%s\tsyncTimeStamp:%s\tpicturePath:%s" % (
|
||||
info.deviceId, info.sensorType, info.syncTimeStamp, info.picturePath))
|
||||
|
||||
matchPath = f"{resultPath}/matchFrames/"
|
||||
safe_make_dir(matchPath)
|
||||
notMatchPath = f"{resultPath}/notMatchFrames/"
|
||||
abnormalPath = f"{resultPath}/abnormal/"
|
||||
|
||||
for key in resultDict:
|
||||
listTmp = list(resultDict[key])
|
||||
if (len(listTmp) == (deviceCount * streamProfileCount)):
|
||||
haveAbnormalData = False
|
||||
for info in listTmp:
|
||||
if info.tspDiff >= tspRangeThreshold:
|
||||
path = matchPath + str(key) + "_" + info.sensorType + "_" + info.deviceIdFull + "_" + str(
|
||||
info.syncTimeStamp) + "_[" + str(info.tspDiff) + "]" + "_xxxxxx" + "_"+ str(info.exp) + "_"+ str(info.gain) + info.fileExt
|
||||
shutil.copy(info.picturePath, path)
|
||||
haveAbnormalData = True
|
||||
else:
|
||||
path = matchPath + str(key) + "_" + info.sensorType + "_" + info.deviceIdFull + "_" + str(
|
||||
info.syncTimeStamp) + "_[" + str(info.tspDiff) + "]" + "_"+ str(info.exp) + "_"+ str(info.gain) + info.fileExt
|
||||
shutil.copy(info.picturePath, path)
|
||||
|
||||
if haveAbnormalData:
|
||||
safe_make_dir(abnormalPath)
|
||||
for info in listTmp:
|
||||
if info.tspDiff >= tspRangeThreshold:
|
||||
path = abnormalPath + str(key) + "_" + info.sensorType + "_" + info.deviceIdFull + "_" + str(
|
||||
info.syncTimeStamp) + "_[" + str(info.tspDiff) + "]" + "_xxxxxx" + "_"+ str(info.exp) + "_"+ str(info.gain) + info.fileExt
|
||||
shutil.copy(info.picturePath, path)
|
||||
else:
|
||||
path = abnormalPath + str(key) + "_" + info.sensorType + "_" + info.deviceIdFull + "_" + str(
|
||||
info.syncTimeStamp) + "_[" + str(info.tspDiff) + "]" + "_"+ str(info.exp) + "_"+ str(info.gain) + info.fileExt
|
||||
shutil.copy(info.picturePath, path)
|
||||
else:
|
||||
safe_make_dir(notMatchPath)
|
||||
for info in listTmp:
|
||||
newFilePath = notMatchPath + str(key) + "_" + info.sensorType + "_" + info.deviceIdFull + "_" + str(
|
||||
info.syncTimeStamp) + "_[" + str(info.tspDiff) + "]" + "_"+ str(info.exp) + "_"+ str(info.gain) + info.fileExt
|
||||
shutil.copy(info.picturePath, newFilePath)
|
||||
|
||||
def main():
|
||||
if not initPrimaryId():
|
||||
print("Initialize primaryId failed. exit.")
|
||||
return
|
||||
|
||||
if not initSyncConfigParams():
|
||||
print("Initialized Sync config parameter failed. exit.")
|
||||
return
|
||||
|
||||
initResultDir()
|
||||
|
||||
print(f"PrimaryId={primaryId}, frameRate={frameRate}, tspRangeThreshold={tspRangeThreshold}")
|
||||
handleSyncFrames()
|
||||
|
||||
return
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
parser = argparse.ArgumentParser(description="Synchronize frames support for 'Orbbec Devices'")
|
||||
parser.add_argument('frames_dir', type=str, help="Frames directory")
|
||||
parser.add_argument('main_script_root_dir', type=str, help="SyncFramesMain.py working directory")
|
||||
args = parser.parse_args()
|
||||
|
||||
sourceRootPath = args.frames_dir
|
||||
sourceFramesPath = f"{args.frames_dir}/TotalModeFrames"
|
||||
mainPythonWorkPath = args.main_script_root_dir
|
||||
print(f"Start of CommonFrameMatch synchronize frame. sourceRootPath={sourceRootPath}")
|
||||
|
||||
main()
|
||||
|
||||
print("Finish of CommonFrameMatch synchronize frame.")
|
||||
@@ -1,42 +0,0 @@
|
||||
{
|
||||
"deviceVid": "0x2BC5",
|
||||
"devicePid": "0x0800",
|
||||
"primarySerialNumber": "CP1E5420006D",
|
||||
"devices": [{
|
||||
"index": 0,
|
||||
"isPrimaryDevice": true,
|
||||
"vid": "0x2BC5",
|
||||
"pid": "0x0800",
|
||||
"name": "Orbbec Gemini 335",
|
||||
"firmwareVersion": "1.3.64",
|
||||
"serialNumber": "CP1E5420006D",
|
||||
"hardwareVersion": "0.1",
|
||||
"ipAddress": "0.0.0.0",
|
||||
"extensionInfo": {
|
||||
"ExtensionInfo": {
|
||||
"IspFwVer": "20240820",
|
||||
"IspNeedVer": "20240820",
|
||||
"HwType": "R1",
|
||||
"HwVer": "V1.1"
|
||||
}
|
||||
}
|
||||
}, {
|
||||
"index": 1,
|
||||
"isPrimaryDevice": false,
|
||||
"vid": "0x2BC5",
|
||||
"pid": "0x0800",
|
||||
"name": "Orbbec Gemini 335",
|
||||
"firmwareVersion": "1.3.64",
|
||||
"serialNumber": "CP1L44P00051",
|
||||
"hardwareVersion": "0.1",
|
||||
"ipAddress": "0.0.0.0",
|
||||
"extensionInfo": {
|
||||
"ExtensionInfo": {
|
||||
"IspFwVer": "20240820",
|
||||
"IspNeedVer": "20240820",
|
||||
"HwType": "R1",
|
||||
"HwVer": "V1.0"
|
||||
}
|
||||
}
|
||||
}]
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
{
|
||||
"D2CAlignMode": "ALIGN_D2C_SW_MODE",
|
||||
"streamProfiles": [{
|
||||
"sensorType": "OB_SENSOR_COLOR",
|
||||
"width": 1280,
|
||||
"height": 720,
|
||||
"fps": 30,
|
||||
"format": "MJPEG"
|
||||
}, {
|
||||
"sensorType": "OB_SENSOR_IR_LEFT",
|
||||
"width": 848,
|
||||
"height": 480,
|
||||
"fps": 30,
|
||||
"format": "Y8"
|
||||
}]
|
||||
}
|
||||
|
Before Width: | Height: | Size: 144 KiB |
|
Before Width: | Height: | Size: 145 KiB |
|
Before Width: | Height: | Size: 145 KiB |
|
Before Width: | Height: | Size: 145 KiB |
|
Before Width: | Height: | Size: 145 KiB |
|
Before Width: | Height: | Size: 145 KiB |