From 221f5bd6a1e2ef062816bd4deefb5d922add7c12 Mon Sep 17 00:00:00 2001 From: NirAz Date: Tue, 20 Oct 2020 13:49:53 +0300 Subject: [PATCH 01/14] Add max usable range option and API - skelton --- include/librealsense2/h/rs_option.h | 1 + include/librealsense2/h/rs_sensor.h | 6 ++++++ include/librealsense2/h/rs_types.h | 1 + include/librealsense2/hpp/rs_sensor.hpp | 11 +++++++++++ src/CMakeLists.txt | 1 + src/l500/l500-depth.cpp | 6 ++++++ src/l500/l500-depth.h | 4 ++++ src/l500/l500-device.cpp | 3 +++ src/l500/l500-options.cpp | 21 ++++++++++++++++++++- src/l500/l500-options.h | 11 +++++++++++ src/max-usable-range-sensor.h | 16 ++++++++++++++++ src/rs.cpp | 10 ++++++++++ src/types.cpp | 2 ++ 13 files changed, 92 insertions(+), 1 deletion(-) create mode 100644 src/max-usable-range-sensor.h diff --git a/include/librealsense2/h/rs_option.h b/include/librealsense2/h/rs_option.h index dee52bcee1..f121e3590d 100644 --- a/include/librealsense2/h/rs_option.h +++ b/include/librealsense2/h/rs_option.h @@ -103,6 +103,7 @@ extern "C" { RS2_OPTION_SEQUENCE_SIZE, /**< HDR Sequence size */ RS2_OPTION_SEQUENCE_ID, /**< HDR Sequence ID - 0 is not HDR; sequence ID for HDR configuration starts from 1 */ RS2_OPTION_HUMIDITY_TEMPERATURE, /**< Humidity temperature [Deg Celsius]*/ + RS2_OPTION_MAX_USABLE_RANGE, /**< Maximum usable range under current environment conditions [m]*/ RS2_OPTION_COUNT /**< Number of enumeration values. Not a valid input: intended to be used in for-loops. */ } rs2_option; diff --git a/include/librealsense2/h/rs_sensor.h b/include/librealsense2/h/rs_sensor.h index 7dce6a1f43..f45c81fd55 100644 --- a/include/librealsense2/h/rs_sensor.h +++ b/include/librealsense2/h/rs_sensor.h @@ -647,6 +647,12 @@ void rs2_reset_sensor_calibration( rs2_sensor const * sensor, rs2_error** error */ void rs2_set_motion_device_intrinsics(const rs2_sensor* sensor, const rs2_stream_profile* profile, const rs2_motion_device_intrinsic* intrinsics, rs2_error** error); +/** When called on a depth sensor, this method will return the maximum range of the camera given the amount of ambient light in the scene +* \param[in] sensor depth sensor +* \param[out] error if non-null, receives any error that occurs during this call, otherwise, errors are ignored +* \return the max usable range in meters +*/ +float rs2_get_max_usable_range(rs2_sensor* sensor, rs2_error** error); #ifdef __cplusplus } diff --git a/include/librealsense2/h/rs_types.h b/include/librealsense2/h/rs_types.h index ee8d6aff85..a9a553a397 100644 --- a/include/librealsense2/h/rs_types.h +++ b/include/librealsense2/h/rs_types.h @@ -212,6 +212,7 @@ typedef enum rs2_extension RS2_EXTENSION_CALIBRATED_SENSOR, RS2_EXTENSION_HDR_MERGE, RS2_EXTENSION_SEQUENCE_ID_FILTER, + RS2_EXTENSION_MAX_USABLE_RANGE_SENSOR, RS2_EXTENSION_COUNT } rs2_extension; const char* rs2_extension_type_to_string(rs2_extension type); diff --git a/include/librealsense2/hpp/rs_sensor.hpp b/include/librealsense2/hpp/rs_sensor.hpp index 45b0247455..e8eed23512 100644 --- a/include/librealsense2/hpp/rs_sensor.hpp +++ b/include/librealsense2/hpp/rs_sensor.hpp @@ -476,6 +476,17 @@ namespace rs2 return res; } + /** Retrieves the maximum range of the camera given the amount of ambient light in the scene. + * \return max usable range in meters + */ + float get_max_usable_range() const + { + rs2_error* e = nullptr; + auto res = rs2_get_max_usable_range(_sensor.get(), &e); + error::handle(e); + return res; + } + operator bool() const { return _sensor.get() != nullptr; } explicit depth_sensor(std::shared_ptr dev) : depth_sensor(sensor(dev)) {} }; diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 9de255e0c2..cfaff00f0b 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -132,4 +132,5 @@ target_sources(${LRS_TARGET} "${CMAKE_CURRENT_LIST_DIR}/calibrated-sensor.h" "${CMAKE_CURRENT_LIST_DIR}/serializable-interface.h" "${CMAKE_CURRENT_LIST_DIR}/depth-to-rgb-calibration.h" + "${CMAKE_CURRENT_LIST_DIR}/max-usable-range-sensor.h" ) diff --git a/src/l500/l500-depth.cpp b/src/l500/l500-depth.cpp index e7b8cf3c66..aab187aac1 100644 --- a/src/l500/l500-depth.cpp +++ b/src/l500/l500-depth.cpp @@ -354,6 +354,12 @@ namespace librealsense AC_LOG( INFO, "Depth sensor calibration has been reset" ); } + float l500_depth_sensor::get_max_usable_range() + { + // TODO Add real implementation + static int cnt = 0; + return cnt++ % 100; + } float l500_depth_sensor::read_baseline() const { diff --git a/src/l500/l500-depth.h b/src/l500/l500-depth.h index e9d0267e5e..e17aadb991 100644 --- a/src/l500/l500-depth.h +++ b/src/l500/l500-depth.h @@ -18,6 +18,7 @@ #include "error-handling.h" #include "l500-options.h" #include "calibrated-sensor.h" +#include "max-usable-range-sensor.h" namespace librealsense { @@ -92,6 +93,7 @@ namespace librealsense , public virtual depth_sensor , public virtual l500_depth_sensor_interface , public calibrated_sensor + , public max_usable_range_sensor { public: explicit l500_depth_sensor( @@ -218,6 +220,8 @@ namespace librealsense return *_owner->_calib_table; } + float get_max_usable_range() override; + void create_snapshot(std::shared_ptr& snapshot) const override { snapshot = std::make_shared(get_depth_scale()); diff --git a/src/l500/l500-device.cpp b/src/l500/l500-device.cpp index 262fa62649..248036a3b3 100644 --- a/src/l500/l500-device.cpp +++ b/src/l500/l500-device.cpp @@ -208,6 +208,9 @@ namespace librealsense is_zo_enabled_opt->set(false); depth_sensor.register_option(RS2_OPTION_ZERO_ORDER_ENABLED, is_zo_enabled_opt); + auto enable_max_usable_range = std::make_shared(); + depth_sensor.register_option(RS2_OPTION_MAX_USABLE_RANGE, enable_max_usable_range); + if( _fw_version >= firmware_version( "1.5.0.0" ) ) { // TODO may not need auto-cal if there's no color sensor, like on the rs500... diff --git a/src/l500/l500-options.cpp b/src/l500/l500-options.cpp index e786d41d19..d36945c2a6 100644 --- a/src/l500/l500-options.cpp +++ b/src/l500/l500-options.cpp @@ -286,4 +286,23 @@ namespace librealsense auto range = _hw_options[RS2_OPTION_LASER_POWER]->get_range(); _hw_options[RS2_OPTION_LASER_POWER]->set_with_no_signal(range.max); } -} + + void max_usable_range_option::set(float value) + { + // TODO if conditions are not meet throw exception! + bool_option::set(value); + } + + + + const char * max_usable_range_option::get_description() const + { + + return "Max Usable Range calculates the maximum range of the camera given the amount of " + "ambient light in the scene.\n" + "For example, if Max Usable Range returns 5m, this means that the ambient light in " + "the scene is reducing the maximum range from 9m down to 5m.\n" + "Values are rounded to whole meter values and are between 3 meters and 9 meters. " + "Max range refers to the center 10% of the frame."; + } +} // namespace librealsense diff --git a/src/l500/l500-options.h b/src/l500/l500-options.h index bb3c38245d..6e3f2714b7 100644 --- a/src/l500/l500-options.h +++ b/src/l500/l500-options.h @@ -61,6 +61,17 @@ namespace librealsense std::string _description; }; + + class max_usable_range_option : public bool_option + { + public: + max_usable_range_option() : bool_option( false ){}; + + void set(float value) override; + + const char * get_description() const override; + }; + class l500_options: public virtual l500_device { public: diff --git a/src/max-usable-range-sensor.h b/src/max-usable-range-sensor.h new file mode 100644 index 0000000000..4d413b55c6 --- /dev/null +++ b/src/max-usable-range-sensor.h @@ -0,0 +1,16 @@ +// License: Apache 2.0. See LICENSE file in root directory. +// Copyright(c) 2020 Intel Corporation. All Rights Reserved. + +#pragma once + +#include "types.h" + +namespace librealsense +{ + class max_usable_range_sensor + { + public: + virtual float get_max_usable_range( ) = 0; + }; + MAP_EXTENSION(RS2_EXTENSION_MAX_USABLE_RANGE_SENSOR, max_usable_range_sensor); +} diff --git a/src/rs.cpp b/src/rs.cpp index d861e06da3..06d05797d1 100644 --- a/src/rs.cpp +++ b/src/rs.cpp @@ -2290,6 +2290,16 @@ float rs2_get_depth_scale(rs2_sensor* sensor, rs2_error** error) BEGIN_API_CALL } HANDLE_EXCEPTIONS_AND_RETURN(0.f, sensor) +float rs2_get_max_usable_range(const rs2_sensor* sensor, rs2_error** error) BEGIN_API_CALL +{ + VALIDATE_NOT_NULL(sensor); + + auto murs = VALIDATE_INTERFACE(sensor->sensor, librealsense::max_usable_range_sensor); + return murs->get_max_usable_range(); +} + +HANDLE_EXCEPTIONS_AND_RETURN(0.f, sensor) + float rs2_get_stereo_baseline(rs2_sensor* sensor, rs2_error** error) BEGIN_API_CALL { VALIDATE_NOT_NULL(sensor); diff --git a/src/types.cpp b/src/types.cpp index 9b0abc7f77..08dfc52876 100644 --- a/src/types.cpp +++ b/src/types.cpp @@ -323,6 +323,7 @@ namespace librealsense CASE(CALIBRATED_SENSOR) CASE(SEQUENCE_ID_FILTER) CASE(HDR_MERGE) + CASE(MAX_USABLE_RANGE_SENSOR) default: assert(!is_valid(value)); return UNKNOWN_VALUE; } #undef CASE @@ -445,6 +446,7 @@ namespace librealsense CASE(SEQUENCE_SIZE) CASE(SEQUENCE_ID) CASE(HUMIDITY_TEMPERATURE) + CASE(MAX_USABLE_RANGE) default: assert(!is_valid(value)); return UNKNOWN_VALUE; } #undef CASE From fe2c550ff5e9b826033e52bd8e0155c53354bbac Mon Sep 17 00:00:00 2001 From: NirAz Date: Wed, 21 Oct 2020 12:19:20 +0300 Subject: [PATCH 02/14] Add new API to all wrappers --- include/librealsense2/h/rs_option.h | 2 +- include/librealsense2/h/rs_sensor.h | 2 +- include/librealsense2/hpp/rs_sensor.hpp | 39 +++++++++++++------ src/l500/l500-depth.cpp | 2 +- src/l500/l500-depth.h | 2 +- src/max-usable-range-sensor.h | 2 +- src/realsense.def | 2 + src/rs.cpp | 34 ++++++++-------- .../realsense/librealsense/Extension.java | 3 +- .../intel/realsense/librealsense/Option.java | 3 +- .../csharp/Intel.RealSense/NativeMethods.cs | 8 +++- .../Intel.RealSense/Sensors/CMakeLists.txt | 1 + .../Sensors/MaxUsableRangeSensor.cs | 26 +++++++++++++ .../Intel.RealSense/Types/Enums/Extension.cs | 5 ++- .../Intel.RealSense/Types/Enums/Option.cs | 5 ++- wrappers/matlab/option.m | 3 +- wrappers/nodejs/index.js | 3 ++ wrappers/nodejs/src/addon.cpp | 1 + wrappers/python/pybackend.cpp | 1 + wrappers/python/pyrs_sensor.cpp | 12 +++++- .../Source/RealSense/Public/RealSenseTypes.h | 1 + 21 files changed, 115 insertions(+), 42 deletions(-) create mode 100644 wrappers/csharp/Intel.RealSense/Sensors/MaxUsableRangeSensor.cs diff --git a/include/librealsense2/h/rs_option.h b/include/librealsense2/h/rs_option.h index f121e3590d..55a6d15bec 100644 --- a/include/librealsense2/h/rs_option.h +++ b/include/librealsense2/h/rs_option.h @@ -103,7 +103,7 @@ extern "C" { RS2_OPTION_SEQUENCE_SIZE, /**< HDR Sequence size */ RS2_OPTION_SEQUENCE_ID, /**< HDR Sequence ID - 0 is not HDR; sequence ID for HDR configuration starts from 1 */ RS2_OPTION_HUMIDITY_TEMPERATURE, /**< Humidity temperature [Deg Celsius]*/ - RS2_OPTION_MAX_USABLE_RANGE, /**< Maximum usable range under current environment conditions [m]*/ + RS2_OPTION_MAX_USABLE_RANGE, /**< Turn on/off the maximum usable range who calculates the maximum range of the camera given the amount of ambient light in the scene */ RS2_OPTION_COUNT /**< Number of enumeration values. Not a valid input: intended to be used in for-loops. */ } rs2_option; diff --git a/include/librealsense2/h/rs_sensor.h b/include/librealsense2/h/rs_sensor.h index f45c81fd55..06782f078c 100644 --- a/include/librealsense2/h/rs_sensor.h +++ b/include/librealsense2/h/rs_sensor.h @@ -652,7 +652,7 @@ void rs2_set_motion_device_intrinsics(const rs2_sensor* sensor, const rs2_stream * \param[out] error if non-null, receives any error that occurs during this call, otherwise, errors are ignored * \return the max usable range in meters */ -float rs2_get_max_usable_range(rs2_sensor* sensor, rs2_error** error); +float rs2_get_max_usable_range(rs2_sensor const * sensor, rs2_error** error); #ifdef __cplusplus } diff --git a/include/librealsense2/hpp/rs_sensor.hpp b/include/librealsense2/hpp/rs_sensor.hpp index e8eed23512..0fbf82ff0b 100644 --- a/include/librealsense2/hpp/rs_sensor.hpp +++ b/include/librealsense2/hpp/rs_sensor.hpp @@ -476,17 +476,6 @@ namespace rs2 return res; } - /** Retrieves the maximum range of the camera given the amount of ambient light in the scene. - * \return max usable range in meters - */ - float get_max_usable_range() const - { - rs2_error* e = nullptr; - auto res = rs2_get_max_usable_range(_sensor.get(), &e); - error::handle(e); - return res; - } - operator bool() const { return _sensor.get() != nullptr; } explicit depth_sensor(std::shared_ptr dev) : depth_sensor(sensor(dev)) {} }; @@ -735,5 +724,33 @@ namespace rs2 error::handle( e ); } }; + + class max_usable_range_sensor : public sensor + { + public: + max_usable_range_sensor(sensor s) + : sensor(s.get()) + { + rs2_error* e = nullptr; + if (rs2_is_sensor_extendable_to(_sensor.get(), RS2_EXTENSION_MAX_USABLE_RANGE_SENSOR, &e) == 0 && !e) + { + _sensor.reset(); + } + error::handle(e); + } + + operator bool() const { return _sensor.get() != nullptr; } + + /** Retrieves the maximum range of the camera given the amount of ambient light in the scene. + * \return max usable range in meters + */ + float get_max_usable_range() const + { + rs2_error* e = nullptr; + auto res = rs2_get_max_usable_range(_sensor.get(), &e); + error::handle(e); + return res; + } + }; } #endif // LIBREALSENSE_RS2_SENSOR_HPP diff --git a/src/l500/l500-depth.cpp b/src/l500/l500-depth.cpp index aab187aac1..1b8e66323c 100644 --- a/src/l500/l500-depth.cpp +++ b/src/l500/l500-depth.cpp @@ -354,7 +354,7 @@ namespace librealsense AC_LOG( INFO, "Depth sensor calibration has been reset" ); } - float l500_depth_sensor::get_max_usable_range() + float l500_depth_sensor::get_max_usable_range() const { // TODO Add real implementation static int cnt = 0; diff --git a/src/l500/l500-depth.h b/src/l500/l500-depth.h index e17aadb991..c7d0cf4bf5 100644 --- a/src/l500/l500-depth.h +++ b/src/l500/l500-depth.h @@ -220,7 +220,7 @@ namespace librealsense return *_owner->_calib_table; } - float get_max_usable_range() override; + float get_max_usable_range() const override; void create_snapshot(std::shared_ptr& snapshot) const override { diff --git a/src/max-usable-range-sensor.h b/src/max-usable-range-sensor.h index 4d413b55c6..99f2aabfbe 100644 --- a/src/max-usable-range-sensor.h +++ b/src/max-usable-range-sensor.h @@ -10,7 +10,7 @@ namespace librealsense class max_usable_range_sensor { public: - virtual float get_max_usable_range( ) = 0; + virtual float get_max_usable_range( ) const = 0; }; MAP_EXTENSION(RS2_EXTENSION_MAX_USABLE_RANGE_SENSOR, max_usable_range_sensor); } diff --git a/src/realsense.def b/src/realsense.def index 5d846aa350..aed7c24c21 100644 --- a/src/realsense.def +++ b/src/realsense.def @@ -394,5 +394,7 @@ EXPORTS rs2_delete_terminal_parser rs2_terminal_parse_command rs2_terminal_parse_response + + rs2_get_max_usable_range diff --git a/src/rs.cpp b/src/rs.cpp index 06d05797d1..ab5f96b9d5 100644 --- a/src/rs.cpp +++ b/src/rs.cpp @@ -1374,21 +1374,23 @@ int rs2_is_sensor_extendable_to(const rs2_sensor* sensor, rs2_extension extensio VALIDATE_ENUM(extension_type); switch (extension_type) { - case RS2_EXTENSION_DEBUG : return VALIDATE_INTERFACE_NO_THROW(sensor->sensor, librealsense::debug_interface) != nullptr; - case RS2_EXTENSION_INFO : return VALIDATE_INTERFACE_NO_THROW(sensor->sensor, librealsense::info_interface) != nullptr; - case RS2_EXTENSION_OPTIONS : return VALIDATE_INTERFACE_NO_THROW(sensor->sensor, librealsense::options_interface) != nullptr; - case RS2_EXTENSION_VIDEO : return VALIDATE_INTERFACE_NO_THROW(sensor->sensor, librealsense::video_sensor_interface) != nullptr; - case RS2_EXTENSION_ROI : return VALIDATE_INTERFACE_NO_THROW(sensor->sensor, librealsense::roi_sensor_interface) != nullptr; - case RS2_EXTENSION_DEPTH_SENSOR : return VALIDATE_INTERFACE_NO_THROW(sensor->sensor, librealsense::depth_sensor) != nullptr; - case RS2_EXTENSION_DEPTH_STEREO_SENSOR : return VALIDATE_INTERFACE_NO_THROW(sensor->sensor, librealsense::depth_stereo_sensor) != nullptr; - case RS2_EXTENSION_SOFTWARE_SENSOR : return VALIDATE_INTERFACE_NO_THROW(sensor->sensor, librealsense::software_sensor) != nullptr; - case RS2_EXTENSION_POSE_SENSOR : return VALIDATE_INTERFACE_NO_THROW(sensor->sensor, librealsense::pose_sensor_interface) != nullptr; - case RS2_EXTENSION_WHEEL_ODOMETER : return VALIDATE_INTERFACE_NO_THROW(sensor->sensor, librealsense::wheel_odometry_interface)!= nullptr; - case RS2_EXTENSION_TM2_SENSOR : return VALIDATE_INTERFACE_NO_THROW(sensor->sensor, librealsense::tm2_sensor_interface) != nullptr; - case RS2_EXTENSION_COLOR_SENSOR : return VALIDATE_INTERFACE_NO_THROW(sensor->sensor, librealsense::color_sensor) != nullptr; - case RS2_EXTENSION_MOTION_SENSOR : return VALIDATE_INTERFACE_NO_THROW(sensor->sensor, librealsense::motion_sensor) != nullptr; - case RS2_EXTENSION_FISHEYE_SENSOR : return VALIDATE_INTERFACE_NO_THROW(sensor->sensor, librealsense::fisheye_sensor) != nullptr; - case RS2_EXTENSION_CALIBRATED_SENSOR : return VALIDATE_INTERFACE_NO_THROW(sensor->sensor, librealsense::calibrated_sensor) != nullptr; + case RS2_EXTENSION_DEBUG : return VALIDATE_INTERFACE_NO_THROW(sensor->sensor, librealsense::debug_interface) != nullptr; + case RS2_EXTENSION_INFO : return VALIDATE_INTERFACE_NO_THROW(sensor->sensor, librealsense::info_interface) != nullptr; + case RS2_EXTENSION_OPTIONS : return VALIDATE_INTERFACE_NO_THROW(sensor->sensor, librealsense::options_interface) != nullptr; + case RS2_EXTENSION_VIDEO : return VALIDATE_INTERFACE_NO_THROW(sensor->sensor, librealsense::video_sensor_interface) != nullptr; + case RS2_EXTENSION_ROI : return VALIDATE_INTERFACE_NO_THROW(sensor->sensor, librealsense::roi_sensor_interface) != nullptr; + case RS2_EXTENSION_DEPTH_SENSOR : return VALIDATE_INTERFACE_NO_THROW(sensor->sensor, librealsense::depth_sensor) != nullptr; + case RS2_EXTENSION_DEPTH_STEREO_SENSOR : return VALIDATE_INTERFACE_NO_THROW(sensor->sensor, librealsense::depth_stereo_sensor) != nullptr; + case RS2_EXTENSION_SOFTWARE_SENSOR : return VALIDATE_INTERFACE_NO_THROW(sensor->sensor, librealsense::software_sensor) != nullptr; + case RS2_EXTENSION_POSE_SENSOR : return VALIDATE_INTERFACE_NO_THROW(sensor->sensor, librealsense::pose_sensor_interface) != nullptr; + case RS2_EXTENSION_WHEEL_ODOMETER : return VALIDATE_INTERFACE_NO_THROW(sensor->sensor, librealsense::wheel_odometry_interface)!= nullptr; + case RS2_EXTENSION_TM2_SENSOR : return VALIDATE_INTERFACE_NO_THROW(sensor->sensor, librealsense::tm2_sensor_interface) != nullptr; + case RS2_EXTENSION_COLOR_SENSOR : return VALIDATE_INTERFACE_NO_THROW(sensor->sensor, librealsense::color_sensor) != nullptr; + case RS2_EXTENSION_MOTION_SENSOR : return VALIDATE_INTERFACE_NO_THROW(sensor->sensor, librealsense::motion_sensor) != nullptr; + case RS2_EXTENSION_FISHEYE_SENSOR : return VALIDATE_INTERFACE_NO_THROW(sensor->sensor, librealsense::fisheye_sensor) != nullptr; + case RS2_EXTENSION_CALIBRATED_SENSOR : return VALIDATE_INTERFACE_NO_THROW(sensor->sensor, librealsense::calibrated_sensor) != nullptr; + case RS2_EXTENSION_MAX_USABLE_RANGE_SENSOR : return VALIDATE_INTERFACE_NO_THROW(sensor->sensor, librealsense::max_usable_range_sensor) != nullptr; + default: return false; @@ -2290,7 +2292,7 @@ float rs2_get_depth_scale(rs2_sensor* sensor, rs2_error** error) BEGIN_API_CALL } HANDLE_EXCEPTIONS_AND_RETURN(0.f, sensor) -float rs2_get_max_usable_range(const rs2_sensor* sensor, rs2_error** error) BEGIN_API_CALL +float rs2_get_max_usable_range(rs2_sensor const * sensor, rs2_error** error) BEGIN_API_CALL { VALIDATE_NOT_NULL(sensor); diff --git a/wrappers/android/librealsense/src/main/java/com/intel/realsense/librealsense/Extension.java b/wrappers/android/librealsense/src/main/java/com/intel/realsense/librealsense/Extension.java index 94a83d7fbb..a8f12feb11 100644 --- a/wrappers/android/librealsense/src/main/java/com/intel/realsense/librealsense/Extension.java +++ b/wrappers/android/librealsense/src/main/java/com/intel/realsense/librealsense/Extension.java @@ -53,7 +53,8 @@ public enum Extension { DEVICE_CALIBRATION(49), CALIBRATED_SENSOR(50), HDR_MERGE(51), - SEQUENCE_ID_FILTER(52); + SEQUENCE_ID_FILTER(52), + MAX_USABLE_RANGE_SENSOR(53); private final int mValue; diff --git a/wrappers/android/librealsense/src/main/java/com/intel/realsense/librealsense/Option.java b/wrappers/android/librealsense/src/main/java/com/intel/realsense/librealsense/Option.java index c3800d714f..32f4858aa4 100644 --- a/wrappers/android/librealsense/src/main/java/com/intel/realsense/librealsense/Option.java +++ b/wrappers/android/librealsense/src/main/java/com/intel/realsense/librealsense/Option.java @@ -82,7 +82,8 @@ public enum Option { SEQUENCE_NAME(77), SEQUENCE_SIZE(78), SEQUENCE_ID(79), - HUMIDITY_TEMPERATURE(80); + HUMIDITY_TEMPERATURE(80), + MAX_USABLE_RANGE(81); private final int mValue; private Option(int value) { mValue = value; } diff --git a/wrappers/csharp/Intel.RealSense/NativeMethods.cs b/wrappers/csharp/Intel.RealSense/NativeMethods.cs index e2805a95af..2fca6dc711 100644 --- a/wrappers/csharp/Intel.RealSense/NativeMethods.cs +++ b/wrappers/csharp/Intel.RealSense/NativeMethods.cs @@ -473,9 +473,13 @@ internal static MemCpyDelegate GetMethod() [DllImport(dllName, CallingConvention = CallingConvention.Cdecl)] internal static extern void rs2_get_motion_intrinsics(IntPtr profile, out MotionDeviceIntrinsics intrinsics, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(ErrorMarshaler))] out object error); -#endregion -#region rs_device [DllImport(dllName, CallingConvention = CallingConvention.Cdecl)] + internal static extern float rs2_get_max_usable_range(IntPtr sensor, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(ErrorMarshaler))] out object error); + + + #endregion + #region rs_device + [DllImport(dllName, CallingConvention = CallingConvention.Cdecl)] internal static extern int rs2_get_device_count(IntPtr info_list, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(ErrorMarshaler))] out object error); [DllImport(dllName, CallingConvention = CallingConvention.Cdecl)] diff --git a/wrappers/csharp/Intel.RealSense/Sensors/CMakeLists.txt b/wrappers/csharp/Intel.RealSense/Sensors/CMakeLists.txt index c5f3ea45c6..91d67e5f8f 100644 --- a/wrappers/csharp/Intel.RealSense/Sensors/CMakeLists.txt +++ b/wrappers/csharp/Intel.RealSense/Sensors/CMakeLists.txt @@ -4,4 +4,5 @@ target_sources(${LRS_DOTNET_TARGET} "${CMAKE_CURRENT_LIST_DIR}/SensorList.cs" "${CMAKE_CURRENT_LIST_DIR}/SoftwareSensor.cs" "${CMAKE_CURRENT_LIST_DIR}/PoseSensor.cs" + "${CMAKE_CURRENT_LIST_DIR}/MaxUsableRangeSensor.cs" ) diff --git a/wrappers/csharp/Intel.RealSense/Sensors/MaxUsableRangeSensor.cs b/wrappers/csharp/Intel.RealSense/Sensors/MaxUsableRangeSensor.cs new file mode 100644 index 0000000000..61ac2aed76 --- /dev/null +++ b/wrappers/csharp/Intel.RealSense/Sensors/MaxUsableRangeSensor.cs @@ -0,0 +1,26 @@ +// License: Apache 2.0. See LICENSE file in root directory. +// Copyright(c) 2017 Intel Corporation. All Rights Reserved. + +namespace Intel.RealSense +{ + using System; + using System.Runtime.InteropServices; + + public class MaxUsableRangeSensor : Sensor + { + internal MaxUsableRangeSensor(IntPtr ptr) + : base(ptr) + { + } + + /// + /// Returns the maximum range of the camera given the amount of ambient light in the scene [m] + /// + /// maximum usable range + public float GetMaxUsableRange( ) + { + object error; + return NativeMethods.rs2_get_max_usable_range(Handle, out error); + } + } +} diff --git a/wrappers/csharp/Intel.RealSense/Types/Enums/Extension.cs b/wrappers/csharp/Intel.RealSense/Types/Enums/Extension.cs index c9fefa4753..6507b9f464 100644 --- a/wrappers/csharp/Intel.RealSense/Types/Enums/Extension.cs +++ b/wrappers/csharp/Intel.RealSense/Types/Enums/Extension.cs @@ -55,6 +55,7 @@ public enum Extension FisheyeSensor = 44, DepthHuffmanDecoder = 45, Serializable = 46, - FirmwareLogger = 47 - } + FirmwareLogger = 47, + MaxUsableRangeSensor = 53 + } } diff --git a/wrappers/csharp/Intel.RealSense/Types/Enums/Option.cs b/wrappers/csharp/Intel.RealSense/Types/Enums/Option.cs index 94da34eabd..6c5fc8347f 100644 --- a/wrappers/csharp/Intel.RealSense/Types/Enums/Option.cs +++ b/wrappers/csharp/Intel.RealSense/Types/Enums/Option.cs @@ -255,6 +255,9 @@ public enum Option SequenceId = 79, /// Humidity temperature [Deg Celsius] - HumidityTemperature = 80 + HumidityTemperature = 80, + + /// Turn on/off the maximum usable range who calculates the maximum range of the camera given the amount of ambient light in the scene + MaxUsableRange = 81 } } diff --git a/wrappers/matlab/option.m b/wrappers/matlab/option.m index 8027b86284..1b9c110df3 100644 --- a/wrappers/matlab/option.m +++ b/wrappers/matlab/option.m @@ -82,6 +82,7 @@ sequence_size (78) sequence_id (79) humidity_temperature (80) - count (81) + max_usable_range (81) + count (82) end end diff --git a/wrappers/nodejs/index.js b/wrappers/nodejs/index.js index 81750881d6..6e232d9511 100644 --- a/wrappers/nodejs/index.js +++ b/wrappers/nodejs/index.js @@ -4942,6 +4942,7 @@ const option = { OPTION_SEQUENCE_SIZE: RS2.RS2_OPTION_SEQUENCE_SIZE, OPTION_SEQUENCE_ID: RS2.RS2_OPTION_SEQUENCE_ID, OPTION_HUMIDITY_TEMPERATURE: RS2.RS2_OPTION_HUMIDITY_TEMPERATURE, + OPTION_MAX_USABLE_RANGE: RS2.RS2_OPTION_MAX_USABLE_RANGE, /** * Number of enumeration values. Not a valid input: intended to be used in for-loops. * @type {Integer} @@ -5094,6 +5095,8 @@ const option = { return this.option_thermal_compensation; case this.OPTION_HUMIDITY_TEMPERATURE: return this.option_humidity_temperature; + case this.OPTION_MAX_USABLE_RANGE: + return this.option_max_usable_range; default: throw new TypeError( 'option.optionToString(option) expects a valid value as the 1st argument'); diff --git a/wrappers/nodejs/src/addon.cpp b/wrappers/nodejs/src/addon.cpp index 5b0ecd9f4b..f0cbc0e665 100644 --- a/wrappers/nodejs/src/addon.cpp +++ b/wrappers/nodejs/src/addon.cpp @@ -4718,6 +4718,7 @@ void InitModule(v8::Local exports) { _FORCE_SET_ENUM(RS2_OPTION_SEQUENCE_SIZE); _FORCE_SET_ENUM(RS2_OPTION_SEQUENCE_ID); _FORCE_SET_ENUM(RS2_OPTION_HUMIDITY_TEMPERATURE); + _FORCE_SET_ENUM(RS2_OPTION_MAX_USABLE_RANGE); _FORCE_SET_ENUM(RS2_OPTION_COUNT); // rs2_camera_info diff --git a/wrappers/python/pybackend.cpp b/wrappers/python/pybackend.cpp index 856910c8a7..3394b4caa9 100644 --- a/wrappers/python/pybackend.cpp +++ b/wrappers/python/pybackend.cpp @@ -181,6 +181,7 @@ PYBIND11_MODULE(NAME, m) { .value("sequence_size", RS2_OPTION_SEQUENCE_SIZE) .value("sequence_id", RS2_OPTION_SEQUENCE_ID) .value("humidity_temperature", RS2_OPTION_HUMIDITY_TEMPERATURE) + .value("max_usable_range", RS2_OPTION_MAX_USABLE_RANGE) .value("count", RS2_OPTION_COUNT); py::enum_ power_state(m, "power_state"); diff --git a/wrappers/python/pyrs_sensor.cpp b/wrappers/python/pyrs_sensor.cpp index f57b0aab3a..bb1d254000 100644 --- a/wrappers/python/pyrs_sensor.cpp +++ b/wrappers/python/pyrs_sensor.cpp @@ -4,6 +4,7 @@ Copyright(c) 2017 Intel Corporation. All Rights Reserved. */ #include "python.hpp" #include "../include/librealsense2/hpp/rs_sensor.hpp" #include "calibrated-sensor.h" +#include "max-usable-range-sensor.h" void init_sensor(py::module &m) { /** rs_sensor.hpp **/ @@ -74,7 +75,8 @@ void init_sensor(py::module &m) { .def(BIND_DOWNCAST(sensor, fisheye_sensor)) .def(BIND_DOWNCAST(sensor, pose_sensor)) .def(BIND_DOWNCAST(sensor, calibrated_sensor)) - .def(BIND_DOWNCAST(sensor, wheel_odometer)); + .def(BIND_DOWNCAST(sensor, wheel_odometer)) + .def(BIND_DOWNCAST(sensor, max_usable_range_sensor)); // rs2::sensor_from_frame [frame.def("get_sensor", ...)? // rs2::sensor==sensor? @@ -124,7 +126,13 @@ void init_sensor(py::module &m) { &rs2::calibrated_sensor::reset_calibration, py::call_guard< py::gil_scoped_release >() ) .def( "__nonzero__", &rs2::calibrated_sensor::operator bool ); - + + py::class_ mur_sensor(m, "max_usable_range_sensor"); + mur_sensor.def(py::init(), "sensor"_a) + .def("get_max_usable_range", + &rs2::max_usable_range_sensor::get_max_usable_range, + py::call_guard< py::gil_scoped_release >()); + // rs2::depth_stereo_sensor py::class_ depth_stereo_sensor(m, "depth_stereo_sensor"); // No docstring in C++ depth_stereo_sensor.def(py::init()) diff --git a/wrappers/unrealengine4/Plugins/RealSense/Source/RealSense/Public/RealSenseTypes.h b/wrappers/unrealengine4/Plugins/RealSense/Source/RealSense/Public/RealSenseTypes.h index f28352a9fb..7f4be5552e 100755 --- a/wrappers/unrealengine4/Plugins/RealSense/Source/RealSense/Public/RealSenseTypes.h +++ b/wrappers/unrealengine4/Plugins/RealSense/Source/RealSense/Public/RealSenseTypes.h @@ -135,6 +135,7 @@ enum class ERealSenseOptionType : uint8 SEQUENCE_SIZE , /**< HDR Sequence size */ SEQUENCE_ID , /**< HDR Sequence ID - 0 is not HDR; sequence ID for HDR configuration starts from 1 */ HUMIDITY_TEMPERATURE , /**< Humidity temperature [Deg Celsius]*/ + MAX_USABLE_RANGE , /**< Turn on/off the maximum usable range who calculates the maximum range of the camera given the amount of ambient light in the scene */ }; UENUM(Blueprintable) From bd2147288cfc39227787a603ad56c4e33fc258f3 Mon Sep 17 00:00:00 2001 From: NirAz Date: Wed, 21 Oct 2020 19:26:06 +0300 Subject: [PATCH 03/14] Implement basic MUR algorythm --- src/l500/l500-depth.cpp | 113 +++++++++++++++++++++++++++++++++++++- src/l500/l500-options.cpp | 6 ++ 2 files changed, 116 insertions(+), 3 deletions(-) diff --git a/src/l500/l500-depth.cpp b/src/l500/l500-depth.cpp index 1b8e66323c..a4bf396157 100644 --- a/src/l500/l500-depth.cpp +++ b/src/l500/l500-depth.cpp @@ -356,9 +356,116 @@ namespace librealsense float l500_depth_sensor::get_max_usable_range() const { - // TODO Add real implementation - static int cnt = 0; - return cnt++ % 100; + if( ! supports_option( RS2_OPTION_MAX_USABLE_RANGE ) ) + throw librealsense::wrong_api_call_sequence_exception( "max usable range option is not supported" ); + + if( get_option( RS2_OPTION_MAX_USABLE_RANGE ).query() != 1.0f ) + throw librealsense::wrong_api_call_sequence_exception( "max usable range option is not on" ); + + if (!is_streaming()) + { + throw librealsense::wrong_api_call_sequence_exception("depth sensor is not streaming!"); + } + + // Algo parameters + auto processing_gain = 1.75f; + auto long_thermal = 74.5f; + auto short_thermal = 10.0f; // #TBD + + // inner values + auto thermal = 0.0f; + auto normalized_nest = 0.0f; + auto indoor_max_range = 9.0f; + + // FW values + // TODO - get from get_temperatures() function + auto nest = 0.0f; + auto humidity_temp = 0.0f; + + int apd = static_cast(get_option( RS2_OPTION_AVALANCHE_PHOTO_DIODE ).query()); + + auto res = _owner->_hw_monitor->send( command( ivcam2::IRB, 0x6C, 0x2, 0x1 ) ); + + if( res.size() < sizeof( uint8_t ) ) + { + throw invalid_value_exception( + to_string() << "Gain trim FW command failed: size expected: " << sizeof( uint8_t ) + << " , size received: " << res.size() ); + } + + int gtr = res[0]; + + auto m_factor = 170.0f / ( std::pow( 1.1f, apd - 9.0f ) ); + + enum class preset_type + { + SHORT, + LONG, + CUSTOM + }; + + preset_type preset = preset_type::LONG; + if( ( apd == 18 ) && ( gtr == 3 ) ) + preset = preset_type::SHORT; + else if( ( apd == 9 ) && ( gtr == 0 ) ) + preset = preset_type::LONG; + else + preset = preset_type::CUSTOM; + + if( preset == preset_type::LONG ) + { + thermal = long_thermal; + normalized_nest = nest / 16.0f; + indoor_max_range = 9.0f; + } + else if( preset == preset_type::SHORT ) + { + thermal = short_thermal; + indoor_max_range = 6.1f; + normalized_nest = ( nest - 797.0f ) / 6.275f; + } + else + { + indoor_max_range = 9.0f / std::sqrt( 170.0f / m_factor ); + if( gtr == 3 ) + { + thermal = short_thermal; + nest = ( nest - 797.0f ) / 6.275f; + } + else + { + thermal = long_thermal; + nest = nest / 16.0f; + } + } + + auto temp_range = indoor_max_range; + auto expected_max_range = 0.0f; + auto trimmed_max_range = 0.0f; + + // Setting max range based on Nest + if (nest > thermal) + { + // Analyzing reflectivity based on 85 % reflectivity data + temp_range = 31000.0f * std::pow(nest, -2.0f) * processing_gain; + } + + expected_max_range = std::min(temp_range, indoor_max_range); + + if (expected_max_range == indoor_max_range) + trimmed_max_range = indoor_max_range; + else if (expected_max_range >= indoor_max_range - 1.5f) + trimmed_max_range = indoor_max_range - 1.5f; + else if (expected_max_range >= indoor_max_range - 3.0f) + trimmed_max_range = indoor_max_range - 3.0f; + else if (expected_max_range >= indoor_max_range - 4.5f) + trimmed_max_range = indoor_max_range - 4.5f; + else if (expected_max_range >= indoor_max_range - 6.0f) + trimmed_max_range = indoor_max_range - 6.0f; + else if (expected_max_range >= indoor_max_range - 7.5f) + trimmed_max_range = indoor_max_range - 7.5f; + + return trimmed_max_range; } float l500_depth_sensor::read_baseline() const diff --git a/src/l500/l500-options.cpp b/src/l500/l500-options.cpp index d36945c2a6..04cc5e79ff 100644 --- a/src/l500/l500-options.cpp +++ b/src/l500/l500-options.cpp @@ -290,6 +290,12 @@ namespace librealsense void max_usable_range_option::set(float value) { // TODO if conditions are not meet throw exception! + //if (_fw_version < firmware_version("1.5.0.0") + // throw + // “Max Usable Range” only supports VGA resolution and Max Range preset + // If the system is configured with unsupported resolution or preset and the user attempts to enable “Max Usable Range” feature, a message should notify the user to set VGA and Max Range preset before attempting to enable “Max Usable Range” + // If “Max Usable Range” is enabled while camera is not streaming, system will automatically select VGA and Max Range preset and not allow changing those settings. + bool_option::set(value); } From 35c738fbd4c153f1f43e7e70d66a65b02e9eecfa Mon Sep 17 00:00:00 2001 From: NirAz Date: Wed, 21 Oct 2020 21:39:11 +0300 Subject: [PATCH 04/14] move algorythm to its own filw --- src/algo/CMakeLists.txt | 1 + src/algo/max-range/CMakeLists.txt | 7 ++ src/algo/max-range/max-usable-range.cpp | 81 +++++++++++++++++ src/algo/max-range/max-usable-range.h | 53 ++++++++++++ src/l500/l500-depth.cpp | 110 ++++-------------------- src/l500/l500-depth.h | 10 +++ 6 files changed, 170 insertions(+), 92 deletions(-) create mode 100644 src/algo/max-range/CMakeLists.txt create mode 100644 src/algo/max-range/max-usable-range.cpp create mode 100644 src/algo/max-range/max-usable-range.h diff --git a/src/algo/CMakeLists.txt b/src/algo/CMakeLists.txt index 6dafa38bfa..f11f65e8d2 100644 --- a/src/algo/CMakeLists.txt +++ b/src/algo/CMakeLists.txt @@ -3,3 +3,4 @@ include(${CMAKE_CURRENT_LIST_DIR}/depth-to-rgb-calibration/CMakeLists.txt) include(${CMAKE_CURRENT_LIST_DIR}/thermal-loop/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/max-range/CMakeLists.txt) diff --git a/src/algo/max-range/CMakeLists.txt b/src/algo/max-range/CMakeLists.txt new file mode 100644 index 0000000000..df13ea2417 --- /dev/null +++ b/src/algo/max-range/CMakeLists.txt @@ -0,0 +1,7 @@ +# License: Apache 2.0. See LICENSE file in root directory. +# Copyright(c) 2020 Intel Corporation. All Rights Reserved. +target_sources(${LRS_TARGET} + PRIVATE + "${CMAKE_CURRENT_LIST_DIR}/max-usable-range.h" + "${CMAKE_CURRENT_LIST_DIR}/max-usable-range.cpp" +) diff --git a/src/algo/max-range/max-usable-range.cpp b/src/algo/max-range/max-usable-range.cpp new file mode 100644 index 0000000000..ce4c8d98d6 --- /dev/null +++ b/src/algo/max-range/max-usable-range.cpp @@ -0,0 +1,81 @@ +//// License: Apache 2.0. See LICENSE file in root directory. +//// Copyright(c) 2020 Intel Corporation. All Rights Reserved. + +#include "max-usable-range.h" + + +using namespace librealsense::algo::max_range; + +float max_usable_range::get_max_range(const max_usable_range_inputs &inputs) const +{ + + auto thermal = 0.0f; + auto normalized_nest = 0.0f; + auto indoor_max_range = 9.0f; + + auto m_factor = 170.0f / (std::pow(1.1f, inputs.apd - 9.0f)); + + preset_type preset = preset_type::LONG; + + if ((inputs.apd == 18) && (inputs.gtr == 3)) + preset = preset_type::SHORT; + else if ((inputs.apd == 9) && (inputs.gtr == 0)) + preset = preset_type::LONG; + else + preset = preset_type::CUSTOM; + + if (preset == preset_type::LONG) + { + thermal = _long_thermal; + normalized_nest = inputs.nest / 16.0f; + indoor_max_range = 9.0f; + } + else if (preset == preset_type::SHORT) + { + thermal = _short_thermal; + indoor_max_range = 6.1f; + normalized_nest = (inputs.nest - 797.0f) / 6.275f; + } + else + { + indoor_max_range = 9.0f / std::sqrt(170.0f / m_factor); + if (inputs.gtr == 3) + { + thermal = thermal = _short_thermal; + normalized_nest = (inputs.nest - 797.0f) / 6.275f; + } + else + { + thermal = _long_thermal; + normalized_nest = inputs.nest / 16.0f; + } + } + + auto temp_range = indoor_max_range; + auto expected_max_range = 0.0f; + auto trimmed_max_range = 0.0f; + + // Setting max range based on Nest + if (normalized_nest > thermal) + { + // Analyzing reflectivity based on 85 % reflectivity data + temp_range = 31000.0f * std::pow(normalized_nest, -2.0f) * _processing_gain; + } + + expected_max_range = std::min(temp_range, indoor_max_range); + + if (expected_max_range == indoor_max_range) + trimmed_max_range = indoor_max_range; + else if (expected_max_range >= indoor_max_range - 1.5f) + trimmed_max_range = indoor_max_range - 1.5f; + else if (expected_max_range >= indoor_max_range - 3.0f) + trimmed_max_range = indoor_max_range - 3.0f; + else if (expected_max_range >= indoor_max_range - 4.5f) + trimmed_max_range = indoor_max_range - 4.5f; + else if (expected_max_range >= indoor_max_range - 6.0f) + trimmed_max_range = indoor_max_range - 6.0f; + else if (expected_max_range >= indoor_max_range - 7.5f) + trimmed_max_range = indoor_max_range - 7.5f; + + return trimmed_max_range; +} diff --git a/src/algo/max-range/max-usable-range.h b/src/algo/max-range/max-usable-range.h new file mode 100644 index 0000000000..f997294969 --- /dev/null +++ b/src/algo/max-range/max-usable-range.h @@ -0,0 +1,53 @@ +// License: Apache 2.0. See LICENSE file in root directory. +// Copyright(c) 2020 Intel Corporation. All Rights Reserved. + +#pragma once + +#include + + +namespace librealsense { +namespace algo { +namespace max_range { + + +struct max_usable_range_inputs +{ + float nest; + float humidity_temp; + int gtr; + int apd; + + max_usable_range_inputs() + : nest( 0.0f ) + , humidity_temp( 0.0f ) + , gtr( 0 ) + , apd( 0 ) + { + } +}; + +class max_usable_range +{ +public: + max_usable_range() = default; + float get_max_range( const max_usable_range_inputs & inputs ) const; + +private: + + // Algo parameters + const float _processing_gain = 1.75f; + const float _long_thermal = 74.5f; + const float _short_thermal = 10.0f; // TBD + + enum class preset_type + { + SHORT, + LONG, + CUSTOM + }; +}; + +} // namespace max_range +} // namespace algo +} // namespace librealsense diff --git a/src/l500/l500-depth.cpp b/src/l500/l500-depth.cpp index a4bf396157..a29dbf1718 100644 --- a/src/l500/l500-depth.cpp +++ b/src/l500/l500-depth.cpp @@ -20,6 +20,7 @@ #include "ac-trigger.h" #include "algo/depth-to-rgb-calibration/debug.h" #include "algo/depth-to-rgb-calibration/utils.h" // validate_dsm_params +#include "algo/max-range/max-usable-range.h" #define MM_TO_METER 1/1000 @@ -362,112 +363,37 @@ namespace librealsense if( get_option( RS2_OPTION_MAX_USABLE_RANGE ).query() != 1.0f ) throw librealsense::wrong_api_call_sequence_exception( "max usable range option is not on" ); - if (!is_streaming()) + if (!is_streaming()) // TODO NOT WORKING!!! { throw librealsense::wrong_api_call_sequence_exception("depth sensor is not streaming!"); } - // Algo parameters - auto processing_gain = 1.75f; - auto long_thermal = 74.5f; - auto short_thermal = 10.0f; // #TBD + algo::max_range::max_usable_range mur; + algo::max_range::max_usable_range_inputs mur_inputs; - // inner values - auto thermal = 0.0f; - auto normalized_nest = 0.0f; - auto indoor_max_range = 9.0f; - - // FW values - // TODO - get from get_temperatures() function - auto nest = 0.0f; - auto humidity_temp = 0.0f; - - int apd = static_cast(get_option( RS2_OPTION_AVALANCHE_PHOTO_DIODE ).query()); + gather_inputs_for_max_usable_range(mur_inputs); + return mur.get_max_range(mur_inputs); + } - auto res = _owner->_hw_monitor->send( command( ivcam2::IRB, 0x6C, 0x2, 0x1 ) ); + void l500_depth_sensor::gather_inputs_for_max_usable_range(algo::max_range::max_usable_range_inputs &mur_inputs) const + { + auto res = _owner->_hw_monitor->send(command(ivcam2::IRB, 0x6C, 0x2, 0x1)); - if( res.size() < sizeof( uint8_t ) ) + if (res.size() < sizeof(uint8_t)) { throw invalid_value_exception( - to_string() << "Gain trim FW command failed: size expected: " << sizeof( uint8_t ) - << " , size received: " << res.size() ); - } - - int gtr = res[0]; - - auto m_factor = 170.0f / ( std::pow( 1.1f, apd - 9.0f ) ); - - enum class preset_type - { - SHORT, - LONG, - CUSTOM - }; - - preset_type preset = preset_type::LONG; - if( ( apd == 18 ) && ( gtr == 3 ) ) - preset = preset_type::SHORT; - else if( ( apd == 9 ) && ( gtr == 0 ) ) - preset = preset_type::LONG; - else - preset = preset_type::CUSTOM; - - if( preset == preset_type::LONG ) - { - thermal = long_thermal; - normalized_nest = nest / 16.0f; - indoor_max_range = 9.0f; - } - else if( preset == preset_type::SHORT ) - { - thermal = short_thermal; - indoor_max_range = 6.1f; - normalized_nest = ( nest - 797.0f ) / 6.275f; + to_string() << "Gain trim FW command failed: size expected: " << sizeof(uint8_t) + << " , size received: " << res.size()); } - else - { - indoor_max_range = 9.0f / std::sqrt( 170.0f / m_factor ); - if( gtr == 3 ) - { - thermal = short_thermal; - nest = ( nest - 797.0f ) / 6.275f; - } - else - { - thermal = long_thermal; - nest = nest / 16.0f; - } - } - - auto temp_range = indoor_max_range; - auto expected_max_range = 0.0f; - auto trimmed_max_range = 0.0f; - // Setting max range based on Nest - if (nest > thermal) - { - // Analyzing reflectivity based on 85 % reflectivity data - temp_range = 31000.0f * std::pow(nest, -2.0f) * processing_gain; - } + mur_inputs.gtr = static_cast(res[0]); + mur_inputs.apd = static_cast(get_option(RS2_OPTION_AVALANCHE_PHOTO_DIODE).query()); + //mur_inputs->humidity_temp = ; + //mur_inputs->nest = - expected_max_range = std::min(temp_range, indoor_max_range); - - if (expected_max_range == indoor_max_range) - trimmed_max_range = indoor_max_range; - else if (expected_max_range >= indoor_max_range - 1.5f) - trimmed_max_range = indoor_max_range - 1.5f; - else if (expected_max_range >= indoor_max_range - 3.0f) - trimmed_max_range = indoor_max_range - 3.0f; - else if (expected_max_range >= indoor_max_range - 4.5f) - trimmed_max_range = indoor_max_range - 4.5f; - else if (expected_max_range >= indoor_max_range - 6.0f) - trimmed_max_range = indoor_max_range - 6.0f; - else if (expected_max_range >= indoor_max_range - 7.5f) - trimmed_max_range = indoor_max_range - 7.5f; - - return trimmed_max_range; } + float l500_depth_sensor::read_baseline() const { const int baseline_address = 0xa00e0868; diff --git a/src/l500/l500-depth.h b/src/l500/l500-depth.h index c7d0cf4bf5..508823a78d 100644 --- a/src/l500/l500-depth.h +++ b/src/l500/l500-depth.h @@ -22,6 +22,14 @@ namespace librealsense { + // forward declaration + namespace algo + { + namespace max_range + { + struct max_usable_range_inputs; + } + } // namespace algo class l500_depth : public virtual l500_device { @@ -258,6 +266,8 @@ namespace librealsense void open(const stream_profiles& requests) override; void stop() override; float get_depth_offset() const; + + void gather_inputs_for_max_usable_range(algo::max_range::max_usable_range_inputs &mur_inputs) const; private: action_delayer _action_delayer; l500_device * const _owner; From 9a8eb919ecdba24d238e59bc568306fa0bb3cd7d Mon Sep 17 00:00:00 2001 From: NirAz Date: Wed, 21 Oct 2020 22:22:30 +0300 Subject: [PATCH 05/14] connect temperatures to source --- src/algo/max-range/max-usable-range.cpp | 2 ++ src/l500/l500-depth.cpp | 13 ++++++++++--- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/src/algo/max-range/max-usable-range.cpp b/src/algo/max-range/max-usable-range.cpp index ce4c8d98d6..2feb7092ac 100644 --- a/src/algo/max-range/max-usable-range.cpp +++ b/src/algo/max-range/max-usable-range.cpp @@ -15,6 +15,8 @@ float max_usable_range::get_max_range(const max_usable_range_inputs &inputs) con auto m_factor = 170.0f / (std::pow(1.1f, inputs.apd - 9.0f)); + + // MOVE THIS CODE OUTSIDE! preset_type preset = preset_type::LONG; if ((inputs.apd == 18) && (inputs.gtr == 3)) diff --git a/src/l500/l500-depth.cpp b/src/l500/l500-depth.cpp index a29dbf1718..a601a38af7 100644 --- a/src/l500/l500-depth.cpp +++ b/src/l500/l500-depth.cpp @@ -363,15 +363,19 @@ namespace librealsense if( get_option( RS2_OPTION_MAX_USABLE_RANGE ).query() != 1.0f ) throw librealsense::wrong_api_call_sequence_exception( "max usable range option is not on" ); - if (!is_streaming()) // TODO NOT WORKING!!! + if (!is_streaming()) { throw librealsense::wrong_api_call_sequence_exception("depth sensor is not streaming!"); } + // TODO Add code that check the preset if not long throw!! + // remove GTR + APD from the inputs algo::max_range::max_usable_range mur; algo::max_range::max_usable_range_inputs mur_inputs; gather_inputs_for_max_usable_range(mur_inputs); + + return mur.get_max_range(mur_inputs); } @@ -388,8 +392,11 @@ namespace librealsense mur_inputs.gtr = static_cast(res[0]); mur_inputs.apd = static_cast(get_option(RS2_OPTION_AVALANCHE_PHOTO_DIODE).query()); - //mur_inputs->humidity_temp = ; - //mur_inputs->nest = + + auto temperatures = _owner->get_temperatures(); + + mur_inputs.humidity_temp = temperatures.HUM_temperature; + mur_inputs.nest = temperatures.nest_avg; } From b178d41bafe0b218558ec7d6ac25cfa45a1c93f1 Mon Sep 17 00:00:00 2001 From: NirAz Date: Thu, 22 Oct 2020 09:44:46 +0300 Subject: [PATCH 06/14] calculate MUR only on long preset --- src/algo/max-range/max-usable-range.cpp | 49 ++----------------------- src/algo/max-range/max-usable-range.h | 31 ++-------------- src/l500/l500-depth.cpp | 30 +++++++-------- src/l500/l500-depth.h | 12 +----- 4 files changed, 23 insertions(+), 99 deletions(-) diff --git a/src/algo/max-range/max-usable-range.cpp b/src/algo/max-range/max-usable-range.cpp index 2feb7092ac..f081916ca4 100644 --- a/src/algo/max-range/max-usable-range.cpp +++ b/src/algo/max-range/max-usable-range.cpp @@ -6,52 +6,11 @@ using namespace librealsense::algo::max_range; -float max_usable_range::get_max_range(const max_usable_range_inputs &inputs) const +float max_usable_range::get_max_range(float nest) const { - - auto thermal = 0.0f; - auto normalized_nest = 0.0f; - auto indoor_max_range = 9.0f; - - auto m_factor = 170.0f / (std::pow(1.1f, inputs.apd - 9.0f)); - - - // MOVE THIS CODE OUTSIDE! - preset_type preset = preset_type::LONG; - - if ((inputs.apd == 18) && (inputs.gtr == 3)) - preset = preset_type::SHORT; - else if ((inputs.apd == 9) && (inputs.gtr == 0)) - preset = preset_type::LONG; - else - preset = preset_type::CUSTOM; - - if (preset == preset_type::LONG) - { - thermal = _long_thermal; - normalized_nest = inputs.nest / 16.0f; - indoor_max_range = 9.0f; - } - else if (preset == preset_type::SHORT) - { - thermal = _short_thermal; - indoor_max_range = 6.1f; - normalized_nest = (inputs.nest - 797.0f) / 6.275f; - } - else - { - indoor_max_range = 9.0f / std::sqrt(170.0f / m_factor); - if (inputs.gtr == 3) - { - thermal = thermal = _short_thermal; - normalized_nest = (inputs.nest - 797.0f) / 6.275f; - } - else - { - thermal = _long_thermal; - normalized_nest = inputs.nest / 16.0f; - } - } + const float thermal = 74.5f; + const float normalized_nest = nest / 16.0f; + const float indoor_max_range = 9.0f; auto temp_range = indoor_max_range; auto expected_max_range = 0.0f; diff --git a/src/algo/max-range/max-usable-range.h b/src/algo/max-range/max-usable-range.h index f997294969..1280fa627b 100644 --- a/src/algo/max-range/max-usable-range.h +++ b/src/algo/max-range/max-usable-range.h @@ -10,42 +10,19 @@ namespace librealsense { namespace algo { namespace max_range { - -struct max_usable_range_inputs -{ - float nest; - float humidity_temp; - int gtr; - int apd; - - max_usable_range_inputs() - : nest( 0.0f ) - , humidity_temp( 0.0f ) - , gtr( 0 ) - , apd( 0 ) - { - } -}; - class max_usable_range { public: max_usable_range() = default; - float get_max_range( const max_usable_range_inputs & inputs ) const; + // Calculate the maximum usable range based on current ambient light conditions + // Input: noise estimation value + // Output: maximum usable range [m] + float get_max_range( float nest ) const; private: // Algo parameters const float _processing_gain = 1.75f; - const float _long_thermal = 74.5f; - const float _short_thermal = 10.0f; // TBD - - enum class preset_type - { - SHORT, - LONG, - CUSTOM - }; }; } // namespace max_range diff --git a/src/l500/l500-depth.cpp b/src/l500/l500-depth.cpp index a601a38af7..96150c8ed2 100644 --- a/src/l500/l500-depth.cpp +++ b/src/l500/l500-depth.cpp @@ -357,29 +357,29 @@ namespace librealsense float l500_depth_sensor::get_max_usable_range() const { - if( ! supports_option( RS2_OPTION_MAX_USABLE_RANGE ) ) + if( !supports_option( RS2_OPTION_MAX_USABLE_RANGE ) ) throw librealsense::wrong_api_call_sequence_exception( "max usable range option is not supported" ); if( get_option( RS2_OPTION_MAX_USABLE_RANGE ).query() != 1.0f ) throw librealsense::wrong_api_call_sequence_exception( "max usable range option is not on" ); - if (!is_streaming()) + if( ! is_streaming() ) { throw librealsense::wrong_api_call_sequence_exception("depth sensor is not streaming!"); } - // TODO Add code that check the preset if not long throw!! - // remove GTR + APD from the inputs - algo::max_range::max_usable_range mur; - algo::max_range::max_usable_range_inputs mur_inputs; - - gather_inputs_for_max_usable_range(mur_inputs); + if( ! is_long_preset() ) + { + throw librealsense::wrong_api_call_sequence_exception("max usable range require long range preset (MAX_RANGE / NO_AMBIENT)"); + } + algo::max_range::max_usable_range mur; + float nest = static_cast(_owner->get_temperatures().nest_avg); - return mur.get_max_range(mur_inputs); + return mur.get_max_range(nest); } - void l500_depth_sensor::gather_inputs_for_max_usable_range(algo::max_range::max_usable_range_inputs &mur_inputs) const + bool l500_depth_sensor::is_long_preset() const { auto res = _owner->_hw_monitor->send(command(ivcam2::IRB, 0x6C, 0x2, 0x1)); @@ -390,14 +390,10 @@ namespace librealsense << " , size received: " << res.size()); } - mur_inputs.gtr = static_cast(res[0]); - mur_inputs.apd = static_cast(get_option(RS2_OPTION_AVALANCHE_PHOTO_DIODE).query()); - - auto temperatures = _owner->get_temperatures(); - - mur_inputs.humidity_temp = temperatures.HUM_temperature; - mur_inputs.nest = temperatures.nest_avg; + int gtr = static_cast(res[0]); + int apd = static_cast(get_option(RS2_OPTION_AVALANCHE_PHOTO_DIODE).query()); + return ((apd == 9) && (gtr == 0)); // indicates long preset } diff --git a/src/l500/l500-depth.h b/src/l500/l500-depth.h index 508823a78d..d8b389ec5d 100644 --- a/src/l500/l500-depth.h +++ b/src/l500/l500-depth.h @@ -22,15 +22,6 @@ namespace librealsense { - // forward declaration - namespace algo - { - namespace max_range - { - struct max_usable_range_inputs; - } - } // namespace algo - class l500_depth : public virtual l500_device { public: @@ -267,8 +258,9 @@ namespace librealsense void stop() override; float get_depth_offset() const; - void gather_inputs_for_max_usable_range(algo::max_range::max_usable_range_inputs &mur_inputs) const; private: + bool is_long_preset() const; + action_delayer _action_delayer; l500_device * const _owner; float _depth_units; From 12ef405b2455978cedae869764ecf12be0152eae Mon Sep 17 00:00:00 2001 From: NirAz Date: Thu, 22 Oct 2020 11:51:26 +0300 Subject: [PATCH 07/14] add MUR to the viewer UI --- common/model-views.cpp | 37 ++++++++++++++++++++++--- src/algo/max-range/max-usable-range.cpp | 22 ++++----------- 2 files changed, 38 insertions(+), 21 deletions(-) diff --git a/common/model-views.cpp b/common/model-views.cpp index 22cacea19d..8f170aadfc 100644 --- a/common/model-views.cpp +++ b/common/model-views.cpp @@ -2883,14 +2883,32 @@ namespace rs2 ss << " 0x" << std::hex << static_cast(round(val)) << " ="; } + bool show_max_range = false; if (texture->get_last_frame().is()) { - auto meters = texture->get_last_frame().as().get_distance(x, y); + auto meters = texture->get_last_frame().as().get_distance(x, y); if (viewer.metric_system) ss << std::dec << " " << std::setprecision(3) << meters << " meters"; else ss << std::dec << " " << std::setprecision(3) << meters / FEET_TO_METER << " feet"; + + auto ds = sensor_from_frame(texture->get_last_frame())->as(); + + if (ds.supports(RS2_OPTION_MAX_USABLE_RANGE)) + { + if (ds.get_option(RS2_OPTION_MAX_USABLE_RANGE) == 1.0) + { + show_max_range = true; + auto mur_sensor = sensor_from_frame(texture->get_last_frame())->as(); + auto max_usable_range = mur_sensor.get_max_usable_range(); + + if (viewer.metric_system) + ss << std::dec << "\nMax usable range: " << std::setprecision(1) << max_usable_range << " meters"; + else + ss << std::dec << "\nMax usable range: " << std::setprecision(1) << max_usable_range / FEET_TO_METER << " feet"; + } + } } std::string msg(ss.str().c_str()); @@ -2898,14 +2916,25 @@ namespace rs2 ImGui_ScopePushFont(font); // adjust windows size to the message length - + auto new_line_start_idx = msg.find_first_of('\n'); + int footer_vertical_size = 35; auto width = float(msg.size() * 8); + + // adjust width according to the longest line + if (show_max_range) + { + footer_vertical_size = 50; + auto first_line_size = msg.find_first_of('\n') + 1; + auto second_line_size = msg.substr(new_line_start_idx).size(); + width = std::max(first_line_size, second_line_size) * 8; + } + auto align = 20; width += align - (int)width % align; - ImVec2 pos{ stream_rect.x + 5, stream_rect.y + stream_rect.h - 35 }; + ImVec2 pos{ stream_rect.x + 5, stream_rect.y + stream_rect.h - footer_vertical_size }; ImGui::GetWindowDrawList()->AddRectFilled({ pos.x, pos.y }, - { pos.x + width, pos.y + 30 }, ImColor(dark_sensor_bg)); + { pos.x + width, pos.y + footer_vertical_size - 5 }, ImColor(dark_sensor_bg)); ImGui::SetCursorScreenPos({ pos.x + 10, pos.y + 5 }); diff --git a/src/algo/max-range/max-usable-range.cpp b/src/algo/max-range/max-usable-range.cpp index f081916ca4..66426e1592 100644 --- a/src/algo/max-range/max-usable-range.cpp +++ b/src/algo/max-range/max-usable-range.cpp @@ -11,9 +11,9 @@ float max_usable_range::get_max_range(float nest) const const float thermal = 74.5f; const float normalized_nest = nest / 16.0f; const float indoor_max_range = 9.0f; + const float min_range = 3.0f; auto temp_range = indoor_max_range; - auto expected_max_range = 0.0f; auto trimmed_max_range = 0.0f; // Setting max range based on Nest @@ -23,20 +23,8 @@ float max_usable_range::get_max_range(float nest) const temp_range = 31000.0f * std::pow(normalized_nest, -2.0f) * _processing_gain; } - expected_max_range = std::min(temp_range, indoor_max_range); - - if (expected_max_range == indoor_max_range) - trimmed_max_range = indoor_max_range; - else if (expected_max_range >= indoor_max_range - 1.5f) - trimmed_max_range = indoor_max_range - 1.5f; - else if (expected_max_range >= indoor_max_range - 3.0f) - trimmed_max_range = indoor_max_range - 3.0f; - else if (expected_max_range >= indoor_max_range - 4.5f) - trimmed_max_range = indoor_max_range - 4.5f; - else if (expected_max_range >= indoor_max_range - 6.0f) - trimmed_max_range = indoor_max_range - 6.0f; - else if (expected_max_range >= indoor_max_range - 7.5f) - trimmed_max_range = indoor_max_range - 7.5f; - - return trimmed_max_range; + // expected_max_range should be in range 3-9 [m] at 1 [m] resolution (rounded) + auto expected_max_range = std::round(std::min(std::max(temp_range, min_range), indoor_max_range)); + + return expected_max_range; } From 75b97baf74ace45c5fa7d72a226cce87aba0c2d6 Mon Sep 17 00:00:00 2001 From: NirAz Date: Thu, 22 Oct 2020 12:10:04 +0300 Subject: [PATCH 08/14] remove display MUR on DQT depth image --- common/model-views.cpp | 21 ++++++++++++--------- common/viewer.h | 2 ++ tools/depth-quality/depth-quality-model.cpp | 1 + 3 files changed, 15 insertions(+), 9 deletions(-) diff --git a/common/model-views.cpp b/common/model-views.cpp index 8f170aadfc..6ed882c63f 100644 --- a/common/model-views.cpp +++ b/common/model-views.cpp @@ -2895,18 +2895,21 @@ namespace rs2 auto ds = sensor_from_frame(texture->get_last_frame())->as(); - if (ds.supports(RS2_OPTION_MAX_USABLE_RANGE)) + if (viewer.draw_max_usable_range) { - if (ds.get_option(RS2_OPTION_MAX_USABLE_RANGE) == 1.0) + if (ds.supports(RS2_OPTION_MAX_USABLE_RANGE)) { - show_max_range = true; - auto mur_sensor = sensor_from_frame(texture->get_last_frame())->as(); - auto max_usable_range = mur_sensor.get_max_usable_range(); + if (ds.get_option(RS2_OPTION_MAX_USABLE_RANGE) == 1.0) + { + show_max_range = true; + auto mur_sensor = sensor_from_frame(texture->get_last_frame())->as(); + auto max_usable_range = mur_sensor.get_max_usable_range(); - if (viewer.metric_system) - ss << std::dec << "\nMax usable range: " << std::setprecision(1) << max_usable_range << " meters"; - else - ss << std::dec << "\nMax usable range: " << std::setprecision(1) << max_usable_range / FEET_TO_METER << " feet"; + if (viewer.metric_system) + ss << std::dec << "\nMax usable range: " << std::setprecision(1) << max_usable_range << " meters"; + else + ss << std::dec << "\nMax usable range: " << std::setprecision(1) << max_usable_range / FEET_TO_METER << " feet"; + } } } } diff --git a/common/viewer.h b/common/viewer.h index 02b14ac8cb..b82acc6d85 100644 --- a/common/viewer.h +++ b/common/viewer.h @@ -188,6 +188,8 @@ namespace rs2 std::shared_ptr updates; + bool draw_max_usable_range = true; + private: void check_permissions(); diff --git a/tools/depth-quality/depth-quality-model.cpp b/tools/depth-quality/depth-quality-model.cpp index 7abc86269b..0064d9246c 100644 --- a/tools/depth-quality/depth-quality-model.cpp +++ b/tools/depth-quality/depth-quality-model.cpp @@ -786,6 +786,7 @@ namespace rs2 _viewer_model.ppf.reset(); _viewer_model.selected_depth_source_uid = -1; _viewer_model.selected_tex_source_uid = -1; + _viewer_model.draw_max_usable_range = false; } auto dev = _pipe.get_active_profile().get_device(); From 308433bddc0ba92743fc58002fed9026a74f34e7 Mon Sep 17 00:00:00 2001 From: NirAz Date: Thu, 22 Oct 2020 15:47:01 +0300 Subject: [PATCH 09/14] Add option conditions --- common/model-views.cpp | 11 ++++-- src/algo/max-range/max-usable-range.cpp | 4 +- src/l500/l500-depth.cpp | 11 ++---- src/l500/l500-depth.h | 2 +- src/l500/l500-device.cpp | 6 +-- src/l500/l500-options.cpp | 42 +++++++++++++++++---- src/l500/l500-options.h | 5 ++- tools/depth-quality/depth-quality-model.cpp | 2 +- 8 files changed, 58 insertions(+), 25 deletions(-) diff --git a/common/model-views.cpp b/common/model-views.cpp index 6ed882c63f..b542c5d361 100644 --- a/common/model-views.cpp +++ b/common/model-views.cpp @@ -527,12 +527,12 @@ namespace rs2 if (ImGui::Checkbox(label.c_str(), &bool_value)) { res = true; - value = bool_value ? 1.0f : 0.0f; try { model.add_log(to_string() << "Setting " << opt << " to " - << value << " (" << (bool_value ? "ON" : "OFF") << ")"); - endpoint->set_option(opt, value); + << (bool_value? "1.0" : "0.0") << " (" << (bool_value ? "ON" : "OFF") << ")"); + endpoint->set_option(opt, bool_value ? 1.f : 0.f); + value = endpoint->get_option(opt); *invalidate_flag = true; } catch (const error& e) @@ -6201,6 +6201,11 @@ namespace rs2 { if (serialize && opt == RS2_OPTION_VISUAL_PRESET) continue; + if (opt == RS2_OPTION_MAX_USABLE_RANGE && !viewer.draw_max_usable_range) + { + continue; + } + if (sub->draw_option(opt, dev.is() || update_read_only_options, error_message, *viewer.not_model)) { get_curr_advanced_controls = true; diff --git a/src/algo/max-range/max-usable-range.cpp b/src/algo/max-range/max-usable-range.cpp index 66426e1592..6858fa0cde 100644 --- a/src/algo/max-range/max-usable-range.cpp +++ b/src/algo/max-range/max-usable-range.cpp @@ -20,11 +20,11 @@ float max_usable_range::get_max_range(float nest) const if (normalized_nest > thermal) { // Analyzing reflectivity based on 85 % reflectivity data - temp_range = 31000.0f * std::pow(normalized_nest, -2.0f) * _processing_gain; + temp_range = 31000.0f * pow(normalized_nest, -2.0f) * _processing_gain; } // expected_max_range should be in range 3-9 [m] at 1 [m] resolution (rounded) - auto expected_max_range = std::round(std::min(std::max(temp_range, min_range), indoor_max_range)); + auto expected_max_range = round(std::min(std::max(temp_range, min_range), indoor_max_range)); return expected_max_range; } diff --git a/src/l500/l500-depth.cpp b/src/l500/l500-depth.cpp index 96150c8ed2..1976a3cbd6 100644 --- a/src/l500/l500-depth.cpp +++ b/src/l500/l500-depth.cpp @@ -368,18 +368,13 @@ namespace librealsense throw librealsense::wrong_api_call_sequence_exception("depth sensor is not streaming!"); } - if( ! is_long_preset() ) - { - throw librealsense::wrong_api_call_sequence_exception("max usable range require long range preset (MAX_RANGE / NO_AMBIENT)"); - } - algo::max_range::max_usable_range mur; float nest = static_cast(_owner->get_temperatures().nest_avg); return mur.get_max_range(nest); } - bool l500_depth_sensor::is_long_preset() const + bool l500_depth_sensor::is_max_range_preset() const { auto res = _owner->_hw_monitor->send(command(ivcam2::IRB, 0x6C, 0x2, 0x1)); @@ -392,8 +387,10 @@ namespace librealsense int gtr = static_cast(res[0]); int apd = static_cast(get_option(RS2_OPTION_AVALANCHE_PHOTO_DIODE).query()); + int laser_power = static_cast(get_option(RS2_OPTION_LASER_POWER).query()); + int max_laser_power = get_option(RS2_OPTION_LASER_POWER).get_range().max; - return ((apd == 9) && (gtr == 0)); // indicates long preset + return ((apd == 9) && (gtr == 0) && (laser_power == max_laser_power)); // indicates max_range preset } diff --git a/src/l500/l500-depth.h b/src/l500/l500-depth.h index d8b389ec5d..e9eaaff1c2 100644 --- a/src/l500/l500-depth.h +++ b/src/l500/l500-depth.h @@ -257,9 +257,9 @@ namespace librealsense void open(const stream_profiles& requests) override; void stop() override; float get_depth_offset() const; + bool is_max_range_preset() const; private: - bool is_long_preset() const; action_delayer _action_delayer; l500_device * const _owner; diff --git a/src/l500/l500-device.cpp b/src/l500/l500-device.cpp index 248036a3b3..8d183316e3 100644 --- a/src/l500/l500-device.cpp +++ b/src/l500/l500-device.cpp @@ -208,11 +208,11 @@ namespace librealsense is_zo_enabled_opt->set(false); depth_sensor.register_option(RS2_OPTION_ZERO_ORDER_ENABLED, is_zo_enabled_opt); - auto enable_max_usable_range = std::make_shared(); - depth_sensor.register_option(RS2_OPTION_MAX_USABLE_RANGE, enable_max_usable_range); - if( _fw_version >= firmware_version( "1.5.0.0" ) ) { + auto enable_max_usable_range = std::make_shared(this); + depth_sensor.register_option(RS2_OPTION_MAX_USABLE_RANGE, enable_max_usable_range); + // TODO may not need auto-cal if there's no color sensor, like on the rs500... _autocal = std::make_shared< ac_trigger >( *this, _hw_monitor ); diff --git a/src/l500/l500-options.cpp b/src/l500/l500-options.cpp index 04cc5e79ff..7f84ce0dcd 100644 --- a/src/l500/l500-options.cpp +++ b/src/l500/l500-options.cpp @@ -289,13 +289,41 @@ namespace librealsense void max_usable_range_option::set(float value) { - // TODO if conditions are not meet throw exception! - //if (_fw_version < firmware_version("1.5.0.0") - // throw - // “Max Usable Range” only supports VGA resolution and Max Range preset - // If the system is configured with unsupported resolution or preset and the user attempts to enable “Max Usable Range” feature, a message should notify the user to set VGA and Max Range preset before attempting to enable “Max Usable Range” - // If “Max Usable Range” is enabled while camera is not streaming, system will automatically select VGA and Max Range preset and not allow changing those settings. - + if (value == 1.0f) + { + auto &sensor_mode_option = _l500_depth_dev->get_depth_sensor().get_option(RS2_OPTION_SENSOR_MODE); + auto sensor_mode = sensor_mode_option.query(); + bool sensor_mode_is_vga = (sensor_mode == rs2_sensor_mode::RS2_SENSOR_MODE_VGA); + + bool visual_preset_is_max_range = _l500_depth_dev->get_depth_sensor().is_max_range_preset(); + + if (_l500_depth_dev->get_depth_sensor().is_streaming()) + { + if (!sensor_mode_is_vga || !visual_preset_is_max_range) + throw wrong_api_call_sequence_exception("Please set 'VGA' and 'Max Range' preset before enabling Max Usable Range"); + } + else + { + if (!visual_preset_is_max_range) + { + auto &visual_preset_option = _l500_depth_dev->get_depth_sensor().get_option(RS2_OPTION_VISUAL_PRESET); + visual_preset_option.set(rs2_l500_visual_preset::RS2_L500_VISUAL_PRESET_MAX_RANGE); + LOG_INFO("Visual Preset was changed to: " << visual_preset_option.get_value_description(rs2_l500_visual_preset::RS2_L500_VISUAL_PRESET_MAX_RANGE)); + } + + if (!sensor_mode_is_vga) + { + sensor_mode_option.set(rs2_sensor_mode::RS2_SENSOR_MODE_VGA); + LOG_INFO("Sensor Mode was changed to: " << sensor_mode_option.get_value_description(rs2_sensor_mode::RS2_SENSOR_MODE_VGA)); + } + } + + // TODO!! + // If “Max Usable Range” is enabled while camera is not streaming, system will automatically select VGA and Max Range preset + // and not allow changing those settings.!! + + } + bool_option::set(value); } diff --git a/src/l500/l500-options.h b/src/l500/l500-options.h index 6e3f2714b7..0204ebe3dc 100644 --- a/src/l500/l500-options.h +++ b/src/l500/l500-options.h @@ -65,11 +65,14 @@ namespace librealsense class max_usable_range_option : public bool_option { public: - max_usable_range_option() : bool_option( false ){}; + max_usable_range_option(l500_device *l500_depth_dev) : bool_option( false ), _l500_depth_dev(l500_depth_dev){}; void set(float value) override; const char * get_description() const override; + + private: + l500_device *_l500_depth_dev; }; class l500_options: public virtual l500_device diff --git a/tools/depth-quality/depth-quality-model.cpp b/tools/depth-quality/depth-quality-model.cpp index 0064d9246c..67b541f4b0 100644 --- a/tools/depth-quality/depth-quality-model.cpp +++ b/tools/depth-quality/depth-quality-model.cpp @@ -786,7 +786,6 @@ namespace rs2 _viewer_model.ppf.reset(); _viewer_model.selected_depth_source_uid = -1; _viewer_model.selected_tex_source_uid = -1; - _viewer_model.draw_max_usable_range = false; } auto dev = _pipe.get_active_profile().get_device(); @@ -799,6 +798,7 @@ namespace rs2 _depth_sensor_model->draw_streams_selector = false; _depth_sensor_model->draw_fps_selector = true; + _viewer_model.draw_max_usable_range = false; // Retrieve stereo baseline for supported devices auto baseline_mm = -1.f; From 66ad3563fc8a79341d25cec4c54f1854da600db4 Mon Sep 17 00:00:00 2001 From: NirAz Date: Sun, 25 Oct 2020 11:21:17 +0200 Subject: [PATCH 10/14] updates after review --- common/model-views.cpp | 10 +++---- include/librealsense2/h/rs_option.h | 2 +- include/librealsense2/h/rs_sensor.h | 2 +- include/librealsense2/hpp/rs_sensor.hpp | 4 +-- src/algo/CMakeLists.txt | 2 +- src/algo/max-range/max-usable-range.cpp | 30 ------------------- src/algo/max-range/max-usable-range.h | 30 ------------------- .../CMakeLists.txt | 4 +-- .../l500/max-usable-range.cpp | 28 +++++++++++++++++ .../max-usable-range/l500/max-usable-range.h | 22 ++++++++++++++ src/l500/l500-depth.cpp | 16 +++++----- src/l500/l500-depth.h | 2 +- src/l500/l500-device.cpp | 2 +- src/max-usable-range-sensor.h | 2 +- src/realsense.def | 2 +- src/rs.cpp | 4 +-- src/types.cpp | 2 +- .../intel/realsense/librealsense/Option.java | 2 +- .../csharp/Intel.RealSense/NativeMethods.cs | 2 +- .../Sensors/MaxUsableRangeSensor.cs | 2 +- .../Intel.RealSense/Types/Enums/Option.cs | 2 +- wrappers/nodejs/index.js | 6 ++-- wrappers/nodejs/src/addon.cpp | 2 +- wrappers/python/pybackend.cpp | 2 +- wrappers/python/pyrs_sensor.cpp | 4 +-- .../Source/RealSense/Public/RealSenseTypes.h | 2 +- 26 files changed, 90 insertions(+), 98 deletions(-) delete mode 100644 src/algo/max-range/max-usable-range.cpp delete mode 100644 src/algo/max-range/max-usable-range.h rename src/algo/{max-range => max-usable-range}/CMakeLists.txt (57%) create mode 100644 src/algo/max-usable-range/l500/max-usable-range.cpp create mode 100644 src/algo/max-usable-range/l500/max-usable-range.h diff --git a/common/model-views.cpp b/common/model-views.cpp index b542c5d361..92891a1577 100644 --- a/common/model-views.cpp +++ b/common/model-views.cpp @@ -2897,13 +2897,13 @@ namespace rs2 if (viewer.draw_max_usable_range) { - if (ds.supports(RS2_OPTION_MAX_USABLE_RANGE)) + if (ds.supports(RS2_OPTION_ENABLE_MAX_USABLE_RANGE)) { - if (ds.get_option(RS2_OPTION_MAX_USABLE_RANGE) == 1.0) + if (ds.get_option(RS2_OPTION_ENABLE_MAX_USABLE_RANGE) == 1.0) { show_max_range = true; - auto mur_sensor = sensor_from_frame(texture->get_last_frame())->as(); - auto max_usable_range = mur_sensor.get_max_usable_range(); + auto mur_sensor = ds.as(); + auto max_usable_range = mur_sensor.get_max_usable_depth_range(); if (viewer.metric_system) ss << std::dec << "\nMax usable range: " << std::setprecision(1) << max_usable_range << " meters"; @@ -6201,7 +6201,7 @@ namespace rs2 { if (serialize && opt == RS2_OPTION_VISUAL_PRESET) continue; - if (opt == RS2_OPTION_MAX_USABLE_RANGE && !viewer.draw_max_usable_range) + if (opt == RS2_OPTION_ENABLE_MAX_USABLE_RANGE && !viewer.draw_max_usable_range) { continue; } diff --git a/include/librealsense2/h/rs_option.h b/include/librealsense2/h/rs_option.h index 55a6d15bec..13395a1e7c 100644 --- a/include/librealsense2/h/rs_option.h +++ b/include/librealsense2/h/rs_option.h @@ -103,7 +103,7 @@ extern "C" { RS2_OPTION_SEQUENCE_SIZE, /**< HDR Sequence size */ RS2_OPTION_SEQUENCE_ID, /**< HDR Sequence ID - 0 is not HDR; sequence ID for HDR configuration starts from 1 */ RS2_OPTION_HUMIDITY_TEMPERATURE, /**< Humidity temperature [Deg Celsius]*/ - RS2_OPTION_MAX_USABLE_RANGE, /**< Turn on/off the maximum usable range who calculates the maximum range of the camera given the amount of ambient light in the scene */ + RS2_OPTION_ENABLE_MAX_USABLE_RANGE, /**< Turn on/off the maximum usable depth sensor range given the amount of ambient light in the scene */ RS2_OPTION_COUNT /**< Number of enumeration values. Not a valid input: intended to be used in for-loops. */ } rs2_option; diff --git a/include/librealsense2/h/rs_sensor.h b/include/librealsense2/h/rs_sensor.h index 06782f078c..1c76a2621e 100644 --- a/include/librealsense2/h/rs_sensor.h +++ b/include/librealsense2/h/rs_sensor.h @@ -652,7 +652,7 @@ void rs2_set_motion_device_intrinsics(const rs2_sensor* sensor, const rs2_stream * \param[out] error if non-null, receives any error that occurs during this call, otherwise, errors are ignored * \return the max usable range in meters */ -float rs2_get_max_usable_range(rs2_sensor const * sensor, rs2_error** error); +float rs2_get_max_usable_depth_range(rs2_sensor const * sensor, rs2_error** error); #ifdef __cplusplus } diff --git a/include/librealsense2/hpp/rs_sensor.hpp b/include/librealsense2/hpp/rs_sensor.hpp index 0fbf82ff0b..04f1395ae0 100644 --- a/include/librealsense2/hpp/rs_sensor.hpp +++ b/include/librealsense2/hpp/rs_sensor.hpp @@ -744,10 +744,10 @@ namespace rs2 /** Retrieves the maximum range of the camera given the amount of ambient light in the scene. * \return max usable range in meters */ - float get_max_usable_range() const + float get_max_usable_depth_range() const { rs2_error* e = nullptr; - auto res = rs2_get_max_usable_range(_sensor.get(), &e); + auto res = rs2_get_max_usable_depth_range(_sensor.get(), &e); error::handle(e); return res; } diff --git a/src/algo/CMakeLists.txt b/src/algo/CMakeLists.txt index f11f65e8d2..6f24b77739 100644 --- a/src/algo/CMakeLists.txt +++ b/src/algo/CMakeLists.txt @@ -3,4 +3,4 @@ include(${CMAKE_CURRENT_LIST_DIR}/depth-to-rgb-calibration/CMakeLists.txt) include(${CMAKE_CURRENT_LIST_DIR}/thermal-loop/CMakeLists.txt) -include(${CMAKE_CURRENT_LIST_DIR}/max-range/CMakeLists.txt) +include(${CMAKE_CURRENT_LIST_DIR}/max-usable-range/CMakeLists.txt) diff --git a/src/algo/max-range/max-usable-range.cpp b/src/algo/max-range/max-usable-range.cpp deleted file mode 100644 index 6858fa0cde..0000000000 --- a/src/algo/max-range/max-usable-range.cpp +++ /dev/null @@ -1,30 +0,0 @@ -//// License: Apache 2.0. See LICENSE file in root directory. -//// Copyright(c) 2020 Intel Corporation. All Rights Reserved. - -#include "max-usable-range.h" - - -using namespace librealsense::algo::max_range; - -float max_usable_range::get_max_range(float nest) const -{ - const float thermal = 74.5f; - const float normalized_nest = nest / 16.0f; - const float indoor_max_range = 9.0f; - const float min_range = 3.0f; - - auto temp_range = indoor_max_range; - auto trimmed_max_range = 0.0f; - - // Setting max range based on Nest - if (normalized_nest > thermal) - { - // Analyzing reflectivity based on 85 % reflectivity data - temp_range = 31000.0f * pow(normalized_nest, -2.0f) * _processing_gain; - } - - // expected_max_range should be in range 3-9 [m] at 1 [m] resolution (rounded) - auto expected_max_range = round(std::min(std::max(temp_range, min_range), indoor_max_range)); - - return expected_max_range; -} diff --git a/src/algo/max-range/max-usable-range.h b/src/algo/max-range/max-usable-range.h deleted file mode 100644 index 1280fa627b..0000000000 --- a/src/algo/max-range/max-usable-range.h +++ /dev/null @@ -1,30 +0,0 @@ -// License: Apache 2.0. See LICENSE file in root directory. -// Copyright(c) 2020 Intel Corporation. All Rights Reserved. - -#pragma once - -#include - - -namespace librealsense { -namespace algo { -namespace max_range { - -class max_usable_range -{ -public: - max_usable_range() = default; - // Calculate the maximum usable range based on current ambient light conditions - // Input: noise estimation value - // Output: maximum usable range [m] - float get_max_range( float nest ) const; - -private: - - // Algo parameters - const float _processing_gain = 1.75f; -}; - -} // namespace max_range -} // namespace algo -} // namespace librealsense diff --git a/src/algo/max-range/CMakeLists.txt b/src/algo/max-usable-range/CMakeLists.txt similarity index 57% rename from src/algo/max-range/CMakeLists.txt rename to src/algo/max-usable-range/CMakeLists.txt index df13ea2417..6045a05848 100644 --- a/src/algo/max-range/CMakeLists.txt +++ b/src/algo/max-usable-range/CMakeLists.txt @@ -2,6 +2,6 @@ # Copyright(c) 2020 Intel Corporation. All Rights Reserved. target_sources(${LRS_TARGET} PRIVATE - "${CMAKE_CURRENT_LIST_DIR}/max-usable-range.h" - "${CMAKE_CURRENT_LIST_DIR}/max-usable-range.cpp" + "${CMAKE_CURRENT_LIST_DIR}/l500/max-usable-range.h" + "${CMAKE_CURRENT_LIST_DIR}/l500/max-usable-range.cpp" ) diff --git a/src/algo/max-usable-range/l500/max-usable-range.cpp b/src/algo/max-usable-range/l500/max-usable-range.cpp new file mode 100644 index 0000000000..a276e5dcec --- /dev/null +++ b/src/algo/max-usable-range/l500/max-usable-range.cpp @@ -0,0 +1,28 @@ +//// License: Apache 2.0. See LICENSE file in root directory. +//// Copyright(c) 2020 Intel Corporation. All Rights Reserved. + +#include "max-usable-range.h" + +// Algo parameters +const float PROCESSING_GAIN = 1.75f; +const float THERMAL = 74.5f; +const float INDOOR_MAX_RANGE = 9.0f; +const float MIN_RANGE = 3.0f; + +// Based off of code in RS5-8358 +float librealsense::algo::max_usable_range::l500::max_usable_range(float nest) +{ + const float normalized_nest = nest / 16.0f; + + auto temp_range = INDOOR_MAX_RANGE; + + if (normalized_nest > THERMAL) + { + temp_range = 31000.0f * pow(normalized_nest, -2.0f) * PROCESSING_GAIN; + } + + // expected_max_range should be in range 3-9 [m] at 1 [m] resolution (rounded) + auto expected_max_range = round(std::min(std::max(temp_range, MIN_RANGE), INDOOR_MAX_RANGE)); + + return expected_max_range; +} diff --git a/src/algo/max-usable-range/l500/max-usable-range.h b/src/algo/max-usable-range/l500/max-usable-range.h new file mode 100644 index 0000000000..57f14a865e --- /dev/null +++ b/src/algo/max-usable-range/l500/max-usable-range.h @@ -0,0 +1,22 @@ +// License: Apache 2.0. See LICENSE file in root directory. +// Copyright(c) 2020 Intel Corporation. All Rights Reserved. + +#pragma once + +#include + + +namespace librealsense { +namespace algo { +namespace max_usable_range { +namespace l500 { + +// Calculate the maximum usable range based on current ambient light conditions +// Input: noise estimation value +// Output: maximum usable range [m] +float max_usable_range( float nest ); + +} // namespace l500 +} // namespace max_range +} // namespace algo +} // namespace librealsense diff --git a/src/l500/l500-depth.cpp b/src/l500/l500-depth.cpp index 1976a3cbd6..7612e4767f 100644 --- a/src/l500/l500-depth.cpp +++ b/src/l500/l500-depth.cpp @@ -20,7 +20,7 @@ #include "ac-trigger.h" #include "algo/depth-to-rgb-calibration/debug.h" #include "algo/depth-to-rgb-calibration/utils.h" // validate_dsm_params -#include "algo/max-range/max-usable-range.h" +#include "algo/max-usable-range/l500/max-usable-range.h" #define MM_TO_METER 1/1000 @@ -355,12 +355,14 @@ namespace librealsense AC_LOG( INFO, "Depth sensor calibration has been reset" ); } - float l500_depth_sensor::get_max_usable_range() const + float l500_depth_sensor::get_max_usable_depth_range() const { - if( !supports_option( RS2_OPTION_MAX_USABLE_RANGE ) ) + using namespace algo::max_usable_range; + + if( !supports_option( RS2_OPTION_ENABLE_MAX_USABLE_RANGE) ) throw librealsense::wrong_api_call_sequence_exception( "max usable range option is not supported" ); - if( get_option( RS2_OPTION_MAX_USABLE_RANGE ).query() != 1.0f ) + if( get_option( RS2_OPTION_ENABLE_MAX_USABLE_RANGE).query() != 1.0f ) throw librealsense::wrong_api_call_sequence_exception( "max usable range option is not on" ); if( ! is_streaming() ) @@ -368,12 +370,12 @@ namespace librealsense throw librealsense::wrong_api_call_sequence_exception("depth sensor is not streaming!"); } - algo::max_range::max_usable_range mur; float nest = static_cast(_owner->get_temperatures().nest_avg); - return mur.get_max_range(nest); + return l500::max_usable_range(nest); } + // We want to disable max-usable-range when not in a particular preset: bool l500_depth_sensor::is_max_range_preset() const { auto res = _owner->_hw_monitor->send(command(ivcam2::IRB, 0x6C, 0x2, 0x1)); @@ -388,7 +390,7 @@ namespace librealsense int gtr = static_cast(res[0]); int apd = static_cast(get_option(RS2_OPTION_AVALANCHE_PHOTO_DIODE).query()); int laser_power = static_cast(get_option(RS2_OPTION_LASER_POWER).query()); - int max_laser_power = get_option(RS2_OPTION_LASER_POWER).get_range().max; + int max_laser_power = static_cast(get_option(RS2_OPTION_LASER_POWER).get_range().max); return ((apd == 9) && (gtr == 0) && (laser_power == max_laser_power)); // indicates max_range preset } diff --git a/src/l500/l500-depth.h b/src/l500/l500-depth.h index e9eaaff1c2..a2a49c9079 100644 --- a/src/l500/l500-depth.h +++ b/src/l500/l500-depth.h @@ -219,7 +219,7 @@ namespace librealsense return *_owner->_calib_table; } - float get_max_usable_range() const override; + float get_max_usable_depth_range() const override; void create_snapshot(std::shared_ptr& snapshot) const override { diff --git a/src/l500/l500-device.cpp b/src/l500/l500-device.cpp index 8d183316e3..faf564df62 100644 --- a/src/l500/l500-device.cpp +++ b/src/l500/l500-device.cpp @@ -211,7 +211,7 @@ namespace librealsense if( _fw_version >= firmware_version( "1.5.0.0" ) ) { auto enable_max_usable_range = std::make_shared(this); - depth_sensor.register_option(RS2_OPTION_MAX_USABLE_RANGE, enable_max_usable_range); + depth_sensor.register_option(RS2_OPTION_ENABLE_MAX_USABLE_RANGE, enable_max_usable_range); // TODO may not need auto-cal if there's no color sensor, like on the rs500... _autocal = std::make_shared< ac_trigger >( *this, _hw_monitor ); diff --git a/src/max-usable-range-sensor.h b/src/max-usable-range-sensor.h index 99f2aabfbe..e2ae1a326b 100644 --- a/src/max-usable-range-sensor.h +++ b/src/max-usable-range-sensor.h @@ -10,7 +10,7 @@ namespace librealsense class max_usable_range_sensor { public: - virtual float get_max_usable_range( ) const = 0; + virtual float get_max_usable_depth_range( ) const = 0; }; MAP_EXTENSION(RS2_EXTENSION_MAX_USABLE_RANGE_SENSOR, max_usable_range_sensor); } diff --git a/src/realsense.def b/src/realsense.def index aed7c24c21..1dce1a8a6b 100644 --- a/src/realsense.def +++ b/src/realsense.def @@ -395,6 +395,6 @@ EXPORTS rs2_terminal_parse_command rs2_terminal_parse_response - rs2_get_max_usable_range + rs2_get_max_usable_depth_range diff --git a/src/rs.cpp b/src/rs.cpp index ab5f96b9d5..d2e5a7d15c 100644 --- a/src/rs.cpp +++ b/src/rs.cpp @@ -2292,12 +2292,12 @@ float rs2_get_depth_scale(rs2_sensor* sensor, rs2_error** error) BEGIN_API_CALL } HANDLE_EXCEPTIONS_AND_RETURN(0.f, sensor) -float rs2_get_max_usable_range(rs2_sensor const * sensor, rs2_error** error) BEGIN_API_CALL +float rs2_get_max_usable_depth_range(rs2_sensor const * sensor, rs2_error** error) BEGIN_API_CALL { VALIDATE_NOT_NULL(sensor); auto murs = VALIDATE_INTERFACE(sensor->sensor, librealsense::max_usable_range_sensor); - return murs->get_max_usable_range(); + return murs->get_max_usable_depth_range(); } HANDLE_EXCEPTIONS_AND_RETURN(0.f, sensor) diff --git a/src/types.cpp b/src/types.cpp index 08dfc52876..67fef6f792 100644 --- a/src/types.cpp +++ b/src/types.cpp @@ -446,7 +446,7 @@ namespace librealsense CASE(SEQUENCE_SIZE) CASE(SEQUENCE_ID) CASE(HUMIDITY_TEMPERATURE) - CASE(MAX_USABLE_RANGE) + CASE(ENABLE_MAX_USABLE_RANGE) default: assert(!is_valid(value)); return UNKNOWN_VALUE; } #undef CASE diff --git a/wrappers/android/librealsense/src/main/java/com/intel/realsense/librealsense/Option.java b/wrappers/android/librealsense/src/main/java/com/intel/realsense/librealsense/Option.java index 32f4858aa4..179039c970 100644 --- a/wrappers/android/librealsense/src/main/java/com/intel/realsense/librealsense/Option.java +++ b/wrappers/android/librealsense/src/main/java/com/intel/realsense/librealsense/Option.java @@ -83,7 +83,7 @@ public enum Option { SEQUENCE_SIZE(78), SEQUENCE_ID(79), HUMIDITY_TEMPERATURE(80), - MAX_USABLE_RANGE(81); + ENABLE_MAX_USABLE_RANGE(81); private final int mValue; private Option(int value) { mValue = value; } diff --git a/wrappers/csharp/Intel.RealSense/NativeMethods.cs b/wrappers/csharp/Intel.RealSense/NativeMethods.cs index 2fca6dc711..d053efbe1a 100644 --- a/wrappers/csharp/Intel.RealSense/NativeMethods.cs +++ b/wrappers/csharp/Intel.RealSense/NativeMethods.cs @@ -474,7 +474,7 @@ internal static MemCpyDelegate GetMethod() internal static extern void rs2_get_motion_intrinsics(IntPtr profile, out MotionDeviceIntrinsics intrinsics, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(ErrorMarshaler))] out object error); [DllImport(dllName, CallingConvention = CallingConvention.Cdecl)] - internal static extern float rs2_get_max_usable_range(IntPtr sensor, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(ErrorMarshaler))] out object error); + internal static extern float rs2_get_max_usable_depth_range(IntPtr sensor, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(ErrorMarshaler))] out object error); #endregion diff --git a/wrappers/csharp/Intel.RealSense/Sensors/MaxUsableRangeSensor.cs b/wrappers/csharp/Intel.RealSense/Sensors/MaxUsableRangeSensor.cs index 61ac2aed76..1c06766487 100644 --- a/wrappers/csharp/Intel.RealSense/Sensors/MaxUsableRangeSensor.cs +++ b/wrappers/csharp/Intel.RealSense/Sensors/MaxUsableRangeSensor.cs @@ -20,7 +20,7 @@ internal MaxUsableRangeSensor(IntPtr ptr) public float GetMaxUsableRange( ) { object error; - return NativeMethods.rs2_get_max_usable_range(Handle, out error); + return NativeMethods.rs2_get_max_usable_depth_range(Handle, out error); } } } diff --git a/wrappers/csharp/Intel.RealSense/Types/Enums/Option.cs b/wrappers/csharp/Intel.RealSense/Types/Enums/Option.cs index 6c5fc8347f..f2c1089372 100644 --- a/wrappers/csharp/Intel.RealSense/Types/Enums/Option.cs +++ b/wrappers/csharp/Intel.RealSense/Types/Enums/Option.cs @@ -258,6 +258,6 @@ public enum Option HumidityTemperature = 80, /// Turn on/off the maximum usable range who calculates the maximum range of the camera given the amount of ambient light in the scene - MaxUsableRange = 81 + EnableMaxUsableRange = 81 } } diff --git a/wrappers/nodejs/index.js b/wrappers/nodejs/index.js index 6e232d9511..536d242b8d 100644 --- a/wrappers/nodejs/index.js +++ b/wrappers/nodejs/index.js @@ -4942,7 +4942,7 @@ const option = { OPTION_SEQUENCE_SIZE: RS2.RS2_OPTION_SEQUENCE_SIZE, OPTION_SEQUENCE_ID: RS2.RS2_OPTION_SEQUENCE_ID, OPTION_HUMIDITY_TEMPERATURE: RS2.RS2_OPTION_HUMIDITY_TEMPERATURE, - OPTION_MAX_USABLE_RANGE: RS2.RS2_OPTION_MAX_USABLE_RANGE, + OPTION_ENABLE_MAX_USABLE_RANGE: RS2.RS2_OPTION_ENABLE_MAX_USABLE_RANGE, /** * Number of enumeration values. Not a valid input: intended to be used in for-loops. * @type {Integer} @@ -5095,8 +5095,8 @@ const option = { return this.option_thermal_compensation; case this.OPTION_HUMIDITY_TEMPERATURE: return this.option_humidity_temperature; - case this.OPTION_MAX_USABLE_RANGE: - return this.option_max_usable_range; + case this.OPTION_ENABLE_MAX_USABLE_RANGE: + return this.option_enable_max_usable_range; default: throw new TypeError( 'option.optionToString(option) expects a valid value as the 1st argument'); diff --git a/wrappers/nodejs/src/addon.cpp b/wrappers/nodejs/src/addon.cpp index f0cbc0e665..45f73b1134 100644 --- a/wrappers/nodejs/src/addon.cpp +++ b/wrappers/nodejs/src/addon.cpp @@ -4718,7 +4718,7 @@ void InitModule(v8::Local exports) { _FORCE_SET_ENUM(RS2_OPTION_SEQUENCE_SIZE); _FORCE_SET_ENUM(RS2_OPTION_SEQUENCE_ID); _FORCE_SET_ENUM(RS2_OPTION_HUMIDITY_TEMPERATURE); - _FORCE_SET_ENUM(RS2_OPTION_MAX_USABLE_RANGE); + _FORCE_SET_ENUM(RS2_OPTION_ENABLE_MAX_USABLE_RANGE); _FORCE_SET_ENUM(RS2_OPTION_COUNT); // rs2_camera_info diff --git a/wrappers/python/pybackend.cpp b/wrappers/python/pybackend.cpp index 3394b4caa9..86cde4f173 100644 --- a/wrappers/python/pybackend.cpp +++ b/wrappers/python/pybackend.cpp @@ -181,7 +181,7 @@ PYBIND11_MODULE(NAME, m) { .value("sequence_size", RS2_OPTION_SEQUENCE_SIZE) .value("sequence_id", RS2_OPTION_SEQUENCE_ID) .value("humidity_temperature", RS2_OPTION_HUMIDITY_TEMPERATURE) - .value("max_usable_range", RS2_OPTION_MAX_USABLE_RANGE) + .value("enable_max_usable_range", RS2_OPTION_ENABLE_MAX_USABLE_RANGE) .value("count", RS2_OPTION_COUNT); py::enum_ power_state(m, "power_state"); diff --git a/wrappers/python/pyrs_sensor.cpp b/wrappers/python/pyrs_sensor.cpp index bb1d254000..75409c4d58 100644 --- a/wrappers/python/pyrs_sensor.cpp +++ b/wrappers/python/pyrs_sensor.cpp @@ -129,8 +129,8 @@ void init_sensor(py::module &m) { py::class_ mur_sensor(m, "max_usable_range_sensor"); mur_sensor.def(py::init(), "sensor"_a) - .def("get_max_usable_range", - &rs2::max_usable_range_sensor::get_max_usable_range, + .def("get_max_usable_depth_range", + &rs2::max_usable_range_sensor::get_max_usable_depth_range, py::call_guard< py::gil_scoped_release >()); // rs2::depth_stereo_sensor diff --git a/wrappers/unrealengine4/Plugins/RealSense/Source/RealSense/Public/RealSenseTypes.h b/wrappers/unrealengine4/Plugins/RealSense/Source/RealSense/Public/RealSenseTypes.h index 7f4be5552e..aba48ea9f5 100755 --- a/wrappers/unrealengine4/Plugins/RealSense/Source/RealSense/Public/RealSenseTypes.h +++ b/wrappers/unrealengine4/Plugins/RealSense/Source/RealSense/Public/RealSenseTypes.h @@ -135,7 +135,7 @@ enum class ERealSenseOptionType : uint8 SEQUENCE_SIZE , /**< HDR Sequence size */ SEQUENCE_ID , /**< HDR Sequence ID - 0 is not HDR; sequence ID for HDR configuration starts from 1 */ HUMIDITY_TEMPERATURE , /**< Humidity temperature [Deg Celsius]*/ - MAX_USABLE_RANGE , /**< Turn on/off the maximum usable range who calculates the maximum range of the camera given the amount of ambient light in the scene */ + ENABLE_MAX_USABLE_RANGE , /**< Turn on/off the maximum usable range who calculates the maximum range of the camera given the amount of ambient light in the scene */ }; UENUM(Blueprintable) From 86e4c6c8d99cf61f2b11090c5a7e4a7889fffa81 Mon Sep 17 00:00:00 2001 From: NirAz Date: Sun, 25 Oct 2020 15:18:31 +0200 Subject: [PATCH 11/14] Move rounding of the output to the viewer --- common/model-views.cpp | 8 ++++++-- src/algo/max-usable-range/l500/max-usable-range.cpp | 8 ++------ 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/common/model-views.cpp b/common/model-views.cpp index 92891a1577..13f1a84dba 100644 --- a/common/model-views.cpp +++ b/common/model-views.cpp @@ -2904,11 +2904,15 @@ namespace rs2 show_max_range = true; auto mur_sensor = ds.as(); auto max_usable_range = mur_sensor.get_max_usable_depth_range(); + const float MIN_RANGE = 3.0f; + const float MAX_RANGE = 9.0f; + // display maximu, usable range in range 3-9 [m] at 1 [m] resolution (rounded) + auto max_usable_range_rounded = round(std::min(std::max(max_usable_range, MIN_RANGE), MAX_RANGE)); if (viewer.metric_system) - ss << std::dec << "\nMax usable range: " << std::setprecision(1) << max_usable_range << " meters"; + ss << std::dec << "\nMax usable range: " << std::setprecision(1) << max_usable_range_rounded << " meters"; else - ss << std::dec << "\nMax usable range: " << std::setprecision(1) << max_usable_range / FEET_TO_METER << " feet"; + ss << std::dec << "\nMax usable range: " << std::setprecision(1) << max_usable_range_rounded / FEET_TO_METER << " feet"; } } } diff --git a/src/algo/max-usable-range/l500/max-usable-range.cpp b/src/algo/max-usable-range/l500/max-usable-range.cpp index a276e5dcec..1a24fdecf9 100644 --- a/src/algo/max-usable-range/l500/max-usable-range.cpp +++ b/src/algo/max-usable-range/l500/max-usable-range.cpp @@ -7,22 +7,18 @@ const float PROCESSING_GAIN = 1.75f; const float THERMAL = 74.5f; const float INDOOR_MAX_RANGE = 9.0f; -const float MIN_RANGE = 3.0f; // Based off of code in RS5-8358 float librealsense::algo::max_usable_range::l500::max_usable_range(float nest) { const float normalized_nest = nest / 16.0f; - auto temp_range = INDOOR_MAX_RANGE; + auto expected_max_range = INDOOR_MAX_RANGE; if (normalized_nest > THERMAL) { - temp_range = 31000.0f * pow(normalized_nest, -2.0f) * PROCESSING_GAIN; + expected_max_range = 31000.0f * pow(normalized_nest, -2.0f) * PROCESSING_GAIN; } - // expected_max_range should be in range 3-9 [m] at 1 [m] resolution (rounded) - auto expected_max_range = round(std::min(std::max(temp_range, MIN_RANGE), INDOOR_MAX_RANGE)); - return expected_max_range; } From 66d5f9d992c47f16d39321c75206fc81e44fa2bc Mon Sep 17 00:00:00 2001 From: NirAz Date: Sun, 25 Oct 2020 16:13:54 +0200 Subject: [PATCH 12/14] Add nodeJs extension --- wrappers/nodejs/src/addon.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/wrappers/nodejs/src/addon.cpp b/wrappers/nodejs/src/addon.cpp index 45f73b1134..6c85eec59e 100644 --- a/wrappers/nodejs/src/addon.cpp +++ b/wrappers/nodejs/src/addon.cpp @@ -4857,6 +4857,7 @@ void InitModule(v8::Local exports) { _FORCE_SET_ENUM(RS2_EXTENSION_CALIBRATED_SENSOR); _FORCE_SET_ENUM(RS2_EXTENSION_HDR_MERGE); _FORCE_SET_ENUM(RS2_EXTENSION_SEQUENCE_ID_FILTER); + _FORCE_SET_ENUM(RS2_EXTENSION_MAX_USABLE_RANGE_SENSOR); _FORCE_SET_ENUM(RS2_EXTENSION_COUNT); From 1d7e7d5fcad03569e8908c504ba4427188d646d3 Mon Sep 17 00:00:00 2001 From: NirAz Date: Mon, 26 Oct 2020 11:50:32 +0200 Subject: [PATCH 13/14] Review fixes --- common/model-views.cpp | 2 +- src/algo/max-usable-range/l500/max-usable-range.cpp | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/common/model-views.cpp b/common/model-views.cpp index 13f1a84dba..25f9ecc178 100644 --- a/common/model-views.cpp +++ b/common/model-views.cpp @@ -532,7 +532,7 @@ namespace rs2 model.add_log(to_string() << "Setting " << opt << " to " << (bool_value? "1.0" : "0.0") << " (" << (bool_value ? "ON" : "OFF") << ")"); endpoint->set_option(opt, bool_value ? 1.f : 0.f); - value = endpoint->get_option(opt); + value = endpoint->get_option(opt); // Update value on UI from the option itself, if set_option throws the UI value will not be updated. *invalidate_flag = true; } catch (const error& e) diff --git a/src/algo/max-usable-range/l500/max-usable-range.cpp b/src/algo/max-usable-range/l500/max-usable-range.cpp index 1a24fdecf9..8707ecb556 100644 --- a/src/algo/max-usable-range/l500/max-usable-range.cpp +++ b/src/algo/max-usable-range/l500/max-usable-range.cpp @@ -4,9 +4,9 @@ #include "max-usable-range.h" // Algo parameters -const float PROCESSING_GAIN = 1.75f; -const float THERMAL = 74.5f; -const float INDOOR_MAX_RANGE = 9.0f; +static const float PROCESSING_GAIN = 1.75f; +static const float THERMAL = 74.5f; +static const float INDOOR_MAX_RANGE = 9.0f; // Based off of code in RS5-8358 float librealsense::algo::max_usable_range::l500::max_usable_range(float nest) From cd73f7629a901a2eac96ee4e078c6711b7b040d0 Mon Sep 17 00:00:00 2001 From: Eran Date: Mon, 26 Oct 2020 12:19:56 +0200 Subject: [PATCH 14/14] Move get_option outside of try/catch --- common/model-views.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/common/model-views.cpp b/common/model-views.cpp index 25f9ecc178..6f121d106f 100644 --- a/common/model-views.cpp +++ b/common/model-views.cpp @@ -527,18 +527,19 @@ namespace rs2 if (ImGui::Checkbox(label.c_str(), &bool_value)) { res = true; + model.add_log(to_string() << "Setting " << opt << " to " + << (bool_value? "1.0" : "0.0") << " (" << (bool_value ? "ON" : "OFF") << ")"); try { - model.add_log(to_string() << "Setting " << opt << " to " - << (bool_value? "1.0" : "0.0") << " (" << (bool_value ? "ON" : "OFF") << ")"); endpoint->set_option(opt, bool_value ? 1.f : 0.f); - value = endpoint->get_option(opt); // Update value on UI from the option itself, if set_option throws the UI value will not be updated. - *invalidate_flag = true; } catch (const error& e) { error_message = error_to_string(e); } + // Only update the cached value once set_option is done! That way, if it doesn't change anything... + try { value = endpoint->get_option(opt); } catch( ... ) {} + *invalidate_flag = true; } if (ImGui::IsItemHovered() && desc) {