From 1941f42fc7bdbf6641d4df36fa28799f6b519b5d Mon Sep 17 00:00:00 2001
From: Paul Beuchat <beuchatp@control.ee.ethz.ch>
Date: Thu, 28 Nov 2019 17:28:26 +0100
Subject: [PATCH] Connected the CS1 integrator buttons to the GUI and tested to
 be working in simulation. Needs testing on the real system

---
 .../forms/csonecontrollertab.ui               | 111 ++++++++-
 .../include/Constants_for_Qt_compile.h        |  19 ++
 .../include/csonecontrollertab.h              |  29 ++-
 .../flyingAgentGUI/src/csonecontrollertab.cpp | 221 +++++++++++++++---
 .../src/dfall_pkg/include/nodes/Constants.h   |  18 ++
 .../include/nodes/CsoneControllerService.h    |  48 +++-
 .../src/dfall_pkg/param/CsoneController.yaml  |   7 +-
 .../src/nodes/CsoneControllerService.cpp      | 153 +++++++++++-
 8 files changed, 549 insertions(+), 57 deletions(-)

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 3815c3ca..a67692b9 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>2011</width>
+    <width>2417</width>
     <height>1336</height>
    </rect>
   </property>
@@ -421,6 +421,80 @@
      <property name="rightMargin">
       <number>0</number>
      </property>
+     <item row="1" column="7">
+      <layout class="QGridLayout" name="gridLayout_8">
+       <item row="2" column="0">
+        <widget class="QPushButton" name="reset_integrator_button">
+         <property name="sizePolicy">
+          <sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
+           <horstretch>0</horstretch>
+           <verstretch>0</verstretch>
+          </sizepolicy>
+         </property>
+         <property name="maximumSize">
+          <size>
+           <width>1000</width>
+           <height>60</height>
+          </size>
+         </property>
+         <property name="text">
+          <string>Reset</string>
+         </property>
+        </widget>
+       </item>
+       <item row="0" column="0">
+        <widget class="QLabel" name="label_integrator_state">
+         <property name="sizePolicy">
+          <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
+           <horstretch>0</horstretch>
+           <verstretch>0</verstretch>
+          </sizepolicy>
+         </property>
+         <property name="text">
+          <string>off</string>
+         </property>
+         <property name="alignment">
+          <set>Qt::AlignCenter</set>
+         </property>
+        </widget>
+       </item>
+       <item row="1" column="0">
+        <widget class="QPushButton" name="toggle_integrator_button">
+         <property name="sizePolicy">
+          <sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
+           <horstretch>0</horstretch>
+           <verstretch>0</verstretch>
+          </sizepolicy>
+         </property>
+         <property name="maximumSize">
+          <size>
+           <width>1000</width>
+           <height>60</height>
+          </size>
+         </property>
+         <property name="text">
+          <string>Toggle</string>
+         </property>
+        </widget>
+       </item>
+      </layout>
+     </item>
+     <item row="0" column="6">
+      <spacer name="horizontalSpacer_7">
+       <property name="orientation">
+        <enum>Qt::Horizontal</enum>
+       </property>
+       <property name="sizeType">
+        <enum>QSizePolicy::Fixed</enum>
+       </property>
+       <property name="sizeHint" stdset="0">
+        <size>
+         <width>100</width>
+         <height>20</height>
+        </size>
+       </property>
+      </spacer>
+     </item>
      <item row="0" column="4">
       <spacer name="horizontalSpacer_3">
        <property name="orientation">
@@ -453,7 +527,7 @@
        </property>
       </widget>
      </item>
-     <item row="0" column="6">
+     <item row="0" column="9">
       <spacer name="horizontalSpacer_2">
        <property name="orientation">
         <enum>Qt::Horizontal</enum>
@@ -849,7 +923,7 @@
           </size>
          </property>
          <property name="text">
-          <string>20</string>
+          <string>10</string>
          </property>
          <property name="alignment">
           <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
@@ -913,7 +987,7 @@
       </spacer>
      </item>
      <item row="0" column="2">
-      <widget class="QLabel" name="label_lead_compenstor_2">
+      <widget class="QLabel" name="label_pid_controller">
        <property name="font">
         <font>
          <weight>75</weight>
@@ -928,6 +1002,35 @@
        </property>
       </widget>
      </item>
+     <item row="0" column="7">
+      <widget class="QLabel" name="label_integrator">
+       <property name="font">
+        <font>
+         <weight>75</weight>
+         <bold>true</bold>
+        </font>
+       </property>
+       <property name="text">
+        <string>Integrator</string>
+       </property>
+       <property name="alignment">
+        <set>Qt::AlignCenter</set>
+       </property>
+      </widget>
+     </item>
+     <item row="0" column="8">
+      <spacer name="horizontalSpacer_8">
+       <property name="orientation">
+        <enum>Qt::Horizontal</enum>
+       </property>
+       <property name="sizeHint" stdset="0">
+        <size>
+         <width>40</width>
+         <height>20</height>
+        </size>
+       </property>
+      </spacer>
+     </item>
     </layout>
    </item>
    <item row="7" column="0">
