diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt index 6875b2884e..62ab4990f4 100644 --- a/common/CMakeLists.txt +++ b/common/CMakeLists.txt @@ -52,6 +52,10 @@ 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 6c637747e0..67bc1ab824 100644 --- a/common/device-model.h +++ b/common/device-model.h @@ -122,6 +122,7 @@ 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 new file mode 100644 index 0000000000..3d949561ac --- /dev/null +++ b/common/frame-drops-dashboard.cpp @@ -0,0 +1,103 @@ +// 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 new file mode 100644 index 0000000000..4d8ce0c536 --- /dev/null +++ b/common/frame-drops-dashboard.h @@ -0,0 +1,41 @@ +// 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 new file mode 100644 index 0000000000..3d3d0ad305 --- /dev/null +++ b/common/motion-dashboard.cpp @@ -0,0 +1,191 @@ +// 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 new file mode 100644 index 0000000000..08656328b2 --- /dev/null +++ b/common/motion-dashboard.h @@ -0,0 +1,55 @@ +// 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 2c471a7700..fdbf7a8f2b 100644 --- a/common/output-model.cpp +++ b/common/output-model.cpp @@ -11,6 +11,9 @@ #include #include +#include "motion-dashboard.h" +#include "frame-drops-dashboard.h" + #include #include @@ -116,15 +119,27 @@ 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["Frame Drops per Second"] = [&](std::string name){ - return std::make_shared(name, &number_of_drops, &total_frames); - }; + 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 ); } ) ); - auto front = available_dashboards.begin(); - dashboards.push_back(front->second(front->first)); + for(const auto& dashboard: available_dashboards) + { + if( dashboard.first == dashboard_names[current_dashboard_index] ) + dashboards.push_back( dashboard.second( dashboard.first ) ); + } } bool output_model::round_indicator(ux_window& win, std::string icon, @@ -670,23 +685,6 @@ 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) { @@ -698,55 +696,53 @@ void output_model::draw(ux_window& win, rect view_rect, device_models_list & dev if (it == dashboards.end()) can_add = true; } - if (can_add) + if( can_add && is_dashboard_open ) { ImGui::SetCursorPosY(ImGui::GetCursorPosY() + 5); - const auto new_dashboard_name = "new_dashboard"; + ImGui::SameLine(); - if (ImGui::Button(u8"\uF0D0 Add Dashboard", ImVec2(-1, 25))) - { - ImGui::OpenPopup(new_dashboard_name); - } + ImGui::Button( u8"\uF0D0 Dashboards", ImVec2( -1, collapse_dashboard_button_size.y ) ); + + ImGui::PushStyleColor( ImGuiCol_Text, white ); + ImGui::PushStyleColor( ImGuiCol_HeaderHovered, light_blue ); - if (ImGui::IsItemHovered()) + int radio_button_choice = 0; + for( auto && kvp : available_dashboards ) { - ImGui::SetTooltip("Add one of the available stream dashboards to view"); - win.link_hovered(); + 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(); + + config_file::instance().set( configurations::viewer::last_opened_dashboard, current_dashboard_index); + dashboards.push_back( kvp.second( kvp.first ) ); + } } + ImGui::PopStyleColor( 2 ); - 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)) + // Draw dashboard background + auto top = 0; + if( dashboard_width == max_dashboard_width ) { - for (auto&& kvp : available_dashboards) + for( auto && dash : dashboards ) { - 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)); - } - } + 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; } - - ImGui::EndPopup(); } - - ImGui::PopStyleColor(4); - ImGui::PopStyleVar(); } - ImGui::EndChild(); ImGui::PopStyleColor(); @@ -1031,6 +1027,7 @@ void stream_dashboard::draw_dashboard(ux_window& win, rect& r) } auto pos = ImGui::GetCursorScreenPos(); + pos.y += 5; ImGui::PushStyleColor(ImGuiCol_Text, white); @@ -1040,24 +1037,16 @@ 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 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)); + float padding_top = ImGui::GetCursorPosY(); // Padding from top for scale digits. + ImGui::SetCursorPos(ImVec2( r.w / 2 - size.x / 2, 5 + padding_top)); ImGui::Text("%s", name.c_str()); ImGui::SameLine(); ImGui::PushStyleColor(ImGuiCol_Text, grey); ImGui::SetCursorPosX(r.w - 25); - ImGui::SetCursorPosY( 3.f + collapse_buton_h ); + ImGui::SetCursorPosY( 3.f + padding_top ); 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 }, @@ -1069,7 +1058,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 + collapse_buton_h)); + ImGui::SetCursorPos(ImVec2( 10, y_pixel + padding_top)); ImGui::Text("%s", y_label.c_str()); ImGui::GetWindowDrawList()->AddLine({ pos.x + max_y_label_width + 15.f, pos.y + y_pixel + 5.f }, @@ -1099,7 +1088,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() + collapse_buton_h)); + ImGui::SetCursorPos(ImVec2( 15 + max_y_label_width+ i * (graph_width / ticks_x), r.h - ImGui::GetTextLineHeight() + padding_top)); 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 }, @@ -1130,93 +1119,4 @@ void stream_dashboard::draw_dashboard(ux_window& win, rect& r) ImGui::PopStyleColor(); xy.clear(); -} - -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); - } - }); -} +} \ No newline at end of file diff --git a/common/output-model.h b/common/output-model.h index 9d5ce8dd71..4345efce55 100644 --- a/common/output-model.h +++ b/common/output-model.h @@ -83,36 +83,10 @@ namespace rs2 std::mutex m; std::atomic stop { false }; std::thread t; - std::vector> xy; + std::deque> 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: @@ -193,7 +167,10 @@ namespace rs2 bool command_focus = true; std::vector> dashboards; - std::map(std::string)>> available_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::atomic to_stop { 0 }; std::thread fw_logger; diff --git a/common/ux-window.cpp b/common/ux-window.cpp index 8ae9eacf93..760581015d 100644 --- a/common/ux-window.cpp +++ b/common/ux-window.cpp @@ -72,6 +72,7 @@ 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