From c93687a4b4dc1f4f38c8061b8837413e459a68ff Mon Sep 17 00:00:00 2001
From: Paul Beuchat <beuchatp@control.ee.ethz.ch>
Date: Fri, 20 Apr 2018 14:03:45 +0200
Subject: [PATCH] Added nested LQR Angle Rate controller, tested to be workin

---
 .../include/DemoControllerService.h           |  60 +++++---
 .../src/d_fall_pps/param/DemoController.yaml  |  17 ++-
 .../d_fall_pps/src/DemoControllerService.cpp  | 144 +++++++++++++++++-
 3 files changed, 193 insertions(+), 28 deletions(-)

diff --git a/pps_ws/src/d_fall_pps/include/DemoControllerService.h b/pps_ws/src/d_fall_pps/include/DemoControllerService.h
index e3a9d084..b788a8b5 100644
--- a/pps_ws/src/d_fall_pps/include/DemoControllerService.h
+++ b/pps_ws/src/d_fall_pps/include/DemoControllerService.h
@@ -114,10 +114,11 @@
 // LQR_MODE_ANGLE     LQR controller based on the state vector:
 //                    [position,velocity]
 //
-#define LQR_MODE_MOTOR      1
-#define LQR_MODE_ACTUATOR   2
-#define LQR_MODE_RATE       3   // (DEFAULT)
-#define LQR_MODE_ANGLE      4
+#define LQR_MODE_MOTOR               1
+#define LQR_MODE_ACTUATOR            2
+#define LQR_MODE_RATE                3   // (DEFAULT)
+#define LQR_MODE_ANGLE               4
+#define LQR_MODE_ANGLE_RATE_NESTED   5
 
 
 // These constants define the method used for estimating the Inertial
@@ -179,6 +180,9 @@ float gravity_force_quarter;
 
 // VARIABLES FOR THE CONTROLLER
 
+// Frequency at which the controller is running
+float vicon_frequency;
+
 // Frequency at which the controller is running
 float control_frequency;
 
@@ -200,21 +204,36 @@ std::vector<float> gainMatrixMotor3 (12,0.0);
 std::vector<float> gainMatrixMotor4 (12,0.0);
 
 // The LQR Controller parameters for "LQR_MODE_ACTUATOR"
-std::vector<float> gainMatrixThrust_TwelveStateVector  (12,0.0);
-std::vector<float> gainMatrixRollTorque                (12,0.0);
-std::vector<float> gainMatrixPitchTorque               (12,0.0);
-std::vector<float> gainMatrixYawTorque                 (12,0.0);
+std::vector<float> gainMatrixThrust_TwelveStateVector (12,0.0);
+std::vector<float> gainMatrixRollTorque               (12,0.0);
+std::vector<float> gainMatrixPitchTorque              (12,0.0);
+std::vector<float> gainMatrixYawTorque                (12,0.0);
 
 // The LQR Controller parameters for "LQR_MODE_RATE"
-std::vector<float> gainMatrixThrust_NineStateVector  =  { 0.00, 0.00, 0.25, 0.00, 0.00, 0.14, 0.00, 0.00, 0.00};
-std::vector<float> gainMatrixRollRate                =  { 0.00,-1.72, 0.00, 0.00,-1.34, 0.00, 5.12, 0.00, 0.00};
-std::vector<float> gainMatrixPitchRate               =  { 1.72, 0.00, 0.00, 1.34, 0.00, 0.00, 0.00, 5.12, 0.00};
-std::vector<float> gainMatrixYawRate                 =  { 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 2.84};
+std::vector<float> gainMatrixThrust_NineStateVector (9,0.0);
+std::vector<float> gainMatrixRollRate               (9,0.0);
+std::vector<float> gainMatrixPitchRate              (9,0.0);
+std::vector<float> gainMatrixYawRate                (9,0.0);
 
 // The LQR Controller parameters for "LQR_MODE_ANGLE"
