You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
3142 lines
142 KiB
3142 lines
142 KiB
// License: Apache 2.0. See LICENSE file in root directory.
|
|
// Copyright(c) 2017 Intel Corporation. All Rights Reserved.
|
|
|
|
#include <glad/glad.h>
|
|
#include "on-chip-calib.h"
|
|
|
|
#include <map>
|
|
#include <vector>
|
|
#include <string>
|
|
#include <thread>
|
|
#include <condition_variable>
|
|
#include <model-views.h>
|
|
#include <viewer.h>
|
|
#include "calibration-model.h"
|
|
#include "os.h"
|
|
#include "../src/algo.h"
|
|
#include "../tools/depth-quality/depth-metrics.h"
|
|
|
|
|
|
static constexpr float off_value = 0.0f;
|
|
static constexpr float on_value = 1.0f;
|
|
|
|
namespace rs2
|
|
{
|
|
on_chip_calib_manager::on_chip_calib_manager(viewer_model& viewer, std::shared_ptr<subdevice_model> sub, device_model& model, device dev, std::shared_ptr<subdevice_model> sub_color, bool uvmapping_calib_full)
|
|
: process_manager("On-Chip Calibration"), _model(model), _dev(dev), _sub(sub), _viewer(viewer), _sub_color(sub_color), py_px_only(!uvmapping_calib_full)
|
|
{
|
|
device_name_string = "Unknown";
|
|
if (dev.supports(RS2_CAMERA_INFO_PRODUCT_ID))
|
|
{
|
|
device_name_string = _dev.get_info( RS2_CAMERA_INFO_NAME );
|
|
if( val_in_range( device_name_string, { std::string( "Intel RealSense D415" ) } ) )
|
|
speed = 4;
|
|
}
|
|
if (dev.supports(RS2_CAMERA_INFO_FIRMWARE_VERSION))
|
|
{
|
|
std::string fw_version = dev.get_info(RS2_CAMERA_INFO_FIRMWARE_VERSION);
|
|
tare_health = is_upgradeable("05.12.14.100", fw_version);
|
|
}
|
|
}
|
|
|
|
on_chip_calib_manager::~on_chip_calib_manager()
|
|
{
|
|
turn_roi_off();
|
|
}
|
|
|
|
void on_chip_calib_manager::turn_roi_on()
|
|
{
|
|
if (_sub)
|
|
{
|
|
_sub->show_algo_roi = true;
|
|
_sub->algo_roi = { librealsense::_roi_ws, librealsense::_roi_hs, librealsense::_roi_we, librealsense::_roi_he };
|
|
}
|
|
|
|
if (_sub_color)
|
|
{
|
|
_sub_color->show_algo_roi = true;
|
|
_sub_color->algo_roi = { librealsense::_roi_ws, librealsense::_roi_hs, librealsense::_roi_we, librealsense::_roi_he };
|
|
}
|
|
}
|
|
|
|
void on_chip_calib_manager::turn_roi_off()
|
|
{
|
|
if (_sub)
|
|
{
|
|
_sub->show_algo_roi = false;
|
|
_sub->algo_roi = { 0, 0, 0, 0 };
|
|
}
|
|
|
|
if (_sub_color)
|
|
{
|
|
_sub_color->show_algo_roi = false;
|
|
_sub_color->algo_roi = { 0, 0, 0, 0 };
|
|
}
|
|
}
|
|
|
|
void on_chip_calib_manager::save_options_controlled_by_calib()
|
|
{
|
|
// Calibration might fail and be restarted, save only once, or we will keep chaged options.
|
|
if( ! _options_saved )
|
|
{
|
|
save_laser_emitter_state();
|
|
save_thermal_loop_state();
|
|
_options_saved = true;
|
|
}
|
|
}
|
|
|
|
void on_chip_calib_manager::restore_options_controlled_by_calib()
|
|
{
|
|
// Restore might be called several times, restore only if options where actually saved.
|
|
if( _options_saved )
|
|
{
|
|
restore_laser_emitter_state();
|
|
restore_thermal_loop_state();
|
|
_options_saved = false;
|
|
}
|
|
}
|
|
|
|
void on_chip_calib_manager::save_laser_emitter_state()
|
|
{
|
|
auto it = _sub->options_metadata.find( RS2_OPTION_EMITTER_ENABLED );
|
|
if ( it != _sub->options_metadata.end() ) //Option supported
|
|
{
|
|
_laser_status_prev = _sub->s->get_option( RS2_OPTION_EMITTER_ENABLED );
|
|
}
|
|
}
|
|
|
|
void on_chip_calib_manager::save_thermal_loop_state()
|
|
{
|
|
auto it = _sub->options_metadata.find( RS2_OPTION_THERMAL_COMPENSATION );
|
|
if( it != _sub->options_metadata.end() ) // Option supported
|
|
{
|
|
_thermal_loop_prev = _sub->s->get_option( RS2_OPTION_THERMAL_COMPENSATION );
|
|
}
|
|
}
|
|
|
|
void on_chip_calib_manager::restore_laser_emitter_state()
|
|
{
|
|
set_laser_emitter_state( _laser_status_prev );
|
|
}
|
|
|
|
void on_chip_calib_manager::restore_thermal_loop_state()
|
|
{
|
|
set_thermal_loop_state( _thermal_loop_prev );
|
|
}
|
|
|
|
void on_chip_calib_manager::set_laser_emitter_state( float value )
|
|
{
|
|
// Use options_model::set_option to update GUI after change
|
|
std::string ignored_error_message{ "" };
|
|
auto it = _sub->options_metadata.find( RS2_OPTION_EMITTER_ENABLED );
|
|
if( it != _sub->options_metadata.end() ) // Option supported
|
|
{
|
|
it->second.set_option( RS2_OPTION_EMITTER_ENABLED, value, ignored_error_message );
|
|
}
|
|
}
|
|
|
|
void on_chip_calib_manager::set_thermal_loop_state( float value )
|
|
{
|
|
// Use options_model::set_option to update GUI after change
|
|
std::string ignored_error_message{ "" };
|
|
auto it = _sub->options_metadata.find( RS2_OPTION_THERMAL_COMPENSATION );
|
|
if( it != _sub->options_metadata.end() ) // Option supported
|
|
{
|
|
it->second.set_option( RS2_OPTION_THERMAL_COMPENSATION, value, ignored_error_message );
|
|
}
|
|
}
|
|
|
|
void on_chip_calib_manager::stop_viewer(invoker invoke)
|
|
{
|
|
try
|
|
{
|
|
auto profiles = _sub->get_selected_profiles();
|
|
|
|
invoke([&]()
|
|
{
|
|
// Stop viewer UI
|
|
_sub->stop(_viewer.not_model);
|
|
if (_sub_color.get())
|
|
_sub_color->stop(_viewer.not_model);
|
|
});
|
|
|
|
// Wait until frames from all active profiles stop arriving
|
|
bool frame_arrived = false;
|
|
while (frame_arrived && _viewer.streams.size())
|
|
{
|
|
for (auto&& stream : _viewer.streams)
|
|
{
|
|
if (std::find(profiles.begin(), profiles.end(),
|
|
stream.second.original_profile) != profiles.end())
|
|
{
|
|
auto now = std::chrono::high_resolution_clock::now();
|
|
if (now - stream.second.last_frame > std::chrono::milliseconds(200))
|
|
frame_arrived = false;
|
|
}
|
|
else frame_arrived = false;
|
|
}
|
|
std::this_thread::sleep_for(std::chrono::milliseconds(10));
|
|
}
|
|
}
|
|
catch (...) {}
|
|
}
|
|
|
|
rs2::depth_frame on_chip_calib_manager::fetch_depth_frame(invoker invoke, int timeout_ms)
|
|
{
|
|
auto profiles = _sub->get_selected_profiles();
|
|
bool frame_arrived = false;
|
|
rs2::depth_frame res = rs2::frame{};
|
|
auto start_time = std::chrono::high_resolution_clock::now();
|
|
while (!frame_arrived)
|
|
{
|
|
for (auto&& stream : _viewer.streams)
|
|
{
|
|
if (std::find(profiles.begin(), profiles.end(),
|
|
stream.second.original_profile) != profiles.end())
|
|
{
|
|
auto now = std::chrono::high_resolution_clock::now();
|
|
if (now - start_time > std::chrono::milliseconds(timeout_ms))
|
|
throw std::runtime_error( rsutils::string::from() << "Failed to fetch depth frame within " << timeout_ms << " ms");
|
|
|
|
if (now - stream.second.last_frame < std::chrono::milliseconds(100))
|
|
{
|
|
if (auto f = stream.second.texture->get_last_frame(false).as<rs2::depth_frame>())
|
|
{
|
|
frame_arrived = true;
|
|
res = f;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
std::this_thread::sleep_for(std::chrono::milliseconds(10));
|
|
}
|
|
return res;
|
|
}
|
|
|
|
void on_chip_calib_manager::stop_viewer()
|
|
{
|
|
try
|
|
{
|
|
auto profiles = _sub->get_selected_profiles();
|
|
if (_sub->streaming)
|
|
_sub->stop(_viewer.not_model);
|
|
if (_sub_color.get() && _sub_color->streaming)
|
|
_sub_color->stop(_viewer.not_model);
|
|
|
|
// Wait until frames from all active profiles stop arriving
|
|
bool frame_arrived = false;
|
|
while (frame_arrived && _viewer.streams.size())
|
|
{
|
|
for (auto&& stream : _viewer.streams)
|
|
{
|
|
if (std::find(profiles.begin(), profiles.end(),
|
|
stream.second.original_profile) != profiles.end())
|
|
{
|
|
auto now = std::chrono::high_resolution_clock::now();
|
|
if (now - stream.second.last_frame > std::chrono::milliseconds(200))
|
|
frame_arrived = false;
|
|
}
|
|
else frame_arrived = false;
|
|
}
|
|
std::this_thread::sleep_for(std::chrono::milliseconds(10));
|
|
}
|
|
}
|
|
catch (...) {}
|
|
}
|
|
|
|
void on_chip_calib_manager::start_gt_viewer()
|
|
{
|
|
try
|
|
{
|
|
stop_viewer();
|
|
_viewer.is_3d_view = false;
|
|
|
|
_uid = 1;
|
|
for (const auto& format : _sub->formats)
|
|
{
|
|
if (format.second[0] == Y8_FORMAT)
|
|
{
|
|
_uid = format.first;
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Select stream
|
|
_sub->stream_enabled.clear();
|
|
_sub->stream_enabled[_uid] = true;
|
|
|
|
_sub->ui.selected_format_id.clear();
|
|
_sub->ui.selected_format_id[_uid] = 0;
|
|
|
|
_sub->ui.selected_shared_fps_id = 0; // For Ground Truth default is the lowest common FPS for USB2/# compatibility
|
|
// Select FPS value
|
|
for (int i = 0; i < _sub->shared_fps_values.size(); i++)
|
|
{
|
|
if (_sub->shared_fps_values[i] == 0)
|
|
_sub->ui.selected_shared_fps_id = i;
|
|
}
|
|
|
|
// Select Resolution
|
|
for (int i = 0; i < _sub->res_values.size(); i++)
|
|
{
|
|
auto kvp = _sub->res_values[i];
|
|
if (kvp.first == 1280 && kvp.second == 720)
|
|
_sub->ui.selected_res_id = i;
|
|
}
|
|
|
|
auto profiles = _sub->get_selected_profiles();
|
|
|
|
if (!_model.dev_syncer)
|
|
_model.dev_syncer = _viewer.syncer->create_syncer();
|
|
|
|
_sub->play(profiles, _viewer, _model.dev_syncer);
|
|
for (auto&& profile : profiles)
|
|
_viewer.begin_stream(_sub, profile);
|
|
}
|
|
catch (...) {}
|
|
}
|
|
|
|
void on_chip_calib_manager::start_fl_viewer()
|
|
{
|
|
try
|
|
{
|
|
stop_viewer();
|
|
_viewer.is_3d_view = false;
|
|
|
|
_uid = 1;
|
|
_uid2 = 2;
|
|
bool first_done = 0;
|
|
for (const auto& format : _sub->formats)
|
|
{
|
|
if (format.second[0] == Y8_FORMAT)
|
|
{
|
|
if (!first_done)
|
|
{
|
|
_uid = format.first;
|
|
first_done = true;
|
|
}
|
|
else
|
|
{
|
|
_uid2 = format.first;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Select stream
|
|
_sub->stream_enabled.clear();
|
|
_sub->stream_enabled[_uid] = true;
|
|
_sub->stream_enabled[_uid2] = true;
|
|
|
|
_sub->ui.selected_format_id.clear();
|
|
_sub->ui.selected_format_id[_uid] = 0;
|
|
_sub->ui.selected_format_id[_uid2] = 0;
|
|
|
|
// Select FPS value
|
|
for (int i = 0; i < _sub->shared_fps_values.size(); i++)
|
|
{
|
|
if (val_in_range(_sub->shared_fps_values[i], {5,6}))
|
|
_sub->ui.selected_shared_fps_id = i;
|
|
}
|
|
|
|
// Select Resolution
|
|
for (int i = 0; i < _sub->res_values.size(); i++)
|
|
{
|
|
auto kvp = _sub->res_values[i];
|
|
if (kvp.first == 1280 && kvp.second == 720)
|
|
_sub->ui.selected_res_id = i;
|
|
}
|
|
|
|
auto profiles = _sub->get_selected_profiles();
|
|
|
|
if (!_model.dev_syncer)
|
|
_model.dev_syncer = _viewer.syncer->create_syncer();
|
|
|
|
_sub->play(profiles, _viewer, _model.dev_syncer);
|
|
for (auto&& profile : profiles)
|
|
_viewer.begin_stream(_sub, profile);
|
|
}
|
|
catch (...) {}
|
|
}
|
|
|
|
void on_chip_calib_manager::start_uvmapping_viewer(bool b3D)
|
|
{
|
|
for (int i = 0; i < 2; ++i)
|
|
{
|
|
try
|
|
{
|
|
stop_viewer();
|
|
_viewer.is_3d_view = b3D;
|
|
|
|
_uid = 1;
|
|
_uid2 = 2;
|
|
bool first_done = 0;
|
|
bool second_done = 0;
|
|
for (const auto& format : _sub->formats)
|
|
{
|
|
if (format.second[0] == Y8_FORMAT && !first_done)
|
|
{
|
|
_uid = format.first;
|
|
first_done = true;
|
|
}
|
|
|
|
if (format.second[0] == Z16_FORMAT && !second_done)
|
|
{
|
|
_uid2 = format.first;
|
|
second_done = true;
|
|
}
|
|
|
|
if (first_done && second_done)
|
|
break;
|
|
}
|
|
|
|
_sub_color->ui.selected_format_id.clear();
|
|
_sub_color->ui.selected_format_id[_uid_color] = 0;
|
|
for (const auto& format : _sub_color->formats)
|
|
{
|
|
int done = false;
|
|
for (int i = 0; i < int(format.second.size()); ++i)
|
|
{
|
|
if (format.second[i] == RGB8_FORMAT)
|
|
{
|
|
_uid_color = format.first;
|
|
_sub_color->ui.selected_format_id[_uid_color] = i;
|
|
done = true;
|
|
break;
|
|
}
|
|
}
|
|
if (done)
|
|
break;
|
|
}
|
|
|
|
// Select stream
|
|
_sub->stream_enabled.clear();
|
|
_sub->stream_enabled[_uid] = true;
|
|
_sub->stream_enabled[_uid2] = true;
|
|
|
|
_sub->ui.selected_format_id.clear();
|
|
_sub->ui.selected_format_id[_uid] = 0;
|
|
_sub->ui.selected_format_id[_uid2] = 0;
|
|
|
|
// Select FPS value
|
|
for (int i = 0; i < int(_sub->shared_fps_values.size()); i++)
|
|
{
|
|
if (_sub->shared_fps_values[i] == 30)
|
|
_sub->ui.selected_shared_fps_id = i;
|
|
}
|
|
|
|
// Select Resolution
|
|
for (int i = 0; i < _sub->res_values.size(); i++)
|
|
{
|
|
auto kvp = _sub->res_values[i];
|
|
if (kvp.first == 1280 && kvp.second == 720)
|
|
_sub->ui.selected_res_id = i;
|
|
}
|
|
|
|
auto profiles = _sub->get_selected_profiles();
|
|
|
|
std::vector<stream_profile> profiles_color;
|
|
_sub_color->stream_enabled[_uid_color] = true;
|
|
|
|
for (int i = 0; i < _sub_color->shared_fps_values.size(); i++)
|
|
{
|
|
if (_sub_color->shared_fps_values[i] == 30)
|
|
_sub_color->ui.selected_shared_fps_id = i;
|
|
}
|
|
|
|
for (int i = 0; i < _sub_color->res_values.size(); i++)
|
|
{
|
|
auto kvp = _sub_color->res_values[i];
|
|
if (kvp.first == 1280 && kvp.second == 720)
|
|
_sub_color->ui.selected_res_id = i;
|
|
}
|
|
|
|
profiles_color = _sub_color->get_selected_profiles();
|
|
|
|
if (!_model.dev_syncer)
|
|
_model.dev_syncer = _viewer.syncer->create_syncer();
|
|
|
|
_sub->play(profiles, _viewer, _model.dev_syncer);
|
|
for (auto&& profile : profiles)
|
|
_viewer.begin_stream(_sub, profile);
|
|
|
|
_sub_color->play(profiles_color, _viewer, _model.dev_syncer);
|
|
for (auto&& profile : profiles_color)
|
|
_viewer.begin_stream(_sub_color, profile);
|
|
}
|
|
catch (...) {}
|
|
}
|
|
}
|
|
|
|
bool on_chip_calib_manager::start_viewer(int w, int h, int fps, invoker invoke)
|
|
{
|
|
bool frame_arrived = false;
|
|
try
|
|
{
|
|
bool run_fl_calib = ( (action == RS2_CALIB_ACTION_FL_CALIB) && (w == 1280) && (h == 720));
|
|
if (action == RS2_CALIB_ACTION_TARE_GROUND_TRUTH)
|
|
{
|
|
_uid = 1;
|
|
for (const auto& format : _sub->formats)
|
|
{
|
|
if (format.second[0] == Y8_FORMAT)
|
|
{
|
|
_uid = format.first;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else if (action == RS2_CALIB_ACTION_UVMAPPING_CALIB)
|
|
{
|
|
_uid = 1;
|
|
_uid2 = 0;
|
|
bool first_done = false;
|
|
bool second_done = false;
|
|
for (const auto& format : _sub->formats)
|
|
{
|
|
if (format.second[0] == Y8_FORMAT && !first_done)
|
|
{
|
|
_uid = format.first;
|
|
first_done = true;
|
|
}
|
|
|
|
if (format.second[0] == Z16_FORMAT && !second_done)
|
|
{
|
|
_uid2 = format.first;
|
|
second_done = true;
|
|
}
|
|
|
|
if (first_done && second_done)
|
|
break;
|
|
}
|
|
|
|
_sub_color->ui.selected_format_id.clear();
|
|
_sub_color->ui.selected_format_id[_uid_color] = 0;
|
|
for (const auto& format : _sub_color->formats)
|
|
{
|
|
int done = false;
|
|
for (int i = 0; i < format.second.size(); ++i)
|
|
{
|
|
if (format.second[i] == RGB8_FORMAT)
|
|
{
|
|
_uid_color = format.first;
|
|
_sub_color->ui.selected_format_id[_uid_color] = i;
|
|
done = true;
|
|
break;
|
|
}
|
|
}
|
|
if (done)
|
|
break;
|
|
}
|
|
|
|
// TODO - When implementing UV mapping calibration - should remove from here and handle in process_flow()
|
|
set_laser_emitter_state( off_value );
|
|
set_thermal_loop_state( off_value );
|
|
}
|
|
else if (action == RS2_CALIB_ACTION_UVMAPPING_CALIB)
|
|
{
|
|
_uid = 1;
|
|
_uid2 = 0;
|
|
bool first_done = false;
|
|
bool second_done = false;
|
|
for (const auto& format : _sub->formats)
|
|
{
|
|
if (format.second[0] == "Y8" && !first_done)
|
|
{
|
|
_uid = format.first;
|
|
first_done = true;
|
|
}
|
|
|
|
if (format.second[0] == "Z16" && !second_done)
|
|
{
|
|
_uid2 = format.first;
|
|
second_done = true;
|
|
}
|
|
|
|
if (first_done && second_done)
|
|
break;
|
|
}
|
|
|
|
_sub_color->ui.selected_format_id.clear();
|
|
_sub_color->ui.selected_format_id[_uid_color] = 0;
|
|
for (const auto& format : _sub_color->formats)
|
|
{
|
|
int done = false;
|
|
for (int i = 0; i < format.second.size(); ++i)
|
|
{
|
|
if (format.second[i] == "RGB8")
|
|
{
|
|
_uid_color = format.first;
|
|
_sub_color->ui.selected_format_id[_uid_color] = i;
|
|
done = true;
|
|
break;
|
|
}
|
|
}
|
|
if (done)
|
|
break;
|
|
}
|
|
|
|
// TODO - When implementing UV mapping calibration - should remove from here and handle in process_flow()
|
|
set_laser_emitter_state( off_value );
|
|
}
|
|
else if (action == RS2_CALIB_ACTION_FL_PLUS_CALIB)
|
|
{
|
|
_uid = 1;
|
|
_uid2 = 0;
|
|
_uid_color = 2;
|
|
bool first_done = false;
|
|
bool second_done = false;
|
|
bool third_done = false;
|
|
for (const auto& format : _sub->formats)
|
|
{
|
|
if (format.second[0] == "Y8")
|
|
{
|
|
if (!first_done)
|
|
{
|
|
_uid = format.first;
|
|
first_done = true;
|
|
}
|
|
else
|
|
{
|
|
_uid_color = format.first;
|
|
third_done = true;
|
|
}
|
|
}
|
|
|
|
if (format.second[0] == "Z16" && !second_done)
|
|
{
|
|
_uid2 = format.first;
|
|
second_done = true;
|
|
}
|
|
|
|
if (first_done && second_done && third_done)
|
|
break;
|
|
}
|
|
|
|
// TODO - When implementing FL plus calibration - should remove from here and handle in process_flow()
|
|
set_laser_emitter_state( off_value );
|
|
}
|
|
else if (run_fl_calib)
|
|
{
|
|
_uid = 1;
|
|
_uid2 = 2;
|
|
bool first_done = false;
|
|
for (const auto& format : _sub->formats)
|
|
{
|
|
if (format.second[0] == Y8_FORMAT)
|
|
{
|
|
if (!first_done)
|
|
{
|
|
_uid = format.first;
|
|
first_done = true;
|
|
}
|
|
else
|
|
{
|
|
_uid2 = format.first;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
_uid = 0;
|
|
for (const auto& format : _sub->formats)
|
|
{
|
|
if (format.second[0] == Z16_FORMAT)
|
|
{
|
|
_uid = format.first;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Select stream
|
|
_sub->stream_enabled.clear();
|
|
_sub->stream_enabled[_uid] = true;
|
|
if (run_fl_calib || action == RS2_CALIB_ACTION_UVMAPPING_CALIB)
|
|
_sub->stream_enabled[_uid2] = true;
|
|
|
|
_sub->ui.selected_format_id.clear();
|
|
_sub->ui.selected_format_id[_uid] = 0;
|
|
if (run_fl_calib || action == RS2_CALIB_ACTION_UVMAPPING_CALIB)
|
|
_sub->ui.selected_format_id[_uid2] = 0;
|
|
|
|
// Select FPS value
|
|
for (int i = 0; i < _sub->shared_fps_values.size(); i++)
|
|
{
|
|
if (_sub->shared_fps_values[i] == fps)
|
|
_sub->ui.selected_shared_fps_id = i;
|
|
}
|
|
|
|
// Select Resolution
|
|
for (int i = 0; i < _sub->res_values.size(); i++)
|
|
{
|
|
auto kvp = _sub->res_values[i];
|
|
if (kvp.first == w && kvp.second == h)
|
|
_sub->ui.selected_res_id = i;
|
|
}
|
|
|
|
// If not supported, try WxHx30
|
|
if (!_sub->is_selected_combination_supported())
|
|
{
|
|
for (int i = 0; i < _sub->shared_fps_values.size(); i++)
|
|
{
|
|
//if (_sub->shared_fps_values[i] == 30)
|
|
_sub->ui.selected_shared_fps_id = i;
|
|
if (_sub->is_selected_combination_supported()) break;
|
|
}
|
|
|
|
// If still not supported, try VGA30
|
|
if (!_sub->is_selected_combination_supported())
|
|
{
|
|
for (int i = 0; i < _sub->res_values.size(); i++)
|
|
{
|
|
auto kvp = _sub->res_values[i];
|
|
if (kvp.first == 640 && kvp.second == 480)
|
|
_sub->ui.selected_res_id = i;
|
|
}
|
|
}
|
|
}
|
|
|
|
auto profiles = _sub->get_selected_profiles();
|
|
|
|
std::vector<stream_profile> profiles_color;
|
|
if (action == RS2_CALIB_ACTION_UVMAPPING_CALIB)
|
|
{
|
|
_sub_color->stream_enabled[_uid_color] = true;
|
|
|
|
for (int i = 0; i < _sub_color->shared_fps_values.size(); i++)
|
|
{
|
|
if (_sub_color->shared_fps_values[i] == fps)
|
|
_sub_color->ui.selected_shared_fps_id = i;
|
|
}
|
|
|
|
for (int i = 0; i < _sub_color->res_values.size(); i++)
|
|
{
|
|
auto kvp = _sub_color->res_values[i];
|
|
if (kvp.first == w && kvp.second == h)
|
|
_sub_color->ui.selected_res_id = i;
|
|
}
|
|
|
|
profiles_color = _sub_color->get_selected_profiles();
|
|
}
|
|
|
|
invoke([&]()
|
|
{
|
|
if (!_model.dev_syncer)
|
|
_model.dev_syncer = _viewer.syncer->create_syncer();
|
|
|
|
// Start streaming
|
|
_sub->play(profiles, _viewer, _model.dev_syncer);
|
|
for (auto&& profile : profiles)
|
|
_viewer.begin_stream(_sub, profile);
|
|
|
|
if (action == RS2_CALIB_ACTION_UVMAPPING_CALIB)
|
|
{
|
|
_sub_color->play(profiles_color, _viewer, _model.dev_syncer);
|
|
for (auto&& profile : profiles_color)
|
|
_viewer.begin_stream(_sub_color, profile);
|
|
}
|
|
});
|
|
|
|
// Wait for frames to arrive
|
|
int count = 0;
|
|
while (!frame_arrived && count++ < 200)
|
|
{
|
|
for (auto&& stream : _viewer.streams)
|
|
{
|
|
if (std::find(profiles.begin(), profiles.end(),
|
|
stream.second.original_profile) != profiles.end())
|
|
{
|
|
auto now = std::chrono::high_resolution_clock::now();
|
|
if (now - stream.second.last_frame < std::chrono::milliseconds(100))
|
|
frame_arrived = true;
|
|
}
|
|
}
|
|
std::this_thread::sleep_for(std::chrono::milliseconds(10));
|
|
}
|
|
}
|
|
catch (...) {}
|
|
|
|
return frame_arrived;
|
|
}
|
|
|
|
std::pair<float, float> on_chip_calib_manager::get_metric(bool use_new)
|
|
{
|
|
return _metrics[use_new ? 1 : 0];
|
|
}
|
|
|
|
void on_chip_calib_manager::try_start_viewer(int w, int h, int fps, invoker invoke)
|
|
{
|
|
bool started = start_viewer(w, h, fps, invoke);
|
|
if (!started)
|
|
{
|
|
std::this_thread::sleep_for(std::chrono::milliseconds(600));
|
|
started = start_viewer(w, h, fps, invoke);
|
|
}
|
|
|
|
if (!started)
|
|
{
|
|
stop_viewer(invoke);
|
|
log( "Failed to start streaming" );
|
|
throw std::runtime_error( rsutils::string::from() << "Failed to start streaming (" << w << ", " << h << ", " << fps << ")!");
|
|
}
|
|
}
|
|
|
|
std::pair<float, float> on_chip_calib_manager::get_depth_metrics(invoker invoke)
|
|
{
|
|
using namespace depth_quality;
|
|
|
|
auto f = fetch_depth_frame(invoke);
|
|
auto sensor = _sub->s->as<rs2::depth_stereo_sensor>();
|
|
auto intr = f.get_profile().as<rs2::video_stream_profile>().get_intrinsics();
|
|
rs2::region_of_interest roi { (int)(f.get_width() * 0.45f), (int)(f.get_height() * 0.45f),
|
|
(int)(f.get_width() * 0.55f), (int)(f.get_height() * 0.55f) };
|
|
std::vector<single_metric_data> v;
|
|
|
|
std::vector<float> fill_rates;
|
|
std::vector<float> rmses;
|
|
|
|
auto show_plane = _viewer.draw_plane;
|
|
|
|
auto on_frame = [sensor, &fill_rates, &rmses, this](
|
|
const std::vector<rs2::float3>& points,
|
|
const plane p,
|
|
const rs2::region_of_interest roi,
|
|
const float baseline_mm,
|
|
const float focal_length_pixels,
|
|
const int ground_thruth_mm,
|
|
const bool plane_fit,
|
|
const float plane_fit_to_ground_truth_mm,
|
|
const float distance_mm,
|
|
bool record,
|
|
std::vector<single_metric_data>& samples)
|
|
{
|
|
static const float TO_MM = 1000.f;
|
|
static const float TO_PERCENT = 100.f;
|
|
|
|
// Calculate fill rate relative to the ROI
|
|
auto fill_rate = points.size() / float((roi.max_x - roi.min_x)*(roi.max_y - roi.min_y)) * TO_PERCENT;
|
|
fill_rates.push_back(fill_rate);
|
|
|
|
if (!plane_fit) return;
|
|
|
|
std::vector<rs2::float3> points_set = points;
|
|
std::vector<float> distances;
|
|
|
|
// Reserve memory for the data
|
|
distances.reserve(points.size());
|
|
|
|
// Convert Z values into Depth values by aligning the Fitted plane with the Ground Truth (GT) plane
|
|
// Calculate distance and disparity of Z values to the fitted plane.
|
|
// Use the rotated plane fit to calculate GT errors
|
|
for (auto & point : points_set)
|
|
{
|
|
// Find distance from point to the reconstructed plane
|
|
auto dist2plane = p.a*point.x + p.b*point.y + p.c*point.z + p.d;
|
|
|
|
// Store distance, disparity and gt- error
|
|
distances.push_back(dist2plane * TO_MM);
|
|
}
|
|
|
|
// Remove outliers [below 1% and above 99%)
|
|
std::sort(points_set.begin(), points_set.end(), [](const rs2::float3& a, const rs2::float3& b) { return a.z < b.z; });
|
|
size_t outliers = points_set.size() / 50;
|
|
points_set.erase(points_set.begin(), points_set.begin() + outliers); // crop min 0.5% of the dataset
|
|
points_set.resize(points_set.size() - outliers); // crop max 0.5% of the dataset
|
|
|
|
// Calculate Plane Fit RMS (Spatial Noise) mm
|
|
double plane_fit_err_sqr_sum = std::inner_product(distances.begin(), distances.end(), distances.begin(), 0.);
|
|
auto rms_error_val = static_cast<float>(std::sqrt(plane_fit_err_sqr_sum / distances.size()));
|
|
auto rms_error_val_per = TO_PERCENT * (rms_error_val / distance_mm);
|
|
rmses.push_back(rms_error_val_per);
|
|
};
|
|
|
|
auto rms_std = 1000.f;
|
|
auto new_rms_std = rms_std;
|
|
auto count = 0;
|
|
|
|
// Capture metrics on bundles of 31 frame
|
|
// Repeat until get "decent" bundle or reach 10 sec
|
|
do
|
|
{
|
|
rms_std = new_rms_std;
|
|
|
|
rmses.clear();
|
|
|
|
for (int i = 0; i < 31; i++)
|
|
{
|
|
f = fetch_depth_frame(invoke);
|
|
auto res = depth_quality::analyze_depth_image(f, sensor.get_depth_scale(), sensor.get_stereo_baseline(),
|
|
&intr, roi, 0, true, v, false, on_frame);
|
|
|
|
_viewer.draw_plane = true;
|
|
_viewer.roi_rect = res.plane_corners;
|
|
}
|
|
|
|
auto rmses_sum_sqr = std::inner_product(rmses.begin(), rmses.end(), rmses.begin(), 0.);
|
|
new_rms_std = static_cast<float>(std::sqrt(rmses_sum_sqr / rmses.size()));
|
|
} while ((new_rms_std < rms_std * 0.8f && new_rms_std > 10.f) && count++ < 10);
|
|
|
|
std::sort(fill_rates.begin(), fill_rates.end());
|
|
std::sort(rmses.begin(), rmses.end());
|
|
|
|
float median_fill_rate, median_rms;
|
|
if (fill_rates.empty())
|
|
median_fill_rate = 0;
|
|
else
|
|
median_fill_rate = fill_rates[fill_rates.size() / 2];
|
|
if (rmses.empty())
|
|
median_rms = 0;
|
|
else
|
|
median_rms = rmses[rmses.size() / 2];
|
|
|
|
_viewer.draw_plane = show_plane;
|
|
|
|
return { median_fill_rate, median_rms };
|
|
}
|
|
|
|
std::vector<uint8_t> on_chip_calib_manager::safe_send_command(const std::vector<uint8_t>& cmd, const std::string& name)
|
|
{
|
|
auto dp = _dev.as<debug_protocol>();
|
|
if (!dp) throw std::runtime_error("Device does not support debug protocol!");
|
|
|
|
auto res = dp.send_and_receive_raw_data(cmd);
|
|
|
|
if( res.size() < sizeof( int32_t ) )
|
|
throw std::runtime_error( rsutils::string::from() << "Not enough data from " << name << "!" );
|
|
auto return_code = *((int32_t*)res.data());
|
|
if( return_code < 0 )
|
|
throw std::runtime_error( rsutils::string::from()
|
|
<< "Firmware error (" << return_code << ") from " << name << "!" );
|
|
|
|
return res;
|
|
}
|
|
|
|
void on_chip_calib_manager::update_last_used()
|
|
{
|
|
time_t rawtime;
|
|
time(&rawtime);
|
|
std::string id = rsutils::string::from() << configurations::viewer::last_calib_notice << "."
|
|
<< _sub->s->get_info( RS2_CAMERA_INFO_SERIAL_NUMBER );
|
|
config_file::instance().set(id.c_str(), (long long)rawtime);
|
|
}
|
|
|
|
void on_chip_calib_manager::calibrate()
|
|
{
|
|
int occ_timeout_ms = 9000;
|
|
if (action == RS2_CALIB_ACTION_ON_CHIP_OB_CALIB || action == RS2_CALIB_ACTION_ON_CHIP_FL_CALIB)
|
|
{
|
|
if (toggle)
|
|
{
|
|
occ_timeout_ms = 12000;
|
|
if (speed_fl == 0)
|
|
speed_fl = 1;
|
|
else if (speed_fl == 1)
|
|
speed_fl = 0;
|
|
toggle = false;
|
|
std::this_thread::sleep_for(std::chrono::milliseconds(3000));
|
|
}
|
|
|
|
if (speed_fl == 0)
|
|
{
|
|
speed = 1;
|
|
fl_step_count = 41;
|
|
fy_scan_range = 30;
|
|
white_wall_mode = 0;
|
|
}
|
|
else if (speed_fl == 1)
|
|
{
|
|
speed = 3;
|
|
fl_step_count = 51;
|
|
fy_scan_range = 40;
|
|
white_wall_mode = 0;
|
|
}
|
|
else if (speed_fl == 2)
|
|
{
|
|
speed = 4;
|
|
fl_step_count = 41;
|
|
fy_scan_range = 30;
|
|
white_wall_mode = 1;
|
|
}
|
|
}
|
|
|
|
std::stringstream ss;
|
|
if (action == RS2_CALIB_ACTION_ON_CHIP_CALIB)
|
|
{
|
|
ss << "{\n \"calib type\":" << 0 <<
|
|
",\n \"host assistance\":" << host_assistance <<
|
|
",\n \"speed\":" << speed <<
|
|
",\n \"average step count\":" << average_step_count <<
|
|
",\n \"scan parameter\":" << (intrinsic_scan ? 0 : 1) <<
|
|
",\n \"step count\":" << step_count <<
|
|
",\n \"apply preset\":" << (apply_preset ? 1 : 0) <<
|
|
",\n \"accuracy\":" << accuracy <<
|
|
",\n \"scan only\":" << (host_assistance ? 1 : 0) <<
|
|
",\n \"interactive scan\":" << 0 << "}";
|
|
}
|
|
else if (action == RS2_CALIB_ACTION_ON_CHIP_FL_CALIB)
|
|
{
|
|
ss << "{\n \"calib type\":" << 1 <<
|
|
",\n \"host assistance\":" << host_assistance <<
|
|
",\n \"fl step count\":" << fl_step_count <<
|
|
",\n \"fy scan range\":" << fy_scan_range <<
|
|
",\n \"keep new value after sucessful scan\":" << keep_new_value_after_sucessful_scan <<
|
|
",\n \"fl data sampling\":" << fl_data_sampling <<
|
|
",\n \"adjust both sides\":" << adjust_both_sides <<
|
|
",\n \"fl scan location\":" << fl_scan_location <<
|
|
",\n \"fy scan direction\":" << fy_scan_direction <<
|
|
",\n \"white wall mode\":" << white_wall_mode <<
|
|
",\n \"scan only\":" << (host_assistance ? 1 : 0) <<
|
|
",\n \"interactive scan\":" << 0 << "}";
|
|
}
|
|
else
|
|
{
|
|
ss << "{\n \"calib type\":" << 2 <<
|
|
",\n \"host assistance\":" << host_assistance <<
|
|
",\n \"fl step count\":" << fl_step_count <<
|
|
",\n \"fy scan range\":" << fy_scan_range <<
|
|
",\n \"keep new value after sucessful scan\":" << keep_new_value_after_sucessful_scan <<
|
|
",\n \"fl data sampling\":" << fl_data_sampling <<
|
|
",\n \"adjust both sides\":" << adjust_both_sides <<
|
|
",\n \"fl scan location\":" << fl_scan_location <<
|
|
",\n \"fy scan direction\":" << fy_scan_direction <<
|
|
",\n \"white wall mode\":" << white_wall_mode <<
|
|
",\n \"speed\":" << speed <<
|
|
",\n \"average step count\":" << average_step_count <<
|
|
",\n \"scan parameter\":" << (intrinsic_scan ? 0 : 1) <<
|
|
",\n \"step count\":" << step_count <<
|
|
",\n \"apply preset\":" << (apply_preset ? 1 : 0) <<
|
|
",\n \"accuracy\":" << accuracy <<
|
|
",\n \"scan only\":" << (host_assistance ? 1 : 0) <<
|
|
",\n \"interactive scan\":" << 0 <<
|
|
",\n \"depth\":" << 0 << "}";
|
|
}
|
|
std::string json = ss.str();
|
|
|
|
float health[2] = { -1.0f, -1.0f };
|
|
auto calib_dev = _dev.as<auto_calibrated_device>();
|
|
if (action == RS2_CALIB_ACTION_TARE_CALIB)
|
|
_new_calib = calib_dev.run_tare_calibration(ground_truth, json, health, [&](const float progress) {_progress = progress; }, 5000);
|
|
else if (action == RS2_CALIB_ACTION_ON_CHIP_CALIB || action == RS2_CALIB_ACTION_ON_CHIP_FL_CALIB || action == RS2_CALIB_ACTION_ON_CHIP_OB_CALIB)
|
|
_new_calib = calib_dev.run_on_chip_calibration(json, health, [&](const float progress) {_progress = progress; }, occ_timeout_ms);
|
|
|
|
auto invoke = [](std::function<void()>) {};
|
|
int frame_fetch_timeout_ms = 3000;
|
|
|
|
bool calib_done(!_new_calib.empty());
|
|
|
|
int timeout_sec(10);
|
|
timeout_sec *= (1 + static_cast<int>(action == RS2_CALIB_ACTION_ON_CHIP_CALIB)); // when RS2_CALIB_ACTION_ON_CHIP_CALIB is in interactive-mode the process takes longer.
|
|
auto start = std::chrono::high_resolution_clock::now();
|
|
bool is_timed_out(std::chrono::high_resolution_clock::now() - start > std::chrono::seconds(timeout_sec));
|
|
|
|
while (!(calib_done || is_timed_out))
|
|
{
|
|
rs2::depth_frame f = fetch_depth_frame(invoke, frame_fetch_timeout_ms);
|
|
_new_calib = calib_dev.process_calibration_frame(f, health, [&](const float progress) {_progress = progress; }, 5000);
|
|
calib_done = !_new_calib.empty();
|
|
is_timed_out = std::chrono::high_resolution_clock::now() - start > std::chrono::seconds(timeout_sec);
|
|
}
|
|
if (is_timed_out)
|
|
{
|
|
throw std::runtime_error("Operation timed-out!\n"
|
|
"Calibration process did not converge on time");
|
|
}
|
|
|
|
// finalize results:
|
|
if (action == RS2_CALIB_ACTION_ON_CHIP_OB_CALIB)
|
|
{
|
|
int h_both = static_cast<int>(_health);
|
|
int h_1 = (h_both & 0x00000FFF);
|
|
int h_2 = (h_both & 0x00FFF000) >> 12;
|
|
int sign = (h_both & 0x0F000000) >> 24;
|
|
|
|
_health_1 = h_1 / 1000.0f;
|
|
if (sign & 1)
|
|
_health_1 = -_health_1;
|
|
|
|
_health_2 = h_2 / 1000.0f;
|
|
if (sign & 2)
|
|
_health_2 = -_health_2;
|
|
}
|
|
else if (action == RS2_CALIB_ACTION_ON_CHIP_CALIB)
|
|
{
|
|
_health = health[0];
|
|
}
|
|
else if (action == RS2_CALIB_ACTION_TARE_CALIB)
|
|
{
|
|
_health_1 = health[0] * 100;
|
|
_health_2 = health[1] * 100;
|
|
}
|
|
}
|
|
|
|
void on_chip_calib_manager::calibrate_fl()
|
|
{
|
|
try
|
|
{
|
|
std::this_thread::sleep_for(std::chrono::milliseconds(1000)); // W/A that allows for USB2 exposure to settle
|
|
constexpr int frames_required = 25;
|
|
|
|
rs2::frame_queue left(frames_required,true);
|
|
rs2::frame_queue right(frames_required, true);
|
|
|
|
int counter = 0;
|
|
|
|
float step = 50.f / frames_required; // The first stage represents 50% of the calibration process
|
|
|
|
// Stage 1 : Gather frames from Left/Right IR sensors
|
|
while (counter < frames_required) // TODO timeout
|
|
{
|
|
auto fl = _viewer.ppf.frames_queue[_uid].wait_for_frame(); // left intensity
|
|
auto fr = _viewer.ppf.frames_queue[_uid2].wait_for_frame(); // right intensity
|
|
if (fl && fr)
|
|
{
|
|
left.enqueue(fl);
|
|
right.enqueue(fr);
|
|
_progress += step;
|
|
counter++;
|
|
}
|
|
}
|
|
|
|
if (counter >= frames_required)
|
|
{
|
|
// Stage 2 : Perform focal length calibration correction routine
|
|
auto calib_dev = _dev.as<auto_calibrated_device>();
|
|
_new_calib = calib_dev.run_focal_length_calibration(left, right,
|
|
config_file::instance().get_or_default(configurations::viewer::target_width_r, 175.0f),
|
|
config_file::instance().get_or_default(configurations::viewer::target_height_r, 100.0f),
|
|
adjust_both_sides,
|
|
&corrected_ratio,
|
|
&tilt_angle,
|
|
[&](const float progress) {_progress = progress; });
|
|
}
|
|
else
|
|
fail("Failed to capture enough frames!");
|
|
}
|
|
catch (const std::runtime_error& error)
|
|
{
|
|
fail(error.what());
|
|
}
|
|
catch (...)
|
|
{
|
|
fail("Focal length calibration failed!\nPlease adjust the camera position \nand make sure the specific target is \nin the middle of the camera image");
|
|
}
|
|
}
|
|
|
|
void on_chip_calib_manager::calibrate_uv_mapping()
|
|
{
|
|
try
|
|
{
|
|
constexpr int frames_required = 25;
|
|
|
|
rs2::frame_queue left(frames_required, true);
|
|
rs2::frame_queue color(frames_required, true);
|
|
rs2::frame_queue depth(frames_required, true);
|
|
|
|
int counter = 0;
|
|
float step = 50.f / frames_required; // The first stage represents 50% of the calibration process
|
|
|
|
// Stage 1 : Gather frames from Depth/Left IR and RGB streams
|
|
while (counter < frames_required)
|
|
{
|
|
auto fl = _viewer.ppf.frames_queue[_uid].wait_for_frame(); // left
|
|
auto fd = _viewer.ppf.frames_queue[_uid2].wait_for_frame(); // depth
|
|
auto fc = _viewer.ppf.frames_queue[_uid_color].wait_for_frame(); // rgb
|
|
|
|
if (fl && fd && fc)
|
|
{
|
|
left.enqueue(fl);
|
|
depth.enqueue(fd);
|
|
color.enqueue(fc);
|
|
counter++;
|
|
}
|
|
_progress += step;
|
|
}
|
|
|
|
if (counter >= frames_required)
|
|
{
|
|
auto calib_dev = _dev.as<auto_calibrated_device>();
|
|
_new_calib = calib_dev.run_uv_map_calibration(left, color, depth, py_px_only, _health_nums, 4,
|
|
[&](const float progress) {_progress = progress; });
|
|
if (!_new_calib.size())
|
|
fail("UV-Mapping calibration failed!\nPlease adjust the camera position\nand make sure the specific target is\ninside the ROI of the camera images!");
|
|
else
|
|
log( "UV-Mapping recalibration - a new work point is generated" );
|
|
}
|
|
else
|
|
fail("Failed to capture sufficient amount of frames to run UV-Map calibration!");
|
|
}
|
|
catch (const std::runtime_error& error)
|
|
{
|
|
fail(error.what());
|
|
}
|
|
catch (...)
|
|
{
|
|
fail("UV-Mapping calibration failed!\nPlease adjust the camera position\nand make sure the specific target is\ninside the ROI of the camera images!");
|
|
}
|
|
}
|
|
|
|
void on_chip_calib_manager::get_ground_truth()
|
|
{
|
|
try
|
|
{
|
|
int counter = 0;
|
|
int frm_idx = 0;
|
|
int limit = 50; // input frames required to calculate the target
|
|
float step = 50.f / limit; // frames gathering is 50% of the process, the rest is the internal data extraction and algo processing
|
|
|
|
rs2::frame_queue queue(limit*2,true);
|
|
rs2::frame_queue queue2(limit * 2, true);
|
|
rs2::frame_queue queue3(limit * 2, true);
|
|
rs2::frame f;
|
|
|
|
// Collect sufficient amount of frames (up to 50) to extract target pattern and calculate distance to it
|
|
while ((counter < limit) && (++frm_idx < limit*2))
|
|
{
|
|
f = _viewer.ppf.frames_queue[_uid].wait_for_frame();
|
|
if (f)
|
|
{
|
|
queue.enqueue(f);
|
|
++counter;
|
|
_progress += step;
|
|
}
|
|
}
|
|
|
|
// Having sufficient number of frames allows to run the algorithm for target distance estimation
|
|
if (counter >= limit)
|
|
{
|
|
auto calib_dev = _dev.as<auto_calibrated_device>();
|
|
float target_z_mm = calib_dev.calculate_target_z(queue, queue2, queue3,
|
|
config_file::instance().get_or_default(configurations::viewer::target_width_r, 175.0f),
|
|
config_file::instance().get_or_default(configurations::viewer::target_height_r, 100.0f),
|
|
[&](const float progress) { _progress = std::min(100.f, _progress+step); });
|
|
|
|
// Update the stored value with algo-calculated
|
|
if (target_z_mm > 0.f)
|
|
{
|
|
log( rsutils::string::from() << "Target Z distance calculated - " << target_z_mm << " mm");
|
|
config_file::instance().set(configurations::viewer::ground_truth_r, target_z_mm);
|
|
}
|
|
else
|
|
fail("Failed to calculate target ground truth");
|
|
}
|
|
else
|
|
fail("Failed to capture enough frames to calculate target'z Z distance !");
|
|
}
|
|
catch (const std::runtime_error& error)
|
|
{
|
|
fail(error.what());
|
|
}
|
|
catch (...)
|
|
{
|
|
fail("Calculating target's Z distance failed");
|
|
}
|
|
}
|
|
|
|
//void on_chip_calib_manager::calibrate_fl_plus()
|
|
//{
|
|
// try
|
|
// {
|
|
// std::shared_ptr<dots_calculator> gt_calculator[2];
|
|
// bool created[3] = { false, false, false };
|
|
|
|
// int counter = 0;
|
|
// int limit = dots_calculator::_frame_num << 1;
|
|
// int step = 50 / dots_calculator::_frame_num;
|
|
|
|
// int ret = { 0 };
|
|
// int id[3] = { _uid, _uid_color, _uid2 }; // 0 for left, 1 for right, and 2 for depth
|
|
// rs2_intrinsics intrin[2];
|
|
// stream_profile profile[2];
|
|
// float dots_x[2][4] = { 0 };
|
|
// float dots_y[2][4] = { 0 };
|
|
|
|
// int idx = 0;
|
|
// int depth_frame_size = 0;
|
|
// std::vector<std::vector<uint16_t>> depth(dots_calculator::_frame_num);
|
|
|
|
// rs2::frame f;
|
|
// int width = 0;
|
|
// int height = 0;
|
|
// bool done[3] = { false, false, false };
|
|
// while (counter < limit)
|
|
// {
|
|
// if (!done[0])
|
|
// {
|
|
// f = _viewer.ppf.frames_queue[id[0]].wait_for_frame();
|
|
|
|
// if (!created[0])
|
|
// {
|
|
// profile[0] = f.get_profile();
|
|
// auto vsp = profile[0].as<video_stream_profile>();
|
|
|
|
// gt_calculator[0] = std::make_shared<dots_calculator>();
|
|
// intrin[0] = vsp.get_intrinsics();
|
|
// created[0] = true;
|
|
// }
|
|
|
|
// ret = gt_calculator[0]->calculate(f.get(), dots_x[0], dots_y[0]);
|
|
// if (ret == 0)
|
|
// ++counter;
|
|
// else if (ret == 1)
|
|
// _progress += step;
|
|
// else if (ret == 2)
|
|
// {
|
|
// _progress += step;
|
|
// done[0] = true;
|
|
// }
|
|
// }
|
|
|
|
// if (!done[1])
|
|
// {
|
|
// f = _viewer.ppf.frames_queue[id[1]].wait_for_frame();
|
|
|
|
// if (!created[1])
|
|
// {
|
|
// profile[1] = f.get_profile();
|
|
// auto vsp = profile[1].as<video_stream_profile>();
|
|
// width = vsp.width();
|
|
// height = vsp.height();
|
|
|
|
// gt_calculator[1] = std::make_shared<dots_calculator>();
|
|
// intrin[1] = vsp.get_intrinsics();
|
|
// created[1] = true;
|
|
// }
|
|
|
|
// ret = gt_calculator[1]->calculate(f.get(), dots_x[1], dots_y[1]);
|
|
// if (ret == 0)
|
|
// ++counter;
|
|
// else if (ret == 1)
|
|
// _progress += step;
|
|
// else if (ret == 2)
|
|
// {
|
|
// _progress += step;
|
|
// done[1] = true;
|
|
// }
|
|
// }
|
|
|
|
// if (!done[2])
|
|
// {
|
|
// f = _viewer.ppf.frames_queue[id[2]].wait_for_frame();
|
|
|
|
// if (!created[2])
|
|
// {
|
|
// auto p = f.get_profile();
|
|
// auto vsp = p.as<video_stream_profile>();
|
|
// width = vsp.width();
|
|
// depth_frame_size = vsp.width() * vsp.height() * sizeof(uint16_t);
|
|
// created[2] = true;
|
|
// }
|
|
|
|
// depth[idx].resize(depth_frame_size);
|
|
// memmove(depth[idx++].data(), f.get_data(), depth_frame_size);
|
|
|
|
// if (idx == dots_calculator::_frame_num)
|
|
// done[2] = true;
|
|
// }
|
|
|
|
// if (done[0] && done[1] && done[2])
|
|
// break;
|
|
// }
|
|
|
|
// if (done[0] && done[1] && done[2])
|
|
// {
|
|
// rs2_extrinsics extrin = profile[0].get_extrinsics_to(profile[1]);
|
|
|
|
// float z[4] = { 0 };
|
|
// find_z_at_corners(dots_x[0], dots_y[0], width, dots_calculator::_frame_num, depth, z);
|
|
|
|
// uvmapping_calib calib(4, dots_x[0], dots_y[0], z, dots_x[1], dots_y[1], intrin[0], intrin[1], extrin);
|
|
|
|
// bool ret = calib.calibrate(_health_1, _health_2, _ppx, _ppy, _fx, _fy, py_px_only);
|
|
// if (!ret)
|
|
// fail("Please adjust the camera position\nand make sure the specific target is\ninsid the ROI of the camera images!");
|
|
|
|
// _viewer.not_model->add_log(to_string() << "PX: " << intrin[1].ppx << " ---> " << _ppx);
|
|
// _viewer.not_model->add_log(to_string() << "PY: " << intrin[1].ppy << " ---> " << _ppy);
|
|
// _viewer.not_model->add_log(to_string() << "FX: " << intrin[1].fx << " ---> " << _fx);
|
|
// _viewer.not_model->add_log(to_string() << "FY: " << intrin[1].fy << " ---> " << _fy);
|
|
|
|
// _new_calib = _old_calib;
|
|
// auto table = (librealsense::ds::coefficients_table*)_new_calib.data();
|
|
|
|
// _health_nums[0] = _ppx / intrin[1].ppx;
|
|
// _health_nums[1] = _ppy / intrin[1].ppy;
|
|
// _health_nums[2] = _fx / intrin[1].fx;
|
|
// _health_nums[3] = _fy / intrin[1].fy;
|
|
|
|
// table->intrinsic_right.x.z *= _health_nums[0];
|
|
// table->intrinsic_right.y.x *= _health_nums[1];
|
|
// table->intrinsic_right.x.x *= _health_nums[2];
|
|
// table->intrinsic_right.x.y *= _health_nums[3];
|
|
|
|
// _health_nums[0] -= 1.0f;
|
|
// _health_nums[1] -= 1.0f;
|
|
// _health_nums[2] -= 1.0f;
|
|
// _health_nums[3] -= 1.0f;
|
|
|
|
// _health_nums[0] *= 100.0f;
|
|
// _health_nums[1] *= 100.0f;
|
|
// _health_nums[2] *= 100.0f;
|
|
// _health_nums[3] *= 100.0f;
|
|
|
|
// auto actual_data = _new_calib.data() + sizeof(librealsense::ds::table_header);
|
|
// auto actual_data_size = _new_calib.size() - sizeof(librealsense::ds::table_header);
|
|
// auto crc = helpers::calc_crc32(actual_data, actual_data_size);
|
|
// table->header.crc32 = crc;
|
|
// }
|
|
// else
|
|
// fail("Please adjust the camera position\nand make sure the specific target is\ninsid the ROI of the camera images!");
|
|
// }
|
|
// catch (const std::runtime_error& error)
|
|
// {
|
|
// fail(error.what());
|
|
// }
|
|
// catch (...)
|
|
// {
|
|
// fail("UVMapping calibration failed!");
|
|
// }
|
|
//}
|
|
|
|
void on_chip_calib_manager::process_flow(std::function<void()> cleanup, invoker invoke)
|
|
{
|
|
if (action == RS2_CALIB_ACTION_FL_CALIB || action == RS2_CALIB_ACTION_UVMAPPING_CALIB || action == RS2_CALIB_ACTION_FL_PLUS_CALIB)
|
|
stop_viewer(invoke);
|
|
|
|
update_last_used();
|
|
|
|
if (action == RS2_CALIB_ACTION_ON_CHIP_FL_CALIB || action == RS2_CALIB_ACTION_FL_CALIB)
|
|
log( rsutils::string::from() << "Starting focal length calibration");
|
|
else if (action == RS2_CALIB_ACTION_ON_CHIP_OB_CALIB)
|
|
log( rsutils::string::from() << "Starting OCC Extended");
|
|
else if (action == RS2_CALIB_ACTION_UVMAPPING_CALIB)
|
|
log( rsutils::string::from() << "Starting UV-Mapping calibration");
|
|
else
|
|
log( rsutils::string::from() << "Starting OCC calibration at speed " << speed);
|
|
|
|
_in_3d_view = _viewer.is_3d_view;
|
|
_viewer.is_3d_view = (action == RS2_CALIB_ACTION_TARE_GROUND_TRUTH ? false : true);
|
|
|
|
auto calib_dev = _dev.as<auto_calibrated_device>();
|
|
_old_calib = calib_dev.get_calibration_table();
|
|
|
|
_was_streaming = _sub->streaming;
|
|
_synchronized = _viewer.synchronization_enable.load();
|
|
_post_processing = _sub->post_processing_enabled;
|
|
_sub->post_processing_enabled = false;
|
|
_viewer.synchronization_enable = false;
|
|
|
|
_restored = false;
|
|
|
|
save_options_controlled_by_calib(); // Restored by GUI thread on dismiss or apply.
|
|
|
|
// Emitter on by default, off for GT/FL calib and for D415 model
|
|
float emitter_value = on_value;
|
|
if( action == RS2_CALIB_ACTION_FL_CALIB ||
|
|
action == RS2_CALIB_ACTION_TARE_GROUND_TRUTH ||
|
|
device_name_string == std::string( "Intel RealSense D415" ) )
|
|
emitter_value = off_value;
|
|
set_laser_emitter_state( emitter_value );
|
|
|
|
// Thermal loop should be off during calibration as to not change calibration tables during calibration
|
|
set_thermal_loop_state( off_value );
|
|
|
|
auto fps = 30;
|
|
if (_sub->dev.supports(RS2_CAMERA_INFO_USB_TYPE_DESCRIPTOR))
|
|
{
|
|
std::string desc = _sub->dev.get_info(RS2_CAMERA_INFO_USB_TYPE_DESCRIPTOR);
|
|
if (!starts_with(desc, "3."))
|
|
fps = 6; //USB2 bandwidth limitation for 720P RGB/DI
|
|
}
|
|
|
|
if (action != RS2_CALIB_ACTION_TARE_GROUND_TRUTH && action != RS2_CALIB_ACTION_UVMAPPING_CALIB)
|
|
{
|
|
if (!_was_streaming)
|
|
{
|
|
if (action == RS2_CALIB_ACTION_FL_CALIB)
|
|
try_start_viewer(848, 480, fps, invoke);
|
|
else
|
|
try_start_viewer(0, 0, 0, invoke);
|
|
}
|
|
|
|
// Capture metrics before
|
|
auto metrics_before = get_depth_metrics(invoke);
|
|
_metrics.push_back(metrics_before);
|
|
}
|
|
|
|
stop_viewer(invoke);
|
|
|
|
_ui = std::make_shared<subdevice_ui_selection>(_sub->ui);
|
|
if (action == RS2_CALIB_ACTION_UVMAPPING_CALIB && _sub_color.get())
|
|
_ui_color = std::make_shared<subdevice_ui_selection>(_sub_color->ui);
|
|
|
|
std::this_thread::sleep_for(std::chrono::milliseconds(600));
|
|
|
|
// Switch into special Auto-Calibration mode
|
|
if (action == RS2_CALIB_ACTION_FL_CALIB || action == RS2_CALIB_ACTION_UVMAPPING_CALIB)
|
|
_viewer.is_3d_view = false;
|
|
|
|
|
|
if (action == RS2_CALIB_ACTION_FL_CALIB || action == RS2_CALIB_ACTION_TARE_GROUND_TRUTH || action == RS2_CALIB_ACTION_UVMAPPING_CALIB)
|
|
try_start_viewer(1280, 720, fps, invoke);
|
|
else
|
|
{
|
|
if (host_assistance && action != RS2_CALIB_ACTION_TARE_GROUND_TRUTH)
|
|
try_start_viewer(0, 0, 0, invoke);
|
|
else
|
|
try_start_viewer(256, 144, 90, invoke);
|
|
}
|
|
|
|
if ( action == RS2_CALIB_ACTION_TARE_GROUND_TRUTH )
|
|
{
|
|
get_ground_truth();
|
|
}
|
|
else
|
|
{
|
|
try
|
|
{
|
|
if (action == RS2_CALIB_ACTION_FL_CALIB)
|
|
calibrate_fl();
|
|
else if (action == RS2_CALIB_ACTION_UVMAPPING_CALIB)
|
|
calibrate_uv_mapping();
|
|
else
|
|
calibrate();
|
|
}
|
|
catch (...)
|
|
{
|
|
log( "Calibration failed with exception" );
|
|
stop_viewer(invoke);
|
|
if (_ui.get())
|
|
{
|
|
_sub->ui = *_ui;
|
|
_ui.reset();
|
|
}
|
|
if (action == RS2_CALIB_ACTION_UVMAPPING_CALIB && _sub_color.get() && _ui_color.get())
|
|
{
|
|
_sub_color->ui = *_ui_color;
|
|
_ui_color.reset();
|
|
}
|
|
|
|
if (_was_streaming)
|
|
start_viewer(0, 0, 0, invoke);
|
|
|
|
throw;
|
|
}
|
|
}
|
|
|
|
if (action == RS2_CALIB_ACTION_TARE_GROUND_TRUTH)
|
|
log( rsutils::string::from() << "Tare ground truth is got: " << ground_truth);
|
|
else if (action == RS2_CALIB_ACTION_FL_CALIB)
|
|
log( rsutils::string::from() << "Focal length ratio is got: " << corrected_ratio);
|
|
else if (action == RS2_CALIB_ACTION_UVMAPPING_CALIB)
|
|
log( "UV-Mapping calibration completed." );
|
|
else
|
|
log( rsutils::string::from() << "Calibration completed, health factor = " << _health);
|
|
|
|
if (action != RS2_CALIB_ACTION_UVMAPPING_CALIB)
|
|
{
|
|
stop_viewer(invoke);
|
|
if (_sub.get() && _ui.get())
|
|
{
|
|
_sub->ui = *_ui;
|
|
_ui.reset();
|
|
}
|
|
if (_sub_color.get() && _ui_color.get())
|
|
{
|
|
_sub_color->ui = *_ui_color;
|
|
_ui_color.reset();
|
|
}
|
|
}
|
|
|
|
if (action != RS2_CALIB_ACTION_TARE_GROUND_TRUTH && action != RS2_CALIB_ACTION_UVMAPPING_CALIB)
|
|
{
|
|
if (action == RS2_CALIB_ACTION_FL_CALIB)
|
|
_viewer.is_3d_view = true;
|
|
|
|
try_start_viewer(0, 0, 0, invoke); // Start with default settings
|
|
|
|
// Make new calibration active
|
|
apply_calib(true);
|
|
|
|
// Capture metrics after
|
|
auto metrics_after = get_depth_metrics(invoke);
|
|
_metrics.push_back(metrics_after);
|
|
}
|
|
|
|
_progress = 100;
|
|
_done = true;
|
|
}
|
|
|
|
void on_chip_calib_manager::restore_workspace(invoker invoke)
|
|
{
|
|
try
|
|
{
|
|
if (_restored) return;
|
|
|
|
_viewer.is_3d_view = _in_3d_view;
|
|
_viewer.synchronization_enable = _synchronized;
|
|
|
|
stop_viewer(invoke);
|
|
|
|
if (_sub.get() && _ui.get())
|
|
{
|
|
_sub->ui = *_ui;
|
|
_ui.reset();
|
|
}
|
|
if (action == RS2_CALIB_ACTION_UVMAPPING_CALIB && _sub_color.get() && _ui_color.get())
|
|
{
|
|
_sub_color->ui = *_ui_color;
|
|
_ui_color.reset();
|
|
}
|
|
|
|
_sub->post_processing_enabled = _post_processing;
|
|
|
|
std::this_thread::sleep_for(std::chrono::milliseconds(200));
|
|
|
|
if (_was_streaming) start_viewer(0, 0, 0, invoke);
|
|
|
|
_restored = true;
|
|
}
|
|
catch (...) {}
|
|
}
|
|
|
|
void on_chip_calib_manager::keep()
|
|
{
|
|
// Write new calibration using SETINITCAL/SETINITCALNEW command
|
|
auto calib_dev = _dev.as<auto_calibrated_device>();
|
|
calib_dev.write_calibration();
|
|
}
|
|
|
|
void on_chip_calib_manager::apply_calib(bool use_new)
|
|
{
|
|
auto calib_dev = _dev.as<auto_calibrated_device>();
|
|
auto calib_table = use_new ? _new_calib : _old_calib;
|
|
if (calib_table.size())
|
|
calib_dev.set_calibration_table(calib_table);
|
|
}
|
|
|
|
void autocalib_notification_model::draw_dismiss(ux_window& win, int x, int y)
|
|
{
|
|
using namespace std;
|
|
using namespace chrono;
|
|
|
|
auto recommend_keep = false;
|
|
if (get_manager().action == on_chip_calib_manager::RS2_CALIB_ACTION_ON_CHIP_OB_CALIB)
|
|
{
|
|
float health_1 = get_manager().get_health_1();
|
|
float health_2 = get_manager().get_health_2();
|
|
bool recommend_keep_1 = fabs(health_1) < 0.25f;
|
|
bool recommend_keep_2 = fabs(health_2) < 0.15f;
|
|
recommend_keep = (recommend_keep_1 && recommend_keep_2);
|
|
}
|
|
else if (get_manager().action == on_chip_calib_manager::RS2_CALIB_ACTION_ON_CHIP_FL_CALIB)
|
|
recommend_keep = fabs(get_manager().get_health()) < 0.15f;
|
|
else if (get_manager().action == on_chip_calib_manager::RS2_CALIB_ACTION_ON_CHIP_CALIB)
|
|
recommend_keep = fabs(get_manager().get_health()) < 0.25f;
|
|
|
|
if (recommend_keep && update_state == RS2_CALIB_STATE_CALIB_COMPLETE && (get_manager().action == on_chip_calib_manager::RS2_CALIB_ACTION_ON_CHIP_CALIB || get_manager().action == on_chip_calib_manager::RS2_CALIB_ACTION_ON_CHIP_FL_CALIB || get_manager().action == on_chip_calib_manager::RS2_CALIB_ACTION_ON_CHIP_OB_CALIB))
|
|
{
|
|
auto sat = 1.f + sin(duration_cast<milliseconds>(system_clock::now() - created_time).count() / 700.f) * 0.1f;
|
|
|
|
ImGui::PushStyleColor(ImGuiCol_Button, saturate(sensor_header_light_blue, sat));
|
|
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, saturate(sensor_header_light_blue, 1.5f));
|
|
notification_model::draw_dismiss(win, x, y);
|
|
ImGui::PopStyleColor(2);
|
|
}
|
|
else
|
|
notification_model::draw_dismiss(win, x, y);
|
|
}
|
|
|
|
void autocalib_notification_model::draw_intrinsic_extrinsic(int x, int y)
|
|
{
|
|
bool intrinsic = get_manager().intrinsic_scan;
|
|
bool extrinsic = !intrinsic;
|
|
|
|
ImGui::SetCursorScreenPos({ float(x + 9), float(y + 35 + ImGui::GetTextLineHeightWithSpacing()) });
|
|
|
|
std::string id = rsutils::string::from() << "##Intrinsic_" << index;
|
|
if (ImGui::Checkbox("Intrinsic", &intrinsic))
|
|
{
|
|
extrinsic = !intrinsic;
|
|
}
|
|
if (ImGui::IsItemHovered())
|
|
{
|
|
ImGui::SetTooltip("%s", "Calibrate intrinsic parameters of the camera");
|
|
}
|
|
ImGui::SetCursorScreenPos({ float(x + 135), float(y + 35 + ImGui::GetTextLineHeightWithSpacing()) });
|
|
|
|
id = rsutils::string::from() << "##Intrinsic_" << index;
|
|
|
|
if (ImGui::Checkbox("Extrinsic", &extrinsic))
|
|
{
|
|
intrinsic = !extrinsic;
|
|
}
|
|
if (ImGui::IsItemHovered())
|
|
{
|
|
ImGui::SetTooltip("%s", "Calibrate extrinsic parameters between left and right cameras");
|
|
}
|
|
|
|
get_manager().intrinsic_scan = intrinsic;
|
|
}
|
|
|
|
void autocalib_notification_model::draw_content(ux_window& win, int x, int y, float t, std::string& error_message)
|
|
{
|
|
using namespace std;
|
|
using namespace chrono;
|
|
|
|
if (update_state == RS2_CALIB_STATE_UVMAPPING_INPUT ||
|
|
update_state == RS2_CALIB_STATE_FL_INPUT ||
|
|
update_state == RS2_CALIB_STATE_GET_TARE_GROUND_TRUTH ||
|
|
update_state == RS2_CALIB_STATE_GET_TARE_GROUND_TRUTH_IN_PROCESS ||
|
|
update_state == RS2_CALIB_STATE_CALIB_IN_PROCESS &&
|
|
(get_manager().action == on_chip_calib_manager::RS2_CALIB_ACTION_FL_CALIB ||
|
|
get_manager().action == on_chip_calib_manager::RS2_CALIB_ACTION_UVMAPPING_CALIB))
|
|
get_manager().turn_roi_on();
|
|
else
|
|
get_manager().turn_roi_off();
|
|
|
|
const auto bar_width = width - 115;
|
|
|
|
ImGui::SetCursorScreenPos({ float(x + 9), float(y + 4) });
|
|
|
|
ImVec4 shadow{ 1.f, 1.f, 1.f, 0.1f };
|
|
ImGui::GetWindowDrawList()->AddRectFilled({ float(x), float(y) },
|
|
{ float(x + width), float(y + 25) }, ImColor(shadow));
|
|
|
|
if (update_state != RS2_CALIB_STATE_COMPLETE)
|
|
{
|
|
if (update_state == RS2_CALIB_STATE_INITIAL_PROMPT)
|
|
ImGui::Text("%s", "Calibration Health-Check");
|
|
else if (update_state == RS2_CALIB_STATE_UVMAPPING_INPUT)
|
|
ImGui::Text("%s", "UV-Mapping Calibration");
|
|
else if (update_state == RS2_CALIB_STATE_CALIB_IN_PROCESS ||
|
|
update_state == RS2_CALIB_STATE_CALIB_COMPLETE ||
|
|
update_state == RS2_CALIB_STATE_SELF_INPUT)
|
|
{
|
|
if (get_manager().action == on_chip_calib_manager::RS2_CALIB_ACTION_ON_CHIP_OB_CALIB)
|
|
ImGui::Text("%s", "On-Chip Calibration Extended");
|
|
else if (get_manager().action == on_chip_calib_manager::RS2_CALIB_ACTION_ON_CHIP_FL_CALIB)
|
|
ImGui::Text("%s", "On-Chip Focal Length Calibration");
|
|
else if (get_manager().action == on_chip_calib_manager::RS2_CALIB_ACTION_TARE_CALIB)
|
|
ImGui::Text("%s", "Tare Calibration");
|
|
else if (get_manager().action == on_chip_calib_manager::RS2_CALIB_ACTION_FL_CALIB)
|
|
ImGui::Text("%s", "Focal Length Calibration");
|
|
else if (get_manager().action == on_chip_calib_manager::RS2_CALIB_ACTION_UVMAPPING_CALIB)
|
|
ImGui::Text("%s", "UV-Mapping Calibration");
|
|
else
|
|
ImGui::Text("%s", "On-Chip Calibration");
|
|
}
|
|
else if (update_state == RS2_CALIB_STATE_FL_INPUT)
|
|
ImGui::Text("%s", "Focal Length Calibration");
|
|
else if (update_state == RS2_CALIB_STATE_TARE_INPUT || update_state == RS2_CALIB_STATE_TARE_INPUT_ADVANCED)
|
|
ImGui::Text("%s", "Tare Calibration");
|
|
else if (update_state == RS2_CALIB_STATE_GET_TARE_GROUND_TRUTH || update_state == RS2_CALIB_STATE_GET_TARE_GROUND_TRUTH_IN_PROCESS || update_state == RS2_CALIB_STATE_GET_TARE_GROUND_TRUTH_COMPLETE)
|
|
ImGui::Text("%s", "Get Tare Calibration Ground Truth");
|
|
else if (update_state == RS2_CALIB_STATE_GET_TARE_GROUND_TRUTH_FAILED)
|
|
ImGui::Text("%s", "Get Tare Calibration Ground Truth Failed");
|
|
else if (update_state == RS2_CALIB_STATE_FAILED && !((get_manager().action == on_chip_calib_manager::RS2_CALIB_ACTION_ON_CHIP_OB_CALIB || get_manager().action == on_chip_calib_manager::RS2_CALIB_ACTION_ON_CHIP_FL_CALIB) && get_manager().retry_times < 3))
|
|
ImGui::Text("%s", "Calibration Failed");
|
|
|
|
if (update_state == RS2_CALIB_STATE_TARE_INPUT || update_state == RS2_CALIB_STATE_TARE_INPUT_ADVANCED)
|
|
ImGui::SetCursorScreenPos({ float(x + width - 30), float(y) });
|
|
else if (update_state == RS2_CALIB_STATE_FAILED)
|
|
ImGui::SetCursorScreenPos({ float(x + 2), float(y + 27) });
|
|
else
|
|
ImGui::SetCursorScreenPos({ float(x + 9), float(y + 27) });
|
|
|
|
ImGui::PushStyleColor(ImGuiCol_Text, alpha(light_grey, 1.f - t));
|
|
|
|
if (update_state == RS2_CALIB_STATE_INITIAL_PROMPT)
|
|
{
|
|
ImGui::SetCursorPosY(ImGui::GetCursorPosY() + 2);
|
|
|
|
ImGui::Text("%s", "Following devices support On-Chip Calibration:");
|
|
ImGui::SetCursorScreenPos({ float(x + 9), float(y + 47) });
|
|
|
|
ImGui::PushStyleColor(ImGuiCol_Text, white);
|
|
ImGui::Text("%s", message.c_str());
|
|
ImGui::PopStyleColor();
|
|
|
|
ImGui::SetCursorScreenPos({ float(x + 9), float(y + 65) });
|
|
ImGui::Text("%s", "Run quick calibration Health-Check? (~30 sec)");
|
|
}
|
|
else if (update_state == RS2_CALIB_STATE_CALIB_IN_PROCESS)
|
|
{
|
|
enable_dismiss = false;
|
|
if (get_manager().action == on_chip_calib_manager::RS2_CALIB_ACTION_FL_CALIB || get_manager().action == on_chip_calib_manager::RS2_CALIB_ACTION_UVMAPPING_CALIB)
|
|
ImGui::Text("%s", "Camera is being calibrated...\nKeep the camera stationary pointing at the target");
|
|
else
|
|
ImGui::Text("%s", "Camera is being calibrated...\nKeep the camera stationary pointing at a wall");
|
|
}
|
|
else if (update_state == RS2_CALIB_STATE_UVMAPPING_INPUT)
|
|
{
|
|
ImGui::SetCursorScreenPos({ float(x + 15), float(y + 33) });
|
|
ImGui::Text("%s", "Please make sure the target is inside yellow\nrectangle on both left and color images. Adjust\ncamera position if necessary before to start.");
|
|
|
|
auto sat = 1.f + sin(duration_cast<milliseconds>(system_clock::now() - created_time).count() / 700.f) * 0.1f;
|
|
ImGui::PushStyleColor(ImGuiCol_Button, saturate(sensor_header_light_blue, sat));
|
|
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, saturate(sensor_header_light_blue, 1.5f));
|
|
ImGui::SetCursorScreenPos({ float(x + 9), float(y + height - 55) });
|
|
ImGui::Checkbox("Px/Py only", &get_manager().py_px_only);
|
|
if (ImGui::IsItemHovered())
|
|
{
|
|
ImGui::SetTooltip("%s", "Calibrate: {Fx/Fy/Px/Py}/{Px/Py}");
|
|
}
|
|
|
|
ImGui::SetCursorScreenPos({ float(x + 9), float(y + height - 25) });
|
|
std::string button_name = rsutils::string::from() << "Calibrate" << "##uvmapping" << index;
|
|
if (ImGui::Button(button_name.c_str(), { float(bar_width - 60), 20.f }))
|
|
{
|
|
get_manager().restore_workspace([this](std::function<void()> a) { a(); });
|
|
get_manager().reset();
|
|
get_manager().retry_times = 0;
|
|
get_manager().action = on_chip_calib_manager::RS2_CALIB_ACTION_UVMAPPING_CALIB;
|
|
auto _this = shared_from_this();
|
|
auto invoke = [_this](std::function<void()> action) {
|
|
_this->invoke(action);
|
|
};
|
|
get_manager().start(invoke);
|
|
update_state = RS2_CALIB_STATE_CALIB_IN_PROCESS;
|
|
enable_dismiss = false;
|
|
}
|
|
|
|
if (ImGui::IsItemHovered())
|
|
ImGui::SetTooltip("%s", "Begin UV-Mapping calibration after adjusting camera position");
|
|
ImGui::PopStyleColor(2);
|
|
|
|
string id = rsutils::string::from() << "Py Px Calibration only##py_px_only" << index;
|
|
ImGui::SetCursorScreenPos({ float(x + 15), float(y + height - ImGui::GetTextLineHeightWithSpacing() - 32) });
|
|
ImGui::Checkbox(id.c_str(), &get_manager().py_px_only);
|
|
}
|
|
else if (update_state == RS2_CALIB_STATE_GET_TARE_GROUND_TRUTH)
|
|
{
|
|
ImGui::SetCursorScreenPos({ float(x + 3), float(y + 33) });
|
|
ImGui::Text("%s", "Please make sure target is inside yellow rectangle.");
|
|
|
|
ImGui::SetCursorScreenPos({ float(x + 9), float(y + 38 + ImGui::GetTextLineHeightWithSpacing()) });
|
|
ImGui::Text("%s", "Target Width:");
|
|
if (ImGui::IsItemHovered())
|
|
{
|
|
ImGui::SetTooltip("%s", "The width of the rectangle in millimeter inside the specific target");
|
|
}
|
|
|
|
const int MAX_SIZE = 256;
|
|
char buff[MAX_SIZE];
|
|
|
|
ImGui::SetCursorScreenPos({ float(x + 135), float(y + 35 + ImGui::GetTextLineHeightWithSpacing()) });
|
|
std::string id = rsutils::string::from() << "##target_width_" << index;
|
|
ImGui::PushItemWidth(width - 145.0f);
|
|
float target_width = config_file::instance().get_or_default(configurations::viewer::target_width_r, 175.0f);
|
|
std::string tw = rsutils::string::from() << target_width;
|
|
memcpy(buff, tw.c_str(), tw.size() + 1);
|
|
if (ImGui::InputText(id.c_str(), buff, std::max((int)tw.size() + 1, 10)))
|
|
{
|
|
std::stringstream ss;
|
|
ss << buff;
|
|
ss >> target_width;
|
|
config_file::instance().set(configurations::viewer::target_width_r, target_width);
|
|
}
|
|
ImGui::PopItemWidth();
|
|
|
|
ImGui::SetCursorScreenPos({ float(x + 9), float(y + 43 + 2 * ImGui::GetTextLineHeightWithSpacing()) });
|
|
ImGui::Text("%s", "Target Height:");
|
|
if (ImGui::IsItemHovered())
|
|
{
|
|
ImGui::SetTooltip("%s", "The height of the rectangle in millimeter inside the specific target");
|
|
}
|
|
|
|
ImGui::SetCursorScreenPos({ float(x + 135), float(y + 40 + 2 * ImGui::GetTextLineHeightWithSpacing()) });
|
|
id = rsutils::string::from() << "##target_height_" << index;
|
|
ImGui::PushItemWidth(width - 145.0f);
|
|
float target_height = config_file::instance().get_or_default(configurations::viewer::target_height_r, 100.0f);
|
|
std::string th = rsutils::string::from() << target_height;
|
|
memcpy(buff, th.c_str(), th.size() + 1);
|
|
if (ImGui::InputText(id.c_str(), buff, std::max((int)th.size() + 1, 10)))
|
|
{
|
|
std::stringstream ss;
|
|
ss << buff;
|
|
ss >> target_height;
|
|
config_file::instance().set(configurations::viewer::target_height_r, target_height);
|
|
}
|
|
ImGui::PopItemWidth();
|
|
|
|
ImGui::SetCursorScreenPos({ float(x + 9), float(y + height - 25) });
|
|
auto sat = 1.f + sin(duration_cast<milliseconds>(system_clock::now() - created_time).count() / 700.f) * 0.1f;
|
|
ImGui::PushStyleColor(ImGuiCol_Button, saturate(sensor_header_light_blue, sat));
|
|
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, saturate(sensor_header_light_blue, 1.5f));
|
|
|
|
std::string back_button_name = rsutils::string::from() << "Back" << "##tare" << index;
|
|
if (ImGui::Button(back_button_name.c_str(), { float(60), 20.f }))
|
|
{
|
|
get_manager().action = on_chip_calib_manager::RS2_CALIB_ACTION_TARE_CALIB;
|
|
update_state = update_state_prev;
|
|
get_manager().stop_viewer();
|
|
}
|
|
|
|
ImGui::SetCursorScreenPos({ float(x + 85), float(y + height - 25) });
|
|
std::string button_name = rsutils::string::from() << "Calculate" << "##tare" << index;
|
|
if (ImGui::Button(button_name.c_str(), { float(bar_width - 70), 20.f }))
|
|
{
|
|
get_manager().restore_workspace([this](std::function<void()> a) { a(); });
|
|
get_manager().reset();
|
|
get_manager().retry_times = 0;
|
|
get_manager().action = on_chip_calib_manager::RS2_CALIB_ACTION_TARE_GROUND_TRUTH;
|
|
auto _this = shared_from_this();
|
|
auto invoke = [_this](std::function<void()> action) {
|
|
_this->invoke(action);
|
|
};
|
|
get_manager().start(invoke);
|
|
update_state = RS2_CALIB_STATE_GET_TARE_GROUND_TRUTH_IN_PROCESS;
|
|
enable_dismiss = false;
|
|
}
|
|
|
|
ImGui::PopStyleColor(2);
|
|
|
|
if (ImGui::IsItemHovered())
|
|
{
|
|
ImGui::SetTooltip("%s", "Begin calculating Tare Calibration/Distance to Target");
|
|
}
|
|
}
|
|
else if (update_state == RS2_CALIB_STATE_GET_TARE_GROUND_TRUTH_IN_PROCESS)
|
|
{
|
|
enable_dismiss = false;
|
|
ImGui::Text("%s", "Distance to Target calculation is in process...\nKeep camera stationary pointing at the target");
|
|
}
|
|
else if (update_state == RS2_CALIB_STATE_GET_TARE_GROUND_TRUTH_COMPLETE)
|
|
{
|
|
get_manager().action = on_chip_calib_manager::RS2_CALIB_ACTION_TARE_CALIB;
|
|
update_state = update_state_prev;
|
|
}
|
|
else if (update_state == RS2_CALIB_STATE_GET_TARE_GROUND_TRUTH_FAILED)
|
|
{
|
|
ImGui::Text("%s", _error_message.c_str());
|
|
|
|
auto sat = 1.f + sin(duration_cast<milliseconds>(system_clock::now() - created_time).count() / 700.f) * 0.1f;
|
|
|
|
ImGui::PushStyleColor(ImGuiCol_Button, saturate(redish, sat));
|
|
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, saturate(redish, 1.5f));
|
|
|
|
std::string button_name = rsutils::string::from() << "Retry" << "##retry" << index;
|
|
|
|
ImGui::SetCursorScreenPos({ float(x + 5), float(y + height - 25) });
|
|
if (ImGui::Button(button_name.c_str(), { float(bar_width), 20.f }))
|
|
{
|
|
get_manager().restore_workspace([this](std::function<void()> a) { a(); });
|
|
get_manager().reset();
|
|
auto _this = shared_from_this();
|
|
auto invoke = [_this](std::function<void()> action) {
|
|
_this->invoke(action);
|
|
};
|
|
get_manager().start(invoke);
|
|
update_state = RS2_CALIB_STATE_GET_TARE_GROUND_TRUTH_IN_PROCESS;
|
|
enable_dismiss = false;
|
|
}
|
|
|
|
ImGui::PopStyleColor(2);
|
|
|
|
if (ImGui::IsItemHovered())
|
|
{
|
|
ImGui::SetTooltip("%s", "Retry calculating ground truth");
|
|
}
|
|
}
|
|
else if (update_state == RS2_CALIB_STATE_TARE_INPUT || update_state == RS2_CALIB_STATE_TARE_INPUT_ADVANCED)
|
|
{
|
|
ImGui::PushStyleColor(ImGuiCol_Text, update_state != RS2_CALIB_STATE_TARE_INPUT_ADVANCED ? light_grey : light_blue);
|
|
ImGui::PushStyleColor(ImGuiCol_TextSelectedBg, update_state != RS2_CALIB_STATE_TARE_INPUT_ADVANCED ? light_grey : light_blue);
|
|
|
|
if (ImGui::Button(u8"\uf0d7"))
|
|
{
|
|
if (update_state == RS2_CALIB_STATE_TARE_INPUT_ADVANCED)
|
|
update_state = RS2_CALIB_STATE_TARE_INPUT;
|
|
else
|
|
update_state = RS2_CALIB_STATE_TARE_INPUT_ADVANCED;
|
|
}
|
|
|
|
if (ImGui::IsItemHovered())
|
|
{
|
|
if (update_state == RS2_CALIB_STATE_TARE_INPUT)
|
|
ImGui::SetTooltip("%s", "More Options...");
|
|
else
|
|
ImGui::SetTooltip("%s", "Less Options...");
|
|
}
|
|
|
|
ImGui::PopStyleColor(2);
|
|
if (update_state == RS2_CALIB_STATE_TARE_INPUT_ADVANCED)
|
|
{
|
|
ImGui::SetCursorScreenPos({ float(x + 9), float(y + 33) });
|
|
ImGui::Text("%s", "Avg Step Count:");
|
|
if (ImGui::IsItemHovered())
|
|
{
|
|
ImGui::SetTooltip("%s", "Number of frames to average, Min = 1, Max = 30, Default = 20");
|
|
}
|
|
ImGui::SetCursorScreenPos({ float(x + 135), float(y + 30) });
|
|
|
|
std::string id = rsutils::string::from() << "##avg_step_count_" << index;
|
|
ImGui::PushItemWidth(width - 145.f);
|
|
ImGui::SliderInt(id.c_str(), &get_manager().average_step_count, 1, 30);
|
|
ImGui::PopItemWidth();
|
|
|
|
//-------------------------
|
|
|
|
ImGui::SetCursorScreenPos({ float(x + 9), float(y + 38 + ImGui::GetTextLineHeightWithSpacing()) });
|
|
ImGui::Text("%s", "Step Count:");
|
|
if (ImGui::IsItemHovered())
|
|
{
|
|
ImGui::SetTooltip("%s", "Max iteration steps, Min = 5, Max = 30, Default = 20");
|
|
}
|
|
ImGui::SetCursorScreenPos({ float(x + 135), float(y + 35 + ImGui::GetTextLineHeightWithSpacing()) });
|
|
|
|
id = rsutils::string::from() << "##step_count_" << index;
|
|
|
|
ImGui::PushItemWidth(width - 145.f);
|
|
ImGui::SliderInt(id.c_str(), &get_manager().step_count, 1, 30);
|
|
ImGui::PopItemWidth();
|
|
|
|
//-------------------------
|
|
|
|
ImGui::SetCursorScreenPos({ float(x + 9), float(y + 43 + 2 * ImGui::GetTextLineHeightWithSpacing()) });
|
|
ImGui::Text("%s", "Accuracy:");
|
|
if (ImGui::IsItemHovered())
|
|
{
|
|
ImGui::SetTooltip("%s", "Subpixel accuracy level, Very high = 0 (0.025%), High = 1 (0.05%), Medium = 2 (0.1%), Low = 3 (0.2%), Default = Very high (0.025%)");
|
|
}
|
|
|
|
ImGui::SetCursorScreenPos({ float(x + 135), float(y + 40 + 2 * ImGui::GetTextLineHeightWithSpacing()) });
|
|
|
|
id = rsutils::string::from() << "##accuracy_" << index;
|
|
|
|
std::vector<std::string> vals{ "Very High", "High", "Medium", "Low" };
|
|
std::vector<const char*> vals_cstr;
|
|
for (auto&& s : vals) vals_cstr.push_back(s.c_str());
|
|
|
|
ImGui::PushItemWidth(width - 145.f);
|
|
ImGui::Combo(id.c_str(), &get_manager().accuracy, vals_cstr.data(), int(vals.size()));
|
|
|
|
ImGui::SetCursorScreenPos({ float(x + 135), float(y + 35 + ImGui::GetTextLineHeightWithSpacing()) });
|
|
|
|
ImGui::PopItemWidth();
|
|
|
|
// Disabled according to the decision on v2.50
|
|
//draw_intrinsic_extrinsic(x, y + 3 * int(ImGui::GetTextLineHeightWithSpacing()) - 10);
|
|
|
|
ImGui::SetCursorScreenPos({ float(x + 9), float(y + 52 + 4 * ImGui::GetTextLineHeightWithSpacing()) });
|
|
id = rsutils::string::from() << "Apply High-Accuracy Preset##apply_preset_" << index;
|
|
ImGui::Checkbox(id.c_str(), &get_manager().apply_preset);
|
|
}
|
|
|
|
if (update_state == RS2_CALIB_STATE_TARE_INPUT_ADVANCED)
|
|
{
|
|
ImGui::SetCursorScreenPos({ float(x + 9), float(y + 60 + 5 * ImGui::GetTextLineHeightWithSpacing()) });
|
|
ImGui::Text("%s", "Ground Truth(mm):");
|
|
ImGui::SetCursorScreenPos({ float(x + 135), float(y + 58 + 5 * ImGui::GetTextLineHeightWithSpacing()) });
|
|
}
|
|
else
|
|
{
|
|
ImGui::SetCursorScreenPos({ float(x + 9), float(y + 33) });
|
|
ImGui::Text("%s", "Ground Truth (mm):");
|
|
ImGui::SetCursorScreenPos({ float(x + 135), float(y + 30) });
|
|
}
|
|
|
|
if (ImGui::IsItemHovered())
|
|
ImGui::SetTooltip("%s", "Distance in millimeter to the flat wall, between 60 and 10000.");
|
|
|
|
std::string id = rsutils::string::from() << "##ground_truth_for_tare" << index;
|
|
get_manager().ground_truth = config_file::instance().get_or_default(configurations::viewer::ground_truth_r, 1200.0f);
|
|
|
|
std::string gt = rsutils::string::from() << get_manager().ground_truth;
|
|
const int MAX_SIZE = 256;
|
|
char buff[MAX_SIZE];
|
|
memcpy(buff, gt.c_str(), gt.size() + 1);
|
|
|
|
ImGui::PushItemWidth(width - 196.f);
|
|
if (ImGui::InputText(id.c_str(), buff, std::max((int)gt.size() + 1, 10)))
|
|
{
|
|
std::stringstream ss;
|
|
ss << buff;
|
|
ss >> get_manager().ground_truth;
|
|
}
|
|
ImGui::PopItemWidth();
|
|
|
|
config_file::instance().set(configurations::viewer::ground_truth_r, get_manager().ground_truth);
|
|
|
|
auto sat = 1.f + sin(duration_cast<milliseconds>(system_clock::now() - created_time).count() / 700.f) * 0.1f;
|
|
|
|
ImGui::PushStyleColor(ImGuiCol_Button, saturate(sensor_header_light_blue, sat));
|
|
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, saturate(sensor_header_light_blue, 1.5f));
|
|
|
|
std::string get_button_name = rsutils::string::from() << "Get" << "##tare" << index;
|
|
if (update_state == RS2_CALIB_STATE_TARE_INPUT_ADVANCED)
|
|
ImGui::SetCursorScreenPos({ float(x + width - 52), float(y + 58 + 5 * ImGui::GetTextLineHeightWithSpacing()) });
|
|
else
|
|
ImGui::SetCursorScreenPos({ float(x + width - 52), float(y + 30) });
|
|
|
|
if (ImGui::Button(get_button_name.c_str(), { 42.0f, 20.f }))
|
|
{
|
|
update_state_prev = update_state;
|
|
update_state = RS2_CALIB_STATE_GET_TARE_GROUND_TRUTH;
|
|
get_manager().start_gt_viewer();
|
|
}
|
|
if (ImGui::IsItemHovered())
|
|
ImGui::SetTooltip("%s", "Calculate ground truth for the specific target");
|
|
|
|
ImGui::SetCursorScreenPos({ float(x + 9), float(y + height - ImGui::GetTextLineHeightWithSpacing() - 30) });
|
|
get_manager().host_assistance = (get_manager().device_name_string == std::string("Intel RealSense D457") ); // To be used for MIPI SKU only
|
|
bool assistance = (get_manager().host_assistance != 0);
|
|
if (ImGui::Checkbox("Host Assistance", &assistance))
|
|
get_manager().host_assistance = (assistance ? 1 : 0);
|
|
if (ImGui::IsItemHovered())
|
|
ImGui::SetTooltip("%s", "check = host assitance for statistics data, uncheck = no host assistance");
|
|
|
|
std::string button_name = rsutils::string::from() << "Calibrate" << "##tare" << index;
|
|
|
|
ImGui::SetCursorScreenPos({ float(x + 5), float(y + height - 28) });
|
|
if (ImGui::Button(button_name.c_str(), { float(bar_width), 20.f }))
|
|
{
|
|
get_manager().restore_workspace([](std::function<void()> a) { a(); });
|
|
get_manager().reset();
|
|
get_manager().retry_times = 0;
|
|
get_manager().action = on_chip_calib_manager::RS2_CALIB_ACTION_TARE_CALIB;
|
|
auto _this = shared_from_this();
|
|
auto invoke = [_this](std::function<void()> action) {
|
|
_this->invoke(action);
|
|
};
|
|
get_manager().start(invoke);
|
|
update_state = RS2_CALIB_STATE_CALIB_IN_PROCESS;
|
|
enable_dismiss = false;
|
|
}
|
|
|
|
ImGui::PopStyleColor(2);
|
|
|
|
if (ImGui::IsItemHovered())
|
|
{
|
|
ImGui::SetTooltip("%s", "Begin Tare Calibration");
|
|
}
|
|
}
|
|
else if (update_state == RS2_CALIB_STATE_SELF_INPUT)
|
|
{
|
|
// Disabled according to the decision on v2.50
|
|
/*
|
|
ImGui::SetCursorScreenPos({ float(x + 9), float(y + 33) });
|
|
ImGui::Text("%s", "Speed:");
|
|
|
|
ImGui::SetCursorScreenPos({ float(x + 135), float(y + 30) });
|
|
|
|
std::string id = to_string() << "##speed_" << index;
|
|
|
|
std::vector<const char*> vals_cstr;
|
|
if (get_manager().action != on_chip_calib_manager::RS2_CALIB_ACTION_ON_CHIP_CALIB)
|
|
{
|
|
std::vector<std::string> vals{ "Fast", "Slow", "White Wall" };
|
|
for (auto&& s : vals) vals_cstr.push_back(s.c_str());
|
|
|
|
ImGui::PushItemWidth(width - 145.f);
|
|
ImGui::Combo(id.c_str(), &get_manager().speed_fl, vals_cstr.data(), int(vals.size()));
|
|
ImGui::PopItemWidth();
|
|
}
|
|
else
|
|
{
|
|
std::vector<std::string> vals{ "Very Fast", "Fast", "Medium", "Slow", "White Wall" };
|
|
for (auto&& s : vals) vals_cstr.push_back(s.c_str());
|
|
|
|
ImGui::PushItemWidth(width - 145.f);
|
|
ImGui::Combo(id.c_str(), &get_manager().speed, vals_cstr.data(), int(vals.size()));
|
|
ImGui::PopItemWidth();
|
|
}
|
|
|
|
if (get_manager().action != on_chip_calib_manager::RS2_CALIB_ACTION_ON_CHIP_FL_CALIB)
|
|
draw_intrinsic_extrinsic(x, y);
|
|
|
|
if (get_manager().action != on_chip_calib_manager::RS2_CALIB_ACTION_ON_CHIP_CALIB)
|
|
{
|
|
float tmp_y = (get_manager().action == on_chip_calib_manager::RS2_CALIB_ACTION_ON_CHIP_OB_CALIB ?
|
|
float(y + 40 + 2 * ImGui::GetTextLineHeightWithSpacing()) : float(y + 35 + ImGui::GetTextLineHeightWithSpacing()));
|
|
ImGui::SetCursorScreenPos({ float(x + 9), tmp_y });
|
|
id = to_string() << "##restore_" << index;
|
|
bool restore = (get_manager().adjust_both_sides == 1);
|
|
if (ImGui::Checkbox("Adjust both sides focal length", &restore))
|
|
get_manager().adjust_both_sides = (restore ? 1 : 0);
|
|
if (ImGui::IsItemHovered())
|
|
ImGui::SetTooltip("%s", "check = adjust both sides, uncheck = adjust right side only");
|
|
}*/
|
|
|
|
// Deprecase OCC-Extended
|
|
//float tmp_y = (get_manager().action == on_chip_calib_manager::RS2_CALIB_ACTION_ON_CHIP_OB_CALIB ?
|
|
// float(y + 45 + 3 * ImGui::GetTextLineHeightWithSpacing()) : float(y + 41 + 2 * ImGui::GetTextLineHeightWithSpacing()));
|
|
|
|
//ImGui::SetCursorScreenPos({ float(x + 9), tmp_y });
|
|
//if (ImGui::RadioButton("OCC", (int*)&(get_manager().action), 1))
|
|
// get_manager().action = on_chip_calib_manager::RS2_CALIB_ACTION_ON_CHIP_CALIB;
|
|
//if (ImGui::IsItemHovered())
|
|
// ImGui::SetTooltip("%s", "On-chip calibration");
|
|
|
|
//ImGui::SetCursorScreenPos({ float(x + 135), tmp_y });
|
|
//if (ImGui::RadioButton("OCC Extended", (int *)&(get_manager().action), 0))
|
|
// get_manager().action = on_chip_calib_manager::RS2_CALIB_ACTION_ON_CHIP_OB_CALIB;
|
|
//if (ImGui::IsItemHovered())
|
|
// ImGui::SetTooltip("%s", "On-Chip Calibration Extended");
|
|
|
|
ImGui::SetCursorScreenPos({ float(x + 9), float(y + height - ImGui::GetTextLineHeightWithSpacing() - 31) });
|
|
get_manager().host_assistance = (get_manager().device_name_string == std::string("Intel RealSense D457") ); // To be used for MIPI SKU only
|
|
bool assistance = (get_manager().host_assistance != 0);
|
|
ImGui::Checkbox("Host Assistance", &assistance);
|
|
if (ImGui::IsItemHovered())
|
|
ImGui::SetTooltip("%s", "check = host assitance for statistics data, uncheck = no host assistance");
|
|
|
|
auto sat = 1.f + sin(duration_cast<milliseconds>(system_clock::now() - created_time).count() / 700.f) * 0.1f;
|
|
ImGui::PushStyleColor(ImGuiCol_Button, saturate(sensor_header_light_blue, sat));
|
|
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, saturate(sensor_header_light_blue, 1.5f));
|
|
|
|
std::string button_name = rsutils::string::from() << "Calibrate" << "##self" << index;
|
|
|
|
ImGui::SetCursorScreenPos({ float(x + 5), float(y + height - 28) });
|
|
if (ImGui::Button(button_name.c_str(), { float(bar_width), 20.f }))
|
|
{
|
|
get_manager().restore_workspace([this](std::function<void()> a) { a(); });
|
|
get_manager().reset();
|
|
get_manager().retry_times = 0;
|
|
auto _this = shared_from_this();
|
|
auto invoke = [_this](std::function<void()> action) {_this->invoke(action);};
|
|
get_manager().start(invoke);
|
|
update_state = RS2_CALIB_STATE_CALIB_IN_PROCESS;
|
|
enable_dismiss = false;
|
|
}
|
|
|
|
ImGui::PopStyleColor(2);
|
|
|
|
if (ImGui::IsItemHovered())
|
|
ImGui::SetTooltip("%s", "Begin On-Chip Calibration");
|
|
}
|
|
else if (update_state == RS2_CALIB_STATE_FL_INPUT)
|
|
{
|
|
ImGui::SetCursorScreenPos({ float(x + 15), float(y + 33) });
|
|
ImGui::Text("%s", "Please make sure the target is inside yellow\nrectangle of both left and right images. Adjust\ncamera position if necessary before to start.");
|
|
|
|
ImGui::SetCursorScreenPos({ float(x + 15), float(y + 70 + ImGui::GetTextLineHeightWithSpacing()) });
|
|
ImGui::Text("%s", "Target Width (mm):");
|
|
if (ImGui::IsItemHovered())
|
|
{
|
|
ImGui::SetTooltip("%s", "The width of the rectangle in millimeters inside the specific target");
|
|
}
|
|
|
|
const int MAX_SIZE = 256;
|
|
char buff[MAX_SIZE];
|
|
|
|
ImGui::SetCursorScreenPos({ float(x + 145), float(y + 70 + ImGui::GetTextLineHeightWithSpacing()) });
|
|
std::string id = rsutils::string::from() << "##target_width_" << index;
|
|
ImGui::PushItemWidth(80);
|
|
float target_width = config_file::instance().get_or_default(configurations::viewer::target_width_r, 175.0f);
|
|
std::string tw = rsutils::string::from() << target_width;
|
|
memcpy(buff, tw.c_str(), tw.size() + 1);
|
|
if (ImGui::InputText(id.c_str(), buff, std::max((int)tw.size() + 1, 10)))
|
|
{
|
|
std::stringstream ss;
|
|
ss << buff;
|
|
ss >> target_width;
|
|
config_file::instance().set(configurations::viewer::target_width_r, target_width);
|
|
}
|
|
ImGui::PopItemWidth();
|
|
|
|
ImGui::SetCursorScreenPos({ float(x + 15), float(y + 80 + 2 * ImGui::GetTextLineHeightWithSpacing()) });
|
|
ImGui::Text("%s", "Target Height (mm):");
|
|
if (ImGui::IsItemHovered())
|
|
{
|
|
ImGui::SetTooltip("%s", "The height of the rectangle in millimeters inside the specific target");
|
|
}
|
|
|
|
ImGui::SetCursorScreenPos({ float(x + 145), float(y + 77 + 2 * ImGui::GetTextLineHeightWithSpacing()) });
|
|
id = rsutils::string::from() << "##target_height_" << index;
|
|
ImGui::PushItemWidth(80);
|
|
float target_height = config_file::instance().get_or_default(configurations::viewer::target_height_r, 100.0f);
|
|
std::string th = rsutils::string::from() << target_height;
|
|
memcpy(buff, th.c_str(), th.size() + 1);
|
|
if (ImGui::InputText(id.c_str(), buff, std::max((int)th.size() + 1, 10)))
|
|
{
|
|
std::stringstream ss;
|
|
ss << buff;
|
|
ss >> target_height;
|
|
config_file::instance().set(configurations::viewer::target_height_r, target_height);
|
|
}
|
|
ImGui::PopItemWidth();
|
|
|
|
ImGui::SetCursorScreenPos({ float(x + 20), float(y + 95) + 3 * ImGui::GetTextLineHeight() });
|
|
bool adj_both = (get_manager().adjust_both_sides == 1);
|
|
if (ImGui::Checkbox("Adjust both sides focal length", &adj_both))
|
|
get_manager().adjust_both_sides = (adj_both ? 1 : 0);
|
|
if (ImGui::IsItemHovered())
|
|
ImGui::SetTooltip("%s", "check = adjust both sides, uncheck = adjust right side only");
|
|
|
|
ImGui::SetCursorScreenPos({ float(x + 9), float(y + height - 25) });
|
|
auto sat = 1.f + sin(duration_cast<milliseconds>(system_clock::now() - created_time).count() / 700.f) * 0.1f;
|
|
ImGui::PushStyleColor(ImGuiCol_Button, saturate(sensor_header_light_blue, sat));
|
|
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, saturate(sensor_header_light_blue, 1.5f));
|
|
|
|
std::string button_name = rsutils::string::from() << "Calibrate" << "##fl" << index;
|
|
|
|
ImGui::SetCursorScreenPos({ float(x + 5), float(y + height - 25) });
|
|
if (ImGui::Button(button_name.c_str(), { float(bar_width), 20.f }))
|
|
{
|
|
get_manager().restore_workspace([this](std::function<void()> a) { a(); });
|
|
get_manager().reset();
|
|
get_manager().retry_times = 0;
|
|
get_manager().action = on_chip_calib_manager::RS2_CALIB_ACTION_FL_CALIB;
|
|
auto _this = shared_from_this();
|
|
auto invoke = [_this](std::function<void()> action) {
|
|
_this->invoke(action);
|
|
};
|
|
get_manager().start(invoke);
|
|
update_state = RS2_CALIB_STATE_CALIB_IN_PROCESS;
|
|
enable_dismiss = false;
|
|
}
|
|
if (ImGui::IsItemHovered())
|
|
ImGui::SetTooltip("%s", "Start focal length calibration after setting up camera position correctly.");
|
|
ImGui::PopStyleColor(2);
|
|
}
|
|
else if (update_state == RS2_CALIB_STATE_FAILED)
|
|
{
|
|
if (get_manager().action == on_chip_calib_manager::RS2_CALIB_ACTION_ON_CHIP_FL_CALIB
|
|
|| get_manager().action == on_chip_calib_manager::RS2_CALIB_ACTION_ON_CHIP_OB_CALIB)
|
|
{
|
|
if (get_manager().retry_times < 3)
|
|
{
|
|
get_manager().restore_workspace([](std::function<void()> a){ a(); });
|
|
get_manager().reset();
|
|
++get_manager().retry_times;
|
|
get_manager().toggle = true;
|
|
|
|
auto _this = shared_from_this();
|
|
auto invoke = [_this](std::function<void()> action) {_this->invoke(action);};
|
|
get_manager().start(invoke);
|
|
update_state = RS2_CALIB_STATE_CALIB_IN_PROCESS;
|
|
enable_dismiss = false;
|
|
}
|
|
else
|
|
{
|
|
ImGui::Text("%s", (get_manager().action == on_chip_calib_manager::RS2_CALIB_ACTION_ON_CHIP_FL_CALIB ? "OCC FL calibraton cannot work with this camera!" : "OCC Extended calibraton cannot work with this camera!"));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ImGui::Text("%s", _error_message.c_str());
|
|
|
|
auto sat = 1.f + sin(duration_cast<milliseconds>(system_clock::now() - created_time).count() / 700.f) * 0.1f;
|
|
|
|
ImGui::PushStyleColor(ImGuiCol_Button, saturate(redish, sat));
|
|
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, saturate(redish, 1.5f));
|
|
|
|
std::string button_name = rsutils::string::from() << "Retry" << "##retry" << index;
|
|
ImGui::SetCursorScreenPos({ float(x + 5), float(y + height - 25) });
|
|
if (ImGui::Button(button_name.c_str(), { float(bar_width), 20.f }))
|
|
{
|
|
get_manager().restore_workspace([](std::function<void()> a) { a(); });
|
|
get_manager().reset();
|
|
auto _this = shared_from_this();
|
|
auto invoke = [_this](std::function<void()> action) {
|
|
_this->invoke(action);
|
|
};
|
|
get_manager().start(invoke);
|
|
update_state = RS2_CALIB_STATE_CALIB_IN_PROCESS;
|
|
enable_dismiss = false;
|
|
}
|
|
|
|
ImGui::PopStyleColor(2);
|
|
|
|
if (ImGui::IsItemHovered())
|
|
ImGui::SetTooltip("%s", "Retry on-chip calibration process");
|
|
}
|
|
}
|
|
else if (update_state == RS2_CALIB_STATE_CALIB_COMPLETE)
|
|
{
|
|
if (get_manager().action == on_chip_calib_manager::RS2_CALIB_ACTION_UVMAPPING_CALIB)
|
|
{
|
|
ImGui::SetCursorScreenPos({ float(x + 20), float(y + 33) });
|
|
ImGui::Text("%s", "Health-Check Number for PX: ");
|
|
|
|
ImGui::SetCursorScreenPos({ float(x + 20), float(y + 38) + ImGui::GetTextLineHeightWithSpacing() });
|
|
ImGui::Text("%s", "Health Check Number for PY: ");
|
|
|
|
ImGui::SetCursorScreenPos({ float(x + 20), float(y + 43) + 2 * ImGui::GetTextLineHeightWithSpacing() });
|
|
ImGui::Text("%s", "Health Check Number for FX: ");
|
|
|
|
ImGui::SetCursorScreenPos({ float(x + 20), float(y + 48) + 3 * ImGui::GetTextLineHeightWithSpacing() });
|
|
ImGui::Text("%s", "Health Check Number for FY: ");
|
|
|
|
ImGui::PushStyleColor(ImGuiCol_Text, white);
|
|
ImGui::PushStyleColor(ImGuiCol_FrameBg, transparent);
|
|
ImGui::PushStyleColor(ImGuiCol_ScrollbarBg, transparent);
|
|
ImGui::PushStyleColor(ImGuiCol_ScrollbarGrab, transparent);
|
|
ImGui::PushStyleColor(ImGuiCol_ScrollbarGrabActive, transparent);
|
|
ImGui::PushStyleColor(ImGuiCol_ScrollbarGrabHovered, transparent);
|
|
ImGui::PushStyleColor(ImGuiCol_TextSelectedBg, white);
|
|
|
|
ImGui::SetCursorScreenPos({ float(x + 220), float(y + 30) });
|
|
std::stringstream ss_1;
|
|
ss_1 << std::fixed << std::setprecision(4) << get_manager().get_health_nums(0);
|
|
auto health_str = ss_1.str();
|
|
std::string text_name_1 = rsutils::string::from() << "##notification_text_1_" << index;
|
|
ImGui::InputTextMultiline(text_name_1.c_str(), const_cast<char*>(health_str.c_str()), strlen(health_str.c_str()) + 1, { 86, ImGui::GetTextLineHeight() + 6 }, ImGuiInputTextFlags_ReadOnly);
|
|
if (ImGui::IsItemHovered())
|
|
ImGui::SetTooltip("%s", "Health check for PX");
|
|
|
|
ImGui::SetCursorScreenPos({ float(x + 220), float(y + 35) + ImGui::GetTextLineHeightWithSpacing() });
|
|
std::stringstream ss_2;
|
|
ss_2 << std::fixed << std::setprecision(4) << get_manager().get_health_nums(1);
|
|
health_str = ss_2.str();
|
|
std::string text_name_2 = rsutils::string::from() << "##notification_text_2_" << index;
|
|
ImGui::InputTextMultiline(text_name_2.c_str(), const_cast<char*>(health_str.c_str()), strlen(health_str.c_str()) + 1, { 86, ImGui::GetTextLineHeight() + 6 }, ImGuiInputTextFlags_ReadOnly);
|
|
if (ImGui::IsItemHovered())
|
|
ImGui::SetTooltip("%s", "Health check for PY");
|
|
|
|
ImGui::SetCursorScreenPos({ float(x + 220), float(y + 40) + 2 * ImGui::GetTextLineHeightWithSpacing() });
|
|
std::stringstream ss_3;
|
|
ss_3 << std::fixed << std::setprecision(4) << get_manager().get_health_nums(2);
|
|
health_str = ss_3.str();
|
|
std::string text_name_3 = rsutils::string::from() << "##notification_text_3_" << index;
|
|
ImGui::InputTextMultiline(text_name_3.c_str(), const_cast<char*>(health_str.c_str()), strlen(health_str.c_str()) + 1, { 86, ImGui::GetTextLineHeight() + 6 }, ImGuiInputTextFlags_ReadOnly);
|
|
if (ImGui::IsItemHovered())
|
|
ImGui::SetTooltip("%s", "Health check for FX");
|
|
|
|
ImGui::SetCursorScreenPos({ float(x + 220), float(y + 45) + 3 * ImGui::GetTextLineHeightWithSpacing() });
|
|
std::stringstream ss_4;
|
|
ss_4 << std::fixed << std::setprecision(4) << get_manager().get_health_nums(3);
|
|
health_str = ss_4.str();
|
|
std::string text_name_4 = rsutils::string::from() << "##notification_text_4_" << index;
|
|
ImGui::InputTextMultiline(text_name_4.c_str(), const_cast<char*>(health_str.c_str()), strlen(health_str.c_str()) + 1, { 86, ImGui::GetTextLineHeight() + 6 }, ImGuiInputTextFlags_ReadOnly);
|
|
if (ImGui::IsItemHovered())
|
|
ImGui::SetTooltip("%s", "Health check for FY");
|
|
|
|
ImGui::PopStyleColor(7);
|
|
|
|
auto sat = 1.f + sin(duration_cast<milliseconds>(system_clock::now() - created_time).count() / 700.f) * 0.1f;
|
|
ImGui::PushStyleColor(ImGuiCol_Button, saturate(sensor_header_light_blue, sat));
|
|
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, saturate(sensor_header_light_blue, 1.5f));
|
|
ImGui::SetCursorScreenPos({ float(x + 9), float(y + height - 25) });
|
|
std::string button_name = rsutils::string::from() << "Apply" << "##apply" << index;
|
|
if (ImGui::Button(button_name.c_str(), { float(bar_width - 60), 20.f }))
|
|
{
|
|
get_manager().apply_calib(true); // Store the new calibration internally
|
|
get_manager().keep(); // Flash the new calibration
|
|
if (RS2_CALIB_STATE_UVMAPPING_INPUT == update_state)
|
|
get_manager().reset_device(); // Workaround for reloading color calibration table. Other approach?
|
|
|
|
update_state = RS2_CALIB_STATE_COMPLETE;
|
|
pinned = false;
|
|
enable_dismiss = false;
|
|
_progress_bar.last_progress_time = last_interacted = system_clock::now() + milliseconds(500);
|
|
|
|
get_manager().restore_workspace([](std::function<void()> a) { a(); });
|
|
}
|
|
|
|
ImGui::PopStyleColor(2);
|
|
if (ImGui::IsItemHovered())
|
|
ImGui::SetTooltip("%s", "New calibration values will be saved in device");
|
|
}
|
|
else
|
|
{
|
|
auto health = get_manager().get_health();
|
|
|
|
auto recommend_keep = fabs(health) < 0.25f;
|
|
if (get_manager().action == on_chip_calib_manager::RS2_CALIB_ACTION_ON_CHIP_FL_CALIB)
|
|
recommend_keep = fabs(health) < 0.15f;
|
|
|
|
float health_1 = -1.0f;
|
|
float health_2 = -1.0f;
|
|
bool recommend_keep_1 = false;
|
|
bool recommend_keep_2 = false;
|
|
if (get_manager().action == on_chip_calib_manager::RS2_CALIB_ACTION_ON_CHIP_OB_CALIB)
|
|
{
|
|
health_1 = get_manager().get_health_1();
|
|
health_2 = get_manager().get_health_2();
|
|
recommend_keep_1 = fabs(health_1) < 0.25f;
|
|
recommend_keep_2 = fabs(health_2) < 0.15f;
|
|
recommend_keep = (recommend_keep_1 && recommend_keep_2);
|
|
}
|
|
|
|
ImGui::SetCursorScreenPos({ float(x + 10), float(y + 33) });
|
|
|
|
if (get_manager().action == on_chip_calib_manager::RS2_CALIB_ACTION_TARE_CALIB)
|
|
{
|
|
if (get_manager().tare_health)
|
|
{
|
|
health_1 = get_manager().get_health_1();
|
|
health_2 = get_manager().get_health_2();
|
|
|
|
ImGui::Text("%s", "Health-Check Before Calibration: ");
|
|
|
|
std::stringstream ss_1;
|
|
ss_1 << std::fixed << std::setprecision(4) << health_1 << "%";
|
|
auto health_str = ss_1.str();
|
|
|
|
std::string text_name = rsutils::string::from() << "##notification_text_1_" << index;
|
|
|
|
ImGui::SetCursorScreenPos({ float(x + 225), float(y + 30) });
|
|
ImGui::PushStyleColor(ImGuiCol_Text, white);
|
|
ImGui::PushStyleColor(ImGuiCol_FrameBg, transparent);
|
|
ImGui::PushStyleColor(ImGuiCol_ScrollbarBg, transparent);
|
|
ImGui::PushStyleColor(ImGuiCol_ScrollbarGrab, transparent);
|
|
ImGui::PushStyleColor(ImGuiCol_ScrollbarGrabActive, transparent);
|
|
ImGui::PushStyleColor(ImGuiCol_ScrollbarGrabHovered, transparent);
|
|
ImGui::PushStyleColor(ImGuiCol_TextSelectedBg, white);
|
|
ImGui::InputTextMultiline(text_name.c_str(), const_cast<char*>(health_str.c_str()), strlen(health_str.c_str()) + 1, { 86, ImGui::GetTextLineHeight() + 6 }, ImGuiInputTextFlags_ReadOnly);
|
|
ImGui::PopStyleColor(7);
|
|
|
|
if (ImGui::IsItemHovered())
|
|
ImGui::SetTooltip("%s", "Health-check number before Tare Calibration");
|
|
|
|
ImGui::SetCursorScreenPos({ float(x + 10), float(y + 38) + ImGui::GetTextLineHeightWithSpacing() });
|
|
ImGui::Text("%s", "Health-Check After Calibration: ");
|
|
|
|
std::stringstream ss_2;
|
|
ss_2 << std::fixed << std::setprecision(4) << health_2 << "%";
|
|
health_str = ss_2.str();
|
|
|
|
text_name = rsutils::string::from() << "##notification_text_2_" << index;
|
|
|
|
ImGui::SetCursorScreenPos({ float(x + 225), float(y + 35) + ImGui::GetTextLineHeightWithSpacing() });
|
|
ImGui::PushStyleColor(ImGuiCol_Text, white);
|
|
ImGui::PushStyleColor(ImGuiCol_FrameBg, transparent);
|
|
ImGui::PushStyleColor(ImGuiCol_ScrollbarBg, transparent);
|
|
ImGui::PushStyleColor(ImGuiCol_ScrollbarGrab, transparent);
|
|
ImGui::PushStyleColor(ImGuiCol_ScrollbarGrabActive, transparent);
|
|
ImGui::PushStyleColor(ImGuiCol_ScrollbarGrabHovered, transparent);
|
|
ImGui::PushStyleColor(ImGuiCol_TextSelectedBg, white);
|
|
ImGui::InputTextMultiline(text_name.c_str(), const_cast<char*>(health_str.c_str()), strlen(health_str.c_str()) + 1, { 86, ImGui::GetTextLineHeight() + 6 }, ImGuiInputTextFlags_ReadOnly);
|
|
ImGui::PopStyleColor(7);
|
|
|
|
if (ImGui::IsItemHovered())
|
|
ImGui::SetTooltip("%s", "Health-check number after Tare Calibration");
|
|
}
|
|
}
|
|
else if (get_manager().action == on_chip_calib_manager::RS2_CALIB_ACTION_ON_CHIP_OB_CALIB)
|
|
{
|
|
ImGui::Text("%s", "Health-Check: ");
|
|
|
|
std::stringstream ss_1;
|
|
ss_1 << std::fixed << std::setprecision(2) << health_1;
|
|
auto health_str = ss_1.str();
|
|
|
|
std::string text_name = rsutils::string::from() << "##notification_text_1_" << index;
|
|
|
|
ImGui::SetCursorScreenPos({ float(x + 125), float(y + 30) });
|
|
ImGui::PushStyleColor(ImGuiCol_Text, white);
|
|
ImGui::PushStyleColor(ImGuiCol_FrameBg, transparent);
|
|
ImGui::PushStyleColor(ImGuiCol_ScrollbarBg, transparent);
|
|
ImGui::PushStyleColor(ImGuiCol_ScrollbarGrab, transparent);
|
|
ImGui::PushStyleColor(ImGuiCol_ScrollbarGrabActive, transparent);
|
|
ImGui::PushStyleColor(ImGuiCol_ScrollbarGrabHovered, transparent);
|
|
ImGui::PushStyleColor(ImGuiCol_TextSelectedBg, white);
|
|
ImGui::InputTextMultiline(text_name.c_str(), const_cast<char*>(health_str.c_str()), strlen(health_str.c_str()) + 1, { 66, ImGui::GetTextLineHeight() + 6 }, ImGuiInputTextFlags_ReadOnly);
|
|
ImGui::PopStyleColor(7);
|
|
|
|
ImGui::SetCursorScreenPos({ float(x + 177), float(y + 33) });
|
|
|
|
if (recommend_keep_1)
|
|
{
|
|
ImGui::PushStyleColor(ImGuiCol_Text, light_blue);
|
|
ImGui::Text("%s", "(Good)");
|
|
}
|
|
else if (fabs(health_1) < 0.75f)
|
|
{
|
|
ImGui::PushStyleColor(ImGuiCol_Text, yellowish);
|
|
ImGui::Text("%s", "(Can be Improved)");
|
|
}
|
|
else
|
|
{
|
|
ImGui::PushStyleColor(ImGuiCol_Text, redish);
|
|
ImGui::Text("%s", "(Requires Calibration)");
|
|
}
|
|
ImGui::PopStyleColor();
|
|
|
|
if (ImGui::IsItemHovered())
|
|
{
|
|
ImGui::SetTooltip("%s", "OCC Health-Check captures how far camera calibration is from the optimal one\n"
|
|
"[0, 0.25) - Good\n"
|
|
"[0.25, 0.75) - Can be Improved\n"
|
|
"[0.75, ) - Requires Calibration");
|
|
}
|
|
|
|
ImGui::SetCursorScreenPos({ float(x + 10), float(y + 38) + ImGui::GetTextLineHeightWithSpacing() });
|
|
ImGui::Text("%s", "FL Health-Check: ");
|
|
|
|
std::stringstream ss_2;
|
|
ss_2 << std::fixed << std::setprecision(2) << health_2;
|
|
health_str = ss_2.str();
|
|
|
|
text_name = rsutils::string::from() << "##notification_text_2_" << index;
|
|
|
|
ImGui::SetCursorScreenPos({ float(x + 125), float(y + 35) + ImGui::GetTextLineHeightWithSpacing() });
|
|
ImGui::PushStyleColor(ImGuiCol_Text, white);
|
|
ImGui::PushStyleColor(ImGuiCol_FrameBg, transparent);
|
|
ImGui::PushStyleColor(ImGuiCol_ScrollbarBg, transparent);
|
|
ImGui::PushStyleColor(ImGuiCol_ScrollbarGrab, transparent);
|
|
ImGui::PushStyleColor(ImGuiCol_ScrollbarGrabActive, transparent);
|
|
ImGui::PushStyleColor(ImGuiCol_ScrollbarGrabHovered, transparent);
|
|
ImGui::PushStyleColor(ImGuiCol_TextSelectedBg, white);
|
|
ImGui::InputTextMultiline(text_name.c_str(), const_cast<char*>(health_str.c_str()), strlen(health_str.c_str()) + 1, { 66, ImGui::GetTextLineHeight() + 6 }, ImGuiInputTextFlags_ReadOnly);
|
|
ImGui::PopStyleColor(7);
|
|
|
|
ImGui::SetCursorScreenPos({ float(x + 175), float(y + 38) + ImGui::GetTextLineHeightWithSpacing() });
|
|
|
|
if (recommend_keep_2)
|
|
{
|
|
ImGui::PushStyleColor(ImGuiCol_Text, light_blue);
|
|
ImGui::Text("%s", "(Good)");
|
|
}
|
|
else if (fabs(health_2) < 0.75f)
|
|
{
|
|
ImGui::PushStyleColor(ImGuiCol_Text, yellowish);
|
|
ImGui::Text("%s", "(Can be Improved)");
|
|
}
|
|
else
|
|
{
|
|
ImGui::PushStyleColor(ImGuiCol_Text, redish);
|
|
ImGui::Text("%s", "(Requires Calibration)");
|
|
}
|
|
ImGui::PopStyleColor();
|
|
|
|
if (ImGui::IsItemHovered())
|
|
{
|
|
ImGui::SetTooltip("%s", "OCC-FL Health-Check captures how far camera calibration is from the optimal one\n"
|
|
"[0, 0.15) - Good\n"
|
|
"[0.15, 0.75) - Can be Improved\n"
|
|
"[0.75, ) - Requires Calibration");
|
|
}
|
|
}
|
|
else if (get_manager().action == on_chip_calib_manager::RS2_CALIB_ACTION_FL_CALIB)
|
|
{
|
|
ImGui::Text("%s", "Focal Length Imbalance: ");
|
|
|
|
std::stringstream ss_1;
|
|
ss_1 << std::fixed << std::setprecision(3) << get_manager().corrected_ratio;
|
|
auto ratio_str = ss_1.str();
|
|
ratio_str += " %";
|
|
|
|
std::string text_name = rsutils::string::from() << "##notification_text_1_" << index;
|
|
|
|
ImGui::SetCursorScreenPos({ float(x + 175), float(y + 30) });
|
|
ImGui::PushStyleColor(ImGuiCol_Text, white);
|
|
ImGui::PushStyleColor(ImGuiCol_FrameBg, transparent);
|
|
ImGui::PushStyleColor(ImGuiCol_ScrollbarBg, transparent);
|
|
ImGui::PushStyleColor(ImGuiCol_ScrollbarGrab, transparent);
|
|
ImGui::PushStyleColor(ImGuiCol_ScrollbarGrabActive, transparent);
|
|
ImGui::PushStyleColor(ImGuiCol_ScrollbarGrabHovered, transparent);
|
|
ImGui::PushStyleColor(ImGuiCol_TextSelectedBg, white);
|
|
ImGui::InputTextMultiline(text_name.c_str(), const_cast<char*>(ratio_str.c_str()), strlen(ratio_str.c_str()) + 1, { 86, ImGui::GetTextLineHeight() + 6 }, ImGuiInputTextFlags_ReadOnly);
|
|
ImGui::PopStyleColor(7);
|
|
|
|
ImGui::SetCursorScreenPos({ float(x + 10), float(y + 38) + ImGui::GetTextLineHeightWithSpacing() });
|
|
ImGui::Text("%s", "Estimated Tilt Angle: ");
|
|
|
|
std::stringstream ss_2;
|
|
ss_2 << std::fixed << std::setprecision(3) << get_manager().tilt_angle;
|
|
auto align_str = ss_2.str();
|
|
align_str += " deg";
|
|
|
|
text_name = rsutils::string::from() << "##notification_text_2_" << index;
|
|
|
|
ImGui::SetCursorScreenPos({ float(x + 175), float(y + 35) + ImGui::GetTextLineHeightWithSpacing() });
|
|
ImGui::PushStyleColor(ImGuiCol_Text, white);
|
|
ImGui::PushStyleColor(ImGuiCol_FrameBg, transparent);
|
|
ImGui::PushStyleColor(ImGuiCol_ScrollbarBg, transparent);
|
|
ImGui::PushStyleColor(ImGuiCol_ScrollbarGrab, transparent);
|
|
ImGui::PushStyleColor(ImGuiCol_ScrollbarGrabActive, transparent);
|
|
ImGui::PushStyleColor(ImGuiCol_ScrollbarGrabHovered, transparent);
|
|
ImGui::PushStyleColor(ImGuiCol_TextSelectedBg, white);
|
|
ImGui::InputTextMultiline(text_name.c_str(), const_cast<char*>(align_str.c_str()), strlen(align_str.c_str()) + 1, { 86, ImGui::GetTextLineHeight() + 6 }, ImGuiInputTextFlags_ReadOnly);
|
|
ImGui::PopStyleColor(7);
|
|
}
|
|
else if (get_manager().action != on_chip_calib_manager::RS2_CALIB_ACTION_TARE_CALIB)
|
|
{
|
|
ImGui::Text("%s", (get_manager().action == on_chip_calib_manager::RS2_CALIB_ACTION_ON_CHIP_CALIB ? "Health-Check: " : "FL Health-Check: "));
|
|
|
|
std::stringstream ss; ss << std::fixed << std::setprecision(2) << health;
|
|
auto health_str = ss.str();
|
|
|
|
std::string text_name = rsutils::string::from() << "##notification_text_" << index;
|
|
|
|
ImGui::SetCursorScreenPos({ float(x + 125), float(y + 30) });
|
|
ImGui::PushStyleColor(ImGuiCol_Text, white);
|
|
ImGui::PushStyleColor(ImGuiCol_FrameBg, transparent);
|
|
ImGui::PushStyleColor(ImGuiCol_ScrollbarBg, transparent);
|
|
ImGui::PushStyleColor(ImGuiCol_ScrollbarGrab, transparent);
|
|
ImGui::PushStyleColor(ImGuiCol_ScrollbarGrabActive, transparent);
|
|
ImGui::PushStyleColor(ImGuiCol_ScrollbarGrabHovered, transparent);
|
|
ImGui::PushStyleColor(ImGuiCol_TextSelectedBg, white);
|
|
ImGui::InputTextMultiline(text_name.c_str(), const_cast<char*>(health_str.c_str()), strlen(health_str.c_str()) + 1, { 66, ImGui::GetTextLineHeight() + 6 }, ImGuiInputTextFlags_ReadOnly);
|
|
ImGui::PopStyleColor(7);
|
|
|
|
ImGui::SetCursorScreenPos({ float(x + 177), float(y + 33) });
|
|
|
|
if (recommend_keep)
|
|
{
|
|
ImGui::PushStyleColor(ImGuiCol_Text, light_blue);
|
|
ImGui::Text("%s", "(Good)");
|
|
}
|
|
else if (fabs(health) < 0.75f)
|
|
{
|
|
ImGui::PushStyleColor(ImGuiCol_Text, yellowish);
|
|
ImGui::Text("%s", "(Can be Improved)");
|
|
}
|
|
else
|
|
{
|
|
ImGui::PushStyleColor(ImGuiCol_Text, redish);
|
|
ImGui::Text("%s", "(Requires Calibration)");
|
|
}
|
|
ImGui::PopStyleColor();
|
|
|
|
if (ImGui::IsItemHovered())
|
|
{
|
|
if (get_manager().action == on_chip_calib_manager::RS2_CALIB_ACTION_ON_CHIP_CALIB)
|
|
{
|
|
ImGui::SetTooltip("%s", "Calibration Health-Check captures how far camera calibration is from the optimal one\n"
|
|
"[0, 0.25) - Good\n"
|
|
"[0.25, 0.75) - Can be Improved\n"
|
|
"[0.75, ) - Requires Calibration");
|
|
}
|
|
else
|
|
{
|
|
ImGui::SetTooltip("%s", "Calibration Health-Check captures how far camera calibration is from the optimal one\n"
|
|
"[0, 0.15) - Good\n"
|
|
"[0.15, 0.75) - Can be Improved\n"
|
|
"[0.75, ) - Requires Calibration");
|
|
}
|
|
}
|
|
}
|
|
|
|
auto old_fr = get_manager().get_metric(false).first;
|
|
auto new_fr = get_manager().get_metric(true).first;
|
|
|
|
auto old_rms = fabs(get_manager().get_metric(false).second);
|
|
auto new_rms = fabs(get_manager().get_metric(true).second);
|
|
|
|
auto fr_improvement = 100.f * ((new_fr - old_fr) / old_fr);
|
|
auto rms_improvement = 100.f * ((old_rms - new_rms) / old_rms);
|
|
|
|
std::string old_units = "mm";
|
|
if (old_rms > 10.f)
|
|
{
|
|
old_rms /= 10.f;
|
|
old_units = "cm";
|
|
}
|
|
|
|
std::string new_units = "mm";
|
|
if (new_rms > 10.f)
|
|
{
|
|
new_rms /= 10.f;
|
|
new_units = "cm";
|
|
}
|
|
|
|
// NOTE: Disabling metrics temporarily
|
|
// TODO: Re-enable in future release
|
|
if (/* fr_improvement > 1.f || rms_improvement > 1.f */ false)
|
|
{
|
|
std::string txt = rsutils::string::from() << " Fill-Rate: " << std::setprecision(1) << std::fixed << new_fr << "%%";
|
|
if (!use_new_calib)
|
|
txt = rsutils::string::from() << " Fill-Rate: " << std::setprecision(1) << std::fixed << old_fr << "%%\n";
|
|
|
|
ImGui::SetCursorScreenPos({ float(x + 12), float(y + 90) });
|
|
ImGui::PushFont(win.get_large_font());
|
|
ImGui::Text("%s", static_cast<const char*>(textual_icons::check));
|
|
ImGui::PopFont();
|
|
|
|
ImGui::SetCursorScreenPos({ float(x + 35), float(y + 92) });
|
|
ImGui::Text("%s", txt.c_str());
|
|
|
|
if (use_new_calib)
|
|
{
|
|
ImGui::SameLine();
|
|
|
|
ImGui::PushStyleColor(ImGuiCol_Text, white);
|
|
txt = rsutils::string::from() << " ( +" << std::fixed << std::setprecision(0) << fr_improvement << "%% )";
|
|
ImGui::Text("%s", txt.c_str());
|
|
ImGui::PopStyleColor();
|
|
}
|
|
|
|
if (rms_improvement > 1.f)
|
|
{
|
|
if (use_new_calib)
|
|
{
|
|
txt = rsutils::string::from() << " Noise Estimate: " << std::setprecision(2) << std::fixed << new_rms << new_units;
|
|
}
|
|
else
|
|
{
|
|
txt = rsutils::string::from() << " Noise Estimate: " << std::setprecision(2) << std::fixed << old_rms << old_units;
|
|
}
|
|
|
|
ImGui::SetCursorScreenPos({ float(x + 12), float(y + 90 + ImGui::GetTextLineHeight() + 6) });
|
|
ImGui::PushFont(win.get_large_font());
|
|
ImGui::Text("%s", static_cast<const char*>(textual_icons::check));
|
|
ImGui::PopFont();
|
|
|
|
ImGui::SetCursorScreenPos({ float(x + 35), float(y + 92 + ImGui::GetTextLineHeight() + 6) });
|
|
ImGui::Text("%s", txt.c_str());
|
|
|
|
if (use_new_calib)
|
|
{
|
|
ImGui::SameLine();
|
|
|
|
ImGui::PushStyleColor(ImGuiCol_Text, white);
|
|
txt = rsutils::string::from() << " ( -" << std::setprecision(0) << std::fixed << rms_improvement << "%% )";
|
|
ImGui::Text("%s", txt.c_str());
|
|
ImGui::PopStyleColor();
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ImGui::SetCursorScreenPos({ float(x + 7), (get_manager().action == on_chip_calib_manager::RS2_CALIB_ACTION_ON_CHIP_OB_CALIB || get_manager().action == on_chip_calib_manager::RS2_CALIB_ACTION_FL_CALIB ? float(y + 105) + ImGui::GetTextLineHeightWithSpacing() : (get_manager().action == on_chip_calib_manager::RS2_CALIB_ACTION_TARE_CALIB ? (get_manager().tare_health ? float(y + 105) : float(y + 50)) + ImGui::GetTextLineHeightWithSpacing() : float(y + 105))) });
|
|
ImGui::Text("%s", "Please compare new vs old calibration\nand decide if to keep or discard the result...");
|
|
}
|
|
|
|
ImGui::SetCursorScreenPos({ float(x + 20), (get_manager().action == on_chip_calib_manager::RS2_CALIB_ACTION_ON_CHIP_OB_CALIB || get_manager().action == on_chip_calib_manager::RS2_CALIB_ACTION_FL_CALIB ? float(y + 70) + ImGui::GetTextLineHeightWithSpacing() : (get_manager().action == on_chip_calib_manager::RS2_CALIB_ACTION_TARE_CALIB ? (get_manager().tare_health ? float(y + 70) : float(y + 15)) + ImGui::GetTextLineHeightWithSpacing() : float(y + 70))) });
|
|
|
|
if (ImGui::RadioButton("New", use_new_calib))
|
|
{
|
|
use_new_calib = true;
|
|
get_manager().apply_calib(true);
|
|
}
|
|
|
|
ImGui::SetCursorScreenPos({ float(x + 150), (get_manager().action == on_chip_calib_manager::RS2_CALIB_ACTION_ON_CHIP_OB_CALIB || get_manager().action == on_chip_calib_manager::RS2_CALIB_ACTION_FL_CALIB ? float(y + 70) + ImGui::GetTextLineHeightWithSpacing() : (get_manager().action == on_chip_calib_manager::RS2_CALIB_ACTION_TARE_CALIB ? (get_manager().tare_health ? float(y + 70) : float(y + 15)) + ImGui::GetTextLineHeightWithSpacing() : float(y + 70))) });
|
|
if (ImGui::RadioButton("Original", !use_new_calib))
|
|
{
|
|
use_new_calib = false;
|
|
get_manager().apply_calib(false);
|
|
}
|
|
|
|
auto sat = 1.f + sin(duration_cast<milliseconds>(system_clock::now() - created_time).count() / 700.f) * 0.1f;
|
|
|
|
if (!recommend_keep || get_manager().action == on_chip_calib_manager::RS2_CALIB_ACTION_TARE_CALIB)
|
|
{
|
|
ImGui::PushStyleColor(ImGuiCol_Button, saturate(sensor_header_light_blue, sat));
|
|
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, saturate(sensor_header_light_blue, 1.5f));
|
|
}
|
|
|
|
float scale = float(bar_width) / 3;
|
|
std::string button_name;
|
|
|
|
if (get_manager().action == on_chip_calib_manager::RS2_CALIB_ACTION_FL_CALIB)
|
|
{
|
|
scale = float(bar_width) / 7;
|
|
|
|
button_name = rsutils::string::from() << "Recalibrate" << "##refl" << index;
|
|
|
|
ImGui::SetCursorScreenPos({ float(x + 5), float(y + height - 25) });
|
|
if (ImGui::Button(button_name.c_str(), { scale * 3, 20.f }))
|
|
{
|
|
get_manager().restore_workspace([this](std::function<void()> a) { a(); });
|
|
get_manager().reset();
|
|
get_manager().retry_times = 0;
|
|
get_manager().action = on_chip_calib_manager::RS2_CALIB_ACTION_FL_CALIB;
|
|
auto _this = shared_from_this();
|
|
auto invoke = [_this](std::function<void()> action) {
|
|
_this->invoke(action);
|
|
};
|
|
get_manager().start(invoke);
|
|
update_state = RS2_CALIB_STATE_CALIB_IN_PROCESS;
|
|
enable_dismiss = false;
|
|
}
|
|
|
|
ImGui::SetCursorScreenPos({ float(x + 5) + 4 * scale, float(y + height - 25) });
|
|
}
|
|
else
|
|
ImGui::SetCursorScreenPos({ float(x + 5), float(y + height - 25) });
|
|
|
|
button_name = rsutils::string::from() << "Apply New" << "##apply" << index;
|
|
if (!use_new_calib) button_name = rsutils::string::from() << "Keep Original" << "##original" << index;
|
|
|
|
if (ImGui::Button(button_name.c_str(), { scale * 3, 20.f }))
|
|
{
|
|
if (use_new_calib)
|
|
{
|
|
get_manager().keep();
|
|
update_state = RS2_CALIB_STATE_COMPLETE;
|
|
pinned = false;
|
|
enable_dismiss = false;
|
|
_progress_bar.last_progress_time = last_interacted = system_clock::now() + milliseconds(500);
|
|
}
|
|
else
|
|
{
|
|
dismiss(false);
|
|
}
|
|
|
|
get_manager().restore_options_controlled_by_calib();
|
|
get_manager().restore_workspace([](std::function<void()> a) { a(); });
|
|
}
|
|
|
|
if (!recommend_keep || get_manager().action == on_chip_calib_manager::RS2_CALIB_ACTION_TARE_CALIB)
|
|
ImGui::PopStyleColor(2);
|
|
|
|
if (ImGui::IsItemHovered())
|
|
ImGui::SetTooltip("%s", "New calibration values will be saved in device");
|
|
}
|
|
}
|
|
|
|
ImGui::PopStyleColor();
|
|
}
|
|
else
|
|
{
|
|
ImGui::Text("%s", "Calibration Complete");
|
|
|
|
ImGui::SetCursorScreenPos({ float(x + 10), float(y + 35) });
|
|
ImGui::PushFont(win.get_large_font());
|
|
std::string txt = rsutils::string::from() << textual_icons::throphy;
|
|
ImGui::Text("%s", txt.c_str());
|
|
ImGui::PopFont();
|
|
|
|
ImGui::SetCursorScreenPos({ float(x + 40), float(y + 35) });
|
|
|
|
ImGui::Text("%s", "Camera Calibration Applied Successfully");
|
|
}
|
|
|
|
ImGui::SetCursorScreenPos({ float(x + 5), float(y + height - 25) });
|
|
|
|
if (update_manager)
|
|
{
|
|
if (update_state == RS2_CALIB_STATE_INITIAL_PROMPT)
|
|
{
|
|
auto sat = 1.f + sin(duration_cast<milliseconds>(system_clock::now() - created_time).count() / 700.f) * 0.1f;
|
|
ImGui::PushStyleColor(ImGuiCol_Button, saturate(sensor_header_light_blue, sat));
|
|
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, saturate(sensor_header_light_blue, 1.5f));
|
|
std::string button_name = rsutils::string::from() << "Health-Check" << "##health_check" << index;
|
|
|
|
if (ImGui::Button(button_name.c_str(), { float(bar_width), 20.f }) || update_manager->started())
|
|
{
|
|
auto _this = shared_from_this();
|
|
auto invoke = [_this](std::function<void()> action) {
|
|
_this->invoke(action);
|
|
};
|
|
|
|
if (!update_manager->started()) update_manager->start(invoke);
|
|
|
|
update_state = RS2_CALIB_STATE_CALIB_IN_PROCESS;
|
|
enable_dismiss = false;
|
|
_progress_bar.last_progress_time = system_clock::now();
|
|
}
|
|
ImGui::PopStyleColor(2);
|
|
|
|
if (ImGui::IsItemHovered())
|
|
{
|
|
ImGui::SetTooltip("%s", "Keep the camera pointing at an object or a wall");
|
|
}
|
|
}
|
|
else if (update_state == RS2_CALIB_STATE_GET_TARE_GROUND_TRUTH_IN_PROCESS)
|
|
{
|
|
if (update_manager->done())
|
|
{
|
|
update_state = RS2_CALIB_STATE_GET_TARE_GROUND_TRUTH_COMPLETE;
|
|
enable_dismiss = true;
|
|
}
|
|
|
|
if (update_manager->failed())
|
|
{
|
|
update_manager->check_error(_error_message);
|
|
update_state = RS2_CALIB_STATE_GET_TARE_GROUND_TRUTH_FAILED;
|
|
enable_dismiss = true;
|
|
}
|
|
|
|
draw_progress_bar(win, bar_width);
|
|
}
|
|
else if (update_state == RS2_CALIB_STATE_CALIB_IN_PROCESS)
|
|
{
|
|
if (update_manager->done())
|
|
{
|
|
update_state = RS2_CALIB_STATE_CALIB_COMPLETE;
|
|
enable_dismiss = true;
|
|
if (get_manager().action != on_chip_calib_manager::RS2_CALIB_ACTION_UVMAPPING_CALIB)
|
|
{
|
|
get_manager().apply_calib(true);
|
|
use_new_calib = true;
|
|
}
|
|
}
|
|
|
|
if (!expanded)
|
|
{
|
|
if (update_manager->failed())
|
|
{
|
|
update_manager->check_error(_error_message);
|
|
update_state = RS2_CALIB_STATE_FAILED;
|
|
enable_dismiss = true;
|
|
}
|
|
|
|
draw_progress_bar(win, bar_width);
|
|
|
|
string id = rsutils::string::from() << "Expand" << "##" << index;
|
|
ImGui::SetCursorScreenPos({ float(x + width - 105), float(y + height - 25) });
|
|
ImGui::PushStyleColor(ImGuiCol_Text, light_grey);
|
|
if (ImGui::Button(id.c_str(), { 100, 20 }))
|
|
expanded = true;
|
|
ImGui::PopStyleColor();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void autocalib_notification_model::dismiss(bool snooze)
|
|
{
|
|
get_manager().update_last_used();
|
|
|
|
if (!use_new_calib && get_manager().done())
|
|
get_manager().apply_calib(false);
|
|
|
|
get_manager().restore_options_controlled_by_calib();
|
|
get_manager().restore_workspace( []( std::function< void() > a ) { a(); } );
|
|
|
|
if (update_state != RS2_CALIB_STATE_TARE_INPUT)
|
|
update_state = RS2_CALIB_STATE_INITIAL_PROMPT;
|
|
|
|
get_manager().turn_roi_off();
|
|
get_manager().reset();
|
|
|
|
notification_model::dismiss(snooze);
|
|
}
|
|
|
|
void autocalib_notification_model::draw_expanded(ux_window& win, std::string& error_message)
|
|
{
|
|
if (update_manager->started() && update_state == RS2_CALIB_STATE_INITIAL_PROMPT)
|
|
update_state = RS2_CALIB_STATE_CALIB_IN_PROCESS;
|
|
|
|
auto flags = ImGuiWindowFlags_NoResize |
|
|
ImGuiWindowFlags_NoMove |
|
|
ImGuiWindowFlags_NoCollapse;
|
|
|
|
ImGui::PushStyleColor(ImGuiCol_WindowBg, { 0, 0, 0, 0 });
|
|
ImGui::PushStyleColor(ImGuiCol_Text, light_grey);
|
|
ImGui::PushStyleColor(ImGuiCol_TextSelectedBg, white);
|
|
ImGui::PushStyleColor(ImGuiCol_PopupBg, sensor_bg);
|
|
|
|
ImGui::PushStyleVar(ImGuiStyleVar_WindowMinSize, ImVec2(500, 100));
|
|
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(5, 5));
|
|
ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 0);
|
|
|
|
std::string title;
|
|
switch (get_manager().action)
|
|
{
|
|
case on_chip_calib_manager::RS2_CALIB_ACTION_ON_CHIP_OB_CALIB: title = "On - Chip Calibration Extended"; break;
|
|
case on_chip_calib_manager::RS2_CALIB_ACTION_ON_CHIP_CALIB: title = "On-Chip Calibration"; break;
|
|
case on_chip_calib_manager::RS2_CALIB_ACTION_ON_CHIP_FL_CALIB: title = "On-Chip Focal Length Calibration"; break;
|
|
case on_chip_calib_manager::RS2_CALIB_ACTION_TARE_CALIB: title = "Tare Calibration"; break;
|
|
case on_chip_calib_manager::RS2_CALIB_ACTION_TARE_GROUND_TRUTH: title = "Ground Truth Calculation"; break;
|
|
case on_chip_calib_manager::RS2_CALIB_ACTION_FL_CALIB: title = "Focal Length Calibration"; break;
|
|
case on_chip_calib_manager::RS2_CALIB_ACTION_UVMAPPING_CALIB: title = "UV - Mapping Calibration"; break;
|
|
default: title = "Calibration";
|
|
}
|
|
|
|
if (update_manager->failed()) title += " Failed";
|
|
|
|
ImGui::OpenPopup(title.c_str());
|
|
if (ImGui::BeginPopupModal(title.c_str(), nullptr, flags))
|
|
{
|
|
ImGui::SetCursorPosX(200);
|
|
std::string progress_str = rsutils::string::from() << "Progress: " << update_manager->get_progress() << "%";
|
|
ImGui::Text("%s", progress_str.c_str());
|
|
|
|
ImGui::SetCursorPosX(5);
|
|
|
|
draw_progress_bar(win, 490);
|
|
|
|
ImGui::PushStyleColor(ImGuiCol_TextSelectedBg, regular_blue);
|
|
auto s = update_manager->get_log();
|
|
ImGui::InputTextMultiline("##autocalib_log", const_cast<char*>(s.c_str()),
|
|
s.size() + 1, { 490,100 }, ImGuiInputTextFlags_AutoSelectAll | ImGuiInputTextFlags_ReadOnly);
|
|
ImGui::PopStyleColor();
|
|
|
|
ImGui::SetCursorPosX(190);
|
|
if (visible || update_manager->done() || update_manager->failed())
|
|
{
|
|
if (ImGui::Button("OK", ImVec2(120, 0)))
|
|
{
|
|
if (update_manager->failed())
|
|
update_state = RS2_CALIB_STATE_FAILED;
|
|
|
|
expanded = false;
|
|
ImGui::CloseCurrentPopup();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ImGui::PushStyleColor(ImGuiCol_Button, transparent);
|
|
ImGui::PushStyleColor(ImGuiCol_ButtonActive, transparent);
|
|
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, transparent);
|
|
ImGui::PushStyleColor(ImGuiCol_Text, transparent);
|
|
ImGui::PushStyleColor(ImGuiCol_TextSelectedBg, transparent);
|
|
ImGui::Button("OK", ImVec2(120, 0));
|
|
ImGui::PopStyleColor(5);
|
|
}
|
|
|
|
ImGui::EndPopup();
|
|
}
|
|
|
|
ImGui::PopStyleVar(3);
|
|
ImGui::PopStyleColor(4);
|
|
|
|
error_message = "";
|
|
}
|
|
|
|
int autocalib_notification_model::calc_height()
|
|
{
|
|
if (update_state == RS2_CALIB_STATE_COMPLETE) return 65;
|
|
else if (update_state == RS2_CALIB_STATE_INITIAL_PROMPT) return 120;
|
|
else if (update_state == RS2_CALIB_STATE_CALIB_COMPLETE)
|
|
{
|
|
if (get_manager().allow_calib_keep())
|
|
{
|
|
if (get_manager().action == on_chip_calib_manager::RS2_CALIB_ACTION_ON_CHIP_OB_CALIB || get_manager().action == on_chip_calib_manager::RS2_CALIB_ACTION_FL_CALIB) return 190;
|
|
else if (get_manager().action == on_chip_calib_manager::RS2_CALIB_ACTION_TARE_CALIB) return 140;
|
|
else if (get_manager().action == on_chip_calib_manager::RS2_CALIB_ACTION_UVMAPPING_CALIB) return 160;
|
|
else return 170;
|
|
}
|
|
else return 80;
|
|
}
|
|
else if (update_state == RS2_CALIB_STATE_SELF_INPUT) return (get_manager().action == on_chip_calib_manager::RS2_CALIB_ACTION_ON_CHIP_OB_CALIB ? 180 : 90);
|
|
else if (update_state == RS2_CALIB_STATE_TARE_INPUT) return 105;
|
|
else if (update_state == RS2_CALIB_STATE_TARE_INPUT_ADVANCED) return 230;
|
|
else if (update_state == RS2_CALIB_STATE_GET_TARE_GROUND_TRUTH) return 135;
|
|
else if (update_state == RS2_CALIB_STATE_GET_TARE_GROUND_TRUTH_FAILED) return 115;
|
|
else if (update_state == RS2_CALIB_STATE_FAILED) return ((get_manager().action == on_chip_calib_manager::RS2_CALIB_ACTION_ON_CHIP_OB_CALIB || get_manager().action == on_chip_calib_manager::RS2_CALIB_ACTION_ON_CHIP_FL_CALIB) ? (get_manager().retry_times < 3 ? 0 : 80) : 110);
|
|
else if (update_state == RS2_CALIB_STATE_FL_INPUT) return 200;
|
|
else if (update_state == RS2_CALIB_STATE_UVMAPPING_INPUT) return 140;
|
|
else return 100;
|
|
}
|
|
|
|
void autocalib_notification_model::set_color_scheme(float t) const
|
|
{
|
|
notification_model::set_color_scheme(t);
|
|
|
|
ImGui::PopStyleColor(1);
|
|
|
|
ImVec4 c;
|
|
|
|
if (update_state == RS2_CALIB_STATE_COMPLETE)
|
|
{
|
|
c = alpha(saturate(light_blue, 0.7f), 1 - t);
|
|
ImGui::PushStyleColor(ImGuiCol_WindowBg, c);
|
|
}
|
|
else if (update_state == RS2_CALIB_STATE_FAILED)
|
|
{
|
|
c = alpha(dark_red, 1 - t);
|
|
ImGui::PushStyleColor(ImGuiCol_WindowBg, c);
|
|
}
|
|
else
|
|
{
|
|
c = alpha(sensor_bg, 1 - t);
|
|
ImGui::PushStyleColor(ImGuiCol_WindowBg, c);
|
|
}
|
|
}
|
|
|
|
autocalib_notification_model::autocalib_notification_model(std::string name, std::shared_ptr<on_chip_calib_manager> manager, bool exp)
|
|
: process_notification_model(manager)
|
|
{
|
|
enable_expand = false;
|
|
enable_dismiss = true;
|
|
expanded = exp;
|
|
if (expanded) visible = false;
|
|
|
|
message = name;
|
|
this->severity = RS2_LOG_SEVERITY_INFO;
|
|
this->category = RS2_NOTIFICATION_CATEGORY_HARDWARE_EVENT;
|
|
|
|
pinned = true;
|
|
}
|
|
}
|