diff --git a/pps_ws/src/d_fall_pps/GUI_Qt/flyingAgentGUI/forms/tuningcontrollertab.ui b/pps_ws/src/d_fall_pps/GUI_Qt/flyingAgentGUI/forms/tuningcontrollertab.ui
index 9db1f6c553be536d00846bc632c537e20c40e56e..28732632ec93dc1d1dba323e5aa054ac505d9da4 100644
--- a/pps_ws/src/d_fall_pps/GUI_Qt/flyingAgentGUI/forms/tuningcontrollertab.ui
+++ b/pps_ws/src/d_fall_pps/GUI_Qt/flyingAgentGUI/forms/tuningcontrollertab.ui
@@ -6,7 +6,7 @@
    <rect>
     <x>0</x>
     <y>0</y>
-    <width>1507</width>
+    <width>1519</width>
     <height>970</height>
    </rect>
   </property>
@@ -162,7 +162,7 @@
           <number>12</number>
          </property>
          <item>
-          <widget class="QLineEdit" name="lineEdit_5">
+          <widget class="QLineEdit" name="lineEdit_error_D">
            <property name="sizePolicy">
             <sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
              <horstretch>0</horstretch>
@@ -258,7 +258,7 @@
           <number>12</number>
          </property>
          <item>
-          <widget class="QLineEdit" name="lineEdit">
+          <widget class="QLineEdit" name="lineEdit_gain_P">
            <property name="sizePolicy">
             <sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
              <horstretch>0</horstretch>
@@ -318,7 +318,7 @@
           <number>12</number>
          </property>
          <item>
-          <widget class="QLineEdit" name="lineEdit_2">
+          <widget class="QLineEdit" name="lineEdit_angle">
            <property name="sizePolicy">
             <sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
              <horstretch>0</horstretch>
@@ -490,7 +490,7 @@
           <number>12</number>
          </property>
          <item>
-          <widget class="QLineEdit" name="lineEdit_4">
+          <widget class="QLineEdit" name="lineEdit_gain_D">
            <property name="sizePolicy">
             <sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
              <horstretch>0</horstretch>
@@ -550,7 +550,7 @@
           <number>12</number>
          </property>
          <item>
-          <widget class="QLineEdit" name="lineEdit_3">
+          <widget class="QLineEdit" name="lineEdit_error_P">
            <property name="sizePolicy">
             <sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
              <horstretch>0</horstretch>
@@ -773,6 +773,23 @@
          </item>
         </layout>
        </item>
+       <item row="3" column="1">
+        <layout class="QHBoxLayout" name="horizontalLayout_15">
+         <property name="leftMargin">
+          <number>12</number>
+         </property>
+         <property name="rightMargin">
+          <number>12</number>
+         </property>
+         <item>
+          <widget class="QLabel" name="label_22">
+           <property name="text">
+            <string>=</string>
+           </property>
+          </widget>
+         </item>
+        </layout>
+       </item>
       </layout>
      </item>
      <item row="11" column="1">
diff --git a/pps_ws/src/d_fall_pps/GUI_Qt/flyingAgentGUI/include/tuningcontrollertab.h b/pps_ws/src/d_fall_pps/GUI_Qt/flyingAgentGUI/include/tuningcontrollertab.h
index d296d0bb573a186106ec002a691af377ba9b26d1..77738088fe6cf24ecc2826541f1abf49e1bc7c2b 100644
--- a/pps_ws/src/d_fall_pps/GUI_Qt/flyingAgentGUI/include/tuningcontrollertab.h
+++ b/pps_ws/src/d_fall_pps/GUI_Qt/flyingAgentGUI/include/tuningcontrollertab.h
@@ -2,6 +2,64 @@
 #define TUNINGCONTROLLERTAB_H
 
 #include <QWidget>
