diff --git a/pps_ws/src/d_fall_pps/param/CustomController.yaml b/pps_ws/src/d_fall_pps/param/CustomController.yaml
index e405cb8dd82264636082f66f509118ccbf52a179..1a07c5dce71f543ae27fc8ddd4649ac3365f33c9 100644
--- a/pps_ws/src/d_fall_pps/param/CustomController.yaml
+++ b/pps_ws/src/d_fall_pps/param/CustomController.yaml
@@ -8,7 +8,7 @@ control_frequency : 200
 motorPoly : [5.484560e-4, 1.032633e-6, 2.130295e-11]
 
 # Boolean for whether to execute the convert into body frame function
-shouldPerformConvertIntoBodyFrame : false
+shouldPerformConvertIntoBodyFrame : true
 
 # Boolean indiciating whether the (x,y,z,yaw) of this agent should be published or not
 shouldPublishCurrent_xyz_yaw : false
@@ -21,4 +21,15 @@ shouldFollowAnotherAgent : false
 # > This parameter is a vector of integers that specifies  agent ID's
 # > The order of the agent ID's is the ordering of the line formation
 # > i.e., the first ID is the leader, the second ID should follow the first ID, and so on
-follow_in_a_line_agentIDs : [1, 2, 3]
\ No newline at end of file
+follow_in_a_line_agentIDs : [1, 2, 3]
+
+# A flag for which controller to use, defined as:
+# 1  -  LQR controller based on the state vector: [position,velocity,angles]
+# 2  -  LQR controller based on the state vector: [position,velocity]
+controller_type : 1
+
+# Boolean indiciating whether the "Debug Message" of this agent should be published or not
+shouldPublishDebugMessage : false
+
+# Boolean indiciating whether the debugging ROS_INFO_STREAM should be displayed or not
+shouldDisplayDebugInfo : false
\ No newline at end of file
diff --git a/pps_ws/src/d_fall_pps/src/CustomControllerService.cpp b/pps_ws/src/d_fall_pps/src/CustomControllerService.cpp
index d4480f4ba3fa6b5336c18a17271ff93ce321dde7..10318ba2f05040317c76bb9f9925060e2ce2a25c 100644
--- a/pps_ws/src/d_fall_pps/src/CustomControllerService.cpp
+++ b/pps_ws/src/d_fall_pps/src/CustomControllerService.cpp
@@ -77,7 +77,7 @@
 // Universal constants
 #define PI 3.1415926535
 
-// The constants define the modes that can be used for controller the Crazyflie 2.0,
+// These constants define the modes that can be used for controller the Crazyflie 2.0,
 // the constants defined here need to be in agreement with those defined in the
 // firmware running on the Crazyflie 2.0.
 // The following is a short description about each mode:
@@ -95,6 +95,18 @@
 #define RATE_MODE  7
 #define ANGLE_MODE 8
 
+// These constants define the controller used for computing the response in the
+// "calculateControlOutput" function
+// The following is a short description about each mode:
+// LQR_RATE_MODE      LQR controller based on the state vector:
+//                    [position,velocity,angles]
+//
+// LQR_ANGLE_MODE     LQR controller based on the state vector:
+//                    [position,velocity]
+//
+#define LQR_RATE_MODE   1   // (DEFAULT)
+#define LQR_ANGLE_MODE  2
+
 // Constants for feching the yaml paramters
 #define FETCH_YAML_SAFE_CONTROLLER_AGENT          1
 #define FETCH_YAML_CUSTOM_CONTROLLER_AGENT        2
@@ -122,15 +134,25 @@ std::vector<float> motorPoly(3);     // Coefficients of the 16-bit command to th
 float control_frequency;             // Frequency at which the controller is running
 float gravity_force;                 // The weight of the Crazyflie in Newtons, i.e., mg
 
-CrazyflieData previous_stateErrorInertial;     // The location error of the Crazyflie at the "previous" time step
+float previous_stateErrorInertial[9];     // The location error of the Crazyflie at the "previous" time step
 
 std::vector<float>  setpoint{0.0,0.0,0.4,0.0};     // The setpoints for (x,y,z) position and yaw angle, in that order
 
+
+// The controller type to run in the "calculateControlOutput" function
+int controller_type = LQR_RATE_MODE;
+
+// The LQR Controller parameters
+const float gainMatrixRollRate[9] = {0, -1.714330725, 0, 0, -1.337107465, 0, 5.115369735, 0, 0};
+const float gainMatrixPitchRate[9] = {1.714330725, 0, 0, 1.337107465, 0, 0, 0, 5.115369735, 0};
+const float gainMatrixYawRate[9] = {0, 0, 0, 0, 0, 0, 0, 0, 2.843099534};
+const float gainMatrixThrust_NineStateVector[9] = {0, 0, 0.22195826, 0, 0, 0.12362477, 0, 0, 0};
+
+
 // The LQR Controller parameters
