From 9feb9547ebf24f7e9bf132f86ce818996ed3ac4d Mon Sep 17 00:00:00 2001
From: Jeremiah the Great <jcoulson@ethz.ch>
Date: Wed, 30 Nov 2022 11:39:44 +0100
Subject: [PATCH] Changes to CS1 controller for HS2022 sesssion

---
 .../forms/csonecontrollertab.ui               |  8 +-
 .../flyingAgentGUI/src/csonecontrollertab.cpp | 92 ++++++++++++-------
 .../include/nodes/CsoneControllerService.h    | 29 ++++--
 .../src/nodes/CsoneControllerService.cpp      | 44 +++++----
 4 files changed, 106 insertions(+), 67 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 09e4b6dc..8ec251bd 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
@@ -698,7 +698,7 @@
           </font>
          </property>
          <property name="text">
-          <string>0.5</string>
+          <string>0.50</string>
          </property>
          <property name="alignment">
           <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
@@ -1046,7 +1046,7 @@
             </font>
            </property>
            <property name="text">
-            <string>0.10</string>
+            <string>0.50</string>
            </property>
            <property name="alignment">
             <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
@@ -1105,7 +1105,7 @@
             </font>
            </property>
            <property name="text">
-            <string>0.0160</string>
+            <string>0.1000</string>
            </property>
            <property name="alignment">
             <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
@@ -1132,7 +1132,7 @@
             </font>
            </property>
            <property name="text">