diff --git a/dfall_ws/src/dfall_pkg/GUI_Qt/flyingAgentGUI/include/Constants_for_Qt_compile.h b/dfall_ws/src/dfall_pkg/GUI_Qt/flyingAgentGUI/include/Constants_for_Qt_compile.h
index 3b5dab86..3a40cb92 100644
--- a/dfall_ws/src/dfall_pkg/GUI_Qt/flyingAgentGUI/include/Constants_for_Qt_compile.h
+++ b/dfall_ws/src/dfall_pkg/GUI_Qt/flyingAgentGUI/include/Constants_for_Qt_compile.h
@@ -205,6 +205,25 @@
 
 
 
+//    ----------------------------------------------------------------------------------
+//
+//
+//
+//
+//
+//    ----------------------------------------------------------------------------------
+
+// These constants deine the current and interaction with an intergrator
+#define INTEGRATOR_FLAG_ON       1
+#define INTEGRATOR_FLAG_OFF      2
+#define INTEGRATOR_FLAG_UNKNOWN  3
+#define INTEGRATOR_FLAG_TOGGLE   4
+#define INTEGRATOR_FLAG_RESET    5
+
+
+
+
+
 //    ----------------------------------------------------------------------------------
 //    
 //    
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 f40fc702..a468c4da 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
@@ -72,11 +72,12 @@ using namespace QtCharts;
 //#include <std_msgs/String.h>
 
 // Include the DFALL message types
-//#include "dfall_pkg/IntWithHeader.h"
+#include "dfall_pkg/IntWithHeader.h"
 #include "dfall_pkg/SetpointWithHeader.h"
 #include "dfall_pkg/CustomButtonWithHeader.h"
 
 // Include the DFALL service types
+#include "dfall_pkg/IntIntService.h"
 #include "dfall_pkg/GetSetpointService.h"
 
 // Include the shared definitions
@@ -121,6 +122,15 @@ private slots:
     void analyseStepResponse();
     void updateStepAnalysisLineEdit(float value, QLineEdit * lineEdit, int num_dec_places);
 
+
+    void on_perform_step_button_clicked();
+    void on_log_data_button_clicked();
+
+    void on_set_lead_compensator_parameters_button_clicked();
+
+    void on_toggle_integrator_button_clicked();
+    void on_reset_integrator_button_clicked();
+
     void on_lineEdit_k_returnPressed();
     void on_lineEdit_T_returnPressed();
     void on_lineEdit_alpha_returnPressed();
@@ -129,10 +139,7 @@ private slots:
     void on_lineEdit_step_size_returnPressed();
     void on_lineEdit_step_duration_returnPressed();
 
-    void on_set_lead_compensator_parameters_button_clicked();
 
-    void on_perform_step_button_clicked();
-    void on_log_data_button_clicked();
 
 
 
@@ -188,13 +195,19 @@ private:
     // > For requesting the setpoint to be changed
     ros::Publisher requestSetpointChangePublisher;
 
-    // > For requestion the controller paramters to be changed
+    // > For requesting the controller paramters to be changed
     ros::Publisher requestControllerParamterChangePublisher;
 
+    // > For requesting a change in the integrator state
+    ros::Publisher requestIntegratorStateChangePublisher;
+
     // SUBSCRIBER
     // > For being notified when the setpoint is changed
     ros::Subscriber setpointChangedSubscriber;
 
+    // > For being notified when the integrator state
+    ros::Subscriber integratorStateChangedSubscriber;
+
     // PUBLISHER
     // > For notifying that a custom button is pressed
     ros::Publisher customButtonPublisher;
@@ -209,7 +222,11 @@ private:
     // For receiving message that the setpoint was changed
     void setpointChangedCallback(const dfall_pkg::SetpointWithHeader& newSetpoint);
 
+    // For receiving message that the integrator state changes
+    void integratorStateChangedCallback(const dfall_pkg::IntWithHeader& newIntegratorState);
+
     // Fill the header for a message
+    void fillIntMessageHeader( dfall_pkg::IntWithHeader & msg );
     void fillSetpointMessageHeader( dfall_pkg::SetpointWithHeader & msg );
     void fillCustomButtonMessageHeader( dfall_pkg::CustomButtonWithHeader & msg );
 
@@ -221,6 +238,8 @@ private:
 
     void publishControllerParamters(float k, float T, float alpha);
 
+    void publishRequestForIntegratorStateChange(int flag_to_publish);
+
 };
 
 #endif // CSONECONTROLLERTAB_H
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 f868f8e2..3f1658e6 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
@@ -157,17 +157,21 @@ CsoneControllerTab::CsoneControllerTab(QWidget *parent) :
     // CREATE THE REQUEST CONTROLLER PARAMTER CHANGE PUBLISHER
     requestControllerParamterChangePublisher = nodeHandle_for_this_gui.advertise<dfall_pkg::SetpointWithHeader>("CsoneControllerService/RequestControllerParametersChange", 1);
 