-std::vector<float> gainMatrixThrust_SixStateVector   =  { 0.00, 0.00, 0.31, 0.00, 0.00, 0.14};
-std::vector<float> gainMatrixRollAngle               =  { 0.00,-0.20, 0.00, 0.00,-0.20, 0.00};
-std::vector<float> gainMatrixPitchAngle              =  { 0.20, 0.00, 0.00, 0.20, 0.00, 0.00};
+std::vector<float> gainMatrixThrust_SixStateVector (6,0.0);
+std::vector<float> gainMatrixRollAngle             (6,0.0);
+std::vector<float> gainMatrixPitchAngle            (6,0.0);
+
+// The LQR Controller parameters for "LQR_MODE_ANGLE_RATE_NESTED"
+std::vector<float> gainMatrixThrust_SixStateVector_50Hz (6,0.0);
+std::vector<float> gainMatrixRollAngle_50Hz             (6,0.0);
+std::vector<float> gainMatrixPitchAngle_50Hz            (6,0.0);
+
+std::vector<float> gainMatrixRollRate_Nested            (3,0.0);
+std::vector<float> gainMatrixPitchRate_Nested           (3,0.0);
+std::vector<float> gainMatrixYawRate_Nested             (3,0.0);
+
+int lqr_angleRateNested_counter = 4;
+float lqr_angleRateNested_prev_thrustAdjustment = 0.0;
+float lqr_angleRateNested_prev_rollAngle        = 0.0;
+float lqr_angleRateNested_prev_pitchAngle       = 0.0;
+float lqr_angleRateNested_prev_yawAngle         = 0.0;
 
 
 // The 16-bit command limits
@@ -365,11 +384,12 @@ ros::Subscriber xyz_yaw_to_follow_subscriber;
 bool calculateControlOutput(Controller::Request &request, Controller::Response &response);
 
 // > The various functions that implement an LQR controller
-void calculateControlOutput_viaLQR(            float stateErrorBody[12], Controller::Request &request, Controller::Response &response);
-void calculateControlOutput_viaLQRforMotors(   float stateErrorBody[12], Controller::Request &request, Controller::Response &response);
-void calculateControlOutput_viaLQRforActuators(float stateErrorBody[12], Controller::Request &request, Controller::Response &response);
-void calculateControlOutput_viaLQRforRates(    float stateErrorBody[12], Controller::Request &request, Controller::Response &response);
-void calculateControlOutput_viaLQRforAngles(   float stateErrorBody[12], Controller::Request &request, Controller::Response &response);
+void calculateControlOutput_viaLQR(                     float stateErrorBody[12], Controller::Request &request, Controller::Response &response);
+void calculateControlOutput_viaLQRforMotors(            float stateErrorBody[12], Controller::Request &request, Controller::Response &response);
+void calculateControlOutput_viaLQRforActuators(         float stateErrorBody[12], Controller::Request &request, Controller::Response &response);
+void calculateControlOutput_viaLQRforRates(             float stateErrorBody[12], Controller::Request &request, Controller::Response &response);
+void calculateControlOutput_viaLQRforAngles(            float stateErrorBody[12], Controller::Request &request, Controller::Response &response);
+void calculateControlOutput_viaLQRforAnglesRatesNested( float stateErrorBody[12], Controller::Request &request, Controller::Response &response);
 
 // ESTIMATOR COMPUTATIONS
 void performEstimatorUpdate_forStateInterial(Controller::Request &request);
diff --git a/pps_ws/src/d_fall_pps/param/DemoController.yaml b/pps_ws/src/d_fall_pps/param/DemoController.yaml
index dcde9927..875e84dc 100644
--- a/pps_ws/src/d_fall_pps/param/DemoController.yaml
+++ b/pps_ws/src/d_fall_pps/param/DemoController.yaml
@@ -2,6 +2,7 @@
 mass : 30
 
 # Frequency of the controller, in hertz
+vicon_frequency : 200
 control_frequency : 200
 
 # Quadratic motor regression equation (a0, a1, a2)
@@ -37,7 +38,8 @@ shouldDisplayDebugInfo : false
 #       commands actuators of total force and bodz torques
 # 3  -  LQR controller based on the state vector: [position,velocity,angles]
 # 4  -  LQR controller based on the state vector: [position,velocity]
-lqr_controller_mode : 3
+# 5  -  LQR Nester angle and rate controller
+lqr_controller_mode : 5
 
 
 # A flag for which estimator to use, defined as:
@@ -50,7 +52,7 @@ lqr_controller_mode : 3
 #       each of (x,y,z,roll,pitch,yaw)
 # 3  -  Quad-rotor Model Based Method
 #       Uses the model of the quad-rotor and the previous inputs
-estimator_method : 1
+estimator_method : 2
 
 
 # The LQR Controller parameters for "mode = 1"
