diff --git a/common/frame-drops-dashboard.cpp b/common/frame-drops-dashboard.cpp index 3d949561ac..2a78a80a2e 100644 --- a/common/frame-drops-dashboard.cpp +++ b/common/frame-drops-dashboard.cpp @@ -53,7 +53,7 @@ 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] ); + add_point_n_vector( (float)i, (float)hist[i] ); } r.h -= ImGui::GetTextLineHeightWithSpacing() + 10; diff --git a/common/motion-dashboard.cpp b/common/motion-dashboard.cpp index 3d3d0ad305..173d8f7975 100644 --- a/common/motion-dashboard.cpp +++ b/common/motion-dashboard.cpp @@ -61,42 +61,44 @@ void motion_dashboard::process_frame( rs2::frame f ) void motion_dashboard::draw( ux_window & win, rect r ) { - if( plots[plot_index] == x_axes_name ) + r.h -= ImGui::GetTextLineHeightWithSpacing() + 10; + + if( show_x_graph ) { 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] ); + add_point_x_axis( (float)i, x_hist[i] ); } } - if( plots[plot_index] == y_axes_name ) + if( show_y_graph ) { 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] ); + add_point_y_axis( (float)i, y_hist[i] ); } } - if( plots[plot_index] == z_axes_name ) + if( show_z_graph ) { 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] ); + add_point_z_axis( (float)i, z_hist[i] ); } } - if( plots[plot_index] == n_axes_name ) + if( show_n_graph ) { 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] ); + add_point_n_vector( (float)i, n_hist[i] ); } } - r.h -= ImGui::GetTextLineHeightWithSpacing() + 10; + draw_dashboard( win, r ); ImGui::SetCursorPosX( ImGui::GetCursorPosX() + ImGui::GetTextLineHeightWithSpacing() * 2 ); @@ -141,28 +143,28 @@ void motion_dashboard::clear( bool full ) 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 ); + ImGui::Checkbox( x_axis_name, &show_x_graph ); if( ImGui::IsItemHovered() ) - ImGui::SetTooltip( "%s", std::string( rsutils::string::from() << "Show " << x_axes_name ).c_str() ); + ImGui::SetTooltip( "%s", std::string( rsutils::string::from() << "Show " << x_axis_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 ); + ImGui::Checkbox( y_axis_name, &show_y_graph ); if( ImGui::IsItemHovered() ) - ImGui::SetTooltip( "%s", std::string( rsutils::string::from() << "Show " << y_axes_name ).c_str() ); + ImGui::SetTooltip( "%s", std::string( rsutils::string::from() << "Show " << y_axis_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 ); + ImGui::Checkbox( z_axis_name, &show_z_graph ); if( ImGui::IsItemHovered() ) - ImGui::SetTooltip( "%s", std::string( rsutils::string::from() << "Show " << z_axes_name ).c_str() ); + ImGui::SetTooltip( "%s", std::string( rsutils::string::from() << "Show " << z_axis_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 ); + ImGui::Checkbox( n_vector_name, &show_n_graph ); if( ImGui::IsItemHovered() ) ImGui::SetTooltip( "%s", "Show Normal - sqrt(x^2 + y^2 + z^2)" ); ImGui::PopStyleColor(); diff --git a/common/motion-dashboard.h b/common/motion-dashboard.h index 08656328b2..b84ecf0e8b 100644 --- a/common/motion-dashboard.h +++ b/common/motion-dashboard.h @@ -34,13 +34,10 @@ namespace rs2 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; + const char * x_axis_name = "X"; + const char * y_axis_name = "Y"; + const char * z_axis_name = "Z"; + const char * n_vector_name = "N"; enum rs2_stream stream_type; const float MIN_FRAME_RATE = 0.01f; @@ -48,8 +45,15 @@ namespace rs2 const int DEQUE_SIZE = 200; std::deque< float > x_history; + bool show_x_graph = true; + std::deque< float > y_history; + bool show_y_graph = false; + std::deque< float > z_history; + bool show_z_graph = false; + std::deque< float > n_history; + bool show_n_graph = false; }; } \ No newline at end of file diff --git a/common/output-model.cpp b/common/output-model.cpp index fdbf7a8f2b..cb2ac33635 100644 --- a/common/output-model.cpp +++ b/common/output-model.cpp @@ -994,22 +994,9 @@ void stream_dashboard::draw_dashboard(ux_window& win, rect& r) auto min_x = 0.f; auto max_x = 1.f; auto min_y = 0.f; - auto max_y = 1.f; + auto max_y = 0.f; - if (xy.size()) - { - min_x = xy[0].first; - max_x = xy[0].first; - min_y = xy[0].second; - max_y = xy[0].second; - for (auto&& p : xy) - { - min_x = std::min(min_x, p.first); - min_y = std::min(min_y, p.second); - max_x = std::max(max_x, p.first); - max_y = std::max(max_y, p.second); - } - } + set_dashboard_size( min_x, max_x, min_y, max_y ); auto gap_y = max_y - min_y; auto gap_x = max_x - min_x; @@ -1095,15 +1082,18 @@ void stream_dashboard::draw_dashboard(ux_window& win, rect& r) { pos.x + max_y_label_width + 15 + i * (graph_width / ticks_x), pos.y + ImGui::GetTextLineHeight() + 5 + height_y }, ImColor(light_grey)); } - std::sort(xy.begin(), xy.end(), [](const std::pair& a, const std::pair& b) { return a.first < b.first; }); + std::sort(xy_x_axis.begin(), xy_x_axis.end(), [](const std::pair& a, const std::pair& b) { return a.first < b.first; }); + std::sort(xy_y_axis.begin(), xy_y_axis.end(), [](const std::pair& a, const std::pair& b) { return a.first < b.first; }); + std::sort(xy_z_axis.begin(), xy_z_axis.end(), [](const std::pair& a, const std::pair& b) { return a.first < b.first; }); + std::sort(xy_n_vector.begin(), xy_n_vector.end(), [](const std::pair& a, const std::pair& b) { return a.first < b.first; }); - for (int i = 0; i + 1 < xy.size(); i++) + for( auto i = 0; i + 1 < xy_x_axis.size(); i++ ) { - auto x0 = xy[i].first; - auto y0 = xy[i].second; + auto x0 = xy_x_axis[i].first; + auto y0 = xy_x_axis[i].second; - auto x1 = xy[i+1].first; - auto y1 = xy[i+1].second; + auto x1 = xy_x_axis[i + 1].first; + auto y1 = xy_x_axis[i + 1].second; x0 = (x0 - min_x) / (max_x - min_x); x1 = (x1 - min_x) / (max_x - min_x); @@ -1111,12 +1101,135 @@ void stream_dashboard::draw_dashboard(ux_window& win, rect& r) y0 = (y0 - min_y) / (max_y - min_y); y1 = (y1 - min_y) / (max_y - min_y); - ImGui::GetWindowDrawList()->AddLine({ pos.x + 15 + max_y_label_width + x0 * graph_width, pos.y + ImGui::GetTextLineHeight() + 5 + height_y * (1.f - y0) }, - { pos.x + 15 + max_y_label_width + x1 * graph_width, pos.y + ImGui::GetTextLineHeight() + 5 + height_y * (1.f - y1) }, ImColor(black)); + // Draw X graph line + ImGui::GetWindowDrawList()->AddLine( { pos.x + 15 + max_y_label_width + x0 * graph_width, + pos.y + ImGui::GetTextLineHeight() + 5 + height_y * ( 1.f - y0 ) }, + { pos.x + 15 + max_y_label_width + x1 * graph_width, + pos.y + ImGui::GetTextLineHeight() + 5 + height_y * ( 1.f - y1 ) }, + ImColor( red ) ); + } + + for( int i = 0; i+1 < xy_y_axis.size(); i++ ) + { + auto x0 = xy_y_axis[i].first; + auto y0 = xy_y_axis[i].second; + + auto x1 = xy_y_axis[i + 1].first; + auto y1 = xy_y_axis[i + 1].second; + + x0 = ( x0 - min_x ) / ( max_x - min_x ); + x1 = ( x1 - min_x ) / ( max_x - min_x ); + + y0 = ( y0 - min_y ) / ( max_y - min_y ); + y1 = ( y1 - min_y ) / ( max_y - min_y ); + + // Draw Y graph line + ImGui::GetWindowDrawList()->AddLine( { pos.x + 15 + max_y_label_width + x0 * graph_width, + pos.y + ImGui::GetTextLineHeight() + 5 + height_y * ( 1.f - y0 ) }, + { pos.x + 15 + max_y_label_width + x1 * graph_width, + pos.y + ImGui::GetTextLineHeight() + 5 + height_y * ( 1.f - y1 ) }, + ImColor( green ) ); } + for( int i = 0; i + 1 < xy_z_axis.size(); i++ ) + { + auto x0 = xy_z_axis[i].first; + auto y0 = xy_z_axis[i].second; + + auto x1 = xy_z_axis[i + 1].first; + auto y1 = xy_z_axis[i + 1].second; + + x0 = ( x0 - min_x ) / ( max_x - min_x ); + x1 = ( x1 - min_x ) / ( max_x - min_x ); + + y0 = ( y0 - min_y ) / ( max_y - min_y ); + y1 = ( y1 - min_y ) / ( max_y - min_y ); + + // Draw Z graph line + ImGui::GetWindowDrawList()->AddLine( { pos.x + 15 + max_y_label_width + x0 * graph_width, + pos.y + ImGui::GetTextLineHeight() + 5 + height_y * ( 1.f - y0 ) }, + { pos.x + 15 + max_y_label_width + x1 * graph_width, + pos.y + ImGui::GetTextLineHeight() + 5 + height_y * ( 1.f - y1 ) }, + ImColor( light_blue ) ); + } + + for( int i = 0; i + 1 < xy_n_vector.size(); i++ ) + { + auto x0 = xy_n_vector[i].first; + auto y0 = xy_n_vector[i].second; + + auto x1 = xy_n_vector[i + 1].first; + auto y1 = xy_n_vector[i + 1].second; + + x0 = ( x0 - min_x ) / ( max_x - min_x ); + x1 = ( x1 - min_x ) / ( max_x - min_x ); + + y0 = ( y0 - min_y ) / ( max_y - min_y ); + y1 = ( y1 - min_y ) / ( max_y - min_y ); + + // Draw N vector line + ImGui::GetWindowDrawList()->AddLine( { pos.x + 15 + max_y_label_width + x0 * graph_width, + pos.y + ImGui::GetTextLineHeight() + 5 + height_y * ( 1.f - y0 ) }, + { pos.x + 15 + max_y_label_width + x1 * graph_width, + pos.y + ImGui::GetTextLineHeight() + 5 + height_y * ( 1.f - y1 ) }, + ImColor( black ) ); + } //ImGui::PopFont(); ImGui::PopStyleColor(); - xy.clear(); + xy_x_axis.clear(); + xy_y_axis.clear(); + xy_z_axis.clear(); + xy_n_vector.clear(); +} + +void stream_dashboard::set_dashboard_size( float& min_x, float& max_x, float& min_y, float& max_y ) +{ + if( xy_x_axis.size() ) + { + for( auto && p : xy_x_axis ) + { + min_x = std::min( min_x, p.first ); + min_y = std::min( min_y, p.second ); + max_x = std::max( max_x, p.first ); + max_y = std::max( max_y, p.second ); + } + } + + if( xy_y_axis.size() ) + { + for( auto && p : xy_y_axis ) + { + min_x = std::min( min_x, p.first ); + min_y = std::min( min_y, p.second ); + max_x = std::max( max_x, p.first ); + max_y = std::max( max_y, p.second ); + } + } + + if( xy_z_axis.size() ) + { + for( auto && p : xy_z_axis ) + { + min_x = std::min( min_x, p.first ); + min_y = std::min( min_y, p.second ); + max_x = std::max( max_x, p.first ); + max_y = std::max( max_y, p.second ); + } + } + + if( xy_n_vector.size() ) + { + for( auto && p : xy_n_vector ) + { + min_x = std::min( min_x, p.first ); + min_y = std::min( min_y, p.second ); + max_x = std::max( max_x, p.first ); + max_y = std::max( max_y, p.second ); + } + } + + // Increase dashboard size (white area) from top and bottom to prevent a graph from being so close to borders. + min_y -= .5f; + max_y += .5f; } \ No newline at end of file diff --git a/common/output-model.h b/common/output-model.h index 4345efce55..d6d1905063 100644 --- a/common/output-model.h +++ b/common/output-model.h @@ -64,10 +64,15 @@ namespace rs2 return res; } - void add_point(float x, float y) { xy.push_back(std::make_pair(x, y)); } + void add_point_x_axis( float x, float y ) { xy_x_axis.push_back( std::make_pair( x, y ) ); } + void add_point_y_axis( float x, float y ) { xy_y_axis.push_back( std::make_pair( x, y ) ); } + void add_point_z_axis( float x, float y ) { xy_z_axis.push_back( std::make_pair( x, y ) ); } + void add_point_n_vector( float x, float y ) { xy_n_vector.push_back( std::make_pair( x, y ) ); } void draw_dashboard(ux_window& win, rect& r); + // Scanning all axes data structures and found optimal dashboard size to show them. + void set_dashboard_size( float & min_x, float & max_x, float & min_y, float & max_y ); private: void thread_function() { @@ -83,7 +88,12 @@ namespace rs2 std::mutex m; std::atomic stop { false }; std::thread t; - std::deque> xy; + + std::deque< std::pair< float, float > > xy_x_axis; + std::deque< std::pair< float, float > > xy_y_axis; + std::deque< std::pair< float, float > > xy_z_axis; + std::deque< std::pair< float, float > > xy_n_vector; + bool to_close = false; };