-    // SUBSCRIBE TO SETPOINT CHANGES
+    // CREATE THE REQUEST INTEGRATOR STATE CHANGE PUBLISHER
+    requestIntegratorStateChangePublisher = nodeHandle_for_this_gui.advertise<dfall_pkg::IntWithHeader>("CsoneControllerService/RequestIntegratorStateChange", 1);
+
+    // SUBSCRIBE TO SETPOINT CHANGES AND INTEGRATOR STATE CHANGES
     // Only if this is an agent GUI
     if (m_type == TYPE_AGENT)
     {
-        setpointChangedSubscriber = nodeHandle_for_this_gui.subscribe("CsoneControllerService/SetpointChanged", 1, &CsoneControllerTab::setpointChangedCallback, this);
+        setpointChangedSubscriber        = nodeHandle_for_this_gui.subscribe("CsoneControllerService/SetpointChanged"       , 1, &CsoneControllerTab::setpointChangedCallback       , this);
+        integratorStateChangedSubscriber = nodeHandle_for_this_gui.subscribe("CsoneControllerService/IntegratorStateChanged", 1, &CsoneControllerTab::integratorStateChangedCallback, this);
     }
 
     // CREATE THE CUSTOM BUTTON PRESSED PUBLISHER
     customButtonPublisher = nodeHandle_for_this_gui.advertise<dfall_pkg::CustomButtonWithHeader>("CsoneControllerService/CustomButtonPressed", 1);
 
-    // GET THE CURRENT SETPOINT
+    // GET THE CURRENT SETPOINT AND CURRENT INTEGRATOR STATE
     // Only if this is an agent GUI
     if (m_type == TYPE_AGENT)
     {
@@ -185,6 +189,23 @@ CsoneControllerTab::CsoneControllerTab(QWidget *parent) :
             // Inform the user
             ROS_INFO("[CSONE CONTROLLER GUI] Failed to get setpoint from controller using the \"GetCurrentSetpoint\" service");
         }
+
+        // > Request the current integrator state
+        ros::ServiceClient getCurrentIntegatorStateServiceClient = nodeHandle_for_this_gui.serviceClient<dfall_pkg::IntIntService>("CsoneControllerService/GetCurrentIntegratorState", false);
+        dfall_pkg::IntIntService getIntegrtorStateCall;
+        getIntegrtorStateCall.request.data = 0;
+        getCurrentIntegatorStateServiceClient.waitForExistence(ros::Duration(2.0));
+        if(getCurrentIntegatorStateServiceClient.call(getIntegrtorStateCall))
+        {
+             dfall_pkg::IntWithHeader temp_msg;
+             temp_msg.data = getIntegrtorStateCall.response.data;
+            integratorStateChangedCallback(temp_msg);
+        }
+        else
+        {
+            // Inform the user
+            ROS_INFO("[CSONE CONTROLLER GUI] Failed to get current integrator state from controller using the \"GetCurrentIntegratorState\" service");
+        }
     }
 
 #endif
@@ -266,6 +287,14 @@ void CsoneControllerTab::on_perform_step_button_clicked()
     //m_lineSeries_for_setpoint_pitch->removePoints(0,m_lineSeries_for_setpoint_pitch->count());
     m_lineSeries_for_measured_pitch->removePoints(0,m_lineSeries_for_measured_pitch->count());
 
+    // Set all the fields to be blank
+    ui->lineEdit_step_start        ->setText("---");
+    ui->lineEdit_step_end          ->setText("---");
+    ui->lineEdit_overshoot_value   ->setText("---");
+    ui->lineEdit_overshoot_percent ->setText("---");
+    ui->lineEdit_rise_time         ->setText("---");
+    ui->lineEdit_settling_time     ->setText("---");
+
     // Set the flag that should store data
     m_shouldStoreData_for_plotting = true;
 
@@ -333,6 +362,14 @@ void CsoneControllerTab::on_log_data_button_clicked()
     //m_lineSeries_for_setpoint_pitch->removePoints(0,m_lineSeries_for_setpoint_pitch->count());
     m_lineSeries_for_measured_pitch->removePoints(0,m_lineSeries_for_measured_pitch->count());
 
+    // Set all the fields to be blank
+    ui->lineEdit_step_start        ->setText("---");
+    ui->lineEdit_step_end          ->setText("---");
+    ui->lineEdit_overshoot_value   ->setText("---");
+    ui->lineEdit_overshoot_percent ->setText("---");
+    ui->lineEdit_rise_time         ->setText("---");
+    ui->lineEdit_settling_time     ->setText("---");
+
     // Set the flag that should store data
     m_shouldStoreData_for_plotting = true;
 
@@ -418,38 +455,30 @@ void CsoneControllerTab::on_set_lead_compensator_parameters_button_clicked()
         ui->lineEdit_alpha->setText(qstr + QString::number( alpha, 'f', 2));
     }
 
-    // Call the function to publish the setpoint
+    // Call the function to publish the controller parameters
     publishControllerParamters(k,T,alpha);
 }
 
 