-            <string>4.00</string>
+            <string>1.00</string>
            </property>
            <property name="alignment">
             <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
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 370e192a..9de2c40f 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
@@ -287,7 +287,7 @@ float CsoneControllerTab::validate_and_get_value_from_lineEdit(QLineEdit * lineE
     if(!lineEdit->text().isEmpty())
     {
         return_value = (lineEdit->text()).toFloat();
-        // Ensure that it is in the range [2,60]
+        // Ensure that it is in the range [min,max]
         if (return_value < min)
             return_value = min;
         else if (return_value > max)
@@ -336,7 +336,7 @@ void CsoneControllerTab::on_perform_step_button_clicked()
     ui->chartView_for_pitch->chart()->axisX()->setMin(m_time_for_step);
 
     // Update the duration from the field
-    m_step_response_data_recording_duration = validate_and_get_value_from_lineEdit(ui->lineEdit_step_duration,2.0,40.0,0,20.0);
+    m_step_response_data_recording_duration = validate_and_get_value_from_lineEdit(ui->lineEdit_step_duration,1.0,100.0,0,20.0);
 
     // Set the minimum of the x-axis to agree with the duration
     ui->chartView_for_x    ->chart()->axisX()->setMax(m_step_response_data_recording_duration);
@@ -390,7 +390,7 @@ void CsoneControllerTab::on_log_data_button_clicked()
     ui->chartView_for_pitch->chart()->axisX()->setMin(m_time_for_step);
 
     // Update the duration from the field
-    m_step_response_data_recording_duration = validate_and_get_value_from_lineEdit(ui->lineEdit_step_duration,2.0,40.0,0,20.0);
+    m_step_response_data_recording_duration = validate_and_get_value_from_lineEdit(ui->lineEdit_step_duration,1.0,100.0,0,20.0);
 
     // Set the minimum of the x-axis to agree with the duration
     ui->chartView_for_x    ->chart()->axisX()->setMax(m_step_response_data_recording_duration);
@@ -508,13 +508,13 @@ void CsoneControllerTab::on_set_lead_compensator_parameters_button_clicked()
 
     // Take the new value if available, otherwise use default
     // > For k
-    k = validate_and_get_value_from_lineEdit(ui->lineEdit_k,-100.0,100.0,4,0.016);
+    k = validate_and_get_value_from_lineEdit(ui->lineEdit_k,-1000.0,1000.0,4,0.1);
 
     // > For T
-    T = validate_and_get_value_from_lineEdit(ui->lineEdit_T,0.0,100.0,2,4.0);
+    T = validate_and_get_value_from_lineEdit(ui->lineEdit_T,0.0,1000.0,2,1.0);
 
     // > For alpha
-    alpha = validate_and_get_value_from_lineEdit(ui->lineEdit_alpha,0.1,1.0,2,0.1);
+    alpha = validate_and_get_value_from_lineEdit(ui->lineEdit_alpha,0.0,1.0,2,0.5);
 
     // Unlock the mutex
     m_controller_parameter_mutex.unlock();
@@ -532,10 +532,10 @@ void CsoneControllerTab::on_set_lag_compensator_parameters_button_clicked()
     m_lag_controller_parameter_mutex.lock();
 
     // > For T
-    T = validate_and_get_value_from_lineEdit(ui->lineEdit_T_lag,0.0,100.0,2,0.0);
+    T = validate_and_get_value_from_lineEdit(ui->lineEdit_T_lag,0.0,1000.0,2,0.0);
 
     // > For alpha
-    alpha = validate_and_get_value_from_lineEdit(ui->lineEdit_alpha_lag,1.0,100.0,2,1.0);
+    alpha = validate_and_get_value_from_lineEdit(ui->lineEdit_alpha_lag,0.0,1000.0,2,1.0);
 
     // Unlock the mutex
     m_lag_controller_parameter_mutex.unlock();
@@ -547,7 +547,7 @@ void CsoneControllerTab::on_set_lag_compensator_parameters_button_clicked()
 void CsoneControllerTab::on_set_time_delay_button_clicked()
 {
     // Take the new value if available, otherwise use default
-    float time_delay_float = validate_and_get_value_from_lineEdit(ui->lineEdit_time_delay,0.0,1000.0,0,0.0);
+    float time_delay_float = validate_and_get_value_from_lineEdit(ui->lineEdit_time_delay,0.0,10000.0,0,0.0);
     float time_delay_int = int(time_delay_float);
 
     // Call the function to publish the time delay
@@ -557,7 +557,7 @@ void CsoneControllerTab::on_set_time_delay_button_clicked()
 void CsoneControllerTab::on_set_pitch_error_button_clicked()
 {
     // Take the new value if available, otherwise use default
-    float pitch_error = validate_and_get_value_from_lineEdit(ui->lineEdit_pitch_error,-60.0,60.0,3,0.0);
+    float pitch_error = validate_and_get_value_from_lineEdit(ui->lineEdit_pitch_error,-180.0,180.0,3,0.0);
 
     // Call the function to publish the pitch error
     publishRequestForPitchErrorChange(pitch_error);
@@ -640,49 +640,49 @@ void CsoneControllerTab::on_lineEdit_step_duration_returnPressed()
 void CsoneControllerTab::on_lineEdit_k_editingFinished()
 {
     m_controller_parameter_mutex.lock();
-    validate_and_get_value_from_lineEdit(ui->lineEdit_k,-100.0,100.0,4,0.016);
+    validate_and_get_value_from_lineEdit(ui->lineEdit_k,-1000.0,1000.0,4,0.1);
     m_controller_parameter_mutex.unlock();
 }
 
 void CsoneControllerTab::on_lineEdit_T_editingFinished()
 {
     m_controller_parameter_mutex.lock();
-    validate_and_get_value_from_lineEdit(ui->lineEdit_T,0.0,100.0,2,4.0);
+    validate_and_get_value_from_lineEdit(ui->lineEdit_T,0.0,1000.0,2,1.0);
     m_controller_parameter_mutex.unlock();
 }
 
 void CsoneControllerTab::on_lineEdit_alpha_editingFinished()
 {
     m_controller_parameter_mutex.lock();
-    validate_and_get_value_from_lineEdit(ui->lineEdit_alpha,0.1,1.0,2,0.1);
+    validate_and_get_value_from_lineEdit(ui->lineEdit_alpha,0.0,1.0,2,0.5);
     m_controller_parameter_mutex.unlock();
 }
 
 void CsoneControllerTab::on_lineEdit_T_lag_editingFinished()
 {
     m_lag_controller_parameter_mutex.lock();
-    validate_and_get_value_from_lineEdit(ui->lineEdit_T_lag,0.0,100.0,2,0.0);
+    validate_and_get_value_from_lineEdit(ui->lineEdit_T_lag,0.0,1000.0,2,0.0);
     m_lag_controller_parameter_mutex.unlock();
 }
 
 void CsoneControllerTab::on_lineEdit_alpha_lag_editingFinished()
 {
     m_lag_controller_parameter_mutex.lock();
-    validate_and_get_value_from_lineEdit(ui->lineEdit_alpha_lag,1.0,100.0,2,1.0);
+    validate_and_get_value_from_lineEdit(ui->lineEdit_alpha_lag,0.0,1000.0,2,1.0);
     m_lag_controller_parameter_mutex.unlock();
 }
 
 void CsoneControllerTab::on_lineEdit_step_size_editingFinished()
 {
     m_chart_mutex.lock();
-    validate_and_get_value_from_lineEdit(ui->lineEdit_step_size,-2.0,2.0,1,0.5);
+    validate_and_get_value_from_lineEdit(ui->lineEdit_step_size,-2.0,2.0,2,0.5);
     m_chart_mutex.unlock();
 }
 
 void CsoneControllerTab::on_lineEdit_step_duration_editingFinished()
 {
     m_chart_mutex.lock();
-    m_step_response_data_recording_duration = validate_and_get_value_from_lineEdit(ui->lineEdit_step_duration,2.0,40.0,0,20.0);
+    m_step_response_data_recording_duration = validate_and_get_value_from_lineEdit(ui->lineEdit_step_duration,1.0,100.0,0,20.0);
     m_chart_mutex.unlock();
 }
 
@@ -802,7 +802,7 @@ void CsoneControllerTab::newDataForPerformingStepAndPlotting(float x, float pitc
                 m_shouldPerformStep = false;
 
                 // Extract the current step size
-                float step_size = validate_and_get_value_from_lineEdit(ui->lineEdit_step_size,-2.0,2.0,1,0.5);
+                float step_size = validate_and_get_value_from_lineEdit(ui->lineEdit_step_size,-2.0,2.0,2,0.5);
 
                 // Determine the new x setpoint
                 float new_x = 0.0;
@@ -1421,9 +1421,9 @@ void CsoneControllerTab::simulate_step_response()
 
     float current_setpoint_x = m_current_setpoint_x;
 
-    float step_size = validate_and_get_value_from_lineEdit(ui->lineEdit_step_size,-2.0,2.0,1,0.5);
+    float step_size = validate_and_get_value_from_lineEdit(ui->lineEdit_step_size,-2.0,2.0,2,0.5);
 
-    m_step_response_data_recording_duration = validate_and_get_value_from_lineEdit(ui->lineEdit_step_duration,2.0,40.0,0,20.0);
+    m_step_response_data_recording_duration = validate_and_get_value_from_lineEdit(ui->lineEdit_step_duration,1.0,100.0,0,20.0);
     float duration = m_step_response_data_recording_duration;
 
     // Unlock the mutex
@@ -1432,7 +1432,7 @@ void CsoneControllerTab::simulate_step_response()
 
 
     // Take the new value if available, otherwise use default
-    float time_delay_float = validate_and_get_value_from_lineEdit(ui->lineEdit_time_delay,0.0,1000.0,0,0.0);
+    float time_delay_float = validate_and_get_value_from_lineEdit(ui->lineEdit_time_delay,0.0,10000.0,0,0.0);
     float time_delay_int = int(time_delay_float);
 
     // Compute the number of milliseconds per time step
@@ -1459,6 +1459,39 @@ void CsoneControllerTab::simulate_step_response()
     float control_frequency = 200.0;
     float control_deltaT = 0.005;
 
+    // Model parameters
+    float k_x = 0.2;
+    float m = 0.3;
+    float g = 9.81;
+
+    // Discrete time x subsystem matrices
+    //  for k_x / m = 0.15, g = 9.81, T = 0.005:
+    //        A =
+    //                    x1         x2         x3
+    //         x1          1   0.004998  0.0001226
+    //         x2          0     0.9993    0.04903
+    //         x3          0          0          1
+
+    //        B =
+    //                    u1
+    //         x1  2.043e-07
+    //         x2  0.0001226
+    //         x3      0.005
+
+    // in general:
+    float A_x_x = 1.0;
+    float A_x_xdot = control_deltaT * (1 - k_x / m * control_deltaT / 2);
+    float A_x_pitch = g * control_deltaT * control_deltaT / 2;
+    float A_xdot_x = 0.0;
+    float A_xdot_xdot = 1 - k_x / m * control_deltaT;
+    float A_xdot_pitch = g * control_deltaT;
+    float A_pitch_x = 0.0;
+    float A_pitch_xdot = 0.0;
+    float A_pitch_pitch = 1.0;
+    float B_x_pitchRate = g * control_deltaT * control_deltaT * control_deltaT / 6;
+    float B_xdot_pitchRate = g * control_deltaT * control_deltaT / 2;
+    float B_pitch_pitchRate = control_deltaT;
+
     float sim_time = 0.0;
 
     int num_time_steps = int( duration / control_deltaT );
@@ -1572,22 +1605,11 @@ void CsoneControllerTab::simulate_step_response()
         // > FOURTH: perform the inner controller
         float pitch_rate = 5.0*(pitch_ref-current_pitch);
 
-//        A =
-//                    x1         x2         x3
-//         x1          1   0.004998  0.0001226
-//         x2          0     0.9993    0.04903
-//         x3          0          0          1
-
-//        B =
-//                    u1
-//         x1  2.043e-07
-//         x2  0.0001226
-//         x3      0.005
 
         // Perform the evolution of the state
-        current_x     = current_x + 0.004998*current_xdot + 0.0001226*current_pitch;
-        current_xdot  = 0.9993*current_xdot + 0.04903*current_pitch + 0.0001226*pitch_rate;
-        current_pitch = current_pitch + 0.005*pitch_rate;
+        current_x     = A_x_x * current_x + A_x_xdot * current_xdot + A_x_pitch * current_pitch + B_x_pitchRate * pitch_rate;
+        current_xdot  = A_xdot_x * current_x + A_xdot_xdot * current_xdot + A_xdot_pitch * current_pitch + B_xdot_pitchRate * pitch_rate;
+        current_pitch = A_pitch_x * current_x + A_pitch_xdot * current_xdot + A_pitch_pitch * current_pitch + B_pitch_pitchRate * pitch_rate;
 
         // Update the min and max
         min_x_value_sim = std::min( min_x_value_sim , current_x );
diff --git a/dfall_ws/src/dfall_pkg/include/nodes/CsoneControllerService.h b/dfall_ws/src/dfall_pkg/include/nodes/CsoneControllerService.h
index 6192a103..7ed1deaf 100644
--- a/dfall_ws/src/dfall_pkg/include/nodes/CsoneControllerService.h
+++ b/dfall_ws/src/dfall_pkg/include/nodes/CsoneControllerService.h
@@ -133,7 +133,7 @@ std::string m_namespace_to_coordinator_parameter_service;
 
 // VARAIBLES FOR VALUES LOADED FROM THE YAML FILE
 // > the mass of the crazyflie, in [grams]
-float yaml_cf_mass_in_grams = 25.0;
+float yaml_cf_mass_in_grams = 30.0;
 
 // > the frequency at which the controller is running
 float yaml_control_frequency = 200.0;
@@ -183,19 +183,30 @@ float m_tau_z_integral   = 0.0;
 float m_cf_weight_in_newtons = 0.0;
 
 // The state space matrices of lead compensator controller
-float m_A=0.967216;
-float m_B=0.00491758;
-float m_C=-12.0;
-float m_D=2.0;
+// the following corresponds to k=0.2, T=1.5, alpha=0.1
+// this works well
+// float m_A=0.967216;
+// float m_B=0.00491758;
+// float m_C=-12.0;
+// float m_D=2.0;
+
+// the following corresponds to k=0.1, T=1.0, alpha=0.5
+// this is barely stabilizing
+float m_A = 0.99004983;
+float m_B = 0.00497508;
+float m_C = -0.2;
+float m_D = 0.2;
 
 // The state of lead compensator controller
 float m_controller_state = 0.0;
 
 // The state space matrices of lag compensator controller
-float m_lag_A=0.0;
-float m_lag_B=0.0;
-float m_lag_C=0.0;
-float m_lag_D=1.0;
+// the following corresponds to T = 0.0, alpha = 1.0
+// (i.e., lag controller inactive)
+float m_lag_A = 0.0;
+float m_lag_B = 0.0;
+float m_lag_C = 0.0;
+float m_lag_D = 1.0;
 
 // The state of lag compensator controller
 float m_lag_controller_state = 0.0;
diff --git a/dfall_ws/src/dfall_pkg/src/nodes/CsoneControllerService.cpp b/dfall_ws/src/dfall_pkg/src/nodes/CsoneControllerService.cpp
index e6c3b637..265cf91f 100644
--- a/dfall_ws/src/dfall_pkg/src/nodes/CsoneControllerService.cpp
+++ b/dfall_ws/src/dfall_pkg/src/nodes/CsoneControllerService.cpp
@@ -830,14 +830,21 @@ void requestLagControllerParametersChangeCallback(const SetpointWithHeader& newS
 // CHANGE CONTROLLER PARAMETERS INTO DISCRETE TIME FUNCTION
 void convertIntoDiscreteTimeParameters(float k, float T, float alpha)
 {
-	if (alpha > 1){alpha = 1;} else if (alpha<0.1){alpha = 0.1;}
-
-	if (T > 100){T = 100;} else if (T<0.1){T = 0.1;}
+	if (alpha > 0.0 && T > 0.0){
+		// valid parameters
+		m_A = pow(2.71828, (-1.0 / (yaml_control_frequency*alpha*T)));
+		m_B = -alpha * T * (m_A - 1.0);
+		m_C = k / (alpha * T) * (1.0 - 1.0 / alpha);
+		m_D = k / alpha;
+	}
+	else{
+		// if invalid parameters, act as a proportional controller with gain k
+		m_A = 0.0;
+		m_B = 0.0;
+        m_C = 0.0;
+        m_D = k;
+	}
 
-	m_A = pow(2.71828,(-1.0/(yaml_control_frequency*alpha*T)));
-	m_B = -alpha*T*(m_A-1.0);
-	m_C = k/(alpha*T)*(1.0-1.0/alpha);
-	m_D = k/alpha;
 
 	ROS_INFO_STREAM("[CSONE CONTROLLER] Parameters changed to k="<<k<<", T="<<T<<", alpha="<<alpha);
 	ROS_INFO_STREAM("[CSONE CONTROLLER] Matrices changed to A="<<m_A<<", B="<<m_B<<", C="<<m_C<<", D="<<m_D);
@@ -848,21 +855,20 @@ void convertIntoDiscreteTimeParameters(float k, float T, float alpha)
 // CHANGE LAG CONTROLLER PARAMETERS INTO DISCRETE TIME FUNCTION
 void convertLagIntoDiscreteTimeParameters(float T, float alpha)
 {
-	if (alpha > 100){alpha = 100;} else if (alpha<1){alpha = 1;}
-
-	if (T > 100){T = 100;} else if (T<0){T = 0;}
-
-	if (T > 0){
-        m_lag_A = pow(2.71828,(-1.0/(yaml_control_frequency*alpha*T)));
-        m_lag_B = -alpha*T*(m_lag_A-1.0);
-        m_lag_C = (alpha-1.0)/(alpha*T);
+	if (alpha > 0.0 && T > 0.0){
+		// valid parameters
+        m_lag_A = pow(2.71828, (-1.0/(yaml_control_frequency*alpha*T)));
+        m_lag_B = -alpha * T * (m_lag_A - 1.0);
+        m_lag_C = (alpha - 1.0) / (alpha * T);
+    	m_lag_D = 1.0;
     }
     else{
-        m_lag_A = 0;
-        m_lag_B = 0;
-        m_lag_C = 0;
+		// if invalid parameters, act as a proportional controller with gain alpha
+        m_lag_A = 0.0;
+        m_lag_B = 0.0;
+        m_lag_C = 0.0;
+    	m_lag_D = alpha;
     }
-    m_lag_D = 1;
 
 	ROS_INFO_STREAM("[CSONE CONTROLLER] Lag parameters changed to T="<<T<<", alpha="<<alpha);
 	ROS_INFO_STREAM("[CSONE CONTROLLER] Lag matrices changed to A="<<m_lag_A<<", B="<<m_lag_B<<", C="<<m_lag_C<<", D="<<m_lag_D);
-- 
GitLab