From 3ae6c2f6610157815d8c8dcc2bfab42f53127ded Mon Sep 17 00:00:00 2001 From: Paul Beuchat <beuchatp@control.ee.ethz.ch> Date: Mon, 25 Nov 2019 08:57:34 +0100 Subject: [PATCH] Connected the chart to the measured data and checked that it works in the emulation environment --- dfall_ws/src/dfall_pkg/CMakeLists.txt | 9 +- .../forms/csonecontrollertab.ui | 6 +- .../include/csonecontrollertab.h | 16 +- .../flyingAgentGUI/src/csonecontrollertab.cpp | 163 ++++++++++++++++-- 4 files changed, 175 insertions(+), 19 deletions(-) diff --git a/dfall_ws/src/dfall_pkg/CMakeLists.txt b/dfall_ws/src/dfall_pkg/CMakeLists.txt index c93e0b49..7b1ca67e 100755 --- a/dfall_ws/src/dfall_pkg/CMakeLists.txt +++ b/dfall_ws/src/dfall_pkg/CMakeLists.txt @@ -29,6 +29,7 @@ find_package(Qt5Widgets CONFIG) find_package(Qt5Core CONFIG) find_package(Qt5Gui CONFIG) find_package(Qt5Svg CONFIG) +find_package(Qt5Charts CONFIG) @@ -81,9 +82,14 @@ if(Qt5Svg_FOUND) else() message(STATUS "NOTE: the Qt5 Svg package was NOT found") endif() +if(Qt5Charts_FOUND) + message(STATUS "NOTE: the Qt5 Charts package was found") +else() + message(STATUS "NOTE: the Qt5 Charts package was NOT found") +endif() -if(Qt5Widgets_FOUND AND Qt5Core_FOUND AND Qt5Gui_FOUND AND Qt5Svg_FOUND) +if(Qt5Widgets_FOUND AND Qt5Core_FOUND AND Qt5Gui_FOUND AND Qt5Svg_FOUND AND Qt5Charts_FOUND) set(Qt5_FOUND TRUE) else() set(Qt5_FOUND FALSE) @@ -572,6 +578,7 @@ if(Qt5_FOUND) # Flying Agent GUI -- link libraries target_link_libraries(FlyingAgentGUI Qt5::Widgets) # GUI -- let FlyingAgentGUI have acesss to Qt stuff + target_link_libraries(FlyingAgentGUI Qt5::Charts) target_link_libraries(FlyingAgentGUI ${catkin_LIBRARIES}) endif() diff --git a/dfall_ws/src/dfall_pkg/GUI_Qt/flyingAgentGUI/forms/csonecontrollertab.ui b/dfall_ws/src/dfall_pkg/GUI_Qt/flyingAgentGUI/forms/csonecontrollertab.ui index de8163e4..a8244e19 100644 --- a/dfall_ws/src/dfall_pkg/GUI_Qt/flyingAgentGUI/forms/csonecontrollertab.ui +++ b/dfall_ws/src/dfall_pkg/GUI_Qt/flyingAgentGUI/forms/csonecontrollertab.ui @@ -6,7 +6,7 @@ <rect> <x>0</x> <y>0</y> - <width>1492</width> + <width>1494</width> <height>1434</height> </rect> </property> @@ -733,7 +733,7 @@ </layout> </item> <item row="1" column="4"> - <widget class="QPushButton" name="custom_button_1"> + <widget class="QPushButton" name="perform_step_button"> <property name="sizePolicy"> <sizepolicy hsizetype="Minimum" vsizetype="Fixed"> <horstretch>0</horstretch> @@ -741,7 +741,7 @@ </sizepolicy> </property> <property name="text"> - <string>Button 1</string> + <string>Perform Step</string> </property> </widget> </item> diff --git a/dfall_ws/src/dfall_pkg/GUI_Qt/flyingAgentGUI/include/csonecontrollertab.h b/dfall_ws/src/dfall_pkg/GUI_Qt/flyingAgentGUI/include/csonecontrollertab.h index ee39cd66..8b0cd5a3 100644 --- a/dfall_ws/src/dfall_pkg/GUI_Qt/flyingAgentGUI/include/csonecontrollertab.h +++ b/dfall_ws/src/dfall_pkg/GUI_Qt/flyingAgentGUI/include/csonecontrollertab.h @@ -103,6 +103,8 @@ public slots: private slots: + void newDataForPerformingStepAndPlotting(float x); + void on_lineEdit_setpoint_new_x_returnPressed(); void on_lineEdit_setpoint_new_y_returnPressed(); void on_lineEdit_setpoint_new_z_returnPressed(); @@ -112,7 +114,8 @@ private slots: void on_default_setpoint_button_clicked(); - void on_custom_button_1_clicked(); + void on_perform_step_button_clicked(); + void on_custom_button_2_clicked(); void on_custom_button_3_clicked(); @@ -138,7 +141,16 @@ private: bool m_shouldCoordinateAll = true; QMutex m_agentIDs_toCoordinate_mutex; - // For plotting data on the chart + // FOR PLOTTING DATA ON THE CHART + // > Mutex for serialising acess to any charting variable + QMutex m_chart_mutex; + // > Flag for whether to perform a step + bool m_shouldPerformStep = false; + // > Flag for whether to store data for plotting + bool m_shouldStoreData_for_plotting = false; + // > Time (as a float) for the horizontal axis + float m_time_for_step = 0.0f; + // > Line Series for the data QLineSeries *m_lineSeries_for_setpoint_x; QLineSeries *m_lineSeries_for_measured_x; diff --git a/dfall_ws/src/dfall_pkg/GUI_Qt/flyingAgentGUI/src/csonecontrollertab.cpp b/dfall_ws/src/dfall_pkg/GUI_Qt/flyingAgentGUI/src/csonecontrollertab.cpp index ef8c15cf..dc90b63b 100644 --- a/dfall_ws/src/dfall_pkg/GUI_Qt/flyingAgentGUI/src/csonecontrollertab.cpp +++ b/dfall_ws/src/dfall_pkg/GUI_Qt/flyingAgentGUI/src/csonecontrollertab.cpp @@ -70,18 +70,24 @@ CsoneControllerTab::CsoneControllerTab(QWidget *parent) : m_lineSeries_for_setpoint_x = new QLineSeries(); m_lineSeries_for_measured_x = new QLineSeries(); - // DEBUGGING: SET SOME FAKE DATA FOR TESTING FOR A LINE CHART - m_lineSeries_for_setpoint_x->append(0, 6); - m_lineSeries_for_setpoint_x->append(2, 4); - m_lineSeries_for_setpoint_x->append(3, 8); - m_lineSeries_for_setpoint_x->append(7, 4); - m_lineSeries_for_setpoint_x->append(10, 5); - *m_lineSeries_for_setpoint_x << QPointF(11, 1) << QPointF(13, 3) << QPointF(17, 6) << QPointF(18, 3) << QPointF(20, 2); - - // Add the +// // DEBUGGING: SET SOME FAKE DATA FOR TESTING FOR A LINE CHART +// m_lineSeries_for_setpoint_x->append(0, 6); +// m_lineSeries_for_setpoint_x->append(2, 4); +// m_lineSeries_for_setpoint_x->append(3, 8); +// m_lineSeries_for_setpoint_x->append(7, 4); +// m_lineSeries_for_setpoint_x->append(10, 5); +// *m_lineSeries_for_setpoint_x << QPointF(11, 1) << QPointF(13, 3) << QPointF(17, 6) << QPointF(18, 3) << QPointF(20, 2); + + // Add the line series to the chart ui->chartView_for_x->chart()->addSeries(m_lineSeries_for_setpoint_x); ui->chartView_for_x->chart()->addSeries(m_lineSeries_for_measured_x); + + // Set the initial axes limits ui->chartView_for_x->chart()->createDefaultAxes(); + ui->chartView_for_x->chart()->axisX()->setMin(-1.0); + ui->chartView_for_x->chart()->axisX()->setMax(10.0); + ui->chartView_for_x->chart()->axisY()->setMin(-0.6); + ui->chartView_for_x->chart()->axisY()->setMax( 0.6); @@ -196,12 +202,30 @@ void CsoneControllerTab::publish_custom_button_command(int button_index , QLineE #endif -void CsoneControllerTab::on_custom_button_1_clicked() +void CsoneControllerTab::on_perform_step_button_clicked() { - m_lineSeries_for_setpoint_x->append(10, 6); - //ui->chartView_for_x->chart()->createDefaultAxes(); + // Lock the mutex + m_chart_mutex.lock(); + + // Set the flag that a step should be performed + m_shouldPerformStep = true; + + // Set the time back to zero + m_time_for_step = -1.0; + + // Clear any data from the line series + m_lineSeries_for_setpoint_x->removePoints(0,m_lineSeries_for_setpoint_x->count()); + m_lineSeries_for_measured_x->removePoints(0,m_lineSeries_for_measured_x->count()); + + // Set the flag that should store data + m_shouldStoreData_for_plotting = true; + + // Unlock the mutex + m_chart_mutex.unlock(); + + // Inform the user about the change #ifdef CATKIN_MAKE - publish_custom_button_command(1,ui->lineEdit_custom_1); + ROS_INFO_STREAM("[CSONE CONTROLLER TAB GUI] Perform step started"); #endif } @@ -239,6 +263,7 @@ void CsoneControllerTab::on_custom_button_3_clicked() void CsoneControllerTab::setMeasuredPose(float x , float y , float z , float roll , float pitch , float yaw , bool occluded) { + // Check if the object is occluded for this data if (!occluded) { // INITIALISE A STRING VARIABLE FOR ADDING THE "+" @@ -272,6 +297,16 @@ void CsoneControllerTab::setMeasuredPose(float x , float y , float z , float rol if ( !(ui->red_frame_position_right->isVisible()) ) ui->red_frame_position_right->setVisible(true); } + + // Pass the data through to the plotting function + if (!occluded) + { + newDataForPerformingStepAndPlotting(x); + } + else + { + newDataForPerformingStepAndPlotting(0.0); + } } @@ -288,6 +323,91 @@ void CsoneControllerTab::poseDataUnavailableSlot() +void CsoneControllerTab::newDataForPerformingStepAndPlotting(float x) +{ + // Static variables for the min and max of the vertical axis + static float min_value_plotted = -0.01; + static float max_value_plotted = 0.01; + static float next_rezoom_at_time = 2.00; + + // Only do something if the flag indicates to do so + if (m_shouldStoreData_for_plotting) + { + // Lock the mutex + m_chart_mutex.lock(); + + // Add the data to the line series + float temp_x_setpoint = (ui->lineEdit_setpoint_current_x->text()).toFloat(); + m_lineSeries_for_setpoint_x->append(m_time_for_step, (ui->lineEdit_setpoint_current_x->text()).toFloat() ); + m_lineSeries_for_measured_x->append(m_time_for_step, x ); + + // Reset the min, max, and rezoom time at the start of performing the step + if (m_time_for_step <= -0.998) + { + min_value_plotted = -0.01; + max_value_plotted = 0.01; + next_rezoom_at_time = 2.00; + } + + // Update the min and max values + min_value_plotted = std::min( min_value_plotted , std::min(temp_x_setpoint,x) ); + max_value_plotted = std::max( max_value_plotted , std::max(temp_x_setpoint,x) ); + + // Increment the time + m_time_for_step += 0.005; + + // Change the setpoint if the time has been incremented to zero + // > Note: use 2 milliseconds as the threshold for zero + if (m_shouldPerformStep) + { + if (m_time_for_step >= -0.002) + { + // Inform the user about the change + #ifdef CATKIN_MAKE + ROS_INFO_STREAM("[CSONE CONTROLLER TAB GUI] DEBUG 1"); + #endif + // Set the flag so that we do not enter this loop again + m_shouldPerformStep = false; + + // Extract the current setpoints + float current_x = (ui->lineEdit_setpoint_current_x->text()).toFloat(); + float current_y = (ui->lineEdit_setpoint_current_y->text()).toFloat(); + float current_z = (ui->lineEdit_setpoint_current_z->text()).toFloat(); + float current_yaw = (ui->lineEdit_setpoint_current_yaw->text()).toFloat(); + + // Determine the new x setpoint + float new_x = -current_x; + + // Publish the new setpoint + publishSetpoint(new_x,current_y,current_z,current_yaw); + } + } + + // Rezoom when the next time is reached + if ( m_time_for_step >= (next_rezoom_at_time+0.002) ) + { + float diff_of_values_plotted = max_value_plotted - min_value_plotted; + ui->chartView_for_x->chart()->axisY()->setMin( min_value_plotted - 0.1*diff_of_values_plotted ); + ui->chartView_for_x->chart()->axisY()->setMax( max_value_plotted + 0.1*diff_of_values_plotted ); + // Increment the next rezoom time + next_rezoom_at_time += 0.5; + } + + // Stop data collection and analyse the results if the time has passed 10 seconds + if (m_time_for_step >= 10.002) + { + m_shouldStoreData_for_plotting = false; + // Aslo rezoom the axes + float diff_of_values_plotted = max_value_plotted - min_value_plotted; + ui->chartView_for_x->chart()->axisY()->setMin( min_value_plotted - 0.1*diff_of_values_plotted ); + ui->chartView_for_x->chart()->axisY()->setMax( max_value_plotted + 0.1*diff_of_values_plotted ); + } + + // Unlock the mutex + m_chart_mutex.unlock(); + } +} + // ---------------------------------------------------------------------------------- @@ -323,6 +443,9 @@ void CsoneControllerTab::setpointChangedCallback(const dfall_pkg::SetpointWithHe float z = newSetpoint.z; float yaw = newSetpoint.yaw; + // Lock the mutex + m_chart_mutex.lock(); + // UPDATE THE SETPOINT COLUMN if (x < 0.0f) qstr = ""; else qstr = "+"; ui->lineEdit_setpoint_current_x->setText(qstr + QString::number( x, 'f', 3)); @@ -333,6 +456,9 @@ void CsoneControllerTab::setpointChangedCallback(const dfall_pkg::SetpointWithHe if (yaw < 0.0f) qstr = ""; else qstr = "+"; ui->lineEdit_setpoint_current_yaw->setText(qstr + QString::number( yaw * RAD2DEG, 'f', 1)); + + // Unlock the mutex + m_chart_mutex.unlock(); } #endif @@ -410,6 +536,8 @@ void CsoneControllerTab::on_lineEdit_setpoint_new_yaw_returnPressed() void CsoneControllerTab::on_set_setpoint_button_clicked() { + // Lock the mutex + m_chart_mutex.lock(); // Initialise local variable for each of (x,y,z,yaw) float x = 0.0f, y = 0.0f, z = 0.0f, yaw = 0.0f; @@ -436,6 +564,9 @@ void CsoneControllerTab::on_set_setpoint_button_clicked() else yaw = (ui->lineEdit_setpoint_current_yaw->text()).toFloat(); + // Unlock the mutex + m_chart_mutex.unlock(); + // Call the function to publish the setpoint publishSetpoint(x,y,z,yaw); } @@ -531,12 +662,18 @@ void CsoneControllerTab::setAgentIDsToCoordinate(QVector<int> agentIDs , bool sh // Unsubscribe setpointChangedSubscriber.shutdown(); + // Lock the mutex + m_chart_mutex.lock(); + // Set information back to the default ui->lineEdit_setpoint_current_x->setText("xx.xx"); ui->lineEdit_setpoint_current_y->setText("xx.xx"); ui->lineEdit_setpoint_current_z->setText("xx.xx"); ui->lineEdit_setpoint_current_yaw->setText("xx.xx"); + // Unlock the mutex + m_chart_mutex.unlock(); + } #endif } -- GitLab