-void CsoneControllerTab::publishControllerParamters(float k, float T, float alpha)
-{
-#ifdef CATKIN_MAKE
-    // Initialise the message as a local variable
-    dfall_pkg::SetpointWithHeader msg;
 
-    // Fill the header of the message
-    fillSetpointMessageHeader( msg );
 
-    // Fill in the controller values
-    msg.x   = k;
-    msg.y   = T;
-    msg.z   = alpha;
 
-    // Publish the setpoint
-    this->requestControllerParamterChangePublisher.publish(msg);
+void CsoneControllerTab::on_toggle_integrator_button_clicked()
+{
+    // Call the function to publish the request for a change in the integrator state
+    publishRequestForIntegratorStateChange(INTEGRATOR_FLAG_TOGGLE);
+}
 
-    // Inform the user about the change
-    ROS_INFO_STREAM("[CSONE CONTROLLER GUI] Published request for new controller parameters (k,T,alpha) =  (" << k << ", "<< T << ", "<< alpha << ")");
-#else
-    // TO ASSIST WITH DEBUGGING WHEN COMPILED AND RUN IN "QtCreator"
-    QTextStream(stdout) << "[CSONE CONTROLLER GUI] would publish request for: [" << k << ", "<< T << ", "<< alpha << "]";
-#endif
+void CsoneControllerTab::on_reset_integrator_button_clicked()
+{
+    // Call the function to publish the request for a change in the integrator state
+    publishRequestForIntegratorStateChange(INTEGRATOR_FLAG_RESET);
 }
 
 
 
+
+
 void CsoneControllerTab::on_lineEdit_k_returnPressed()
 {
     ui->set_lead_compensator_parameters_button->animateClick();
@@ -488,7 +517,6 @@ void CsoneControllerTab::on_lineEdit_step_duration_returnPressed()
 
 
 
-
 //    ----------------------------------------------------------------------------------
 //    PPPP    OOO    SSSS  EEEEE     DDDD     A    TTTTT    A
 //    P   P  O   O  S      E         D   D   A A     T     A A
@@ -797,22 +825,25 @@ void CsoneControllerTab::analyseStepResponse()
     // DISPLAY THE RESULTS IN THE FIELDS OF THE GUI
 
     // Lock the mutex
-    //m_chart_mutex.lock();
+    m_chart_mutex.lock();
 
     // Call the "update" function for each
     updateStepAnalysisLineEdit(setpoint_start     , ui->lineEdit_step_start         , 3);
     updateStepAnalysisLineEdit(setpoint_end       , ui->lineEdit_step_end           , 3);
     updateStepAnalysisLineEdit(overshoot_value    , ui->lineEdit_overshoot_value    , 3);
     updateStepAnalysisLineEdit(overshoot_percent  , ui->lineEdit_overshoot_percent  , 1);
+    updateStepAnalysisLineEdit(rise_time          , ui->lineEdit_rise_time          , 2);
+    updateStepAnalysisLineEdit(settling_time      , ui->lineEdit_settling_time      , 2);
 
 
     // Unlock the mutex
-    //m_chart_mutex.unlock();
+    m_chart_mutex.unlock();
 
 
 }
 
 
+
 void CsoneControllerTab::updateStepAnalysisLineEdit(float value, QLineEdit * lineEdit, int num_dec_places)
 {
     // Initialise a string variable for adding the "+"
@@ -879,6 +910,46 @@ void CsoneControllerTab::setpointChangedCallback(const dfall_pkg::SetpointWithHe
 
 
 
+#ifdef CATKIN_MAKE
+void CsoneControllerTab::integratorStateChangedCallback(const dfall_pkg::IntWithHeader& newIntegratorState)
+{
+    // EXTRACT THE NEW STATE
+    int new_state = newIntegratorState.data;
+
+    // Lock the mutex
+    //m_chart_mutex.lock();
+
+    switch (new_state)
+    {
+        case INTEGRATOR_FLAG_ON:
+        {
+            ui->label_integrator_state->setText("on");
+            break;
+        }
+        case INTEGRATOR_FLAG_OFF:
+        {
+            ui->label_integrator_state->setText("off");
+            break;
+        }
+        case INTEGRATOR_FLAG_UNKNOWN:
+        {
+            ui->label_integrator_state->setText("Unknown");
+            break;
+        }
+        default:
+        {
+            ui->label_integrator_state->setText("Not recognised");
+            break;
+        }
+    }
+
+    // Unlock the mutex
+    //m_chart_mutex.unlock();
+}
+#endif
+
+
+
 
 
 
@@ -930,6 +1001,61 @@ void CsoneControllerTab::publishSetpoint(float x, float y, float z, float yaw_de
 
 
 
+void CsoneControllerTab::publishControllerParamters(float k, float T, float alpha)
+{
+#ifdef CATKIN_MAKE
+    // Initialise the message as a local variable
+    dfall_pkg::SetpointWithHeader msg;
+
+    // Fill the header of the message
+    fillSetpointMessageHeader( msg );
+
+    // Fill in the controller values
+    msg.x   = k;
+    msg.y   = T;
+    msg.z   = alpha;
+
+    // Publish the setpoint
+    this->requestControllerParamterChangePublisher.publish(msg);
+
+    // Inform the user about the change
+    ROS_INFO_STREAM("[CSONE CONTROLLER GUI] Published request for new controller parameters (k,T,alpha) =  (" << k << ", "<< T << ", "<< alpha << ")");
+#else
+    // TO ASSIST WITH DEBUGGING WHEN COMPILED AND RUN IN "QtCreator"
+    QTextStream(stdout) << "[CSONE CONTROLLER GUI] would publish request for: [" << k << ", "<< T << ", "<< alpha << "]";
+#endif
+}
+
+
+
+
+
+void CsoneControllerTab::publishRequestForIntegratorStateChange(int flag_to_publish)
+{
+#ifdef CATKIN_MAKE
+    // Initialise the message as a local variable
+    dfall_pkg::IntWithHeader msg;
+
+    // Fill the header of the message
+    fillIntMessageHeader( msg );
+
+    // Fill in the controller values
+    msg.data = flag_to_publish;
+
+    // Publish the setpoint
+    this->requestIntegratorStateChangePublisher.publish(msg);
+
+    // Inform the user about the change
+    ROS_INFO_STREAM("[CSONE CONTROLLER GUI] Published request for integrator state to change with flag " << flag_to_publish << ")");
+#else
+    // TO ASSIST WITH DEBUGGING WHEN COMPILED AND RUN IN "QtCreator"
+    QTextStream(stdout) << "[CSONE CONTROLLER GUI] would publish request for integrator state to change with flag " << flag_to_publish << ")";
+#endif
+}
+
+
+
+
 //    ----------------------------------------------------------------------------------
 //      A     GGGG  EEEEE  N   N  TTTTT     III  DDDD    SSSS
 //     A A   G      E      NN  N    T        I   D   D  S
@@ -1025,6 +1151,49 @@ void CsoneControllerTab::setAgentIDsToCoordinate(QVector<int> agentIDs , bool sh
 
 
 
+#ifdef CATKIN_MAKE
+// Fill the header for a message
+void CsoneControllerTab::fillIntMessageHeader( dfall_pkg::IntWithHeader & msg )
+{
+    switch (m_type)
+    {
+        case TYPE_AGENT:
+        {
+            msg.shouldCheckForAgentID = false;
+            break;
+        }
+        case TYPE_COORDINATOR:
+        {
+            // Lock the mutex
+            m_agentIDs_toCoordinate_mutex.lock();
+            // Add the "coordinate all" flag
+            msg.shouldCheckForAgentID = !(m_shouldCoordinateAll);
+            // Add the agent IDs if necessary
+            if (!m_shouldCoordinateAll)
+            {
+                for ( int irow = 0 ; irow < m_vector_of_agentIDs_toCoordinate.size() ; irow++ )
+                {
+                    msg.agentIDs.push_back( m_vector_of_agentIDs_toCoordinate[irow] );
+                }
+            }
+            // Unlock the mutex
+            m_agentIDs_toCoordinate_mutex.unlock();
+            break;
+        }
+
+        default:
+        {
+            msg.shouldCheckForAgentID = true;
+            ROS_ERROR("[CSONE CONTROLLER TAB GUI] The 'm_type' variable was not recognised.");
+            break;
+        }
+    }
+}
+#endif
+
+
+
+
 #ifdef CATKIN_MAKE
 // Fill the header for a message
 void CsoneControllerTab::fillSetpointMessageHeader( dfall_pkg::SetpointWithHeader & msg )
diff --git a/dfall_ws/src/dfall_pkg/include/nodes/Constants.h b/dfall_ws/src/dfall_pkg/include/nodes/Constants.h
index 2525931a..c28c297d 100644
--- a/dfall_ws/src/dfall_pkg/include/nodes/Constants.h
+++ b/dfall_ws/src/dfall_pkg/include/nodes/Constants.h
@@ -221,6 +221,24 @@
 
 
 
+//    ----------------------------------------------------------------------------------
+//    
+//    
+//    
+//    
+//    
+//    ----------------------------------------------------------------------------------
+
+// These constants deine the current and interaction with an intergrator
+#define INTEGRATOR_FLAG_ON       1
+#define INTEGRATOR_FLAG_OFF      2
+#define INTEGRATOR_FLAG_UNKNOWN  3
+#define INTEGRATOR_FLAG_TOGGLE   4
+#define INTEGRATOR_FLAG_RESET    5
+
+
+
+
 
 //    ----------------------------------------------------------------------------------
 //    
diff --git a/dfall_ws/src/dfall_pkg/include/nodes/CsoneControllerService.h b/dfall_ws/src/dfall_pkg/include/nodes/CsoneControllerService.h
index 085cdc5a..1dee19c3 100644
--- a/dfall_ws/src/dfall_pkg/include/nodes/CsoneControllerService.h
+++ b/dfall_ws/src/dfall_pkg/include/nodes/CsoneControllerService.h
@@ -68,6 +68,7 @@
 
 // Include the DFALL service types
 #include "dfall_pkg/LoadYamlFromFilename.h"
+#include "dfall_pkg/IntIntService.h"
 #include "dfall_pkg/GetSetpointService.h"
 
 // Include the shared definitions
@@ -107,7 +108,6 @@ using namespace dfall_pkg;
 
 
 
-
 //    ----------------------------------------------------------------------------------
 //    V   V    A    RRRR   III    A    BBBB   L      EEEEE   SSSS
 //    V   V   A A   R   R   I    A A   B   B  L      E      S
@@ -163,13 +163,30 @@ std::vector<float> yaml_gainMatrixRollRate                =  { 0.00,-6.20, 0.00,
 std::vector<float> yaml_gainMatrixPitchRate               =  { 6.20, 0.00, 0.00, 3.00, 0.00, 0.00, 0.00, 5.20, 0.00};
 std::vector<float> yaml_gainMatrixYawRate                 =  { 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 2.30};
 
+// Integrator gains
+float yaml_integratorGain_forThrust = 0.0;
+float yaml_integratorGain_forTauXY  = 0.0;
+float yaml_integratorGain_forTauYaw = 0.0;
+
+// The state of the integrator
+int m_integratorState = INTEGRATOR_FLAG_OFF;
+
+// The current value of the integrator for each axis
+float m_newtons_intergal = 0.0;
+float m_tau_x_integral   = 0.0;
+float m_tau_y_integral   = 0.0;
+float m_tau_z_integral   = 0.0;
+
 
 
 // The weight of the Crazyflie in Newtons, i.e., mg
 float m_cf_weight_in_newtons = 0.0;
 
 // The state space matrices of lead compensator controller
-float m_A=0.0,m_B=0.0,m_C=0.0,m_D=1.0;
+float m_A=0.967216;
+float m_B=0.00491758;
+float m_C=-12;
+float m_D=2;
 
 // The state of lead compensator controller
 float m_controller_state = 0.0;
@@ -190,10 +207,14 @@ std::vector<float>  m_setpoint{0.0,0.0,0.4,0.0};
 // ROS Publisher for debugging variables
 ros::Publisher m_debugPublisher;
 
-// ROS Publisher for inform the network about
-// changes to the setpoin
+// ROS Publisher for informing the network about
+// changes to the setpoint
 ros::Publisher m_setpointChangedPublisher;
 
+// ROS Publisher for informing the network about
+// changes to the integrator state
+ros::Publisher m_integratorStateChangedPublisher;
+
 
 
 
@@ -232,18 +253,27 @@ float computeMotorPolyBackward(float thrust);
 // REQUEST SETPOINT CHANGE CALLBACK
 void requestSetpointChangeCallback(const SetpointWithHeader& newSetpoint);
 
+// CHANGE SETPOINT FUNCTION
+void setNewSetpoint(float x, float y, float z, float yaw);
+
+// GET CURRENT SETPOINT SERVICE CALLBACK
+bool getCurrentSetpointCallback(GetSetpointService::Request &request, GetSetpointService::Response &response);
+
 // REQUEST CONTROLLER PARAMETERS CALLBACK
-void requestControllerParametersCallback(const SetpointWithHeader& newSetpoint);
+void requestIntegratorStateChangeCallback(const IntWithHeader& msg);
 
 // CHANGE SETPOINT FUNCTION
-void setNewSetpoint(float x, float y, float z, float yaw);
+void setNewIntegratorState(int newIntegratorState);
+
+// GET CURRENT INTEGRATOR STATE SERVICE CALLBACK
+bool getCurrentIntegratorStateCallback(IntIntService::Request &request, IntIntService::Response &response);
+
+// REQUEST CONTROLLER PARAMETERS CALLBACK
+void requestControllerParametersCallback(const SetpointWithHeader& newSetpoint);
 
 // CHANGE CONTROLLER PARAMETERS INTO DISCRETE TIME FUNCTION
 void convertIntoDiscreteTimeParameters(float k, float T, float alpha);
 
-// GET CURRENT SETPOINT SERVICE CALLBACK
-bool getCurrentSetpointCallback(GetSetpointService::Request &request, GetSetpointService::Response &response);
-
 // CUSTOM COMMAND RECEIVED CALLBACK
 void customCommandReceivedCallback(const CustomButtonWithHeader& commandReceived);
 
diff --git a/dfall_ws/src/dfall_pkg/param/CsoneController.yaml b/dfall_ws/src/dfall_pkg/param/CsoneController.yaml
index 89076bca..fd02486a 100644
--- a/dfall_ws/src/dfall_pkg/param/CsoneController.yaml
+++ b/dfall_ws/src/dfall_pkg/param/CsoneController.yaml
@@ -1,5 +1,5 @@
 # Mass of the crazyflie
-mass : 28
+mass : 30
 
 # Frequency of the controller, in hertz
 control_frequency : 200
@@ -26,3 +26,8 @@ gainMatrixThrust_NineStateVector    :  [ 0.00, 0.00, 0.98, 0.00, 0.00, 0.25, 0.0
 gainMatrixRollRate                  :  [ 0.00,-1.71, 0.00, 0.00,-1.33, 0.00, 5.12, 0.00, 0.00]
 gainMatrixPitchRate                 :  [ 1.71, 0.00, 0.00, 1.33, 0.00, 0.00, 0.00, 5.12, 0.00]
 gainMatrixYawRate                   :  [ 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 2.30]
+
+# Integrator gains
+integratorGain_forThrust  :  0.10
+integratorGain_forTauXY   :  0.06
+integratorGain_forTauYaw  :  0.05
diff --git a/dfall_ws/src/dfall_pkg/src/nodes/CsoneControllerService.cpp b/dfall_ws/src/dfall_pkg/src/nodes/CsoneControllerService.cpp
index 1f90286f..0e94e7c6 100644
--- a/dfall_ws/src/dfall_pkg/src/nodes/CsoneControllerService.cpp
+++ b/dfall_ws/src/dfall_pkg/src/nodes/CsoneControllerService.cpp
@@ -272,17 +272,28 @@ bool calculateControlOutput(Controller::Request &request, Controller::Response &
 	// > THIRD: perform the inner controller
 	pitchRate_forResponse = 5.0*(pitch_ref-request.ownCrazyflie.pitch);
 
-
-
-	// m_beta_ref = 0.99*m_beta_ref - 1.71/5*stateErrorBody[0] - 1.33/5*m_controller_state;
-	// m_controller_state = -stateErrorBody[0];
-
-
 	// Put the computed body rate commands into the "response" variable
 	response.controlOutput.roll = rollRate_forResponse;
 	response.controlOutput.pitch = pitchRate_forResponse;
 	response.controlOutput.yaw = yawRate_forResponse;
 
+
+
+
+	// PERFORM THE INTEGRATOR COMPUTATIONS
+	if (m_integratorState == INTEGRATOR_FLAG_ON)
+	{
+		m_newtons_intergal   -= yaml_integratorGain_forThrust * stateErrorBody[2] / yaml_control_frequency;
+		m_tau_x_integral     += yaml_integratorGain_forTauXY  * stateErrorBody[1] / yaml_control_frequency;
+		m_tau_y_integral     -= yaml_integratorGain_forTauXY  * stateErrorBody[0] / yaml_control_frequency;
+		m_tau_z_integral     -= yaml_integratorGain_forTauYaw * stateErrorBody[8] / yaml_control_frequency;
+	}
+
+	 float cmd1_integral_adjustments = m_newtons_intergal - m_tau_x_integral - m_tau_y_integral - m_tau_z_integral;
+	 float cmd2_integral_adjustments = m_newtons_intergal - m_tau_x_integral + m_tau_y_integral + m_tau_z_integral;
+	 float cmd3_integral_adjustments = m_newtons_intergal + m_tau_x_integral + m_tau_y_integral - m_tau_z_integral;
+	 float cmd4_integral_adjustments = m_newtons_intergal + m_tau_x_integral - m_tau_y_integral + m_tau_z_integral;
+
 	// Put the thrust commands into the "response" variable.
 	// The thrust adjustment computed by the controller need to be added to the
 	// the feed-forward thrust that "counter-acts" gravity.
@@ -296,10 +307,10 @@ bool calculateControlOutput(Controller::Request &request, Controller::Response &
 	float thrust_request_per_motor = thrustAdjustment / 4.0 + feed_forward_thrust_per_motor;
 	// > NOTE: the function "computeMotorPolyBackward" converts the input argument
 	//         from Newtons to the 16-bit command expected by the Crazyflie.
-	response.controlOutput.motorCmd1 = computeMotorPolyBackward(thrust_request_per_motor);
-	response.controlOutput.motorCmd2 = computeMotorPolyBackward(thrust_request_per_motor);
-	response.controlOutput.motorCmd3 = computeMotorPolyBackward(thrust_request_per_motor);
-	response.controlOutput.motorCmd4 = computeMotorPolyBackward(thrust_request_per_motor);
+	response.controlOutput.motorCmd1 = computeMotorPolyBackward(thrust_request_per_motor + cmd1_integral_adjustments);
+	response.controlOutput.motorCmd2 = computeMotorPolyBackward(thrust_request_per_motor + cmd2_integral_adjustments);
+	response.controlOutput.motorCmd3 = computeMotorPolyBackward(thrust_request_per_motor + cmd3_integral_adjustments);
+	response.controlOutput.motorCmd4 = computeMotorPolyBackward(thrust_request_per_motor + cmd4_integral_adjustments);
 
 	
 	// PREPARE AND RETURN THE VARIABLE "response"
@@ -549,7 +560,6 @@ void requestSetpointChangeCallback(const SetpointWithHeader& newSetpoint)
 	}
 }
 
-
 // CHANGE SETPOINT FUNCTION
 void setNewSetpoint(float x, float y, float z, float yaw)
 {
@@ -574,7 +584,6 @@ void setNewSetpoint(float x, float y, float z, float yaw)
 	m_setpointChangedPublisher.publish(msg);
 }
 
-
 // GET CURRENT SETPOINT SERVICE CALLBACK
 bool getCurrentSetpointCallback(GetSetpointService::Request &request, GetSetpointService::Response &response)
 {
@@ -587,6 +596,93 @@ bool getCurrentSetpointCallback(GetSetpointService::Request &request, GetSetpoin
 	return true;
 }
 
+
+
+
+
+// REQUEST SETPOINT CHANGE CALLBACK
+void requestIntegratorStateChangeCallback(const IntWithHeader& msg)
+{
+	// Check whether the message is relevant
+	bool isRevelant = checkMessageHeader( m_agentID , msg.shouldCheckForAgentID , msg.agentIDs );
+
+	// Continue if the message is relevant
+	if (isRevelant)
+	{
+		// Extract the request change
+		int requested_change = msg.data;
+
+		// Switch between the possible cases
+		switch (requested_change)
+		{
+			case INTEGRATOR_FLAG_ON:
+				setNewIntegratorState(INTEGRATOR_FLAG_ON);
+				break;
+
+			case INTEGRATOR_FLAG_OFF:
+				setNewIntegratorState(INTEGRATOR_FLAG_OFF);
+				break;
+
+			case INTEGRATOR_FLAG_UNKNOWN:
+				ROS_INFO("[CSONE CONTROLLER] Does not respond for the integrator to change to state INTEGRATOR_FLAG_UNKNOWN");
+				break;
+
+			case INTEGRATOR_FLAG_TOGGLE:
+			{
+				if (m_integratorState==INTEGRATOR_FLAG_OFF)
+					setNewIntegratorState(INTEGRATOR_FLAG_ON);
+				else
+					setNewIntegratorState(INTEGRATOR_FLAG_OFF);
+				break;
+			}
+			
+			case INTEGRATOR_FLAG_RESET:
+				// Reset the integrator value to zero
+				m_newtons_intergal = 0.0;
+				m_tau_x_integral   = 0.0;
+				m_tau_y_integral   = 0.0;
+				m_tau_z_integral   = 0.0;
+				// Inform the user
+				ROS_INFO("[CSONE CONTROLLER] integrator values were reset to zero.");
+				break;
+
+			default:
+				ROS_INFO_STREAM("[CSONE CONTROLLER] The requested integrator state change of " << requested_change << " is not recognised.");
+				break;
+		}
+	}
+}
+
+// CHANGE SETPOINT FUNCTION
+void setNewIntegratorState(int newIntegratorState){
+	// Directly set this to the class variable
+	m_integratorState = newIntegratorState;
+
+	// Publish the change so that the network is updated
+	// (mainly the "flying agent GUI" is interested in
+	// displaying this change to the user)
+
+	// Instantiate a local variable of type "IntWithHeader"
+	IntWithHeader msg;
+	// Fill in the integrator state
+	msg.data = m_integratorState;
+	// Publish the message
+	m_integratorStateChangedPublisher.publish(msg);
+}
+
+
+
+
+// GET CURRENT SETPOINT SERVICE CALLBACK
+bool getCurrentIntegratorStateCallback(IntIntService::Request &request, IntIntService::Response &response)
+{
+	// Directly put the current integrator state into the response
+	response.data = m_integratorState;
+	// Return
+	return true;
+}
+
+
 // REQUEST CONTROLLER PARAMETERS CALLBACK
 // Using x y z from SetpointWithHeader for k T alpha controller parameters
 void requestControllerParametersCallback(const SetpointWithHeader& newSetpoint)
@@ -1038,6 +1134,39 @@ int main(int argc, char* argv[]) {
 	ros::ServiceServer getCurrentSetpointService = nodeHandle.advertiseService("GetCurrentSetpoint", getCurrentSetpointCallback);
 
 
+	// Instantiate the local variable:
+	// variable name:    "requestIntegatorStateChangeSubscriber"
+	// variable type:    ros::Subscriber
+	// name of message:  "RequestIntegratorStateChange"
+	// The message has the structure defined in the file:
+	//    "IntWithHeader.msg" (located in the "msg" folder).
+	// The messages received by this subscriber typically come from
+	// the "flying agent GUI".
+	ros::Subscriber requestIntegatorStateChangeSubscriber = nodeHandle.subscribe("RequestIntegratorStateChange", 1, requestIntegratorStateChangeCallback);
+
+	// Instantiate the class variable:
+	// variable name:    "m_integratorStateChangedPublisher"
+	// variable type:    ros::Publisher
+	// name of message:  "IntegratorStateChanged"
+	// The message has the structure defined in the file:
+	//    "IntWithHeader.msg" (located in the "msg" folder).
+	// This publisher is used by the "flying agent GUI" to update the
+	// field that displays the current state of the integator.
+	m_integratorStateChangedPublisher = nodeHandle.advertise<IntWithHeader>("IntegratorStateChanged", 1);
+
+	// Instantiate the local variable:
+	// variable name:    "getCurrentIntegratorStateService"
+	// variable type:    ros::ServiceServer
+	// name of service:  "GetCurrentIntegratorState"
+	// callback funcion: "getCurrentIntegratorStateCallback"
+	// This service has the input-output behaviour defined in the file:
+	//  "IntIntService.srv" (located in the "srv" folder)
+	// This service, when called, is provided with an integer (that is
+	// essentially ignored), and is expected to respond with the current
+	// state of the integrator.
+	ros::ServiceServer getCurrentIntegratorStateService = nodeHandle.advertiseService("GetCurrentIntegratorState", getCurrentIntegratorStateCallback);
+
+
 
     // Instantiate the local variable "service" to be a "ros::ServiceServer" type
     // variable that advertises the service called "CsoneController". This service has
-- 
GitLab