-const float gainMatrixRoll[9] = {0, -1.714330725, 0, 0, -1.337107465, 0, 5.115369735, 0, 0};
-const float gainMatrixPitch[9] = {1.714330725, 0, 0, 1.337107465, 0, 0, 0, 5.115369735, 0};
-const float gainMatrixYaw[9] = {0, 0, 0, 0, 0, 0, 0, 0, 2.843099534};
-const float gainMatrixThrust[9] = {0, 0, 0.22195826, 0, 0, 0.12362477, 0, 0, 0};
+const float gainMatrixRollAngle[6] = {0, -1.714330725, 0, 0, -1.337107465, 0};
+const float gainMatrixPitchAngle[6] = {1.714330725, 0, 0, 1.337107465, 0, 0};
+const float gainMatrixThrust_SixStateVector[6] = {0, 0, 0.22195826, 0, 0, 0.12362477};
 
 // ROS Publisher for debugging variables
 ros::Publisher debugPublisher;
@@ -143,10 +165,22 @@ std::string namespace_to_own_agent_parameter_service;
 std::string namespace_to_coordinator_parameter_service;
 
 
+
+// VARIABLES RELATING TO PERFORMING THE CONVERSION INTO BODY FRAME
+
 // Boolean whether to execute the convert into body frame function
 bool shouldPerformConvertIntoBodyFrame = false;
 
 
+// VARIABLES RELATING TO THE PUBLISHING OF A DEBUG MESSAGE
+
+// Boolean indiciating whether the "Debug Message" of this agent should be published or not
+bool shouldPublishDebugMessage = false;
+
+// Boolean indiciating whether the debugging ROS_INFO_STREAM should be displayed or not
+bool shouldDisplayDebugInfo = false;
+
+
 // VARIABLES RELATING TO PUBLISHING CURRENT POSITION AND FOLLOWING ANOTHER AGENT'S
 // POSITION
 
@@ -183,7 +217,7 @@ ros::Subscriber xyz_yaw_to_follow_subscriber;
 
 
 // RELEVANT NOTES ABOUT THE VARIABLES DECLARE HERE:
-// The "CrazyflieData" type used for the "previous_stateErrorInertial" variable is a
+// The "CrazyflieData" type used for the "request" variable is a
 // structure as defined in the file "CrazyflieData.msg" which has the following
 // properties:
 //     string crazyflieName              The name given to the Crazyflie in the Vicon software
@@ -220,6 +254,10 @@ ros::Subscriber xyz_yaw_to_follow_subscriber;
 // written below in an order that ensure each function is implemented before it is
 // called from another function, hence why the "main" function is at the bottom.
 
+// CONTROLLER COMPUTATIONS
+bool calculateControlOutput(Controller::Request &request, Controller::Response &response);
+void calculateControlOutput_viaLQRforRates(stateErrorBody, Controller::Request &request, Controller::Response &response);
+
 // TRANSFORMATION OF THE (x,y) INERTIAL FRAME ERROR INTO AN (x,y) BODY FRAME ERROR
 void convertIntoBodyFrame(float stateInertial[9], float (&stateBody)[9], float yaw_measured);
 
@@ -364,270 +402,449 @@ void processFetchedParameters();
 // (CCW) | M3 |                       | M2 | (CW)
 //       \____/                       \____/
 //
-//   
+//
 //
 // This function WILL NEED TO BE edited for successful completion of the PPS exercise
