diff --git a/README.md b/README.md index 2d30095..76ee3c8 100644 --- a/README.md +++ b/README.md @@ -5,14 +5,14 @@ [![Build status](https://ci.appveyor.com/api/projects/status/iolvq2tckcgdcdrp?svg=true)](https://ci.appveyor.com/project/hiroMTB/ofxrealsense2) # ofxRealsense2 -This repos is openFrameworks addon for [Intel® RealSense™ SDK 2.0](https://github.com/IntelRealSense/librealsense). You can test your D400 series camera quickly. If you dont have device, you cann still playback BAG files and see how it works (for example performance, postprocessing, depth quality, etc) +This repos is openFrameworks addon for [Intel® RealSense™ SDK 2.0](https://github.com/IntelRealSense/librealsense), specifically the D435i. You can test your D400 series camera quickly. If you dont have device, you can still playback BAG files and see how it works (for example performance, postprocessing, depth quality, etc). ## Development period -- 2018.7 ~ active +- 2019.5 ~ active ## Version -- Realsense 2.14.1 (released on 2018.7, this is not latest) +- Realsense 2.2.22 (released on 2019.01, the latest as of May 2019) - libusb 1.0.22 - openFrameworks 0.10.0, 0.10.1 @@ -25,15 +25,28 @@ This repos is openFrameworks addon for [Intel® RealSense™ SDK 2.0](https://gi - [x] add bag file playback example ## Install Realsense SDK -Follow the official instalaction [here](https://realsense.intel.com/sdk-2/) and check you can launch realsense viewer. +Follow the official installation [here](https://realsense.intel.com/sdk-2/) and check you can launch realsense viewer. +OR : +using brew : +``` +brew install libusb pkg-config +brew install homebrew/core/glfw3 +brew install cmake +brew install librealsense -## Using oF Poroject Generator +#all of these things should now be visible in /usr/local/lib +#after brew installing librealsense you should be able to immediately type realsense-viewer into the terminal and see the viewer + +``` + + +## Using oF Project Generator This repo does not contain any project file. Please generate project file by yourself. -Project Generator needs addon_config.make for setting library properly. This repo contain follwing two .make. Please rename your favorite one to addon_config.make. +Project Generator needs addon_config.make for setting library properly. This repo contain following two .make. Please rename your favorite one to addon_config.make. - addon_config_shared.make : Generate project file which use shared library(.dylib, .dll + .lib) -- addon_config_static.make : Generate project file which use static library(.a, .lib). +- addon_config_static.make : Generate project file which use static library(.a, .lib). ## Static library vs Shared library @@ -59,8 +72,8 @@ With Realsense Viewer you can record/playback depth & color stream to bag file. ## Hardware - Sometimes I experienced collapesed data stream when I use USB 3.0 extension cable from D435 camera. Unplug and plug camera again if you see strange data. -- The quality of depth data from D400 series is depends on parameter of postprocessing. I recommend to check out [this PDF article](https://realsense.intel.com/wp-content/uploads/sites/63/BKM-For-Tuning-D435-and-D415-Cameras-Webinar_Rev3.pdf) and test with Realsense Viewer. +- The quality of depth data from D400 series is depends on parameter of postprocessing. I recommend to check out [this PDF article](https://realsense.intel.com/wp-content/uploads/sites/63/BKM-For-Tuning-D435-and-D415-Cameras-Webinar_Rev3.pdf) and test with Realsense Viewer. ## Notice ### libusb in osx -- libusb is NOT included in this repo. Should be installed to your system with 'brew install libusb' at first SDK install step. \ No newline at end of file +- libusb is NOT included in this repo. Should be installed to your system with 'brew install libusb' at first SDK install step. diff --git a/exampleLiveCamera/exampleLiveCamera.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/exampleLiveCamera/exampleLiveCamera.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings new file mode 100644 index 0000000..949b678 --- /dev/null +++ b/exampleLiveCamera/exampleLiveCamera.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -0,0 +1,8 @@ + + + + + BuildSystemType + Original + + diff --git a/exampleLiveCamera/src/ofApp.cpp b/exampleLiveCamera/src/ofApp.cpp index 3eae946..c45e54f 100755 --- a/exampleLiveCamera/src/ofApp.cpp +++ b/exampleLiveCamera/src/ofApp.cpp @@ -9,18 +9,29 @@ void ofApp::setup(){ // if you see app crash at runtime, please check, // 1. Copy Intel.Realsense.dll and realsense2.dll in to /bin? // 2. Unplug and re-connect Realsense camera and restart app. - pipe.start(); + cfg.enable_stream(RS2_STREAM_DEPTH); + cfg.enable_stream(RS2_STREAM_COLOR); + pipe.start(cfg); } void ofApp::update(){ // Get depth data from camera - auto frames = pipe.wait_for_frames(); + rs2::frameset frames = pipe.wait_for_frames(); + + rs2::align align_to_color(RS2_STREAM_COLOR); + frames = align_to_color.process(frames); + auto depth = frames.get_depth_frame(); + auto color = frames.get_color_frame(); + pc.map_to(color); points = pc.calculate(depth); + textureImg.setFromPixels((const unsigned char*) color.get_data(), color.get_width(), color.get_height(), OF_IMAGE_COLOR); + // Create oF mesh mesh.clear(); + mesh.setMode(OF_PRIMITIVE_POINTS); int n = points.size(); if(n!=0){ const rs2::vertex * vs = points.get_vertices(); @@ -29,7 +40,13 @@ void ofApp::update(){ const rs2::vertex v = vs[i]; glm::vec3 v3(v.x,v.y,v.z); mesh.addVertex(v3); - mesh.addColor(ofFloatColor(0,0,ofMap(v.z, 2, 6, 1, 0), 0.8)); + + float red = (float)(textureImg.getPixels()[i * 3]); + float green = (float)(textureImg.getPixels()[(i * 3) + 1]); + float blue = (float)(textureImg.getPixels()[(i * 3) + 2]); + ofColor c = ofColor({red,green,blue}); + + mesh.addColor(c); } } } @@ -50,7 +67,7 @@ void ofApp::draw(){ ofDrawGridPlane(1, 5, true); ofPopMatrix(); - mesh.drawVertices(); + mesh.draw(); cam.end(); } diff --git a/exampleLiveCamera/src/ofApp.h b/exampleLiveCamera/src/ofApp.h index 875d7ef..71ebdb9 100755 --- a/exampleLiveCamera/src/ofApp.h +++ b/exampleLiveCamera/src/ofApp.h @@ -11,11 +11,17 @@ class ofApp : public ofBaseApp{ rs2::pipeline pipe; rs2::device device; + rs2::config cfg; + rs2::points points; rs2::pointcloud pc; + const rs2::texture_coordinate* texCoord; + rs2::frame colorFrame; + ofVboMesh mesh; ofEasyCam cam; + ofImage textureImg; }; diff --git a/examplePlayback/examplePlayback.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/examplePlayback/examplePlayback.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings new file mode 100644 index 0000000..949b678 --- /dev/null +++ b/examplePlayback/examplePlayback.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -0,0 +1,8 @@ + + + + + BuildSystemType + Original + + diff --git a/libs/realsense2/include/librealsense2/h/rs_advanced_mode_command.h b/libs/realsense2/include/librealsense2/h/rs_advanced_mode_command.h old mode 100755 new mode 100644 index eead854..ce8b462 --- 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 old mode 100755 new mode 100644 index 52718f3..cd316cd --- 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 old mode 100755 new mode 100644 index 5ef5de3..3ed6031 --- a/libs/realsense2/include/librealsense2/h/rs_device.h +++ b/libs/realsense2/include/librealsense2/h/rs_device.h @@ -146,6 +146,275 @@ 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); + +/** +* This will improve the depth noise. +* \param[in] json_content Json string to configure speed on chip calibration parameters: + { + "speed": 3, + "scan parameter": 0, + "data sampling": 0 + } + speed - value can be one of: Very fast = 0, Fast = 1, Medium = 2, Slow = 3, White wall = 4, default is Slow + scan_parameter - value can be one of: Py scan (default) = 0, Rx scan = 1 + data_sampling - value can be one of:polling data sampling = 0, interrupt data sampling = 1 + if json is nullptr it will be ignored and calibration will use the default parameters +* \param[out] health Calibration Health-Check captures how far camera calibration is from the optimal one + [0, 0.25) - Good + [0.25, 0.75) - Can be Improved + [0.75, ) - Requires Calibration +* \param[in] callback Optional callback to get progress notifications +* \param[in] timeout_ms Timeout in ms (use 5000 msec unless instructed otherwise) +* \return New calibration table +*/ +const rs2_raw_data_buffer* rs2_run_on_chip_calibration_cpp(rs2_device* device, const void* json_content, int content_size, float* health, rs2_update_progress_callback* progress_callback, int timeout_ms, rs2_error** error); + +/** +* This will improve the depth noise. +* \param[in] json_content Json string to configure speed on chip calibration parameters: + { + "speed": 3, + "scan parameter": 0, + "data sampling": 0 + } + speed - value can be one of: Very fast = 0, Fast = 1, Medium = 2, Slow = 3, White wall = 4, default is Slow + scan_parameter - value can be one of: Py scan (default) = 0, Rx scan = 1 + data_sampling - value can be one of:polling data sampling = 0, interrupt data sampling = 1 + if json is nullptr it will be ignored and calibration will use the default parameters +* \param[out] health Calibration Health-Check captures how far camera calibration is from the optimal one + [0, 0.25) - Good + [0.25, 0.75) - Can be Improved + [0.75, ) - Requires Calibration +* \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] timeout_ms Timeout in ms (use 5000 msec unless instructed otherwise) +* \return New calibration table +*/ +const rs2_raw_data_buffer* rs2_run_on_chip_calibration(rs2_device* device, const void* json_content, int content_size, float* health, rs2_update_progress_callback_ptr callback, void* client_data, int timeout_ms, rs2_error** error); + +/** +* This will adjust camera absolute distance to flat target. User needs to enter the known ground truth. +* \param[in] ground_truth_mm Ground truth in mm must be between 2500 - 2000000 +* \param[in] json_content Json string to configure tare calibration parameters: + { + "average step count": 20, + "step count": 20, + "accuracy": 2, + "scan parameter": 0, + "data sampling": 0 + } + average step count - number of frames to average, must be between 1 - 30, default = 20 + step count - max iteration steps, must be between 5 - 30, default = 10 + accuracy - Subpixel accuracy level, value can be one of: Very high = 0 (0.025%), High = 1 (0.05%), Medium = 2 (0.1%), Low = 3 (0.2%), Default = Very high (0.025%), default is very high (0.025%) + scan_parameter - value can be one of: Py scan (default) = 0, Rx scan = 1 + data_sampling - value can be one of:polling data sampling = 0, interrupt data sampling = 1 + if json is nullptr it will be ignored and calibration will use the default parameters +* \param[in] content_size Json string size if its 0 the json will be ignored and calibration will use the default parameters +* \param[in] callback Optional callback to get progress notifications +* \param[in] timeout_ms Timeout in ms (use 5000 msec unless instructed otherwise) +* \return New calibration table +*/ +const rs2_raw_data_buffer* rs2_run_tare_calibration_cpp(rs2_device* dev, float ground_truth_mm, const void* json_content, int content_size, rs2_update_progress_callback* progress_callback, int timeout_ms, rs2_error** error); + + +/** + * Used in device_calibration; enumerates the different calibration types + * available for that extension. + */ +typedef enum rs2_calibration_type +{ + RS2_CALIBRATION_DEPTH_TO_RGB, + RS2_CALIBRATION_TYPE_COUNT +} rs2_calibration_type; +const char* rs2_calibration_type_to_string( rs2_calibration_type ); + +/** + * Used in device_calibration with rs2_calibration_change_callback + */ +typedef enum rs2_calibration_status +{ + // Anything >= 0 is not an issue + RS2_CALIBRATION_SPECIAL_FRAME = 0, // Special frame received; expect a frame-drop! + RS2_CALIBRATION_STARTED = 1, // Have all frames in hand; starting processing + RS2_CALIBRATION_NOT_NEEDED = 2, // Finished; existing calibration within tolerances; nothing done! + RS2_CALIBRATION_SUCCESSFUL = 3, // Finished; have new calibration in-hand + + RS2_CALIBRATION_RETRY = -1, // Initiating retry (asked for a new special frame) + RS2_CALIBRATION_FAILED = -2, + RS2_CALIBRATION_SCENE_INVALID = -3, // Scene was not good enough for calibration; will retry + RS2_CALIBRATION_BAD_RESULT = -4, // Calibration finished, but results aren't good; will retry + + RS2_CALIBRATION_STATUS_FIRST = -4, + RS2_CALIBRATION_STATUS_LAST = 3, + RS2_CALIBRATION_STATUS_COUNT = RS2_CALIBRATION_STATUS_LAST - RS2_CALIBRATION_STATUS_FIRST + 1, +} rs2_calibration_status; +const char* rs2_calibration_status_to_string( rs2_calibration_status ); + +typedef struct rs2_calibration_change_callback rs2_calibration_change_callback; +typedef void (*rs2_calibration_change_callback_ptr)(rs2_calibration_status, void* arg); + +/** + * Adds a callback for a sensor that gets called when calibration (intrinsics) changes, e.g. due to auto-calibration + * \param[in] sensor the sensor + * \param[in] callback the C callback function that gets called + * \param[in] user user argument that gets passed to the callback function + * \param[out] error if non-null, receives any error that occurs during this call, otherwise, errors are ignored + */ +void rs2_register_calibration_change_callback( rs2_device* dev, rs2_calibration_change_callback_ptr callback, void* user, rs2_error** error ); + +/** + * Adds a callback for a sensor that gets called when calibration (intrinsics) changes, e.g. due to auto-calibration + * \param[in] sensor the sensor + * \param[in] callback the C++ callback interface that gets called + * \param[out] error if non-null, receives any error that occurs during this call, otherwise, errors are ignored + */ +void rs2_register_calibration_change_callback_cpp( rs2_device* dev, rs2_calibration_change_callback* callback, rs2_error** error ); + +/** + * Triggers calibration of the given type + * \param[in] dev the device + * \param[in] type the type of calibration requested + * \param[out] error if non-null, receives any error that occurs during this call, otherwise, errors are ignored + */ +void rs2_trigger_device_calibration( rs2_device* dev, rs2_calibration_type type, rs2_error** error ); + +/** +* This will adjust camera absolute distance to flat target. User needs to enter the known ground truth. +* \param[in] ground_truth_mm Ground truth in mm must be between 2500 - 2000000 +* \param[in] json_content Json string to configure tare calibration parameters: + { + "average_step_count": 20, + "step count": 20, + "accuracy": 2, + "scan parameter": 0, + "data sampling": 0 + } + average step count - number of frames to average, must be between 1 - 30, default = 20 + step count - max iteration steps, must be between 5 - 30, default = 10 + accuracy - Subpixel accuracy level, value can be one of: Very high = 0 (0.025%), High = 1 (0.05%), Medium = 2 (0.1%), Low = 3 (0.2%), Default = Very high (0.025%), default is very high (0.025%) + scan_parameter - value can be one of: Py scan (default) = 0, Rx scan = 1 + data_sampling - value can be one of:polling data sampling = 0, interrupt data sampling = 1 + if json is nullptr it will be ignored and calibration will use the default parameters +* \param[in] content_size Json string size if its 0 the json will be ignored and calibration will use the default parameters +* \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] timeout_ms Timeout in ms (use 5000 msec unless instructed otherwise) +* \return New calibration table +*/ +const rs2_raw_data_buffer* rs2_run_tare_calibration(rs2_device* dev, float ground_truth_mm, const void* json_content, int content_size, rs2_update_progress_callback_ptr callback, void* client_data, int timeout_ms, rs2_error** error); + +/** +* Read current calibration table from flash. +* \return Calibration table +*/ +const rs2_raw_data_buffer* rs2_get_calibration_table(const rs2_device* dev, rs2_error** error); + +/** +* Set current table to dynamic area. +* \param[in] Calibration table +*/ +void rs2_set_calibration_table(const rs2_device* device, const void* calibration, int calibration_size, rs2_error** error); + +/* Serialize JSON content, returns ASCII-serialized JSON string on success. otherwise nullptr */ +rs2_raw_data_buffer* rs2_serialize_json(rs2_device* dev, rs2_error** error); + +/* Load JSON and apply advanced-mode controls */ +void rs2_load_json(rs2_device* dev, const void* json_content, unsigned content_size, 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 old mode 100755 new mode 100644 index c346d24..f507362 --- 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. deprecated, replaced by RS2_FRAME_METADATA_FRAME_EMITTER_MODE*/ 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. */ @@ -57,49 +58,14 @@ typedef enum rs2_frame_metadata_value RS2_FRAME_METADATA_MANUAL_WHITE_BALANCE , /**< Color image white balance. */ RS2_FRAME_METADATA_POWER_LINE_FREQUENCY , /**< Power Line Frequency for anti-flickering Off/50Hz/60Hz/Auto. */ RS2_FRAME_METADATA_LOW_LIGHT_COMPENSATION , /**< Color lowlight compensation. Zero corresponds to switched off. */ + RS2_FRAME_METADATA_FRAME_EMITTER_MODE , /**< Emitter mode: 0 - all emitters disabled. 1 - laser enabled. 2 - auto laser enabled (opt). 3 - LED enabled (opt).*/ + RS2_FRAME_METADATA_FRAME_LED_POWER , /**< Led power value 0-360. */ + RS2_FRAME_METADATA_RAW_FRAME_SIZE , /**< The number of transmitted payload bytes, not including metadata */ RS2_FRAME_METADATA_COUNT } 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 +102,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 +118,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 @@ -168,6 +150,12 @@ int rs2_get_frame_width(const rs2_frame* frame, rs2_error** error); */ int rs2_get_frame_height(const rs2_frame* frame, rs2_error** error); +/** +* retrieve the scaling factor to use when converting a depth frame's get_data() units to meters +* \return float - depth, in meters, per 1 unit stored in the frame data +*/ +float rs2_depth_frame_get_units( const rs2_frame* frame, rs2_error** error ); + /** * retrieve frame stride in bytes (number of bytes from start of line N to start of line N+1) * \param[in] frame handle returned from a callback @@ -276,6 +264,30 @@ 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 motion frame using a frame-source provided form 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[in] frame_type New value for frame type for the allocated frame +* \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_synthetic_motion_frame(rs2_source* source, const rs2_stream_profile* new_stream, rs2_frame* original, + 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 +335,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 old mode 100755 new mode 100644 index d812c99..3807d6b --- 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 required to define a 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 required to define a 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 required to define a 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 required to define a video frame. */ typedef struct rs2_software_video_frame { void* pixels; @@ -57,6 +78,51 @@ typedef struct rs2_software_video_frame const rs2_stream_profile* profile; } rs2_software_video_frame; +/** \brief All the parameters required to define a 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 required to define a 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; + +/** \brief All the parameters required to define a sensor notification. */ +typedef struct rs2_software_notification +{ + rs2_notification_category category; + int type; + rs2_log_severity severity; + const char* description; + const char* serialized_data; +} rs2_software_notification; + +struct rs2_software_device_destruction_callback; + /** * 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 +174,38 @@ 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); + + +/** +* Inject notification to software sonsor +* \param[in] sensor the software sensor +* \param[in] notif all the notification components +* \param[out] error if non-null, receives any error that occurs during this call, otherwise, errors are ignored +*/ +void rs2_software_sensor_on_notification(rs2_sensor* sensor, rs2_software_notification notif, rs2_error** error); + /** * Set frame metadata for the upcoming frames * \param[in] sensor the software sensor @@ -124,6 +215,22 @@ void rs2_software_sensor_on_video_frame(rs2_sensor* sensor, rs2_software_video_f */ void rs2_software_sensor_set_metadata(rs2_sensor* sensor, rs2_frame_metadata_value value, rs2_metadata_type type, rs2_error** error); +/** +* set callback to be notified when a specific software device is destroyed +* \param[in] dev software device +* \param[in] on_notification function pointer to register as callback +* \param[out] error if non-null, receives any error that occurs during this call, otherwise, errors are ignored +*/ +void rs2_software_device_set_destruction_callback(const rs2_device* dev, rs2_software_device_destruction_callback_ptr on_notification, void* user, rs2_error** error); + +/** +* set callback to be notified when a specific software device is destroyed +* \param[in] dev software device +* \param[in] callback callback object created from c++ application. ownership over the callback object is moved into the relevant device lock +* \param[out] error if non-null, receives any error that occurs during this call, otherwise, errors are ignored +*/ +void rs2_software_device_set_destruction_callback_cpp(const rs2_device* dev, rs2_software_device_destruction_callback* callback, rs2_error** error); + /** * Set the wanted matcher type that will be used by the syncer * \param[in] dev the software device @@ -132,6 +239,24 @@ void rs2_software_sensor_set_metadata(rs2_sensor* sensor, rs2_frame_metadata_val */ void rs2_software_device_create_matcher(rs2_device* dev, rs2_matchers matcher, rs2_error** error); +/** + * Register a camera info value for the software device + * \param[in] dev the software device + * \param[in] info identifier for the camera info to add. + * \param[in] val string value for this new camera info. + * \param[out] error if non-null, receives any error that occurs during this call, otherwise, errors are ignored + */ +void rs2_software_device_register_info(rs2_device* dev, rs2_camera_info info, const char *val, rs2_error** error); + +/** + * Update an existing camera info value for the software device + * \param[in] dev the software device + * \param[in] info identifier for the camera info to add. + * \param[in] val string value for this new camera info. + * \param[out] error if non-null, receives any error that occurs during this call, otherwise, errors are ignored + */ +void rs2_software_device_update_info(rs2_device* dev, rs2_camera_info info, const char * val, rs2_error** error); + /** * Add video stream to sensor * \param[in] sensor the software sensor @@ -140,6 +265,49 @@ 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 video stream to sensor + * \param[in] sensor the software sensor + * \param[in] video_stream all the stream components + * \param[in] is_default whether or not the stream should be a default stream for the device + * \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_video_stream_ex(rs2_sensor* sensor, rs2_video_stream video_stream, int is_default, rs2_error** error); + +/** +* Add motion stream to sensor +* \param[in] sensor the software sensor +* \param[in] motion_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 motion stream to sensor +* \param[in] sensor the software sensor +* \param[in] motion_stream all the stream components +* \param[in] is_default whether or not the stream should be a default stream for the device +* \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_ex(rs2_sensor* sensor, rs2_motion_stream motion_stream, int is_default, rs2_error** error); + +/** +* Add pose stream to sensor +* \param[in] sensor the software sensor +* \param[in] pose_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 pose stream to sensor +* \param[in] sensor the software sensor +* \param[in] pose_stream all the stream components +* \param[in] is_default whether or not the stream should be a default stream for the device +* \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_ex(rs2_sensor* sensor, rs2_pose_stream pose_stream, int is_default, rs2_error** error); + /** * Add read only option to sensor * \param[in] sensor the software sensor @@ -157,6 +325,217 @@ void rs2_software_sensor_add_read_only_option(rs2_sensor* sensor, rs2_option opt * \param[out] error if non-null, receives any error that occurs during this call, otherwise, errors are ignored */ void rs2_software_sensor_update_read_only_option(rs2_sensor* sensor, rs2_option option, float val, rs2_error** error); + +/** + * Add an option to sensor + * \param[in] sensor the software sensor + * \param[in] option the wanted 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 initial value of the option + * \param[in] is_writable should the option be read-only or not + * \param[out] error if non-null, receives any error that occurs during this call, otherwise, errors are ignored + */ +void rs2_software_sensor_add_option(rs2_sensor* sensor, rs2_option option, float min, float max, float step, float def, int is_writable, rs2_error** error); + +/** +* Sensors hold the parent device in scope via a shared_ptr. This function detaches that so that the software sensor doesn't keep the software device alive. +* Note that this is dangerous as it opens the door to accessing freed memory if care isn't taken. +* \param[in] sensor the software sensor +* \param[out] error if non-null, recieves any error that occurs during this call, otherwise, errors are ignored +*/ +void rs2_software_sensor_detach(rs2_sensor* sensor, rs2_error** error); + + +/** +* \brief Creates RealSense firmware log message. +* \param[in] dev Device from which the FW log will be taken using the created message +* \param[out] error If non-null, receives any error that occurs during this call, otherwise, errors are ignored. +* \return pointer to created empty firmware log message +*/ +rs2_firmware_log_message* rs2_create_fw_log_message(rs2_device* dev, rs2_error** error); + +/** +* \brief Gets RealSense firmware log. +* \param[in] dev Device from which the FW log should be taken +* \param[in] fw_log_msg Firmware log message object to be filled +* \param[out] error If non-null, receives any error that occurs during this call, otherwise, errors are ignored. +* \return true for success, false for failure - failure happens if no firmware log was sent by the hardware monitor +*/ +int rs2_get_fw_log(rs2_device* dev, rs2_firmware_log_message* fw_log_msg, rs2_error** error); + +/** +* \brief Gets RealSense flash log - this is a fw log that has been written in the device during the previous shutdown of the device +* \param[in] dev Device from which the FW log should be taken +* \param[in] fw_log_msg Firmware log message object to be filled +* \param[out] error If non-null, receives any error that occurs during this call, otherwise, errors are ignored. +* \return true for success, false for failure - failure happens if no firmware log was sent by the hardware monitor +*/ +int rs2_get_flash_log(rs2_device* dev, rs2_firmware_log_message* fw_log_msg, rs2_error** error); + +/** +* Delete RealSense firmware log message +* \param[in] device Realsense firmware log message to delete +*/ +void rs2_delete_fw_log_message(rs2_firmware_log_message* msg); + +/** +* \brief Gets RealSense firmware log message data. +* \param[in] msg firmware log message object +* \param[out] error If non-null, receives any error that occurs during this call, otherwise, errors are ignored. +* \return pointer to start of the firmware log message data +*/ +const unsigned char* rs2_fw_log_message_data(rs2_firmware_log_message* msg, rs2_error** error); + +/** +* \brief Gets RealSense firmware log message size. +* \param[in] msg firmware log message object +* \param[out] error If non-null, receives any error that occurs during this call, otherwise, errors are ignored. +* \return size of the firmware log message data +*/ +int rs2_fw_log_message_size(rs2_firmware_log_message* msg, rs2_error** error); + + +/** +* \brief Gets RealSense firmware log message timestamp. +* \param[in] msg firmware log message object +* \param[out] error If non-null, receives any error that occurs during this call, otherwise, errors are ignored. +* \return timestamp of the firmware log message +*/ +unsigned int rs2_fw_log_message_timestamp(rs2_firmware_log_message* msg, rs2_error** error); + +/** +* \brief Gets RealSense firmware log message severity. +* \param[in] msg firmware log message object +* \param[out] error If non-null, receives any error that occurs during this call, otherwise, errors are ignored. +* \return severity of the firmware log message data +*/ +rs2_log_severity rs2_fw_log_message_severity(const rs2_firmware_log_message* msg, rs2_error** error); + +/** +* \brief Initializes RealSense firmware logs parser in device. +* \param[in] dev Device from which the FW log will be taken +* \param[in] xml_content content of the xml file needed for parsing +* \param[out] error If non-null, receives any error that occurs during this call, otherwise, errors are ignored. +* \return true for success, false for failure - failure happens if opening the xml from the xml_path input fails +*/ +int rs2_init_fw_log_parser(rs2_device* dev, const char* xml_content, rs2_error** error); + + +/** +* \brief Creates RealSense firmware log parsed message. +* \param[in] dev Device from which the FW log will be taken using the created message +* \param[out] error If non-null, receives any error that occurs during this call, otherwise, errors are ignored. +* \return pointer to created empty firmware log message +*/ +rs2_firmware_log_parsed_message* rs2_create_fw_log_parsed_message(rs2_device* dev, rs2_error** error); + +/** +* \brief Deletes RealSense firmware log parsed message. +* \param[in] msg message to be deleted +*/ +void rs2_delete_fw_log_parsed_message(rs2_firmware_log_parsed_message* fw_log_parsed_msg); + + +/** +* \brief Gets RealSense firmware log parser +* \param[in] dev Device from which the FW log will be taken +* \param[in] fw_log_msg firmware log message to be parsed +* \param[in] parsed_msg firmware log parsed message - place holder for the resulting parsed message +* \param[out] error If non-null, receives any error that occurs during this call, otherwise, errors are ignored. +* \return true for success, false for failure - failure happens if message could not be parsed +*/ +int rs2_parse_firmware_log(rs2_device* dev, rs2_firmware_log_message* fw_log_msg, rs2_firmware_log_parsed_message* parsed_msg, rs2_error** error); + +/** +* \brief Gets RealSense firmware log parsed message. +* \param[in] fw_log_parsed_msg firmware log parsed message object +* \param[out] error If non-null, receives any error that occurs during this call, otherwise, errors are ignored. +* \return message of the firmware log parsed message +*/ +const char* rs2_get_fw_log_parsed_message(rs2_firmware_log_parsed_message* fw_log_parsed_msg, rs2_error** error); + +/** +* \brief Gets RealSense firmware log parsed message file name. +* \param[in] fw_log_parsed_msg firmware log parsed message object +* \param[out] error If non-null, receives any error that occurs during this call, otherwise, errors are ignored. +* \return file name of the firmware log parsed message +*/ +const char* rs2_get_fw_log_parsed_file_name(rs2_firmware_log_parsed_message* fw_log_parsed_msg, rs2_error** error); + +/** +* \brief Gets RealSense firmware log parsed message thread name. +* \param[in] fw_log_parsed_msg firmware log parsed message object +* \param[out] error If non-null, receives any error that occurs during this call, otherwise, errors are ignored. +* \return thread name of the firmware log parsed message +*/ +const char* rs2_get_fw_log_parsed_thread_name(rs2_firmware_log_parsed_message* fw_log_parsed_msg, rs2_error** error); + +/** +* \brief Gets RealSense firmware log parsed message severity. +* \param[in] fw_log_parsed_msg firmware log parsed message object +* \param[out] error If non-null, receives any error that occurs during this call, otherwise, errors are ignored. +* \return severity of the firmware log parsed message +*/ +rs2_log_severity rs2_get_fw_log_parsed_severity(rs2_firmware_log_parsed_message* fw_log_parsed_msg, rs2_error** error); + +/** +* \brief Gets RealSense firmware log parsed message relevant line (in the file that is returned by rs2_get_fw_log_parsed_file_name). +* \param[in] fw_log_parsed_msg firmware log parsed message object +* \param[out] error If non-null, receives any error that occurs during this call, otherwise, errors are ignored. +* \return line number of the firmware log parsed message +*/ +unsigned int rs2_get_fw_log_parsed_line(rs2_firmware_log_parsed_message* fw_log_parsed_msg, rs2_error** error); + +/** +* \brief Gets RealSense firmware log parsed message timestamp +* \param[in] fw_log_parsed_msg firmware log parsed message object +* \param[out] error If non-null, receives any error that occurs during this call, otherwise, errors are ignored. +* \return timestamp of the firmware log parsed message +*/ +unsigned int rs2_get_fw_log_parsed_timestamp(rs2_firmware_log_parsed_message* fw_log_parsed_msg, rs2_error** error); + +/** +* \brief Creates RealSense terminal parser. +* \param[in] xml_content content of the xml file needed for parsing +* \param[out] error If non-null, receives any error that occurs during this call, otherwise, errors are ignored. +* \return pointer to created terminal parser object +*/ +rs2_terminal_parser* rs2_create_terminal_parser(const char* xml_content, rs2_error** error); + +/** +* \brief Deletes RealSense terminal parser. +* \param[in] terminal_parser terminal parser to be deleted +*/ +void rs2_delete_terminal_parser(rs2_terminal_parser* terminal_parser); + +/** +* \brief Parses terminal command via RealSense terminal parser +* \param[in] terminal_parser Terminal parser object +* \param[in] command command to be sent to the hw monitor of the device +* \param[in] size_of_command size of command to be sent to the hw monitor of the device +* \param[out] error If non-null, receives any error that occurs during this call, otherwise, errors are ignored. +* \return command to hw monitor, in hex +*/ +rs2_raw_data_buffer* rs2_terminal_parse_command(rs2_terminal_parser* terminal_parser, + const char* command, unsigned int size_of_command, rs2_error** error); + +/** +* \brief Parses terminal response via RealSense terminal parser +* \param[in] terminal_parser Terminal parser object +* \param[in] command command sent to the hw monitor of the device +* \param[in] size_of_command size of the command to sent to the hw monitor of the device +* \param[in] response response received by the hw monitor of the device +* \param[in] size_of_response size of the response received by the hw monitor of the device +* \param[out] error If non-null, receives any error that occurs during this call, otherwise, errors are ignored. +* \return answer parsed +*/ +rs2_raw_data_buffer* rs2_terminal_parse_response(rs2_terminal_parser* terminal_parser, + const char* command, unsigned int size_of_command, + const void* response, unsigned int size_of_response, rs2_error** error); + + #ifdef __cplusplus } #endif diff --git a/libs/realsense2/include/librealsense2/h/rs_option.h b/libs/realsense2/include/librealsense2/h/rs_option.h old mode 100755 new mode 100644 index 71be14b..ad6e5a2 --- 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,257 @@ 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 laser emitter, 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, /**< Emitter select: 0 – disable all emitters. 1 – enable laser. 2 – enable auto laser. 3 – enable LED.*/ + 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/L500/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_LED_POWER, /**< Power of the LED (light emitting diode), with 0 meaning LED off*/ + RS2_OPTION_ZERO_ORDER_ENABLED, /**< Toggle Zero-Order mode */ + RS2_OPTION_ENABLE_MAP_PRESERVATION, /**< Preserve previous map when starting */ + RS2_OPTION_FREEFALL_DETECTION_ENABLED, /**< Enable/disable sensor shutdown when a free-fall is detected (on by default) */ + RS2_OPTION_AVALANCHE_PHOTO_DIODE, /**< Changes the exposure time of Avalanche Photo Diode in the receiver */ + RS2_OPTION_POST_PROCESSING_SHARPENING, /**< Changes the amount of sharpening in the post-processed image */ + RS2_OPTION_PRE_PROCESSING_SHARPENING, /**< Changes the amount of sharpening in the pre-processed image */ + RS2_OPTION_NOISE_FILTERING, /**< Control edges and background noise */ + RS2_OPTION_INVALIDATION_BYPASS, /**< Enable\disable pixel invalidation */ + RS2_OPTION_AMBIENT_LIGHT, /**< Change the depth ambient light see rs2_ambient_light for values */ + RS2_OPTION_SENSOR_MODE, /**< The resolution mode: see rs2_sensor_mode for values */ + RS2_OPTION_EMITTER_ALWAYS_ON, /**< Enable Laser On constantly (GS SKU Only) */ + RS2_OPTION_THERMAL_COMPENSATION, /**< Depth Thermal Compensation for selected D400 SKUs */ + RS2_OPTION_TRIGGER_CAMERA_ACCURACY_HEALTH, /**< Enable depth & color frame sync with periodic calibration for proper alignment */ + RS2_OPTION_RESET_CAMERA_ACCURACY_HEALTH, + 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 /**< Number of enumeration values. Not a valid input: intended to be used in for-loops. */ + } rs2_rs400_visual_preset; + const char* rs2_rs400_visual_preset_to_string(rs2_rs400_visual_preset preset); + + /** \brief For L500 devices: provides optimized settings (presets) for specific types of usage. */ + typedef enum rs2_l500_visual_preset + { + RS2_L500_VISUAL_PRESET_CUSTOM, + RS2_L500_VISUAL_PRESET_DEFAULT, + RS2_L500_VISUAL_PRESET_NO_AMBIENT, + RS2_L500_VISUAL_PRESET_LOW_AMBIENT, + RS2_L500_VISUAL_PRESET_MAX_RANGE, + RS2_L500_VISUAL_PRESET_SHORT_RANGE, + RS2_L500_VISUAL_PRESET_COUNT /**< Number of enumeration values. Not a valid input: intended to be used in for-loops. */ + } rs2_l500_visual_preset; + const char* rs2_l500_visual_preset_to_string(rs2_l500_visual_preset preset); + + /** \brief For setting the camera_mode option */ + typedef enum rs2_sensor_mode + { + RS2_SENSOR_MODE_VGA, + RS2_SENSOR_MODE_XGA, + RS2_SENSOR_MODE_QVGA, + RS2_SENSOR_MODE_COUNT /**< Number of enumeration values. Not a valid input: intended to be used in for-loops. */ + } rs2_sensor_mode; + const char* rs2_sensor_mode_to_string(rs2_sensor_mode preset); + + /** \brief ambient light for RS2_OPTION_AMBIENT_LIGHT option. */ + typedef enum rs2_ambient_light + { + RS2_AMBIENT_LIGHT_NO_AMBIENT = 1, + RS2_AMBIENT_LIGHT_LOW_AMBIENT = 2, + } rs2_ambient_light; + const char* rs2_ambient_light_to_string(rs2_ambient_light preset); + + /** + * check if an option is read-only + * \param[in] options the options container + * \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] options the options container + * \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] options the options container + * \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 the options container + * \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] options the options container + * \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] options the options container + * \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] options the options container + * \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 old mode 100755 new mode 100644 index f617236..1018c77 --- 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 old mode 100755 new mode 100644 index 7836470..240b5c5 --- 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,55 @@ 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); + +/** +* Creates Depth frame decompression module. Decoded frames compressed and transmitted with Z16H variable-lenght Huffman code to +* standartized Z16 Depth data format. Using the compression allows to reduce the Depth frames bandwidth by more than 50 percent +* \param[out] error If non-null, receives any error that occurs during this call, otherwise, errors are ignored +* \return Huffman-code decompression processing block +*/ +rs2_processing_block* rs2_create_huffman_depth_decompress_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 old mode 100755 new mode 100644 index cddec6d..a540e6d --- 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 old mode 100755 new mode 100644 index 9120275..975e6ef --- a/libs/realsense2/include/librealsense2/h/rs_sensor.h +++ b/libs/realsense2/include/librealsense2/h/rs_sensor.h @@ -30,11 +30,15 @@ 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_IP_ADDRESS , /**< IP address for remote camera. */ 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 +50,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 +69,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 +78,20 @@ 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_Y8I , /**< 8-bit per pixel interleaved. 8-bit left, 8-bit right. */ + RS2_FORMAT_Y12I , /**< 12-bit per pixel interleaved. 12-bit left, 12-bit right. Each pixel is stored in a 24-bit word in little-endian order. */ + RS2_FORMAT_INZI , /**< multi-planar Depth 16bit + IR 10bit. */ + RS2_FORMAT_INVI , /**< 8-bit IR stream. */ + RS2_FORMAT_W10 , /**< Grey-scale image as a bit-packed array. 4 pixel data stream taking 5 bytes */ + RS2_FORMAT_Z16H , /**< Variable-length Huffman-compressed 16-bit depth values. */ 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 +168,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 @@ -298,11 +318,19 @@ const char* rs2_get_notification_serialized_data(rs2_notification* notification, /** * check if physical subdevice is supported -* \param[in] device input RealSense device +* \param[in] sensor input RealSense subdevice * \param[out] error if non-null, receives any error that occurs during this call, otherwise, errors are ignored * \return list of stream profiles that given subdevice can provide, should be released by rs2_delete_profiles_list */ -rs2_stream_profile_list* rs2_get_stream_profiles(rs2_sensor* device, rs2_error** error); +rs2_stream_profile_list* rs2_get_stream_profiles(rs2_sensor* sensor, rs2_error** error); + +/** +* check how subdevice is streaming +* \param[in] sensor input RealSense subdevice +* \param[out] error if non-null, receives any error that occurs during this call, otherwise, errors are ignored +* \return list of stream profiles that given subdevice is currently streaming, should be released by rs2_delete_profiles_list +*/ +rs2_stream_profile_list* rs2_get_active_streams(rs2_sensor* sensor, rs2_error** error); /** * Get pointer to specific stream profile @@ -345,6 +373,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 @@ -421,6 +464,17 @@ void rs2_register_extrinsics(const rs2_stream_profile* from, const rs2_stream_profile* to, rs2_extrinsics extrin, rs2_error** error); +/** + * \brief Override extrinsics of a given sensor that supports calibrated_sensor. + * + * This will affect extrinsics at the source device and may affect multiple profiles. Used for DEPTH_TO_RGB calibration. + * +* \param[in] sensor The sensor +* \param[in] extrinsics Extrinsics from Depth to the named sensor +* \param[out] error If non-null, receives any error that occurs during this call, otherwise, errors are ignored +*/ +void rs2_override_extrinsics( const rs2_sensor* sensor, const rs2_extrinsics* extrinsics, rs2_error** error ); + /** * When called on a video profile, returns the intrinsics of specific stream configuration * \param[in] mode input stream profile @@ -429,8 +483,172 @@ 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); + +/** +* Retrieve 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); + +/** +* Remove a named location tag +* \param[in] sensor T2xx position-tracking sensor +* \param[in] guid Null-terminated string of up to 127 characters +* \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_remove_static_node(const rs2_sensor* sensor, const char* guid, 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); + +/** + * \brief Override intrinsics of a given sensor that supports calibrated_sensor. + * + * This will affect intrinsics at the source and may affect multiple profiles. Used for DEPTH_TO_RGB calibration. + * +* \param[in] sensor The RealSense device +* \param[in] intrinsics Intrinsics value to be written to the sensor +* \param[out] error If non-null, receives any error that occurs during this call, otherwise, errors are ignored +*/ +void rs2_override_intrinsics( const rs2_sensor* sensor, 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); + +/** + * Get the DSM parameters for a sensor + * \param[in] sensor Sensor that supports the CALIBRATED_SENSOR extension + * \param[out] p_params_out Pointer to the structure that will get the DSM parameters + * \param[out] error If non-null, receives any error that occurs during this call, otherwise, errors are ignored + */ +void rs2_get_dsm_params( rs2_sensor const * sensor, rs2_dsm_params * p_params_out, rs2_error** error ); + +/** + * Set the sensor DSM parameters + * This should ideally be done when the stream is NOT running. If it is, the + * parameters may not take effect immediately. + * \param[in] sensor Sensor that supports the CALIBRATED_SENSOR extension + * \param[out] p_params Pointer to the structure that contains the DSM parameters + * \param[out] error If non-null, receives any error that occurs during this call, otherwise, errors are ignored + */ +void rs2_override_dsm_params( rs2_sensor const * sensor, rs2_dsm_params const * p_params, rs2_error** error ); + +/** + * Reset the sensor DSM parameters + * This should ideally be done when the stream is NOT running. May not take effect immediately. + * \param[in] sensor Sensor that supports the CALIBRATED_SENSOR extension + * \param[out] error If non-null, receives any error that occurs during this call, otherwise, errors are ignored + */ +void rs2_reset_sensor_calibration( rs2_sensor const * sensor, 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_terminal_parser.h b/libs/realsense2/include/librealsense2/h/rs_terminal_parser.h new file mode 100644 index 0000000..f0728f1 --- /dev/null +++ b/libs/realsense2/include/librealsense2/h/rs_terminal_parser.h @@ -0,0 +1,63 @@ +/* License: Apache 2.0. See LICENSE file in root directory. + Copyright(c) 2020 Intel Corporation. All Rights Reserved. */ + +/** \file rs_terminal.h +* \brief Exposes RealSense terminal functionality for C compilers +*/ + + +#ifndef LIBREALSENSE_RS2_TERMINAL_H +#define LIBREALSENSE_RS2_TERMINAL_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "rs_types.h" + +/** +* \brief Creates RealSense terminal parser. +* \param[in] xml_content content of the xml file needed for parsing +* \param[out] error If non-null, receives any error that occurs during this call, otherwise, errors are ignored. +* \return pointer to created terminal parser object +*/ +rs2_terminal_parser* rs2_create_terminal_parser(const char* xml_content, rs2_error** error); + +/** +* \brief Deletes RealSense terminal parser. +* \param[in] terminal_parser terminal parser to be deleted +*/ +void rs2_delete_terminal_parser(rs2_terminal_parser* terminal_parser); + +/** +* \brief Parses terminal command via RealSense terminal parser +* \param[in] terminal_parser Terminal parser object +* \param[in] command command to be sent to the hw monitor of the device +* \param[in] size_of_command size of command to be sent to the hw monitor of the device +* \param[out] error If non-null, receives any error that occurs during this call, otherwise, errors are ignored. +* \return command to hw monitor, in hex +*/ +rs2_raw_data_buffer* rs2_terminal_parse_command(rs2_terminal_parser* terminal_parser, + const char* command, unsigned int size_of_command, rs2_error** error); + +/** +* \brief Parses terminal response via RealSense terminal parser +* \param[in] terminal_parser Terminal parser object +* \param[in] command command sent to the hw monitor of the device +* \param[in] size_of_command size of the command to sent to the hw monitor of the device +* \param[in] response response received by the hw monitor of the device +* \param[in] size_of_response size of the response received by the hw monitor of the device +* \param[out] error If non-null, receives any error that occurs during this call, otherwise, errors are ignored. +* \return answer parsed +*/ +rs2_raw_data_buffer* rs2_terminal_parse_response(rs2_terminal_parser* terminal_parser, + const char* command, unsigned int size_of_command, + const void* response, unsigned int size_of_response, rs2_error** error); + + + + +#ifdef __cplusplus +} +#endif +#endif diff --git a/libs/realsense2/include/librealsense2/h/rs_types.h b/libs/realsense2/include/librealsense2/h/rs_types.h old mode 100755 new mode 100644 index fa088d4..ef2ef62 --- 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,36 @@ 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 Video DSM (Digital Sync Module) parameters for calibration (same layout as in FW ac_depth_params) + This is the block in MC that converts angles to dimensionless integers reported to MA (using "DSM coefficients"). +*/ +typedef struct rs2_dsm_params +{ + unsigned long long timestamp; /**< system_clock::time_point::time_since_epoch().count() */ + unsigned short version; /**< MAJOR<<12 | MINOR<<4 | PATCH */ + unsigned char model; /**< rs2_dsm_correction_model */ + unsigned char flags[5]; /**< TBD, now 0s */ + float h_scale; /**< the scale factor to horizontal DSM scale thermal results */ + float v_scale; /**< the scale factor to vertical DSM scale thermal results */ + float h_offset; /**< the offset to horizontal DSM offset thermal results */ + float v_offset; /**< the offset to vertical DSM offset thermal results */ + float rtd_offset; /**< the offset to the Round-Trip-Distance delay thermal results */ + unsigned char temp_x2; /**< the temperature recorded times 2 (ldd for depth; hum for rgb) */ + unsigned char reserved[11]; +} rs2_dsm_params; + +typedef enum rs2_dsm_correction_model +{ + RS2_DSM_CORRECTION_NONE, /**< hFactor and hOffset are not used, and no artificial error is induced */ + RS2_DSM_CORRECTION_AOT, /**< Aging-over-thermal (default); aging-induced error is uniform across temperature */ + RS2_DSM_CORRECTION_TOA, /**< Thermal-over-aging; aging-induced error changes alongside temperature */ + RS2_DSM_CORRECTION_COUNT +} rs2_dsm_correction_model; + +/** \brief Motion device intrinsics: scale, bias, and variances. */ typedef struct rs2_motion_device_intrinsic { /* \internal @@ -78,7 +106,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 */ @@ -86,11 +151,12 @@ typedef enum rs2_log_severity { RS2_LOG_SEVERITY_ERROR, /**< Indication of definite failure */ RS2_LOG_SEVERITY_FATAL, /**< Indication of unrecoverable failure */ RS2_LOG_SEVERITY_NONE , /**< No logging will occur */ - RS2_LOG_SEVERITY_COUNT /**< Number of enumeration values. Not a valid input: intended to be used in for-loops. */ -} rs2_log_severity; + RS2_LOG_SEVERITY_COUNT, /**< Number of enumeration values. Not a valid input: intended to be used in for-loops. */ + RS2_LOG_SEVERITY_ALL = RS2_LOG_SEVERITY_DEBUG /**< Include any/all log messages */ + } 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 +184,32 @@ 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_AUTO_CALIBRATED_DEVICE, + RS2_EXTENSION_COLOR_SENSOR, + RS2_EXTENSION_MOTION_SENSOR, + RS2_EXTENSION_FISHEYE_SENSOR, + RS2_EXTENSION_DEPTH_HUFFMAN_DECODER, + RS2_EXTENSION_SERIALIZABLE, + RS2_EXTENSION_FW_LOGGER, + RS2_EXTENSION_AUTO_CALIBRATION_FILTER, + RS2_EXTENSION_DEVICE_CALIBRATION, + RS2_EXTENSION_CALIBRATED_SENSOR, RS2_EXTENSION_COUNT } rs2_extension; const char* rs2_extension_type_to_string(rs2_extension type); @@ -130,14 +222,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 @@ -147,6 +245,7 @@ typedef enum rs2_matchers typedef struct rs2_device_info rs2_device_info; typedef struct rs2_device rs2_device; typedef struct rs2_error rs2_error; +typedef struct rs2_log_message rs2_log_message; typedef struct rs2_raw_data_buffer rs2_raw_data_buffer; typedef struct rs2_frame rs2_frame; typedef struct rs2_frame_queue rs2_frame_queue; @@ -155,6 +254,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,22 +264,32 @@ 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; +typedef struct rs2_firmware_log_message rs2_firmware_log_message; +typedef struct rs2_firmware_log_parsed_message rs2_firmware_log_parsed_message; +typedef struct rs2_firmware_log_parser rs2_firmware_log_parser; +typedef struct rs2_terminal_parser rs2_terminal_parser; +typedef void (*rs2_log_callback_ptr)(rs2_log_severity, rs2_log_message const *, void * arg); typedef void (*rs2_notification_callback_ptr)(rs2_notification*, void*); +typedef void(*rs2_software_device_destruction_callback_ptr)(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 old mode 100755 new mode 100644 index 6b383ce..3d105aa --- 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 old mode 100755 new mode 100644 index 917450d..b23f177 --- 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,451 @@ 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(), int(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(), int(fw_image.size()), new update_progress_callback(std::move(callback)), &e); + error::handle(e); + } + }; + + typedef std::vector calibration_table; + + class calibrated_device : public device + { + public: + calibrated_device(device d) + : device(d.get()) + {} + + /** + * Write calibration that was set by set_calibration_table to device's EEPROM. + */ + void write_calibration() const + { + rs2_error* e = nullptr; + rs2_write_calibration(_dev.get(), &e); + error::handle(e); + } + + /** + * Reset device to factory calibration + */ + void reset_to_factory_calibration() + { + rs2_error* e = nullptr; + rs2_reset_to_factory_calibration(_dev.get(), &e); + error::handle(e); + } + }; + + class auto_calibrated_device : public calibrated_device + { + public: + auto_calibrated_device(device d) + : calibrated_device(d) + { + rs2_error* e = nullptr; + if (rs2_is_device_extendable_to(_dev.get(), RS2_EXTENSION_AUTO_CALIBRATED_DEVICE, &e) == 0 && !e) + { + _dev.reset(); + } + error::handle(e); + } + + /** + * This will improve the depth noise. + * \param[in] json_content Json string to configure speed on chip calibration parameters: + { + "speed": 3, + "scan parameter": 0, + "data sampling": 0 + } + speed - value can be one of: Very fast = 0, Fast = 1, Medium = 2, Slow = 3, White wall = 4, default is Slow + scan_parameter - value can be one of: Py scan (default) = 0, Rx scan = 1 + data_sampling - value can be one of:polling data sampling = 0, interrupt data sampling = 1 + if json is nullptr it will be ignored and calibration will use the default parameters + * \param[out] health Calibration Health-Check captures how far camera calibration is from the optimal one + [0, 0.25) - Good + [0.25, 0.75) - Can be Improved + [0.75, ) - Requires Calibration + * \param[in] callback Optional callback to get progress notifications + * \param[in] timeout_ms Timeout in ms + * \return New calibration table + */ + template + calibration_table run_on_chip_calibration(std::string json_content, float* health, T callback, int timeout_ms = 5000) const + { + std::vector results; + + rs2_error* e = nullptr; + std::shared_ptr list( + rs2_run_on_chip_calibration_cpp(_dev.get(), json_content.data(), int(json_content.size()), health, new update_progress_callback(std::move(callback)), timeout_ms, &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; + } + + /** + * This will improve the depth noise. + * \param[in] json_content Json string to configure speed on chip calibration parameters: + { + "speed": 3, + "scan parameter": 0, + "data sampling": 0 + } + speed - value can be one of: Very fast = 0, Fast = 1, Medium = 2, Slow = 3, White wall = 4, default is Slow + scan parameter - value can be one of: Py scan (default) = 0, Rx scan = 1 + data sampling - value can be one of:polling data sampling = 0, interrupt data sampling = 1 + if json is nullptr it will be ignored and calibration will use the default parameters + * \param[out] health Calibration Health-Check captures how far camera calibration is from the optimal one + [0, 0.25) - Good + [0.25, 0.75) - Can be Improved + [0.75, ) - Requires Calibration + * \param[in] timeout_ms Timeout in ms + * \return New calibration table + */ + calibration_table run_on_chip_calibration(std::string json_content, float* health, int timeout_ms = 5000) const { + std::vector results; + + rs2_error* e = nullptr; + std::shared_ptr list( + rs2_run_on_chip_calibration_cpp(_dev.get(), json_content.data(), static_cast< int >( json_content.size() ), health, nullptr, timeout_ms, &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; + } + + /** + * This will adjust camera absolute distance to flat target. User needs to enter the known ground truth. + * \param[in] ground_truth_mm Ground truth in mm must be between 2500 - 2000000 + * \param[in] json_content Json string to configure tare calibration parameters: + { + "average step count": 20, + "step count": 20, + "accuracy": 2, + "scan parameter": 0, + "data sampling": 0 + } + average step count - number of frames to average, must be between 1 - 30, default = 20 + step count - max iteration steps, must be between 5 - 30, default = 10 + accuracy - Subpixel accuracy level, value can be one of: Very high = 0 (0.025%), High = 1 (0.05%), Medium = 2 (0.1%), Low = 3 (0.2%), Default = Very high (0.025%), default is very high (0.025%) + scan_parameter - value can be one of: Py scan (default) = 0, Rx scan = 1 + data_sampling - value can be one of:polling data sampling = 0, interrupt data sampling = 1 + if json is nullptr it will be ignored and calibration will use the default parameters + * \param[in] content_size Json string size if its 0 the json will be ignored and calibration will use the default parameters + * \param[in] callback Optional callback to get progress notifications + * \param[in] timeout_ms Timeout in ms + * \return New calibration table + */ + template + calibration_table run_tare_calibration(float ground_truth_mm, std::string json_content, T callback, int timeout_ms = 5000) const + { + std::vector results; + + rs2_error* e = nullptr; + std::shared_ptr list( + rs2_run_tare_calibration_cpp(_dev.get(), ground_truth_mm, json_content.data(), int(json_content.size()), new update_progress_callback(std::move(callback)), timeout_ms, &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; + } + + /** + * This will adjust camera absolute distance to flat target. User needs to enter the known ground truth. + * \param[in] ground_truth_mm Ground truth in mm must be between 2500 - 2000000 + * \param[in] json_content Json string to configure tare calibration parameters: + { + "average step count": 20, + "step count": 20, + "accuracy": 2, + "scan parameter": 0, + "data sampling": 0 + } + average step count - number of frames to average, must be between 1 - 30, default = 20 + step count - max iteration steps, must be between 5 - 30, default = 10 + accuracy - Subpixel accuracy level, value can be one of: Very high = 0 (0.025%), High = 1 (0.05%), Medium = 2 (0.1%), Low = 3 (0.2%), Default = Very high (0.025%), default is very high (0.025%) + scan_parameter - value can be one of: Py scan (default) = 0, Rx scan = 1 + data_sampling - value can be one of:polling data sampling = 0, interrupt data sampling = 1 + if json is nullptr it will be ignored and calibration will use the default parameters + * \param[in] content_size Json string size if its 0 the json will be ignored and calibration will use the default parameters + * \param[in] timeout_ms Timeout in ms + * \return New calibration table + */ + calibration_table run_tare_calibration(float ground_truth_mm, std::string json_content, int timeout_ms = 5000) const + { + std::vector results; + + rs2_error* e = nullptr; + std::shared_ptr list( + rs2_run_tare_calibration_cpp(_dev.get(), ground_truth_mm, json_content.data(), static_cast< int >( json_content.size() ), nullptr, timeout_ms, &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; + } + + /** + * Read current calibration table from flash. + * \return Calibration table + */ + calibration_table get_calibration_table() + { + std::vector results; + + rs2_error* e = nullptr; + std::shared_ptr list( + rs2_get_calibration_table(_dev.get(), &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; + } + + /** + * Set current table to dynamic area. + * \param[in] Calibration table + */ + void set_calibration_table(const calibration_table& calibration) + { + rs2_error* e = nullptr; + rs2_set_calibration_table(_dev.get(), calibration.data(), static_cast< int >( calibration.size() ), &e); + error::handle(e); + } + + + }; + + /* + Wrapper around any callback function that is given to calibration_change_callback. + */ + template< class callback > + class calibration_change_callback : public rs2_calibration_change_callback + { + //using callback = std::function< void( rs2_calibration_status ) >; + callback _callback; + public: + calibration_change_callback( callback cb ) : _callback( cb ) {} + + void on_calibration_change( rs2_calibration_status status ) noexcept override + { + _callback( status ); + } + void release() override { delete this; } + }; + + class device_calibration : public device + { + public: + device_calibration( device d ) + : device( d.get() ) + { + rs2_error* e = nullptr; + if( rs2_is_device_extendable_to( _dev.get(), RS2_EXTENSION_DEVICE_CALIBRATION, &e ) == 0 && !e ) + { + _dev.reset(); + } + error::handle( e ); + } + + /* + Your callback should look like this, for example: + sensor.register_calibration_change_callback( + []( rs2_calibration_status ) noexcept + { + ... + }) + */ + template< typename T > + void register_calibration_change_callback( T callback ) + { + // We wrap the callback with an interface and pass it to librealsense, who will + // now manage its lifetime. Rather than deleting it, though, it will call its + // release() function, where (back in our context) it can be safely deleted: + rs2_error* e = nullptr; + rs2_register_calibration_change_callback_cpp( + _dev.get(), + new calibration_change_callback< T >( std::move( callback )), + &e ); + error::handle( e ); + } + + /** + * This will trigger the given calibration, if available + */ + void trigger_device_calibration( rs2_calibration_type type ) + { + rs2_error* e = nullptr; + rs2_trigger_device_calibration( _dev.get(), type, &e ); + error::handle( e ); } }; @@ -283,15 +729,26 @@ namespace rs2 return _list.get(); } + operator std::shared_ptr() { return _list; }; + private: std::shared_ptr _list; }; - class tm2 : public device //TODO: add to wrappers + /** + * 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 calibrated_device // TODO: add to wrappers [Python done] { public: tm2(device d) - : device(d.get()) + : calibrated_device(d) { rs2_error* e = nullptr; if (rs2_is_device_extendable_to(_dev.get(), RS2_EXTENSION_TM2, &e) == 0 && !e) @@ -355,6 +812,61 @@ 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); + } + + 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..55f52f0 --- /dev/null +++ b/libs/realsense2/include/librealsense2/hpp/rs_export.hpp @@ -0,0 +1,390 @@ +// 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" +#include +#include +#include +namespace rs2 +{ + struct vec3d { + float x, y, z; + float length() const { return sqrt(x * x + y * y + z * z); } + + vec3d normalize() const + { + auto len = length(); + return { x / len, y / len, z / len }; + } + }; + + inline vec3d operator + (const vec3d & a, const vec3d & b) { return{ a.x + b.x, a.y + b.y, a.z + b.z }; } + inline vec3d operator - (const vec3d & a, const vec3d & b) { return{ a.x - b.x, a.y - b.y, a.z - b.z }; } + inline vec3d cross(const vec3d & a, const vec3d & b) { return { a.y * b.z - a.z * b.y, a.z * b.x - a.x * b.z, a.x * b.y - a.y * b.x }; } + + class save_to_ply : public filter + { + public: + static const auto OPTION_IGNORE_COLOR = rs2_option(RS2_OPTION_COUNT + 10); + static const auto OPTION_PLY_MESH = rs2_option(RS2_OPTION_COUNT + 11); + static const auto OPTION_PLY_BINARY = rs2_option(RS2_OPTION_COUNT + 12); + static const auto OPTION_PLY_NORMALS = rs2_option(RS2_OPTION_COUNT + 13); + static const auto OPTION_PLY_THRESHOLD = rs2_option(RS2_OPTION_COUNT + 14); + + 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 }); + register_simple_option(OPTION_PLY_MESH, option_range{ 0, 1, 1, 1 }); + register_simple_option(OPTION_PLY_NORMALS, option_range{ 0, 1, 0, 1 }); + register_simple_option(OPTION_PLY_BINARY, option_range{ 0, 1, 1, 1 }); + register_simple_option(OPTION_PLY_THRESHOLD, option_range{ 0, 1, 0.05f, 0 }); + } + + 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); + bool mesh = get_option(OPTION_PLY_MESH); + bool binary = get_option(OPTION_PLY_BINARY); + bool use_normals = get_option(OPTION_PLY_NORMALS); + const auto verts = p.get_vertices(); + const auto texcoords = p.get_texture_coordinates(); + const uint8_t* texture_data; + if (use_texcoords) // texture might be on the gpu, get pointer to data before for-loop to avoid repeated access + texture_data = reinterpret_cast(color.get_data()); + std::vector new_verts; + std::vector normals; + std::vector> new_tex; + std::map idx_map; + std::map> index_to_normals; + + 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[int(i)] = int(new_verts.size()); + new_verts.push_back({ verts[i].x, -1 * verts[i].y, -1 * verts[i].z }); + if (use_texcoords) + { + auto rgb = get_texcolor(color, texture_data, 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 = get_option(OPTION_PLY_THRESHOLD); + std::vector> faces; + if (mesh) + { + 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[d], idx_map[b] }); + faces.push_back({ idx_map[d], idx_map[a], idx_map[c] }); + + if (use_normals) + { + vec3d point_a = { verts[a].x , -1 * verts[a].y, -1 * verts[a].z }; + vec3d point_b = { verts[b].x , -1 * verts[b].y, -1 * verts[b].z }; + vec3d point_c = { verts[c].x , -1 * verts[c].y, -1 * verts[c].z }; + vec3d point_d = { verts[d].x , -1 * verts[d].y, -1 * verts[d].z }; + + auto n1 = cross(point_d - point_a, point_b - point_a); + auto n2 = cross(point_c - point_a, point_d - point_a); + + index_to_normals[idx_map[a]].push_back(n1); + index_to_normals[idx_map[a]].push_back(n2); + + index_to_normals[idx_map[b]].push_back(n1); + + index_to_normals[idx_map[c]].push_back(n2); + + index_to_normals[idx_map[d]].push_back(n1); + index_to_normals[idx_map[d]].push_back(n2); + } + } + } + } + } + + if (mesh && use_normals) + { + for (int i = 0; i < new_verts.size(); ++i) + { + auto normals_vec = index_to_normals[i]; + vec3d sum = { 0, 0, 0 }; + for (auto& n : normals_vec) + sum = sum + n; + if (normals_vec.size() > 0) + normals.push_back((sum.normalize())); + else + normals.push_back({ 0, 0, 0 }); + } + } + + std::ofstream out(fname); + out << "ply\n"; + if (binary) + out << "format binary_little_endian 1.0\n"; + else + out << "format ascii 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 (mesh && use_normals) + { + out << "property float" << sizeof(float) * 8 << " nx\n"; + out << "property float" << sizeof(float) * 8 << " ny\n"; + out << "property float" << sizeof(float) * 8 << " nz\n"; + } + if (use_texcoords) + { + out << "property uchar red\n"; + out << "property uchar green\n"; + out << "property uchar blue\n"; + } + if (mesh) + { + out << "element face " << faces.size() << "\n"; + out << "property list uchar int vertex_indices\n"; + } + out << "end_header\n"; + + if (binary) + { + out.close(); + out.open(fname, 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 (mesh && use_normals) + { + out.write(reinterpret_cast(&(normals[i].x)), sizeof(float)); + out.write(reinterpret_cast(&(normals[i].y)), sizeof(float)); + out.write(reinterpret_cast(&(normals[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)); + } + } + if (mesh) + { + 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)); + } + } + } + else + { + for (int i = 0; i (faces[i]) << " "; + out << std::get<1>(faces[i]) << " "; + out << std::get<2>(faces[i]) << " "; + out << "\n"; + } + } + } + } + + std::array get_texcolor(const video_frame& texture, const uint8_t* texture_data, 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(); + 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 old mode 100755 new mode 100644 index 14f8d00..c151209 --- 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` (FRAME_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 { @@ -721,13 +814,25 @@ namespace rs2 error::handle(e); return r; } + + /** + * Provide the scaling factor to use when converting from get_data() units to meters + * \return float - depth, in meters, per 1 unit stored in the frame data + */ + float get_units() const + { + rs2_error * e = nullptr; + auto r = rs2_depth_frame_get_units( get(), &e ); + error::handle( e ); + return r; + } }; class disparity_frame : public depth_frame { 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 +846,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 +862,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 +876,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 +890,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 +904,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 +921,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 +941,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 +1002,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 +1015,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 +1077,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 +1111,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 +1131,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 old mode 100755 new mode 100644 index 7cf1048..3d36a53 --- a/libs/realsense2/include/librealsense2/hpp/rs_internal.hpp +++ b/libs/realsense2/include/librealsense2/hpp/rs_internal.hpp @@ -70,6 +70,21 @@ namespace rs2 } } + template + class software_device_destruction_callback : public rs2_software_device_destruction_callback + { + T on_destruction_function; + public: + explicit software_device_destruction_callback(T on_destruction) : on_destruction_function(on_destruction) {} + + void on_destruction() override + { + on_destruction_function(); + } + + void release() override { delete this; } + }; + class software_sensor : public sensor { public: @@ -78,18 +93,51 @@ namespace rs2 * * \param[in] video_stream all the parameters that required to defind video stream */ - stream_profile add_video_stream(rs2_video_stream video_stream) + stream_profile add_video_stream(rs2_video_stream video_stream, bool is_default=false) { rs2_error* e = nullptr; - stream_profile stream(rs2_software_sensor_add_video_stream(_sensor.get(),video_stream, &e)); + auto profile = rs2_software_sensor_add_video_stream_ex(_sensor.get(), video_stream, is_default, &e); error::handle(e); + stream_profile stream(profile); return stream; } /** - * 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, bool is_default=false) + { + rs2_error* e = nullptr; + + auto profile = rs2_software_sensor_add_motion_stream_ex(_sensor.get(), motion_stream, is_default, &e); + error::handle(e); + + stream_profile stream(profile); + 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, bool is_default=false) + { + rs2_error* e = nullptr; + + auto profile = rs2_software_sensor_add_pose_stream_ex(_sensor.get(), pose_stream, is_default, &e); + error::handle(e); + + stream_profile stream(profile); + return stream; + } + + /** + * Inject video frame into the sensor * * \param[in] frame all the parameters that required to define video frame */ @@ -100,6 +148,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 @@ -113,7 +185,7 @@ namespace rs2 } /** - * Register option that will be supported by the sensor + * Register read-only option that will be supported by the sensor * * \param[in] option the option * \param[in] val the initial value @@ -126,7 +198,7 @@ namespace rs2 } /** - * Update value of registered option + * Update value of registered read-only option * * \param[in] option the option * \param[in] val the initial value @@ -137,6 +209,38 @@ namespace rs2 rs2_software_sensor_update_read_only_option(_sensor.get(), option, val, &e); error::handle(e); } + /** + * Register option that will be supported by the sensor + * + * \param[in] option the option + * \param[in] range range data for the option. range.def will be used as the initial value + */ + void add_option(rs2_option option, const option_range& range, bool is_writable=true) + { + rs2_error* e = nullptr; + rs2_software_sensor_add_option(_sensor.get(), option, range.min, + range.max, range.step, range.def, is_writable, &e); + error::handle(e); + } + + void on_notification(rs2_software_notification notif) + { + rs2_error * e = nullptr; + rs2_software_sensor_on_notification(_sensor.get(), notif, &e); + error::handle(e); + } + /** + * Sensors hold the parent device in scope via a shared_ptr. This function detaches that so that the + * software sensor doesn't keep the software device alive. Note that this is dangerous as it opens the + * door to accessing freed memory if care isn't taken. + */ + void detach() + { + rs2_error * e = nullptr; + rs2_software_sensor_detach(_sensor.get(), &e); + error::handle(e); + } + private: friend class software_device; @@ -155,23 +259,31 @@ namespace rs2 class software_device : public device { - std::shared_ptr create_device_ptr() + std::shared_ptr create_device_ptr(std::function deleter) { rs2_error* e = nullptr; std::shared_ptr dev( rs2_create_software_device(&e), - rs2_delete_device); + deleter); error::handle(e); return dev; } public: - software_device() - : device(create_device_ptr()) - {} + software_device(std::function deleter = &rs2_delete_device) + : device(create_device_ptr(deleter)) + { + this->set_destruction_callback([]{}); + } + + software_device(std::string name) + : device(create_device_ptr(&rs2_delete_device)) + { + update_info(RS2_CAMERA_INFO_NAME, name); + } /** - * Add sensor stream to software sensor + * Add software sensor with given name to the software device. * * \param[in] name the name of the sensor */ @@ -186,6 +298,59 @@ namespace rs2 return software_sensor(sensor); } + /** + * Register destruction callback + * \param[in] callback destruction callback + */ + template + void set_destruction_callback(T callback) const + { + rs2_error* e = nullptr; + rs2_software_device_set_destruction_callback_cpp(_dev.get(), + new software_device_destruction_callback(std::move(callback)), &e); + error::handle(e); + } + + /** + * 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); + } + + /** + * Add a new camera info value, like serial number + * + * \param[in] info Identifier of the camera info type + * \param[in] val string value to set to this camera info type + */ + void register_info(rs2_camera_info info, const std::string& val) + { + rs2_error* e = nullptr; + rs2_software_device_register_info(_dev.get(), info, val.c_str(), &e); + error::handle(e); + } + + /** + * Update an existing camera info value, like serial number + * + * \param[in] info Identifier of the camera info type + * \param[in] val string value to set to this camera info type + */ + void update_info(rs2_camera_info info, const std::string& val) + { + rs2_error* e = nullptr; + rs2_software_device_update_info(_dev.get(), info, val.c_str(), &e); + error::handle(e); + } + /** * Set the wanted matcher type that will be used by the syncer * \param[in] matcher matcher type @@ -198,5 +363,252 @@ namespace rs2 } }; + class firmware_log_message + { + public: + explicit firmware_log_message(std::shared_ptr msg) : + _fw_log_message(msg) {} + + rs2_log_severity get_severity() const { + rs2_error* e = nullptr; + rs2_log_severity severity = rs2_fw_log_message_severity(_fw_log_message.get(), &e); + error::handle(e); + return severity; + } + std::string get_severity_str() const { + return rs2_log_severity_to_string(get_severity()); + } + + uint32_t get_timestamp() const + { + rs2_error* e = nullptr; + uint32_t timestamp = rs2_fw_log_message_timestamp(_fw_log_message.get(), &e); + error::handle(e); + return timestamp; + } + + int size() const + { + rs2_error* e = nullptr; + int size = rs2_fw_log_message_size(_fw_log_message.get(), &e); + error::handle(e); + return size; + } + + std::vector data() const + { + rs2_error* e = nullptr; + auto size = rs2_fw_log_message_size(_fw_log_message.get(), &e); + error::handle(e); + std::vector result; + if (size > 0) + { + auto start = rs2_fw_log_message_data(_fw_log_message.get(), &e); + error::handle(e); + result.insert(result.begin(), start, start + size); + } + return result; + } + + const std::shared_ptr get_message() const { return _fw_log_message; } + + private: + std::shared_ptr _fw_log_message; + }; + + class firmware_log_parsed_message + { + public: + explicit firmware_log_parsed_message(std::shared_ptr msg) : + _parsed_fw_log(msg) {} + + std::string message() const + { + rs2_error* e = nullptr; + std::string msg(rs2_get_fw_log_parsed_message(_parsed_fw_log.get(), &e)); + error::handle(e); + return msg; + } + std::string file_name() const + { + rs2_error* e = nullptr; + std::string file_name(rs2_get_fw_log_parsed_file_name(_parsed_fw_log.get(), &e)); + error::handle(e); + return file_name; + } + std::string thread_name() const + { + rs2_error* e = nullptr; + std::string thread_name(rs2_get_fw_log_parsed_thread_name(_parsed_fw_log.get(), &e)); + error::handle(e); + return thread_name; + } + std::string severity() const + { + rs2_error* e = nullptr; + rs2_log_severity sev = rs2_get_fw_log_parsed_severity(_parsed_fw_log.get(), &e); + error::handle(e); + return std::string(rs2_log_severity_to_string(sev)); + } + uint32_t line() const + { + rs2_error* e = nullptr; + uint32_t line(rs2_get_fw_log_parsed_line(_parsed_fw_log.get(), &e)); + error::handle(e); + return line; + } + uint32_t timestamp() const + { + rs2_error* e = nullptr; + uint32_t timestamp(rs2_get_fw_log_parsed_timestamp(_parsed_fw_log.get(), &e)); + error::handle(e); + return timestamp; + } + + const std::shared_ptr get_message() const { return _parsed_fw_log; } + + private: + std::shared_ptr _parsed_fw_log; + }; + + class firmware_logger : public device + { + public: + firmware_logger(device d) + : device(d.get()) + { + rs2_error* e = nullptr; + if (rs2_is_device_extendable_to(_dev.get(), RS2_EXTENSION_FW_LOGGER, &e) == 0 && !e) + { + _dev.reset(); + } + error::handle(e); + } + + rs2::firmware_log_message create_message() + { + rs2_error* e = nullptr; + std::shared_ptr msg( + rs2_create_fw_log_message(_dev.get(), &e), + rs2_delete_fw_log_message); + error::handle(e); + + return firmware_log_message(msg); + } + + rs2::firmware_log_parsed_message create_parsed_message() + { + rs2_error* e = nullptr; + std::shared_ptr msg( + rs2_create_fw_log_parsed_message(_dev.get(), &e), + rs2_delete_fw_log_parsed_message); + error::handle(e); + + return firmware_log_parsed_message(msg); + } + + bool get_firmware_log(rs2::firmware_log_message& msg) const + { + rs2_error* e = nullptr; + rs2_firmware_log_message* m = msg.get_message().get(); + bool fw_log_pulling_status = + rs2_get_fw_log(_dev.get(), m, &e); + + error::handle(e); + + return fw_log_pulling_status; + } + + bool get_flash_log(rs2::firmware_log_message& msg) const + { + rs2_error* e = nullptr; + rs2_firmware_log_message* m = msg.get_message().get(); + bool flash_log_pulling_status = + rs2_get_flash_log(_dev.get(), m, &e); + + error::handle(e); + + return flash_log_pulling_status; + } + + bool init_parser(const std::string& xml_content) + { + rs2_error* e = nullptr; + + bool parser_initialized = rs2_init_fw_log_parser(_dev.get(), xml_content.c_str(), &e); + error::handle(e); + + return parser_initialized; + } + + bool parse_log(const rs2::firmware_log_message& msg, const rs2::firmware_log_parsed_message& parsed_msg) + { + rs2_error* e = nullptr; + + bool parsingResult = rs2_parse_firmware_log(_dev.get(), msg.get_message().get(), parsed_msg.get_message().get(), &e); + error::handle(e); + + return parsingResult; + } + }; + + class terminal_parser + { + public: + terminal_parser(const std::string& xml_content) + { + rs2_error* e = nullptr; + + _terminal_parser = std::shared_ptr( + rs2_create_terminal_parser(xml_content.c_str(), &e), + rs2_delete_terminal_parser); + error::handle(e); + } + + std::vector parse_command(const std::string& command) + { + rs2_error* e = nullptr; + + std::shared_ptr list( + rs2_terminal_parse_command(_terminal_parser.get(), command.c_str(), command.size(), &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); + + std::vector results; + results.insert(results.begin(), start, start + size); + + return results; + } + + std::string parse_response(const std::string& command, const std::vector& response) + { + rs2_error* e = nullptr; + + std::shared_ptr list( + rs2_terminal_parse_response(_terminal_parser.get(), command.c_str(), command.size(), + (void*)response.data(), response.size(), &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); + + std::string results; + results.insert(results.begin(), start, start + size); + + return results; + } + + private: + std::shared_ptr _terminal_parser; + }; + } #endif // LIBREALSENSE_RS2_INTERNAL_HPP 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..020c17e --- /dev/null +++ b/libs/realsense2/include/librealsense2/hpp/rs_options.hpp @@ -0,0 +1,159 @@ +// 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 old mode 100755 new mode 100644 index 120a80c..a7f06da --- 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 old mode 100755 new mode 100644 index 66f5c8c..a09f477 --- a/libs/realsense2/include/librealsense2/hpp/rs_processing.hpp +++ b/libs/realsense2/include/librealsense2/hpp/rs_processing.hpp @@ -6,26 +6,27 @@ #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. * \param[in] new_bpp Frame bit per pixel to create. * \param[in] new_width Frame width to create. * \param[in] new_height Frame height to create. - * \param[in] new_stride Frame stride to crate. + * \param[in] new_stride Frame stride to create. * \param[in] frame_type Which frame type are going to create. * \return The allocated frame */ @@ -43,6 +44,35 @@ namespace rs2 error::handle(e); return result; } + + /** + * Allocate a new motion frame with given params + * + * \param[in] profile Stream profile going to allocate. + * \param[in] original Original frame. + * \param[in] frame_type Which frame type are going to create. + * \return The allocated frame + */ + frame allocate_motion_frame(const stream_profile& profile, + const frame& original, + rs2_extension frame_type = RS2_EXTENSION_MOTION_FRAME) const + { + rs2_error* e = nullptr; + auto result = rs2_allocate_synthetic_motion_frame(_source, profile.get(), + original.get(), frame_type, &e); + 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 +131,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 +270,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 +291,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(); } - - private: - std::shared_ptr _block; - }; + operator rs2_options*() const { return (rs2_options*)get(); } + rs2_processing_block* get() const { return _block.get(); } - 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 +430,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 +651,7 @@ namespace rs2 void operator()(frame f) const { - _sync(std::move(f)); + _sync.invoke(std::move(f)); } private: asynchronous_syncer _sync; @@ -431,83 +659,78 @@ 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); + align(rs2_stream align_to) : filter(init(align_to), 1) {} - _block->start(_queue); - } + using filter::process; /** * 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 +739,366 @@ 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) + { + 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) { - (*_block)(std::move(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; + 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 pb = std::shared_ptr( + 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 + disparity_transform(bool transform_to_disparity = true) : filter(init(transform_to_disparity), 1) { } + + disparity_transform(filter f) :filter(f) { - (*_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; + 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); + // Redirect options API to the processing block + //options::operator=(pb); + + return block; + } + }; + + class zero_order_invalidation : public filter + { + public: /** - * process the frame - * \param[in] frame - depth frame to be processed + * Create zero order fix filter + * The filter fixes the zero order artifact */ - void operator()(frame f) const override + zero_order_invalidation() : filter(init()) + {} + + zero_order_invalidation(filter f) :filter(f) { - (*_block)(std::move(f)); + rs2_error* e = nullptr; + if (!rs2_is_processing_block_extendable_to(f.get(), RS2_EXTENSION_ZERO_ORDER_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_zero_order_invalidation_block(&e), + rs2_delete_processing_block); + error::handle(e); + + return block; + } }; - class disparity_transform : public process_interface + class depth_huffman_decoder : public filter { public: /** - * Create disparity transform processing block - * the processing convert the depth and disparity from each pixel + * Create decoder for Huffman-code compressed Depth frames */ - disparity_transform(bool transform_to_disparity=true) :_queue(1) + depth_huffman_decoder() : filter(init()) + {} + + depth_huffman_decoder(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_DEPTH_HUFFMAN_DECODER, &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_huffman_depth_decompress_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 old mode 100755 new mode 100644 index 8352023..1668ef9 --- 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 old mode 100755 new mode 100644 index 21e41ec..45b0247 --- 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,6 @@ 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 { @@ -342,14 +212,13 @@ namespace rs2 error::handle(e); } - /** - * 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 +239,62 @@ namespace rs2 return results; } + /** + * Retrieves the list of stream profiles currently streaming on the sensor. + * \return list of stream profiles that given sensor is streaming + */ + std::vector get_active_streams() const + { + std::vector results{}; + + rs2_error* e = nullptr; + std::shared_ptr list( + rs2_get_active_streams(_sensor.get(), &e), + rs2_delete_stream_profiles_list); + error::handle(e); + + auto size = rs2_get_stream_profiles_count(list.get(), &e); + error::handle(e); + + for (auto i = 0; i < size; i++) + { + stream_profile profile(rs2_get_stream_profile(list.get(), i, &e)); + error::handle(e); + results.push_back(profile); + } + + 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 +336,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 +351,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) @@ -436,6 +370,54 @@ namespace rs2 && std::string(lhs.get_info(RS2_CAMERA_INFO_SERIAL_NUMBER)) == rhs.get_info(RS2_CAMERA_INFO_SERIAL_NUMBER); } + class color_sensor : public sensor + { + public: + color_sensor(sensor s) + : sensor(s.get()) + { + rs2_error* e = nullptr; + if (rs2_is_sensor_extendable_to(_sensor.get(), RS2_EXTENSION_COLOR_SENSOR, &e) == 0 && !e) + { + _sensor.reset(); + } + error::handle(e); + } + operator bool() const { return _sensor.get() != nullptr; } + }; + + class motion_sensor : public sensor + { + public: + motion_sensor(sensor s) + : sensor(s.get()) + { + rs2_error* e = nullptr; + if (rs2_is_sensor_extendable_to(_sensor.get(), RS2_EXTENSION_MOTION_SENSOR, &e) == 0 && !e) + { + _sensor.reset(); + } + error::handle(e); + } + operator bool() const { return _sensor.get() != nullptr; } + }; + + class fisheye_sensor : public sensor + { + public: + fisheye_sensor(sensor s) + : sensor(s.get()) + { + rs2_error* e = nullptr; + if (rs2_is_sensor_extendable_to(_sensor.get(), RS2_EXTENSION_FISHEYE_SENSOR, &e) == 0 && !e) + { + _sensor.reset(); + } + error::handle(e); + } + operator bool() const { return _sensor.get() != nullptr; } + }; + class roi_sensor : public sensor { public: @@ -495,6 +477,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 +493,236 @@ 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 recent 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 + { + std::vector results; + rs2_error* e = nullptr; + const rs2_raw_data_buffer *map = rs2_export_localization_map(_sensor.get(), &e); + error::handle(e); + std::shared_ptr loc_map(map, rs2_delete_raw_data); + + auto start = rs2_get_raw_data(loc_map.get(), &e); + error::handle(e); + + 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; + } + + /** + * Removes a static node from the current map. + * \param[in] guid unique name of the static node (limited to 127 chars). + */ + bool remove_static_node(const std::string& guid) const + { + rs2_error* e = nullptr; + auto res = rs2_remove_static_node(_sensor.get(), guid.c_str(), &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)) {} + }; + + class calibrated_sensor : public sensor + { + public: + calibrated_sensor( sensor s ) + : sensor( s.get() ) + { + rs2_error* e = nullptr; + if( rs2_is_sensor_extendable_to( _sensor.get(), RS2_EXTENSION_CALIBRATED_SENSOR, &e ) == 0 && !e ) + { + _sensor.reset(); + } + error::handle( e ); + } + + operator bool() const { return _sensor.get() != nullptr; } + + /** Override the intrinsics at the sensor level, as DEPTH_TO_RGB calibration does */ + void override_intrinsics( rs2_intrinsics const& intr ) + { + rs2_error* e = nullptr; + rs2_override_intrinsics( _sensor.get(), &intr, &e ); + error::handle( e ); + } + + /** Override the intrinsics at the sensor level, as DEPTH_TO_RGB calibration does */ + void override_extrinsics( rs2_extrinsics const& extr ) + { + rs2_error* e = nullptr; + rs2_override_extrinsics( _sensor.get(), &extr, &e ); + error::handle( e ); + } + + /** Override the intrinsics at the sensor level, as DEPTH_TO_RGB calibration does */ + rs2_dsm_params get_dsm_params() const + { + rs2_error* e = nullptr; + rs2_dsm_params params; + rs2_get_dsm_params( _sensor.get(), ¶ms, &e ); + error::handle( e ); + return params; + } + + /** Set the sensor DSM parameters + * This should ideally be done when the stream is NOT running. If it is, the + * parameters may not take effect immediately. */ + void override_dsm_params( rs2_dsm_params const & params ) + { + rs2_error* e = nullptr; + rs2_override_dsm_params( _sensor.get(), ¶ms, &e ); + error::handle( e ); + } + + /** Reset the sensor DSM calibration + */ + void reset_calibration() + { + rs2_error* e = nullptr; + rs2_reset_sensor_calibration( _sensor.get(), &e ); + error::handle( e ); + } + }; } #endif // LIBREALSENSE_RS2_SENSOR_HPP diff --git a/libs/realsense2/include/librealsense2/hpp/rs_serializable_device.hpp b/libs/realsense2/include/librealsense2/hpp/rs_serializable_device.hpp new file mode 100644 index 0000000..b221a16 --- /dev/null +++ b/libs/realsense2/include/librealsense2/hpp/rs_serializable_device.hpp @@ -0,0 +1,57 @@ +// License: Apache 2.0. See LICENSE file in root directory. +// Copyright(c) 2020 Intel Corporation. All Rights Reserved. + +#pragma once +#include "rs_types.hpp" +#include "rs_device.hpp" +#include +#include + +namespace rs2 +{ + class serializable_device : public rs2::device + { + public: + serializable_device(rs2::device d) + : rs2::device(d.get()) + { + rs2_error* e = nullptr; + if (rs2_is_device_extendable_to(_dev.get(), RS2_EXTENSION_SERIALIZABLE, &e) == 0 && !e) + { + _dev = nullptr; + } + rs2::error::handle(e); + } + + std::string serialize_json() const + { + std::string results; + + rs2_error* e = nullptr; + std::shared_ptr json_data( + rs2_serialize_json(_dev.get(), &e), + rs2_delete_raw_data); + rs2::error::handle(e); + + auto size = rs2_get_raw_data_size(json_data.get(), &e); + rs2::error::handle(e); + + auto start = rs2_get_raw_data(json_data.get(), &e); + rs2::error::handle(e); + + results.insert(results.begin(), start, start + size); + + return results; + } + + void load_json(const std::string& json_content) const + { + rs2_error* e = nullptr; + rs2_load_json(_dev.get(), + json_content.data(), + (unsigned int)json_content.size(), + &e); + rs2::error::handle(e); + } + }; +} diff --git a/libs/realsense2/include/librealsense2/hpp/rs_types.hpp b/libs/realsense2/include/librealsense2/hpp/rs_types.hpp old mode 100755 new mode 100644 index cf6fe84..eece655 --- a/libs/realsense2/include/librealsense2/hpp/rs_types.hpp +++ b/libs/realsense2/include/librealsense2/hpp/rs_types.hpp @@ -43,13 +43,29 @@ struct rs2_notifications_callback virtual ~rs2_notifications_callback() {} }; +typedef void ( *log_callback_function_ptr )(rs2_log_severity severity, rs2_log_message const * msg ); + +struct rs2_software_device_destruction_callback +{ + virtual void on_destruction() = 0; + virtual void release() = 0; + virtual ~rs2_software_device_destruction_callback() {} +}; + struct rs2_log_callback { - virtual void on_event(rs2_log_severity severity, const char * message) = 0; + virtual void on_log( rs2_log_severity severity, rs2_log_message const & msg ) noexcept = 0; virtual void release() = 0; virtual ~rs2_log_callback() {} }; +struct rs2_calibration_change_callback +{ + virtual void on_calibration_change( rs2_calibration_status ) noexcept = 0; + virtual void release() = 0; + virtual ~rs2_calibration_change_callback() {} +}; + struct rs2_devices_changed_callback { virtual void on_devices_changed(rs2_device_list* removed, rs2_device_list* added) = 0; @@ -64,6 +80,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 +190,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 old mode 100755 new mode 100644 index 1cebc0d..5cc362a --- 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 36 #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 */ @@ -37,6 +41,7 @@ extern "C" { #define RS2_API_VERSION (((RS2_API_MAJOR_VERSION) * 10000) + ((RS2_API_MINOR_VERSION) * 100) + (RS2_API_PATCH_VERSION)) /* Return version in "X.Y.Z" format */ #define RS2_API_VERSION_STR (VAR_ARG_STRING(RS2_API_MAJOR_VERSION.RS2_API_MINOR_VERSION.RS2_API_PATCH_VERSION)) +#define RS2_API_FULL_VERSION_STR (VAR_ARG_STRING(RS2_API_MAJOR_VERSION.RS2_API_MINOR_VERSION.RS2_API_PATCH_VERSION.RS2_API_BUILD_VERSION)) /** * get the size of rs2_raw_data_buffer @@ -71,6 +76,16 @@ void rs2_log_to_console(rs2_log_severity min_severity, rs2_error ** error); void rs2_log_to_file(rs2_log_severity min_severity, const char * file_path, rs2_error ** error); +void rs2_log_to_callback_cpp( rs2_log_severity min_severity, rs2_log_callback * callback, rs2_error ** error ); + +void rs2_log_to_callback( rs2_log_severity min_severity, rs2_log_callback_ptr callback, void * arg, rs2_error** error ); + + +unsigned rs2_get_log_message_line_number( rs2_log_message const * msg, rs2_error** error ); +const char * rs2_get_log_message_filename( rs2_log_message const * msg, rs2_error** error ); +const char * rs2_get_raw_log_message( rs2_log_message const * msg, rs2_error** error ); +const char * rs2_get_full_log_message( rs2_log_message const * msg, rs2_error** error ); + /** * Add custom message into librealsense log * \param[in] severity The log level for the message to be written under diff --git a/libs/realsense2/include/librealsense2/rs.hpp b/libs/realsense2/include/librealsense2/rs.hpp old mode 100755 new mode 100644 index 4b58f1a..8922881 --- a/libs/realsense2/include/librealsense2/rs.hpp +++ b/libs/realsense2/include/librealsense2/rs.hpp @@ -30,6 +30,101 @@ namespace rs2 error::handle(e); } + /* + Interface to the log message data we expose. + */ + class log_message + { + // Only log_callback should be creating us! + template< class T > friend class log_callback; + + log_message( rs2_log_message const & msg ) : _msg( msg ) {} + + public: + /* Returns the line-number in the file where the LOG() comment was issued */ + size_t line_number() const + { + rs2_error* e = nullptr; + size_t ln = rs2_get_log_message_line_number( &_msg, &e ); + error::handle( e ); + return ln; + } + /* Returns the file in which the LOG() command was issued */ + const char * filename() const + { + rs2_error* e = nullptr; + const char * path = rs2_get_log_message_filename( &_msg, &e ); + error::handle( e ); + return path; + } + /* Returns the raw message, as it was passed to LOG(), before any embelishments like level etc. */ + const char* raw() const + { + rs2_error* e = nullptr; + const char* r = rs2_get_raw_log_message( &_msg, &e ); + error::handle( e ); + return r; + } + /* + Returns a complete log message, as defined by librealsense, with level, timestamp, etc.: + 11/12 13:49:40,153 INFO [10604] (rs.cpp:2271) Framebuffer size changed to 1552 x 919 + */ + const char* full() const + { + rs2_error* e = nullptr; + const char* str = rs2_get_full_log_message( &_msg, &e ); + error::handle( e ); + return str; + } + + private: + rs2_log_message const & _msg; + }; + + /* + Wrapper around any callback function that is given to log_to_callback. + */ + template + class log_callback : public rs2_log_callback + { + T on_log_function; + public: + explicit log_callback( T on_log ) : on_log_function( on_log ) {} + + void on_log( rs2_log_severity severity, rs2_log_message const & msg ) noexcept override + { + on_log_function( severity, log_message( msg )); + } + + void release() override { delete this; } + }; + + /* + Your callback should look like this, for example: + void callback( rs2_log_severity severity, rs2::log_message const & msg ) noexcept + { + std::cout << msg.build() << std::endl; + } + and, when initializing rs2: + rs2::log_to_callback( callback ); + or: + rs2::log_to_callback( + []( rs2_log_severity severity, rs2::log_message const & msg ) noexcept + { + std::cout << msg.build() << std::endl; + }) + */ + template< typename S > + inline void log_to_callback( rs2_log_severity min_severity, S callback ) + { + // We wrap the callback with an interface and pass it to librealsense, who will + // now manage its lifetime. Rather than deleting it, though, it will call its + // release() function, where (back in our context) it can be safely deleted: + rs2_error* e = nullptr; + rs2_log_to_callback_cpp( min_severity, new log_callback< S >( std::move( callback )), &e ); + error::handle( e ); + } + inline void log(rs2_log_severity severity, const char* message) { rs2_error* e = nullptr; @@ -41,8 +136,9 @@ 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::log_message const & msg ) { return o << msg.raw(); } 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); } inline std::ostream & operator << (std::ostream & o, rs2_timestamp_domain domain) { return o << rs2_timestamp_domain_to_string(domain); } @@ -50,5 +146,9 @@ inline std::ostream & operator << (std::ostream & o, rs2_notification_category n inline std::ostream & operator << (std::ostream & o, rs2_sr300_visual_preset preset) { return o << rs2_sr300_visual_preset_to_string(preset); } inline std::ostream & operator << (std::ostream & o, rs2_exception_type exception_type) { return o << rs2_exception_type_to_string(exception_type); } inline std::ostream & operator << (std::ostream & o, rs2_playback_status status) { return o << rs2_playback_status_to_string(status); } +inline std::ostream & operator << (std::ostream & o, rs2_l500_visual_preset preset) {return o << rs2_l500_visual_preset_to_string(preset);} +inline std::ostream & operator << (std::ostream & o, rs2_sensor_mode mode) { return o << rs2_sensor_mode_to_string(mode); } +inline std::ostream & operator << (std::ostream & o, rs2_calibration_type mode) { return o << rs2_calibration_type_to_string(mode); } +inline std::ostream & operator << (std::ostream & o, rs2_calibration_status mode) { return o << rs2_calibration_status_to_string(mode); } #endif // LIBREALSENSE_RS2_HPP diff --git a/libs/realsense2/include/librealsense2/rs_advanced_mode.h b/libs/realsense2/include/librealsense2/rs_advanced_mode.h old mode 100755 new mode 100644 index 0849257..a963037 --- a/libs/realsense2/include/librealsense2/rs_advanced_mode.h +++ b/libs/realsense2/include/librealsense2/rs_advanced_mode.h @@ -88,11 +88,10 @@ 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); -/* 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); +void rs2_set_amp_factor(rs2_device* dev, const STAFactor* group, rs2_error** error); -/* Serialize JSON content, returns 0 if success */ -rs2_raw_data_buffer* rs2_serialize_json(rs2_device* dev, 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); #ifdef __cplusplus } diff --git a/libs/realsense2/include/librealsense2/rs_advanced_mode.hpp b/libs/realsense2/include/librealsense2/rs_advanced_mode.hpp old mode 100755 new mode 100644 index 4570755..6bad55d --- a/libs/realsense2/include/librealsense2/rs_advanced_mode.hpp +++ b/libs/realsense2/include/librealsense2/rs_advanced_mode.hpp @@ -4,19 +4,21 @@ #ifndef R4XX_ADVANCED_MODE_HPP #define R4XX_ADVANCED_MODE_HPP +#include #include "rs.hpp" #include "rs_advanced_mode.h" +#include "hpp/rs_serializable_device.hpp" namespace rs400 { - class advanced_mode : public rs2::device + class advanced_mode : public rs2::serializable_device { public: advanced_mode(rs2::device d) - : rs2::device(d.get()) + : rs2::serializable_device(d) { rs2_error* e = nullptr; - if(rs2_is_device_extendable_to(_dev.get(), RS2_EXTENSION_ADVANCED_MODE, &e) == 0 && !e) + if(_dev && rs2_is_device_extendable_to(_dev.get(), RS2_EXTENSION_ADVANCED_MODE, &e) == 0 && !e) { _dev = nullptr; } @@ -244,35 +246,21 @@ namespace rs400 return group; } - std::string serialize_json() const + void set_amp_factor(const STAFactor& group) { - std::string results; - rs2_error* e = nullptr; - std::shared_ptr json_data( - rs2_serialize_json(_dev.get(), &e), - rs2_delete_raw_data); - rs2::error::handle(e); - - auto size = rs2_get_raw_data_size(json_data.get(), &e); + rs2_set_amp_factor(_dev.get(), &group, &e); rs2::error::handle(e); - - auto start = rs2_get_raw_data(json_data.get(), &e); - rs2::error::handle(e); - - results.insert(results.begin(), start, start + size); - - return results; } - void load_json(const std::string& json_content) + STAFactor get_amp_factor(int mode = 0) const { rs2_error* e = nullptr; - rs2_load_json(_dev.get(), - json_content.data(), - (unsigned int)json_content.size(), - &e); + STAFactor group{}; + rs2_get_amp_factor(_dev.get(), &group, mode, &e); rs2::error::handle(e); + + return group; } }; } @@ -389,5 +377,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 old mode 100755 new mode 100644 index e6218b1..35260e4 --- 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; @@ -30,13 +33,47 @@ static void rs2_project_point_to_pixel(float pixel[2], const struct rs2_intrinsi x = dx; y = dy; } + + if (intrin->model == RS2_DISTORTION_BROWN_CONRADY) + { + float r2 = x * x + y * y; + float f = 1 + intrin->coeffs[0] * r2 + intrin->coeffs[1] * r2*r2 + intrin->coeffs[4] * r2*r2*r2; + + float xf = x * f; + float yf = y * f; + + float dx = xf + 2 * intrin->coeffs[2] * x*y + intrin->coeffs[3] * (r2 + 2 * x*x); + float dy = yf + 2 * intrin->coeffs[3] * x*y + intrin->coeffs[2] * (r2 + 2 * y*y); + + x = dx; + y = dy; + } + 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 +83,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 +96,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 +153,79 @@ 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 diff --git a/libs/realsense2/lib/osx/librealsense2.2.14.1.dylib b/libs/realsense2/lib/osx/librealsense2.2.14.1.dylib deleted file mode 100755 index b6e64b8..0000000 Binary files a/libs/realsense2/lib/osx/librealsense2.2.14.1.dylib and /dev/null differ diff --git a/libs/realsense2/lib/osx/librealsense2.2.36.0.dylib b/libs/realsense2/lib/osx/librealsense2.2.36.0.dylib new file mode 100644 index 0000000..d05053e Binary files /dev/null and b/libs/realsense2/lib/osx/librealsense2.2.36.0.dylib differ diff --git a/libs/realsense2/lib/osx/librealsense2.2.36.dylib b/libs/realsense2/lib/osx/librealsense2.2.36.dylib new file mode 120000 index 0000000..bfde85f --- /dev/null +++ b/libs/realsense2/lib/osx/librealsense2.2.36.dylib @@ -0,0 +1 @@ +librealsense2.2.36.0.dylib \ No newline at end of file diff --git a/libs/realsense2/lib/osx/librealsense2.2.dylib b/libs/realsense2/lib/osx/librealsense2.2.dylib deleted file mode 120000 index 18b192a..0000000 --- a/libs/realsense2/lib/osx/librealsense2.2.dylib +++ /dev/null @@ -1 +0,0 @@ -librealsense2.2.14.1.dylib \ No newline at end of file diff --git a/libs/realsense2/lib/osx/librealsense2.dylib b/libs/realsense2/lib/osx/librealsense2.dylib index d37581b..86c170c 120000 --- a/libs/realsense2/lib/osx/librealsense2.dylib +++ b/libs/realsense2/lib/osx/librealsense2.dylib @@ -1 +1 @@ -librealsense2.2.dylib \ No newline at end of file +librealsense2.2.36.dylib \ No newline at end of file