@@ -72,11 +74,20 @@ gainMatrixPitchRate                 :  [ 1.80, 0.00, 0.00, 1.38, 0.00, 0.00, 0.0
 gainMatrixYawRate                   :  [ 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 2.30]
 
 # The LQR Controller parameters for "mode = 4"
-gainMatrixThrust_SixStateVector     :  [ 0.00, 0.00, 0.31, 0.00, 0.00, 0.14]
+gainMatrixThrust_SixStateVector     :  [ 0.00, 0.00, 0.98, 0.00, 0.00, 0.25]
 gainMatrixRollAngle                 :  [ 0.00,-0.20, 0.00, 0.00,-0.20, 0.00]
 gainMatrixPitchAngle                :  [ 0.20, 0.00, 0.00, 0.20, 0.00, 0.00]
 
 
+# The LQR Controller parameters for "mode = 5"
+gainMatrixThrust_SixStateVector_50Hz:  [ 0.00, 0.00, 0.82, 0.00, 0.00, 0.22]
+gainMatrixRollAngle_50Hz            :  [ 0.00,-0.31, 0.00, 0.00,-0.25, 0.00]
+gainMatrixPitchAngle_50Hz           :  [ 0.31, 0.00, 0.00, 0.25, 0.00, 0.00]
+
+gainMatrixRollRate_Nested           :  [ 4.00, 0.00, 0.00]
+gainMatrixPitchRate_Nested          :  [ 0.00, 4.00, 0.00]
+gainMatrixYawRate_Nested            :  [ 0.00, 0.00, 2.30]
+
 # The max and minimum thrust for a 16-bit command
 command_sixteenbit_min : 1000
 command_sixteenbit_max : 60000
diff --git a/pps_ws/src/d_fall_pps/src/DemoControllerService.cpp b/pps_ws/src/d_fall_pps/src/DemoControllerService.cpp
index 6a3ab506..5e351d37 100644
--- a/pps_ws/src/d_fall_pps/src/DemoControllerService.cpp
+++ b/pps_ws/src/d_fall_pps/src/DemoControllerService.cpp
@@ -428,6 +428,15 @@ void calculateControlOutput_viaLQR(float stateErrorBody[12], Controller::Request
 			break;
 		}
 
+		// LQR controller based on the state vector:
+		// [position,velocity,angles]
+		case LQR_MODE_ANGLE_RATE_NESTED:
+		{
+			// Call the function that performs the control computations for this mode
+			calculateControlOutput_viaLQRforAnglesRatesNested(stateErrorBody,request,response);
+			break;
+		}
+
 		default:
 		{
 			// Display that the "lqr_controller_mode" was not recognised
@@ -808,7 +817,7 @@ void calculateControlOutput_viaLQRforAngles(float stateErrorBody[12], Controller
 	float thrustAdjustment = 0;
 
 	// Perform the "-Kx" LQR computation for the rates and thrust:
-	for(int i = 0; i < 9; ++i)
+	for(int i = 0; i < 6; ++i)
 	{
 		// BODY FRAME Y CONTROLLER
 		rollAngle_forResponse -= gainMatrixRollAngle[i] * stateErrorBody[i];
@@ -829,6 +838,7 @@ void calculateControlOutput_viaLQRforAngles(float stateErrorBody[12], Controller
 	// > NOTE: remember that the thrust is commanded per motor, so you sohuld
 	//         consider whether the "thrustAdjustment" computed by your
 	//         controller needed to be divided by 4 or not.
+	thrustAdjustment = thrustAdjustment / 4.0;
 	// > NOTE: the "gravity_force_quarter" value was already divided by 4 when
 	//         it was loaded/processes from the .yaml file.
 	response.controlOutput.motorCmd1 = computeMotorPolyBackward(thrustAdjustment + gravity_force_quarter);
@@ -847,6 +857,116 @@ void calculateControlOutput_viaLQRforAngles(float stateErrorBody[12], Controller
 
 
 
+void calculateControlOutput_viaLQRforAnglesRatesNested( float stateErrorBody[12], Controller::Request &request, Controller::Response &response)
+{
+	// PERFORM THE NESTED "u=Kx" LQR CONTROLLER COMPUTATION
+
+	// Increment the counter variable
+	lqr_angleRateNested_counter++;
+
+	if (lqr_angleRateNested_counter > 4)
+	{
+		//ROS_INFO("Outer called");
+			
+		// Reset the counter to 1
+		lqr_angleRateNested_counter = 1;
+
+		// PERFORM THE OUTER "u=Kx" LQR CONTROLLER COMPUTATION
+
+		// Reset the class variable to zero for the following:
+		// > body frame roll angle,
+		// > body frame pitch angle,
+		// > body frame yaw angle,
+		// > total thrust adjustment.
+		// These will be requested from the "inner-loop" LQR controller below
+		lqr_angleRateNested_prev_rollAngle        = 0;
+		lqr_angleRateNested_prev_pitchAngle       = 0;
+		lqr_angleRateNested_prev_thrustAdjustment = 0;
+
+		// Perform the "-Kx" LQR computation for the rates and thrust:
+		for(int i = 0; i < 6; ++i)
+		{
+			// BODY FRAME Y CONTROLLER
+			lqr_angleRateNested_prev_rollAngle        -= gainMatrixRollAngle_50Hz[i] * stateErrorBody[i];
+			// BODY FRAME X CONTROLLER
+			lqr_angleRateNested_prev_pitchAngle       -= gainMatrixPitchAngle_50Hz[i] * stateErrorBody[i];
+			// > ALITUDE CONTROLLER (i.e., z-controller):
+			lqr_angleRateNested_prev_thrustAdjustment -= gainMatrixThrust_SixStateVector_50Hz[i] * stateErrorBody[i];
+		}
+
+		// BODY FRAME Z CONTROLLER
+		//lqr_angleRateNested_prev_yawAngle = setpoint[3];
+		lqr_angleRateNested_prev_yawAngle = stateErrorBody[8];
+
+
+	}
+
+	//ROS_INFO("Inner called");
+
+	// PERFORM THE INNER "u=Kx" LQR CONTROLLER COMPUTATION
+	// Instantiate the local variables for the following:
+	// > body frame roll rate,
+	// > body frame pitch rate,
+	// > body frame yaw rate,
+	// These will be requested from the Crazyflie's on-baord "inner-loop" controller
+	float rollRate_forResponse  = 0;
+	float pitchRate_forResponse = 0;
+	float yawRate_forResponse   = 0;
+
+	// Create the angle error to use for the inner controller
+	float temp_stateAngleError[3] = {
+		stateErrorBody[6] - lqr_angleRateNested_prev_rollAngle,
+		stateErrorBody[7] - lqr_angleRateNested_prev_pitchAngle,
+		lqr_angleRateNested_prev_yawAngle
+	};
+	
+	// Perform the "-Kx" LQR computation for the rates and thrust:
+	for(int i = 0; i < 4; ++i)
+	{
+		// BODY FRAME Y CONTROLLER
+		rollRate_forResponse  -= gainMatrixRollRate_Nested[i]  * temp_stateAngleError[i];
+		// BODY FRAME X CONTROLLER
+		pitchRate_forResponse -= gainMatrixPitchRate_Nested[i] * temp_stateAngleError[i];
+		// BODY FRAME Z CONTROLLER
+		yawRate_forResponse   -= gainMatrixYawRate_Nested[i]   * temp_stateAngleError[i];
+	}
+
+
+	// UPDATE THE "RETURN" THE VARIABLE NAMED "response"
+
+	// Put the computed rates and thrust into the "response" variable
+	// > For roll, pitch, and yaw:
+	response.controlOutput.roll  = rollRate_forResponse;
+	response.controlOutput.pitch = pitchRate_forResponse;
+	response.controlOutput.yaw   = yawRate_forResponse;
+	// > For the thrust adjustment we must add the feed-forward thrust to counter-act gravity.
+	// > NOTE: remember that the thrust is commanded per motor, so you sohuld
+	//         consider whether the "thrustAdjustment" computed by your
+	//         controller needed to be divided by 4 or not.
+	float thrustAdjustment = lqr_angleRateNested_prev_thrustAdjustment / 4.0;
+	// > NOTE: the "gravity_force_quarter" value was already divided by 4 when
+	//         it was loaded/processes from the .yaml file.
+	response.controlOutput.motorCmd1 = computeMotorPolyBackward(thrustAdjustment + gravity_force_quarter);
+	response.controlOutput.motorCmd2 = computeMotorPolyBackward(thrustAdjustment + gravity_force_quarter);
+	response.controlOutput.motorCmd3 = computeMotorPolyBackward(thrustAdjustment + gravity_force_quarter);
+	response.controlOutput.motorCmd4 = computeMotorPolyBackward(thrustAdjustment + gravity_force_quarter);
+
+	
+	// Specify that this controller is a rate controller
+	// response.controlOutput.onboardControllerType = CF_COMMAND_TYPE_MOTOR;
+	response.controlOutput.onboardControllerType = CF_COMMAND_TYPE_RATE;
+	// response.controlOutput.onboardControllerType = CF_COMMAND_TYPE_ANGLE;
+
+
+	ROS_INFO_STREAM("thrust    =" << lqr_angleRateNested_prev_thrustAdjustment );
+	ROS_INFO_STREAM("rollrate  =" << response.controlOutput.roll );
+	ROS_INFO_STREAM("pitchrate =" << response.controlOutput.pitch );
+	ROS_INFO_STREAM("yawrate   =" << response.controlOutput.yaw );
+
+}
+
+
+
 
 
 
@@ -1171,6 +1291,10 @@ void fetchYamlParameters(ros::NodeHandle& nodeHandle)
 	// Display one of the YAML parameters to debug if it is working correctly
 	//ROS_INFO_STREAM("DEBUGGING: mass leaded from loacl file = " << cf_mass );
 
+	// > The frequency at which the "computeControlOutput" is being called, as determined
+	//   by the frequency at which the Vicon system provides position and attitude data
+	vicon_frequency = getParameterFloat(nodeHandle_for_demoController, "vicon_frequency");
+
 	// > The frequency at which the "computeControlOutput" is being called, as determined
 	//   by the frequency at which the Vicon system provides position and attitude data
 	control_frequency = getParameterFloat(nodeHandle_for_demoController, "control_frequency");
@@ -1228,15 +1352,25 @@ void fetchYamlParameters(ros::NodeHandle& nodeHandle)
 	getParameterFloatVector(nodeHandle_for_demoController, "gainMatrixYawTorque",                gainMatrixYawTorque,                12);
 
 	// The LQR Controller parameters for "LQR_MODE_RATE"
+	getParameterFloatVector(nodeHandle_for_demoController, "gainMatrixThrust_NineStateVector", gainMatrixThrust_NineStateVector, 9);
 	getParameterFloatVector(nodeHandle_for_demoController, "gainMatrixRollRate",               gainMatrixRollRate,               9);
 	getParameterFloatVector(nodeHandle_for_demoController, "gainMatrixPitchRate",              gainMatrixPitchRate,              9);
 	getParameterFloatVector(nodeHandle_for_demoController, "gainMatrixYawRate",                gainMatrixYawRate,                9);
-	getParameterFloatVector(nodeHandle_for_demoController, "gainMatrixThrust_NineStateVector", gainMatrixThrust_NineStateVector, 9);
-
+	
 	// The LQR Controller parameters for "LQR_MODE_ANGLE"
+	getParameterFloatVector(nodeHandle_for_demoController, "gainMatrixThrust_SixStateVector",  gainMatrixThrust_SixStateVector,  6);
 	getParameterFloatVector(nodeHandle_for_demoController, "gainMatrixRollAngle",              gainMatrixRollAngle,              6);
 	getParameterFloatVector(nodeHandle_for_demoController, "gainMatrixPitchAngle",             gainMatrixPitchAngle,             6);
-	getParameterFloatVector(nodeHandle_for_demoController, "gainMatrixThrust_SixStateVector",  gainMatrixThrust_SixStateVector,  6);
+	
+	// The LQR Controller parameters for "LQR_MODE_ANGLE_RATE_NESTED"
+	getParameterFloatVector(nodeHandle_for_demoController, "gainMatrixThrust_SixStateVector_50Hz",  gainMatrixThrust_SixStateVector_50Hz,  6);
+	getParameterFloatVector(nodeHandle_for_demoController, "gainMatrixRollAngle_50Hz",              gainMatrixRollAngle_50Hz,              6);
+	getParameterFloatVector(nodeHandle_for_demoController, "gainMatrixPitchAngle_50Hz",             gainMatrixPitchAngle_50Hz,             6);
+
+	getParameterFloatVector(nodeHandle_for_demoController, "gainMatrixRollRate_Nested",             gainMatrixRollRate_Nested,             3);
+	getParameterFloatVector(nodeHandle_for_demoController, "gainMatrixPitchRate_Nested",            gainMatrixPitchRate_Nested,            3);
+	getParameterFloatVector(nodeHandle_for_demoController, "gainMatrixYawRate_Nested",              gainMatrixYawRate_Nested,              3);
+	
 
 
 	// 16-BIT COMMAND LIMITS
@@ -1276,7 +1410,7 @@ void processFetchedParameters()
     gravity_force_quarter = cf_mass * 9.81/(1000*4);
 
     // Set that the estimator frequency is the same as the control frequency
-    estimator_frequency = control_frequency;
+    estimator_frequency = vicon_frequency;
 
     // Look-up which agent should be followed
     if (shouldFollowAnotherAgent)
-- 
GitLab