diff --git a/common/model-views.cpp b/common/model-views.cpp index 22cacea19d..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; - value = bool_value ? 1.0f : 0.0f; + 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 " - << value << " (" << (bool_value ? "ON" : "OFF") << ")"); - endpoint->set_option(opt, value); - *invalidate_flag = true; + endpoint->set_option(opt, bool_value ? 1.f : 0.f); } 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) { @@ -2883,14 +2884,39 @@ 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 (viewer.draw_max_usable_range) + { + if (ds.supports(RS2_OPTION_ENABLE_MAX_USABLE_RANGE)) + { + if (ds.get_option(RS2_OPTION_ENABLE_MAX_USABLE_RANGE) == 1.0) + { + 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_rounded << " meters"; + else + ss << std::dec << "\nMax usable range: " << std::setprecision(1) << max_usable_range_rounded / FEET_TO_METER << " feet"; + } + } + } } std::string msg(ss.str().c_str()); @@ -2898,14 +2924,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 }); @@ -6169,6 +6206,11 @@ namespace rs2 { if (serialize && opt == RS2_OPTION_VISUAL_PRESET) continue; + if (opt == RS2_OPTION_ENABLE_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/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/include/librealsense2/h/rs_option.h b/include/librealsense2/h/rs_option.h index dee52bcee1..13395a1e7c 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_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 7dce6a1f43..1c76a2621e 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_depth_range(rs2_sensor const * 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..04f1395ae0 100644 --- a/include/librealsense2/hpp/rs_sensor.hpp +++ b/include/librealsense2/hpp/rs_sensor.hpp @@ -724,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_depth_range() const + { + rs2_error* e = nullptr; + auto res = rs2_get_max_usable_depth_range(_sensor.get(), &e); + error::handle(e); + return res; + } + }; } #endif // LIBREALSENSE_RS2_SENSOR_HPP 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/algo/CMakeLists.txt b/src/algo/CMakeLists.txt index 6dafa38bfa..6f24b77739 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-usable-range/CMakeLists.txt) diff --git a/src/algo/max-usable-range/CMakeLists.txt b/src/algo/max-usable-range/CMakeLists.txt new file mode 100644 index 0000000000..6045a05848 --- /dev/null +++ b/src/algo/max-usable-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}/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..8707ecb556 --- /dev/null +++ b/src/algo/max-usable-range/l500/max-usable-range.cpp @@ -0,0 +1,24 @@ +//// 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 +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) +{ + const float normalized_nest = nest / 16.0f; + + auto expected_max_range = INDOOR_MAX_RANGE; + + if (normalized_nest > THERMAL) + { + expected_max_range = 31000.0f * pow(normalized_nest, -2.0f) * PROCESSING_GAIN; + } + + 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 e7b8cf3c66..7612e4767f 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-usable-range/l500/max-usable-range.h" #define MM_TO_METER 1/1000 @@ -354,6 +355,46 @@ namespace librealsense AC_LOG( INFO, "Depth sensor calibration has been reset" ); } + float l500_depth_sensor::get_max_usable_depth_range() const + { + 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_ENABLE_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!"); + } + + float nest = static_cast(_owner->get_temperatures().nest_avg); + + 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)); + + 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 = 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 = 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 + } + float l500_depth_sensor::read_baseline() const { diff --git a/src/l500/l500-depth.h b/src/l500/l500-depth.h index e9d0267e5e..a2a49c9079 100644 --- a/src/l500/l500-depth.h +++ b/src/l500/l500-depth.h @@ -18,10 +18,10 @@ #include "error-handling.h" #include "l500-options.h" #include "calibrated-sensor.h" +#include "max-usable-range-sensor.h" namespace librealsense { - class l500_depth : public virtual l500_device { public: @@ -92,6 +92,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 +219,8 @@ namespace librealsense return *_owner->_calib_table; } + float get_max_usable_depth_range() const override; + void create_snapshot(std::shared_ptr& snapshot) const override { snapshot = std::make_shared(get_depth_scale()); @@ -254,7 +257,10 @@ namespace librealsense void open(const stream_profiles& requests) override; void stop() override; float get_depth_offset() const; + bool is_max_range_preset() const; + private: + action_delayer _action_delayer; l500_device * const _owner; float _depth_units; diff --git a/src/l500/l500-device.cpp b/src/l500/l500-device.cpp index 262fa62649..faf564df62 100644 --- a/src/l500/l500-device.cpp +++ b/src/l500/l500-device.cpp @@ -210,6 +210,9 @@ 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_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/l500/l500-options.cpp b/src/l500/l500-options.cpp index e786d41d19..7f84ce0dcd 100644 --- a/src/l500/l500-options.cpp +++ b/src/l500/l500-options.cpp @@ -286,4 +286,57 @@ 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) + { + 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); + } + + + + 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..0204ebe3dc 100644 --- a/src/l500/l500-options.h +++ b/src/l500/l500-options.h @@ -61,6 +61,20 @@ namespace librealsense std::string _description; }; + + class max_usable_range_option : public bool_option + { + public: + 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 { public: diff --git a/src/max-usable-range-sensor.h b/src/max-usable-range-sensor.h new file mode 100644 index 0000000000..e2ae1a326b --- /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_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 5d846aa350..1dce1a8a6b 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_depth_range diff --git a/src/rs.cpp b/src/rs.cpp index d861e06da3..d2e5a7d15c 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,6 +2292,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_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_depth_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..67fef6f792 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(ENABLE_MAX_USABLE_RANGE) default: assert(!is_valid(value)); return UNKNOWN_VALUE; } #undef CASE diff --git a/tools/depth-quality/depth-quality-model.cpp b/tools/depth-quality/depth-quality-model.cpp index 7abc86269b..67b541f4b0 100644 --- a/tools/depth-quality/depth-quality-model.cpp +++ b/tools/depth-quality/depth-quality-model.cpp @@ -798,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; 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..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 @@ -82,7 +82,8 @@ public enum Option { SEQUENCE_NAME(77), SEQUENCE_SIZE(78), SEQUENCE_ID(79), - HUMIDITY_TEMPERATURE(80); + HUMIDITY_TEMPERATURE(80), + 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 e2805a95af..d053efbe1a 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_depth_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..1c06766487 --- /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_depth_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..f2c1089372 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 + EnableMaxUsableRange = 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..536d242b8d 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_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} @@ -5094,6 +5095,8 @@ const option = { return this.option_thermal_compensation; case this.OPTION_HUMIDITY_TEMPERATURE: return this.option_humidity_temperature; + 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 5b0ecd9f4b..6c85eec59e 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_ENABLE_MAX_USABLE_RANGE); _FORCE_SET_ENUM(RS2_OPTION_COUNT); // rs2_camera_info @@ -4856,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); diff --git a/wrappers/python/pybackend.cpp b/wrappers/python/pybackend.cpp index 856910c8a7..86cde4f173 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("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 f57b0aab3a..75409c4d58 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_depth_range", + &rs2::max_usable_range_sensor::get_max_usable_depth_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..aba48ea9f5 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]*/ + 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)