+#include <QMutex>
+#include <QVector>
+#include <QLineEdit>
+#include <QTextStream>
+
+#ifdef CATKIN_MAKE
+#include <ros/ros.h>
+#include <ros/network.h>
+#include <ros/package.h>
+
+// Include the standard message types
+//#include "std_msgs/Int32.h"
+//#include "std_msgs/Float32.h"
+//#include <std_msgs/String.h>
+
+// Include the DFALL message types
+//#include "d_fall_pps/IntWithHeader.h"
+#include "d_fall_pps/FloatWithHeader.h"
+#include "d_fall_pps/SetpointWithHeader.h"
+#include "d_fall_pps/CustomButtonWithHeader.h"
+
+// Include the DFALL service types
+#include "d_fall_pps/GetSetpointService.h"
+
+// Include the shared definitions
+#include "nodes/Constants.h"
+
+// SPECIFY THE PACKAGE NAMESPACE
+//using namespace d_fall_pps;
+
+#else
+// Include the shared definitions
+#include "include/Constants_for_Qt_compile.h"
+
+#endif
+
+
+#define P_GAIN_MIN_GUI  1
+#define P_GAIN_MAX_GUI  10
+#define P_TO_D_GAIN_RATIO_GUI 0.4
+
+#define DECIMAL_PLACES_POSITION_MEASURED 3
+#define DECIMAL_PLACES_ANGLE_DEGREES 1
+#define DECIMAL_PLACES_VELOCITY 2
+#define DECIMAL_PLACES_GAIN 2
+
+#define DECIMAL_PLACES_SETPOINT 2
+
+#define SETPOINT_X_MINUS -0.25
+#define SETPOINT_X_PLUS   0.25
+
+#define SETPOINT_Y  0.0
+#define SETPOINT_Z  0.4
+#define SETPOINT_YAW_DEGREES  0.0
+
+#define MEASUREMENT_FRQUENCY 200.0
+
+
 
 namespace Ui {
 class TuningControllerTab;
@@ -15,6 +73,15 @@ public:
     explicit TuningControllerTab(QWidget *parent = 0);
     ~TuningControllerTab();
 
+
+
+public slots:
+    void setAgentIDsToCoordinate(QVector<int> agentIDs , bool shouldCoordinateAll);
+    void setMeasuredPose(float x , float y , float z , float roll , float pitch , float yaw , bool occluded);
+    void poseDataUnavailableSlot();
+
+
+
 private slots:
     void on_button_setpoint_toggle_clicked();
 
@@ -22,8 +89,80 @@ private slots:
 
     void on_slider_gain_P_valueChanged(int value);
 
+
+
 private:
     Ui::TuningControllerTab *ui;
+
+    // --------------------------------------------------- //
+        // PRIVATE VARIABLES
+
+        // The type of this node, i.e., agent or a coordinator,
+        // specified as a parameter in the "*.launch" file
+        int m_type = 0;
+
+        // The ID  of this node
+        int m_ID;
+
+        // For coordinating multiple agents
+        std::vector<int> m_vector_of_agentIDs_toCoordinate;
+        bool m_shouldCoordinateAll = true;
+        QMutex m_agentIDs_toCoordinate_mutex;
+
+
+
+        float m_gain_P = 0.0;
+        float m_gain_D = 0.0;
+
+        float m_current_setpoint = 0.0;
+
+        QMutex m_gain_setpoint_mutex;
+
+        float m_x_previous = 0.0;
+
+
+
+    #ifdef CATKIN_MAKE
+        // PUBLISHER
+        // > For requesting the setpoint to be changed
+        ros::Publisher requestSetpointChangePublisher;
+
+        // SUBSCRIBER
+        // > For being notified when the setpoint is changed
+        ros::Subscriber setpointChangedSubscriber;
+
+        // PUBLISHER
+        // > For notifying the P gain is changed
+        ros::Publisher requestNewGainChangePublisher;
+
+        // PUBLISHER
+        // > For notifying that a custom button is pressed
+        //ros::Publisher customButtonPublisher;
+    #endif
+
+        // --------------------------------------------------- //
+        // PRIVATE FUNCTIONS
+
+
+    #ifdef CATKIN_MAKE
+        // For receiving message that the setpoint was changed
+        void setpointChangedCallback(const d_fall_pps::SetpointWithHeader& newSetpoint);
+
+        // Publish a message when a custom button is pressed
+        //void publish_custom_button_command(int button_index , QLineEdit * lineEdit_pointer);
+
+        // Fill the header for a message
+        void fillSetpointMessageHeader( d_fall_pps::SetpointWithHeader & msg );
+        void fillFloatMessageHeader( d_fall_pps::FloatWithHeader & msg );
+
+        // Get the paramters that specify the type and ID
+        bool getTypeAndIDParameters();
+    #endif
+
+        void publishSetpoint(float x, float y, float z, float yaw);
+
+        void publishGain(float new_gain);
+
 };
 
 #endif // TUNINGCONTROLLERTAB_H
