From dacc34ec28417b4a3a5c01a5e5fd3b6939b76187 Mon Sep 17 00:00:00 2001 From: Nir Azkiel Date: Tue, 12 Mar 2024 16:28:06 +0200 Subject: [PATCH] revert PR #12671 from Tamir91: Viewer Accel and Gyro dashboards --- common/CMakeLists.txt | 4 - common/device-model.h | 1 - common/frame-drops-dashboard.cpp | 103 -------------- common/frame-drops-dashboard.h | 41 ------ common/motion-dashboard.cpp | 191 -------------------------- common/motion-dashboard.h | 55 -------- common/output-model.cpp | 224 ++++++++++++++++++++++--------- common/output-model.h | 33 ++++- common/ux-window.cpp | 1 - 9 files changed, 190 insertions(+), 463 deletions(-) delete mode 100644 common/frame-drops-dashboard.cpp delete mode 100644 common/frame-drops-dashboard.h delete mode 100644 common/motion-dashboard.cpp delete mode 100644 common/motion-dashboard.h diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt index 62ab4990f4..6875b2884e 100644 --- a/common/CMakeLists.txt +++ b/common/CMakeLists.txt @@ -52,10 +52,6 @@ set(COMMON_SRC "${CMAKE_CURRENT_LIST_DIR}/processing-block-model.cpp" "${CMAKE_CURRENT_LIST_DIR}/stream-model.h" "${CMAKE_CURRENT_LIST_DIR}/stream-model.cpp" - "${CMAKE_CURRENT_LIST_DIR}/motion-dashboard.h" - "${CMAKE_CURRENT_LIST_DIR}/motion-dashboard.cpp" - "${CMAKE_CURRENT_LIST_DIR}/frame-drops-dashboard.h" - "${CMAKE_CURRENT_LIST_DIR}/frame-drops-dashboard.cpp" "${CMAKE_CURRENT_LIST_DIR}/post-processing-filters.h" "${CMAKE_CURRENT_LIST_DIR}/post-processing-filters.cpp" ) diff --git a/common/device-model.h b/common/device-model.h index 67bc1ab824..6c637747e0 100644 --- a/common/device-model.h +++ b/common/device-model.h @@ -122,7 +122,6 @@ namespace rs2 static const char* is_measuring{ "viewer_model.is_measuring" }; static const char* output_open{ "viewer_model.output_open" }; static const char* dashboard_open{ "viewer_model.dashboard_open" }; - static const char* last_opened_dashboard{ "viewer_model.last_opened_dashboard" }; static const char* search_term{ "viewer_model.search_term" }; static const char* log_to_console{ "viewer_model.log_to_console" }; diff --git a/common/frame-drops-dashboard.cpp b/common/frame-drops-dashboard.cpp deleted file mode 100644 index 3d949561ac..0000000000 --- a/common/frame-drops-dashboard.cpp +++ /dev/null @@ -1,103 +0,0 @@ -// License: Apache 2.0. See LICENSE file in root directory. -// Copyright(c) 2024 Intel Corporation. All Rights Reserved. - -#include "frame-drops-dashboard.h" - -using namespace rs2; -using namespace rsutils::string; - -void frame_drops_dashboard::process_frame( rs2::frame f ) -{ - write_shared_data( - [&]() - { - double ts = glfwGetTime(); - if( method == 1 ) - ts = f.get_timestamp() / 1000.f; - auto it = stream_to_time.find( f.get_profile().unique_id() ); - if( it != stream_to_time.end() ) - { - auto last = stream_to_time[f.get_profile().unique_id()]; - - double fps = (double)f.get_profile().fps(); - - if( f.supports_frame_metadata( RS2_FRAME_METADATA_ACTUAL_FPS ) ) - fps = f.get_frame_metadata( RS2_FRAME_METADATA_ACTUAL_FPS ) / 1000.; - - if( 1000. * ( ts - last ) > 1.5 * ( 1000. / fps ) ) - { - drops++; - } - } - - counter++; - - if( ts - last_time > 1.f ) - { - if( drops_history.size() > 100 ) - drops_history.pop_front(); - drops_history.push_back( drops ); - *total = counter; - *frame_drop_count = drops; - drops = 0; - last_time = ts; - counter = 0; - } - - stream_to_time[f.get_profile().unique_id()] = ts; - } ); -} - -void frame_drops_dashboard::draw( ux_window & win, rect r ) -{ - auto hist = read_shared_data< std::deque< int > >( [&]() { return drops_history; } ); - for( int i = 0; i < hist.size(); i++ ) - { - add_point( (float)i, (float)hist[i] ); - } - r.h -= ImGui::GetTextLineHeightWithSpacing() + 10; - - draw_dashboard( win, r ); - - ImGui::SetCursorPosX( ImGui::GetCursorPosX() + ImGui::GetTextLineHeightWithSpacing() * 2 ); - ImGui::SetCursorPosY( ImGui::GetCursorPosY() + 3 ); - ImGui::Text( "%s", "Measurement Metric:" ); - ImGui::SameLine(); - ImGui::SetCursorPosY( ImGui::GetCursorPosY() - 3 ); - - ImGui::SetCursorPosX( 11.5f * win.get_font_size() ); - - std::vector< const char * > methods; - methods.push_back( "Viewer Processing Rate" ); - methods.push_back( "Camera Timestamp Rate" ); - - ImGui::PushItemWidth( -1.f ); - if( ImGui::Combo( "##fps_method", &method, methods.data(), (int)( methods.size() ) ) ) - { - clear( false ); - } - ImGui::PopItemWidth(); -} - -int frame_drops_dashboard::get_height() const -{ - return (int)( 10 * ImGui::GetTextLineHeight() + ImGui::GetTextLineHeightWithSpacing() ); -} - -void frame_drops_dashboard::clear( bool full ) -{ - write_shared_data( - [&]() - { - stream_to_time.clear(); - last_time = 0; - *total = 0; - *frame_drop_count = 0; - if( full ) - { - drops_history.clear(); - for( int i = 0; i < 100; i++ ) - drops_history.push_back( 0 ); - } - } ); -} diff --git a/common/frame-drops-dashboard.h b/common/frame-drops-dashboard.h deleted file mode 100644 index 4d8ce0c536..0000000000 --- a/common/frame-drops-dashboard.h +++ /dev/null @@ -1,41 +0,0 @@ -// License: Apache 2.0. See LICENSE file in root directory. -// Copyright(c) 2024 Intel Corporation. All Rights Reserved. - -#pragma once - -#include "output-model.h" -#include "device-model.h" - -#include -#include "ux-window.h" - -namespace rs2 -{ - class frame_drops_dashboard : public stream_dashboard - { - public: - frame_drops_dashboard( std::string name, int * frame_drop_count, int * total ) - : stream_dashboard( name, 30 ) - , last_time( glfwGetTime() ) - , frame_drop_count( frame_drop_count ) - , total( total ) - { - clear( true ); - } - - void process_frame( rs2::frame f ) override; - void draw( ux_window & win, rect r ) override; - int get_height() const override; - - void clear( bool full ) override; - - private: - std::map< int, double > stream_to_time; - int drops = 0; - double last_time; - std::deque< int > drops_history; - int *frame_drop_count, *total; - int counter = 0; - int method = 0; - }; -} \ No newline at end of file diff --git a/common/motion-dashboard.cpp b/common/motion-dashboard.cpp deleted file mode 100644 index 3d3d0ad305..0000000000 --- a/common/motion-dashboard.cpp +++ /dev/null @@ -1,191 +0,0 @@ -// License: Apache 2.0. See LICENSE file in root directory. -// Copyright(c) 2024 Intel Corporation. All Rights Reserved. - -#include "output-model.h" -#include "motion-dashboard.h" - -using namespace rs2; -using namespace rsutils::string; - -motion_dashboard::motion_dashboard( std::string name, enum rs2_stream stream) - : stream_dashboard( name, 30 ) - , last_time( glfwGetTime() ) - , x_value( 0 ) - , y_value( 0 ) - , z_value( 0 ) - , n_value( 0 ) -{ - dashboard_update_rate = MAX_FRAME_RATE; - stream_type = stream; - clear( true ); -} - -void motion_dashboard::process_frame( rs2::frame f ) -{ - write_shared_data( - [&]() - { - if( f && f.is< rs2::motion_frame >() - && ( f.as< rs2::motion_frame >() ).get_profile().stream_type() == stream_type ) - { - double ts = glfwGetTime(); - - if( ts - last_time > dashboard_update_rate ) - { - rs2::motion_frame frame = f.as< rs2::motion_frame >(); - - x_value = frame.get_motion_data().x; - y_value = frame.get_motion_data().y; - z_value = frame.get_motion_data().z; - n_value = std::sqrt( ( x_value * x_value ) + ( y_value * y_value ) + ( z_value * z_value ) ); - - if( x_history.size() > DEQUE_SIZE ) - x_history.pop_front(); - if( y_history.size() > DEQUE_SIZE ) - y_history.pop_front(); - if( z_history.size() > DEQUE_SIZE ) - z_history.pop_front(); - if( n_history.size() > DEQUE_SIZE ) - n_history.pop_front(); - - x_history.push_back( x_value ); - y_history.push_back( y_value ); - z_history.push_back( z_value ); - n_history.push_back( n_value ); - - last_time = ts; - } - } - } ); -} - -void motion_dashboard::draw( ux_window & win, rect r ) -{ - if( plots[plot_index] == x_axes_name ) - { - auto x_hist = read_shared_data< std::deque< float > >( [&]() { return x_history; } ); - for( int i = 0; i < x_hist.size(); i++ ) - { - add_point( (float)i, x_hist[i] ); - } - } - - if( plots[plot_index] == y_axes_name ) - { - auto y_hist = read_shared_data< std::deque< float > >( [&]() { return y_history; } ); - for( int i = 0; i < y_hist.size(); i++ ) - { - add_point( (float)i, y_hist[i] ); - } - } - - if( plots[plot_index] == z_axes_name ) - { - auto z_hist = read_shared_data< std::deque< float > >( [&]() { return z_history; } ); - for( int i = 0; i < z_hist.size(); i++ ) - { - add_point( (float)i, z_hist[i] ); - } - } - - if( plots[plot_index] == n_axes_name ) - { - auto n_hist = read_shared_data< std::deque< float > >( [&]() { return n_history; } ); - for( int i = 0; i < n_hist.size(); i++ ) - { - add_point( (float)i, n_hist[i] ); - } - } - r.h -= ImGui::GetTextLineHeightWithSpacing() + 10; - draw_dashboard( win, r ); - - ImGui::SetCursorPosX( ImGui::GetCursorPosX() + ImGui::GetTextLineHeightWithSpacing() * 2 ); - show_radiobuttons(); - - ImGui::SameLine(); - - show_data_rate_slider(); -} - -int motion_dashboard::get_height() const -{ - return (int)( 10 * ImGui::GetTextLineHeight() + ImGui::GetTextLineHeightWithSpacing() ); -} - -void motion_dashboard::clear( bool full ) -{ - write_shared_data( - [&]() - { - if( full ) - { - x_history.clear(); - for( int i = 0; i < DEQUE_SIZE; i++ ) - x_history.push_back( 0 ); - - y_history.clear(); - for( int i = 0; i < DEQUE_SIZE; i++ ) - y_history.push_back( 0 ); - - z_history.clear(); - for( int i = 0; i < DEQUE_SIZE; i++ ) - z_history.push_back( 0 ); - - n_history.clear(); - for( int i = 0; i < DEQUE_SIZE; i++ ) - n_history.push_back( 0 ); - } - } ); -} - -void motion_dashboard::show_radiobuttons() -{ - ImGui::PushStyleColor( ImGuiCol_Text, ImVec4( 1.0f, 0.0f, 0.0f, 1.0f ) ); // -> Red - ImGui::RadioButton( "X", &plot_index, 0 ); - if( ImGui::IsItemHovered() ) - ImGui::SetTooltip( "%s", std::string( rsutils::string::from() << "Show " << x_axes_name ).c_str() ); - ImGui::PopStyleColor(); - ImGui::SameLine(); - - ImGui::PushStyleColor( ImGuiCol_Text, ImVec4( 0.00f, 1.00f, 0.00f, 1.00f ) ); // -> Green - ImGui::RadioButton( "Y", &plot_index, 1 ); - if( ImGui::IsItemHovered() ) - ImGui::SetTooltip( "%s", std::string( rsutils::string::from() << "Show " << y_axes_name ).c_str() ); - ImGui::PopStyleColor(); - ImGui::SameLine(); - - ImGui::PushStyleColor( ImGuiCol_Text, ImVec4( 0.00f, 0.00f, 1.00f, 1.00f ) ); // -> Blue - ImGui::RadioButton( "Z", &plot_index, 2 ); - if( ImGui::IsItemHovered() ) - ImGui::SetTooltip( "%s", std::string( rsutils::string::from() << "Show " << z_axes_name ).c_str() ); - ImGui::PopStyleColor(); - ImGui::SameLine(); - - ImGui::PushStyleColor( ImGuiCol_Text, ImVec4( 1.00f, 1.00f, 1.00f, 1.00f ) ); // -> White - ImGui::RadioButton( "N", &plot_index, 3 ); - if( ImGui::IsItemHovered() ) - ImGui::SetTooltip( "%s", "Show Normal - sqrt(x^2 + y^2 + z^2)" ); - ImGui::PopStyleColor(); -} - -void motion_dashboard::show_data_rate_slider() -{ - if( ( ImGui::GetContentRegionMax().x - ImGui::GetCursorPosX() - 10.f ) < 100 ) - ImGui::PushItemWidth( ImGui::GetContentRegionMax().x - ImGui::GetCursorPosX() - 10.f ); - else - ImGui::PushItemWidth( 100 ); - - ImGui::SliderFloat( "##rate", &dashboard_update_rate, MIN_FRAME_RATE, MAX_FRAME_RATE, "%.2f" ); - ImGui::GetWindowWidth(); - - if (ImGui::IsItemHovered()) - { - ImGui::SetTooltip( "%s", std::string( rsutils::string::from() - << "Dashboard update every " - << std::fixed - << std::setprecision(1) - << dashboard_update_rate * 1000 - << " mSec" - ).c_str() ); - } -} \ No newline at end of file diff --git a/common/motion-dashboard.h b/common/motion-dashboard.h deleted file mode 100644 index 08656328b2..0000000000 --- a/common/motion-dashboard.h +++ /dev/null @@ -1,55 +0,0 @@ -// License: Apache 2.0. See LICENSE file in root directory. -// Copyright(c) 2024 Intel Corporation. All Rights Reserved. - - -namespace rs2 -{ - class stream_dashboard; - - class motion_dashboard : public stream_dashboard - { - public: - - motion_dashboard( std::string name, enum rs2_stream stream); - - // Draw Accelerate dashboard and graph's lines - void draw( ux_window & window, rect rectangle ) override; - int get_height() const override; - void clear( bool full ) override; - - // Show radio buttons for X, Y, Z and N lines - void show_radiobuttons(); - // Show slider that change pause between acceleration values that we saving. - void show_data_rate_slider(); - - // Extract X, Y, Z and calculate N values from a frame - void process_frame( rs2::frame f ) override; - - protected: - float x_value; - float y_value; - float z_value; - float n_value; // Norm ||V|| = SQRT(X^2 + Y^2 + Z^2) - - float dashboard_update_rate; - double last_time; - - const char * x_axes_name = "X"; - const char * y_axes_name = "Y"; - const char * z_axes_name = "Z"; - const char * n_axes_name = "N"; - - std::vector< std::string > plots = { x_axes_name, y_axes_name, z_axes_name, n_axes_name }; - int plot_index = 0; - - enum rs2_stream stream_type; - const float MIN_FRAME_RATE = 0.01f; - const float MAX_FRAME_RATE = 0.1f; - - const int DEQUE_SIZE = 200; - std::deque< float > x_history; - std::deque< float > y_history; - std::deque< float > z_history; - std::deque< float > n_history; - }; -} \ No newline at end of file diff --git a/common/output-model.cpp b/common/output-model.cpp index fdbf7a8f2b..2c471a7700 100644 --- a/common/output-model.cpp +++ b/common/output-model.cpp @@ -11,9 +11,6 @@ #include #include -#include "motion-dashboard.h" -#include "frame-drops-dashboard.h" - #include #include @@ -119,27 +116,15 @@ output_model::output_model() : fw_logger([this](){ thread_loop(); }) , incoming_ configurations::viewer::search_term, std::string("")); is_dashboard_open = config_file::instance().get_or_default( configurations::viewer::dashboard_open, true ); - current_dashboard_index = config_file::instance().get( configurations::viewer::last_opened_dashboard ); if (search_line != "") search_open = true; - available_dashboards.push_back( std::make_pair( dashboard_names[0], - [&]( std::string name ) - { return std::make_shared< frame_drops_dashboard >( name, &number_of_drops, &total_frames ); } ) ); - - available_dashboards.push_back( std::make_pair( dashboard_names[1], - [&]( std::string name ) - { return std::make_shared< motion_dashboard >( name, RS2_STREAM_ACCEL ); } ) ); - - available_dashboards.push_back( std::make_pair( dashboard_names[2], - [&]( std::string name ) - { return std::make_shared< motion_dashboard >( name, RS2_STREAM_GYRO ); } ) ); + available_dashboards["Frame Drops per Second"] = [&](std::string name){ + return std::make_shared(name, &number_of_drops, &total_frames); + }; - for(const auto& dashboard: available_dashboards) - { - if( dashboard.first == dashboard_names[current_dashboard_index] ) - dashboards.push_back( dashboard.second( dashboard.first ) ); - } + auto front = available_dashboards.begin(); + dashboards.push_back(front->second(front->first)); } bool output_model::round_indicator(ux_window& win, std::string icon, @@ -685,6 +670,23 @@ void output_model::draw(ux_window& win, rect view_rect, device_models_list & dev default_dashboard_w = min_dashboard_width; } + auto top = 0; + if( is_dashboard_open && dashboard_width == max_dashboard_width ) + { + for( auto && dash : dashboards ) + { + auto h = dash->get_height(); + auto r = rect{ 0.f, (float)top, get_dashboard_width() - 8.f, (float)h }; + dash->draw( win, r ); + top += h; + } + } + + dashboards.erase(std::remove_if(dashboards.begin(), dashboards.end(), + [](std::shared_ptr p){ + return p->closing(); + }), dashboards.end()); + bool can_add = false; for (auto&& kvp : available_dashboards) { @@ -696,53 +698,55 @@ void output_model::draw(ux_window& win, rect view_rect, device_models_list & dev if (it == dashboards.end()) can_add = true; } - if( can_add && is_dashboard_open ) + if (can_add) { ImGui::SetCursorPosY(ImGui::GetCursorPosY() + 5); - + const auto new_dashboard_name = "new_dashboard"; ImGui::SameLine(); - ImGui::Button( u8"\uF0D0 Dashboards", ImVec2( -1, collapse_dashboard_button_size.y ) ); - - ImGui::PushStyleColor( ImGuiCol_Text, white ); - ImGui::PushStyleColor( ImGuiCol_HeaderHovered, light_blue ); - - int radio_button_choice = 0; - for( auto && kvp : available_dashboards ) + if (ImGui::Button(u8"\uF0D0 Add Dashboard", ImVec2(-1, 25))) { - auto name = kvp.first; - auto it = std::find_if( dashboards.begin(), - dashboards.end(), - [name]( std::shared_ptr< stream_dashboard > p ) { return p->get_name() == name; } ); - - ImGui::SetCursorPosX( ImGui::GetCursorPosX() + collapse_dashboard_button_size.x ); - - // Show dashboard radio button to user - if( ImGui::RadioButton( name.c_str(), ¤t_dashboard_index, radio_button_choice++ ) ) - { - for( auto & d : dashboards ) - d->close(); - dashboards.clear(); + ImGui::OpenPopup(new_dashboard_name); + } - config_file::instance().set( configurations::viewer::last_opened_dashboard, current_dashboard_index); - dashboards.push_back( kvp.second( kvp.first ) ); - } + if (ImGui::IsItemHovered()) + { + ImGui::SetTooltip("Add one of the available stream dashboards to view"); + win.link_hovered(); } - ImGui::PopStyleColor( 2 ); - // Draw dashboard background - auto top = 0; - if( dashboard_width == max_dashboard_width ) + ImGui::PushStyleColor(ImGuiCol_PopupBg, almost_white_bg); + ImGui::PushStyleColor(ImGuiCol_Text, black); + ImGui::PushStyleColor(ImGuiCol_HeaderHovered, light_blue); + ImGui::PushStyleColor(ImGuiCol_TextSelectedBg, white); + ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(5,5)); + if (ImGui::BeginPopup(new_dashboard_name)) { - for( auto && dash : dashboards ) + for (auto&& kvp : available_dashboards) { - auto h = dash->get_height(); - auto r = rect{ 0.f, (float)top, get_dashboard_width() - 8.f, (float)h }; - dash->draw( win, r ); - top += h; + auto name = kvp.first; + auto it = std::find_if(dashboards.begin(), dashboards.end(), + [name](std::shared_ptr p){ + return p->get_name() == name; + }); + if (it == dashboards.end()) + { + name = name + "##New"; + bool selected = false; + if (ImGui::Selectable(name.c_str(), &selected)) + { + dashboards.push_back(kvp.second(kvp.first)); + } + } } + + ImGui::EndPopup(); } + + ImGui::PopStyleColor(4); + ImGui::PopStyleVar(); } + ImGui::EndChild(); ImGui::PopStyleColor(); @@ -1027,7 +1031,6 @@ void stream_dashboard::draw_dashboard(ux_window& win, rect& r) } auto pos = ImGui::GetCursorScreenPos(); - pos.y += 5; ImGui::PushStyleColor(ImGuiCol_Text, white); @@ -1037,16 +1040,24 @@ void stream_dashboard::draw_dashboard(ux_window& win, rect& r) { pos.x + r.w, pos.y + get_height() }, ImColor(dark_sensor_bg)); auto size = ImGui::CalcTextSize(name.c_str()); - float padding_top = ImGui::GetCursorPosY(); // Padding from top for scale digits. - ImGui::SetCursorPos(ImVec2( r.w / 2 - size.x / 2, 5 + padding_top)); + float collapse_buton_h = 28.f + 3.f; // Dashboard button size plus some spacing + ImGui::SetCursorPos(ImVec2( r.w / 2 - size.x / 2, 5 + collapse_buton_h)); ImGui::Text("%s", name.c_str()); ImGui::SameLine(); ImGui::PushStyleColor(ImGuiCol_Text, grey); ImGui::SetCursorPosX(r.w - 25); - ImGui::SetCursorPosY( 3.f + padding_top ); + ImGui::SetCursorPosY( 3.f + collapse_buton_h ); std::string id = rsutils::string::from() << u8"\uF00D##Close_" << name; - + if (ImGui::Button(id.c_str(),ImVec2(22,22))) + { + close(); + } + if (ImGui::IsItemHovered()) + { + ImGui::SetTooltip("Remove Dashboard from View"); + win.link_hovered(); + } ImGui::PopStyleColor(); ImGui::GetWindowDrawList()->AddRectFilled({ pos.x + max_y_label_width + 15, pos.y + ImGui::GetTextLineHeight() + 5 }, @@ -1058,7 +1069,7 @@ void stream_dashboard::draw_dashboard(ux_window& win, rect& r) auto y = max_y - i * (gap_y / ticks_y); std::string y_label = rsutils::string::from() << std::fixed << std::setprecision(2) << y; auto y_pixel = ImGui::GetTextLineHeight() + i * (height_y / ticks_y); - ImGui::SetCursorPos(ImVec2( 10, y_pixel + padding_top)); + ImGui::SetCursorPos(ImVec2( 10, y_pixel + collapse_buton_h)); ImGui::Text("%s", y_label.c_str()); ImGui::GetWindowDrawList()->AddLine({ pos.x + max_y_label_width + 15.f, pos.y + y_pixel + 5.f }, @@ -1088,7 +1099,7 @@ void stream_dashboard::draw_dashboard(ux_window& win, rect& r) { auto x = min_x + i * (gap_x / ticks_x); std::string x_label = rsutils::string::from() << std::fixed << std::setprecision(2) << x; - ImGui::SetCursorPos(ImVec2( 15 + max_y_label_width+ i * (graph_width / ticks_x), r.h - ImGui::GetTextLineHeight() + padding_top)); + ImGui::SetCursorPos(ImVec2( 15 + max_y_label_width+ i * (graph_width / ticks_x), r.h - ImGui::GetTextLineHeight() + collapse_buton_h)); ImGui::Text("%s", x_label.c_str()); ImGui::GetWindowDrawList()->AddLine({ pos.x + 15 + max_y_label_width + i * (graph_width / ticks_x), pos.y + ImGui::GetTextLineHeight() + 5 }, @@ -1119,4 +1130,93 @@ void stream_dashboard::draw_dashboard(ux_window& win, rect& r) ImGui::PopStyleColor(); xy.clear(); -} \ No newline at end of file +} + +void frame_drops_dashboard::process_frame(rs2::frame f) +{ + write_shared_data([&](){ + double ts = glfwGetTime(); + if (method == 1) ts = f.get_timestamp() / 1000.f; + auto it = stream_to_time.find(f.get_profile().unique_id()); + if (it != stream_to_time.end()) + { + auto last = stream_to_time[f.get_profile().unique_id()]; + + double fps = (double)f.get_profile().fps(); + + if( f.supports_frame_metadata( RS2_FRAME_METADATA_ACTUAL_FPS ) ) + fps = f.get_frame_metadata( RS2_FRAME_METADATA_ACTUAL_FPS ) / 1000.; + + if (1000. * (ts - last) > 1.5 * (1000. / fps)) { + drops++; + } + } + + counter++; + + if (ts - last_time > 1.f) + { + if (drops_history.size() > 100) drops_history.pop_front(); + drops_history.push_back(drops); + *total = counter; + *frame_drop_count = drops; + drops = 0; + last_time = ts; + counter = 0; + } + + stream_to_time[f.get_profile().unique_id()] = ts; + }); +} + +void frame_drops_dashboard::draw(ux_window& win, rect r) +{ + auto hist = read_shared_data>([&](){ return drops_history; }); + for (int i = 0; i < hist.size(); i++) + { + add_point((float)i, (float)hist[i]); + } + r.h -= ImGui::GetTextLineHeightWithSpacing() + 10; + + if( config_file::instance().get( configurations::viewer::dashboard_open) ) + draw_dashboard(win, r); + + ImGui::SetCursorPosX(ImGui::GetCursorPosX() + 40); + ImGui::SetCursorPosY(ImGui::GetCursorPosY() + 3); + ImGui::Text("%s", "Measurement Metric:"); ImGui::SameLine(); + ImGui::SetCursorPosY(ImGui::GetCursorPosY() - 3); + + ImGui::SetCursorPosX( 11.5f * win.get_font_size() ); + + std::vector methods; + methods.push_back("Viewer Processing Rate"); + methods.push_back("Camera Timestamp Rate"); + + ImGui::PushItemWidth(-1.f); + if (ImGui::Combo("##fps_method", &method, methods.data(), (int)(methods.size()))) + { + clear(false); + } + ImGui::PopItemWidth(); +} + +int frame_drops_dashboard::get_height() const +{ + return (int)(160 + ImGui::GetTextLineHeightWithSpacing()); +} + +void frame_drops_dashboard::clear(bool full) +{ + write_shared_data([&](){ + stream_to_time.clear(); + last_time = 0; + *total = 0; + *frame_drop_count = 0; + if (full) + { + drops_history.clear(); + for (int i = 0; i < 100; i++) + drops_history.push_back(0); + } + }); +} diff --git a/common/output-model.h b/common/output-model.h index 4345efce55..9d5ce8dd71 100644 --- a/common/output-model.h +++ b/common/output-model.h @@ -83,10 +83,36 @@ namespace rs2 std::mutex m; std::atomic stop { false }; std::thread t; - std::deque> xy; + std::vector> xy; bool to_close = false; }; + class frame_drops_dashboard : public stream_dashboard + { + public: + frame_drops_dashboard(std::string name, int* frame_drop_count, int* total) + : stream_dashboard(name, 30), + last_time(glfwGetTime()), frame_drop_count(frame_drop_count), total(total) + { + clear(true); + } + + void process_frame(rs2::frame f) override; + void draw(ux_window& win, rect r) override; + int get_height() const override; + + void clear(bool full) override; + + private: + std::map stream_to_time; + int drops = 0; + double last_time; + std::deque drops_history; + int *frame_drop_count, *total; + int counter = 0; + int method = 0; + }; + class output_model { public: @@ -167,10 +193,7 @@ namespace rs2 bool command_focus = true; std::vector> dashboards; - std::vector(std::string)>>> available_dashboards; - const std::vector< std::string > dashboard_names = { "Frame Drops per Second", "Acceleration", "Gyro" }; - - int current_dashboard_index; + std::map(std::string)>> available_dashboards; std::atomic to_stop { 0 }; std::thread fw_logger; diff --git a/common/ux-window.cpp b/common/ux-window.cpp index 760581015d..8ae9eacf93 100644 --- a/common/ux-window.cpp +++ b/common/ux-window.cpp @@ -72,7 +72,6 @@ namespace rs2 config_file::instance().set_default(configurations::viewer::metric_system, true); config_file::instance().set_default(configurations::viewer::ground_truth_r, 2500); config_file::instance().set_default(configurations::viewer::dashboard_open, true); - config_file::instance().set_default(configurations::viewer::last_opened_dashboard, 0 ); config_file::instance().set_default(configurations::record::compression_mode, 2); // Let the device decide config_file::instance().set_default(configurations::record::file_save_mode, 0); // Auto-select name