Files
hivecore_robot_drivers/librealsense-r-256/common/d500-on-chip-calib.cpp
2026-01-06 18:45:34 +08:00

346 lines
12 KiB
C++

// License: Apache 2.0. See LICENSE file in root directory.
// Copyright(c) 2024 Intel Corporation. All Rights Reserved.
#include <viewer.h>
#include "d500-on-chip-calib.h"
namespace rs2
{
d500_on_chip_calib_manager::d500_on_chip_calib_manager(viewer_model& viewer, std::shared_ptr<subdevice_model> sub,
device_model& model, device dev)
: process_manager("D500 On-Chip Calibration"),
_model(model),
_dev(dev),
_sub(sub)
{
if (dev.supports(RS2_CAMERA_INFO_PRODUCT_LINE) &&
std::string(dev.get_info(RS2_CAMERA_INFO_PRODUCT_LINE)) != "D500")
{
throw std::runtime_error("This Calibration Process cannot be processed with this device");
}
}
std::string d500_on_chip_calib_manager::convert_action_to_json_string()
{
std::stringstream ss;
if (action == RS2_CALIB_ACTION_ON_CHIP_CALIB)
{
ss << "{\n calib run }";
}
else if (action == RS2_CALIB_ACTION_ON_CHIP_CALIB_DRY_RUN)
{
ss << "{\n calib dry run }";
}
else if (action == RS2_CALIB_ACTION_ON_CHIP_CALIB_ABORT)
{
ss << "{\n calib abort }";
}
return ss.str();
}
void d500_on_chip_calib_manager::process_flow(std::function<void()> cleanup, invoker invoke)
{
std::string json = convert_action_to_json_string();
auto calib_dev = _dev.as<auto_calibrated_device>();
float health = 0.f;
int timeout_ms = 240000; // increased to 4 minutes for additional algo processing
auto ans = calib_dev.run_on_chip_calibration(json, &health,
[&](const float progress) {_progress = progress; }, timeout_ms);
// in order to grep new calibration from answer, use:
// auto new_calib = std::vector<uint8_t>(ans.begin() + 3, ans.end());
if (_progress == 100.0)
{
_done = true;
}
else
{
// exception must have been thrown from run_on_chip_calibration call
_failed = true;
}
}
bool d500_on_chip_calib_manager::abort()
{
auto calib_dev = _dev.as<auto_calibrated_device>();
float health = 0.f;
int timeout_ms = 50000; // 50 seconds
std::string json = convert_action_to_json_string();
auto ans = calib_dev.run_on_chip_calibration(json, &health,
[&](const float progress) {}, timeout_ms);
// returns 1 on success, 0 on failure
return (ans[0] == 1);
}
void d500_on_chip_calib_manager::prepare_for_calibration()
{
// set depth preset as default preset, turn projector ON and depth AE ON
if (_sub->s->supports(RS2_CAMERA_INFO_NAME) &&
(std::string(_sub->s->get_info(RS2_CAMERA_INFO_NAME)) == "Stereo Module"))
{
auto depth_sensor = _sub->s->as <rs2::depth_sensor>();
// disabling the depth visual preset change for D555 - not needed
std::string dev_name = _dev.supports( RS2_CAMERA_INFO_NAME ) ? _dev.get_info( RS2_CAMERA_INFO_NAME ) : "";
if( dev_name.find( "D555" ) == std::string::npos )
{
// set depth preset as default preset
set_option_if_needed<rs2::depth_sensor>(depth_sensor, RS2_OPTION_VISUAL_PRESET, 1);
}
// turn projector ON
set_option_if_needed<rs2::depth_sensor>(depth_sensor, RS2_OPTION_EMITTER_ENABLED, 1);
// turn depth AE ON
set_option_if_needed<rs2::depth_sensor>(depth_sensor, RS2_OPTION_ENABLE_AUTO_EXPOSURE, 1);
}
}
std::string d500_on_chip_calib_manager::get_device_pid() const
{
std::string pid_str;
if (_dev.supports(RS2_CAMERA_INFO_PRODUCT_ID))
pid_str = _dev.get_info(RS2_CAMERA_INFO_PRODUCT_ID);
return pid_str;
}
d500_autocalib_notification_model::d500_autocalib_notification_model(std::string name,
std::shared_ptr<process_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;
}
void d500_autocalib_notification_model::draw_content(ux_window& win, int x, int y, float t, std::string& error_message)
{
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 (get_manager().action == d500_on_chip_calib_manager::RS2_CALIB_ACTION_ON_CHIP_CALIB)
ImGui::Text("%s", "On-Chip Calibration");
else if (get_manager().action == d500_on_chip_calib_manager::RS2_CALIB_ACTION_ON_CHIP_CALIB_DRY_RUN)
ImGui::Text("%s", "Dry Run On-Chip Calibration");
ImGui::PushStyleColor(ImGuiCol_Text, alpha(light_grey, 1.f - t));
if (update_state == RS2_CALIB_STATE_CALIB_IN_PROCESS)
{
enable_dismiss = false;
ImGui::SetCursorScreenPos({ float(x + 9), float(y + 27) });
ImGui::Text("%s", "Camera is being calibrated...\n");
draw_abort(win, x, y);
}
else if (update_state == RS2_CALIB_STATE_ABORT)
{
get_manager().action = d500_on_chip_calib_manager::RS2_CALIB_ACTION_ON_CHIP_CALIB_ABORT;
auto _this = shared_from_this();
auto invoke = [_this](std::function<void()> action) {_this->invoke(action); };
try
{
update_state = RS2_CALIB_STATE_ABORT_CALLED;
_has_abort_succeeded = get_manager().abort();
}
catch (...)
{
throw std::runtime_error("Abort could not be performed!");
}
}
else if (update_state == RS2_CALIB_STATE_ABORT_CALLED)
{
update_ui_after_abort_called(win, x, y);
}
else if (update_state == RS2_CALIB_STATE_INIT_CALIB ||
update_state == RS2_CALIB_STATE_INIT_DRY_RUN)
{
calibration_button(win, x, y, bar_width);
}
else if (update_state == RS2_CALIB_STATE_FAILED)
{
update_ui_on_failure(win, x, y);
}
ImGui::PopStyleColor();
}
else
{
update_ui_on_calibration_complete(win, x, y);
}
ImGui::SetCursorScreenPos({ float(x + 5), float(y + height - 25) });
if (update_manager)
{
if (update_state == RS2_CALIB_STATE_CALIB_IN_PROCESS)
{
if (update_manager->done())
{
update_state = RS2_CALIB_STATE_COMPLETE;
enable_dismiss = true;
}
else if (update_manager->failed())
{
update_state = RS2_CALIB_STATE_FAILED;
enable_dismiss = 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);
ImGui::SetCursorScreenPos({ float(x + width - 105), float(y + height - 25) });
ImGui::PushStyleColor(ImGuiCol_Text, light_grey);
ImGui::PopStyleColor();
}
}
}
}
int d500_autocalib_notification_model::calc_height()
{
// adjusting the height of the notification window
if (update_state == RS2_CALIB_STATE_CALIB_IN_PROCESS ||
update_state == RS2_CALIB_STATE_COMPLETE ||
update_state == RS2_CALIB_STATE_ABORT_CALLED ||
update_state == RS2_CALIB_STATE_FAILED)
return 90;
return 60;
}
void d500_autocalib_notification_model::calibration_button(ux_window& win, int x, int y, int bar_width)
{
using namespace std;
using namespace chrono;
ImGui::SetCursorScreenPos({ float(x + 9), float(y + height - ImGui::GetTextLineHeightWithSpacing() - 31) });
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 activation_cal_str = "Calibrate";
if (update_state == RS2_CALIB_STATE_INIT_DRY_RUN)
activation_cal_str = "Calibrate Dry Run";
std::string calibrate_button_name = rsutils::string::from() << activation_cal_str << "##self" << index;
ImGui::SetCursorScreenPos({ float(x + 5), float(y + height - 28) });
if (ImGui::Button(calibrate_button_name.c_str(), { float(bar_width), 20.f }))
{
get_manager().reset();
if (update_state == RS2_CALIB_STATE_INIT_DRY_RUN)
{
get_manager().action = d500_on_chip_calib_manager::RS2_CALIB_ACTION_ON_CHIP_CALIB_DRY_RUN;
}
get_manager().prepare_for_calibration();
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);
}
void d500_autocalib_notification_model::draw_abort(ux_window& win, int x, int y)
{
ImGui::SetCursorScreenPos({ float(x + width - 105), float(y + height - 25) });
std::string id = rsutils::string::from() << "Abort" << "##" << index;
ImGui::SetNextWindowPos({ float(x + width - 125), float(y + height - 25) });
ImGui::SetNextWindowSize({ 120, 70 });
if (ImGui::Button(id.c_str(), { 100, 20 }))
{
update_state = RS2_CALIB_STATE_ABORT;
}
if (ImGui::IsItemHovered())
{
RsImGui::CustomTooltip("Abort Calibration Process");
}
}
void d500_autocalib_notification_model::update_ui_after_abort_called(ux_window& win, int x, int y)
{
ImGui::Text("%s", "Calibration Aborting");
ImGui::SetCursorScreenPos({ float(x + 10), float(y + 40) });
ImGui::PushFont(win.get_large_font());
std::string txt = rsutils::string::from() << textual_icons::stop;
ImGui::Text("%s", txt.c_str());
ImGui::PopFont();
ImGui::SetCursorScreenPos({ float(x + 40), float(y + 40) });
if (_has_abort_succeeded)
{
ImGui::Text("%s", "Camera Calibration Aborted Successfully");
}
else
{
ImGui::Text("%s", "Camera Calibration Could not be Aborted");
}
enable_dismiss = true;
}
void d500_autocalib_notification_model::update_ui_on_failure(ux_window& win, int x, int y)
{
ImGui::SetCursorScreenPos({ float(x + 50), float(y + 50) });
ImGui::Text("%s", "Calibration Failed");
ImGui::SetCursorScreenPos({ float(x + 10), float(y + 50) });
ImGui::PushFont(win.get_large_font());
std::string txt = rsutils::string::from() << textual_icons::exclamation_triangle;
ImGui::Text("%s", txt.c_str());
ImGui::PopFont();
ImGui::SetCursorScreenPos({ float(x + 40), float(y + 50) });
enable_dismiss = true;
}
void d500_autocalib_notification_model::update_ui_on_calibration_complete(ux_window& win, int x, int y)
{
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");
}
}