From 9cd83444fb30950b64f2f7c9b9f70c59ca133140 Mon Sep 17 00:00:00 2001 From: zilog Date: Thu, 28 Nov 2019 12:21:58 +0100 Subject: [PATCH] updated the realsense libraries to match a more up to date version --- .../h/rs_advanced_mode_command.h | 5 + .../include/librealsense2/h/rs_config.h | 200 ++++ .../include/librealsense2/h/rs_context.h | 38 +- .../include/librealsense2/h/rs_device.h | 95 ++ .../include/librealsense2/h/rs_frame.h | 75 +- .../include/librealsense2/h/rs_internal.h | 92 +- .../include/librealsense2/h/rs_option.h | 355 ++++--- .../include/librealsense2/h/rs_pipeline.h | 243 ++--- .../include/librealsense2/h/rs_processing.h | 83 ++ .../librealsense2/h/rs_record_playback.h | 11 + .../include/librealsense2/h/rs_sensor.h | 162 ++- .../include/librealsense2/h/rs_types.h | 86 +- .../include/librealsense2/hpp/rs_context.hpp | 55 +- .../include/librealsense2/hpp/rs_device.hpp | 228 +++- .../include/librealsense2/hpp/rs_export.hpp | 260 +++++ .../include/librealsense2/hpp/rs_frame.hpp | 304 ++++-- .../include/librealsense2/hpp/rs_internal.hpp | 71 +- .../include/librealsense2/hpp/rs_options.hpp | 160 +++ .../include/librealsense2/hpp/rs_pipeline.hpp | 118 ++- .../librealsense2/hpp/rs_processing.hpp | 973 +++++++++++------- .../librealsense2/hpp/rs_record_playback.hpp | 24 +- .../include/librealsense2/hpp/rs_sensor.hpp | 351 ++++--- .../include/librealsense2/hpp/rs_types.hpp | 10 + libs/realsense2/include/librealsense2/rs.h | 6 +- libs/realsense2/include/librealsense2/rs.hpp | 2 +- .../include/librealsense2/rs_advanced_mode.h | 5 + .../librealsense2/rs_advanced_mode.hpp | 23 + .../realsense2/include/librealsense2/rsutil.h | 145 ++- 28 files changed, 3144 insertions(+), 1036 deletions(-) create mode 100644 libs/realsense2/include/librealsense2/h/rs_config.h create mode 100644 libs/realsense2/include/librealsense2/hpp/rs_export.hpp create mode 100644 libs/realsense2/include/librealsense2/hpp/rs_options.hpp diff --git a/libs/realsense2/include/librealsense2/h/rs_advanced_mode_command.h b/libs/realsense2/include/librealsense2/h/rs_advanced_mode_command.h index eead854..ce8b462 100755 --- a/libs/realsense2/include/librealsense2/h/rs_advanced_mode_command.h +++ b/libs/realsense2/include/librealsense2/h/rs_advanced_mode_command.h @@ -122,6 +122,11 @@ typedef struct uint32_t vDiameter; }STCensusRadius; +typedef struct +{ + float amplitude; +}STAFactor; + #ifdef __cplusplus extern "C"{ #endif diff --git a/libs/realsense2/include/librealsense2/h/rs_config.h b/libs/realsense2/include/librealsense2/h/rs_config.h new file mode 100644 index 0000000..43bff1d --- /dev/null +++ b/libs/realsense2/include/librealsense2/h/rs_config.h @@ -0,0 +1,200 @@ +/* License: Apache 2.0. See LICENSE file in root directory. +Copyright(c) 2017 Intel Corporation. All Rights Reserved. */ + +/** \file rs_pipeline.h +* \brief +* Exposes RealSense processing-block functionality for C compilers +*/ + + +#ifndef LIBREALSENSE_RS2_CONFIG_H +#define LIBREALSENSE_RS2_CONFIG_H + +#define RS2_DEFAULT_TIMEOUT 15000 + +#ifdef __cplusplus +extern "C" { +#endif + +#include "rs_types.h" +#include "rs_sensor.h" + + /** + * Create a config instance + * The config allows pipeline users to request filters for the pipeline streams and device selection and configuration. + * This is an optional step in pipeline creation, as the pipeline resolves its streaming device internally. + * Config provides its users a way to set the filters and test if there is no conflict with the pipeline requirements + * from the device. It also allows the user to find a matching device for the config filters and the pipeline, in order to + * select a device explicitly, and modify its controls before streaming starts. + * + * \param[out] error if non-null, receives any error that occurs during this call, otherwise, errors are ignored + * \return rs2_config* A pointer to a new config instance + */ + rs2_config* rs2_create_config(rs2_error** error); + + /** + * Deletes an instance of a config + * + * \param[in] config A pointer to an instance of a config + */ + void rs2_delete_config(rs2_config* config); + + /** + * Enable a device stream explicitly, with selected stream parameters. + * The method allows the application to request a stream with specific configuration. If no stream is explicitly enabled, the pipeline + * configures the device and its streams according to the attached computer vision modules and processing blocks requirements, or + * default configuration for the first available device. + * The application can configure any of the input stream parameters according to its requirement, or set to 0 for don't care value. + * The config accumulates the application calls for enable configuration methods, until the configuration is applied. Multiple enable + * stream calls for the same stream with conflicting parameters override each other, and the last call is maintained. + * Upon calling \c resolve(), the config checks for conflicts between the application configuration requests and the attached computer + * vision modules and processing blocks requirements, and fails if conflicts are found. Before \c resolve() is called, no conflict + * check is done. + * + * \param[in] config A pointer to an instance of a config + * \param[in] stream Stream type to be enabled + * \param[in] index Stream index, used for multiple streams of the same type. -1 indicates any. + * \param[in] width Stream image width - for images streams. 0 indicates any. + * \param[in] height Stream image height - for images streams. 0 indicates any. + * \param[in] format Stream data format - pixel format for images streams, of data type for other streams. RS2_FORMAT_ANY indicates any. + * \param[in] framerate Stream frames per second. 0 indicates any. + * \param[out] error if non-null, receives any error that occurs during this call, otherwise, errors are ignored + */ + void rs2_config_enable_stream(rs2_config* config, + rs2_stream stream, + int index, + int width, + int height, + rs2_format format, + int framerate, + rs2_error** error); + + /** + * Enable all device streams explicitly. + * The conditions and behavior of this method are similar to those of \c enable_stream(). + * This filter enables all raw streams of the selected device. The device is either selected explicitly by the application, + * or by the pipeline requirements or default. The list of streams is device dependent. + * + * \param[in] config A pointer to an instance of a config + * \param[out] error if non-null, receives any error that occurs during this call, otherwise, errors are ignored + */ + void rs2_config_enable_all_stream(rs2_config* config, rs2_error ** error); + + /** + * Select a specific device explicitly by its serial number, to be used by the pipeline. + * The conditions and behavior of this method are similar to those of \c enable_stream(). + * This method is required if the application needs to set device or sensor settings prior to pipeline streaming, to enforce + * the pipeline to use the configured device. + * + * \param[in] config A pointer to an instance of a config + * \param[in] serial device serial number, as returned by RS2_CAMERA_INFO_SERIAL_NUMBER + * \param[out] error if non-null, receives any error that occurs during this call, otherwise, errors are ignored + */ + void rs2_config_enable_device(rs2_config* config, const char* serial, rs2_error ** error); + + /** + * Select a recorded device from a file, to be used by the pipeline through playback. + * The device available streams are as recorded to the file, and \c resolve() considers only this device and configuration + * as available. + * This request cannot be used if enable_record_to_file() is called for the current config, and vise versa + * By default, playback is repeated once the file ends. To control this, see 'rs2_config_enable_device_from_file_repeat_option'. + * + * \param[in] config A pointer to an instance of a config + * \param[in] file The playback file of the device + * \param[out] error if non-null, receives any error that occurs during this call, otherwise, errors are ignored + */ + void rs2_config_enable_device_from_file(rs2_config* config, const char* file, rs2_error ** error); + + /** + * Select a recorded device from a file, to be used by the pipeline through playback. + * The device available streams are as recorded to the file, and \c resolve() considers only this device and configuration + * as available. + * This request cannot be used if enable_record_to_file() is called for the current config, and vise versa + * + * \param[in] config A pointer to an instance of a config + * \param[in] file The playback file of the device + * \param[in] repeat_playback if true, when file ends the playback starts again, in an infinite loop; + if false, when file ends playback does not start again, and should by stopped manually by the user. + * \param[out] error if non-null, receives any error that occurs during this call, otherwise, errors are ignored + */ + void rs2_config_enable_device_from_file_repeat_option(rs2_config* config, const char* file, int repeat_playback, rs2_error ** error); + + /** + * Requires that the resolved device would be recorded to file + * This request cannot be used if enable_device_from_file() is called for the current config, and vise versa + * + * \param[in] config A pointer to an instance of a config + * \param[in] file The desired file for the output record + * \param[out] error if non-null, receives any error that occurs during this call, otherwise, errors are ignored + */ + void rs2_config_enable_record_to_file(rs2_config* config, const char* file, rs2_error ** error); + + + /** + * Disable a device stream explicitly, to remove any requests on this stream type. + * The stream can still be enabled due to pipeline computer vision module request. This call removes any filter on the + * stream configuration. + * + * \param[in] config A pointer to an instance of a config + * \param[in] stream Stream type, for which the filters are cleared + * \param[out] error if non-null, receives any error that occurs during this call, otherwise, errors are ignored + */ + void rs2_config_disable_stream(rs2_config* config, rs2_stream stream, rs2_error ** error); + + /** + * Disable a device stream explicitly, to remove any requests on this stream profile. + * The stream can still be enabled due to pipeline computer vision module request. This call removes any filter on the + * stream configuration. + * + * \param[in] config A pointer to an instance of a config + * \param[in] stream Stream type, for which the filters are cleared + * \param[in] index Stream index, for which the filters are cleared + * \param[out] error if non-null, receives any error that occurs during this call, otherwise, errors are ignored + */ + void rs2_config_disable_indexed_stream(rs2_config* config, rs2_stream stream, int index, rs2_error ** error); + + /** + * Disable all device stream explicitly, to remove any requests on the streams profiles. + * The streams can still be enabled due to pipeline computer vision module request. This call removes any filter on the + * streams configuration. + * + * \param[in] config A pointer to an instance of a config + * \param[out] error if non-null, receives any error that occurs during this call, otherwise, errors are ignored + */ + void rs2_config_disable_all_streams(rs2_config* config, rs2_error ** error); + + /** + * Resolve the configuration filters, to find a matching device and streams profiles. + * The method resolves the user configuration filters for the device and streams, and combines them with the requirements of + * the computer vision modules and processing blocks attached to the pipeline. If there are no conflicts of requests, it looks + * for an available device, which can satisfy all requests, and selects the first matching streams configuration. In the absence + * of any request, the rs2::config selects the first available device and the first color and depth streams configuration. + * The pipeline profile selection during \c start() follows the same method. Thus, the selected profile is the same, if no + * change occurs to the available devices occurs. + * Resolving the pipeline configuration provides the application access to the pipeline selected device for advanced control. + * The returned configuration is not applied to the device, so the application doesn't own the device sensors. However, the + * application can call \c enable_device(), to enforce the device returned by this method is selected by pipeline \c start(), + * and configure the device and sensors options or extensions before streaming starts. + * + * \param[in] config A pointer to an instance of a config + * \param[in] pipe The pipeline for which the selected filters are applied + * \param[out] error if non-null, receives any error that occurs during this call, otherwise, errors are ignored + * \return A matching device and streams profile, which satisfies the filters and pipeline requests. + */ + rs2_pipeline_profile* rs2_config_resolve(rs2_config* config, rs2_pipeline* pipe, rs2_error ** error); + + /** + * Check if the config can resolve the configuration filters, to find a matching device and streams profiles. + * The resolution conditions are as described in \c resolve(). + * + * \param[in] config A pointer to an instance of a config + * \param[in] pipe The pipeline for which the selected filters are applied + * \param[out] error if non-null, receives any error that occurs during this call, otherwise, errors are ignored + * \return True if a valid profile selection exists, false if no selection can be found under the config filters and the available devices. + */ + int rs2_config_can_resolve(rs2_config* config, rs2_pipeline* pipe, rs2_error ** error); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/libs/realsense2/include/librealsense2/h/rs_context.h b/libs/realsense2/include/librealsense2/h/rs_context.h index 52718f3..cd316cd 100755 --- a/libs/realsense2/include/librealsense2/h/rs_context.h +++ b/libs/realsense2/include/librealsense2/h/rs_context.h @@ -54,6 +54,14 @@ void rs2_set_devices_changed_callback(const rs2_context* context, rs2_devices_ch * @return A pointer to a device that plays data from the file, or null in case of failure */ rs2_device* rs2_context_add_device(rs2_context* ctx, const char* file, rs2_error** error); + +/** + * Add an instance of software device to the context + * \param ctx The context to which the new device will be added + * \param dev Instance of software device to register into the context + * \param[out] error If non-null, receives any error that occurs during this call, otherwise, errors are ignored + */ +void rs2_context_add_software_device(rs2_context* ctx, rs2_device* dev, rs2_error** error); /** * Removes a playback device from the context, if exists @@ -63,6 +71,15 @@ rs2_device* rs2_context_add_device(rs2_context* ctx, const char* file, rs2_error */ void rs2_context_remove_device(rs2_context* ctx, const char* file, rs2_error** error); +/** + * Removes tracking module. + * function query_devices() locks the tracking module in the tm_context object. + * If the tracking module device is not used it should be removed using this function, so that other applications could find it. + * This function can be used both before the call to query_device() to prevent enabling tracking modules or afterwards to + * release them. + */ +void rs2_context_unload_tracking_module(rs2_context* ctx, rs2_error** error); + /** * create a static snapshot of all connected devices at the time of the call * \param context Object representing librealsense session @@ -71,6 +88,25 @@ void rs2_context_remove_device(rs2_context* ctx, const char* file, rs2_error** e */ rs2_device_list* rs2_query_devices(const rs2_context* context, rs2_error** error); +#define RS2_PRODUCT_LINE_ANY 0xff +#define RS2_PRODUCT_LINE_ANY_INTEL 0xfe +#define RS2_PRODUCT_LINE_NON_INTEL 0x01 +#define RS2_PRODUCT_LINE_D400 0x02 +#define RS2_PRODUCT_LINE_SR300 0x04 +#define RS2_PRODUCT_LINE_L500 0x08 +#define RS2_PRODUCT_LINE_T200 0x10 +#define RS2_PRODUCT_LINE_DEPTH (RS2_PRODUCT_LINE_L500 | RS2_PRODUCT_LINE_SR300 | RS2_PRODUCT_LINE_D400) +#define RS2_PRODUCT_LINE_TRACKING RS2_PRODUCT_LINE_T200 + +/** +* create a static snapshot of all connected devices at the time of the call +* \param context Object representing librealsense session +* \param product_mask Controls what kind of devices will be returned +* \param[out] error if non-null, receives any error that occurs during this call, otherwise, errors are ignored +* \return the list of devices, should be released by rs2_delete_device_list +*/ +rs2_device_list* rs2_query_devices_ex(const rs2_context* context, int product_mask, rs2_error** error); + /** * \brief Creates RealSense device_hub . * \param[in] context The context for the device hub @@ -93,7 +129,7 @@ void rs2_delete_device_hub(const rs2_device_hub* hub); * \param[out] error If non-null, receives any error that occurs during this call, otherwise, errors are ignored. * \return device object */ -rs2_device* rs2_device_hub_wait_for_device(rs2_context* ctx, const rs2_device_hub* hub, rs2_error** error); +rs2_device* rs2_device_hub_wait_for_device(const rs2_device_hub* hub, rs2_error** error); /** * Checks if device is still connected diff --git a/libs/realsense2/include/librealsense2/h/rs_device.h b/libs/realsense2/include/librealsense2/h/rs_device.h index 5ef5de3..0806b9b 100755 --- a/libs/realsense2/include/librealsense2/h/rs_device.h +++ b/libs/realsense2/include/librealsense2/h/rs_device.h @@ -146,6 +146,101 @@ void rs2_connect_tm2_controller(const rs2_device* device, const unsigned char* m */ void rs2_disconnect_tm2_controller(const rs2_device* device, int id, rs2_error** error); + +/** +* Reset device to factory calibration +* \param[in] device The RealSense device +* \param[out] error If non-null, receives any error that occurs during this call, otherwise, errors are ignored +*/ +void rs2_reset_to_factory_calibration(const rs2_device* device, rs2_error** e); + +/** +* Write calibration to device's EEPROM +* \param[in] device The RealSense device +* \param[out] error If non-null, receives any error that occurs during this call, otherwise, errors are ignored +*/ +void rs2_write_calibration(const rs2_device* device, rs2_error** e); + +/** +* Update device to the provided firmware, the device must be extendable to RS2_EXTENSION_UPDATABLE. +* This call is executed on the caller's thread and it supports progress notifications via the optional callback. +* \param[in] device Device to update +* \param[in] fw_image Firmware image buffer +* \param[in] fw_image_size Firmware image buffer size +* \param[in] callback Optional callback for update progress notifications, the progress value is normailzed to 1 +* \param[out] error If non-null, receives any error that occurs during this call, otherwise, errors are ignored +*/ +void rs2_update_firmware_cpp(const rs2_device* device, const void* fw_image, int fw_image_size, rs2_update_progress_callback* callback, rs2_error** error); + +/** +* Update device to the provided firmware, the device must be extendable to RS2_EXTENSION_UPDATABLE. +* This call is executed on the caller's thread and it supports progress notifications via the optional callback. +* \param[in] device Device to update +* \param[in] fw_image Firmware image buffer +* \param[in] fw_image_size Firmware image buffer size +* \param[in] callback Optional callback for update progress notifications, the progress value is normailzed to 1 +* \param[in] client_data Optional client data for the callback +* \param[out] error If non-null, receives any error that occurs during this call, otherwise, errors are ignored +*/ +void rs2_update_firmware(const rs2_device* device, const void* fw_image, int fw_image_size, rs2_update_progress_callback_ptr callback, void* client_data, rs2_error** error); + +/** +* Create backup of camera flash memory. Such backup does not constitute valid firmware image, and cannot be +* loaded back to the device, but it does contain all calibration and device information. +* \param[in] device Device to update +* \param[in] callback Optional callback for update progress notifications, the progress value is normailzed to 1 +* \param[out] error If non-null, receives any error that occurs during this call, otherwise, errors are ignored +*/ +const rs2_raw_data_buffer* rs2_create_flash_backup_cpp(const rs2_device* device, rs2_update_progress_callback* callback, rs2_error** error); + +/** +* Create backup of camera flash memory. Such backup does not constitute valid firmware image, and cannot be +* loaded back to the device, but it does contain all calibration and device information. +* \param[in] device Device to update +* \param[in] callback Optional callback for update progress notifications, the progress value is normailzed to 1 +* \param[in] client_data Optional client data for the callback +* \param[out] error If non-null, receives any error that occurs during this call, otherwise, errors are ignored +*/ +const rs2_raw_data_buffer* rs2_create_flash_backup(const rs2_device* device, rs2_update_progress_callback_ptr callback, void* client_data, rs2_error** error); + +#define RS2_UNSIGNED_UPDATE_MODE_UPDATE 0 +#define RS2_UNSIGNED_UPDATE_MODE_READ_ONLY 1 +#define RS2_UNSIGNED_UPDATE_MODE_FULL 2 + +/** +* Update device to the provided firmware by writing raw data directly to the flash, this command can be executed only on unlocked camera. +* The device must be extendable to RS2_EXTENSION_UPDATABLE. +* This call is executed on the caller's thread and it supports progress notifications via the optional callback. +* \param[in] device Device to update +* \param[in] fw_image Firmware image buffer +* \param[in] fw_image_size Firmware image buffer size +* \param[in] callback Optional callback for update progress notifications, the progress value is normailzed to 1 +* \param[in] update_mode Select one of RS2_UNSIGNED_UPDATE_MODE, WARNING!!! setting to any option other than RS2_UNSIGNED_UPDATE_MODE_UPDATE will make this call unsafe and might damage the camera +* \param[out] error If non-null, receives any error that occurs during this call, otherwise, errors are ignored +*/ +void rs2_update_firmware_unsigned_cpp(const rs2_device* device, const void* fw_image, int fw_image_size, rs2_update_progress_callback* callback, int update_mode, rs2_error** error); + +/** +* Update device to the provided firmware by writing raw data directly to the flash, this command can be executed only on unlocked camera. +* The device must be extendable to RS2_EXTENSION_UPDATABLE. +* This call is executed on the caller's thread and it supports progress notifications via the optional callback. +* \param[in] device Device to update +* \param[in] fw_image Firmware image buffer +* \param[in] fw_image_size Firmware image buffer size +* \param[in] callback Optional callback for update progress notifications, the progress value is normailzed to 1 +* \param[in] client_data Optional client data for the callback +* \param[in] update_mode Select one of RS2_UNSIGNED_UPDATE_MODE, WARNING!!! setting to any option other than RS2_UNSIGNED_UPDATE_MODE_UPDATE will make this call unsafe and might damage the camera +* \param[out] error If non-null, receives any error that occurs during this call, otherwise, errors are ignored +*/ +void rs2_update_firmware_unsigned(const rs2_device* device, const void* fw_image, int fw_image_size, rs2_update_progress_callback_ptr callback, void* client_data, int update_mode, rs2_error** error); + +/** +* Enter the device to update state, this will cause the updatable device to disconnect and reconnect as update device. +* \param[in] device Device to update +* \param[out] error If non-null, receives any error that occurs during this call, otherwise, errors are ignored +*/ +void rs2_enter_update_state(const rs2_device* device, rs2_error** error); + #ifdef __cplusplus } #endif diff --git a/libs/realsense2/include/librealsense2/h/rs_frame.h b/libs/realsense2/include/librealsense2/h/rs_frame.h index c346d24..9a2f95e 100755 --- a/libs/realsense2/include/librealsense2/h/rs_frame.h +++ b/libs/realsense2/include/librealsense2/h/rs_frame.h @@ -20,11 +20,12 @@ typedef enum rs2_timestamp_domain { RS2_TIMESTAMP_DOMAIN_HARDWARE_CLOCK, /**< Frame timestamp was measured in relation to the camera clock */ RS2_TIMESTAMP_DOMAIN_SYSTEM_TIME, /**< Frame timestamp was measured in relation to the OS system clock */ + RS2_TIMESTAMP_DOMAIN_GLOBAL_TIME, /**< Frame timestamp was measured in relation to the camera clock and converted to OS system clock by constantly measure the difference*/ RS2_TIMESTAMP_DOMAIN_COUNT /**< Number of enumeration values. Not a valid input: intended to be used in for-loops. */ } rs2_timestamp_domain; const char* rs2_timestamp_domain_to_string(rs2_timestamp_domain info); -/** \brief Per-Frame-Metadata are set of read-only properties that might be exposed for each individual frame */ +/** \brief Per-Frame-Metadata is the set of read-only properties that might be exposed for each individual frame. */ typedef enum rs2_frame_metadata_value { RS2_FRAME_METADATA_FRAME_COUNTER , /**< A sequential index managed per-stream. Integer value*/ @@ -40,9 +41,9 @@ typedef enum rs2_frame_metadata_value RS2_FRAME_METADATA_BACKEND_TIMESTAMP , /**< Timestamp get from uvc driver. usec*/ RS2_FRAME_METADATA_ACTUAL_FPS , /**< Actual fps */ RS2_FRAME_METADATA_FRAME_LASER_POWER , /**< Laser power value 0-360. */ - RS2_FRAME_METADATA_FRAME_LASER_POWER_MODE , /**< Laser power mode. Zero corresponds to Laser power switched off and one for switched on. */ + RS2_FRAME_METADATA_FRAME_LASER_POWER_MODE , /**< Laser power mode. Zero corresponds to Laser power switched off and one for switched on. */ RS2_FRAME_METADATA_EXPOSURE_PRIORITY , /**< Exposure priority. */ - RS2_FRAME_METADATA_EXPOSURE_ROI_LEFT , /**< Left region of interest for the auto exposure Algorithm. */ + RS2_FRAME_METADATA_EXPOSURE_ROI_LEFT , /**< Left region of interest for the auto exposure Algorithm. */ RS2_FRAME_METADATA_EXPOSURE_ROI_RIGHT , /**< Right region of interest for the auto exposure Algorithm. */ RS2_FRAME_METADATA_EXPOSURE_ROI_TOP , /**< Top region of interest for the auto exposure Algorithm. */ RS2_FRAME_METADATA_EXPOSURE_ROI_BOTTOM , /**< Bottom region of interest for the auto exposure Algorithm. */ @@ -62,44 +63,6 @@ typedef enum rs2_frame_metadata_value const char* rs2_frame_metadata_to_string(rs2_frame_metadata_value metadata); const char* rs2_frame_metadata_value_to_string(rs2_frame_metadata_value metadata); -/** \brief 3D coordinates with origin at topmost left corner of the lense, - with positive Z pointing away from the camera, positive X pointing camera right and positive Y pointing camera down */ -typedef struct rs2_vertex -{ - float xyz[3]; -} rs2_vertex; - -/** \brief Pixel location within 2D image. (0,0) is the topmost, left corner. Positive X is right, positive Y is down */ -typedef struct rs2_pixel -{ - int ij[2]; -} rs2_pixel; - -/** \brief 3D vector in Euclidean coordinate space */ -typedef struct rs2_vector -{ - float x, y, z; -}rs2_vector; - -/** \brief Quaternion used to represent rotation */ -typedef struct rs2_quaternion -{ - float x, y, z, w; -}rs2_quaternion; - -typedef struct rs2_pose -{ - rs2_vector translation; /**< X, Y, Z values of translation, in meters (relative to initial position) */ - rs2_vector velocity; /**< X, Y, Z values of velocity, in meter/sec */ - rs2_vector acceleration; /**< X, Y, Z values of acceleration, in meter/sec^2 */ - rs2_quaternion rotation; /**< Qi, Qj, Qk, Qr components of rotation as represented in quaternion rotation (relative to initial position) */ - rs2_vector angular_velocity; /**< X, Y, Z values of angular velocity, in radians/sec */ - rs2_vector angular_acceleration; /**< X, Y, Z values of angular acceleration, in radians/sec^2 */ - unsigned int tracker_confidence; /**< pose data confidence 0x0 - Failed, 0x1 - Low, 0x2 - Medium, 0x3 - High */ - unsigned int mapper_confidence; /**< pose data confidence 0x0 - Failed, 0x1 - Low, 0x2 - Medium, 0x3 - High */ -} rs2_pose; - - /** * retrieve metadata from frame handle * \param[in] frame handle returned from a callback @@ -136,6 +99,14 @@ rs2_timestamp_domain rs2_get_frame_timestamp_domain(const rs2_frame* frameset, r */ rs2_time_t rs2_get_frame_timestamp(const rs2_frame* frame, rs2_error** error); +/** +* retrieve frame parent sensor from frame handle +* \param[in] frame handle returned from a callback +* \param[out] error if non-null, receives any error that occurs during this call, otherwise, errors are ignored +* \return the parent sensor of the frame +*/ +rs2_sensor* rs2_get_frame_sensor(const rs2_frame* frame, rs2_error** error); + /** * retrieve frame number from frame handle * \param[in] frame handle returned from a callback @@ -144,6 +115,14 @@ rs2_time_t rs2_get_frame_timestamp(const rs2_frame* frame, rs2_error** error); */ unsigned long long rs2_get_frame_number(const rs2_frame* frame, rs2_error** error); +/** +* retrieve data size from frame handle +* \param[in] frame handle returned from a callback +* \param[out] error if non-null, receives any error that occurs during this call, otherwise, errors are ignored +* \return the size of the frame data +*/ +int rs2_get_frame_data_size(const rs2_frame* frame, rs2_error** error); + /** * retrieve data from frame handle * \param[in] frame handle returned from a callback @@ -276,6 +255,17 @@ int rs2_is_frame_extendable_to(const rs2_frame* frame, rs2_extension extension_t rs2_frame* rs2_allocate_synthetic_video_frame(rs2_source* source, const rs2_stream_profile* new_stream, rs2_frame* original, int new_bpp, int new_width, int new_height, int new_stride, rs2_extension frame_type, rs2_error** error); +/** +* Allocate new points frame using a frame-source provided from a processing block +* \param[in] source Frame pool to allocate the frame from +* \param[in] new_stream New stream profile to assign to newly created frame +* \param[in] original A reference frame that can be used to fill in auxilary information like format, width, height, bpp, stride (if applicable) +* \param[out] error If non-null, receives any error that occurs during this call, otherwise, errors are ignored +* \return reference to a newly allocated frame, must be released with release_frame +* memory for the frame is likely to be re-used from previous frame, but in lack of available frames in the pool will be allocated from the free store +*/ +rs2_frame* rs2_allocate_points(rs2_source* source, const rs2_stream_profile* new_stream, rs2_frame* original, rs2_error** error); + /** * Allocate new composite frame, aggregating a set of existing frames * \param[in] source Frame pool to allocate the frame from @@ -323,9 +313,6 @@ void rs2_synthetic_frame_ready(rs2_source* source, rs2_frame* frame, rs2_error** */ void rs2_pose_frame_get_pose_data(const rs2_frame* frame, rs2_pose* pose, rs2_error** error); - - - #ifdef __cplusplus } #endif diff --git a/libs/realsense2/include/librealsense2/h/rs_internal.h b/libs/realsense2/include/librealsense2/h/rs_internal.h index d812c99..28a58ab 100755 --- a/libs/realsense2/include/librealsense2/h/rs_internal.h +++ b/libs/realsense2/include/librealsense2/h/rs_internal.h @@ -30,7 +30,7 @@ typedef enum rs2_recording_mode RS2_RECORDING_MODE_COUNT } rs2_recording_mode; -/** \brief All the parameters are requaired to defind video stream*/ +/** \brief All the parameters are required to define video stream*/ typedef struct rs2_video_stream { rs2_stream type; @@ -44,7 +44,28 @@ typedef struct rs2_video_stream rs2_intrinsics intrinsics; } rs2_video_stream; -/** \brief All the parameters are requaired to define video frame*/ +/** \brief All the parameters are required to define motion stream*/ +typedef struct rs2_motion_stream +{ + rs2_stream type; + int index; + int uid; + int fps; + rs2_format fmt; + rs2_motion_device_intrinsic intrinsics; +} rs2_motion_stream; + +/** \brief All the parameters are required to define pose stream*/ +typedef struct rs2_pose_stream +{ + rs2_stream type; + int index; + int uid; + int fps; + rs2_format fmt; +} rs2_pose_stream; + +/** \brief All the parameters are required to define video frame*/ typedef struct rs2_software_video_frame { void* pixels; @@ -57,6 +78,39 @@ typedef struct rs2_software_video_frame const rs2_stream_profile* profile; } rs2_software_video_frame; +/** \brief All the parameters are required to define motion frame*/ +typedef struct rs2_software_motion_frame +{ + void* data; + void(*deleter)(void*); + rs2_time_t timestamp; + rs2_timestamp_domain domain; + int frame_number; + const rs2_stream_profile* profile; +} rs2_software_motion_frame; + +/** \brief All the parameters are required to define pose frame*/ +typedef struct rs2_software_pose_frame +{ + struct pose_frame_info + { + float translation[3]; + float velocity[3]; + float acceleration[3]; + float rotation[4]; + float angular_velocity[3]; + float angular_acceleration[3]; + int tracker_confidence; + int mapper_confidence; + }; + void* data; + void(*deleter)(void*); + rs2_time_t timestamp; + rs2_timestamp_domain domain; + int frame_number; + const rs2_stream_profile* profile; +} rs2_software_pose_frame; + /** * Create librealsense context that will try to record all operations over librealsense into a file * \param[in] api_version realsense API version as provided by RS2_API_VERSION macro @@ -108,13 +162,29 @@ rs2_device* rs2_create_software_device(rs2_error** error); rs2_sensor* rs2_software_device_add_sensor(rs2_device* dev, const char* sensor_name, rs2_error** error); /** - * Inject frame to software sonsor + * Inject video frame to software sonsor * \param[in] sensor the software sensor * \param[in] frame all the frame components * \param[out] error if non-null, receives any error that occurs during this call, otherwise, errors are ignored */ void rs2_software_sensor_on_video_frame(rs2_sensor* sensor, rs2_software_video_frame frame, rs2_error** error); +/** +* Inject motion frame to software sonsor +* \param[in] sensor the software sensor +* \param[in] frame all the frame components +* \param[out] error if non-null, receives any error that occurs during this call, otherwise, errors are ignored +*/ +void rs2_software_sensor_on_motion_frame(rs2_sensor* sensor, rs2_software_motion_frame frame, rs2_error** error); + +/** +* Inject pose frame to software sonsor +* \param[in] sensor the software sensor +* \param[in] frame all the frame components +* \param[out] error if non-null, receives any error that occurs during this call, otherwise, errors are ignored +*/ +void rs2_software_sensor_on_pose_frame(rs2_sensor* sensor, rs2_software_pose_frame frame, rs2_error** error); + /** * Set frame metadata for the upcoming frames * \param[in] sensor the software sensor @@ -140,6 +210,22 @@ void rs2_software_device_create_matcher(rs2_device* dev, rs2_matchers matcher, r */ rs2_stream_profile* rs2_software_sensor_add_video_stream(rs2_sensor* sensor, rs2_video_stream video_stream, rs2_error** error); +/** +* Add motion stream to sensor +* \param[in] sensor the software sensor +* \param[in] video_stream all the stream components +* \param[out] error if non-null, receives any error that occurs during this call, otherwise, errors are ignored +*/ +rs2_stream_profile* rs2_software_sensor_add_motion_stream(rs2_sensor* sensor, rs2_motion_stream motion_stream, rs2_error** error); + +/** +* Add pose stream to sensor +* \param[in] sensor the software sensor +* \param[in] video_stream all the stream components +* \param[out] error if non-null, receives any error that occurs during this call, otherwise, errors are ignored +*/ +rs2_stream_profile* rs2_software_sensor_add_pose_stream(rs2_sensor* sensor, rs2_pose_stream pose_stream, rs2_error** error); + /** * Add read only option to sensor * \param[in] sensor the software sensor diff --git a/libs/realsense2/include/librealsense2/h/rs_option.h b/libs/realsense2/include/librealsense2/h/rs_option.h index 71be14b..bd1c130 100755 --- a/libs/realsense2/include/librealsense2/h/rs_option.h +++ b/libs/realsense2/include/librealsense2/h/rs_option.h @@ -1,5 +1,5 @@ /* License: Apache 2.0. See LICENSE file in root directory. - Copyright(c) 2017 Intel Corporation. All Rights Reserved. */ +Copyright(c) 2017 Intel Corporation. All Rights Reserved. */ /** \file rs_option.h * \brief @@ -16,156 +16,211 @@ extern "C" { #include "rs_types.h" -/** \brief Defines general configuration controls. - These can generally be mapped to camera UVC controls, and unless stated otherwise, can be set/queried at any time. + /** \brief Defines general configuration controls. + These can generally be mapped to camera UVC controls, and can be set / queried at any time unless stated otherwise. */ -typedef enum rs2_option -{ - RS2_OPTION_BACKLIGHT_COMPENSATION , /**< Enable / disable color backlight compensation*/ - RS2_OPTION_BRIGHTNESS , /**< Color image brightness*/ - RS2_OPTION_CONTRAST , /**< Color image contrast*/ - RS2_OPTION_EXPOSURE , /**< Controls exposure time of color camera. Setting any value will disable auto exposure*/ - RS2_OPTION_GAIN , /**< Color image gain*/ - RS2_OPTION_GAMMA , /**< Color image gamma setting*/ - RS2_OPTION_HUE , /**< Color image hue*/ - RS2_OPTION_SATURATION , /**< Color image saturation setting*/ - RS2_OPTION_SHARPNESS , /**< Color image sharpness setting*/ - RS2_OPTION_WHITE_BALANCE , /**< Controls white balance of color image. Setting any value will disable auto white balance*/ - RS2_OPTION_ENABLE_AUTO_EXPOSURE , /**< Enable / disable color image auto-exposure*/ - RS2_OPTION_ENABLE_AUTO_WHITE_BALANCE , /**< Enable / disable color image auto-white-balance*/ - RS2_OPTION_VISUAL_PRESET , /**< Provide access to several recommend sets of option presets for the depth camera */ - RS2_OPTION_LASER_POWER , /**< Power of the F200 / SR300 projector, with 0 meaning projector off*/ - RS2_OPTION_ACCURACY , /**< Set the number of patterns projected per frame. The higher the accuracy value the more patterns projected. Increasing the number of patterns help to achieve better accuracy. Note that this control is affecting the Depth FPS */ - RS2_OPTION_MOTION_RANGE , /**< Motion vs. Range trade-off, with lower values allowing for better motion sensitivity and higher values allowing for better depth range*/ - RS2_OPTION_FILTER_OPTION , /**< Set the filter to apply to each depth frame. Each one of the filter is optimized per the application requirements*/ - RS2_OPTION_CONFIDENCE_THRESHOLD , /**< The confidence level threshold used by the Depth algorithm pipe to set whether a pixel will get a valid range or will be marked with invalid range*/ - RS2_OPTION_EMITTER_ENABLED , /**< Laser Emitter enabled */ - RS2_OPTION_FRAMES_QUEUE_SIZE , /**< Number of frames the user is allowed to keep per stream. Trying to hold-on to more frames will cause frame-drops.*/ - RS2_OPTION_TOTAL_FRAME_DROPS , /**< Total number of detected frame drops from all streams */ - RS2_OPTION_AUTO_EXPOSURE_MODE , /**< Auto-Exposure modes: Static, Anti-Flicker and Hybrid */ - RS2_OPTION_POWER_LINE_FREQUENCY , /**< Power Line Frequency control for anti-flickering Off/50Hz/60Hz/Auto */ - RS2_OPTION_ASIC_TEMPERATURE , /**< Current Asic Temperature */ - RS2_OPTION_ERROR_POLLING_ENABLED , /**< disable error handling */ - RS2_OPTION_PROJECTOR_TEMPERATURE , /**< Current Projector Temperature */ - RS2_OPTION_OUTPUT_TRIGGER_ENABLED , /**< Enable / disable trigger to be outputed from the camera to any external device on every depth frame */ - RS2_OPTION_MOTION_MODULE_TEMPERATURE , /**< Current Motion-Module Temperature */ - RS2_OPTION_DEPTH_UNITS , /**< Number of meters represented by a single depth unit */ - RS2_OPTION_ENABLE_MOTION_CORRECTION , /**< Enable/Disable automatic correction of the motion data */ - RS2_OPTION_AUTO_EXPOSURE_PRIORITY , /**< Allows sensor to dynamically ajust the frame rate depending on lighting conditions */ - RS2_OPTION_COLOR_SCHEME , /**< Color scheme for data visualization */ - RS2_OPTION_HISTOGRAM_EQUALIZATION_ENABLED , /**< Perform histogram equalization post-processing on the depth data */ - RS2_OPTION_MIN_DISTANCE , /**< Minimal distance to the target */ - RS2_OPTION_MAX_DISTANCE , /**< Maximum distance to the target */ - RS2_OPTION_TEXTURE_SOURCE , /**< Texture mapping stream unique ID */ - RS2_OPTION_FILTER_MAGNITUDE , /**< The 2D-filter effect. The specific interpretation is given within the context of the filter */ - RS2_OPTION_FILTER_SMOOTH_ALPHA , /**< 2D-filter parameter controls the weight/radius for smoothing.*/ - RS2_OPTION_FILTER_SMOOTH_DELTA , /**< 2D-filter range/validity threshold*/ - RS2_OPTION_HOLES_FILL , /**< Enhance depth data post-processing with holes filling where appropriate*/ - RS2_OPTION_STEREO_BASELINE , /**< The distance in mm between the first and the second imagers in stereo-based depth cameras*/ - RS2_OPTION_AUTO_EXPOSURE_CONVERGE_STEP , /**< Allows dynamically ajust the converge step value of the target exposure in Auto-Exposure algorithm*/ - RS2_OPTION_INTER_CAM_SYNC_MODE , /**< Impose Inter-camera HW synchronization mode. Applicable for D400/Rolling Shutter SKUs */ - RS2_OPTION_COUNT /**< Number of enumeration values. Not a valid input: intended to be used in for-loops. */ -} rs2_option; -const char* rs2_option_to_string(rs2_option option); - -/** \brief For SR300 devices: provides optimized settings (presets) for specific types of usage. */ -typedef enum rs2_sr300_visual_preset -{ - RS2_SR300_VISUAL_PRESET_SHORT_RANGE , /**< Preset for short range */ - RS2_SR300_VISUAL_PRESET_LONG_RANGE , /**< Preset for long range */ - RS2_SR300_VISUAL_PRESET_BACKGROUND_SEGMENTATION , /**< Preset for background segmentation */ - RS2_SR300_VISUAL_PRESET_GESTURE_RECOGNITION , /**< Preset for gesture recognition */ - RS2_SR300_VISUAL_PRESET_OBJECT_SCANNING , /**< Preset for object scanning */ - RS2_SR300_VISUAL_PRESET_FACE_ANALYTICS , /**< Preset for face analytics */ - RS2_SR300_VISUAL_PRESET_FACE_LOGIN , /**< Preset for face login */ - RS2_SR300_VISUAL_PRESET_GR_CURSOR , /**< Preset for GR cursor */ - RS2_SR300_VISUAL_PRESET_DEFAULT , /**< Camera default settings */ - RS2_SR300_VISUAL_PRESET_MID_RANGE , /**< Preset for mid-range */ - RS2_SR300_VISUAL_PRESET_IR_ONLY , /**< Preset for IR only */ - RS2_SR300_VISUAL_PRESET_COUNT /**< Number of enumeration values. Not a valid input: intended to be used in for-loops. */ -} rs2_sr300_visual_preset; -const char* rs2_sr300_visual_preset_to_string(rs2_sr300_visual_preset preset); - -/** \brief For RS400 devices: provides optimized settings (presets) for specific types of usage. */ -typedef enum rs2_rs400_visual_preset -{ - RS2_RS400_VISUAL_PRESET_CUSTOM, - RS2_RS400_VISUAL_PRESET_DEFAULT, - RS2_RS400_VISUAL_PRESET_HAND, - RS2_RS400_VISUAL_PRESET_HIGH_ACCURACY, - RS2_RS400_VISUAL_PRESET_HIGH_DENSITY, - RS2_RS400_VISUAL_PRESET_MEDIUM_DENSITY, - RS2_RS400_VISUAL_PRESET_REMOVE_IR_PATTERN, - RS2_RS400_VISUAL_PRESET_COUNT -} rs2_rs400_visual_preset; -const char* rs2_rs400_visual_preset_to_string(rs2_rs400_visual_preset preset); - -/** -* check if an option is read-only -* \param[in] sensor the RealSense sensor -* \param[in] option option id to be checked -* \param[out] error if non-null, receives any error that occurs during this call, otherwise, errors are ignored -* \return true if option is read-only -*/ -int rs2_is_option_read_only(const rs2_options* options, rs2_option option, rs2_error** error); - -/** -* read option value from the sensor -* \param[in] sensor the RealSense sensor -* \param[in] option option id to be queried -* \param[out] error if non-null, receives any error that occurs during this call, otherwise, errors are ignored -* \return value of the option -*/ -float rs2_get_option(const rs2_options* options, rs2_option option, rs2_error** error); - -/** -* write new value to sensor option -* \param[in] sensor the RealSense sensor -* \param[in] option option id to be queried -* \param[in] value new value for the option -* \param[out] error if non-null, receives any error that occurs during this call, otherwise, errors are ignored -*/ -void rs2_set_option(const rs2_options* options, rs2_option option, float value, rs2_error** error); - -/** -* check if particular option is supported by a subdevice -* \param[in] sensor the RealSense sensor -* \param[in] option option id to be checked -* \param[out] error if non-null, receives any error that occurs during this call, otherwise, errors are ignored -* \return true if option is supported -*/ -int rs2_supports_option(const rs2_options* options, rs2_option option, rs2_error** error); - -/** -* retrieve the available range of values of a supported option -* \param[in] sensor the RealSense device -* \param[in] option the option whose range should be queried -* \param[out] min the minimum value which will be accepted for this option -* \param[out] max the maximum value which will be accepted for this option -* \param[out] step the granularity of options which accept discrete values, or zero if the option accepts continuous values -* \param[out] def the default value of the option -* \param[out] error if non-null, receives any error that occurs during this call, otherwise, errors are ignored -*/ -void rs2_get_option_range(const rs2_options* sensor, rs2_option option, float* min, float* max, float* step, float* def, rs2_error** error); - -/** -* get option description -* \param[in] sensor the RealSense sensor -* \param[in] option option id to be checked -* \param[out] error if non-null, receives any error that occurs during this call, otherwise, errors are ignored -* \return human-readable option description -*/ -const char* rs2_get_option_description(const rs2_options* options, rs2_option option, rs2_error ** error); - -/** -* get option value description (in case specific option value hold special meaning) -* \param[in] device the RealSense device -* \param[in] option option id to be checked -* \param[in] value value of the option -* \param[out] error if non-null, receives any error that occurs during this call, otherwise, errors are ignored -* \return human-readable description of a specific value of an option or null if no special meaning -*/ -const char* rs2_get_option_value_description(const rs2_options* options, rs2_option option, float value, rs2_error ** error); + typedef enum rs2_option + { + RS2_OPTION_BACKLIGHT_COMPENSATION, /**< Enable / disable color backlight compensation*/ + RS2_OPTION_BRIGHTNESS, /**< Color image brightness*/ + RS2_OPTION_CONTRAST, /**< Color image contrast*/ + RS2_OPTION_EXPOSURE, /**< Controls exposure time of color camera. Setting any value will disable auto exposure*/ + RS2_OPTION_GAIN, /**< Color image gain*/ + RS2_OPTION_GAMMA, /**< Color image gamma setting*/ + RS2_OPTION_HUE, /**< Color image hue*/ + RS2_OPTION_SATURATION, /**< Color image saturation setting*/ + RS2_OPTION_SHARPNESS, /**< Color image sharpness setting*/ + RS2_OPTION_WHITE_BALANCE, /**< Controls white balance of color image. Setting any value will disable auto white balance*/ + RS2_OPTION_ENABLE_AUTO_EXPOSURE, /**< Enable / disable color image auto-exposure*/ + RS2_OPTION_ENABLE_AUTO_WHITE_BALANCE, /**< Enable / disable color image auto-white-balance*/ + RS2_OPTION_VISUAL_PRESET, /**< Provide access to several recommend sets of option presets for the depth camera */ + RS2_OPTION_LASER_POWER, /**< Power of the F200 / SR300 projector, with 0 meaning projector off*/ + RS2_OPTION_ACCURACY, /**< Set the number of patterns projected per frame. The higher the accuracy value the more patterns projected. Increasing the number of patterns help to achieve better accuracy. Note that this control is affecting the Depth FPS */ + RS2_OPTION_MOTION_RANGE, /**< Motion vs. Range trade-off, with lower values allowing for better motion sensitivity and higher values allowing for better depth range*/ + RS2_OPTION_FILTER_OPTION, /**< Set the filter to apply to each depth frame. Each one of the filter is optimized per the application requirements*/ + RS2_OPTION_CONFIDENCE_THRESHOLD, /**< The confidence level threshold used by the Depth algorithm pipe to set whether a pixel will get a valid range or will be marked with invalid range*/ + RS2_OPTION_EMITTER_ENABLED, /**< Laser Emitter enabled */ + RS2_OPTION_FRAMES_QUEUE_SIZE, /**< Number of frames the user is allowed to keep per stream. Trying to hold-on to more frames will cause frame-drops.*/ + RS2_OPTION_TOTAL_FRAME_DROPS, /**< Total number of detected frame drops from all streams */ + RS2_OPTION_AUTO_EXPOSURE_MODE, /**< Auto-Exposure modes: Static, Anti-Flicker and Hybrid */ + RS2_OPTION_POWER_LINE_FREQUENCY, /**< Power Line Frequency control for anti-flickering Off/50Hz/60Hz/Auto */ + RS2_OPTION_ASIC_TEMPERATURE, /**< Current Asic Temperature */ + RS2_OPTION_ERROR_POLLING_ENABLED, /**< disable error handling */ + RS2_OPTION_PROJECTOR_TEMPERATURE, /**< Current Projector Temperature */ + RS2_OPTION_OUTPUT_TRIGGER_ENABLED, /**< Enable / disable trigger to be outputed from the camera to any external device on every depth frame */ + RS2_OPTION_MOTION_MODULE_TEMPERATURE, /**< Current Motion-Module Temperature */ + RS2_OPTION_DEPTH_UNITS, /**< Number of meters represented by a single depth unit */ + RS2_OPTION_ENABLE_MOTION_CORRECTION, /**< Enable/Disable automatic correction of the motion data */ + RS2_OPTION_AUTO_EXPOSURE_PRIORITY, /**< Allows sensor to dynamically ajust the frame rate depending on lighting conditions */ + RS2_OPTION_COLOR_SCHEME, /**< Color scheme for data visualization */ + RS2_OPTION_HISTOGRAM_EQUALIZATION_ENABLED, /**< Perform histogram equalization post-processing on the depth data */ + RS2_OPTION_MIN_DISTANCE, /**< Minimal distance to the target */ + RS2_OPTION_MAX_DISTANCE, /**< Maximum distance to the target */ + RS2_OPTION_TEXTURE_SOURCE, /**< Texture mapping stream unique ID */ + RS2_OPTION_FILTER_MAGNITUDE, /**< The 2D-filter effect. The specific interpretation is given within the context of the filter */ + RS2_OPTION_FILTER_SMOOTH_ALPHA, /**< 2D-filter parameter controls the weight/radius for smoothing.*/ + RS2_OPTION_FILTER_SMOOTH_DELTA, /**< 2D-filter range/validity threshold*/ + RS2_OPTION_HOLES_FILL, /**< Enhance depth data post-processing with holes filling where appropriate*/ + RS2_OPTION_STEREO_BASELINE, /**< The distance in mm between the first and the second imagers in stereo-based depth cameras*/ + RS2_OPTION_AUTO_EXPOSURE_CONVERGE_STEP, /**< Allows dynamically ajust the converge step value of the target exposure in Auto-Exposure algorithm*/ + RS2_OPTION_INTER_CAM_SYNC_MODE, /**< Impose Inter-camera HW synchronization mode. Applicable for D400/Rolling Shutter SKUs */ + RS2_OPTION_STREAM_FILTER, /**< Select a stream to process */ + RS2_OPTION_STREAM_FORMAT_FILTER, /**< Select a stream format to process */ + RS2_OPTION_STREAM_INDEX_FILTER, /**< Select a stream index to process */ + RS2_OPTION_EMITTER_ON_OFF, /**< When supported, this option make the camera to switch the emitter state every frame. 0 for disabled, 1 for enabled */ + RS2_OPTION_ZERO_ORDER_POINT_X, /**< Zero order point x*/ + RS2_OPTION_ZERO_ORDER_POINT_Y, /**< Zero order point y*/ + RS2_OPTION_LLD_TEMPERATURE, /**< LLD temperature*/ + RS2_OPTION_MC_TEMPERATURE, /**< MC temperature*/ + RS2_OPTION_MA_TEMPERATURE, /**< MA temperature*/ + RS2_OPTION_HARDWARE_PRESET, /**< Hardware stream configuration */ + RS2_OPTION_GLOBAL_TIME_ENABLED, /**< disable global time */ + RS2_OPTION_APD_TEMPERATURE, /**< APD temperature*/ + RS2_OPTION_ENABLE_MAPPING, /**< Enable an internal map */ + RS2_OPTION_ENABLE_RELOCALIZATION, /**< Enable appearance based relocalization */ + RS2_OPTION_ENABLE_POSE_JUMPING, /**< Enable position jumping */ + RS2_OPTION_ENABLE_DYNAMIC_CALIBRATION, /**< Enable dynamic calibration */ + RS2_OPTION_DEPTH_OFFSET, /**< Offset from sensor to depth origin in millimetrers*/ + RS2_OPTION_COUNT /**< Number of enumeration values. Not a valid input: intended to be used in for-loops. */ + } rs2_option; + + // This function is being deprecated. For existing options it will return option name, but for future API additions the user should call rs2_get_option_name instead. + const char* rs2_option_to_string(rs2_option option); + + /** \brief For SR300 devices: provides optimized settings (presets) for specific types of usage. */ + typedef enum rs2_sr300_visual_preset + { + RS2_SR300_VISUAL_PRESET_SHORT_RANGE, /**< Preset for short range */ + RS2_SR300_VISUAL_PRESET_LONG_RANGE, /**< Preset for long range */ + RS2_SR300_VISUAL_PRESET_BACKGROUND_SEGMENTATION, /**< Preset for background segmentation */ + RS2_SR300_VISUAL_PRESET_GESTURE_RECOGNITION, /**< Preset for gesture recognition */ + RS2_SR300_VISUAL_PRESET_OBJECT_SCANNING, /**< Preset for object scanning */ + RS2_SR300_VISUAL_PRESET_FACE_ANALYTICS, /**< Preset for face analytics */ + RS2_SR300_VISUAL_PRESET_FACE_LOGIN, /**< Preset for face login */ + RS2_SR300_VISUAL_PRESET_GR_CURSOR, /**< Preset for GR cursor */ + RS2_SR300_VISUAL_PRESET_DEFAULT, /**< Camera default settings */ + RS2_SR300_VISUAL_PRESET_MID_RANGE, /**< Preset for mid-range */ + RS2_SR300_VISUAL_PRESET_IR_ONLY, /**< Preset for IR only */ + RS2_SR300_VISUAL_PRESET_COUNT /**< Number of enumeration values. Not a valid input: intended to be used in for-loops. */ + } rs2_sr300_visual_preset; + const char* rs2_sr300_visual_preset_to_string(rs2_sr300_visual_preset preset); + + /** \brief For RS400 devices: provides optimized settings (presets) for specific types of usage. */ + typedef enum rs2_rs400_visual_preset + { + RS2_RS400_VISUAL_PRESET_CUSTOM, + RS2_RS400_VISUAL_PRESET_DEFAULT, + RS2_RS400_VISUAL_PRESET_HAND, + RS2_RS400_VISUAL_PRESET_HIGH_ACCURACY, + RS2_RS400_VISUAL_PRESET_HIGH_DENSITY, + RS2_RS400_VISUAL_PRESET_MEDIUM_DENSITY, + RS2_RS400_VISUAL_PRESET_REMOVE_IR_PATTERN, + RS2_RS400_VISUAL_PRESET_COUNT + } rs2_rs400_visual_preset; + const char* rs2_rs400_visual_preset_to_string(rs2_rs400_visual_preset preset); + + /** + * check if an option is read-only + * \param[in] sensor the RealSense sensor + * \param[in] option option id to be checked + * \param[out] error if non-null, receives any error that occurs during this call, otherwise, errors are ignored + * \return true if option is read-only + */ + int rs2_is_option_read_only(const rs2_options* options, rs2_option option, rs2_error** error); + + /** + * read option value from the sensor + * \param[in] sensor the RealSense sensor + * \param[in] option option id to be queried + * \param[out] error if non-null, receives any error that occurs during this call, otherwise, errors are ignored + * \return value of the option + */ + float rs2_get_option(const rs2_options* options, rs2_option option, rs2_error** error); + + /** + * write new value to sensor option + * \param[in] sensor the RealSense sensor + * \param[in] option option id to be queried + * \param[in] value new value for the option + * \param[out] error if non-null, receives any error that occurs during this call, otherwise, errors are ignored + */ + void rs2_set_option(const rs2_options* options, rs2_option option, float value, rs2_error** error); + + /** + * get the list of supported options of options container + * \param[in] options the options container + * \param[out] error if non-null, receives any error that occurs during this call, otherwise, errors are ignored + */ + rs2_options_list* rs2_get_options_list(const rs2_options* options, rs2_error** error); + + /** + * get the size of options list + * \param[in] options the option list + * \param[out] error if non-null, receives any error that occurs during this call, otherwise, errors are ignored + */ + int rs2_get_options_list_size(const rs2_options_list* options, rs2_error** error); + + /** + * get option name + * \param[in] options options object + * \param[in] option option id to be checked + * \param[out] error if non-null, receives any error that occurs during this call, otherwise, errors are ignored + * \return human-readable option name + */ + const char* rs2_get_option_name(const rs2_options* options, rs2_option option, rs2_error** error); + + /** + * get the specific option from options list + * \param[in] i the index of the option + * \param[out] error if non-null, receives any error that occurs during this call, otherwise, errors are ignored + */ + rs2_option rs2_get_option_from_list(const rs2_options_list* options, int i, rs2_error** error); + + /** + * Deletes options list + * \param[in] list list to delete + */ + void rs2_delete_options_list(rs2_options_list* list); + + /** + * check if particular option is supported by a subdevice + * \param[in] sensor the RealSense sensor + * \param[in] option option id to be checked + * \param[out] error if non-null, receives any error that occurs during this call, otherwise, errors are ignored + * \return true if option is supported + */ + int rs2_supports_option(const rs2_options* options, rs2_option option, rs2_error** error); + + /** + * retrieve the available range of values of a supported option + * \param[in] sensor the RealSense device + * \param[in] option the option whose range should be queried + * \param[out] min the minimum value which will be accepted for this option + * \param[out] max the maximum value which will be accepted for this option + * \param[out] step the granularity of options which accept discrete values, or zero if the option accepts continuous values + * \param[out] def the default value of the option + * \param[out] error if non-null, receives any error that occurs during this call, otherwise, errors are ignored + */ + void rs2_get_option_range(const rs2_options* sensor, rs2_option option, float* min, float* max, float* step, float* def, rs2_error** error); + + /** + * get option description + * \param[in] sensor the RealSense sensor + * \param[in] option option id to be checked + * \param[out] error if non-null, receives any error that occurs during this call, otherwise, errors are ignored + * \return human-readable option description + */ + const char* rs2_get_option_description(const rs2_options* options, rs2_option option, rs2_error ** error); + + /** + * get option value description (in case specific option value hold special meaning) + * \param[in] device the RealSense device + * \param[in] option option id to be checked + * \param[in] value value of the option + * \param[out] error if non-null, receives any error that occurs during this call, otherwise, errors are ignored + * \return human-readable description of a specific value of an option or null if no special meaning + */ + const char* rs2_get_option_value_description(const rs2_options* options, rs2_option option, float value, rs2_error ** error); #ifdef __cplusplus } diff --git a/libs/realsense2/include/librealsense2/h/rs_pipeline.h b/libs/realsense2/include/librealsense2/h/rs_pipeline.h index f617236..1018c77 100755 --- a/libs/realsense2/include/librealsense2/h/rs_pipeline.h +++ b/libs/realsense2/include/librealsense2/h/rs_pipeline.h @@ -16,6 +16,7 @@ extern "C" { #include "rs_types.h" #include "rs_sensor.h" +#include "rs_config.h" /** * Create a pipeline instance @@ -111,7 +112,6 @@ extern "C" { */ rs2_pipeline_profile* rs2_pipeline_start(rs2_pipeline* pipe, rs2_error ** error); - /** * Start the pipeline streaming according to the configuraion. * The pipeline streaming loop captures samples from the device, and delivers them to the attached computer vision modules @@ -132,6 +132,72 @@ extern "C" { */ rs2_pipeline_profile* rs2_pipeline_start_with_config(rs2_pipeline* pipe, rs2_config* config, rs2_error ** error); + /** + * Start the pipeline streaming with its default configuration. + * The pipeline captures samples from the device, and delivers them to the through the provided frame callback. + * Starting the pipeline is possible only when it is not started. If the pipeline was started, an exception is raised. + * When starting the pipeline with a callback both \c wait_for_frames() or \c poll_for_frames() will throw exception. + * + * \param[in] pipe A pointer to an instance of the pipeline + * \param[in] on_frame function pointer to register as per-frame callback + * \param[in] user auxiliary data the user wishes to receive together with every frame callback + * \param[out] error If non-null, receives any error that occurs during this call, otherwise, errors are ignored + * \return The actual pipeline device and streams profile, which was successfully configured to the streaming device. + */ + rs2_pipeline_profile* rs2_pipeline_start_with_callback(rs2_pipeline* pipe, rs2_frame_callback_ptr on_frame, void* user, rs2_error ** error); + + /** + * Start the pipeline streaming with its default configuration. + * The pipeline captures samples from the device, and delivers them to the through the provided frame callback. + * Starting the pipeline is possible only when it is not started. If the pipeline was started, an exception is raised. + * When starting the pipeline with a callback both \c wait_for_frames() or \c poll_for_frames() will throw exception. + * + * \param[in] pipe A pointer to an instance of the pipeline + * \param[in] callback callback object created from c++ application. ownership over the callback object is moved into the relevant streaming lock + * \param[out] error If non-null, receives any error that occurs during this call, otherwise, errors are ignored + * \return The actual pipeline device and streams profile, which was successfully configured to the streaming device. + */ + rs2_pipeline_profile* rs2_pipeline_start_with_callback_cpp(rs2_pipeline* pipe, rs2_frame_callback* callback, rs2_error ** error); + + /** + * Start the pipeline streaming according to the configuraion. + * The pipeline captures samples from the device, and delivers them to the through the provided frame callback. + * Starting the pipeline is possible only when it is not started. If the pipeline was started, an exception is raised. + * When starting the pipeline with a callback both \c wait_for_frames() or \c poll_for_frames() will throw exception. + * The pipeline selects and activates the device upon start, according to configuration or a default configuration. + * When the rs2::config is provided to the method, the pipeline tries to activate the config \c resolve() result. If the application + * requests are conflicting with pipeline computer vision modules or no matching device is available on the platform, the method fails. + * Available configurations and devices may change between config \c resolve() call and pipeline start, in case devices are connected + * or disconnected, or another application acquires ownership of a device. + * + * \param[in] pipe A pointer to an instance of the pipeline + * \param[in] config A rs2::config with requested filters on the pipeline configuration. By default no filters are applied. + * \param[in] on_frame function pointer to register as per-frame callback + * \param[in] user auxiliary data the user wishes to receive together with every frame callback + * \param[out] error If non-null, receives any error that occurs during this call, otherwise, errors are ignored + * \return The actual pipeline device and streams profile, which was successfully configured to the streaming device. + */ + rs2_pipeline_profile* rs2_pipeline_start_with_config_and_callback(rs2_pipeline* pipe, rs2_config* config, rs2_frame_callback_ptr on_frame, void* user, rs2_error ** error); + + /** + * Start the pipeline streaming according to the configuraion. + * The pipeline captures samples from the device, and delivers them to the through the provided frame callback. + * Starting the pipeline is possible only when it is not started. If the pipeline was started, an exception is raised. + * When starting the pipeline with a callback both \c wait_for_frames() or \c poll_for_frames() will throw exception. + * The pipeline selects and activates the device upon start, according to configuration or a default configuration. + * When the rs2::config is provided to the method, the pipeline tries to activate the config \c resolve() result. If the application + * requests are conflicting with pipeline computer vision modules or no matching device is available on the platform, the method fails. + * Available configurations and devices may change between config \c resolve() call and pipeline start, in case devices are connected + * or disconnected, or another application acquires ownership of a device. + * + * \param[in] pipe A pointer to an instance of the pipeline + * \param[in] config A rs2::config with requested filters on the pipeline configuration. By default no filters are applied. + * \param[in] callback callback object created from c++ application. ownership over the callback object is moved into the relevant streaming lock + * \param[out] error If non-null, receives any error that occurs during this call, otherwise, errors are ignored + * \return The actual pipeline device and streams profile, which was successfully configured to the streaming device. + */ + rs2_pipeline_profile* rs2_pipeline_start_with_config_and_callback_cpp(rs2_pipeline* pipe, rs2_config* config, rs2_frame_callback* callback, rs2_error ** error); + /** * Return the active device and streams profiles, used by the pipeline. * The pipeline streams profiles are selected during \c start(). The method returns a valid result only when the pipeline is active - @@ -175,181 +241,6 @@ extern "C" { */ void rs2_delete_pipeline_profile(rs2_pipeline_profile* profile); - /** - * Create a config instance - * The config allows pipeline users to request filters for the pipeline streams and device selection and configuration. - * This is an optional step in pipeline creation, as the pipeline resolves its streaming device internally. - * Config provides its users a way to set the filters and test if there is no conflict with the pipeline requirements - * from the device. It also allows the user to find a matching device for the config filters and the pipeline, in order to - * select a device explicitly, and modify its controls before streaming starts. - * - * \param[out] error if non-null, receives any error that occurs during this call, otherwise, errors are ignored - * \return rs2_config* A pointer to a new config instance - */ - rs2_config* rs2_create_config(rs2_error** error); - - /** - * Deletes an instance of a config - * - * \param[in] config A pointer to an instance of a config - */ - void rs2_delete_config(rs2_config* config); - - /** - * Enable a device stream explicitly, with selected stream parameters. - * The method allows the application to request a stream with specific configuration. If no stream is explicitly enabled, the pipeline - * configures the device and its streams according to the attached computer vision modules and processing blocks requirements, or - * default configuration for the first available device. - * The application can configure any of the input stream parameters according to its requirement, or set to 0 for don't care value. - * The config accumulates the application calls for enable configuration methods, until the configuration is applied. Multiple enable - * stream calls for the same stream with conflicting parameters override each other, and the last call is maintained. - * Upon calling \c resolve(), the config checks for conflicts between the application configuration requests and the attached computer - * vision modules and processing blocks requirements, and fails if conflicts are found. Before \c resolve() is called, no conflict - * check is done. - * - * \param[in] config A pointer to an instance of a config - * \param[in] stream Stream type to be enabled - * \param[in] index Stream index, used for multiple streams of the same type. -1 indicates any. - * \param[in] width Stream image width - for images streams. 0 indicates any. - * \param[in] height Stream image height - for images streams. 0 indicates any. - * \param[in] format Stream data format - pixel format for images streams, of data type for other streams. RS2_FORMAT_ANY indicates any. - * \param[in] framerate Stream frames per second. 0 indicates any. - * \param[out] error if non-null, receives any error that occurs during this call, otherwise, errors are ignored - */ - void rs2_config_enable_stream(rs2_config* config, - rs2_stream stream, - int index, - int width, - int height, - rs2_format format, - int framerate, - rs2_error** error); - - /** - * Enable all device streams explicitly. - * The conditions and behavior of this method are similar to those of \c enable_stream(). - * This filter enables all raw streams of the selected device. The device is either selected explicitly by the application, - * or by the pipeline requirements or default. The list of streams is device dependent. - * - * \param[in] config A pointer to an instance of a config - * \param[out] error if non-null, receives any error that occurs during this call, otherwise, errors are ignored - */ - void rs2_config_enable_all_stream(rs2_config* config, rs2_error ** error); - - /** - * Select a specific device explicitly by its serial number, to be used by the pipeline. - * The conditions and behavior of this method are similar to those of \c enable_stream(). - * This method is required if the application needs to set device or sensor settings prior to pipeline streaming, to enforce - * the pipeline to use the configured device. - * - * \param[in] config A pointer to an instance of a config - * \param[in] serial device serial number, as returned by RS2_CAMERA_INFO_SERIAL_NUMBER - * \param[out] error if non-null, receives any error that occurs during this call, otherwise, errors are ignored - */ - void rs2_config_enable_device(rs2_config* config, const char* serial, rs2_error ** error); - - /** - * Select a recorded device from a file, to be used by the pipeline through playback. - * The device available streams are as recorded to the file, and \c resolve() considers only this device and configuration - * as available. - * This request cannot be used if enable_record_to_file() is called for the current config, and vise versa - * By default, playback is repeated once the file ends. To control this, see 'rs2_config_enable_device_from_file_repeat_option'. - * - * \param[in] config A pointer to an instance of a config - * \param[in] file The playback file of the device - * \param[out] error if non-null, receives any error that occurs during this call, otherwise, errors are ignored - */ - void rs2_config_enable_device_from_file(rs2_config* config, const char* file, rs2_error ** error); - - /** - * Select a recorded device from a file, to be used by the pipeline through playback. - * The device available streams are as recorded to the file, and \c resolve() considers only this device and configuration - * as available. - * This request cannot be used if enable_record_to_file() is called for the current config, and vise versa - * - * \param[in] config A pointer to an instance of a config - * \param[in] file The playback file of the device - * \param[in] repeat_playback if true, when file ends the playback starts again, in an infinite loop; - if false, when file ends playback does not start again, and should by stopped manually by the user. - * \param[out] error if non-null, receives any error that occurs during this call, otherwise, errors are ignored - */ - void rs2_config_enable_device_from_file_repeat_option(rs2_config* config, const char* file, int repeat_playback, rs2_error ** error); - - /** - * Requires that the resolved device would be recorded to file - * This request cannot be used if enable_device_from_file() is called for the current config, and vise versa - * - * \param[in] config A pointer to an instance of a config - * \param[in] file The desired file for the output record - * \param[out] error if non-null, receives any error that occurs during this call, otherwise, errors are ignored - */ - void rs2_config_enable_record_to_file(rs2_config* config, const char* file, rs2_error ** error); - - - /** - * Disable a device stream explicitly, to remove any requests on this stream type. - * The stream can still be enabled due to pipeline computer vision module request. This call removes any filter on the - * stream configuration. - * - * \param[in] config A pointer to an instance of a config - * \param[in] stream Stream type, for which the filters are cleared - * \param[out] error if non-null, receives any error that occurs during this call, otherwise, errors are ignored - */ - void rs2_config_disable_stream(rs2_config* config, rs2_stream stream, rs2_error ** error); - - /** - * Disable a device stream explicitly, to remove any requests on this stream profile. - * The stream can still be enabled due to pipeline computer vision module request. This call removes any filter on the - * stream configuration. - * - * \param[in] config A pointer to an instance of a config - * \param[in] stream Stream type, for which the filters are cleared - * \param[in] index Stream index, for which the filters are cleared - * \param[out] error if non-null, receives any error that occurs during this call, otherwise, errors are ignored - */ - void rs2_config_disable_indexed_stream(rs2_config* config, rs2_stream stream, int index, rs2_error ** error); - - /** - * Disable all device stream explicitly, to remove any requests on the streams profiles. - * The streams can still be enabled due to pipeline computer vision module request. This call removes any filter on the - * streams configuration. - * - * \param[in] config A pointer to an instance of a config - * \param[out] error if non-null, receives any error that occurs during this call, otherwise, errors are ignored - */ - void rs2_config_disable_all_streams(rs2_config* config, rs2_error ** error); - - /** - * Resolve the configuration filters, to find a matching device and streams profiles. - * The method resolves the user configuration filters for the device and streams, and combines them with the requirements of - * the computer vision modules and processing blocks attached to the pipeline. If there are no conflicts of requests, it looks - * for an available device, which can satisfy all requests, and selects the first matching streams configuration. In the absence - * of any request, the rs2::config selects the first available device and the first color and depth streams configuration. - * The pipeline profile selection during \c start() follows the same method. Thus, the selected profile is the same, if no - * change occurs to the available devices occurs. - * Resolving the pipeline configuration provides the application access to the pipeline selected device for advanced control. - * The returned configuration is not applied to the device, so the application doesn't own the device sensors. However, the - * application can call \c enable_device(), to enforce the device returned by this method is selected by pipeline \c start(), - * and configure the device and sensors options or extensions before streaming starts. - * - * \param[in] config A pointer to an instance of a config - * \param[in] pipe The pipeline for which the selected filters are applied - * \param[out] error if non-null, receives any error that occurs during this call, otherwise, errors are ignored - * \return A matching device and streams profile, which satisfies the filters and pipeline requests. - */ - rs2_pipeline_profile* rs2_config_resolve(rs2_config* config, rs2_pipeline* pipe, rs2_error ** error); - - /** - * Check if the config can resolve the configuration filters, to find a matching device and streams profiles. - * The resolution conditions are as described in \c resolve(). - * - * \param[in] config A pointer to an instance of a config - * \param[in] pipe The pipeline for which the selected filters are applied - * \param[out] error if non-null, receives any error that occurs during this call, otherwise, errors are ignored - * \return True if a valid profile selection exists, false if no selection can be found under the config filters and the available devices. - */ - int rs2_config_can_resolve(rs2_config* config, rs2_pipeline* pipe, rs2_error ** error); - #ifdef __cplusplus } #endif diff --git a/libs/realsense2/include/librealsense2/h/rs_processing.h b/libs/realsense2/include/librealsense2/h/rs_processing.h index 7836470..4e78793 100755 --- a/libs/realsense2/include/librealsense2/h/rs_processing.h +++ b/libs/realsense2/include/librealsense2/h/rs_processing.h @@ -16,6 +16,7 @@ extern "C" { #include "rs_types.h" #include "rs_sensor.h" +#include "rs_option.h" /** * Creates Depth-Colorizer processing block that can be used to quickly visualize the depth data @@ -41,6 +42,32 @@ rs2_processing_block* rs2_create_sync_processing_block(rs2_error** error); */ rs2_processing_block* rs2_create_pointcloud(rs2_error** error); +/** +* Creates YUY decoder processing block. This block accepts raw YUY frames and outputs frames of other formats. +* YUY is a common video format used by a variety of web-cams. It benefits from packing pixels into 2 bytes per pixel +* without signficant quality drop. YUY representation can be converted back to more usable RGB form, +* but this requires somewhat costly conversion. +* The SDK will automatically try to use SSE2 and AVX instructions and CUDA where available to get +* best performance. Other implementations (using GLSL, OpenCL, Neon and NCS) should follow. +* \param[out] error if non-null, receives any error that occurs during this call, otherwise, errors are ignored +*/ +rs2_processing_block* rs2_create_yuy_decoder(rs2_error** error); + +/** +* Creates depth thresholding processing block +* By controlling min and max options on the block, one could filter out depth values +* that are either too large or too small, as a software post-processing step +* \param[out] error if non-null, receives any error that occurs during this call, otherwise, errors are ignored +*/ +rs2_processing_block* rs2_create_threshold(rs2_error** error); + +/** +* Creates depth units transformation processing block +* All of the pixels are transformed from depth units into meters. +* \param[out] error if non-null, receives any error that occurs during this call, otherwise, errors are ignored +*/ +rs2_processing_block* rs2_create_units_transform(rs2_error** error); + /** * This method creates new custom processing block. This lets the users pass frames between module boundaries for processing * This is an infrastructure function aimed at middleware developers, and also used by provided blocks such as sync, colorizer, etc.. @@ -60,6 +87,20 @@ rs2_processing_block* rs2_create_processing_block(rs2_frame_processor_callback* */ rs2_processing_block* rs2_create_processing_block_fptr(rs2_frame_processor_callback_ptr proc, void * context, rs2_error** error); +/** +* This method adds a custom option to a custom processing block. This is a simple float that can be accessed via rs2_set_option and rs2_get_option +* This is an infrastructure function aimed at middleware developers, and also used by provided blocks such as save_to_ply, etc.. +* \param[in] block Processing block +* \param[in] option_id an int ID for referencing the option +* \param[in] min the minimum value which will be accepted for this option +* \param[in] max the maximum value which will be accepted for this option +* \param[in] step the granularity of options which accept discrete values, or zero if the option accepts continuous values +* \param[in] def the default value of the option. This will be the initial value. +* \param[out] error if non-null, receives any error that occurs during this call, otherwise, errors are ignored +* \return true if adding the option succeeds. false if it fails e.g. an option with this id is already registered +*/ +int rs2_processing_block_register_simple_option(rs2_processing_block* block, rs2_option option_id, float min, float max, float step, float def, rs2_error** error); + /** * This method is used to direct the output from the processing block to some callback or sink object * \param[in] block Processing block @@ -151,6 +192,7 @@ void rs2_enqueue_frame(rs2_frame* frame, void* queue); /** * Creates Align processing block. +* \param[in] align_to stream type to be used as the target of frameset alignment * \param[out] error if non-null, receives any error that occurs during this call, otherwise, errors are ignored */ rs2_processing_block* rs2_create_align(rs2_stream align_to, rs2_error** error); @@ -187,6 +229,47 @@ rs2_processing_block* rs2_create_disparity_transform_block(unsigned char transfo */ rs2_processing_block* rs2_create_hole_filling_filter_block(rs2_error** error); +/** +* Creates a rates printer block. The printer prints the actual FPS of the invoked frame stream. +* The block ignores reapiting frames and calculats the FPS only if the frame number of the relevant frame was changed. +* \param[out] error if non-null, receives any error that occurs during this call, otherwise, errors are ignored +*/ +rs2_processing_block* rs2_create_rates_printer_block(rs2_error** error); + +/** +* Creates Depth post-processing zero order fix block. The filter invalidates pixels that has a wrong value due to zero order effect +* \param[out] error If non-null, receives any error that occurs during this call, otherwise, errors are ignored +* \return zero order fix processing block +*/ +rs2_processing_block* rs2_create_zero_order_invalidation_block(rs2_error** error); + +/** +* Retrieve processing block specific information, like name. +* \param[in] block The processing block +* \param[in] info processing block info type to retrieve +* \param[out] error If non-null, receives any error that occurs during this call, otherwise, errors are ignored +* \return The requested processing block info string, in a format specific to the device model +*/ +const char* rs2_get_processing_block_info(const rs2_processing_block* block, rs2_camera_info info, rs2_error** error); + +/** +* Check if a processing block supports a specific info type. +* \param[in] block The processing block to check +* \param[in] info The parameter to check for support +* \param[out] error If non-null, receives any error that occurs during this call, otherwise, errors are ignored +* \return True if the parameter both exist and well-defined for the specific device +*/ +int rs2_supports_processing_block_info(const rs2_processing_block* block, rs2_camera_info info, rs2_error** error); + +/** + * Test if the given processing block can be extended to the requested extension + * \param[in] block processing block + * \param[in] extension The extension to which the sensor should be tested if it is extendable + * \param[out] error if non-null, receives any error that occurs during this call, otherwise, errors are ignored + * \return non-zero value iff the processing block can be extended to the given extension + */ +int rs2_is_processing_block_extendable_to(const rs2_processing_block* block, rs2_extension extension_type, rs2_error** error); + #ifdef __cplusplus } #endif diff --git a/libs/realsense2/include/librealsense2/h/rs_record_playback.h b/libs/realsense2/include/librealsense2/h/rs_record_playback.h index cddec6d..a540e6d 100755 --- a/libs/realsense2/include/librealsense2/h/rs_record_playback.h +++ b/libs/realsense2/include/librealsense2/h/rs_record_playback.h @@ -24,6 +24,7 @@ typedef enum rs2_playback_status RS2_PLAYBACK_STATUS_STOPPED, /**< All sensors were stopped, or playback has ended (all data was read). This is the initial playback status*/ RS2_PLAYBACK_STATUS_COUNT } rs2_playback_status; + const char* rs2_playback_status_to_string(rs2_playback_status status); typedef void (*rs2_playback_status_changed_callback_ptr)(rs2_playback_status); @@ -37,6 +38,16 @@ typedef void (*rs2_playback_status_changed_callback_ptr)(rs2_playback_status); */ rs2_device* rs2_create_record_device(const rs2_device* device, const char* file, rs2_error** error); +/** +* Creates a recording device to record the given device and save it to the given file +* \param[in] device The device to record +* \param[in] file The desired path to which the recorder should save the data +* \param[in] compression_enabled Indicates if compression is enabled, 0 means false, otherwise true +* \param[out] error If non-null, receives any error that occurs during this call, otherwise, errors are ignored +* \return A pointer to a device that records its data to file, or null in case of failure +*/ +rs2_device* rs2_create_record_device_ex(const rs2_device* device, const char* file, int compression_enabled, rs2_error** error); + /** * Pause the recording device without stopping the actual device from streaming. * Pausing will cause the device to stop writing new data to the file, in particular, frames and changes to extensions diff --git a/libs/realsense2/include/librealsense2/h/rs_sensor.h b/libs/realsense2/include/librealsense2/h/rs_sensor.h index 9120275..4d22945 100755 --- a/libs/realsense2/include/librealsense2/h/rs_sensor.h +++ b/libs/realsense2/include/librealsense2/h/rs_sensor.h @@ -30,11 +30,14 @@ typedef enum rs2_camera_info { RS2_CAMERA_INFO_PRODUCT_ID , /**< Product ID as reported in the USB descriptor */ RS2_CAMERA_INFO_CAMERA_LOCKED , /**< True iff EEPROM is locked */ RS2_CAMERA_INFO_USB_TYPE_DESCRIPTOR , /**< Designated USB specification: USB2/USB3 */ + RS2_CAMERA_INFO_PRODUCT_LINE , /**< Device product line D400/SR300/L500/T200 */ + RS2_CAMERA_INFO_ASIC_SERIAL_NUMBER , /**< ASIC serial number */ + RS2_CAMERA_INFO_FIRMWARE_UPDATE_ID , /**< Firmware update ID */ RS2_CAMERA_INFO_COUNT /**< Number of enumeration values. Not a valid input: intended to be used in for-loops. */ } rs2_camera_info; const char* rs2_camera_info_to_string(rs2_camera_info info); -/** \brief Streams are different types of data provided by RealSense devices */ +/** \brief Streams are different types of data provided by RealSense devices. */ typedef enum rs2_stream { RS2_STREAM_ANY, @@ -46,17 +49,17 @@ typedef enum rs2_stream RS2_STREAM_ACCEL , /**< Native stream of accelerometer motion data produced by RealSense device */ RS2_STREAM_GPIO , /**< Signals from external device connected through GPIO */ RS2_STREAM_POSE , /**< 6 Degrees of Freedom pose data, calculated by RealSense device */ - RS2_STREAM_CONFIDENCE, + RS2_STREAM_CONFIDENCE , /**< 4 bit per-pixel depth confidence level */ RS2_STREAM_COUNT } rs2_stream; const char* rs2_stream_to_string(rs2_stream stream); -/** \brief Format identifies how binary data is encoded within a frame */ +/** \brief A stream's format identifies how binary data is encoded within a frame. */ typedef enum rs2_format { RS2_FORMAT_ANY , /**< When passed to enable stream, librealsense will try to provide best suited format */ RS2_FORMAT_Z16 , /**< 16-bit linear depth values. The depth is meters is equal to depth scale * pixel value. */ - RS2_FORMAT_DISPARITY16 , /**< 16-bit linear disparity values. The depth in meters is equal to depth scale / pixel value. */ + RS2_FORMAT_DISPARITY16 , /**< 16-bit float-point disparity values. Depth->Disparity conversion : Disparity = Baseline*FocalLength/Depth. */ RS2_FORMAT_XYZ32F , /**< 32-bit floating point 3D coordinates. */ RS2_FORMAT_YUYV , /**< 32-bit y0, u, y1, v data for every two pixels. Similar to YUV422 but packed in a different order - https://en.wikipedia.org/wiki/YUV */ RS2_FORMAT_RGB8 , /**< 8-bit red, green and blue channels */ @@ -65,7 +68,7 @@ typedef enum rs2_format RS2_FORMAT_BGRA8 , /**< 8-bit blue, green, and red channels + constant alpha channel equal to FF */ RS2_FORMAT_Y8 , /**< 8-bit per-pixel grayscale image */ RS2_FORMAT_Y16 , /**< 16-bit per-pixel grayscale image */ - RS2_FORMAT_RAW10 , /**< Four 10-bit luminance values encoded into a 5-byte macropixel */ + RS2_FORMAT_RAW10 , /**< Four 10 bits per pixel luminance values packed into a 5-byte macropixel */ RS2_FORMAT_RAW16 , /**< 16-bit raw image */ RS2_FORMAT_RAW8 , /**< 8-bit raw image */ RS2_FORMAT_UYVY , /**< Similar to the standard YUYV pixel format, but packed in a different order */ @@ -74,11 +77,14 @@ typedef enum rs2_format RS2_FORMAT_GPIO_RAW , /**< Raw data from the external sensors hooked to one of the GPIO's */ RS2_FORMAT_6DOF , /**< Pose data packed as floats array, containing translation vector, rotation quaternion and prediction velocities and accelerations vectors */ RS2_FORMAT_DISPARITY32 , /**< 32-bit float-point disparity values. Depth->Disparity conversion : Disparity = Baseline*FocalLength/Depth */ + RS2_FORMAT_Y10BPACK , /**< 16-bit per-pixel grayscale image unpacked from 10 bits per pixel packed ([8:8:8:8:2222]) grey-scale image. The data is unpacked to LSB and padded with 6 zero bits */ + RS2_FORMAT_DISTANCE , /**< 32-bit float-point depth distance value. */ + RS2_FORMAT_MJPEG , /**< Bitstream encoding for video in which an image of each frame is encoded as JPEG-DIB */ RS2_FORMAT_COUNT /**< Number of enumeration values. Not a valid input: intended to be used in for-loops. */ } rs2_format; const char* rs2_format_to_string(rs2_format format); -/** \brief Cross-stream extrinsics: encode the topology describing how the different devices are connected. */ +/** \brief Cross-stream extrinsics: encodes the topology describing how the different devices are oriented. */ typedef struct rs2_extrinsics { float rotation[9]; /**< Column-major 3x3 rotation matrix */ @@ -155,12 +161,19 @@ int rs2_is_sensor_extendable_to(const rs2_sensor* sensor, rs2_extension extensio float rs2_get_depth_scale(rs2_sensor* sensor, rs2_error** error); /** -* Retrieve the stereoscopic baseline value. Applicable to stereo-based depth modules +* Retrieve the stereoscopic baseline value from frame. Applicable to stereo-based depth modules * \param[out] float Stereoscopic baseline in millimeters * \param[out] error if non-null, receives any error that occurs during this call, otherwise, errors are ignored */ float rs2_depth_stereo_frame_get_baseline(const rs2_frame* frame_ref, rs2_error** error); +/** +* Retrieve the stereoscopic baseline value from sensor. Applicable to stereo-based depth modules +* \param[out] float Stereoscopic baseline in millimeters +* \param[out] error if non-null, receives any error that occurs during this call, otherwise, errors are ignored +*/ +float rs2_get_stereo_baseline(rs2_sensor* sensor, rs2_error** error); + /** * \brief sets the active region of interest to be used by auto-exposure algorithm * \param[in] sensor the RealSense sensor @@ -345,6 +358,21 @@ void rs2_set_stream_profile_data(rs2_stream_profile* mode, rs2_stream stream, in */ rs2_stream_profile* rs2_clone_stream_profile(const rs2_stream_profile* mode, rs2_stream stream, int index, rs2_format format, rs2_error** error); +/** +* Creates a copy of stream profile, assigning new values to some of the fields +* \param[in] mode input stream profile +* \param[in] stream stream type for the profile +* \param[in] format binary data format of the profile +* \param[in] width new width for the profile +* \param[in] height new height for the profile +* \param[in] intr new intrinsics for the profile +* \param[in] index stream index the profile in case there are multiple streams of the same type +* \param[out] error if non-null, receives any error that occurs during this call, otherwise, errors are ignored +* \return new stream profile, must be deleted by rs2_delete_stream_profile +*/ +rs2_stream_profile* rs2_clone_video_stream_profile(const rs2_stream_profile* mode, rs2_stream stream, int index, rs2_format format, int width, int height, const rs2_intrinsics* intr, rs2_error** error); + + /** * Delete stream profile allocated by rs2_clone_stream_profile * Should not be called on stream profiles returned by the device @@ -429,8 +457,126 @@ void rs2_register_extrinsics(const rs2_stream_profile* from, */ void rs2_get_video_stream_intrinsics(const rs2_stream_profile* mode, rs2_intrinsics* intrinsics, rs2_error** error); +/** + * Returns the list of recommended processing blocks for a specific sensor. + * Order and configuration of the blocks are decided by the sensor + * \param[in] sensor input sensor + * \param[out] error if non-null, receives any error that occurs during this call, otherwise, errors are ignored + * \return list of supported sensor recommended processing blocks +*/ +rs2_processing_block_list* rs2_get_recommended_processing_blocks(rs2_sensor* sensor, rs2_error** error); + +/** +* Returns specific processing blocks from processing blocks list +* \param[in] list the processing blocks list +* \param[in] index the requested processing block +* \param[out] error if non-null, receives any error that occurs during this call, otherwise, errors are ignored +* \return processing block +*/ +rs2_processing_block* rs2_get_processing_block(const rs2_processing_block_list* list, int index, rs2_error** error); + +/** +* Returns the processing blocks list size +* \param[in] list the processing blocks list +* \param[out] error if non-null, receives any error that occurs during this call, otherwise, errors are ignored +* \return the processing block list size +*/ +int rs2_get_recommended_processing_blocks_count(const rs2_processing_block_list* list, rs2_error** error); + +/** +* Deletes processing blocks list +* \param[in] list list to delete +*/ +void rs2_delete_recommended_processing_blocks(rs2_processing_block_list* list); + +/** +* Imports a localization map from file to tm2 tracking device +* \param[in] sensor TM2 position-tracking sensor +* \param[in] lmap_blob Localization map raw buffer, serialized +* \param[in] blob_size The buffer's size in bytes +* \param[out] error If non-null, receives any error that occurs during this call, otherwise, errors are ignored +* \return Non-zero if succeeded, otherwise 0 +*/ +int rs2_import_localization_map(const rs2_sensor* sensor, const unsigned char* lmap_blob, unsigned int blob_size, rs2_error** error); + +/** +* Extract and store the localization map of tm2 tracking device to file +* \param[in] sensor TM2 position-tracking sensor +* \param[in] lmap_fname The file name of the localization map +* \param[out] error If non-null, receives any error that occurs during this call, otherwise, errors are ignored +* \return Device's response in a rs2_raw_data_buffer, which should be released by rs2_delete_raw_data +*/ +//void rs2_export_localization_map(const rs2_sensor* sensor, const char* lmap_fname, rs2_error** error); +const rs2_raw_data_buffer* rs2_export_localization_map(const rs2_sensor* sensor, rs2_error** error); + +/** +* Create a named location tag +* \param[in] sensor T2xx position-tracking sensor +* \param[in] guid Null-terminated string of up to 127 characters +* \param[in] pos Position in meters, relative to the current tracking session +* \param[in] orient Quaternion orientation, expressed the the coordinate system of the current tracking session +* \param[out] error If non-null, receives any error that occurs during this call, otherwise, errors are ignored +* \return Non-zero if succeeded, otherwise 0 +*/ +int rs2_set_static_node(const rs2_sensor* sensor, const char* guid, const rs2_vector pos, const rs2_quaternion orient, rs2_error** error); + +/** +* Create a named location tag +* \param[in] sensor T2xx position-tracking sensor +* \param[in] guid Null-terminated string of up to 127 characters +* \param[out] pos Position in meters of the tagged (stored) location +* \param[out] orient Quaternion orientation of the tagged (stored) location +* \param[out] error If non-null, receives any error that occurs during this call, otherwise, errors are ignored +* \return Non-zero if succeeded, otherwise 0 +*/ +int rs2_get_static_node(const rs2_sensor* sensor, const char* guid, rs2_vector *pos, rs2_quaternion *orient, rs2_error** error); + +/** Load Wheel odometer settings from host to device +* \param[in] odometry_config_buf odometer configuration/calibration blob serialized from jsom file +* \return true on success +*/ +int rs2_load_wheel_odometry_config(const rs2_sensor* sensor, const unsigned char* odometry_config_buf, unsigned int blob_size, rs2_error** error); + +/** Send wheel odometry data for each individual sensor (wheel) +* \param[in] wo_sensor_id - Zero-based index of (wheel) sensor with the same type within device +* \param[in] frame_num - Monotonocally increasing frame number, managed per sensor. +* \param[in] translational_velocity - Translational velocity of the wheel sensor [meter/sec] +* \return true on success +*/ +int rs2_send_wheel_odometry(const rs2_sensor* sensor, char wo_sensor_id, unsigned int frame_num, + const rs2_vector translational_velocity, rs2_error** error); + +/** +* Set intrinsics of a given sensor +* \param[in] sensor The RealSense device +* \param[in] profile Target stream profile +* \param[in] intrinsics Intrinsics value to be written to the device +* \param[out] error If non-null, receives any error that occurs during this call, otherwise, errors are ignored +*/ +void rs2_set_intrinsics(const rs2_sensor* sensor, const rs2_stream_profile* profile , const rs2_intrinsics* intrinsics, rs2_error** error); + +/** + * Set extrinsics between two sensors + * \param[in] from_sensor Origin sensor + * \param[in] from_profile Origin profile + * \param[in] to_sensor Target sensor + * \param[in] to_profile Target profile + * \param[out] extrinsics Extrinsics from origin to target + * \param[out] error If non-null, receives any error that occurs during this call, otherwise, errors are ignored + */ +void rs2_set_extrinsics(const rs2_sensor* from_sensor, const rs2_stream_profile* from_profile, rs2_sensor* to_sensor, const rs2_stream_profile* to_profile, const rs2_extrinsics* extrinsics, rs2_error** error); + +/** +* Set motion device intrinsics +* \param[in] sensor Motion sensor +* \param[in] profile Motion stream profile +* \param[out] intrinsics Pointer to the struct to store the data in +* \param[out] error If non-null, receives any error that occurs during this call, otherwise, errors are ignored +*/ +void rs2_set_motion_device_intrinsics(const rs2_sensor* sensor, const rs2_stream_profile* profile, const rs2_motion_device_intrinsic* intrinsics, rs2_error** error); + #ifdef __cplusplus } #endif -#endif +#endif // LIBREALSENSE_RS2_SENSOR_H diff --git a/libs/realsense2/include/librealsense2/h/rs_types.h b/libs/realsense2/include/librealsense2/h/rs_types.h index fa088d4..97357d6 100755 --- a/libs/realsense2/include/librealsense2/h/rs_types.h +++ b/libs/realsense2/include/librealsense2/h/rs_types.h @@ -13,7 +13,7 @@ extern "C" { #endif -/** \brief Category of the librealsense notifications */ +/** \brief Category of the librealsense notification. */ typedef enum rs2_notification_category{ RS2_NOTIFICATION_CATEGORY_FRAMES_TIMEOUT, /**< Frames didn't arrived within 5 seconds */ RS2_NOTIFICATION_CATEGORY_FRAME_CORRUPTED, /**< Received partial/incomplete frame */ @@ -21,11 +21,12 @@ typedef enum rs2_notification_category{ RS2_NOTIFICATION_CATEGORY_HARDWARE_EVENT, /**< General Hardeware notification that is not an error */ RS2_NOTIFICATION_CATEGORY_UNKNOWN_ERROR, /**< Received unknown error from the device */ RS2_NOTIFICATION_CATEGORY_FIRMWARE_UPDATE_RECOMMENDED, /**< Current firmware version installed is not the latest available */ + RS2_NOTIFICATION_CATEGORY_POSE_RELOCALIZATION, /**< A relocalization event has updated the pose provided by a pose sensor */ RS2_NOTIFICATION_CATEGORY_COUNT /**< Number of enumeration values. Not a valid input: intended to be used in for-loops. */ } rs2_notification_category; const char* rs2_notification_category_to_string(rs2_notification_category category); -/** \brief Exception types are the different categories of errors that RealSense API might return */ +/** \brief Exception types are the different categories of errors that RealSense API might return. */ typedef enum rs2_exception_type { RS2_EXCEPTION_TYPE_UNKNOWN, @@ -48,11 +49,12 @@ typedef enum rs2_distortion RS2_DISTORTION_INVERSE_BROWN_CONRADY , /**< Equivalent to Brown-Conrady distortion, except undistorts image instead of distorting it */ RS2_DISTORTION_FTHETA , /**< F-Theta fish-eye distortion model */ RS2_DISTORTION_BROWN_CONRADY , /**< Unmodified Brown-Conrady distortion model */ + RS2_DISTORTION_KANNALA_BRANDT4 , /**< Four parameter Kannala Brandt distortion model */ RS2_DISTORTION_COUNT /**< Number of enumeration values. Not a valid input: intended to be used in for-loops. */ } rs2_distortion; const char* rs2_distortion_to_string(rs2_distortion distortion); -/** \brief Video stream intrinsics */ +/** \brief Video stream intrinsics. */ typedef struct rs2_intrinsics { int width; /**< Width of the image in pixels */ @@ -62,10 +64,10 @@ typedef struct rs2_intrinsics float fx; /**< Focal length of the image plane, as a multiple of pixel width */ float fy; /**< Focal length of the image plane, as a multiple of pixel height */ rs2_distortion model; /**< Distortion model of the image */ - float coeffs[5]; /**< Distortion coefficients, order: k1, k2, p1, p2, k3 */ + float coeffs[5]; /**< Distortion coefficients */ } rs2_intrinsics; -/** \brief Motion device intrinsics: scale, bias, and variances */ +/** \brief Motion device intrinsics: scale, bias, and variances. */ typedef struct rs2_motion_device_intrinsic { /* \internal @@ -78,7 +80,44 @@ typedef struct rs2_motion_device_intrinsic float bias_variances[3]; /**< Variance of bias for X, Y, and Z axis */ } rs2_motion_device_intrinsic; -/** \brief Severity of the librealsense logger */ +/** \brief 3D coordinates with origin at topmost left corner of the lense, + with positive Z pointing away from the camera, positive X pointing camera right and positive Y pointing camera down */ +typedef struct rs2_vertex +{ + float xyz[3]; +} rs2_vertex; + +/** \brief Pixel location within 2D image. (0,0) is the topmost, left corner. Positive X is right, positive Y is down */ +typedef struct rs2_pixel +{ + int ij[2]; +} rs2_pixel; + +/** \brief 3D vector in Euclidean coordinate space */ +typedef struct rs2_vector +{ + float x, y, z; +}rs2_vector; + +/** \brief Quaternion used to represent rotation */ +typedef struct rs2_quaternion +{ + float x, y, z, w; +}rs2_quaternion; + +typedef struct rs2_pose +{ + rs2_vector translation; /**< X, Y, Z values of translation, in meters (relative to initial position) */ + rs2_vector velocity; /**< X, Y, Z values of velocity, in meters/sec */ + rs2_vector acceleration; /**< X, Y, Z values of acceleration, in meters/sec^2 */ + rs2_quaternion rotation; /**< Qi, Qj, Qk, Qr components of rotation as represented in quaternion rotation (relative to initial position) */ + rs2_vector angular_velocity; /**< X, Y, Z values of angular velocity, in radians/sec */ + rs2_vector angular_acceleration; /**< X, Y, Z values of angular acceleration, in radians/sec^2 */ + unsigned int tracker_confidence; /**< Pose confidence 0x0 - Failed, 0x1 - Low, 0x2 - Medium, 0x3 - High */ + unsigned int mapper_confidence; /**< Pose map confidence 0x0 - Failed, 0x1 - Low, 0x2 - Medium, 0x3 - High */ +} rs2_pose; + +/** \brief Severity of the librealsense logger. */ typedef enum rs2_log_severity { RS2_LOG_SEVERITY_DEBUG, /**< Detailed information about ordinary operations */ RS2_LOG_SEVERITY_INFO , /**< Terse information about ordinary operations */ @@ -90,7 +129,7 @@ typedef enum rs2_log_severity { } rs2_log_severity; const char* rs2_log_severity_to_string(rs2_log_severity info); -/** \brief Specifies advanced interfaces (capabilities) objects may implement */ +/** \brief Specifies advanced interfaces (capabilities) objects may implement. */ typedef enum rs2_extension { RS2_EXTENSION_UNKNOWN, @@ -118,6 +157,22 @@ typedef enum rs2_extension RS2_EXTENSION_TM2, RS2_EXTENSION_SOFTWARE_DEVICE, RS2_EXTENSION_SOFTWARE_SENSOR, + RS2_EXTENSION_DECIMATION_FILTER, + RS2_EXTENSION_THRESHOLD_FILTER, + RS2_EXTENSION_DISPARITY_FILTER, + RS2_EXTENSION_SPATIAL_FILTER, + RS2_EXTENSION_TEMPORAL_FILTER, + RS2_EXTENSION_HOLE_FILLING_FILTER, + RS2_EXTENSION_ZERO_ORDER_FILTER, + RS2_EXTENSION_RECOMMENDED_FILTERS, + RS2_EXTENSION_POSE, + RS2_EXTENSION_POSE_SENSOR, + RS2_EXTENSION_WHEEL_ODOMETER, + RS2_EXTENSION_GLOBAL_TIMER, + RS2_EXTENSION_UPDATABLE, + RS2_EXTENSION_UPDATE_DEVICE, + RS2_EXTENSION_L500_DEPTH_SENSOR, + RS2_EXTENSION_TM2_SENSOR, RS2_EXTENSION_COUNT } rs2_extension; const char* rs2_extension_type_to_string(rs2_extension type); @@ -130,14 +185,20 @@ typedef enum rs2_matchers RS2_MATCHER_DI_C, //compare depth and ir based on frame number, //compare the pair of corresponding depth and ir with color based on closest timestamp, - //commonlly used by SR300 + //commonly used by SR300 RS2_MATCHER_DLR_C, //compare depth, left and right ir based on frame number, //compare the set of corresponding depth, left and right with color based on closest timestamp, - //commonlly used by RS415, RS435 + //commonly used by RS415, RS435 RS2_MATCHER_DLR, //compare depth, left and right ir based on frame number, - //commonlly used by RS400, RS405, RS410, RS420, RS430 + //commonly used by RS400, RS405, RS410, RS420, RS430 + + RS2_MATCHER_DIC, //compare depth, ir and confidence based on frame number used by RS500 + + RS2_MATCHER_DIC_C, //compare depth, ir and confidence based on frame number, + //compare the set of corresponding depth, ir and confidence with color based on closest timestamp, + //commonly used by RS515 RS2_MATCHER_DEFAULT, //the default matcher compare all the streams based on closest timestamp @@ -155,6 +216,7 @@ typedef struct rs2_pipeline_profile rs2_pipeline_profile; typedef struct rs2_config rs2_config; typedef struct rs2_device_list rs2_device_list; typedef struct rs2_stream_profile_list rs2_stream_profile_list; +typedef struct rs2_processing_block_list rs2_processing_block_list; typedef struct rs2_stream_profile rs2_stream_profile; typedef struct rs2_frame_callback rs2_frame_callback; typedef struct rs2_log_callback rs2_log_callback; @@ -164,11 +226,13 @@ typedef struct rs2_source rs2_source; typedef struct rs2_processing_block rs2_processing_block; typedef struct rs2_frame_processor_callback rs2_frame_processor_callback; typedef struct rs2_playback_status_changed_callback rs2_playback_status_changed_callback; +typedef struct rs2_update_progress_callback rs2_update_progress_callback; typedef struct rs2_context rs2_context; typedef struct rs2_device_hub rs2_device_hub; typedef struct rs2_sensor_list rs2_sensor_list; typedef struct rs2_sensor rs2_sensor; typedef struct rs2_options rs2_options; +typedef struct rs2_options_list rs2_options_list; typedef struct rs2_devices_changed_callback rs2_devices_changed_callback; typedef struct rs2_notification rs2_notification; typedef struct rs2_notifications_callback rs2_notifications_callback; @@ -176,10 +240,12 @@ typedef void (*rs2_notification_callback_ptr)(rs2_notification*, void*); typedef void (*rs2_devices_changed_callback_ptr)(rs2_device_list*, rs2_device_list*, void*); typedef void (*rs2_frame_callback_ptr)(rs2_frame*, void*); typedef void (*rs2_frame_processor_callback_ptr)(rs2_frame*, rs2_source*, void*); +typedef void(*rs2_update_progress_callback_ptr)(const float, void*); typedef double rs2_time_t; /**< Timestamp format. units are milliseconds */ typedef long long rs2_metadata_type; /**< Metadata attribute type is defined as 64 bit signed integer*/ +rs2_error * rs2_create_error(const char* what, const char* name, const char* args, rs2_exception_type type); rs2_exception_type rs2_get_librealsense_exception_type(const rs2_error* error); const char* rs2_get_failed_function (const rs2_error* error); const char* rs2_get_failed_args (const rs2_error* error); diff --git a/libs/realsense2/include/librealsense2/hpp/rs_context.hpp b/libs/realsense2/include/librealsense2/hpp/rs_context.hpp index 6b383ce..3d105aa 100755 --- a/libs/realsense2/include/librealsense2/hpp/rs_context.hpp +++ b/libs/realsense2/include/librealsense2/hpp/rs_context.hpp @@ -17,7 +17,7 @@ namespace rs2 :_removed(removed), _added(added) {} /** - * check if specific device was disconnected + * check if a specific device was disconnected * \return true if device disconnected, false if device connected */ bool was_removed(const rs2::device& dev) const @@ -34,7 +34,7 @@ namespace rs2 } /** - * check if specific device was added + * check if a specific device was added * \return true if device added, false otherwise */ bool was_added(const rs2::device& dev) const @@ -49,7 +49,7 @@ namespace rs2 return res > 0; } - + /** * returns a list of all newly connected devices * \return the list of all new connected devices @@ -59,15 +59,6 @@ namespace rs2 return _added; } - /** - * returns a list of all newly removed devices - * \return the list of all newly removed devices - */ - device_list get_removed_devices() const - { - return _removed; - } - private: device_list _removed; device_list _added; @@ -96,6 +87,7 @@ namespace rs2 class pipeline; class device_hub; + class software_device; /** * default librealsense context class @@ -128,6 +120,21 @@ namespace rs2 return device_list(list); } + /** + * create a static snapshot of all connected devices at the time of the call + * \return the list of devices connected devices at the time of the call + */ + device_list query_devices(int mask) const + { + rs2_error* e = nullptr; + std::shared_ptr list( + rs2_query_devices_ex(_context.get(), mask, &e), + rs2_delete_device_list); + error::handle(e); + + return device_list(list); + } + /** * @brief Generate a flat list of all available sensors from all RealSense devices * @return List of sensors @@ -192,13 +199,22 @@ namespace rs2 rs2::error::handle(e); } -protected: - friend class rs2::pipeline; - friend class rs2::device_hub; + void unload_tracking_module() + { + rs2_error* e = nullptr; + rs2_context_unload_tracking_module(_context.get(), &e); + rs2::error::handle(e); + } context(std::shared_ptr ctx) : _context(ctx) {} + explicit operator std::shared_ptr() { return _context; }; + protected: + friend class rs2::pipeline; + friend class rs2::device_hub; + friend class rs2::software_device; + std::shared_ptr _context; }; @@ -209,11 +225,10 @@ namespace rs2 { public: explicit device_hub(context ctx) - : _ctx(std::move(ctx)) { rs2_error* e = nullptr; _device_hub = std::shared_ptr( - rs2_create_device_hub(_ctx._context.get(), &e), + rs2_create_device_hub(ctx._context.get(), &e), rs2_delete_device_hub); error::handle(e); } @@ -226,7 +241,7 @@ namespace rs2 { rs2_error* e = nullptr; std::shared_ptr dev( - rs2_device_hub_wait_for_device(_ctx._context.get(), _device_hub.get(), &e), + rs2_device_hub_wait_for_device(_device_hub.get(), &e), rs2_delete_device); error::handle(e); @@ -247,8 +262,10 @@ namespace rs2 return res > 0 ? true : false; } + + explicit operator std::shared_ptr() { return _device_hub; } + explicit device_hub(std::shared_ptr hub) : _device_hub(std::move(hub)) {} private: - context _ctx; std::shared_ptr _device_hub; }; diff --git a/libs/realsense2/include/librealsense2/hpp/rs_device.hpp b/libs/realsense2/include/librealsense2/hpp/rs_device.hpp index 917450d..85ee2bb 100755 --- a/libs/realsense2/include/librealsense2/hpp/rs_device.hpp +++ b/libs/realsense2/include/librealsense2/hpp/rs_device.hpp @@ -134,6 +134,9 @@ namespace rs2 virtual ~device() { } + + explicit operator std::shared_ptr() { return _dev; }; + explicit device(std::shared_ptr dev) : _dev(dev) {} protected: friend class rs2::context; friend class rs2::device_list; @@ -141,8 +144,141 @@ namespace rs2 friend class rs2::device_hub; std::shared_ptr _dev; - explicit device(std::shared_ptr dev) : _dev(dev) + + }; + + template + class update_progress_callback : public rs2_update_progress_callback + { + T _callback; + + public: + explicit update_progress_callback(T callback) : _callback(callback) {} + + void on_update_progress(const float progress) override + { + _callback(progress); + } + + void release() override { delete this; } + }; + + class updatable : public device + { + public: + updatable() : device() {} + updatable(device d) + : device(d.get()) + { + rs2_error* e = nullptr; + if (rs2_is_device_extendable_to(_dev.get(), RS2_EXTENSION_UPDATABLE, &e) == 0 && !e) + { + _dev.reset(); + } + error::handle(e); + } + + // Move the device to update state, this will cause the updatable device to disconnect and reconnect as an update device. + void enter_update_state() const + { + rs2_error* e = nullptr; + rs2_enter_update_state(_dev.get(), &e); + error::handle(e); + } + + // Create backup of camera flash memory. Such backup does not constitute valid firmware image, and cannot be + // loaded back to the device, but it does contain all calibration and device information." + std::vector create_flash_backup() const + { + std::vector results; + + rs2_error* e = nullptr; + std::shared_ptr list( + rs2_create_flash_backup_cpp(_dev.get(), nullptr, &e), + rs2_delete_raw_data); + error::handle(e); + + auto size = rs2_get_raw_data_size(list.get(), &e); + error::handle(e); + + auto start = rs2_get_raw_data(list.get(), &e); + + results.insert(results.begin(), start, start + size); + + return results; + } + + template + std::vector create_flash_backup(T callback) const + { + std::vector results; + + rs2_error* e = nullptr; + std::shared_ptr list( + rs2_create_flash_backup_cpp(_dev.get(), new update_progress_callback(std::move(callback)), &e), + rs2_delete_raw_data); + error::handle(e); + + auto size = rs2_get_raw_data_size(list.get(), &e); + error::handle(e); + + auto start = rs2_get_raw_data(list.get(), &e); + + results.insert(results.begin(), start, start + size); + + return results; + } + + // Update an updatable device to the provided unsigned firmware. This call is executed on the caller's thread. + void update_unsigned(const std::vector& image, int update_mode = RS2_UNSIGNED_UPDATE_MODE_UPDATE) const + { + rs2_error* e = nullptr; + rs2_update_firmware_unsigned_cpp(_dev.get(), image.data(), (int)image.size(), nullptr, update_mode, &e); + error::handle(e); + } + + // Update an updatable device to the provided unsigned firmware. This call is executed on the caller's thread and it supports progress notifications via the callback. + template + void update_unsigned(const std::vector& image, T callback, int update_mode = RS2_UNSIGNED_UPDATE_MODE_UPDATE) const + { + rs2_error* e = nullptr; + rs2_update_firmware_unsigned_cpp(_dev.get(), image.data(), image.size(), new update_progress_callback(std::move(callback)), update_mode, &e); + error::handle(e); + } + }; + + class update_device : public device + { + public: + update_device() : device() {} + update_device(device d) + : device(d.get()) + { + rs2_error* e = nullptr; + if (rs2_is_device_extendable_to(_dev.get(), RS2_EXTENSION_UPDATE_DEVICE, &e) == 0 && !e) + { + _dev.reset(); + } + error::handle(e); + } + + // Update an updatable device to the provided firmware. + // This call is executed on the caller's thread. + void update(const std::vector& fw_image) const { + rs2_error* e = nullptr; + rs2_update_firmware_cpp(_dev.get(), fw_image.data(), (int)fw_image.size(), NULL, &e); + error::handle(e); + } + + // Update an updatable device to the provided firmware. + // This call is executed on the caller's thread and it supports progress notifications via the callback. + template + void update(const std::vector& fw_image, T callback) const + { + rs2_error* e = nullptr; + rs2_update_firmware_cpp(_dev.get(), fw_image.data(), fw_image.size(), new update_progress_callback(std::move(callback)), &e); + error::handle(e); } }; @@ -283,10 +419,21 @@ namespace rs2 return _list.get(); } + operator std::shared_ptr() { return _list; }; + private: std::shared_ptr _list; }; + /** + * The tm2 class is an interface for T2XX devices, such as T265. + * + * For T265, it provides RS2_STREAM_FISHEYE (2), RS2_STREAM_GYRO, RS2_STREAM_ACCEL, and RS2_STREAM_POSE streams, + * and contains the following sensors: + * + * - pose_sensor: map and relocalization functions. + * - wheel_odometer: input for odometry data. + */ class tm2 : public device //TODO: add to wrappers { public: @@ -355,6 +502,85 @@ namespace rs2 rs2_disconnect_tm2_controller(_dev.get(), id, &e); error::handle(e); } + + /** + * Set tm2 camera intrinsics + * \param[in] fisheye_senor_id The ID of the fisheye sensor + * \param[in] intrinsics value to be written to the device + */ + void set_intrinsics(int fisheye_sensor_id, const rs2_intrinsics& intrinsics) + { + rs2_error* e = nullptr; + auto fisheye_sensor = get_sensor_profile(RS2_STREAM_FISHEYE, fisheye_sensor_id); + rs2_set_intrinsics(fisheye_sensor.first.get().get(), fisheye_sensor.second.get(), &intrinsics, &e); + error::handle(e); + } + + /** + * Set tm2 camera extrinsics + * \param[in] from_stream only support RS2_STREAM_FISHEYE + * \param[in] from_id only support left fisheye = 1 + * \param[in] to_stream only support RS2_STREAM_FISHEYE + * \param[in] to_id only support right fisheye = 2 + * \param[in] extrinsics extrinsics value to be written to the device + */ + void set_extrinsics(rs2_stream from_stream, int from_id, rs2_stream to_stream, int to_id, rs2_extrinsics& extrinsics) + { + rs2_error* e = nullptr; + auto from_sensor = get_sensor_profile(from_stream, from_id); + auto to_sensor = get_sensor_profile(to_stream, to_id); + rs2_set_extrinsics(from_sensor.first.get().get(), from_sensor.second.get(), to_sensor.first.get().get(), to_sensor.second.get(), &extrinsics, &e); + error::handle(e); + } + + /** + * Set tm2 motion device intrinsics + * \param[in] stream_type stream type of the motion device + * \param[in] motion_intriniscs intrinsics value to be written to the device + */ + void set_motion_device_intrinsics(rs2_stream stream_type, const rs2_motion_device_intrinsic& motion_intriniscs) + { + rs2_error* e = nullptr; + auto motion_sensor = get_sensor_profile(stream_type, 0); + rs2_set_motion_device_intrinsics(motion_sensor.first.get().get(), motion_sensor.second.get(), &motion_intriniscs, &e); + error::handle(e); + } + + /** + * Reset tm2 to factory calibration + * \param[in] device tm2 device + * \param[out] error If non-null, receives any error that occurs during this call, otherwise, errors are ignored + */ + void reset_to_factory_calibration() + { + rs2_error* e = nullptr; + rs2_reset_to_factory_calibration(_dev.get(), &e); + error::handle(e); + } + + /** + * Write calibration to tm2 device's EEPROM + * \param[in] device tm2 device + * \param[out] error If non-null, receives any error that occurs during this call, otherwise, errors are ignored + */ + void write_calibration() + { + rs2_error* e = nullptr; + rs2_write_calibration(_dev.get(), &e); + error::handle(e); + } + + private: + + std::pair get_sensor_profile(rs2_stream stream_type, int stream_index) { + for (auto s : query_sensors()) { + for (auto p : s.get_stream_profiles()) { + if (p.stream_type() == stream_type && p.stream_index() == stream_index) + return std::pair(s, p); + } + } + return std::pair(); + } }; } #endif // LIBREALSENSE_RS2_DEVICE_HPP diff --git a/libs/realsense2/include/librealsense2/hpp/rs_export.hpp b/libs/realsense2/include/librealsense2/hpp/rs_export.hpp new file mode 100644 index 0000000..127c4e2 --- /dev/null +++ b/libs/realsense2/include/librealsense2/hpp/rs_export.hpp @@ -0,0 +1,260 @@ +// License: Apache 2.0. See LICENSE file in root directory. +// Copyright(c) 2017 Intel Corporation. All Rights Reserved. + +#ifndef LIBREALSENSE_RS2_EXPORT_HPP +#define LIBREALSENSE_RS2_EXPORT_HPP + +#include +#include +#include +#include +#include +#include "rs_processing.hpp" +#include "rs_internal.hpp" + +namespace rs2 +{ + class save_to_ply : public filter + { + public: + save_to_ply(std::string filename = "RealSense Pointcloud ", pointcloud pc = pointcloud()) + : filter([this](frame f, frame_source& s) { func(f, s); }), + _pc(std::move(pc)), fname(filename) + { + register_simple_option(OPTION_IGNORE_COLOR, option_range{ 0, 1, 0, 1 }); + } + + + static const auto OPTION_IGNORE_COLOR = rs2_option(RS2_OPTION_COUNT + 1); + private: + void func(frame data, frame_source& source) + { + frame depth, color; + if (auto fs = data.as()) { + for (auto f : fs) { + if (f.is()) depth = f; + else if (!depth && f.is()) depth = f; + else if (!color && f.is()) color = f; + } + } else if (data.is() || data.is()) { + depth = data; + } + + if (!depth) throw std::runtime_error("Need depth data to save PLY"); + if (!depth.is()) { + if (color) _pc.map_to(color); + depth = _pc.calculate(depth); + } + + export_to_ply(depth, color); + source.frame_ready(data); // passthrough filter because processing_block::process doesn't support sinks + } + + void export_to_ply(points p, video_frame color) { + const bool use_texcoords = color && !get_option(OPTION_IGNORE_COLOR); + const auto verts = p.get_vertices(); + const auto texcoords = p.get_texture_coordinates(); + std::vector new_verts; + std::vector> new_tex; + std::map idx_map; + + new_verts.reserve(p.size()); + if (use_texcoords) new_tex.reserve(p.size()); + + static const auto min_distance = 1e-6; + + for (size_t i = 0; i < p.size(); ++i) { + if (fabs(verts[i].x) >= min_distance || fabs(verts[i].y) >= min_distance || + fabs(verts[i].z) >= min_distance) + { + idx_map[i] = new_verts.size(); + new_verts.push_back(verts[i]); + if (use_texcoords) + { + auto rgb = get_texcolor(color, texcoords[i].u, texcoords[i].v); + new_tex.push_back(rgb); + } + } + } + + auto profile = p.get_profile().as(); + auto width = profile.width(), height = profile.height(); + static const auto threshold = 0.05f; + std::vector> faces; + for (int x = 0; x < width - 1; ++x) { + for (int y = 0; y < height - 1; ++y) { + auto a = y * width + x, b = y * width + x + 1, c = (y + 1)*width + x, d = (y + 1)*width + x + 1; + if (verts[a].z && verts[b].z && verts[c].z && verts[d].z + && fabs(verts[a].z - verts[b].z) < threshold && fabs(verts[a].z - verts[c].z) < threshold + && fabs(verts[b].z - verts[d].z) < threshold && fabs(verts[c].z - verts[d].z) < threshold) + { + if (idx_map.count(a) == 0 || idx_map.count(b) == 0 || idx_map.count(c) == 0 || + idx_map.count(d) == 0) + continue; + faces.push_back({ idx_map[a], idx_map[b], idx_map[d] }); + faces.push_back({ idx_map[d], idx_map[c], idx_map[a] }); + } + } + } + + std::stringstream name; + name << fname << p.get_frame_number() << ".ply"; + std::ofstream out(name.str()); + out << "ply\n"; + out << "format binary_little_endian 1.0\n"; + out << "comment pointcloud saved from Realsense Viewer\n"; + out << "element vertex " << new_verts.size() << "\n"; + out << "property float" << sizeof(float) * 8 << " x\n"; + out << "property float" << sizeof(float) * 8 << " y\n"; + out << "property float" << sizeof(float) * 8 << " z\n"; + if (use_texcoords) + { + out << "property uchar red\n"; + out << "property uchar green\n"; + out << "property uchar blue\n"; + } + out << "element face " << faces.size() << "\n"; + out << "property list uchar int vertex_indices\n"; + out << "end_header\n"; + out.close(); + + out.open(name.str(), std::ios_base::app | std::ios_base::binary); + for (int i = 0; i < new_verts.size(); ++i) + { + // we assume little endian architecture on your device + out.write(reinterpret_cast(&(new_verts[i].x)), sizeof(float)); + out.write(reinterpret_cast(&(new_verts[i].y)), sizeof(float)); + out.write(reinterpret_cast(&(new_verts[i].z)), sizeof(float)); + + if (use_texcoords) + { + out.write(reinterpret_cast(&(new_tex[i][0])), sizeof(uint8_t)); + out.write(reinterpret_cast(&(new_tex[i][1])), sizeof(uint8_t)); + out.write(reinterpret_cast(&(new_tex[i][2])), sizeof(uint8_t)); + } + } + auto size = faces.size(); + for (int i = 0; i < size; ++i) { + static const int three = 3; + out.write(reinterpret_cast(&three), sizeof(uint8_t)); + out.write(reinterpret_cast(&(faces[i][0])), sizeof(int)); + out.write(reinterpret_cast(&(faces[i][1])), sizeof(int)); + out.write(reinterpret_cast(&(faces[i][2])), sizeof(int)); + } + } + + // TODO: get_texcolor, options API + std::array get_texcolor(const video_frame& texture, float u, float v) + { + const int w = texture.get_width(), h = texture.get_height(); + int x = std::min(std::max(int(u*w + .5f), 0), w - 1); + int y = std::min(std::max(int(v*h + .5f), 0), h - 1); + int idx = x * texture.get_bytes_per_pixel() + y * texture.get_stride_in_bytes(); + const auto texture_data = reinterpret_cast(texture.get_data()); + return { texture_data[idx], texture_data[idx + 1], texture_data[idx + 2] }; + } + + std::string fname; + pointcloud _pc; + }; + + class save_single_frameset : public filter { + public: + save_single_frameset(std::string filename = "RealSense Frameset ") + : filter([this](frame f, frame_source& s) { save(f, s); }), fname(filename) + {} + + private: + void save(frame data, frame_source& source, bool do_signal=true) + { + software_device dev; + + std::vector> sensors; + std::vector> extrinsics; + + if (auto fs = data.as()) { + for (int i = 0; i < fs.size(); ++i) { + frame f = fs[i]; + auto profile = f.get_profile(); + std::stringstream sname; + sname << "Sensor (" << i << ")"; + auto s = dev.add_sensor(sname.str()); + stream_profile software_profile; + + if (auto vf = f.as()) { + auto vp = profile.as(); + rs2_video_stream stream{ vp.stream_type(), vp.stream_index(), i, vp.width(), vp.height(), vp.fps(), vf.get_bytes_per_pixel(), vp.format(), vp.get_intrinsics() }; + software_profile = s.add_video_stream(stream); + if (f.is()) { + auto ds = sensor_from_frame(f)->as(); + s.add_read_only_option(RS2_OPTION_DEPTH_UNITS, ds.get_option(RS2_OPTION_DEPTH_UNITS)); + } + } else if (f.is()) { + auto mp = profile.as(); + rs2_motion_stream stream{ mp.stream_type(), mp.stream_index(), i, mp.fps(), mp.format(), mp.get_motion_intrinsics() }; + software_profile = s.add_motion_stream(stream); + } else if (f.is()) { + rs2_pose_stream stream{ profile.stream_type(), profile.stream_index(), i, profile.fps(), profile.format() }; + software_profile = s.add_pose_stream(stream); + } else { + // TODO: How to handle other frame types? (e.g. points) + assert(false); + } + sensors.emplace_back(s, software_profile, i); + + bool found_extrin = false; + for (auto& root : extrinsics) { + try { + std::get<0>(root).register_extrinsics_to(software_profile, + std::get<1>(root).get_extrinsics_to(profile) + ); + found_extrin = true; + break; + } catch (...) {} + } + if (!found_extrin) { + extrinsics.emplace_back(software_profile, profile); + } + } + + + + // Recorder needs sensors to already exist when its created + std::stringstream name; + name << fname << data.get_frame_number() << ".bag"; + recorder rec(name.str(), dev); + + for (auto group : sensors) { + auto s = std::get<0>(group); + auto profile = std::get<1>(group); + s.open(profile); + s.start([](frame) {}); + frame f = fs[std::get<2>(group)]; + if (auto vf = f.as()) { + s.on_video_frame({ const_cast(vf.get_data()), [](void*) {}, vf.get_stride_in_bytes(), vf.get_bytes_per_pixel(), + vf.get_timestamp(), vf.get_frame_timestamp_domain(), static_cast(vf.get_frame_number()), profile }); + } else if (f.is()) { + s.on_motion_frame({ const_cast(f.get_data()), [](void*) {}, f.get_timestamp(), + f.get_frame_timestamp_domain(), static_cast(f.get_frame_number()), profile }); + } else if (f.is()) { + s.on_pose_frame({ const_cast(f.get_data()), [](void*) {}, f.get_timestamp(), + f.get_frame_timestamp_domain(), static_cast(f.get_frame_number()), profile }); + } + s.stop(); + s.close(); + } + } else { + // single frame + auto set = source.allocate_composite_frame({ data }); + save(set, source, false); + } + + if (do_signal) + source.frame_ready(data); + } + + std::string fname; + }; +} + +#endif \ No newline at end of file diff --git a/libs/realsense2/include/librealsense2/hpp/rs_frame.hpp b/libs/realsense2/include/librealsense2/hpp/rs_frame.hpp index 14f8d00..0ecf670 100755 --- a/libs/realsense2/include/librealsense2/hpp/rs_frame.hpp +++ b/libs/realsense2/include/librealsense2/hpp/rs_frame.hpp @@ -17,6 +17,7 @@ namespace rs2 class frame; class pipeline_profile; class points; + class video_stream_profile; class stream_profile { @@ -32,7 +33,7 @@ namespace rs2 */ int stream_index() const { return _index; } /** - * Return the stream format + * Return the stream type * \return rs2_stream - stream type */ rs2_stream stream_type() const { return _type; } @@ -53,7 +54,7 @@ namespace rs2 int unique_id() const { return _uid; } /** - * Clone current profile and change the type, index and format to input parameters + * Clone the current profile and change the type, index and format to input parameters * \param[in] type - will change the stream type from the cloned profile. * \param[in] index - will change the stream index from the cloned profile. * \param[in] format - will change the stream format from the cloned profile. @@ -77,10 +78,10 @@ namespace rs2 */ bool operator==(const stream_profile& rhs) { - return stream_index() == rhs.stream_index()&& - stream_type() == rhs.stream_type()&& - format() == rhs.format()&& - fps() == rhs.fps(); + return stream_index() == rhs.stream_index() && + stream_type() == rhs.stream_type() && + format() == rhs.format() && + fps() == rhs.fps(); } /** @@ -118,13 +119,13 @@ namespace rs2 } /** - * Checking if stream profile is marked/assigned as default, the meaning is that the profile will be selected when the user will request stream configuration using wildcards (RS2_DEPTH, -1,-1,... + * Checks if stream profile is marked/assigned as default, meaning that the profile will be selected when the user requests stream configuration using wildcards (RS2_DEPTH, -1,-1,... * \return bool - true or false. */ bool is_default() const { return _default; } /** - * Parenthesis operator check that the profile is valid + * Checks if the profile is valid * \return bool - true or false. */ operator bool() const { return _profile != nullptr; } @@ -139,10 +140,6 @@ namespace rs2 Operator implement, return the internal stream profile instance. * \return rs2_stream_profile* - internal instance to communicate with real implementation. */ - operator const rs2_stream_profile*() - { - return _profile; - } /** * Get the extrinsic transformation between two profiles (representing physical sensors) * \param[in] stream_profile to - the stream profile (another sensor) to be based to return the extrinsic @@ -157,8 +154,8 @@ namespace rs2 return res; } /** - * Assign extrinsic transformation parameters to a specific profile (sensor). The extrinsic information is generally available as part of the camera calibration, and librealsense is responsible to retrieve and assign these parameters where appropriate. - * The specific function is intended for synthetic/mock-up (software) devices for which the parameters are produced and injected by the user. + * Assign extrinsic transformation parameters to a specific profile (sensor). The extrinsic information is generally available as part of the camera calibration, and librealsense is responsible for retrieving and assigning these parameters where appropriate. + * This specific function is intended for synthetic/mock-up (software) devices for which the parameters are produced and injected by the user. * \param[in] stream_profile to - which stream profile to be registered with the extrinsic. * \param[in] rs2_extrinsics extrinsics - the extrinsics to be registered. */ @@ -169,12 +166,7 @@ namespace rs2 error::handle(e); } - protected: - friend class rs2::sensor; - friend class rs2::frame; - friend class rs2::pipeline_profile; - friend class software_sensor; - + bool is_cloned() { return bool(_clone); } explicit stream_profile(const rs2_stream_profile* profile) : _profile(profile) { rs2_error* e = nullptr; @@ -185,6 +177,14 @@ namespace rs2 error::handle(e); } + operator const rs2_stream_profile*() { return _profile; } + explicit operator std::shared_ptr() { return _clone; } + + protected: + friend class rs2::sensor; + friend class rs2::frame; + friend class rs2::pipeline_profile; + friend class rs2::video_stream_profile; const rs2_stream_profile* _profile; std::shared_ptr _clone; @@ -202,7 +202,7 @@ namespace rs2 { public: /** - * Video stream profile instance which contans additional video attributes + * Stream profile instance which contains additional video attributes * \param[in] stream_profile sp - assign exisiting stream_profile to this instance. */ explicit video_stream_profile(const stream_profile& sp) @@ -232,7 +232,7 @@ namespace rs2 return _height; } /** - * Get stream profile instrinsics attribute + * Get stream profile instrinsics attributes * \return rs2_intrinsics - stream intrinsics. */ rs2_intrinsics get_intrinsics() const @@ -244,6 +244,28 @@ namespace rs2 return intr; } + using stream_profile::clone; + + /** + * Clone current profile and change the type, index and format to input parameters + * \param[in] type - will change the stream type from the cloned profile. + * \param[in] index - will change the stream index from the cloned profile. + * \param[in] format - will change the stream format from the cloned profile. + * \param[in] width - will change the width of the profile + * \param[in] height - will change the height of the profile + * \param[in] intr - will change the intrinsics of the profile + * \return stream_profile - return the cloned stream profile. + */ + stream_profile clone(rs2_stream type, int index, rs2_format format, int width, int height, const rs2_intrinsics& intr) const + { + rs2_error* e = nullptr; + auto ref = rs2_clone_video_stream_profile(_profile, type, index, format, width, height, &intr, &e); + error::handle(e); + stream_profile res(ref); + res._clone = std::shared_ptr(ref, [](rs2_stream_profile* r) { rs2_delete_stream_profile(r); }); + + return res; + } private: int _width = 0; int _height = 0; @@ -254,7 +276,7 @@ namespace rs2 { public: /** - * Video stream profile instance which contans additional motion attributes + * Stream profile instance which contains IMU-specific intrinsics. * \param[in] stream_profile sp - assign exisiting stream_profile to this instance. */ explicit motion_stream_profile(const stream_profile& sp) @@ -269,11 +291,10 @@ namespace rs2 } /** - * Returns scale and bias of a the motion stream profile + * Returns scale/bias/covariances of a the motion sensors * \return rs2_motion_device_intrtinsic - stream motion intrinsics */ rs2_motion_device_intrinsic get_motion_intrinsics() const - { rs2_error* e = nullptr; rs2_motion_device_intrinsic intrin; @@ -283,6 +304,35 @@ namespace rs2 } }; + class pose_stream_profile : public stream_profile + { + public: + /** + * Stream profile instance with an explicit pose extension type. + * \param[in] stream_profile sp - assign exisiting stream_profile to this instance. + */ + explicit pose_stream_profile(const stream_profile& sp) + : stream_profile(sp) + { + rs2_error* e = nullptr; + if ((rs2_stream_profile_is(sp.get(), RS2_EXTENSION_POSE_PROFILE, &e) == 0 && !e)) + { + _profile = nullptr; + } + error::handle(e); + } + }; + + /** + Interface for frame filtering functionality + */ + class filter_interface + { + public: + virtual rs2::frame process(rs2::frame frame) const = 0; + virtual ~filter_interface() = default; + }; + class frame { public: @@ -294,16 +344,16 @@ namespace rs2 * Base class for multiple frame extensions with internal frame handle * \param[in] rs2_frame frame_ref - internal frame instance */ - frame(rs2_frame* frame_ref) : frame_ref(frame_ref) + frame(rs2_frame* ref) : frame_ref(ref) { #ifdef _DEBUG - if (frame_ref) + if (ref) { rs2_error* e = nullptr; - auto r = rs2_get_frame_number(frame_ref, &e); + auto r = rs2_get_frame_number(ref, &e); if (!e) frame_number = r; - auto s = rs2_get_frame_stream_profile(frame_ref, &e); + auto s = rs2_get_frame_stream_profile(ref, &e); if (!e) profile = stream_profile(s); } @@ -335,6 +385,7 @@ namespace rs2 swap(other); return *this; } + /** * Set the internal frame handle to the one in parameter, the function create additional reference if internal reference exist. * \param[in] frame other - another frame instance to be pointed to @@ -345,7 +396,7 @@ namespace rs2 if (frame_ref) add_ref(); #ifdef _DEBUG frame_number = other.frame_number; - profile = other.profile; + profile = other.profile; #endif } /** @@ -379,14 +430,39 @@ namespace rs2 void keep() { rs2_keep_frame(frame_ref); } /** - * Parenthesis operator check internal frame handle is valid. + * Parenthesis operator check if internal frame handle is valid. * \return bool - true or false. */ operator bool() const { return frame_ref != nullptr; } + rs2_sensor* get_sensor() + { + rs2_error* e = nullptr; + auto r = rs2_get_frame_sensor(frame_ref, &e); + error::handle(e); + return r; + } + /** * retrieve the time at which the frame was captured - * \return the timestamp of the frame, in milliseconds since the device was started + * During the frame's lifetime it receives timestamps both at the device and host levels. + * The different timestamps are gathered and managed under the frame's Metadata attributes. + * Chronologically the list of timestamps comprises of: + * SENSOR_TIMESTAMP - Device clock. For video sensors designates the middle of exposure. Requires metadata support. + * FRAME_TIMESTAMP - Device clock. Stamped at the beginning of frame readout and transfer. Requires metadata support. + * BACKEND_TIMESTAMP - Host (EPOCH) clock in Kernel space. Frame transfer from USB Controller to the USB Driver. + * TIME_OF_ARRIVAL - Host (EPOCH) clock in User space. Frame transfer from the USB Driver to Librealsense. + * + * During runtime the SDK dynamically selects the most correct representaion, based on both device and host capabilities: + * In case the frame metadata is not configured: + * - The function call provides the TIME_OF_ARRIVAL stamp. + * In case the metadata is available the function returns: + * - `HW Timestamp` (SENSOR_TIMESTAMP), or + * - `Global Timestamp` Host-corrected derivative of `HW Timestamp` required for multi-sensor/device synchronization + * - The user can select between the unmodified and the host-calculated Hardware Timestamp by toggling + * the `RS2_OPTION_GLOBAL_TIME_ENABLED` option. + * To query which of the three alternatives is active use `get_frame_timestamp_domain()` function call + * \return the timestamp of the frame, in milliseconds according to the elaborated flow */ double get_timestamp() const { @@ -443,6 +519,18 @@ namespace rs2 return r; } + /** + * retrieve data size from frame handle + * \return the number of bytes in frame + */ + const int get_data_size() const + { + rs2_error* e = nullptr; + auto r = rs2_get_frame_data_size(frame_ref, &e); + error::handle(e); + return r; + } + /** * retrieve data from frame handle * \return the pointer to the start of the frame data @@ -493,6 +581,12 @@ namespace rs2 * \return rs2_frame - internal frame handle. */ rs2_frame* get() const { return frame_ref; } + explicit operator rs2_frame*() { return frame_ref; } + + frame apply_filter(filter_interface& filter) + { + return filter.process(*this); + } protected: /** @@ -536,7 +630,7 @@ namespace rs2 { public: /** - * Inherit frame class with additional video related attributs/functions + * Extends the frame class with additional video related attributes and functions * \param[in] frame - existing frame instance */ video_frame(const frame& f) @@ -619,12 +713,12 @@ namespace rs2 { public: /** - * Inherit frame class with additional point cloud related attributs/functions + * Extends the frame class with additional point cloud related attributes and functions */ points() : frame(), _size(0) {} /** - * Inherit frame class with additional point cloud related attributs/functions + * Extends the frame class with additional point cloud related attributes and functions * \param[in] frame - existing frame instance */ points(const frame& f) @@ -639,13 +733,12 @@ namespace rs2 if (get()) { - rs2_error* e = nullptr; _size = rs2_get_frame_points_count(get(), &e); error::handle(e); } } /** - * Retrieve back the vertices + * Retrieve the vertices of the point cloud * \param[in] vertex* - pointer of vertex sturcture */ const vertex* get_vertices() const @@ -657,7 +750,7 @@ namespace rs2 } /** - * Export current point cloud to PLY file + * Export the point cloud to a PLY file * \param[in] string fname - file name of the PLY to be saved * \param[in] video_frame texture - the texture for the PLY. */ @@ -670,7 +763,7 @@ namespace rs2 error::handle(e); } /** - * return the texture coordinate(uv map) for the point cloud + * Retrieve the texture coordinates (uv map) for the point cloud * \return texture_coordinate* - pointer of texture coordinates. */ const texture_coordinate* get_texture_coordinates() const @@ -694,7 +787,7 @@ namespace rs2 { public: /** - * Inherit video_frame class with additional depth related attributs/functions + * Extends the video_frame class with additional depth related attributes and functions * \param[in] frame - existing frame instance */ depth_frame(const frame& f) @@ -709,10 +802,10 @@ namespace rs2 } /** - * Return the distance between two depth pixels - * \param[in] int x - first pixel position. - * \param[in] int y - second pixel position. - * \return float - distance between to points. + * Provide the depth in meters at the given pixel + * \param[in] int x - pixel's x coordinate. + * \param[in] int y - pixel's y coordinate. + * \return float - depth in metric units at given pixel */ float get_distance(int x, int y) const { @@ -727,7 +820,7 @@ namespace rs2 { public: /** - * Inherit depth_frame class with additional disparity related attributs/functions + * Extend depth_frame class with additional disparity related attributes/functions * \param[in] frame - existing frame instance */ disparity_frame(const frame& f) @@ -741,7 +834,7 @@ namespace rs2 error::handle(e); } /** - * Retrieve back the distance between two IR sensors. + * Retrieve the distance between the two IR sensors. * \return float - baseline. */ float get_baseline(void) const @@ -757,7 +850,7 @@ namespace rs2 { public: /** - * Inherit frame class with additional motion related attributs/functions + * Extends the frame class with additional motion related attributes and functions * \param[in] frame - existing frame instance */ motion_frame(const frame& f) @@ -771,13 +864,13 @@ namespace rs2 error::handle(e); } /** - * Retrieve back the motion data from IMU sensor + * Retrieve the motion data from IMU sensor * \return rs2_vector - 3D vector in Euclidean coordinate space. */ - rs2_vector get_motion_data() + rs2_vector get_motion_data() const { auto data = reinterpret_cast(get_data()); - return rs2_vector{data[0], data[1], data[2]}; + return rs2_vector{ data[0], data[1], data[2] }; } }; @@ -785,7 +878,7 @@ namespace rs2 { public: /** - * Inherit frame class with additional pose related attributs/functions + * Extends the frame class with additional pose related attributes and functions * \param[in] frame - existing frame instance */ pose_frame(const frame& f) @@ -799,10 +892,10 @@ namespace rs2 error::handle(e); } /** - * Retrieve back the pose data from IMU sensor + * Retrieve the pose data from T2xx position tracking sensor * \return rs2_pose - orientation and velocity data. */ - rs2_pose get_pose_data() + rs2_pose get_pose_data() const { rs2_pose pose_data; rs2_error* e = nullptr; @@ -816,11 +909,11 @@ namespace rs2 { public: /** - * Inherit frame class with additional frameset related attributs/functions + * Extends the frame class with additional frameset related attributes and functions */ frameset() :_size(0) {}; /** - * Inherit frame class with additional frameset related attributs/functions + * Extends the frame class with additional frameset related attributes and functions * \param[in] frame - existing frame instance */ frameset(const frame& f) @@ -836,51 +929,52 @@ namespace rs2 if (get()) { - rs2_error* e = nullptr; _size = rs2_embedded_frames_count(get(), &e); error::handle(e); } } /** - * Retrieve back the first frame of specific stream type, if no frame found, return the default one(frame instance) + * Retrieve the first frame of a specific stream and optionally with a specific format. If no frame is found, return an empty frame instance. * \param[in] rs2_stream s - frame to be retrieved from this stream type. + * \param[in] rs2_format f - frame to be retrieved from this format type. * \return frame - first found frame with s stream type. */ - frame first_or_default(rs2_stream s) const + frame first_or_default(rs2_stream s, rs2_format f = RS2_FORMAT_ANY) const { frame result; - foreach([&result, s](frame f) { - if (!result && f.get_profile().stream_type() == s) + foreach_rs([&result, s, f](frame frm) { + if (!result && frm.get_profile().stream_type() == s && (f == RS2_FORMAT_ANY || f == frm.get_profile().format())) { - result = std::move(f); + result = std::move(frm); } }); return result; } /** - * Retrieve back the first frame of specific stream type, if no frame found, error will be thrown + * Retrieve the first frame of a specific stream type and optionally with a specific format. If no frame is found, an error will be thrown. * \param[in] rs2_stream s - frame to be retrieved from this stream type. + * \param[in] rs2_format f - frame to be retrieved from this format type. * \return frame - first found frame with s stream type. */ - frame first(rs2_stream s) const + frame first(rs2_stream s, rs2_format f = RS2_FORMAT_ANY) const { - auto f = first_or_default(s); - if (!f) throw error("Frame of requested stream type was not found!"); - return f; + auto frm = first_or_default(s, f); + if (!frm) throw error("Frame of requested stream type was not found!"); + return frm; } /** - * Retrieve back the first depth framee, if no frame found, return the default one(frame instance) + * Retrieve the first depth frame, if no frame is found, return an empty frame instance. * \return depth_frame - first found depth frame. */ depth_frame get_depth_frame() const { - auto f = first_or_default(RS2_STREAM_DEPTH); + auto f = first_or_default(RS2_STREAM_DEPTH, RS2_FORMAT_Z16); return f.as(); } /** - * Retrieve back the first color frame, if no frame found, search the color frame from IR stream. If still can't find, return the default one(frame instance) + * Retrieve the first color frame, if no frame is found, search for the color frame from IR stream. If one still can't be found, return an empty frame instance. * \return video_frame - first found color frame. */ video_frame get_color_frame() const @@ -896,7 +990,7 @@ namespace rs2 return f; } /** - * Retrieve back the first infrared frame, return the default one(frame instance) + * Retrieve the first infrared frame, if no frame is found, return an empty frame instance. * \param[in] size_t index * \return video_frame - first found infrared frame. */ @@ -909,13 +1003,58 @@ namespace rs2 } else { - foreach([&f, index](const frame& frame) { - if (frame.get_profile().stream_type() == RS2_STREAM_INFRARED && frame.get_profile().stream_index() == index) - f = frame; + foreach_rs([&f, index](const frame& frm) { + if (frm.get_profile().stream_type() == RS2_STREAM_INFRARED && + frm.get_profile().stream_index() == index) f = frm; + }); + } + return f; + } + + /** + * Retrieve the fisheye monochrome video frame + * \param[in] size_t index + * \return video_frame - the fisheye frame denoted by index. + */ + video_frame get_fisheye_frame(const size_t index = 0) const + { + frame f; + if (!index) + { + f = first_or_default(RS2_STREAM_FISHEYE); + } + else + { + foreach_rs([&f, index](const frame& frm) { + if (frm.get_profile().stream_type() == RS2_STREAM_FISHEYE && + frm.get_profile().stream_index() == index) f = frm; }); } return f; } + + /** + * Retrieve the pose frame + * \param[in] size_t index + * \return pose_frame - the sensor's positional data + */ + pose_frame get_pose_frame(const size_t index = 0) const + { + frame f; + if (!index) + { + f = first_or_default(RS2_STREAM_POSE); + } + else + { + foreach_rs([&f, index](const frame& frm) { + if (frm.get_profile().stream_type() == RS2_STREAM_POSE && + frm.get_profile().stream_index() == index) f = frm; + }); + } + return f.as(); + } + /** * Return the size of the frameset * \return size_t - frameset size. @@ -926,11 +1065,11 @@ namespace rs2 } /** - * Template function, extract internal frame handle from the frameset and invoke the action function + * Template function, extract internal frame handles from the frameset and invoke the action function * \param[in] action - instance with () operator implemented will be invoke after frame extraction. */ template - void foreach(T action) const + void foreach_rs(T action) const { rs2_error* e = nullptr; auto count = size(); @@ -960,7 +1099,7 @@ namespace rs2 throw error("Requested index is out of range!"); } - class iterator + class iterator : public std::iterator { public: iterator(const frameset* owner, size_t index = 0) : _index(index), _owner(owner) {} @@ -980,6 +1119,19 @@ namespace rs2 size_t _size; }; + template + class frame_callback : public rs2_frame_callback + { + T on_frame_function; + public: + explicit frame_callback(T on_frame) : on_frame_function(on_frame) {} + + void on_frame(rs2_frame* fref) override + { + on_frame_function(frame{ fref }); + } + void release() override { delete this; } + }; } #endif // LIBREALSENSE_RS2_FRAME_HPP diff --git a/libs/realsense2/include/librealsense2/hpp/rs_internal.hpp b/libs/realsense2/include/librealsense2/hpp/rs_internal.hpp index 7cf1048..69eb6d1 100755 --- a/libs/realsense2/include/librealsense2/hpp/rs_internal.hpp +++ b/libs/realsense2/include/librealsense2/hpp/rs_internal.hpp @@ -89,7 +89,37 @@ namespace rs2 } /** - * Inject frame into the sensor + * Add motion stream to software sensor + * + * \param[in] motion all the parameters that required to defind motion stream + */ + stream_profile add_motion_stream(rs2_motion_stream motion_stream) + { + rs2_error* e = nullptr; + + stream_profile stream(rs2_software_sensor_add_motion_stream(_sensor.get(), motion_stream, &e)); + error::handle(e); + + return stream; + } + + /** + * Add pose stream to software sensor + * + * \param[in] pose all the parameters that required to defind pose stream + */ + stream_profile add_pose_stream(rs2_pose_stream pose_stream) + { + rs2_error* e = nullptr; + + stream_profile stream(rs2_software_sensor_add_pose_stream(_sensor.get(), pose_stream, &e)); + error::handle(e); + + return stream; + } + + /** + * Inject video frame into the sensor * * \param[in] frame all the parameters that required to define video frame */ @@ -100,6 +130,30 @@ namespace rs2 error::handle(e); } + /** + * Inject motion frame into the sensor + * + * \param[in] frame all the parameters that required to define motion frame + */ + void on_motion_frame(rs2_software_motion_frame frame) + { + rs2_error* e = nullptr; + rs2_software_sensor_on_motion_frame(_sensor.get(), frame, &e); + error::handle(e); + } + + /** + * Inject pose frame into the sensor + * + * \param[in] frame all the parameters that required to define pose frame + */ + void on_pose_frame(rs2_software_pose_frame frame) + { + rs2_error* e = nullptr; + rs2_software_sensor_on_pose_frame(_sensor.get(), frame, &e); + error::handle(e); + } + /** * Set frame metadata for the upcoming frames * \param[in] value metadata key to set @@ -185,6 +239,21 @@ namespace rs2 return software_sensor(sensor); } + + /** + * Add software device to existing context + * Any future queries on the context + * Will return this device + * This operation cannot be undone (except for destroying the context) + * + * \param[in] ctx context to add the device to + */ + void add_to(context& ctx) + { + rs2_error* e = nullptr; + rs2_context_add_software_device(ctx._context.get(), _dev.get(), &e); + error::handle(e); + } /** * Set the wanted matcher type that will be used by the syncer diff --git a/libs/realsense2/include/librealsense2/hpp/rs_options.hpp b/libs/realsense2/include/librealsense2/hpp/rs_options.hpp new file mode 100644 index 0000000..fe9fffa --- /dev/null +++ b/libs/realsense2/include/librealsense2/hpp/rs_options.hpp @@ -0,0 +1,160 @@ +// License: Apache 2.0. See LICENSE file in root directory. +// Copyright(c) 2019 Intel Corporation. All Rights Reserved. + +#ifndef LIBREALSENSE_RS2_OPTIONS_HPP +#define LIBREALSENSE_RS2_OPTIONS_HPP + +#include "rs_types.hpp" + +namespace rs2 +{ + class options + { + public: + /** + * check if particular option is supported + * \param[in] option option id to be checked + * \return true if option is supported + */ + bool supports(rs2_option option) const + { + rs2_error* e = nullptr; + auto res = rs2_supports_option(_options, option, &e); + error::handle(e); + return res > 0; + } + + /** + * get option description + * \param[in] option option id to be checked + * \return human-readable option description + */ + const char* get_option_description(rs2_option option) const + { + rs2_error* e = nullptr; + auto res = rs2_get_option_description(_options, option, &e); + error::handle(e); + return res; + } + + /** + * get option name + * \param[in] option option id to be checked + * \return human-readable option name + */ + const char* get_option_name(rs2_option option) const + { + rs2_error* e = nullptr; + auto res = rs2_get_option_name(_options, option, &e); + error::handle(e); + return res; + } + + /** + * get option value description (in case specific option value hold special meaning) + * \param[in] option option id to be checked + * \param[in] val value of the option + * \return human-readable description of a specific value of an option or null if no special meaning + */ + const char* get_option_value_description(rs2_option option, float val) const + { + rs2_error* e = nullptr; + auto res = rs2_get_option_value_description(_options, option, val, &e); + error::handle(e); + return res; + } + + /** + * read option's value + * \param[in] option option id to be queried + * \return value of the option + */ + float get_option(rs2_option option) const + { + rs2_error* e = nullptr; + auto res = rs2_get_option(_options, option, &e); + error::handle(e); + return res; + } + + /** + * retrieve the available range of values of a supported option + * \return option range containing minimum and maximum values, step and default value + */ + option_range get_option_range(rs2_option option) const + { + option_range result; + rs2_error* e = nullptr; + rs2_get_option_range(_options, option, + &result.min, &result.max, &result.step, &result.def, &e); + error::handle(e); + return result; + } + + /** + * write new value to the option + * \param[in] option option id to be queried + * \param[in] value new value for the option + */ + void set_option(rs2_option option, float value) const + { + rs2_error* e = nullptr; + rs2_set_option(_options, option, value, &e); + error::handle(e); + } + + /** + * check if particular option is read-only + * \param[in] option option id to be checked + * \return true if option is read-only + */ + bool is_option_read_only(rs2_option option) const + { + rs2_error* e = nullptr; + auto res = rs2_is_option_read_only(_options, option, &e); + error::handle(e); + return res > 0; + } + + std::vector get_supported_options() + { + std::vector res; + rs2_error* e = nullptr; + std::shared_ptr options_list( + rs2_get_options_list(_options, &e), + rs2_delete_options_list); + + + for (auto opt = 0; opt < rs2_get_options_list_size(options_list.get(), &e);opt++) + { + res.push_back(rs2_get_option_from_list(options_list.get(), opt, &e)); + } + return res; + }; + + options& operator=(const options& other) + { + _options = other._options; + return *this; + } + // if operator= is ok, this should be ok too + options(const options& other) : _options(other._options) {} + + virtual ~options() = default; + protected: + explicit options(rs2_options* o = nullptr) : _options(o) + { + } + + template + options& operator=(const T& dev) + { + _options = (rs2_options*)(dev.get()); + return *this; + } + + private: + rs2_options* _options; + }; +} +#endif // LIBREALSENSE_RS2_OIPTIONS_HPP diff --git a/libs/realsense2/include/librealsense2/hpp/rs_pipeline.hpp b/libs/realsense2/include/librealsense2/hpp/rs_pipeline.hpp index 120a80c..a7f06da 100755 --- a/libs/realsense2/include/librealsense2/hpp/rs_pipeline.hpp +++ b/libs/realsense2/include/librealsense2/hpp/rs_pipeline.hpp @@ -11,7 +11,7 @@ namespace rs2 { /** - * The pipeline profile includes a device and a selection of active streams, with specific profile. + * The pipeline profile includes a device and a selection of active streams, with specific profiles. * The profile is a selection of the above under filters and conditions defined by the pipeline. * Streams may belong to more than one sensor of the device. */ @@ -50,7 +50,7 @@ namespace rs2 } /** - * Return the selected stream profile, which are enabled in this profile. + * Return the stream profile that is enabled for the specified stream in this profile. * * \param[in] stream_type Stream type of the desired profile * \param[in] stream_index Stream index of the desired profile. -1 for any matching. @@ -102,12 +102,11 @@ namespace rs2 return _pipeline_profile != nullptr; } - private: + explicit operator std::shared_ptr() { return _pipeline_profile; } pipeline_profile(std::shared_ptr profile) : - _pipeline_profile(profile) - { + _pipeline_profile(profile){} + private: - } std::shared_ptr _pipeline_profile; friend class config; friend class pipeline; @@ -161,25 +160,51 @@ namespace rs2 error::handle(e); } - //Stream type and possibly also stream index + /** + * Stream type and possibly also stream index. Other parameters are resolved internally. + * + * \param[in] stream_type Stream type to be enabled + * \param[in] stream_index Stream index, used for multiple streams of the same type. -1 indicates any. + */ void enable_stream(rs2_stream stream_type, int stream_index = -1) { enable_stream(stream_type, stream_index, 0, 0, RS2_FORMAT_ANY, 0); } - //Stream type and resolution, and possibly format and frame rate + /** + * Stream type and resolution, and possibly format and frame rate. Other parameters are resolved internally. + * + * \param[in] stream_type Stream type to be enabled + * \param[in] width Stream image width - for images streams. 0 indicates any. + * \param[in] height Stream image height - for images streams. 0 indicates any. + * \param[in] format Stream data format - pixel format for images streams, of data type for other streams. RS2_FORMAT_ANY indicates any. + * \param[in] framerate Stream frames per second. 0 indicates any. + */ void enable_stream(rs2_stream stream_type, int width, int height, rs2_format format = RS2_FORMAT_ANY, int framerate = 0) { enable_stream(stream_type, -1, width, height, format, framerate); } - //Stream type and format + /** + * Stream type and format, and possibly frame rate. Other parameters are resolved internally. + * + * \param[in] stream_type Stream type to be enabled + * \param[in] format Stream data format - pixel format for images streams, of data type for other streams. RS2_FORMAT_ANY indicates any. + * \param[in] framerate Stream frames per second. 0 indicates any. + */ void enable_stream(rs2_stream stream_type, rs2_format format, int framerate = 0) { enable_stream(stream_type, -1, 0, 0, format, framerate); } - //Stream type and format + /** + * Stream type, index, and format, and possibly framerate. Other parameters are resolved internally. + * + * \param[in] stream_type Stream type to be enabled + * \param[in] stream_index Stream index, used for multiple streams of the same type. -1 indicates any. + * \param[in] format Stream data format - pixel format for images streams, of data type for other streams. RS2_FORMAT_ANY indicates any. + * \param[in] framerate Stream frames per second. 0 indicates any. + */ void enable_stream(rs2_stream stream_type, int stream_index, rs2_format format, int framerate = 0) { enable_stream(stream_type, stream_index, 0, 0, format, framerate); @@ -217,7 +242,7 @@ namespace rs2 * Select a recorded device from a file, to be used by the pipeline through playback. * The device available streams are as recorded to the file, and \c resolve() considers only this device and * configuration as available. - * This request cannot be used if enable_record_to_file() is called for the current config, and vise versa + * This request cannot be used if \c enable_record_to_file() is called for the current config, and vice versa. * * \param[in] file_name The playback file of the device */ @@ -229,8 +254,8 @@ namespace rs2 } /** - * Requires that the resolved device would be recorded to file - * This request cannot be used if enable_device_from_file() is called for the current config, and vise versa + * Requires that the resolved device would be recorded to file. + * This request cannot be used if \c enable_device_from_file() is called for the current config, and vice versa. * as available. * * \param[in] file_name The desired file for the output record @@ -316,12 +341,14 @@ namespace rs2 { return _config; } - private: - config(std::shared_ptr config) : _config(config) + explicit operator std::shared_ptr() const { + return _config; } - std::shared_ptr _config; + config(std::shared_ptr cfg) : _config(cfg) {} + private: + std::shared_ptr _config; }; /** @@ -343,7 +370,6 @@ namespace rs2 * \param[in] ctx The context allocated by the application. Using the platform context by default. */ pipeline(context ctx = context()) - : _ctx(ctx) { rs2_error* e = nullptr; _pipeline = std::shared_ptr( @@ -403,6 +429,54 @@ namespace rs2 return pipeline_profile(p); } + /** + * Start the pipeline streaming with its default configuration. + * The pipeline captures samples from the device, and delivers them to the provided frame callback. + * Starting the pipeline is possible only when it is not started. If the pipeline was started, an exception is raised. + * When starting the pipeline with a callback both \c wait_for_frames() and \c poll_for_frames() will throw exception. + * + * \param[in] callback Stream callback, can be any callable object accepting rs2::frame + * \return The actual pipeline device and streams profile, which was successfully configured to the streaming device. + */ + template + pipeline_profile start(S callback) + { + rs2_error* e = nullptr; + auto p = std::shared_ptr( + rs2_pipeline_start_with_callback_cpp(_pipeline.get(), new frame_callback(callback), &e), + rs2_delete_pipeline_profile); + + error::handle(e); + return pipeline_profile(p); + } + + /** + * Start the pipeline streaming according to the configuraion. + * The pipeline captures samples from the device, and delivers them to the provided frame callback. + * Starting the pipeline is possible only when it is not started. If the pipeline was started, an exception is raised. + * When starting the pipeline with a callback both \c wait_for_frames() and \c poll_for_frames() will throw exception. + * The pipeline selects and activates the device upon start, according to configuration or a default configuration. + * When the rs2::config is provided to the method, the pipeline tries to activate the config \c resolve() result. + * If the application requests are conflicting with pipeline computer vision modules or no matching device is available on + * the platform, the method fails. + * Available configurations and devices may change between config \c resolve() call and pipeline start, in case devices + * are connected or disconnected, or another application acquires ownership of a device. + * + * \param[in] config A rs2::config with requested filters on the pipeline configuration. By default no filters are applied. + * \param[in] callback Stream callback, can be any callable object accepting rs2::frame + * \return The actual pipeline device and streams profile, which was successfully configured to the streaming device. + */ + template + pipeline_profile start(const config& config, S callback) + { + rs2_error* e = nullptr; + auto p = std::shared_ptr( + rs2_pipeline_start_with_config_and_callback_cpp(_pipeline.get(), config.get().get(), new frame_callback(callback), &e), + rs2_delete_pipeline_profile); + + error::handle(e); + return pipeline_profile(p); + } /** * Stop the pipeline streaming. @@ -428,12 +502,12 @@ namespace rs2 * should be called as fast as the device frame rate. * The application can maintain the frames handles to defer processing. However, if the application maintains too long * history, the device may lack memory resources to produce new frames, and the following call to this method shall fail - * to retrieve new frames, until resources are retained. + * to retrieve new frames, until resources become available. * * \param[in] timeout_ms Max time in milliseconds to wait until an exception will be thrown * \return Set of time synchronized frames, one from each active stream */ - frameset wait_for_frames(unsigned int timeout_ms = 5000) const + frameset wait_for_frames(unsigned int timeout_ms = RS2_DEFAULT_TIMEOUT) const { rs2_error* e = nullptr; frame f(rs2_pipeline_wait_for_frames(_pipeline.get(), timeout_ms, &e)); @@ -451,7 +525,7 @@ namespace rs2 * To avoid frame drops, this method should be called as fast as the device frame rate. * The application can maintain the frames handles to defer processing. However, if the application maintains too long * history, the device may lack memory resources to produce new frames, and the following calls to this method shall - * return no new frames, until resources are retained. + * return no new frames, until resources become available. * * \param[out] f Frames set handle * \return True if new set of time synchronized frames was stored to f, false if no new frames set is available @@ -471,7 +545,7 @@ namespace rs2 return res > 0; } - bool try_wait_for_frames(frameset* f, unsigned int timeout_ms = 5000) const + bool try_wait_for_frames(frameset* f, unsigned int timeout_ms = RS2_DEFAULT_TIMEOUT) const { if (!f) { @@ -509,9 +583,9 @@ namespace rs2 { return _pipeline; } + explicit pipeline(std::shared_ptr ptr) : _pipeline(ptr) {} private: - context _ctx; std::shared_ptr _pipeline; friend class config; }; diff --git a/libs/realsense2/include/librealsense2/hpp/rs_processing.hpp b/libs/realsense2/include/librealsense2/hpp/rs_processing.hpp index 66f5c8c..e2831c2 100755 --- a/libs/realsense2/include/librealsense2/hpp/rs_processing.hpp +++ b/libs/realsense2/include/librealsense2/hpp/rs_processing.hpp @@ -6,19 +6,20 @@ #include "rs_types.hpp" #include "rs_frame.hpp" -#include "rs_context.hpp" +#include "rs_options.hpp" namespace rs2 { /** - * The source used to generate the frame, which usually generated by low level driver for each sensor. The frame_source is one of the parameter of processing_block callback function, which can be used to re-generate the frame and via frame_ready to invoke another callback function - * to notify application frame is ready. Best understanding please refer to "video_processing_thread" code snippet in rs-measure.cpp. + * The source used to generate frames, which is usually done by the low level driver for each sensor. frame_source is one of the parameters + * of processing_block's callback function, which can be used to re-generate the frame and via frame_ready invoke another callback function + * to notify application frame is ready. Please refer to "video_processing_thread" code snippet in rs-measure.cpp for a detailed usage example. */ class frame_source { public: /** - * Allocate video frame with given params + * Allocate a new video frame with given params * * \param[in] profile Stream profile going to allocate. * \param[in] original Original frame, if new_bpp, new_width, new_height or new_stride is zero, newly created frame will base on original frame's metadata to allocate new frame. If frame_type is RS2_EXTENSION_DEPTH_FRAME, the original of the returned frame will be set to it. @@ -43,6 +44,16 @@ namespace rs2 error::handle(e); return result; } + + frame allocate_points(const stream_profile& profile, + const frame& original) const + { + rs2_error* e = nullptr; + auto result = rs2_allocate_points(_source, profile.get(), original.get(), &e); + error::handle(e); + return result; + } + /** * Allocate composite frame with given params * @@ -101,22 +112,120 @@ namespace rs2 void release() override { delete this; } }; + class frame_queue + { + public: + /** + * create frame queue. frame queues are the simplest x-platform synchronization primitive provided by librealsense + * to help developers who are not using async APIs + * param[in] capacity size of the frame queue + * param[in] keep_frames if set to true, the queue automatically calls keep() on every frame enqueued into it. + */ + explicit frame_queue(unsigned int capacity, bool keep_frames = false) : _capacity(capacity), _keep(keep_frames) + { + rs2_error* e = nullptr; + _queue = std::shared_ptr( + rs2_create_frame_queue(capacity, &e), + rs2_delete_frame_queue); + error::handle(e); + } + + frame_queue() : frame_queue(1) {} + + /** + * enqueue new frame into the queue + * \param[in] f - frame handle to enqueue (this operation passed ownership to the queue) + */ + void enqueue(frame f) const + { + if (_keep) f.keep(); + rs2_enqueue_frame(f.frame_ref, _queue.get()); // noexcept + f.frame_ref = nullptr; // frame has been essentially moved from + } + + /** + * wait until new frame becomes available in the queue and dequeue it + * \return frame handle to be released using rs2_release_frame + */ + frame wait_for_frame(unsigned int timeout_ms = 5000) const + { + rs2_error* e = nullptr; + auto frame_ref = rs2_wait_for_frame(_queue.get(), timeout_ms, &e); + error::handle(e); + return{ frame_ref }; + } + + /** + * poll if a new frame is available and dequeue if it is + * \param[out] f - frame handle + * \return true if new frame was stored to f + */ + template + typename std::enable_if::value, bool>::type poll_for_frame(T* output) const + { + rs2_error* e = nullptr; + rs2_frame* frame_ref = nullptr; + auto res = rs2_poll_for_frame(_queue.get(), &frame_ref, &e); + error::handle(e); + frame f{ frame_ref }; + if (res) *output = f; + return res > 0; + } + + template + typename std::enable_if::value, bool>::type try_wait_for_frame(T* output, unsigned int timeout_ms = 5000) const + { + rs2_error* e = nullptr; + rs2_frame* frame_ref = nullptr; + auto res = rs2_try_wait_for_frame(_queue.get(), timeout_ms, &frame_ref, &e); + error::handle(e); + frame f{ frame_ref }; + if (res) *output = f; + return res > 0; + } + /** + * Does the same thing as enqueue function. + */ + void operator()(frame f) const + { + enqueue(std::move(f)); + } + /** + * Return the capacity of the queue + * \return capacity size + */ + size_t capacity() const { return _capacity; } + + /** + * Return whether or not the queue calls keep on enqueued frames + * \return keeping frames + */ + bool keep_frames() const { return _keep; } + + private: + std::shared_ptr _queue; + size_t _capacity; + bool _keep; + }; + /** - * Define the processing block flow, inherit this class to generate your own processing_block. Best understanding is to refer to colorizer.h/cpp + * Define the processing block flow, inherit this class to generate your own processing_block. Please refer to the viewer class in examples.hpp for a detailed usage example. */ class processing_block : public options { public: + using options::supports; + /** * Start the processing block with callback function on_frame to inform the application the frame is processed. * - * \param[in] on_frame callback function for noticing the frame to be processed is ready. + * \param[in] on_frame callback function for notifying the frame to be processed is ready. */ template void start(S on_frame) { rs2_error* e = nullptr; - rs2_start_processing(_block.get(), new frame_callback(on_frame), &e); + rs2_start_processing(get(), new frame_callback(on_frame), &e); error::handle(e); } /** @@ -142,23 +251,16 @@ namespace rs2 std::swap(f.frame_ref, ptr); rs2_error* e = nullptr; - rs2_process_frame(_block.get(), ptr, &e); + rs2_process_frame(get(), ptr, &e); error::handle(e); } /** - * Does the same thing as "invoke" function - */ - void operator()(frame f) const - { - invoke(std::move(f)); - } - /** * constructor with already created low level processing block assigned. * * \param[in] block - low level rs2_processing_block created before. */ processing_block(std::shared_ptr block) - : options((rs2_options*)block.get()),_block(block) + : options((rs2_options*)block.get()), _block(block) { } @@ -170,131 +272,136 @@ namespace rs2 template processing_block(S processing_function) { - rs2_error* e = nullptr; + rs2_error* e = nullptr; _block = std::shared_ptr( - rs2_create_processing_block(new frame_processor_callback(processing_function),&e), - rs2_delete_processing_block); + rs2_create_processing_block(new frame_processor_callback(processing_function), &e), + rs2_delete_processing_block); options::operator=(_block); error::handle(e); } - operator rs2_options*() const { return (rs2_options*)_block.get(); } + operator rs2_options*() const { return (rs2_options*)get(); } + rs2_processing_block* get() const { return _block.get(); } - private: - std::shared_ptr _block; - }; - - class frame_queue - { - public: /** - * create frame queue. frame queues are the simplest x-platform synchronization primitive provided by librealsense - * to help developers who are not using async APIs - * param[in] capacity size of the frame queue + * Check if a specific camera info field is supported. + * \param[in] info the parameter to check for support + * \return true if the parameter both exists and well-defined for the specific processing_block */ - explicit frame_queue(unsigned int capacity): _capacity(capacity) + bool supports(rs2_camera_info info) const { rs2_error* e = nullptr; - _queue = std::shared_ptr( - rs2_create_frame_queue(capacity, &e), - rs2_delete_frame_queue); + auto is_supported = rs2_supports_processing_block_info(_block.get(), info, &e); error::handle(e); + return is_supported > 0; } - frame_queue() : frame_queue(1) {} + /** + * Retrieve camera specific information, like versions of various internal components. + * \param[in] info camera info type to retrieve + * \return the requested camera info string, in a format specific to the processing_block model + */ + const char* get_info(rs2_camera_info info) const + { + rs2_error* e = nullptr; + auto result = rs2_get_processing_block_info(_block.get(), info, &e); + error::handle(e); + return result; + } + protected: + void register_simple_option(rs2_option option_id, option_range range) { + rs2_error * e = nullptr; + rs2_processing_block_register_simple_option(_block.get(), option_id, + range.min, range.max, range.step, range.def, &e); + error::handle(e); + } + std::shared_ptr _block; + }; + /** + * Define the filter workflow, inherit this class to generate your own filter. Refer to the viewer class in examples.hpp for a more detailed example. + */ + class filter : public processing_block, public filter_interface + { + public: /** - * enqueue new frame into a queue - * \param[in] f - frame handle to enqueue (this operation passed ownership to the queue) + * Ask processing block to process the frame and poll the processed frame from internal queue + * + * \param[in] on_frame frame to be processed. + * return processed frame */ - void enqueue(frame f) const + rs2::frame process(rs2::frame frame) const override { - rs2_enqueue_frame(f.frame_ref, _queue.get()); // noexcept - f.frame_ref = nullptr; // frame has been essentially moved from + invoke(frame); + rs2::frame f; + if (!_queue.poll_for_frame(&f)) + throw std::runtime_error("Error occured during execution of the processing block! See the log for more info"); + return f; } /** - * wait until new frame becomes available in the queue and dequeue it - * \return frame handle to be released using rs2_release_frame + * constructor with already created low level processing block assigned. + * + * \param[in] block - low level rs2_processing_block created before. */ - frame wait_for_frame(unsigned int timeout_ms = 5000) const + filter(std::shared_ptr block, int queue_size = 1) + : processing_block(block), + _queue(queue_size) { - rs2_error* e = nullptr; - auto frame_ref = rs2_wait_for_frame(_queue.get(), timeout_ms, &e); - error::handle(e); - return{ frame_ref }; + start(_queue); } /** - * poll if a new frame is available and dequeue if it is - * \param[out] f - frame handle - * \return true if new frame was stored to f + * constructor with callback function on_frame in rs2_frame_processor_callback structure assigned. + * + * \param[in] processing_function - function pointer of on_frame function in rs2_frame_processor_callback structure, which will be called back by invoke function . */ - template - typename std::enable_if::value, bool>::type poll_for_frame(T* output) const + template + filter(S processing_function, int queue_size = 1) : + processing_block(processing_function), + _queue(queue_size) { - rs2_error* e = nullptr; - rs2_frame* frame_ref = nullptr; - auto res = rs2_poll_for_frame(_queue.get(), &frame_ref, &e); - error::handle(e); - frame f{ frame_ref }; - if (res) *output = f; - return res > 0; + start(_queue); } - template - typename std::enable_if::value, bool>::type try_wait_for_frame(T* output, unsigned int timeout_ms = 5000) const + + frame_queue get_queue() { return _queue; } + rs2_processing_block* get() const { return _block.get(); } + + template + bool is() const { - rs2_error* e = nullptr; - rs2_frame* frame_ref = nullptr; - auto res = rs2_try_wait_for_frame(_queue.get(), timeout_ms, &frame_ref, &e); - error::handle(e); - frame f{ frame_ref }; - if (res) *output = f; - return res > 0; + T extension(*this); + return extension; } - /** - * Does the same thing as enqueue function. - */ - void operator()(frame f) const + + template + T as() const { - enqueue(std::move(f)); + T extension(*this); + return extension; } - /** - * return the capacity of the queue - * \return capacity size - */ - size_t capacity() const { return _capacity; } - private: - std::shared_ptr _queue; - size_t _capacity; + operator bool() const { return _block.get() != nullptr; } + protected: + frame_queue _queue; }; /** - * Generating the 3D point cloud base on depth frame also create the mapped texture. + * Generates 3D point clouds based on a depth frame. Can also map textures from a color frame. */ - class pointcloud : public options + class pointcloud : public filter { public: /** * create pointcloud instance */ - pointcloud() : _queue(1) - { - rs2_error* e = nullptr; - - auto pb = std::shared_ptr( - rs2_create_pointcloud(&e), - rs2_delete_processing_block); - _block = std::make_shared(pb); - - error::handle(e); - - // Redirect options API to the processing block - options::operator=(pb); + pointcloud() : filter(init(), 1) {} - _block->start(_queue); + pointcloud(rs2_stream stream, int index = 0) : filter(init(), 1) + { + set_option(RS2_OPTION_STREAM_FILTER, float(stream)); + set_option(RS2_OPTION_STREAM_INDEX_FILTER, float(index)); } /** * Generate the pointcloud and texture mappings of depth map. @@ -304,78 +411,180 @@ namespace rs2 */ points calculate(frame depth) { - _block->invoke(std::move(depth)); - rs2::frame f; - if (!_queue.poll_for_frame(&f)) - throw std::runtime_error("Error occured during execution of the processing block! See the log for more info"); - return points(f); + auto res = process(depth); + if (res.as()) + return res; + + if (auto set = res.as ()) + { + for (auto f : set) + { + if(f.as()) + return f; + } + } + throw std::runtime_error("Error occured during execution of the processing block! See the log for more info"); } /** - * Map the point cloud to other frame. + * Map the point cloud to the given color frame. * * \param[in] mapped - the frame to be mapped to as texture. */ void map_to(frame mapped) { - _block->set_option(RS2_OPTION_TEXTURE_SOURCE, float(mapped.get_profile().unique_id())); - _block->invoke(std::move(mapped)); + set_option(RS2_OPTION_STREAM_FILTER, float(mapped.get_profile().stream_type())); + set_option(RS2_OPTION_STREAM_FORMAT_FILTER, float(mapped.get_profile().format())); + set_option(RS2_OPTION_STREAM_INDEX_FILTER, float(mapped.get_profile().stream_index())); + process(mapped); } + + protected: + pointcloud(std::shared_ptr block) : filter(block, 1) {} + private: friend class context; - std::shared_ptr _block; - frame_queue _queue; + std::shared_ptr init() + { + rs2_error* e = nullptr; + + auto block = std::shared_ptr( + rs2_create_pointcloud(&e), + rs2_delete_processing_block); + + error::handle(e); + + // Redirect options API to the processing block + //options::operator=(pb); + return block; + } }; - class asynchronous_syncer + class yuy_decoder : public filter { public: /** - * Real asynchronous syncer within syncer class + * Creates YUY decoder processing block. This block accepts raw YUY frames and outputs frames of other formats. + * YUY is a common video format used by a variety of web-cams. It benefits from packing pixels into 2 bytes per pixel + * without signficant quality drop. YUY representation can be converted back to more usable RGB form, + * but this requires somewhat costly conversion. + * The SDK will automatically try to use SSE2 and AVX instructions and CUDA where available to get + * best performance. Other implementations (using GLSL, OpenCL, Neon and NCS) should follow. */ - asynchronous_syncer() + yuy_decoder() : filter(init(), 1) { } + + protected: + yuy_decoder(std::shared_ptr block) : filter(block, 1) {} + + private: + std::shared_ptr init() { rs2_error* e = nullptr; - _processing_block = std::make_shared( - std::shared_ptr( - rs2_create_sync_processing_block(&e), - rs2_delete_processing_block)); + auto block = std::shared_ptr( + rs2_create_yuy_decoder(&e), + rs2_delete_processing_block); + error::handle(e); + + return block; + } + }; + + class threshold_filter : public filter + { + public: + /** + * Creates depth thresholding filter + * By controlling min and max options on the block, one could filter out depth values + * that are either too large or too small, as a software post-processing step + */ + threshold_filter(float min_dist = 0.15f, float max_dist = 4.f) + : filter(init(), 1) + { + set_option(RS2_OPTION_MIN_DISTANCE, min_dist); + set_option(RS2_OPTION_MAX_DISTANCE, max_dist); + } + threshold_filter(filter f) : filter(f) + { + rs2_error* e = nullptr; + if (!rs2_is_processing_block_extendable_to(f.get(), RS2_EXTENSION_THRESHOLD_FILTER, &e) && !e) + { + _block.reset(); + } error::handle(e); } + protected: + threshold_filter(std::shared_ptr block) : filter(block, 1) {} + + private: + std::shared_ptr init() + { + rs2_error* e = nullptr; + auto block = std::shared_ptr( + rs2_create_threshold(&e), + rs2_delete_processing_block); + error::handle(e); + + return block; + } + }; + + class units_transform : public filter + { + public: /** - * Start and set the callback when the synchronization is done. - * \param[in] on_frame - callback function, will be invoked when synchronization is finished. + * Creates depth units to meters processing block. */ - template - void start(S on_frame) + units_transform() : filter(init(), 1) {} + + protected: + units_transform(std::shared_ptr block) : filter(block, 1) {} + + private: + std::shared_ptr init() { - _processing_block->start(on_frame); + rs2_error* e = nullptr; + auto block = std::shared_ptr( + rs2_create_units_transform(&e), + rs2_delete_processing_block); + error::handle(e); + + return block; } + }; + + class asynchronous_syncer : public processing_block + { + public: /** - * Doing the actual synchronization work for the frame - * \param[in] f - frame to send to processing block to do the synchronization. + * Real asynchronous syncer within syncer class */ - void operator()(frame f) const + asynchronous_syncer() : processing_block(init()) {} + + private: + std::shared_ptr init() { - _processing_block->operator()(std::move(f)); + rs2_error* e = nullptr; + auto block = std::shared_ptr( + rs2_create_sync_processing_block(&e), + rs2_delete_processing_block); + + error::handle(e); + return block; } - private: - std::shared_ptr _processing_block; }; class syncer { public: /** - * Sync instance to align the different frames from different streams + * Sync instance to align frames from different streams */ syncer(int queue_size = 1) :_results(queue_size) { _sync.start(_results); - } /** @@ -423,7 +632,7 @@ namespace rs2 void operator()(frame f) const { - _sync(std::move(f)); + _sync.invoke(std::move(f)); } private: asynchronous_syncer _sync; @@ -431,83 +640,76 @@ namespace rs2 }; /** - Auxiliary processing block that performs image alignment using depth data and camera calibration + Auxiliary processing block that performs image alignment using depth data and camera calibration */ - class align + class align : public filter { public: /** - Create align processing block - Alignment is performed between a depth image and another image. - To perform alignment of a depth image to the other, set the align_to parameter with the other stream type. - To perform alignment of a non depth image to a depth image, set the align_to parameter to RS2_STREAM_DEPTH - Camera calibration and frame's stream type are determined on the fly, according to the first valid frameset passed to process() + Create align filter + Alignment is performed between a depth image and another image. + To perform alignment of a depth image to the other, set the align_to parameter with the other stream type. + To perform alignment of a non depth image to a depth image, set the align_to parameter to RS2_STREAM_DEPTH. + Camera calibration and frame's stream type are determined on the fly, according to the first valid frameset passed to process(). - * \param[in] align_to The stream type to which alignment should be made. + * \param[in] align_to The stream type to which alignment should be made. */ - align(rs2_stream align_to) :_queue(1) - { - rs2_error* e = nullptr; - _block = std::make_shared( - std::shared_ptr( - rs2_create_align(align_to, &e), - rs2_delete_processing_block)); - error::handle(e); - - _block->start(_queue); - } + align(rs2_stream align_to) : filter(init(align_to), 1) {} /** * Run the alignment process on the given frames to get an aligned set of frames * - * \param[in] frame A pair of images, where at least one of which is a depth frame - * \return Input frames aligned to one another - */ - frameset process(frameset frame) - { - (*_block)(frame); - rs2::frame f; - if (!_queue.poll_for_frame(&f)) - throw std::runtime_error("Error occured during execution of the processing block! See the log for more info"); - return frameset(f); - } - /** - * Run the alignment process on the given frame - * - * \param[in] f - A pair of images, where at least one of which is a depth frame + * \param[in] frames A set of frames, where at least one of which is a depth frame * \return Input frames aligned to one another */ - void operator()(frame f) const + frameset process(frameset frames) { - (*_block)(std::move(f)); + return filter::process(frames); } + + protected: + align(std::shared_ptr block) : filter(block, 1) {} + private: friend class context; + std::shared_ptr init(rs2_stream align_to) + { + rs2_error* e = nullptr; + auto block = std::shared_ptr( + rs2_create_align(align_to, &e), + rs2_delete_processing_block); + error::handle(e); - std::shared_ptr _block; - frame_queue _queue; + return block; + } }; - class colorizer : public options + class colorizer : public filter { public: + /** + * Create colorizer filter + * Colorizer generate color image based on input depth frame + */ + colorizer() : filter(init(), 1) { } /** * Create colorizer processing block * Colorizer generate color image base on input depth frame + * \param[in] color_scheme - select one of the available color schemes: + * 0 - Jet + * 1 - Classic + * 2 - WhiteToBlack + * 3 - BlackToWhite + * 4 - Bio + * 5 - Cold + * 6 - Warm + * 7 - Quantized + * 8 - Pattern + * 9 - Hue */ - colorizer() : _queue(1) + colorizer(float color_scheme) : filter(init(), 1) { - rs2_error* e = nullptr; - auto pb = std::shared_ptr( - rs2_create_colorizer(&e), - rs2_delete_processing_block); - _block = std::make_shared(pb); - error::handle(e); - - // Redirect options API to the processing block - options::operator=(pb); - - _block->start(_queue); + set_option(RS2_OPTION_COLOR_SCHEME, float(color_scheme)); } /** * Start to generate color image base on depth frame @@ -516,291 +718,332 @@ namespace rs2 */ video_frame colorize(frame depth) const { - if(depth) - { - _block->invoke(std::move(depth)); - rs2::frame f; - if (!_queue.poll_for_frame(&f)) - throw std::runtime_error("Error occured during execution of the processing block! See the log for more info"); - return video_frame(f); - } - return depth; + return process(depth); } - /** - * Same function as colorize(depth) - * \param[in] depth - depth frame to be processed to generate the color image - * \return video_frame - generated color image - */ - video_frame operator()(frame depth) const { return colorize(depth); } - private: - std::shared_ptr _block; - frame_queue _queue; - }; - - /** - Interface for frame processing functionality - */ - class process_interface : public options - { - public: - virtual rs2::frame process(rs2::frame frame) = 0; - virtual void operator()(frame f) const = 0; - virtual ~process_interface() = default; - }; + protected: + colorizer(std::shared_ptr block) : filter(block, 1) {} - class decimation_filter : public process_interface - { - public: - /** - * Create decimation filter processing block - * decimation filter performing downsampling by using the median with specific kernel size - */ - decimation_filter() :_queue(1) + private: + std::shared_ptr init() { rs2_error* e = nullptr; - auto pb = std::shared_ptr( - rs2_create_decimation_filter_block(&e), + auto block = std::shared_ptr( + rs2_create_colorizer(&e), rs2_delete_processing_block); - _block = std::make_shared(pb); error::handle(e); // Redirect options API to the processing block - options::operator=(pb); + //options::operator=(pb); - _block->start(_queue); + return block; } + }; + + class decimation_filter : public filter + { + public: /** - * process the frame AND return the result - * \param[in] frame - depth frame to be processed - * \return rs2::frame - filtered frame + * Create decimation filter + * Decimation filter performs downsampling by using the median with specific kernel size */ - rs2::frame process(rs2::frame frame) override - { - (*_block)(frame); - rs2::frame f; - if (!_queue.poll_for_frame(&f)) - throw std::runtime_error("Error occured during execution of the processing block! See the log for more info"); - return f; - } + decimation_filter() : filter(init(), 1) {} /** - * process the frame - * \param[in] frame - depth frame to be processed + * Create decimation filter + * Decimation filter performs downsampling by using the median with specific kernel size + * \param[in] magnitude - number of filter iterations. */ - void operator()(frame f) const override + decimation_filter(float magnitude) : filter(init(), 1) + { + set_option(RS2_OPTION_FILTER_MAGNITUDE, magnitude); + } + + decimation_filter(filter f) : filter(f) { - (*_block)(std::move(f)); + rs2_error* e = nullptr; + if (!rs2_is_processing_block_extendable_to(f.get(), RS2_EXTENSION_DECIMATION_FILTER, &e) && !e) + { + _block.reset(); + } + error::handle(e); } + private: friend class context; - std::shared_ptr _block; - frame_queue _queue; - }; - - class temporal_filter : public process_interface - { - public: - /** - * Create temporal filter processing block - * temporal filter smooth the image by calculating multiple frames with alpha and delta settings - * alpha defines the weight of current frame, delta defines threshold for edge classification and preserving. - * For more information, check the temporal-filter.cpp - */ - temporal_filter() :_queue(1) + std::shared_ptr init() { rs2_error* e = nullptr; - auto pb = std::shared_ptr( - rs2_create_temporal_filter_block(&e), + auto block = std::shared_ptr( + rs2_create_decimation_filter_block(&e), rs2_delete_processing_block); - _block = std::make_shared(pb); error::handle(e); // Redirect options API to the processing block - options::operator=(pb); + //options::operator=(this); - _block->start(_queue); + return block; } + }; + + class temporal_filter : public filter + { + public: /** - * process the frame AND return the result - * \param[in] frame - depth frame to be processed - * \return rs2::frame - filtered frame + * Create temporal filter with default settings + * Temporal filter smooths the image by calculating multiple frames with alpha and delta settings + * alpha defines the weight of current frame, and delta defines the threshold for edge classification and preserving. + * For more information, check the temporal-filter.cpp */ - rs2::frame process(rs2::frame frame) override - { - (*_block)(frame); - rs2::frame f; - if (!_queue.poll_for_frame(&f)) - throw std::runtime_error("Error occured during execution of the processing block! See the log for more info"); - return f; - } + temporal_filter() : filter(init(), 1) {} /** - * process the frame - * \param[in] frame - depth frame to be processed + * Create temporal filter with user settings + * Temporal filter smooths the image by calculating multiple frames with alpha and delta settings + * \param[in] smooth_alpha - defines the weight of current frame. + * \param[in] smooth_delta - delta defines the threshold for edge classification and preserving. + * \param[in] persistence_control - A set of predefined rules (masks) that govern when missing pixels will be replaced with the last valid value so that the data will remain persistent over time: + * 0 - Disabled - Persistency filter is not activated and no hole filling occurs. + * 1 - Valid in 8/8 - Persistency activated if the pixel was valid in 8 out of the last 8 frames + * 2 - Valid in 2/last 3 - Activated if the pixel was valid in two out of the last 3 frames + * 3 - Valid in 2/last 4 - Activated if the pixel was valid in two out of the last 4 frames + * 4 - Valid in 2/8 - Activated if the pixel was valid in two out of the last 8 frames + * 5 - Valid in 1/last 2 - Activated if the pixel was valid in one of the last two frames + * 6 - Valid in 1/last 5 - Activated if the pixel was valid in one out of the last 5 frames + * 7 - Valid in 1/last 8 - Activated if the pixel was valid in one out of the last 8 frames + * 8 - Persist Indefinitely - Persistency will be imposed regardless of the stored history(most aggressive filtering) + * For more information, check temporal-filter.cpp */ - void operator()(frame f) const override + temporal_filter(float smooth_alpha, float smooth_delta, int persistence_control) : filter(init(), 1) { - (*_block)(std::move(f)); + set_option(RS2_OPTION_HOLES_FILL, float(persistence_control)); + set_option(RS2_OPTION_FILTER_SMOOTH_ALPHA, float(smooth_alpha)); + set_option(RS2_OPTION_FILTER_SMOOTH_DELTA, float(smooth_delta)); + } + + temporal_filter(filter f) :filter(f) + { + rs2_error* e = nullptr; + if (!rs2_is_processing_block_extendable_to(f.get(), RS2_EXTENSION_TEMPORAL_FILTER, &e) && !e) + { + _block.reset(); + } + error::handle(e); } private: friend class context; - std::shared_ptr _block; - frame_queue _queue; + std::shared_ptr init() + { + rs2_error* e = nullptr; + auto block = std::shared_ptr( + rs2_create_temporal_filter_block(&e), + rs2_delete_processing_block); + error::handle(e); + + // Redirect options API to the processing block + //options::operator=(pb); + + return block; + } }; - class spatial_filter : public process_interface + class spatial_filter : public filter { public: /** - * Create spatial filter processing block - * spatial filter smooth the image by calculating frame with alpha and delta settings - * alpha defines he weight of the current pixel for smoothing is bounded within [25..100]%, + * Create spatial filter + * Spatial filter smooths the image by calculating frame with alpha and delta settings + * alpha defines the weight of the current pixel for smoothing, and is bounded within [25..100]%, * delta defines the depth gradient below which the smoothing will occur as number of depth levels * For more information, check the spatial-filter.cpp */ - spatial_filter() :_queue(1) + spatial_filter() : filter(init(), 1) { } + + /** + * Create spatial filter + * Spatial filter smooths the image by calculating frame with alpha and delta settings + * \param[in] smooth_alpha - defines the weight of the current pixel for smoothing is bounded within [25..100]% + * \param[in] smooth_delta - defines the depth gradient below which the smoothing will occur as number of depth levels + * \param[in] magnitude - number of filter iterations. + * \param[in] hole_fill - an in-place heuristic symmetric hole-filling mode applied horizontally during the filter passes. + * Intended to rectify minor artefacts with minimal performance impact + */ + spatial_filter(float smooth_alpha, float smooth_delta, float magnitude, float hole_fill) : filter(init(), 1) + { + set_option(RS2_OPTION_FILTER_SMOOTH_ALPHA, float(smooth_alpha)); + set_option(RS2_OPTION_FILTER_SMOOTH_DELTA, float(smooth_delta)); + set_option(RS2_OPTION_FILTER_MAGNITUDE, magnitude); + set_option(RS2_OPTION_HOLES_FILL, hole_fill); + } + + spatial_filter(filter f) :filter(f) { rs2_error* e = nullptr; - auto pb = std::shared_ptr( + if (!rs2_is_processing_block_extendable_to(f.get(), RS2_EXTENSION_SPATIAL_FILTER, &e) && !e) + { + _block.reset(); + } + error::handle(e); + } + private: + friend class context; + + std::shared_ptr init() + { + rs2_error* e = nullptr; + auto block = std::shared_ptr( rs2_create_spatial_filter_block(&e), rs2_delete_processing_block); - _block = std::make_shared(pb); error::handle(e); // Redirect options API to the processing block - options::operator=(pb); + //options::operator=(pb); - _block->start(_queue); + return block; } + }; + class disparity_transform : public filter + { + public: /** - * process the frame AND return the result - * \param[in] frame - depth frame to be processed - * \return rs2::frame - filtered frame + * Create disparity transform filter + * Converts from depth representation to disparity representation and vice-versa in depth frames */ - rs2::frame process(rs2::frame frame) override - { - (*_block)(frame); - rs2::frame f; - if (!_queue.poll_for_frame(&f)) - throw std::runtime_error("Error occured during execution of the processing block! See the log for more info"); - return f; - } + disparity_transform(bool transform_to_disparity = true) : filter(init(transform_to_disparity), 1) { } - /** - * process the frame - * \param[in] frame - depth frame to be processed - */ - void operator()(frame f) const override + disparity_transform(filter f) :filter(f) { - (*_block)(std::move(f)); + rs2_error* e = nullptr; + if (!rs2_is_processing_block_extendable_to(f.get(), RS2_EXTENSION_DISPARITY_FILTER, &e) && !e) + { + _block.reset(); + } + error::handle(e); } private: friend class context; + std::shared_ptr init(bool transform_to_disparity) + { + rs2_error* e = nullptr; + auto block = std::shared_ptr( + rs2_create_disparity_transform_block(uint8_t(transform_to_disparity), &e), + rs2_delete_processing_block); + error::handle(e); - std::shared_ptr _block; - frame_queue _queue; - }; + // Redirect options API to the processing block + //options::operator=(pb); - class disparity_transform : public process_interface + return block; + } + }; + + class zero_order_invalidation : public filter { public: /** - * Create disparity transform processing block - * the processing convert the depth and disparity from each pixel + * Create zero order fix filter + * The filter fixes the zero order artifact */ - disparity_transform(bool transform_to_disparity=true) :_queue(1) + zero_order_invalidation() : filter(init()) + {} + + zero_order_invalidation(filter f) :filter(f) { rs2_error* e = nullptr; - auto pb = std::shared_ptr( - rs2_create_disparity_transform_block(uint8_t(transform_to_disparity),&e), - rs2_delete_processing_block); - _block = std::make_shared(pb); + if (!rs2_is_processing_block_extendable_to(f.get(), RS2_EXTENSION_ZERO_ORDER_FILTER, &e) && !e) + { + _block.reset(); + } error::handle(e); + } - // Redirect options API to the processing block - options::operator=(pb); + private: + friend class context; - _block->start(_queue); + std::shared_ptr init() + { + rs2_error* e = nullptr; + auto block = std::shared_ptr( + rs2_create_zero_order_invalidation_block(&e), + rs2_delete_processing_block); + error::handle(e); + + return block; } + }; + class hole_filling_filter : public filter + { + public: /** - * process the frame AND return the result - * \param[in] frame - depth frame to be processed - * \return rs2::frame - filtered frame + * Create hole filling filter + * The processing performed depends on the selected hole filling mode. */ - rs2::frame process(rs2::frame frame) override - { - (*_block)(frame); - rs2::frame f; - if (!_queue.poll_for_frame(&f)) - throw std::runtime_error("Error occured during execution of the processing block! See the log for more info"); - return f; - } + hole_filling_filter() : filter(init(), 1) {} /** - * process the frame - * \param[in] frame - depth frame to be processed + * Create hole filling filter + * The processing performed depends on the selected hole filling mode. + * \param[in] mode - select the hole fill mode: + * 0 - fill_from_left - Use the value from the left neighbor pixel to fill the hole + * 1 - farest_from_around - Use the value from the neighboring pixel which is furthest away from the sensor + * 2 - nearest_from_around - - Use the value from the neighboring pixel closest to the sensor */ - void operator()(frame f) const override + hole_filling_filter(int mode) : filter(init(), 1) { - (*_block)(std::move(f)); + set_option(RS2_OPTION_HOLES_FILL, float(mode)); + } + + hole_filling_filter(filter f) :filter(f) + { + rs2_error* e = nullptr; + if (!rs2_is_processing_block_extendable_to(f.get(), RS2_EXTENSION_HOLE_FILLING_FILTER, &e) && !e) + { + _block.reset(); + } + error::handle(e); } private: friend class context; - std::shared_ptr _block; - frame_queue _queue; - }; - - class hole_filling_filter : public process_interface - { - public: - /** - * Create hole filling processing block - * the processing perform the hole filling base on different hole filling mode. - */ - hole_filling_filter() :_queue(1) + std::shared_ptr init() { rs2_error* e = nullptr; - auto pb = std::shared_ptr( + auto block = std::shared_ptr( rs2_create_hole_filling_filter_block(&e), rs2_delete_processing_block); - _block = std::make_shared(pb); error::handle(e); // Redirect options API to the processing block - options::operator=(pb); + //options::operator=(_block); - _block->start(_queue); - } - /** - * process the frame AND return the result - * \param[in] frame - depth frame to be processed - * \return rs2::frame - filtered frame - */ - rs2::frame process(rs2::frame frame) override - { - (*_block)(frame); - rs2::frame f; - if (!_queue.poll_for_frame(&f)) - throw std::runtime_error("Error occured during execution of the processing block! See the log for more info"); - return f; + return block; } + }; + + class rates_printer : public filter + { + public: /** - * process the frame - * \param[in] frame - depth frame to be processed + * Create hole filling processing block + * the processing perform the hole filling base on different hole filling mode. */ - void operator()(frame f) const override - { - (*_block)(std::move(f)); - } + rates_printer() : filter(init(), 1) {} + private: friend class context; - std::shared_ptr _block; - frame_queue _queue; + std::shared_ptr init() + { + rs2_error* e = nullptr; + auto block = std::shared_ptr( + rs2_create_rates_printer_block(&e), + rs2_delete_processing_block); + error::handle(e); + + return block; + } }; } #endif // LIBREALSENSE_RS2_PROCESSING_HPP diff --git a/libs/realsense2/include/librealsense2/hpp/rs_record_playback.hpp b/libs/realsense2/include/librealsense2/hpp/rs_record_playback.hpp index 8352023..1668ef9 100755 --- a/libs/realsense2/include/librealsense2/hpp/rs_record_playback.hpp +++ b/libs/realsense2/include/librealsense2/hpp/rs_record_playback.hpp @@ -145,7 +145,7 @@ namespace rs2 /** * Register to receive callback from playback device upon its status changes * - * Callbacks are invoked from the reading thread, any heavy processing in the callback handler will affect + * Callbacks are invoked from the reading thread, and as such any heavy processing in the callback handler will affect * the reading thread and may cause frame drops\ high latency * \param[in] callback A callback handler that will be invoked when the playback status changes, can be any callable object accepting rs2_playback_status */ @@ -210,15 +210,31 @@ namespace rs2 * \param[in] file The desired path to which the recorder should save the data * \param[in] device The device to record */ - recorder(const std::string& file, rs2::device device) + recorder(const std::string& file, rs2::device dev) { rs2_error* e = nullptr; _dev = std::shared_ptr( - rs2_create_record_device(device.get().get(), file.c_str(), &e), + rs2_create_record_device(dev.get().get(), file.c_str(), &e), rs2_delete_device); rs2::error::handle(e); } + /** + * Creates a recording device to record the given device and save it to the given file as rosbag format + * \param[in] file The desired path to which the recorder should save the data + * \param[in] device The device to record + * \param[in] compression_enabled Indicates if compression is enabled + */ + recorder(const std::string& file, rs2::device dev, bool compression_enabled) + { + rs2_error* e = nullptr; + _dev = std::shared_ptr( + rs2_create_record_device_ex(dev.get().get(), file.c_str(), compression_enabled, &e), + rs2_delete_device); + rs2::error::handle(e); + } + + /** * Pause the recording device without stopping the actual device from streaming. */ @@ -230,7 +246,7 @@ namespace rs2 } /** - * Unpauses the recording device, making it resume recording + * Unpauses the recording device, making it resume recording. */ void resume() { diff --git a/libs/realsense2/include/librealsense2/hpp/rs_sensor.hpp b/libs/realsense2/include/librealsense2/hpp/rs_sensor.hpp index 21e41ec..e72d569 100755 --- a/libs/realsense2/include/librealsense2/hpp/rs_sensor.hpp +++ b/libs/realsense2/include/librealsense2/hpp/rs_sensor.hpp @@ -6,24 +6,26 @@ #include "rs_types.hpp" #include "rs_frame.hpp" - +#include "rs_processing.hpp" +#include "rs_options.hpp" namespace rs2 { + class notification { public: - notification(rs2_notification* notification) + notification(rs2_notification* nt) { rs2_error* e = nullptr; - _description = rs2_get_notification_description(notification, &e); + _description = rs2_get_notification_description(nt, &e); error::handle(e); - _timestamp = rs2_get_notification_timestamp(notification, &e); + _timestamp = rs2_get_notification_timestamp(nt, &e); error::handle(e); - _severity = rs2_get_notification_severity(notification, &e); + _severity = rs2_get_notification_severity(nt, &e); error::handle(e); - _category = rs2_get_notification_category(notification, &e); + _category = rs2_get_notification_category(nt, &e); error::handle(e); - _serialized_data = rs2_get_notification_serialized_data(notification, &e); + _serialized_data = rs2_get_notification_serialized_data(nt, &e); error::handle(e); } @@ -96,138 +98,7 @@ namespace rs2 void release() override { delete this; } }; - template - class frame_callback : public rs2_frame_callback - { - T on_frame_function; - public: - explicit frame_callback(T on_frame) : on_frame_function(on_frame) {} - - void on_frame(rs2_frame* fref) override - { - on_frame_function(frame{ fref }); - } - - void release() override { delete this; } - }; - - class options - { - public: - /** - * check if particular option is supported - * \param[in] option option id to be checked - * \return true if option is supported - */ - bool supports(rs2_option option) const - { - rs2_error* e = nullptr; - auto res = rs2_supports_option(_options, option, &e); - error::handle(e); - return res > 0; - } - - /** - * get option description - * \param[in] option option id to be checked - * \return human-readable option description - */ - const char* get_option_description(rs2_option option) const - { - rs2_error* e = nullptr; - auto res = rs2_get_option_description(_options, option, &e); - error::handle(e); - return res; - } - - /** - * get option value description (in case specific option value hold special meaning) - * \param[in] option option id to be checked - * \param[in] val value of the option - * \return human-readable description of a specific value of an option or null if no special meaning - */ - const char* get_option_value_description(rs2_option option, float val) const - { - rs2_error* e = nullptr; - auto res = rs2_get_option_value_description(_options, option, val, &e); - error::handle(e); - return res; - } - /** - * read option's value - * \param[in] option option id to be queried - * \return value of the option - */ - float get_option(rs2_option option) const - { - rs2_error* e = nullptr; - auto res = rs2_get_option(_options, option, &e); - error::handle(e); - return res; - } - - /** - * retrieve the available range of values of a supported option - * \return option range containing minimum and maximum values, step and default value - */ - option_range get_option_range(rs2_option option) const - { - option_range result; - rs2_error* e = nullptr; - rs2_get_option_range(_options, option, - &result.min, &result.max, &result.step, &result.def, &e); - error::handle(e); - return result; - } - - /** - * write new value to the option - * \param[in] option option id to be queried - * \param[in] value new value for the option - */ - void set_option(rs2_option option, float value) const - { - rs2_error* e = nullptr; - rs2_set_option(_options, option, value, &e); - error::handle(e); - } - - /** - * check if particular option is read-only - * \param[in] option option id to be checked - * \return true if option is read-only - */ - bool is_option_read_only(rs2_option option) const - { - rs2_error* e = nullptr; - auto res = rs2_is_option_read_only(_options, option, &e); - error::handle(e); - return res > 0; - } - - options& operator=(const options& other) - { - _options = other._options; - return *this; - } - - virtual ~options() = default; - protected: - explicit options(rs2_options* o = nullptr) : _options(o) {} - - template - options& operator=(const T& dev) - { - _options = (rs2_options*)(dev.get()); - return *this; - } - - options(const options& other) : _options(other._options) {} - - private: - rs2_options* _options; - }; class sensor : public options { @@ -344,12 +215,12 @@ namespace rs2 /** - * check if physical sensor is supported - * \return list of stream profiles that given sensor can provide, should be released by rs2_delete_profiles_list + * Retrieves the list of stream profiles supported by the sensor. + * \return list of stream profiles that given sensor can provide */ std::vector get_stream_profiles() const { - std::vector results; + std::vector results{}; rs2_error* e = nullptr; std::shared_ptr list( @@ -370,6 +241,35 @@ namespace rs2 return results; } + /** + * get the recommended list of filters by the sensor + * \return list of filters that recommended by sensor + */ + std::vector get_recommended_filters() const + { + std::vector results{}; + + rs2_error* e = nullptr; + std::shared_ptr list( + rs2_get_recommended_processing_blocks(_sensor.get(), &e), + rs2_delete_recommended_processing_blocks); + error::handle(e); + + auto size = rs2_get_recommended_processing_blocks_count(list.get(), &e); + error::handle(e); + + for (auto i = 0; i < size; i++) + { + auto f = std::shared_ptr( + rs2_get_processing_block(list.get(), i, &e), + rs2_delete_processing_block); + error::handle(e); + results.push_back(f); + } + + return results; + } + sensor& operator=(const std::shared_ptr other) { options::operator=(other); @@ -411,6 +311,12 @@ namespace rs2 return extension; } + explicit sensor(std::shared_ptr dev) + :options((rs2_options*)dev.get()), _sensor(dev) + { + } + explicit operator std::shared_ptr() { return _sensor; } + protected: friend context; friend device_list; @@ -420,12 +326,15 @@ namespace rs2 std::shared_ptr _sensor; - explicit sensor(std::shared_ptr dev) - :options((rs2_options*)dev.get()), _sensor(dev) - { - } + }; + inline std::shared_ptr sensor_from_frame(frame f) + { + std::shared_ptr psens(f.get_sensor(), rs2_delete_sensor); + return std::make_shared(psens); + } + inline bool operator==(const sensor& lhs, const sensor& rhs) { if (!(lhs.supports(RS2_CAMERA_INFO_NAME) && lhs.supports(RS2_CAMERA_INFO_SERIAL_NUMBER) @@ -495,6 +404,7 @@ namespace rs2 } operator bool() const { return _sensor.get() != nullptr; } + explicit depth_sensor(std::shared_ptr dev) : depth_sensor(sensor(dev)) {} }; class depth_stereo_sensor : public depth_sensor @@ -510,18 +420,163 @@ namespace rs2 error::handle(e); } - /** Retrieves mapping between the units of the depth image and meters - * \return depth in meters corresponding to a depth value of 1 + /** + * Retrieve the stereoscopic baseline value from the sensor. */ float get_stereo_baseline() const { rs2_error* e = nullptr; - auto res = rs2_get_depth_scale(_sensor.get(), &e); + auto res = rs2_get_stereo_baseline(_sensor.get(), &e); error::handle(e); return res; } operator bool() const { return _sensor.get() != nullptr; } }; + + + class pose_sensor : public sensor + { + public: + pose_sensor(sensor s) + : sensor(s.get()) + { + rs2_error* e = nullptr; + if (rs2_is_sensor_extendable_to(_sensor.get(), RS2_EXTENSION_POSE_SENSOR, &e) == 0 && !e) + { + _sensor.reset(); + } + error::handle(e); + } + + /** + * Load relocalization map onto device. Only one relocalization map can be imported at a time; + * any previously existing map will be overwritten. + * The imported map exists simultaneously with the map created during the most tracking session after start(), + * and they are merged after the imported map is relocalized. + * This operation must be done before start(). + * \param[in] lmap_buf map data as a binary blob + * \return true if success + */ + bool import_localization_map(const std::vector& lmap_buf) const + { + rs2_error* e = nullptr; + auto res = rs2_import_localization_map(_sensor.get(), lmap_buf.data(), uint32_t(lmap_buf.size()), &e); + error::handle(e); + return !!res; + } + + /** + * Get relocalization map that is currently on device, created and updated during most recent tracking session. + * Can be called before or after stop(). + * \return map data as a binary blob + */ + std::vector export_localization_map() const + { + rs2_error* e = nullptr; + std::shared_ptr loc_map( + rs2_export_localization_map(_sensor.get(), &e), + rs2_delete_raw_data); + error::handle(e); + + auto start = rs2_get_raw_data(loc_map.get(), &e); + error::handle(e); + + std::vector results; + if (start) + { + auto size = rs2_get_raw_data_size(loc_map.get(), &e); + error::handle(e); + + results = std::vector(start, start + size); + } + return results; + } + + /** + * Creates a named virtual landmark in the current map, known as static node. + * The static node's pose is provided relative to the origin of current coordinate system of device poses. + * This function fails if the current tracker confidence is below 3 (high confidence). + * \param[in] guid unique name of the static node (limited to 127 chars). + * If a static node with the same name already exists in the current map or the imported map, the static node is overwritten. + * \param[in] pos position of the static node in the 3D space. + * \param[in] orient_quat orientation of the static node in the 3D space, represented by a unit quaternion. + * \return true if success. + */ + bool set_static_node(const std::string& guid, const rs2_vector& pos, const rs2_quaternion& orient) const + { + rs2_error* e = nullptr; + auto res = rs2_set_static_node(_sensor.get(), guid.c_str(), pos, orient, &e); + error::handle(e); + return !!res; + } + + + /** + * Gets the current pose of a static node that was created in the current map or in an imported map. + * Static nodes of imported maps are available after relocalizing the imported map. + * The static node's pose is returned relative to the current origin of coordinates of device poses. + * Thus, poses of static nodes of an imported map are consistent with current device poses after relocalization. + * This function fails if the current tracker confidence is below 3 (high confidence). + * \param[in] guid unique name of the static node (limited to 127 chars). + * \param[out] pos position of the static node in the 3D space. + * \param[out] orient_quat orientation of the static node in the 3D space, represented by a unit quaternion. + * \return true if success. + */ + bool get_static_node(const std::string& guid, rs2_vector& pos, rs2_quaternion& orient) const + { + rs2_error* e = nullptr; + auto res = rs2_get_static_node(_sensor.get(), guid.c_str(), &pos, &orient, &e); + error::handle(e); + return !!res; + } + + operator bool() const { return _sensor.get() != nullptr; } + explicit pose_sensor(std::shared_ptr dev) : pose_sensor(sensor(dev)) {} + }; + + class wheel_odometer : public sensor + { + public: + wheel_odometer(sensor s) + : sensor(s.get()) + { + rs2_error* e = nullptr; + if (rs2_is_sensor_extendable_to(_sensor.get(), RS2_EXTENSION_WHEEL_ODOMETER, &e) == 0 && !e) + { + _sensor.reset(); + } + error::handle(e); + } + + /** Load Wheel odometer settings from host to device + * \param[in] odometry_config_buf odometer configuration/calibration blob serialized from jsom file + * \return true on success + */ + bool load_wheel_odometery_config(const std::vector& odometry_config_buf) const + { + rs2_error* e = nullptr; + auto res = rs2_load_wheel_odometry_config(_sensor.get(), odometry_config_buf.data(), uint32_t(odometry_config_buf.size()), &e); + error::handle(e); + return !!res; + } + + /** Send wheel odometry data for each individual sensor (wheel) + * \param[in] wo_sensor_id - Zero-based index of (wheel) sensor with the same type within device + * \param[in] frame_num - Monotonocally increasing frame number, managed per sensor. + * \param[in] translational_velocity - Translational velocity in meter/sec + * \return true on success + */ + bool send_wheel_odometry(uint8_t wo_sensor_id, uint32_t frame_num, const rs2_vector& translational_velocity) + { + rs2_error* e = nullptr; + auto res = rs2_send_wheel_odometry(_sensor.get(), wo_sensor_id, frame_num, translational_velocity, &e); + error::handle(e); + return !!res; + } + + operator bool() const { return _sensor.get() != nullptr; } + explicit wheel_odometer(std::shared_ptr dev) : wheel_odometer(sensor(dev)) {} + }; } #endif // LIBREALSENSE_RS2_SENSOR_HPP diff --git a/libs/realsense2/include/librealsense2/hpp/rs_types.hpp b/libs/realsense2/include/librealsense2/hpp/rs_types.hpp index cf6fe84..9acaee0 100755 --- a/libs/realsense2/include/librealsense2/hpp/rs_types.hpp +++ b/libs/realsense2/include/librealsense2/hpp/rs_types.hpp @@ -64,6 +64,13 @@ struct rs2_playback_status_changed_callback virtual ~rs2_playback_status_changed_callback() {} }; +struct rs2_update_progress_callback +{ + virtual void on_update_progress(const float update_progress) = 0; + virtual void release() = 0; + virtual ~rs2_update_progress_callback() {} +}; + namespace rs2 { class error : public std::runtime_error @@ -167,4 +174,7 @@ namespace rs2 }; } +inline std::ostream & operator << (std::ostream & o, rs2_vector v) { return o << v.x << ", " << v.y << ", " << v.z; } +inline std::ostream & operator << (std::ostream & o, rs2_quaternion q) { return o << q.x << ", " << q.y << ", " << q.z << ", " << q.w; } + #endif // LIBREALSENSE_RS2_TYPES_HPP diff --git a/libs/realsense2/include/librealsense2/rs.h b/libs/realsense2/include/librealsense2/rs.h index 1cebc0d..4aac425 100755 --- a/libs/realsense2/include/librealsense2/rs.h +++ b/libs/realsense2/include/librealsense2/rs.h @@ -23,12 +23,16 @@ extern "C" { #include "h/rs_sensor.h" #define RS2_API_MAJOR_VERSION 2 -#define RS2_API_MINOR_VERSION 14 +#define RS2_API_MINOR_VERSION 30 #define RS2_API_PATCH_VERSION 0 #define RS2_API_BUILD_VERSION 0 +#ifndef STRINGIFY #define STRINGIFY(arg) #arg +#endif +#ifndef VAR_ARG_STRING #define VAR_ARG_STRING(arg) STRINGIFY(arg) +#endif /* Versioning rules : For each release at least one of [MJR/MNR/PTCH] triple is promoted */ /* : Versions that differ by RS2_API_PATCH_VERSION only are interface-compatible, i.e. no user-code changes required */ diff --git a/libs/realsense2/include/librealsense2/rs.hpp b/libs/realsense2/include/librealsense2/rs.hpp index 4b58f1a..151133d 100755 --- a/libs/realsense2/include/librealsense2/rs.hpp +++ b/libs/realsense2/include/librealsense2/rs.hpp @@ -41,7 +41,7 @@ namespace rs2 inline std::ostream & operator << (std::ostream & o, rs2_stream stream) { return o << rs2_stream_to_string(stream); } inline std::ostream & operator << (std::ostream & o, rs2_format format) { return o << rs2_format_to_string(format); } inline std::ostream & operator << (std::ostream & o, rs2_distortion distortion) { return o << rs2_distortion_to_string(distortion); } -inline std::ostream & operator << (std::ostream & o, rs2_option option) { return o << rs2_option_to_string(option); } +inline std::ostream & operator << (std::ostream & o, rs2_option option) { return o << rs2_option_to_string(option); } // This function is being deprecated. For existing options it will return option name, but for future API additions the user should call rs2_get_option_name instead. inline std::ostream & operator << (std::ostream & o, rs2_log_severity severity) { return o << rs2_log_severity_to_string(severity); } inline std::ostream & operator << (std::ostream & o, rs2_camera_info camera_info) { return o << rs2_camera_info_to_string(camera_info); } inline std::ostream & operator << (std::ostream & o, rs2_frame_metadata_value metadata) { return o << rs2_frame_metadata_to_string(metadata); } diff --git a/libs/realsense2/include/librealsense2/rs_advanced_mode.h b/libs/realsense2/include/librealsense2/rs_advanced_mode.h index 0849257..6954ccc 100755 --- a/libs/realsense2/include/librealsense2/rs_advanced_mode.h +++ b/libs/realsense2/include/librealsense2/rs_advanced_mode.h @@ -88,6 +88,11 @@ void rs2_set_census(rs2_device* dev, const STCensusRadius* group, rs2_error** e void rs2_get_census(rs2_device* dev, STCensusRadius* group, int mode, rs2_error** error); +void rs2_set_amp_factor(rs2_device* dev, const STAFactor* group, rs2_error** error); + +/* Gets new values for STAFactor, returns 0 if success */ +void rs2_get_amp_factor(rs2_device* dev, STAFactor* group, int mode, rs2_error** error); + /* Load JSON and apply advanced-mode controls, returns 0 if success */ void rs2_load_json(rs2_device* dev, const void* json_content, unsigned content_size, rs2_error** error); diff --git a/libs/realsense2/include/librealsense2/rs_advanced_mode.hpp b/libs/realsense2/include/librealsense2/rs_advanced_mode.hpp index 4570755..154d4db 100755 --- a/libs/realsense2/include/librealsense2/rs_advanced_mode.hpp +++ b/libs/realsense2/include/librealsense2/rs_advanced_mode.hpp @@ -4,6 +4,7 @@ #ifndef R4XX_ADVANCED_MODE_HPP #define R4XX_ADVANCED_MODE_HPP +#include #include "rs.hpp" #include "rs_advanced_mode.h" @@ -244,6 +245,23 @@ namespace rs400 return group; } + void set_amp_factor(const STAFactor& group) + { + rs2_error* e = nullptr; + rs2_set_amp_factor(_dev.get(), &group, &e); + rs2::error::handle(e); + } + + STAFactor get_amp_factor(int mode = 0) const + { + rs2_error* e = nullptr; + STAFactor group{}; + rs2_get_amp_factor(_dev.get(), &group, mode, &e); + rs2::error::handle(e); + + return group; + } + std::string serialize_json() const { std::string results; @@ -389,5 +407,10 @@ inline bool operator==(const STCensusRadius& a, const STCensusRadius& b) a.vDiameter == b.vDiameter); } +inline bool operator==(const STAFactor& a, const STAFactor& b) +{ + return (fabs(a.amplitude - b.amplitude) < std::numeric_limits::epsilon()); +} + #endif // R4XX_ADVANCED_MODE_HPP diff --git a/libs/realsense2/include/librealsense2/rsutil.h b/libs/realsense2/include/librealsense2/rsutil.h index e6218b1..cb64a69 100755 --- a/libs/realsense2/include/librealsense2/rsutil.h +++ b/libs/realsense2/include/librealsense2/rsutil.h @@ -6,19 +6,22 @@ #include "h/rs_types.h" #include "h/rs_sensor.h" +#include "h/rs_frame.h" +#include "rs.h" #include "assert.h" - +#include +#include +#include #include - +#include /* Given a point in 3D space, compute the corresponding pixel coordinates in an image with no distortion or forward distortion coefficients produced by the same camera */ static void rs2_project_point_to_pixel(float pixel[2], const struct rs2_intrinsics * intrin, const float point[3]) { - //assert(intrin->model != RS2_DISTORTION_INVERSE_BROWN_CONRADY); // Cannot project to an inverse-distorted image - float x = point[0] / point[2], y = point[1] / point[2]; - if(intrin->model == RS2_DISTORTION_MODIFIED_BROWN_CONRADY) + if ((intrin->model == RS2_DISTORTION_MODIFIED_BROWN_CONRADY) || + (intrin->model == RS2_DISTORTION_INVERSE_BROWN_CONRADY)) { float r2 = x*x + y*y; @@ -33,10 +36,28 @@ static void rs2_project_point_to_pixel(float pixel[2], const struct rs2_intrinsi if (intrin->model == RS2_DISTORTION_FTHETA) { float r = sqrtf(x*x + y*y); + if (r < FLT_EPSILON) + { + r = FLT_EPSILON; + } float rd = (float)(1.0f / intrin->coeffs[0] * atan(2 * r* tan(intrin->coeffs[0] / 2.0f))); x *= rd / r; y *= rd / r; } + if (intrin->model == RS2_DISTORTION_KANNALA_BRANDT4) + { + float r = sqrtf(x*x + y*y); + if (r < FLT_EPSILON) + { + r = FLT_EPSILON; + } + float theta = atan(r); + float theta2 = theta*theta; + float series = 1 + theta2*(intrin->coeffs[0] + theta2*(intrin->coeffs[1] + theta2*(intrin->coeffs[2] + theta2*intrin->coeffs[3]))); + float rd = theta*series; + x *= rd / r; + y *= rd / r; + } pixel[0] = x * intrin->fx + intrin->ppx; pixel[1] = y * intrin->fy + intrin->ppy; @@ -46,7 +67,6 @@ static void rs2_project_point_to_pixel(float pixel[2], const struct rs2_intrinsi static void rs2_deproject_pixel_to_point(float point[3], const struct rs2_intrinsics * intrin, const float pixel[2], float depth) { assert(intrin->model != RS2_DISTORTION_MODIFIED_BROWN_CONRADY); // Cannot deproject from a forward-distorted image - assert(intrin->model != RS2_DISTORTION_FTHETA); // Cannot deproject to an ftheta image //assert(intrin->model != RS2_DISTORTION_BROWN_CONRADY); // Cannot deproject to an brown conrady model float x = (pixel[0] - intrin->ppx) / intrin->fx; @@ -60,6 +80,43 @@ static void rs2_deproject_pixel_to_point(float point[3], const struct rs2_intrin x = ux; y = uy; } + if (intrin->model == RS2_DISTORTION_KANNALA_BRANDT4) + { + float rd = sqrtf(x*x + y*y); + if (rd < FLT_EPSILON) + { + rd = FLT_EPSILON; + } + + float theta = rd; + float theta2 = rd*rd; + for (int i = 0; i < 4; i++) + { + float f = theta*(1 + theta2*(intrin->coeffs[0] + theta2*(intrin->coeffs[1] + theta2*(intrin->coeffs[2] + theta2*intrin->coeffs[3])))) - rd; + if (abs(f) < FLT_EPSILON) + { + break; + } + float df = 1 + theta2*(3 * intrin->coeffs[0] + theta2*(5 * intrin->coeffs[1] + theta2*(7 * intrin->coeffs[2] + 9 * theta2*intrin->coeffs[3]))); + theta -= f / df; + theta2 = theta*theta; + } + float r = tan(theta); + x *= r / rd; + y *= r / rd; + } + if (intrin->model == RS2_DISTORTION_FTHETA) + { + float rd = sqrtf(x*x + y*y); + if (rd < FLT_EPSILON) + { + rd = FLT_EPSILON; + } + float r = (float)(tan(intrin->coeffs[0] * rd) / atan(2 * tan(intrin->coeffs[0] / 2.0f))); + x *= r / rd; + y *= r / rd; + } + point[0] = depth * x; point[1] = depth * y; point[2] = depth; @@ -80,4 +137,80 @@ static void rs2_fov(const struct rs2_intrinsics * intrin, float to_fov[2]) to_fov[1] = (atan2f(intrin->ppy + 0.5f, intrin->fy) + atan2f(intrin->height - (intrin->ppy + 0.5f), intrin->fy)) * 57.2957795f; } +static void next_pixel_in_line(float curr[2], const float start[2], const float end[2]) +{ + float line_slope = (end[1] - start[1]) / (end[0] - start[0]); + if (fabs(end[0] - curr[0]) > fabs(end[1] - curr[1])) + { + curr[0] = end[0] > curr[0] ? curr[0] + 1 : curr[0] - 1; + curr[1] = end[1] - line_slope * (end[0] - curr[0]); + } + else + { + curr[1] = end[1] > curr[1] ? curr[1] + 1 : curr[1] - 1; + curr[0] = end[0] - ((end[1] + curr[1]) / line_slope); + } +} + +static bool is_pixel_in_line(const float curr[2], const float start[2], const float end[2]) +{ + return ((end[0] >= start[0] && end[0] >= curr[0] && curr[0] >= start[0]) || (end[0] <= start[0] && end[0] <= curr[0] && curr[0] <= start[0])) && + ((end[1] >= start[1] && end[1] >= curr[1] && curr[1] >= start[1]) || (end[1] <= start[1] && end[1] <= curr[1] && curr[1] <= start[1])); +} + +static void adjust_2D_point_to_boundary(float p[2], int width, int height) +{ + if (p[0] < 0) p[0] = 0; + if (p[0] > width) p[0] = (float)width; + if (p[1] < 0) p[1] = 0; + if (p[1] > height) p[1] = (float)height; +} + +/* Find projected pixel with unknown depth search along line. */ +static void rs2_project_color_pixel_to_depth_pixel(float to_pixel[2], + const uint16_t* data, float depth_scale, + float depth_min, float depth_max, + const struct rs2_intrinsics* depth_intrin, + const struct rs2_intrinsics* color_intrin, + const struct rs2_extrinsics* color_to_depth, + const struct rs2_extrinsics* depth_to_color, + const float from_pixel[2]) +{ + //Find line start pixel + float start_pixel[2] = { 0 }, min_point[3] = { 0 }, min_transformed_point[3] = { 0 }; + rs2_deproject_pixel_to_point(min_point, color_intrin, from_pixel, depth_min); + rs2_transform_point_to_point(min_transformed_point, color_to_depth, min_point); + rs2_project_point_to_pixel(start_pixel, depth_intrin, min_transformed_point); + adjust_2D_point_to_boundary(start_pixel, depth_intrin->width, depth_intrin->height); + + //Find line end depth pixel + float end_pixel[2] = { 0 }, max_point[3] = { 0 }, max_transformed_point[3] = { 0 }; + rs2_deproject_pixel_to_point(max_point, color_intrin, from_pixel, depth_max); + rs2_transform_point_to_point(max_transformed_point, color_to_depth, max_point); + rs2_project_point_to_pixel(end_pixel, depth_intrin, max_transformed_point); + adjust_2D_point_to_boundary(end_pixel, depth_intrin->width, depth_intrin->height); + + //search along line for the depth pixel that it's projected pixel is the closest to the input pixel + float min_dist = -1; + for (float p[2] = { start_pixel[0], start_pixel[1] }; is_pixel_in_line(p, start_pixel, end_pixel); next_pixel_in_line(p, start_pixel, end_pixel)) + { + float depth = depth_scale * data[(int)p[1] * depth_intrin->width + (int)p[0]]; + if (depth == 0) + continue; + + float projected_pixel[2] = { 0 }, point[3] = { 0 }, transformed_point[3] = { 0 }; + rs2_deproject_pixel_to_point(point, depth_intrin, p, depth); + rs2_transform_point_to_point(transformed_point, depth_to_color, point); + rs2_project_point_to_pixel(projected_pixel, color_intrin, transformed_point); + + float new_dist = pow((projected_pixel[1] - from_pixel[1]), 2) + pow((projected_pixel[0] - from_pixel[0]), 2); + if (new_dist < min_dist || min_dist < 0) + { + min_dist = new_dist; + to_pixel[0] = p[0]; + to_pixel[1] = p[1]; + } + } +} + #endif