-bool calculateControlOutput(Controller::Request &request, Controller::Response &response) {
+bool calculateControlOutput(Controller::Request &request, Controller::Response &response)
+{
 
-    // This is the "start" of the outer loop controller, add all your control
-    // computation here, or you may find it convienient to create functions
-    // to keep you code cleaner
-    
-    
-    // Define a local array to fill in with the state error
-    float stateErrorInertial[9];
-
-    // Fill in the (x,y,z) position error
-    stateErrorInertial[0] = request.ownCrazyflie.x - setpoint[0];
-    stateErrorInertial[1] = request.ownCrazyflie.y - setpoint[1];
-    stateErrorInertial[2] = request.ownCrazyflie.z - setpoint[2];
-
-    // Compute an estimate of the velocity
-    // > As simply the derivative between the current and previous position
-    stateErrorInertial[3] = (stateErrorInertial[0] - previous_stateErrorInertial.x) * control_frequency;
-    stateErrorInertial[4] = (stateErrorInertial[1] - previous_stateErrorInertial.y) * control_frequency;
-    stateErrorInertial[5] = (stateErrorInertial[2] - previous_stateErrorInertial.z) * control_frequency;
-
-    // Fill in the roll and pitch angle measurements directly
-    stateErrorInertial[6] = request.ownCrazyflie.roll;
-    stateErrorInertial[7] = request.ownCrazyflie.pitch;
-
-    // Fill in the yaw angle error
-    // > This error should be "unwrapped" to be in the range
-    //   ( -pi , pi )
-    // > First, get the yaw error into a local variable
-    float yawError = request.ownCrazyflie.yaw - setpoint[3];
-    // > Second, "unwrap" the yaw error to the interval ( -pi , pi )
-    while(yawError > PI) {yawError -= 2 * PI;}
-    while(yawError < -PI) {yawError += 2 * PI;}
-    // > Third, put the "yawError" into the "stateError" variable
-    stateErrorInertial[8] = yawError;
+	// This is the "start" of the outer loop controller, add all your control
+	// computation here, or you may find it convienient to create functions
+	// to keep you code cleaner
+
+
+	// Define a local array to fill in with the state error
+	float stateErrorInertial[9];
+
+	// Fill in the (x,y,z) position error
+	stateErrorInertial[0] = request.ownCrazyflie.x - setpoint[0];
+	stateErrorInertial[1] = request.ownCrazyflie.y - setpoint[1];
+	stateErrorInertial[2] = request.ownCrazyflie.z - setpoint[2];
+
+	// Compute an estimate of the velocity
+	// > As simply the derivative between the current and previous position
+	stateErrorInertial[3] = (stateErrorInertial[0] - previous_stateErrorInertial[0]) * control_frequency;
+	stateErrorInertial[4] = (stateErrorInertial[1] - previous_stateErrorInertial[1]) * control_frequency;
+	stateErrorInertial[5] = (stateErrorInertial[2] - previous_stateErrorInertial[2]) * control_frequency;
+
+	// Fill in the roll and pitch angle measurements directly
+	stateErrorInertial[6] = request.ownCrazyflie.roll;
+	stateErrorInertial[7] = request.ownCrazyflie.pitch;
+
+	// Fill in the yaw angle error
+	// > This error should be "unwrapped" to be in the range
+	//   ( -pi , pi )
+	// > First, get the yaw error into a local variable
+	float yawError = request.ownCrazyflie.yaw - setpoint[3];
+	// > Second, "unwrap" the yaw error to the interval ( -pi , pi )
+	while(yawError > PI) {yawError -= 2 * PI;}
+	while(yawError < -PI) {yawError += 2 * PI;}
+	// > Third, put the "yawError" into the "stateError" variable
+	stateErrorInertial[8] = yawError;
+
+
+	// CONVERSION INTO BODY FRAME
+	// Conver the state erorr from the Inertial frame into the Body frame
+	// > Note: the function "convertIntoBodyFrame" is implemented in this file
+	//   and by default does not perform any conversion. The equations to convert
+	//   the state error into the body frame should be implemented in that function
+	//   for successful completion of the PPS exercise
+	float stateErrorBody[9];
+	convertIntoBodyFrame(stateErrorInertial, stateErrorBody, request.ownCrazyflie.yaw);
+
+
+	// SAVE THE STATE ERROR TO BE USED NEXT TIME THIS FUNCTION IS CALLED
+	// > as we have already used previous error we can now update it update it
+	for(int i = 0; i < 9; ++i)
+	{
+		previous_stateErrorInertial[i] = stateErrorInertial[i];
+	}
 
-    
-    // CONVERSION INTO BODY FRAME
-    // Conver the state erorr from the Inertial frame into the Body frame
-    // > Note: the function "convertIntoBodyFrame" is implemented in this file
-    //   and by default does not perform any conversion. The equations to convert
-    //   the state error into the body frame should be implemented in that function
-    //   for successful completion of the PPS exercise
-    float stateErrorBody[9];
-    convertIntoBodyFrame(stateErrorInertial, stateErrorBody, request.ownCrazyflie.yaw);
 
 
+	// SWITCH BETWEEN THE DIFFERENT CONTROLLER TYPES:
+	switch (controller_type)
+	{
+		// LQR controller based on the state vector: [position,velocity,angles]
+		case LQR_RATE_MODE:
+		{
+			// Call the function that performs the control computations for this mode
+			calculateControlOutput_viaLQRforRates(stateErrorBody,request,response);
+			break;
+		}
 
+		// LQR controller based on the state vector: [position,velocity]
+		case LQR_ANGLE_MODE:
+		{
+			// Call the function that performs the control computations for this mode
+			calculateControlOutput_viaLQRforAngles(stateErrorBody,request,response);
+			break;
+		}
 
-    //  **********************
-    //  Y   Y    A    W     W
-    //   Y Y    A A   W     W
-    //    Y    A   A  W     W
-    //    Y    AAAAA   W W W
-    //    Y    A   A    W W
-    //
-    // YAW CONTROLLER
+		default:
+		{
+			// Display that the "controller_type" was not recognised
+			ROS_INFO_STREAM("ERROR: in the 'calculateControlOutput' function of the 'CustomControllerService': the 'controller_type' is not recognised.");
+			// Set everything in the response to zero
+			response.controlOutput.roll       =  0;
+			response.controlOutput.pitch      =  0;
+			response.controlOutput.yaw        =  0;
+			response.controlOutput.motorCmd1  =  0;
+			response.controlOutput.motorCmd2  =  0;
+			response.controlOutput.motorCmd3  =  0;
+			response.controlOutput.motorCmd4  =  0;
+			response.controlOutput.onboardControllerType = MOTOR_MODE;
+			break;
+		}
 
-    // Instantiate the local variable for the yaw rate that will be requested
-    // from the Crazyflie's on-baord "inner-loop" controller
-    float yawRate_forResponse = 0;
 
-    // Perform the "-Kx" LQR computation for the yaw rate to respoond with
-    for(int i = 0; i < 9; ++i)
-    {
-        yawRate_forResponse -= gainMatrixYaw[i] * stateErrorBody[i];
-    }
 
-    // Put the computed yaw rate into the "response" variable
-    response.controlOutput.yaw = yawRate_forResponse;
+	}
 
 
 
+	
 
-    //  **************************************
-    //  BBBB    OOO   DDDD   Y   Y       ZZZZZ
-    //  B   B  O   O  D   D   Y Y           Z
-    //  BBBB   O   O  D   D    Y           Z
-    //  B   B  O   O  D   D    Y          Z
-    //  BBBB    OOO   DDDD     Y         ZZZZZ
-    //
-    // ALITUDE CONTROLLER (i.e., z-controller)
 
-    // Instantiate the local variable for the thrust adjustment that will be
-    // requested from the Crazyflie's on-baord "inner-loop" controller
-    float thrustAdjustment = 0;
 
-    // Perform the "-Kx" LQR computation for the thrust adjustment to respoond with
-    for(int i = 0; i < 9; ++i)
-    {
-        thrustAdjustment -= gainMatrixThrust[i] * stateErrorBody[i];
-    }
+	//  ************************************************************************************************
+	//  PPPP   U   U  BBBB   L      III   SSSS  H  H       X   X  Y   Y  ZZZZZ     Y   Y    A    W     W
+	//  P   P  U   U  B   B  L       I   S      H  H        X X    Y Y      Z       Y Y    A A   W     W
+	//  PPPP   U   U  BBBB   L       I    SSS   HHHH         X      Y      Z         Y    A   A  W     W
+	//  P      U   U  B   B  L       I       S  H  H        X X     Y     Z          Y    AAAAA   W W W
+	//  P       UUU   BBBB   LLLLL  III  SSSS   H  H       X   X    Y    ZZZZZ       Y    A   A    W W
 
-    // Put the computed thrust adjustment into the "response" variable,
-    // as well as adding 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.
-    // > NOTE: the "gravity_force" value was already divided by 4 when is was
-    //         loaded from the .yaml file via the "fetchYamlParameters"
-    //         class function in this file.
-    response.controlOutput.motorCmd1 = computeMotorPolyBackward(thrustAdjustment + gravity_force);
-    response.controlOutput.motorCmd2 = computeMotorPolyBackward(thrustAdjustment + gravity_force);
-    response.controlOutput.motorCmd3 = computeMotorPolyBackward(thrustAdjustment + gravity_force);
-    response.controlOutput.motorCmd4 = computeMotorPolyBackward(thrustAdjustment + gravity_force);
-
-
-
-
-    //  **************************************
-    //  BBBB    OOO   DDDD   Y   Y       X   X
-    //  B   B  O   O  D   D   Y Y         X X
-    //  BBBB   O   O  D   D    Y           X
-    //  B   B  O   O  D   D    Y          X X
-    //  BBBB    OOO   DDDD     Y         X   X
-    //
-    // BODY FRAME X CONTROLLER
-
-    // Instantiate the local variable for the pitch rate that will be requested
-    // from the Crazyflie's on-baord "inner-loop" controller
-    float pitchRate_forResponse = 0;
-    
-    // Perform the "-Kx" LQR computation for the pitch rate to respoond with
-    for(int i = 0; i < 9; ++i)
+	// PUBLISH THE CURRENT X,Y,Z, AND YAW (if required)
+	if (shouldPublishCurrent_xyz_yaw)
+	{
+		// publish setpoint for FollowController of another student group
+		Setpoint temp_current_xyz_yaw;
+		// Fill in the x,y,z, and yaw info directly from the data provided to this
+		// function
+		temp_current_xyz_yaw.x   = request.ownCrazyflie.x;
+		temp_current_xyz_yaw.y   = request.ownCrazyflie.y;
+		temp_current_xyz_yaw.z   = request.ownCrazyflie.z;
+		temp_current_xyz_yaw.yaw = request.ownCrazyflie.yaw;
+		my_current_xyz_yaw_publisher.publish(temp_current_xyz_yaw);
+	}
+
+
+
+
+	//  ***********************************************************
+	//  DDDD   EEEEE  BBBB   U   U   GGGG       M   M   SSSS   GGGG
+	//  D   D  E      B   B  U   U  G           MM MM  S      G
+	//  D   D  EEE    BBBB   U   U  G           M M M   SSS   G
+	//  D   D  E      B   B  U   U  G   G       M   M      S  G   G
+	//  DDDD   EEEEE  BBBB    UUU    GGGG       M   M  SSSS    GGGG
+
+    // DEBUGGING CODE:
+    // As part of the D-FaLL-System we have defined a message type names"DebugMsg".
+    // By fill this message with data and publishing it you can display the data in
+    // real time using rpt plots. Instructions for using rqt plots can be found on
+    // the wiki of the D-FaLL-System repository
+    if (shouldPublishDebugMessage)
     {
-        pitchRate_forResponse -= gainMatrixPitch[i] * stateErrorBody[i];
-    }
+		// Instantiate a local variable of type "DebugMsg", see the file "DebugMsg.msg"
+		// (located in the "msg" folder) to see the full structure of this message.
+		DebugMsg debugMsg;
+
+		// Fill the debugging message with the data provided by Vicon
+		debugMsg.vicon_x = request.ownCrazyflie.x;
+		debugMsg.vicon_y = request.ownCrazyflie.y;
+		debugMsg.vicon_z = request.ownCrazyflie.z;
+		debugMsg.vicon_roll = request.ownCrazyflie.roll;
+		debugMsg.vicon_pitch = request.ownCrazyflie.pitch;
+		debugMsg.vicon_yaw = request.ownCrazyflie.yaw;
+
+		// Fill in the debugging message with any other data you would like to display
+		// in real time. For example, it might be useful to display the thrust
+		// adjustment computed by the z-altitude controller.
+		// The "DebugMsg" type has 10 properties from "value_1" to "value_10", all of
+		// type "float64" that you can fill in with data you would like to plot in
+		// real-time.
+		// debugMsg.value_1 = thrustAdjustment;
+		// ......................
+		// debugMsg.value_10 = your_variable_name;
+
+		// Publish the "debugMsg"
+		debugPublisher.publish(debugMsg);
+	}
+
+
+	// An alternate debugging technique is to print out data directly to the
+	// command line from which this node was launched.
+	if (shouldDisplayDebugInfo)
+	{
+		// An example of "printing out" the data from the "request" argument to the
+		// command line. This might be useful for debugging.
+		ROS_INFO_STREAM("x-coordinates: " << request.ownCrazyflie.x);
+		ROS_INFO_STREAM("y-coordinates: " << request.ownCrazyflie.y);
+		ROS_INFO_STREAM("z-coordinates: " << request.ownCrazyflie.z);
+		ROS_INFO_STREAM("roll: " << request.ownCrazyflie.roll);
+		ROS_INFO_STREAM("pitch: " << request.ownCrazyflie.pitch);
+		ROS_INFO_STREAM("yaw: " << request.ownCrazyflie.yaw);
+		ROS_INFO_STREAM("Delta t: " << request.ownCrazyflie.acquiringTime);
+
+		// An example of "printing out" the control actions computed.
+		ROS_INFO_STREAM("thrustAdjustment = " << thrustAdjustment);
+		ROS_INFO_STREAM("controlOutput.roll = " << response.controlOutput.roll);
+		ROS_INFO_STREAM("controlOutput.pitch = " << response.controlOutput.pitch);
+		ROS_INFO_STREAM("controlOutput.yaw = " << response.controlOutput.yaw);
+
+		// An example of "printing out" the "thrust-to-command" conversion parameters.
+		ROS_INFO_STREAM("motorPoly 0:" << motorPoly[0]);
+		ROS_INFO_STREAM("motorPoly 0:" << motorPoly[1]);
+		ROS_INFO_STREAM("motorPoly 0:" << motorPoly[2]);
+
+		// An example of "printing out" the per motor 16-bit command computed.
+		ROS_INFO_STREAM("controlOutput.cmd1 = " << response.controlOutput.motorCmd1);
+		ROS_INFO_STREAM("controlOutput.cmd3 = " << response.controlOutput.motorCmd2);
+		ROS_INFO_STREAM("controlOutput.cmd2 = " << response.controlOutput.motorCmd3);
+		ROS_INFO_STREAM("controlOutput.cmd4 = " << response.controlOutput.motorCmd4);
+	}
+
+	// Return "true" to indicate that the control computation was performed successfully
+	return true;
+}
+
+
+
+
+
+void calculateControlOutput_viaLQRforRates(stateErrorBody, Controller::Request &request, Controller::Response &response)
+{
+	//  **********************
+	//  Y   Y    A    W     W
+	//   Y Y    A A   W     W
+	//    Y    A   A  W     W
+	//    Y    AAAAA   W W W
+	//    Y    A   A    W W
+	//
+	// YAW CONTROLLER
+
+	// Instantiate the local variable for the yaw rate that will be requested
+	// from the Crazyflie's on-baord "inner-loop" controller
+	float yawRate_forResponse = 0;
+
+	// Perform the "-Kx" LQR computation for the yaw rate to respoond with
+	for(int i = 0; i < 9; ++i)
+	{
+		yawRate_forResponse -= gainMatrixYawRate[i] * stateErrorBody[i];
+	}
+
+	// Put the computed yaw rate into the "response" variable
+	response.controlOutput.yaw = yawRate_forResponse;
 
-    // Put the computed pitch rate into the "response" variable
-    response.controlOutput.pitch = pitchRate_forResponse;
-    
 
 
 
 	//  **************************************
-    //  BBBB    OOO   DDDD   Y   Y       Y   Y
-    //  B   B  O   O  D   D   Y Y         Y Y
-    //  BBBB   O   O  D   D    Y           Y
-    //  B   B  O   O  D   D    Y           Y
-    //  BBBB    OOO   DDDD     Y           Y
-    //
-    // BODY FRAME Y CONTROLLER
-
-    // Instantiate the local variable for the roll rate that will be requested
-    // from the Crazyflie's on-baord "inner-loop" controller
-    float rollRate_forResponse = 0;
-    
-    // Perform the "-Kx" LQR computation for the roll rate to respoond with
-    for(int i = 0; i < 9; ++i)
-    {
-        rollRate_forResponse -= gainMatrixRoll[i] * stateErrorBody[i];
-    }
+	//  BBBB    OOO   DDDD   Y   Y       ZZZZZ
+	//  B   B  O   O  D   D   Y Y           Z
+	//  BBBB   O   O  D   D    Y           Z
+	//  B   B  O   O  D   D    Y          Z
+	//  BBBB    OOO   DDDD     Y         ZZZZZ
+	//
+	// ALITUDE CONTROLLER (i.e., z-controller)
+
+	// Instantiate the local variable for the thrust adjustment that will be
+	// requested from the Crazyflie's on-baord "inner-loop" controller
+	float thrustAdjustment = 0;
+
+	// Perform the "-Kx" LQR computation for the thrust adjustment to respoond with
+	for(int i = 0; i < 9; ++i)
+	{
+		thrustAdjustment -= gainMatrixThrust_NineStateVector[i] * stateErrorBody[i];
+	}
 
-    // Put the computed roll rate into the "response" variable
-    response.controlOutput.roll = rollRate_forResponse;
-    
-    
+	// Put the computed thrust adjustment into the "response" variable,
+	// as well as adding 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.
+	// > NOTE: the "gravity_force" value was already divided by 4 when is was
+	//         loaded from the .yaml file via the "fetchYamlParameters"
+	//         class function in this file.
+	response.controlOutput.motorCmd1 = computeMotorPolyBackward(thrustAdjustment + gravity_force);
+	response.controlOutput.motorCmd2 = computeMotorPolyBackward(thrustAdjustment + gravity_force);
+	response.controlOutput.motorCmd3 = computeMotorPolyBackward(thrustAdjustment + gravity_force);
+	response.controlOutput.motorCmd4 = computeMotorPolyBackward(thrustAdjustment + gravity_force);
 
 
 
-    // PREPARE AND RETURN THE VARIABLE "response"
 
-    /*choosing the Crazyflie onBoard controller type.
-    it can either be Motor, Rate or Angle based */
-    // response.controlOutput.onboardControllerType = MOTOR_MODE;
-    response.controlOutput.onboardControllerType = RATE_MODE;
-    // response.controlOutput.onboardControllerType = ANGLE_MODE;
+	//  **************************************
+	//  BBBB    OOO   DDDD   Y   Y       X   X
+	//  B   B  O   O  D   D   Y Y         X X
+	//  BBBB   O   O  D   D    Y           X
+	//  B   B  O   O  D   D    Y          X X
+	//  BBBB    OOO   DDDD     Y         X   X
+	//
+	// BODY FRAME X CONTROLLER
+
+	// Instantiate the local variable for the pitch rate that will be requested
+	// from the Crazyflie's on-baord "inner-loop" controller
+	float pitchRate_forResponse = 0;
+
+	// Perform the "-Kx" LQR computation for the pitch rate to respoond with
+	for(int i = 0; i < 9; ++i)
+	{
+		pitchRate_forResponse -= gainMatrixPitchRate[i] * stateErrorBody[i];
+	}
 
-    
-    // SAVE THE STATE ERROR TO BE USED NEXT TIME THIS FUNCTION IS CALLED
-    previous_stateErrorInertial = request.ownCrazyflie; // we have already used previous location, update it
+	// Put the computed pitch rate into the "response" variable
+	response.controlOutput.pitch = pitchRate_forResponse;
 
-    // Adjust (x,y,z) for the stepoint
-    previous_stateErrorInertial.x = request.ownCrazyflie.x - setpoint[0];
-    previous_stateErrorInertial.y = request.ownCrazyflie.y - setpoint[1];
-    previous_stateErrorInertial.z = request.ownCrazyflie.z - setpoint[2];
 
-    // Adjust yaw for the stepoint
-    previous_stateErrorInertial.yaw = stateErrorInertial[8];
 
 
+	//  **************************************
+	//  BBBB    OOO   DDDD   Y   Y       Y   Y
+	//  B   B  O   O  D   D   Y Y         Y Y
+	//  BBBB   O   O  D   D    Y           Y
+	//  B   B  O   O  D   D    Y           Y
+	//  BBBB    OOO   DDDD     Y           Y
+	//
+	// BODY FRAME Y CONTROLLER
+
+	// Instantiate the local variable for the roll rate that will be requested
+	// from the Crazyflie's on-baord "inner-loop" controller
+	float rollRate_forResponse = 0;
+
+	// Perform the "-Kx" LQR computation for the roll rate to respoond with
+	for(int i = 0; i < 9; ++i)
+	{
+		rollRate_forResponse -= gainMatrixRollRate[i] * stateErrorBody[i];
+	}
 
-    // PUBLISH THE CURRENT X,Y,Z, AND YAW (if required)
-    if (shouldPublishCurrent_xyz_yaw)
-    {
-	    // publish setpoint for FollowController of another student group
-	    Setpoint temp_current_xyz_yaw;
-	    // Fill in the x,y,z, and yaw info directly from the data provided to this
-	    // function
-	    temp_current_xyz_yaw.x   = request.ownCrazyflie.x;
-	    temp_current_xyz_yaw.y   = request.ownCrazyflie.y;
-	    temp_current_xyz_yaw.z   = request.ownCrazyflie.z;
-	    temp_current_xyz_yaw.yaw = request.ownCrazyflie.yaw;
-	    my_current_xyz_yaw_publisher.publish(temp_current_xyz_yaw);
+	// Put the computed roll rate into the "response" variable
+	response.controlOutput.roll = rollRate_forResponse;
+
+
+
+
+	// PREPARE AND RETURN THE VARIABLE "response"
+
+	/*choosing the Crazyflie onBoard controller type.
+	it can either be Motor, Rate or Angle based */
+	// response.controlOutput.onboardControllerType = MOTOR_MODE;
+	response.controlOutput.onboardControllerType = RATE_MODE;
+	// response.controlOutput.onboardControllerType = ANGLE_MODE;
+}
+
+
+
+
+void calculateControlOutput_viaLQRforAngles(stateErrorBody, Controller::Request &request, Controller::Response &response)
+{
+	//  **********************
+	//  Y   Y    A    W     W
+	//   Y Y    A A   W     W
+	//    Y    A   A  W     W
+	//    Y    AAAAA   W W W
+	//    Y    A   A    W W
+	//
+	// YAW CONTROLLER
+
+	// Put the yaw setpoint directly as the response
+	response.controlOutput.yaw = setpoint[3];
+
+
+
+
+	//  **************************************
+	//  BBBB    OOO   DDDD   Y   Y       ZZZZZ
+	//  B   B  O   O  D   D   Y Y           Z
+	//  BBBB   O   O  D   D    Y           Z
+	//  B   B  O   O  D   D    Y          Z
+	//  BBBB    OOO   DDDD     Y         ZZZZZ
+	//
+	// ALITUDE CONTROLLER (i.e., z-controller)
+
+	// Instantiate the local variable for the thrust adjustment that will be
+	// requested from the Crazyflie's on-baord "inner-loop" controller
+	float thrustAdjustment = 0;
+
+	// Perform the "-Kx" LQR computation for the thrust adjustment to respoond with
+	for(int i = 0; i < 6; ++i)
+	{
+		thrustAdjustment -= gainMatrixThrust_SixStateVector[i] * stateErrorBody[i];
 	}
 
+	// Put the computed thrust adjustment into the "response" variable,
+	// as well as adding 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.
+	// > NOTE: the "gravity_force" value was already divided by 4 when is was
+	//         loaded from the .yaml file via the "fetchYamlParameters"
+	//         class function in this file.
+	response.controlOutput.motorCmd1 = computeMotorPolyBackward(thrustAdjustment + gravity_force);
+	response.controlOutput.motorCmd2 = computeMotorPolyBackward(thrustAdjustment + gravity_force);
+	response.controlOutput.motorCmd3 = computeMotorPolyBackward(thrustAdjustment + gravity_force);
+	response.controlOutput.motorCmd4 = computeMotorPolyBackward(thrustAdjustment + gravity_force);
 
-    // DEBUGGING CODE:
-    // As part of the D-FaLL-System we have defined a message type names"DebugMsg".
-    // By fill this message with data and publishing it you can display the data in
-    // real time using rpt plots. Instructions for using rqt plots can be found on
-    // the wiki of the D-FaLL-System repository
 
-    // Instantiate a local variable of type "DebugMsg", see the file "DebugMsg.msg"
-    // (located in the "msg" folder) to see the full structure of this message.
-    DebugMsg debugMsg;
-
-    // Fill the debugging message with the data provided by Vicon
-    debugMsg.vicon_x = request.ownCrazyflie.x;
-    debugMsg.vicon_y = request.ownCrazyflie.y;
-    debugMsg.vicon_z = request.ownCrazyflie.z;
-    debugMsg.vicon_roll = request.ownCrazyflie.roll;
-    debugMsg.vicon_pitch = request.ownCrazyflie.pitch;
-    debugMsg.vicon_yaw = request.ownCrazyflie.yaw;
-
-    // Fill in the debugging message with any other data you would like to display
-    // in real time. For example, it might be useful to display the thrust
-    // adjustment computed by the z-altitude controller.
-    // The "DebugMsg" type has 10 properties from "value_1" to "value_10", all of
-    // type "float64" that you can fill in with data you would like to plot in
-    // real-time.
-    // debugMsg.value_1 = thrustAdjustment;
-    // ......................
-    // debugMsg.value_10 = your_variable_name;
-
-    // Publish the "debugMsg"
-    debugPublisher.publish(debugMsg);
-
-
-    // An alternate debugging technique is to print out data directly to the
-    // command line from which this node was launched.
-
-    // An example of "printing out" the data from the "request" argument to the
-    // command line. This might be useful for debugging.
-    // ROS_INFO_STREAM("x-coordinates: " << request.ownCrazyflie.x);
-    // ROS_INFO_STREAM("y-coordinates: " << request.ownCrazyflie.y);
-    // ROS_INFO_STREAM("z-coordinates: " << request.ownCrazyflie.z);
-    // ROS_INFO_STREAM("roll: " << request.ownCrazyflie.roll);
-    // ROS_INFO_STREAM("pitch: " << request.ownCrazyflie.pitch);
-    // ROS_INFO_STREAM("yaw: " << request.ownCrazyflie.yaw);
-    // ROS_INFO_STREAM("Delta t: " << request.ownCrazyflie.acquiringTime);
-
-    // An example of "printing out" the control actions computed.
-    // ROS_INFO_STREAM("thrustAdjustment = " << thrustAdjustment);
-    // ROS_INFO_STREAM("controlOutput.roll = " << response.controlOutput.roll);
-    // ROS_INFO_STREAM("controlOutput.pitch = " << response.controlOutput.pitch);
-    // ROS_INFO_STREAM("controlOutput.yaw = " << response.controlOutput.yaw);
-
-    // An example of "printing out" the "thrust-to-command" conversion parameters.
-    // ROS_INFO_STREAM("motorPoly 0:" << motorPoly[0]);
-    // ROS_INFO_STREAM("motorPoly 0:" << motorPoly[1]);
-    // ROS_INFO_STREAM("motorPoly 0:" << motorPoly[2]);
-
-    // An example of "printing out" the per motor 16-bit command computed.
-    // ROS_INFO_STREAM("controlOutput.cmd1 = " << response.controlOutput.motorCmd1);
-    // ROS_INFO_STREAM("controlOutput.cmd3 = " << response.controlOutput.motorCmd2);
-    // ROS_INFO_STREAM("controlOutput.cmd2 = " << response.controlOutput.motorCmd3);
-    // ROS_INFO_STREAM("controlOutput.cmd4 = " << response.controlOutput.motorCmd4);
-
-    // Return "true" to indicate that the control computation was performed successfully
-    return true;
+
+
+	//  **************************************
+	//  BBBB    OOO   DDDD   Y   Y       X   X
+	//  B   B  O   O  D   D   Y Y         X X
+	//  BBBB   O   O  D   D    Y           X
+	//  B   B  O   O  D   D    Y          X X
+	//  BBBB    OOO   DDDD     Y         X   X
+	//
+	// BODY FRAME X CONTROLLER
+
+	// Instantiate the local variable for the pitch angle that will be requested
+	// from the Crazyflie's on-baord "inner-loop" controller
+	float pitchAngle_forResponse = 0;
+
+	// Perform the "-Kx" LQR computation for the pitch angle to respoond with
+	for(int i = 0; i < 6; ++i)
+	{
+		pitchAngle_forResponse -= gainMatrixPitchAngle[i] * stateErrorBody[i];
+	}
+
+	// Put the computed pitch angle into the "response" variable
+	response.controlOutput.pitch = pitchAngle_forResponse;
+
+
+
+
+	//  **************************************
+	//  BBBB    OOO   DDDD   Y   Y       Y   Y
+	//  B   B  O   O  D   D   Y Y         Y Y
+	//  BBBB   O   O  D   D    Y           Y
+	//  B   B  O   O  D   D    Y           Y
+	//  BBBB    OOO   DDDD     Y           Y
+	//
+	// BODY FRAME Y CONTROLLER
+
+	// Instantiate the local variable for the roll angle that will be requested
+	// from the Crazyflie's on-baord "inner-loop" controller
+	float rollAngle_forResponse = 0;
+
+	// Perform the "-Kx" LQR computation for the roll angle to respoond with
+	for(int i = 0; i < 6; ++i)
+	{
+		rollAngle_forResponse -= gainMatrixRollAngle[i] * stateErrorBody[i];
+	}
+
+	// Put the computed roll angle into the "response" variable
+	response.controlOutput.roll = rollAngle_forResponse;
+
+
+
+
+	// PREPARE AND RETURN THE VARIABLE "response"
+
+	/*choosing the Crazyflie onBoard controller type.
+	it can either be Motor, Rate or Angle based */
+	//response.controlOutput.onboardControllerType = MOTOR_MODE;
+	//response.controlOutput.onboardControllerType = RATE_MODE;
+	response.controlOutput.onboardControllerType = ANGLE_MODE;
 }
 
 
@@ -893,6 +1110,15 @@ void fetchYamlParameters(ros::NodeHandle& nodeHandle)
     	ROS_ERROR_STREAM("parameter 'follow_in_a_line_agentIDs' was loaded with two different lengths, " << temp_number_of_agents_in_a_line << " versus " << follow_in_a_line_agentIDs.size() );
     }
 
+    // A flag for which controller to use, defined as:
+    controller_type = getParameterInt( nodeHandle_for_customController , "controller_type" );
+
+    // Boolean indiciating whether the "Debug Message" of this agent should be published or not
+	shouldPublishDebugMessage = getParameterBool(nodeHandle_for_customController, "shouldPublishDebugMessage");
+
+    // Boolean indiciating whether the debugging ROS_INFO_STREAM should be displayed or not
+	shouldDisplayDebugInfo = getParameterBool(nodeHandle_for_customController, "shouldDisplayDebugInfo");
+
     // DEBUGGING: Print out one of the parameters that was loaded
     ROS_INFO_STREAM("DEBUGGING: the fetched SafeController/mass = " << cf_mass);