diff --git a/pps_ws/src/d_fall_pps/GUI_Qt/flyingAgentGUI/src/tuningcontrollertab.cpp b/pps_ws/src/d_fall_pps/GUI_Qt/flyingAgentGUI/src/tuningcontrollertab.cpp
index 801865ddde106ad50d89c6c5f412f2256ba99904..7fa20851f61bfe97316799391ac0e98c46ca3768 100644
--- a/pps_ws/src/d_fall_pps/GUI_Qt/flyingAgentGUI/src/tuningcontrollertab.cpp
+++ b/pps_ws/src/d_fall_pps/GUI_Qt/flyingAgentGUI/src/tuningcontrollertab.cpp
@@ -6,6 +6,80 @@ TuningControllerTab::TuningControllerTab(QWidget *parent) :
     ui(new Ui::TuningControllerTab)
 {
     ui->setupUi(this);
+
+    // Set the gain field
+    int starting_slider_value = ui->slider_gain_P->value();
+    float slider_ratio = float(starting_slider_value) / 1000.0;
+
+    m_gain_P = P_GAIN_MIN_GUI + slider_ratio * (P_GAIN_MAX_GUI-P_GAIN_MIN_GUI);
+    m_gain_D = m_gain_P * P_TO_D_GAIN_RATIO_GUI;
+
+    ui->lineEdit_gain_P->setText( QString::number( m_gain_P, 'f', DECIMAL_PLACES_GAIN) );
+    ui->lineEdit_gain_D->setText( QString::number( m_gain_D, 'f', DECIMAL_PLACES_GAIN) );
+
+    ui->lineEdit_setpoint->setText( QString::number( m_current_setpoint, 'f', DECIMAL_PLACES_SETPOINT) );
+
+
+#ifdef CATKIN_MAKE
+
+    //ros::init();
+
+    // Get the namespace of this node
+    std::string this_namespace = ros::this_node::getNamespace();
+    ROS_INFO_STREAM("[TUNING CONTROLLER TAB GUI] ros::this_node::getNamespace() =  " << this_namespace);
+
+    // Get the type and ID of this flying agent GUI
+    bool isValid_type_and_ID = getTypeAndIDParameters();
+
+    // Stall if the node IDs are not valid
+    if ( !isValid_type_and_ID )
+    {
+        ROS_ERROR("[TUNING CONTROLLER TAB GUI] Node NOT FUNCTIONING :-)");
+        ros::spin();
+    }
+
+
+    // CREATE A NODE HANDLE TO THIS GUI
+    ros::NodeHandle nodeHandle_for_this_gui(this_namespace);
+
+    // CREATE THE REQUEST SETPOINT CHANGE PUBLISHER
+    requestSetpointChangePublisher = nodeHandle_for_this_gui.advertise<d_fall_pps::SetpointWithHeader>("TuningControllerService/RequestSetpointChange", 1);
+
+    // SUBSCRIBE TO SETPOINT CHANGES
+    // Only if this is an agent GUI
+    if (m_type == TYPE_AGENT)
+    {
+        setpointChangedSubscriber = nodeHandle_for_this_gui.subscribe("TuningControllerService/SetpointChanged", 1, &TuningControllerTab::setpointChangedCallback, this);
+    }
+
+
+    // CREATE THE NEW GAIN PUBLISHER
+    requestNewGainChangePublisher = nodeHandle_for_this_gui.advertise<d_fall_pps::FloatWithHeader>("TuningControllerService/RequestGainChange", 1);
+
+    // CREATE THE CUSTOM BUTTON PRESSED PUBLISHER
+    //customButtonPublisher = nodeHandle_for_this_gui.advertise<d_fall_pps::CustomButtonWithHeader>("TuningControllerService/CustomButtonPressed", 1);
+
+    // GET THE CURRENT SETPOINT
+    // Only if this is an agent GUI
+    if (m_type == TYPE_AGENT)
+    {
+//        // > Request the current setpoint
+//        ros::ServiceClient getCurrentSetpointServiceClient = nodeHandle_for_this_gui.serviceClient<d_fall_pps::GetSetpointService>("TuningControllerService/GetCurrentSetpoint", false);
+//        d_fall_pps::GetSetpointService getSetpointCall;
+//        getSetpointCall.request.data = 0;
+//        getCurrentSetpointServiceClient.waitForExistence(ros::Duration(2.0));
+//        if(getCurrentSetpointServiceClient.call(getSetpointCall))
+//        {
+//            setpointChangedCallback(getSetpointCall.response.setpointWithHeader);
+//        }
+//        else
+//        {
+//            // Inform the user
+//            ROS_INFO("[TUNING CONTROLLER GUI] Failed to get setpoint from controller using the \"GetCurrentSetpoint\" service");
+//        }
+    }
+
+#endif
 }
 
 TuningControllerTab::~TuningControllerTab()
@@ -13,17 +87,587 @@ TuningControllerTab::~TuningControllerTab()
     delete ui;
 }
 
+
+
+//    ----------------------------------------------------------------------------------
+//    PPPP    OOO    SSSS  EEEEE     DDDD     A    TTTTT    A
+//    P   P  O   O  S      E         D   D   A A     T     A A
+//    PPPP   O   O   SSS   EEE       D   D  A   A    T    A   A
+//    P      O   O      S  E         D   D  AAAAA    T    AAAAA
+//    P       OOO   SSSS   EEEEE     DDDD   A   A    T    A   A
+//    ----------------------------------------------------------------------------------
+
+
+void TuningControllerTab::setMeasuredPose(float x , float y , float z , float roll , float pitch , float yaw , bool occluded)
+{
+    if (!occluded)
+    {
+        m_gain_setpoint_mutex.lock();
+
+        // INITIALISE A STRING VARIABLE FOR ADDING THE "+"
+        QString qstr = "";
+
+        // PUT IN THE POSITION ERROR
+        float error_x = x - m_current_setpoint;
+        ui->lineEdit_error_P->setText( QString::number( error_x, 'f', DECIMAL_PLACES_POSITION_MEASURED) );
+
+        // COMPUTE AND PUT IN THE VELOCITY
+        float velocity_x = (x - m_x_previous) * MEASUREMENT_FRQUENCY;
+        m_x_previous = x;
+        ui->lineEdit_error_D->setText( QString::number( velocity_x, 'f', DECIMAL_PLACES_VELOCITY) );
+
+        // COMPUTE AND PUT IN THE ANGLE
+        float angle = (m_gain_P * error_x + m_gain_D * velocity_x) * RAD2DEG;
+        ui->lineEdit_angle->setText( QString::number( angle, 'f', DECIMAL_PLACES_ANGLE_DEGREES) );
+
+        m_gain_setpoint_mutex.unlock();
+
+//        // UPDATE THE MEASUREMENT COLUMN
+//        if (x < 0.0f) qstr = ""; else qstr = "+";
+//        ui->lineEdit_measured_x->setText(qstr + QString::number( x, 'f', 3));
+//        if (y < 0.0f) qstr = ""; else qstr = "+";
+//        ui->lineEdit_measured_y->setText(qstr + QString::number( y, 'f', 3));
+//        if (z < 0.0f) qstr = ""; else qstr = "+";
+//        ui->lineEdit_measured_z->setText(qstr + QString::number( z, 'f', 3));
+
+//        if (roll < 0.0f) qstr = ""; else qstr = "+";
+//        ui->lineEdit_measured_roll->setText(qstr + QString::number( roll  * RAD2DEG, 'f', 1));
+//        if (pitch < 0.0f) qstr = ""; else qstr = "+";
+//        ui->lineEdit_measured_pitch->setText(qstr + QString::number( pitch * RAD2DEG, 'f', 1));
+//        if (yaw < 0.0f) qstr = ""; else qstr = "+";
+//        ui->lineEdit_measured_yaw->setText(qstr + QString::number( yaw   * RAD2DEG, 'f', 1));
+
+//        // GET THE CURRENT SETPOINT
+//        float error_x   = x   - (ui->lineEdit_setpoint_current_x->text()  ).toFloat();
+//        float error_y   = y   - (ui->lineEdit_setpoint_current_y->text()  ).toFloat();
+//        float error_z   = z   - (ui->lineEdit_setpoint_current_z->text()  ).toFloat();
+//        float error_yaw = yaw - (ui->lineEdit_setpoint_current_yaw->text()).toFloat();
+
+//        // UPDATE THE ERROR COLUMN
+//        if (error_x < 0.0f) qstr = ""; else qstr = "+";
+//        ui->lineEdit_error_x->setText(qstr + QString::number( error_x, 'f', 3));
+//        if (error_y < 0.0f) qstr = ""; else qstr = "+";
+//        ui->lineEdit_error_y->setText(qstr + QString::number( error_y, 'f', 3));
+//        if (error_z < 0.0f) qstr = ""; else qstr = "+";
+//        ui->lineEdit_error_z->setText(qstr + QString::number( error_z, 'f', 3));
+
+//        if (error_yaw < 0.0f) qstr = ""; else qstr = "+";
+//        ui->lineEdit_error_yaw->setText(qstr + QString::number( error_yaw * RAD2DEG, 'f', 1));
+
+//        // Ensure the red frames are not visible
+//        if ( ui->red_frame_position_left->isVisible() )
+//            ui->red_frame_position_left->setVisible(false);
+//        if ( ui->red_frame_position_right->isVisible() )
+//            ui->red_frame_position_right->setVisible(false);
+    }
+    else
+    {
+//        // Make visible the red frames to indicate occluded
+//        if ( !(ui->red_frame_position_left->isVisible()) )
+//            ui->red_frame_position_left->setVisible(true);
+//        if ( !(ui->red_frame_position_right->isVisible()) )
+//            ui->red_frame_position_right->setVisible(true);
+    }
+}
+
+
+void TuningControllerTab::poseDataUnavailableSlot()
+{
+    ui->lineEdit_angle->setText("xx.xx");
+    ui->lineEdit_error_P->setText("xx.xx");
+    ui->lineEdit_error_D->setText("xx.xx");
+}
+
+
+
+//    ----------------------------------------------------------------------------------
+//     SSSS  EEEEE  TTTTT  PPPP    OOO   III  N   N  TTTTT
+//    S      E        T    P   P  O   O   I   NN  N    T
+//     SSS   EEE      T    PPPP   O   O   I   N N N    T
+//        S  E        T    P      O   O   I   N  NN    T
+//    SSSS   EEEEE    T    P       OOO   III  N   N    T
+//
+//     CCCC  H   H    A    N   N   GGGG  EEEEE  DDDD
+//    C      H   H   A A   NN  N  G      E      D   D
+//    C      HHHHH  A   A  N N N  G      EEE    D   D
+//    C      H   H  AAAAA  N  NN  G   G  E      D   D
+//     CCCC  H   H  A   A  N   N   GGGG  EEEEE  DDDD
+//
+//     CCCC    A    L      L      BBBB     A     CCCC  K   K
+//    C       A A   L      L      B   B   A A   C      K  K
+//    C      A   A  L      L      BBBB   A   A  C      KKK
+//    C      AAAAA  L      L      B   B  AAAAA  C      K  K
+//     CCCC  A   A  LLLLL  LLLLL  BBBB   A   A   CCCC  K   K
+//    ----------------------------------------------------------------------------------
+
+
+#ifdef CATKIN_MAKE
+void TuningControllerTab::setpointChangedCallback(const d_fall_pps::SetpointWithHeader& newSetpoint)
+{
+//    // INITIALISE A STRING VARIABLE FOR ADDING THE "+"
+//    QString qstr = "";
+
+//    // EXTRACT THE SETPOINT
+//    float x = newSetpoint.x;
+//    float y = newSetpoint.y;
+//    float z = newSetpoint.z;
+//    float yaw = newSetpoint.yaw;
+
+//    // UPDATE THE SETPOINT COLUMN
+//    if (x < 0.0f) qstr = ""; else qstr = "+";
+//    ui->lineEdit_setpoint_current_x->setText(qstr + QString::number( x, 'f', 3));
+//    if (y < 0.0f) qstr = ""; else qstr = "+";
+//    ui->lineEdit_setpoint_current_y->setText(qstr + QString::number( y, 'f', 3));
+//    if (z < 0.0f) qstr = ""; else qstr = "+";
+//    ui->lineEdit_setpoint_current_z->setText(qstr + QString::number( z, 'f', 3));
+
+//    if (yaw < 0.0f) qstr = ""; else qstr = "+";
+//    ui->lineEdit_setpoint_current_yaw->setText(qstr + QString::number( yaw * RAD2DEG, 'f', 3));
+}
+#endif
+
+
+
+
+
+
+
+
+
+
+//    ----------------------------------------------------------------------------------
+//    RRRR   EEEEE   QQQ   U   U  EEEEE   SSSS  TTTTT     N   N  EEEEE  W     W
+//    R   R  E      Q   Q  U   U  E      S        T       NN  N  E      W     W
+//    RRRR   EEE    Q   Q  U   U  EEE     SSS     T       N N N  EEE    W     W
+//    R   R  E      Q  Q   U   U  E          S    T       N  NN  E       W W W
+//    R   R  EEEEE   QQ Q   UUU   EEEEE  SSSS     T       N   N  EEEEE    W W
+//
+//     SSSS  EEEEE  TTTTT  PPPP    OOO   III  N   N  TTTTT
+//    S      E        T    P   P  O   O   I   NN  N    T
+//     SSS   EEE      T    PPPP   O   O   I   N N N    T
+//        S  E        T    P      O   O   I   N  NN    T
+//    SSSS   EEEEE    T    P       OOO   III  N   N    T
+//    ----------------------------------------------------------------------------------
+
+
+void TuningControllerTab::publishSetpoint(float x, float y, float z, float yaw)
+{
+#ifdef CATKIN_MAKE
+    // Initialise the message as a local variable
+    d_fall_pps::SetpointWithHeader msg;
+
+    // Fill the header of the message
+    fillSetpointMessageHeader( msg );
+
+    // Fill in the (x,y,z,yaw) values
+    msg.x   = x;
+    msg.y   = y;
+    msg.z   = z;
+    msg.yaw = yaw * DEG2RAD;
+
+    // Publish the setpoint
+    this->requestSetpointChangePublisher.publish(msg);
+
+    // Inform the user about the change
+    ROS_INFO_STREAM("[TUNING CONTROLLER GUI] Published request for setpoint change to: [" << x << ", "<< y << ", "<< z << ", "<< yaw << "]");
+#else
+    // TO ASSIST WITH DEBUGGING WHEN COMPILED AND RUN IN "QtCreator"
+    QTextStream(stdout) << "[TUNING CONTROLLER GUI] would publish request for: [" << x << ", "<< y << ", "<< z << ", "<< yaw << "]";
+#endif
+}
+
+
+
+
+
 void TuningControllerTab::on_button_setpoint_toggle_clicked()
 {
 
+    m_gain_setpoint_mutex.lock();
+
+    float setpoint_copy = m_current_setpoint;
+    float new_setpoint = 0.0;
+
+    if (setpoint_copy < SETPOINT_X_MINUS)
+        new_setpoint = SETPOINT_X_MINUS;
+    else if (setpoint_copy < 0.0)
+        new_setpoint = SETPOINT_X_PLUS;
+    else if (setpoint_copy > SETPOINT_X_PLUS)
+        new_setpoint = SETPOINT_X_PLUS;
+    else
+        new_setpoint = SETPOINT_X_MINUS;
+
+    ui->lineEdit_setpoint->setText( QString::number( new_setpoint, 'f', DECIMAL_PLACES_SETPOINT) );
+    float lineEdit_as_float_rounded = (ui->lineEdit_setpoint->text()).toFloat();
+    m_current_setpoint = lineEdit_as_float_rounded;
+    publishSetpoint( m_current_setpoint, SETPOINT_Y, SETPOINT_Z, SETPOINT_YAW_DEGREES);
+
+    m_gain_setpoint_mutex.unlock();
+
 }
 
 void TuningControllerTab::on_lineEdit_setpoint_editingFinished()
 {
+    m_gain_setpoint_mutex.lock();
+
+
+    // Get the line edit data, as a float if possible
+    bool isValidFloat = false;
+    float lineEdit_as_float = (ui->lineEdit_setpoint->text()).toFloat(&isValidFloat);
+
+    // Fill in the data
+    if (isValidFloat)
+    {
+        ui->lineEdit_setpoint->setText( QString::number( lineEdit_as_float, 'f', DECIMAL_PLACES_SETPOINT) );
+        float lineEdit_as_float_rounded = (ui->lineEdit_setpoint->text()).toFloat();
+        m_current_setpoint = lineEdit_as_float_rounded;
+        publishSetpoint( m_current_setpoint, SETPOINT_Y, SETPOINT_Z, SETPOINT_YAW_DEGREES);
+    }
+    else
+    {
+        ui->lineEdit_setpoint->setText( QString::number( m_current_setpoint, 'f', DECIMAL_PLACES_SETPOINT) );
+    }
+    m_gain_setpoint_mutex.unlock();
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+void TuningControllerTab::publishGain(float new_gain)
+{
+#ifdef CATKIN_MAKE
+    // Initialise the message as a local variable
+    d_fall_pps::FloatWithHeader msg;
+
+    // Fill the header of the message
+    fillSetpointMessageHeader( msg );
 
+    // Fill in the gain value
+    msg.data = new_gain;
+
+    // Publish the setpoint
+    this->requestNewGainChangePublisher.publish(msg);
+
+    // Inform the user about the change
+    ROS_INFO_STREAM("[TUNING CONTROLLER GUI] Published request for gain change to: " << new_gain );
+#else
+    // TO ASSIST WITH DEBUGGING WHEN COMPILED AND RUN IN "QtCreator"
+    QTextStream(stdout) << "[TUNING CONTROLLER GUI] would publish gain value: " << new_gain;
+#endif
 }
 
+
 void TuningControllerTab::on_slider_gain_P_valueChanged(int value)
 {
 
+    m_gain_setpoint_mutex.lock();
+
+    float slider_ratio = float(value) / 1000.0;
+
+    float new_gain_P = P_GAIN_MIN_GUI + slider_ratio * (P_GAIN_MAX_GUI-P_GAIN_MIN_GUI);
+    float new_gain_D = new_gain_P * P_TO_D_GAIN_RATIO_GUI;
+
+    ui->lineEdit_gain_P->setText( QString::number( new_gain_P, 'f', DECIMAL_PLACES_GAIN) );
+    ui->lineEdit_gain_D->setText( QString::number( new_gain_D, 'f', DECIMAL_PLACES_GAIN) );
+
+    float gain_P_rounded = (ui->lineEdit_gain_P->text()).toFloat();
+    float gain_D_rounded = (ui->lineEdit_gain_D->text()).toFloat();
+
+    m_gain_P = gain_P_rounded;
+    m_gain_D = gain_D_rounded;
+
+    publishGain(m_gain_P);
+
+    m_gain_setpoint_mutex.unlock();
+
+}
+
+
+
+
+
+
+
+//    ----------------------------------------------------------------------------------
+//      A     GGGG  EEEEE  N   N  TTTTT     III  DDDD    SSSS
+//     A A   G      E      NN  N    T        I   D   D  S
+//    A   A  G      EEE    N N N    T        I   D   D   SSS
+//    AAAAA  G   G  E      N  NN    T        I   D   D      S
+//    A   A   GGGG  EEEEE  N   N    T       III  DDDD   SSSS
+//    ----------------------------------------------------------------------------------
+
+
+void TuningControllerTab::setAgentIDsToCoordinate(QVector<int> agentIDs , bool shouldCoordinateAll)
+{
+
+    // Lock the mutex
+    m_agentIDs_toCoordinate_mutex.lock();
+    // Add the "coordinate all" flag
+    m_shouldCoordinateAll = shouldCoordinateAll;
+    // Clear the previous list of agent IDs
+    m_vector_of_agentIDs_toCoordinate.clear();
+    // Copy across the agent IDs, if necessary
+    if (!shouldCoordinateAll)
+    {
+        for ( int irow = 0 ; irow < agentIDs.length() ; irow++ )
+        {
+            m_vector_of_agentIDs_toCoordinate.push_back( agentIDs[irow] );
+        }
+    }
+    // Unlock the mutex
+    m_agentIDs_toCoordinate_mutex.unlock();
+
+
+#ifdef CATKIN_MAKE
+    // If there is only one agent to coordinate,
+    // then subscribe to the relevant data
+    if (agentIDs.length() == 1)
+    {
+
+//        // // > Create the appropriate node handle
+//        QString agent_base_namespace = "/dfall/agent" + QString::number(agentIDs[0]).rightJustified(3, '0');
+//        ros::NodeHandle agent_base_nodeHandle(agent_base_namespace.toStdString());
+
+//        // // > Request the current setpoint
+//        ros::ServiceClient getCurrentSetpointServiceClient = agent_base_nodeHandle.serviceClient<d_fall_pps::GetSetpointService>("TuningControllerService/GetCurrentSetpoint", false);
+//        d_fall_pps::GetSetpointService getSetpointCall;
+//        getSetpointCall.request.data = 0;
+//        getCurrentSetpointServiceClient.waitForExistence(ros::Duration(2.0));
+//        if(getCurrentSetpointServiceClient.call(getSetpointCall))
+//        {
+//            setpointChangedCallback(getSetpointCall.response.setpointWithHeader);
+//        }
+//        else
+//        {
+//            // Inform the user
+//            ROS_INFO("[TUNING CONTROLLER GUI] Failed to get setpoint from controller using the \"GetCurrentSetpoint\" service");
+//        }
+
+//        // SUBSCRIBERS
+//        // > For receiving message that the setpoint was changed
+//        setpointChangedSubscriber = agent_base_nodeHandle.subscribe("TuningControllerService/SetpointChanged", 1, &TuningControllerTab::setpointChangedCallback, this);
+    }
+    else
+    {
+        // Unsubscribe
+        setpointChangedSubscriber.shutdown();
+
+        // 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");
+
+    }
+#endif
+}
+
+
+
+
+
+
+//    ----------------------------------------------------------------------------------
+//    M   M   SSSS   GGG      H   H  EEEEE    A    DDDD   EEEEE  RRRR
+//    MM MM  S      G   G     H   H  E       A A   D   D  E      R   R
+//    M M M   SSS   G         HHHHH  EEE    A   A  D   D  EEE    RRRR
+//    M   M      S  G   G     H   H  E      AAAAA  D   D  E      R   R
+//    M   M  SSSS    GGGG     H   H  EEEEE  A   A  DDDD   EEEEE  R   R
+//    ----------------------------------------------------------------------------------
+
+
+
+#ifdef CATKIN_MAKE
+// Fill the header for a message
+void TuningControllerTab::fillSetpointMessageHeader( d_fall_pps::SetpointWithHeader & 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("[TUNING CONTROLLER TAB GUI] The 'm_type' variable was not recognised.");
+            break;
+        }
+    }
+}
+#endif
+
+
+
+#ifdef CATKIN_MAKE
+// Fill the header for a message
+void TuningControllerTab::fillFloatMessageHeader( d_fall_pps::FloatWithHeader & 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("[TUNING CONTROLLER TAB GUI] The 'm_type' variable was not recognised.");
+            break;
+        }
+    }
+}
+#endif
+
+
+
+
+
+//    ----------------------------------------------------------------------------------
+//    III  DDDD       &&&      TTTTT  Y   Y  PPPP   EEEEE
+//     I   D   D     &           T     Y Y   P   P  E
+//     I   D   D      &          T      Y    PPPP   EEE
+//     I   D   D     & & &       T      Y    P      E
+//    III  DDDD       &&&        T      Y    P      EEEEE
+//    ----------------------------------------------------------------------------------
+
+
+
+#ifdef CATKIN_MAKE
+bool TuningControllerTab::getTypeAndIDParameters()
+{
+    // Initialise the return variable as success
+    bool return_was_successful = true;
+
+    // Create a "ros::NodeHandle" type local variable "nodeHandle" as the current node,
+    // the "~" indcates that "self" is the node handle assigned to this variable.
+    ros::NodeHandle nodeHandle("~");
+
+    // Get the value of the "type" parameter into a local string variable
+    std::string type_string;
+    if(!nodeHandle.getParam("type", type_string))
+    {
+        // Throw an error if the agent ID parameter could not be obtained
+        ROS_ERROR("[TUNING CONTROLLER TAB GUI] Failed to get type");
+    }
+
+    // Set the "m_type" class variable based on this string loaded
+    if ((!type_string.compare("coordinator")))
+    {
+        m_type = TYPE_COORDINATOR;
+    }
+    else if ((!type_string.compare("agent")))
+    {
+        m_type = TYPE_AGENT;
+    }
+    else
+    {
+        // Set "m_type" to the value indicating that it is invlid
+        m_type = TYPE_INVALID;
+        return_was_successful = false;
+        ROS_ERROR("[TUNING CONTROLLER TAB GUI] The 'type' parameter retrieved was not recognised.");
+    }
+
+
+    // Construct the string to the namespace of this Paramater Service
+    switch (m_type)
+    {
+        case TYPE_AGENT:
+        {
+            // Get the value of the "agentID" parameter into the class variable "m_Id"
+            if(!nodeHandle.getParam("agentID", m_ID))
+            {
+                // Throw an error if the agent ID parameter could not be obtained
+                return_was_successful = false;
+                ROS_ERROR("[TUNING CONTROLLER TAB GUI] Failed to get agentID");
+            }
+            else
+            {
+                // Inform the user about the type and ID
+                ROS_INFO_STREAM("[TUNING CONTROLLER TAB GUI] Is of type AGENT with ID = " << m_ID);
+            }
+            break;
+        }
+
+        // A COORDINATOR TYPE PARAMETER SERVICE IS REQUESTED FROM:
+        // > The master GUI
+        case TYPE_COORDINATOR:
+        {
+            // Get the value of the "coordID" parameter into the class variable "m_Id"
+            if(!nodeHandle.getParam("coordID", m_ID))
+            {
+                // Throw an error if the coord ID parameter could not be obtained
+                return_was_successful = false;
+                ROS_ERROR("[TUNING CONTROLLER TAB GUI] Failed to get coordID");
+            }
+            else
+            {
+                // Inform the user about the type and ID
+                ROS_INFO_STREAM("[TUNING CONTROLLER TAB GUI] Is of type COORDINATOR with ID = " << m_ID);
+            }
+            break;
+        }
+
+        default:
+        {
+            // Throw an error if the type is not recognised
+            return_was_successful = false;
+            ROS_ERROR("[TUNING CONTROLLER TAB GUI] The 'm_type' variable was not recognised.");
+            break;
+        }
+    }
+
+    // Return
+    return return_was_successful;
 }
+#endif