diff --git a/pps_ws/src/d_fall_pps/CMakeLists.txt b/pps_ws/src/d_fall_pps/CMakeLists.txt
index 3e92c2eb1509ae3176e774a68ff1bbbff0bb5dc5..a7bf2d91b3d142b568509e5d4efc270bf221a6fb 100755
--- a/pps_ws/src/d_fall_pps/CMakeLists.txt
+++ b/pps_ws/src/d_fall_pps/CMakeLists.txt
@@ -134,7 +134,6 @@ add_message_files(
   CrazyflieDB.msg
   #----------------------------------------------------------------------
   DebugMsg.msg
-  CustomControllerYAML.msg
   CustomButton.msg
 )
 
@@ -238,12 +237,9 @@ include_directories(
 add_executable(ViconDataPublisher src/ViconDataPublisher.cpp)
 add_executable(PPSClient src/PPSClient.cpp)
 add_executable(SafeControllerService src/SafeControllerService.cpp)
-add_executable(CustomControllerService src/CustomControllerService.cpp)
+add_executable(DemoControllerService src/DemoControllerService.cpp)
 add_executable(CentralManagerService src/CentralManagerService.cpp src/CrazyflieIO.cpp)
 add_executable(ParameterService src/ParameterService.cpp)
-add_executable(CircleControllerService src/CircleControllerService.cpp)
-add_executable(FollowCrazyflieService src/FollowCrazyflieService.cpp)
-add_executable(FollowN_1Service src/FollowN_1Service.cpp)
 
 
 
@@ -287,12 +283,9 @@ qt5_use_modules(student_GUI Widgets)
 add_dependencies(ViconDataPublisher d_fall_pps_generate_messages_cpp ${catkin_EXPORTED_TARGETS})
 add_dependencies(PPSClient d_fall_pps_generate_messages_cpp ${catkin_EXPORTED_TARGETS})
 add_dependencies(SafeControllerService d_fall_pps_generate_messages_cpp ${catkin_EXPORTED_TARGETS})
-add_dependencies(CustomControllerService d_fall_pps_generate_messages_cpp ${catkin_EXPORTED_TARGETS})
+add_dependencies(DemoControllerService d_fall_pps_generate_messages_cpp ${catkin_EXPORTED_TARGETS})
 add_dependencies(CentralManagerService d_fall_pps_generate_messages_cpp ${catkin_EXPORTED_TARGETS})
 add_dependencies(ParameterService d_fall_pps_generate_messages_cpp ${catkin_EXPORTED_TARGETS})
-add_dependencies(CircleControllerService d_fall_pps_generate_messages_cpp ${catkin_EXPORTED_TARGETS})
-add_dependencies(FollowCrazyflieService d_fall_pps_generate_messages_cpp ${catkin_EXPORTED_TARGETS})
-add_dependencies(FollowN_1Service d_fall_pps_generate_messages_cpp ${catkin_EXPORTED_TARGETS})
 
 # GUI-- dependencies
 add_dependencies(my_GUI d_fall_pps_generate_messages_cpp ${catkin_EXPORTED_TARGETS})
@@ -324,18 +317,12 @@ target_link_libraries(PPSClient ${catkin_LIBRARIES})
 
 target_link_libraries(SafeControllerService ${catkin_LIBRARIES})
 
-target_link_libraries(CustomControllerService ${catkin_LIBRARIES})
+target_link_libraries(DemoControllerService ${catkin_LIBRARIES})
 
 target_link_libraries(CentralManagerService ${catkin_LIBRARIES})
 
 target_link_libraries(ParameterService ${catkin_LIBRARIES})
 
-target_link_libraries(CircleControllerService ${catkin_LIBRARIES})
-
-target_link_libraries(FollowCrazyflieService ${catkin_LIBRARIES})
-
-target_link_libraries(FollowN_1Service ${catkin_LIBRARIES})
-
 # GUI -- link libraries
 target_link_libraries(my_GUI Qt5::Widgets) # GUI -- let my_GUI have acesss to Qt stuff
 target_link_libraries(my_GUI Qt5::Svg)
diff --git a/pps_ws/src/d_fall_pps/launch/Crazyflie.launch b/pps_ws/src/d_fall_pps/launch/Crazyflie.launch
deleted file mode 100755
index 003fc84e62208be400ab6a671b2cb5caf21f7131..0000000000000000000000000000000000000000
--- a/pps_ws/src/d_fall_pps/launch/Crazyflie.launch
+++ /dev/null
@@ -1,33 +0,0 @@
-<launch>
-	<node pkg="d_fall_pps" name="CentralManagerService" output="screen" type="CentralManagerService">
-	</node>
-
-	<node pkg="d_fall_pps" name="CrazyRadio" output="screen" type="CrazyRadio.py">
-		<rosparam command="load" file="$(find d_fall_pps)/param/ClientConfig.yaml" />
-	</node>
-
-	<node pkg="d_fall_pps" name="ViconDataPublisher" output="screen" type="ViconDataPublisher">
-		<rosparam command="load" file="$(find d_fall_pps)/param/ViconConfig.yaml" />
-	</node>
-
-	<node pkg="d_fall_pps" name="PPSClient" output="screen" type="PPSClient">
-		<rosparam command="load" file="$(find d_fall_pps)/param/ClientConfig.yaml" />
-	</node>
-
-
-	<node pkg="d_fall_pps" name="SafeControllerService" output="screen" type="SafeControllerService">
-		<rosparam command="load" file="$(find d_fall_pps)/param/SafeController.yaml" />
-	</node>
-
-	<node pkg="d_fall_pps" name="CustomControllerService" output="screen" type="CustomControllerService">
-	</node>
-
-
-	<node pkg="rqt_plot" name="commandplotter" type="rqt_plot" args="/PPSClient/ControlCommand/roll /PPSClient/ControlCommand/pitch /PPSClient/ControlCommand/yaw" />
-
-	<!-- When we have a GUI, this has to be adapted and included -->
-	<node pkg="d_fall_pps" name="my_GUI" output="screen" type="my_GUI">
-		<!-- <rosparam command="load" file="$(find d_fall_pps)/launch/ControlParams.yaml" /> -->
-	</node>
-
-</launch>
diff --git a/pps_ws/src/d_fall_pps/launch/FollowN_1.launch b/pps_ws/src/d_fall_pps/launch/FollowN_1.launch
deleted file mode 100644
index 750e4db856d11fe383b10fa7bcbae7ce739563f3..0000000000000000000000000000000000000000
--- a/pps_ws/src/d_fall_pps/launch/FollowN_1.launch
+++ /dev/null
@@ -1,28 +0,0 @@
-<launch>
-
-	<node pkg="d_fall_pps" name="CrazyRadio" output="screen" type="CrazyRadio.py">
-		<rosparam command="load" file="$(find d_fall_pps)/param/ClientConfig.yaml" />
-	</node>
-
-	<node pkg="d_fall_pps" name="PPSClient" output="screen" type="PPSClient">
-		<rosparam command="load" file="$(find d_fall_pps)/param/ClientConfig.yaml" />
-		<param name="studentID" value="$(optenv ROS_NAMESPACE)" />
-	</node>
-
-	<node pkg="d_fall_pps" name="SafeControllerService" output="screen" type="SafeControllerService">
-		<rosparam command="load" file="$(find d_fall_pps)/param/SafeController.yaml" />
-	</node>
-
-	<node pkg="d_fall_pps" name="FollowN_1Service" output="screen" type="FollowN_1Service">
-		<rosparam command="load" file="$(find d_fall_pps)/param/SafeController.yaml" />
-	</node>
-
-    <!-- When we have a GUI, this has to be adapted and included -->
-	<node pkg="d_fall_pps" name="student_GUI" output="screen" type="student_GUI">
-		<!-- <rosparam command="load" file="$(find d_fall_pps)/launch/ControlParams.yaml" /> -->
-	</node>
-
-
-	<!-- <node pkg="rqt_plot" name="commandplotter" type="rqt_plot" args="/PPSClient/ControlCommand/roll /PPSClient/ControlCommand/pitch /PPSClient/ControlCommand/yaw" /> -->
-
-</launch>
diff --git a/pps_ws/src/d_fall_pps/launch/Student.launch b/pps_ws/src/d_fall_pps/launch/Student.launch
index 918c01067471dccce718677c983b50457b531112..11c72653e12e4c278b465ae06f3cb87b4d26276a 100755
--- a/pps_ws/src/d_fall_pps/launch/Student.launch
+++ b/pps_ws/src/d_fall_pps/launch/Student.launch
@@ -24,7 +24,7 @@
 		<param name="type" type="str" value="agent" />
 		<param name="agentID" value="$(optenv ROS_NAMESPACE)" />
 		<rosparam command="load" file="$(find d_fall_pps)/param/SafeController.yaml" ns="SafeController" />
-		<rosparam command="load" file="$(find d_fall_pps)/param/CustomController.yaml" ns="CustomController" />
+		<rosparam command="load" file="$(find d_fall_pps)/param/DemoController.yaml" ns="CustomController" />
 	</node>
 
 	<!-- AGENT GUI (aka. the "student GUI") -->
diff --git a/pps_ws/src/d_fall_pps/launch/StudentCircle.launch b/pps_ws/src/d_fall_pps/launch/StudentCircle.launch
deleted file mode 100755
index 70a9972edcef1a8cc3705c89a4496c42efa60eea..0000000000000000000000000000000000000000
--- a/pps_ws/src/d_fall_pps/launch/StudentCircle.launch
+++ /dev/null
@@ -1,23 +0,0 @@
-<launch>
-
-	<node pkg="d_fall_pps" name="CrazyRadio" output="screen" type="CrazyRadio.py">
-		<rosparam command="load" file="$(find d_fall_pps)/param/ClientConfig.yaml" />
-	</node>
-
-	<node pkg="d_fall_pps" name="PPSClient" output="screen" type="PPSClient">
-		<rosparam command="load" file="$(find d_fall_pps)/param/ClientConfig.yaml" />
-		<param name="studentID" value="$(optenv ROS_NAMESPACE)" />
-	</node>
-
-	<node pkg="d_fall_pps" name="SafeControllerService" output="screen" type="SafeControllerService">
-		<rosparam command="load" file="$(find d_fall_pps)/param/SafeController.yaml" />
-	</node>
-
-	<node pkg="d_fall_pps" name="CircleControllerService" output="screen" type="CircleControllerService">
-		<rosparam command="load" file="$(find d_fall_pps)/param/SafeController.yaml" />
-	</node>
-
-
-	<!-- <node pkg="rqt_plot" name="commandplotter" type="rqt_plot" args="/PPSClient/ControlCommand/roll /PPSClient/ControlCommand/pitch /PPSClient/ControlCommand/yaw" /> -->
-
-</launch>
diff --git a/pps_ws/src/d_fall_pps/launch/StudentFollow.launch b/pps_ws/src/d_fall_pps/launch/StudentFollow.launch
deleted file mode 100755
index 0dbd33c73925fb2619fb445cda3c1f7ab000d130..0000000000000000000000000000000000000000
--- a/pps_ws/src/d_fall_pps/launch/StudentFollow.launch
+++ /dev/null
@@ -1,23 +0,0 @@
-<launch>
-
-	<node pkg="d_fall_pps" name="CrazyRadio" output="screen" type="CrazyRadio.py">
-		<rosparam command="load" file="$(find d_fall_pps)/param/ClientConfig.yaml" />
-	</node>
-
-	<node pkg="d_fall_pps" name="PPSClient" output="screen" type="PPSClient">
-		<rosparam command="load" file="$(find d_fall_pps)/param/ClientConfig.yaml" />
-		<param name="studentID" value="$(optenv ROS_NAMESPACE)" />
-	</node>
-
-	<node pkg="d_fall_pps" name="SafeControllerService" output="screen" type="SafeControllerService">
-		<rosparam command="load" file="$(find d_fall_pps)/param/SafeController.yaml" />
-	</node>
-
-	<node pkg="d_fall_pps" name="FollowCrazyflieService" output="screen" type="FollowCrazyflieService">
-		<rosparam command="load" file="$(find d_fall_pps)/param/SafeController.yaml" />
-	</node>
-
-
-	<!-- <node pkg="rqt_plot" name="commandplotter" type="rqt_plot" args="/PPSClient/ControlCommand/roll /PPSClient/ControlCommand/pitch /PPSClient/ControlCommand/yaw" /> -->
-
-</launch>
diff --git a/pps_ws/src/d_fall_pps/launch/Teacher.launch b/pps_ws/src/d_fall_pps/launch/Teacher.launch
index 1c2e6a9d63045b3969339f7f17d3ac0faf18e2b8..ef7b20a73aaf513096282fc723b2e33c8fe9d3d7 100755
--- a/pps_ws/src/d_fall_pps/launch/Teacher.launch
+++ b/pps_ws/src/d_fall_pps/launch/Teacher.launch
@@ -15,7 +15,7 @@
 		<param name="type" type="str" value="coordinator" />
 		<param name="agentID" value="0" />
 		<rosparam command="load" file="$(find d_fall_pps)/param/SafeController.yaml" ns="SafeController" />
-		<rosparam command="load" file="$(find d_fall_pps)/param/CustomController.yaml" ns="CustomController" />
+		<rosparam command="load" file="$(find d_fall_pps)/param/DemoController.yaml" ns="CustomController" />
 	</node>
 
 </launch>
diff --git a/pps_ws/src/d_fall_pps/msg/CustomControllerYAML.msg b/pps_ws/src/d_fall_pps/msg/CustomControllerYAML.msg
deleted file mode 100644
index ebe1dee883ffcd744fe81b94023e395d099775fc..0000000000000000000000000000000000000000
--- a/pps_ws/src/d_fall_pps/msg/CustomControllerYAML.msg
+++ /dev/null
@@ -1,7 +0,0 @@
-float64 mass
-float64 control_frequency
-float64[] motorPoly
-bool shouldPerformConvertIntoBodyFrame
-bool shouldPublishCurrent_xyz_yaw
-bool shouldFollowAnotherAgent
-uint32[] follow_in_a_line_agentIDs
diff --git a/pps_ws/src/d_fall_pps/param/ClientConfig.yaml b/pps_ws/src/d_fall_pps/param/ClientConfig.yaml
index 07c6cbedcd7a8ba61cdf13927c69c44003c25ce9..cda1948a7611b0cf78bc3dc4c481b5fb07f842f2 100755
--- a/pps_ws/src/d_fall_pps/param/ClientConfig.yaml
+++ b/pps_ws/src/d_fall_pps/param/ClientConfig.yaml
@@ -2,7 +2,7 @@ safeController: "SafeControllerService/RateController"
 customController: "CustomControllerService/CustomController"
 strictSafety: true
 angleMargin: 0.6
-battery_threshold_while_flying: 2.9      # in V
-battery_threshold_while_motors_off: 3.34 # in V
-battery_polling_period: 100         # in ms
+battery_threshold_while_flying: 2.8       # in V
+battery_threshold_while_motors_off: 3.30  # in V
+battery_polling_period: 100               # in ms
 
diff --git a/pps_ws/src/d_fall_pps/param/DemoController.yaml b/pps_ws/src/d_fall_pps/param/DemoController.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..15659071844119abcd3b493d2aa0c32ddff534ce
--- /dev/null
+++ b/pps_ws/src/d_fall_pps/param/DemoController.yaml
@@ -0,0 +1,46 @@
+# Mass of the crazyflie
+mass : 31
+
+# Frequency of the controller, in hertz
+control_frequency : 200
+
+# Quadratic motor regression equation (a0, a1, a2)
+motorPoly : [5.484560e-4, 1.032633e-6, 2.130295e-11]
+
+# Boolean for whether to execute the convert into body frame function
+shouldPerformConvertIntoBodyFrame : true
+
+# Boolean indiciating whether the (x,y,z,yaw) of this agent should be published or not
+shouldPublishCurrent_xyz_yaw : false
+
+# Boolean indicating whether the (x,y,z,yaw) setpoint of this agent should adapted in
+# an attempt to follow the "my_current_xyz_yaw_topic" from another agent
+shouldFollowAnotherAgent : false
+
+# The order in which agents should follow eachother
+# > 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]
+
+# 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
+
+# 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
+
+# The LQR Controller parameters for "mode = 1"
+gainMatrixRollRate                :  [ 0.00,-1.72, 0.00, 0.00,-1.34, 0.00, 5.12, 0.00, 0.00]
+gainMatrixPitchRate               :  [ 1.72, 0.00, 0.00, 1.34, 0.00, 0.00, 0.00, 5.12, 0.00]
+gainMatrixYawRate                 :  [ 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 2.84]
+gainMatrixThrust_NineStateVector  :  [ 0.00, 0.00, 0.25, 0.00, 0.00, 0.14, 0.00, 0.00, 0.00]
+
+# The LQR Controller parameters for "mode = 2"
+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]
+gainMatrixThrust_SixStateVector   :  [ 0.00, 0.00, 0.31, 0.00, 0.00, 0.14]
diff --git a/pps_ws/src/d_fall_pps/param/SafeController.yaml b/pps_ws/src/d_fall_pps/param/SafeController.yaml
index 60efb4480984c85a640d235799b61a0eaa7da4a5..400d253640349519f090c0926005f5e466077109 100644
--- a/pps_ws/src/d_fall_pps/param/SafeController.yaml
+++ b/pps_ws/src/d_fall_pps/param/SafeController.yaml
@@ -1,5 +1,5 @@
 #equlibrium offset
-mass : 29
+mass : 30
 #quadratic motor regression equation (a0, a1, a2)
 motorPoly: [5.484560e-4, 1.032633e-6, 2.130295e-11]
 
@@ -7,7 +7,7 @@ motorPoly: [5.484560e-4, 1.032633e-6, 2.130295e-11]
 gainMatrixRoll: [0, -1.714330725, 0, 0, -1.337107465, 0, 5.115369735, 0, 0]
 gainMatrixPitch: [1.714330725, 0, 0, 1.337107465, 0, 0, 0, 5.115369735, 0]
 gainMatrixYaw: [0, 0, 0, 0, 0, 0, 0, 0, 2.843099534]
-gainMatrixThrust: [0, 0, 0.22195826, 0, 0, 0.12362477, 0, 0, 0]
+gainMatrixThrust: [0, 0, 0.20195826, 0, 0, 0.08362477, 0, 0, 0]
 
 #kalman filter
 filterGain: [1, 1, 1, 22.3384, 22.3384, 22.3384] #K_infinite of feedback
@@ -18,9 +18,9 @@ defaultSetpoint: [0.0, 0.0, 0.4, 0.0]
 
 #take off and landing parameters (in meters and seconds)
 takeOffDistance : 0.4
-landingDistance : 0.05
-durationTakeOff : 1.5
-durationLanding : 2
+landingDistance : -0.05
+durationTakeOff : 1.0
+durationLanding : 2.0
 
 # Liner Trayectory following parameters
 distanceThreshold : 0.5
diff --git a/pps_ws/src/d_fall_pps/param/CustomController.yaml b/pps_ws/src/d_fall_pps/param/StudentController.yaml
similarity index 100%
rename from pps_ws/src/d_fall_pps/param/CustomController.yaml
rename to pps_ws/src/d_fall_pps/param/StudentController.yaml
diff --git a/pps_ws/src/d_fall_pps/src/CircleControllerService.cpp b/pps_ws/src/d_fall_pps/src/CircleControllerService.cpp
deleted file mode 100755
index 0f6c387a8232d16b588ead699b0e90c5b94238be..0000000000000000000000000000000000000000
--- a/pps_ws/src/d_fall_pps/src/CircleControllerService.cpp
+++ /dev/null
@@ -1,258 +0,0 @@
-//    Copyright (C) 2017, ETH Zurich, D-ITET, Cyrill Burgener, Marco Mueller, Philipp Friedli
-//
-//    This file is part of D-FaLL-System.
-//    
-//    D-FaLL-System is free software: you can redistribute it and/or modify
-//    it under the terms of the GNU General Public License as published by
-//    the Free Software Foundation, either version 3 of the License, or
-//    (at your option) any later version.
-//    
-//    D-FaLL-System is distributed in the hope that it will be useful,
-//    but WITHOUT ANY WARRANTY; without even the implied warranty of
-//    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-//    GNU General Public License for more details.
-//    
-//    You should have received a copy of the GNU General Public License
-//    along with D-FaLL-System.  If not, see <http://www.gnu.org/licenses/>.
-//    
-//
-//    ----------------------------------------------------------------------------------
-//    DDDD        FFFFF        L     L           SSSS  Y   Y   SSSS  TTTTT  EEEEE  M   M
-//    D   D       F      aaa   L     L          S       Y Y   S        T    E      MM MM
-//    D   D  ---  FFFF  a   a  L     L     ---   SSS     Y     SSS     T    EEE    M M M
-//    D   D       F     a  aa  L     L              S    Y        S    T    E      M   M
-//    DDDD        F      aa a  LLLL  LLLL       SSSS     Y    SSSS     T    EEEEE  M   M
-//
-//
-//    DESCRIPTION:
-//    Alternate controller that flies the quadcopter in a circle.
-//
-//    ----------------------------------------------------------------------------------
-
-
-#include <math.h>
-#include <stdlib.h>
-#include "ros/ros.h"
-#include <std_msgs/String.h>
-#include <ros/package.h>
-#include "std_msgs/Float32.h"
-
-#include "d_fall_pps/CrazyflieData.h"
-#include "d_fall_pps/Setpoint.h"
-#include "d_fall_pps/ControlCommand.h"
-#include "d_fall_pps/Controller.h"
-
-#define PI 3.1415926535
-#define RATE_CONTROLLER 7
-
-using namespace d_fall_pps;
-
-std::vector<float>  ffThrust(4);
-std::vector<float>  feedforwardMotor(4);
-std::vector<float>  motorPoly(3);
-
-std::vector<float>  gainMatrixRoll(9);
-std::vector<float>  gainMatrixPitch(9);
-std::vector<float>  gainMatrixYaw(9);
-std::vector<float>  gainMatrixThrust(9);
-
-//K_infinite of feedback
-std::vector<float> filterGain(6);
-//only for velocity calculation
-std::vector<float> estimatorMatrix(2);
-float prevEstimate[9];
-
-float saturationThrust;
-
-CrazyflieData previousLocation;
-
-//circle stuff
-float currentTime;
-const float OMEGA = 0.25*2*PI;
-const float RADIUS = 0.25;
-
-//point publisher for FollowCrazyflieService
-ros::Publisher followPublisher;
-
-
-void loadParameterFloatVector(ros::NodeHandle& nodeHandle, std::string name, std::vector<float>& val, int length) {
-    if(!nodeHandle.getParam(name, val)){
-        ROS_ERROR_STREAM("missing parameter '" << name << "'");
-    }
-    if(val.size() != length) {
-        ROS_ERROR_STREAM("parameter '" << name << "' has wrong array length, " << length << " needed");
-    }
-}
-
-void loadParameters(ros::NodeHandle& nodeHandle) {
-    loadParameterFloatVector(nodeHandle, "feedforwardMotor", feedforwardMotor, 4);
-    loadParameterFloatVector(nodeHandle, "motorPoly", motorPoly, 3);
-
-    for(int i = 0; i < 4; ++i) {
-        ffThrust[i] = motorPoly[2] * feedforwardMotor[i] * feedforwardMotor[i] + motorPoly[1] * feedforwardMotor[i] + motorPoly[0];
-    }
-    saturationThrust = motorPoly[2] * 12000 * 12000 + motorPoly[1] * 12000 + motorPoly[0];
-
-    loadParameterFloatVector(nodeHandle, "gainMatrixRoll", gainMatrixRoll, 9);
-    loadParameterFloatVector(nodeHandle, "gainMatrixPitch", gainMatrixPitch, 9);
-    loadParameterFloatVector(nodeHandle, "gainMatrixYaw", gainMatrixYaw, 9);
-    loadParameterFloatVector(nodeHandle, "gainMatrixThrust", gainMatrixThrust, 9);
-
-    loadParameterFloatVector(nodeHandle, "filterGain", filterGain, 6);
-    loadParameterFloatVector(nodeHandle, "estimatorMatrix", estimatorMatrix, 2);
-
-}
-
-float computeMotorPolyBackward(float thrust) {
-    return (-motorPoly[1] + sqrt(motorPoly[1] * motorPoly[1] - 4 * motorPoly[2] * (motorPoly[0] - thrust))) / (2 * motorPoly[2]);
-}
-
-
-//Kalman
-void estimateState(Controller::Request &request, float (&est)[9]) {
-    // attitude
-    est[6] = request.ownCrazyflie.roll;
-    est[7] = request.ownCrazyflie.pitch;
-    est[8] = request.ownCrazyflie.yaw;
-
-    //velocity & filtering
-    float ahat_x[6]; //estimator matrix times state (x, y, z, vx, vy, vz)
-    ahat_x[0] = 0; ahat_x[1]=0; ahat_x[2]=0;
-    ahat_x[3] = estimatorMatrix[0] * prevEstimate[0] + estimatorMatrix[1] * prevEstimate[3];
-    ahat_x[4] = estimatorMatrix[0] * prevEstimate[1] + estimatorMatrix[1] * prevEstimate[4];
-    ahat_x[5] = estimatorMatrix[0] * prevEstimate[2] + estimatorMatrix[1] * prevEstimate[5];
-
-    
-    float k_x[6]; //filterGain times state
-    k_x[0] = request.ownCrazyflie.x * filterGain[0];
-    k_x[1] = request.ownCrazyflie.y * filterGain[1];
-    k_x[2] = request.ownCrazyflie.z * filterGain[2];
-    k_x[3] = request.ownCrazyflie.x * filterGain[3];
-    k_x[4] = request.ownCrazyflie.y * filterGain[4];
-    k_x[5] = request.ownCrazyflie.z * filterGain[5];
-   
-    est[0] = ahat_x[0] + k_x[0];
-    est[1] = ahat_x[1] + k_x[1];
-	est[2] = ahat_x[2] + k_x[2];
-    est[3] = ahat_x[3] + k_x[3];
-    est[4] = ahat_x[4] + k_x[4];
-    est[5] = ahat_x[5] + k_x[5];
-
-    memcpy(prevEstimate, est, 9 * sizeof(float));
-    
-}
-
-void convertIntoBodyFrame(float est[9], float (&state)[9], float yaw_measured) {
-	float sinYaw = sin(yaw_measured);
-    float cosYaw = cos(yaw_measured);
-
-    state[0] = est[0] * cosYaw + est[1] * sinYaw;
-    state[1] = -est[0] * sinYaw + est[1] * cosYaw;
-    state[2] = est[2];
-
-    state[3] = est[3] * cosYaw + est[4] * sinYaw;
-    state[4] = -est[3] * sinYaw + est[4] * cosYaw;
-    state[5] = est[5];
-
-    state[6] = est[6];
-    state[7] = est[7];
-    state[8] = est[8];
-}
-
-void calculateCircle(Setpoint &circlePoint){
-    circlePoint.x = 0;
-    circlePoint.y = RADIUS*sin(OMEGA*currentTime);
-    circlePoint.z = RADIUS*cos(OMEGA*currentTime);
-    circlePoint.yaw = 0;//OMEGA*currentTime;
-
-}
-
-bool calculateControlOutput(Controller::Request &request, Controller::Response &response) {
-    CrazyflieData vicon = request.ownCrazyflie;
-	
-    currentTime += request.ownCrazyflie.acquiringTime;
-
-    //publish setpoint for FollowController of another student group
-    Setpoint pubSetpoint;
-    pubSetpoint.x = request.ownCrazyflie.x;
-    pubSetpoint.y = request.ownCrazyflie.y;
-    pubSetpoint.z = request.ownCrazyflie.z;
-    pubSetpoint.yaw = request.ownCrazyflie.yaw;
-    followPublisher.publish(pubSetpoint);
-
-    //actual Circle Controller stuff follows
-	Setpoint circlePoint;
-    calculateCircle(circlePoint);
-
-	float yaw_measured = request.ownCrazyflie.yaw;
-
-    //move coordinate system to make setpoint origin
-    request.ownCrazyflie.x -= circlePoint.x;
-    request.ownCrazyflie.y -= circlePoint.y;
-    request.ownCrazyflie.z -= circlePoint.z;
-    float yaw = request.ownCrazyflie.yaw - circlePoint.yaw;
-	
-    while(yaw > PI) {yaw -= 2 * PI;}
-    while(yaw < -PI) {yaw += 2 * PI;}
-    request.ownCrazyflie.yaw = yaw;
-
-    float est[9]; //px, py, pz, vx, vy, vz, roll, pitch, yaw
-    estimateState(request, est);
-	
-    float state[9]; //px, py, pz, vx, vy, vz, roll, pitch, yaw
-    convertIntoBodyFrame(est, state, yaw_measured);
-
-    //calculate feedback
-    float outRoll = 0;
-    float outPitch = 0;
-    float outYaw = 0;
-    float thrustIntermediate = 0;
-    for(int i = 0; i < 9; ++i) {
-    	outRoll -= gainMatrixRoll[i] * state[i];
-    	outPitch -= gainMatrixPitch[i] * state[i];
-    	outYaw -= gainMatrixYaw[i] * state[i];
-    	thrustIntermediate -= gainMatrixThrust[i] * state[i];
-    }
-
-    response.controlOutput.roll = outRoll;
-    response.controlOutput.pitch = outPitch;
-    response.controlOutput.yaw = outYaw;
-
-    if(thrustIntermediate > saturationThrust)
-        thrustIntermediate = saturationThrust;
-    else if(thrustIntermediate < -saturationThrust)
-        thrustIntermediate = -saturationThrust;
-
-    response.controlOutput.motorCmd1 = computeMotorPolyBackward(thrustIntermediate + ffThrust[0]);
-    response.controlOutput.motorCmd2 = computeMotorPolyBackward(thrustIntermediate + ffThrust[1]);
-    response.controlOutput.motorCmd3 = computeMotorPolyBackward(thrustIntermediate + ffThrust[2]);
-    response.controlOutput.motorCmd4 = computeMotorPolyBackward(thrustIntermediate + ffThrust[3]);
-
-    response.controlOutput.onboardControllerType = RATE_CONTROLLER;
-
-    previousLocation = request.ownCrazyflie;
-
-
-    
-	return true;
-}
-
-
-int main(int argc, char* argv[]) {
-    ros::init(argc, argv, "CircleControllerService");
-
-    currentTime = 0;
-
-    ros::NodeHandle nodeHandle("~");
-    loadParameters(nodeHandle);
-
-    //publisher for Follow Controller of another student group
-    followPublisher = nodeHandle.advertise<Setpoint>("FollowTopic", 1);
-
-    ros::ServiceServer service = nodeHandle.advertiseService("CircleController", calculateControlOutput);
-    ROS_INFO("CircleControllerService ready");
-    
-    ros::spin();
-
-    return 0;
-}
diff --git a/pps_ws/src/d_fall_pps/src/DemoControllerService.cpp b/pps_ws/src/d_fall_pps/src/DemoControllerService.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..7d4889183a77e57fc4897f4e662a627264c0ca3a
--- /dev/null
+++ b/pps_ws/src/d_fall_pps/src/DemoControllerService.cpp
@@ -0,0 +1,1487 @@
+//    Copyright (C) 2017, ETH Zurich, D-ITET, Paul Beuchat, Angel Romero, Cyrill Burgener, Marco Mueller, Philipp Friedli
+//
+//    This file is part of D-FaLL-System.
+//    
+//    D-FaLL-System is free software: you can redistribute it and/or modify
+//    it under the terms of the GNU General Public License as published by
+//    the Free Software Foundation, either version 3 of the License, or
+//    (at your option) any later version.
+//    
+//    D-FaLL-System is distributed in the hope that it will be useful,
+//    but WITHOUT ANY WARRANTY; without even the implied warranty of
+//    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//    GNU General Public License for more details.
+//    
+//    You should have received a copy of the GNU General Public License
+//    along with D-FaLL-System.  If not, see <http://www.gnu.org/licenses/>.
+//    
+//
+//    ----------------------------------------------------------------------------------
+//    DDDD        FFFFF        L     L           SSSS  Y   Y   SSSS  TTTTT  EEEEE  M   M
+//    D   D       F      aaa   L     L          S       Y Y   S        T    E      MM MM
+//    D   D  ---  FFFF  a   a  L     L     ---   SSS     Y     SSS     T    EEE    M M M
+//    D   D       F     a  aa  L     L              S    Y        S    T    E      M   M
+//    DDDD        F      aa a  LLLL  LLLL       SSSS     Y    SSSS     T    EEEEE  M   M
+//
+//
+//    DESCRIPTION:
+//    Place for students to implement their controller
+//
+//    ----------------------------------------------------------------------------------
+
+
+
+
+
+//    ----------------------------------------------------------------------------------
+//    III  N   N   CCCC  L      U   U  DDDD   EEEEE   SSSS
+//     I   NN  N  C      L      U   U  D   D  E      S
+//     I   N N N  C      L      U   U  D   D  EEE     SSS
+//     I   N  NN  C      L      U   U  D   D  E          S
+//    III  N   N   CCCC  LLLLL   UUU   DDDD   EEEEE  SSSS
+//    ----------------------------------------------------------------------------------
+
+// These various headers need to be included so that this controller service can be
+// connected with the D-FaLL system.
+
+//some useful libraries
+#include <math.h>
+#include <stdlib.h>
+#include "ros/ros.h"
+#include <ros/package.h>
+
+//the generated structs from the msg-files have to be included
+#include "d_fall_pps/ViconData.h"
+#include "d_fall_pps/Setpoint.h"
+#include "d_fall_pps/ControlCommand.h"
+#include "d_fall_pps/Controller.h"
+#include "d_fall_pps/DebugMsg.h"
+#include "d_fall_pps/CustomControllerYAML.h"
+
+#include <std_msgs/Int32.h>
+
+
+
+
+
+//    ----------------------------------------------------------------------------------
+//    DDDD   EEEEE  FFFFF  III  N   N  EEEEE   SSSS
+//    D   D  E      F       I   NN  N  E      S
+//    D   D  EEE    FFF     I   N N N  EEE     SSS
+//    D   D  E      F       I   N  NN  E          S
+//    DDDD   EEEEE  F      III  N   N  EEEEE  SSSS
+//    ----------------------------------------------------------------------------------
+
+// These constants are defined to make the code more readable and adaptable.
+
+// Universal constants
+#define PI 3.1415926535
+
+// 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:
+// MOTOR_MODE    In this mode the Crazyflie will apply the requested 16-bit per motor
+//               command directly to each of the motors
+// RATE_MODE     In this mode the Crazyflie will apply the requested 16-bit per motor
+//               command directly to each of the motors, and additionally request the
+//               body frame roll, pitch, and yaw angular rates from the PID rate
+//               controllers implemented in the Crazyflie 2.0 firmware.
+// ANGE_MODE     In this mode the Crazyflie will apply the requested 16-bit per motor
+//               command directly to each of the motors, and additionally request the
+//               body frame roll, pitch, and yaw angles from the PID attitude
+//               controllers implemented in the Crazyflie 2.0 firmware.
+#define MOTOR_MODE 6
+#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
+#define FETCH_YAML_SAFE_CONTROLLER_COORDINATOR    3
+#define FETCH_YAML_CUSTOM_CONTROLLER_COORDINATOR  4
+
+// Namespacing the package
+using namespace d_fall_pps;
+
+
+
+
+
+//    ----------------------------------------------------------------------------------
+//    V   V    A    RRRR   III    A    BBBB   L      EEEEE   SSSS
+//    V   V   A A   R   R   I    A A   B   B  L      E      S
+//    V   V  A   A  RRRR    I   A   A  BBBB   L      EEE     SSS
+//     V V   AAAAA  R  R    I   AAAAA  B   B  L      E          S
+//      V    A   A  R   R  III  A   A  BBBB   LLLLL  EEEEE  SSSS
+//    ----------------------------------------------------------------------------------
+
+// Variables for controller
+float cf_mass;                       // Crazyflie mass in grams
+std::vector<float> motorPoly(3);     // Coefficients of the 16-bit command to thrust conversion
+float control_frequency;             // Frequency at which the controller is running
+float gravity_force;                 // The weight of the Crazyflie in Newtons, i.e., mg
+
+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 for "LQR_RATE_MODE"
+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  =  { 0.00, 0.00, 0.25, 0.00, 0.00, 0.14, 0.00, 0.00, 0.00};
+
+
+// The LQR Controller parameters for "LQR_ANGLE_MODE"
+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   =  { 0.00, 0.00, 0.31, 0.00, 0.00, 0.14};
+
+// ROS Publisher for debugging variables
+ros::Publisher debugPublisher;
+
+
+// Variable for the namespaces for the paramter services
+// > For the paramter service of this agent
+std::string namespace_to_own_agent_parameter_service;
+// > For the parameter service of the coordinator
+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
+
+// The ID of this agent, i.e., the ID of this compute
+int my_agentID = 0;
+
+// Boolean indicating whether the (x,y,z,yaw) of this agent should be published or not
+// > The default behaviour is: do not publish,
+// > This varaible is changed based on parameters loaded from the YAML file
+bool shouldPublishCurrent_xyz_yaw = false;
+
+// Boolean indicating whether the (x,y,z,yaw) setpoint of this agent should adapted in
+// an attempt to follow the "my_current_xyz_yaw_topic" from another agent
+// > The default behaviour is: do not follow,
+// > This varaible is changed based on parameters loaded from the YAML file
+bool shouldFollowAnotherAgent = false;
+
+// The order in which agents should follow eachother
+// > 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
+std::vector<int> follow_in_a_line_agentIDs(100);
+
+// Integer specifying the ID of the agent that will be followed by this agent
+// > The default behaviour not to follow any agent, indicated by ID zero
+// > This varaible is changed based on parameters loaded from the YAML file
+int agentID_to_follow = 0;
+
+// ROS Publisher for my current (x,y,z,yaw) position
+ros::Publisher my_current_xyz_yaw_publisher;
+
+// ROS Subscriber for my position
+ros::Subscriber xyz_yaw_to_follow_subscriber;
+
+
+// RELEVANT NOTES ABOUT THE VARIABLES DECLARE HERE:
+// 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
+//     float64 x                         The x position of the Crazyflie [metres]
+//     float64 y                         The y position of the Crazyflie [metres]
+//     float64 z                         The z position of the Crazyflie [metres]
+//     float64 roll                      The roll component of the intrinsic Euler angles [radians]
+//     float64 pitch                     The pitch component of the intrinsic Euler angles [radians]
+//     float64 yaw                       The yaw component of the intrinsic Euler angles [radians]
+//     float64 acquiringTime #delta t    The time elapsed since the previous "CrazyflieData" was received [seconds]
+//     bool occluded                     A boolean indicted whether the Crazyflie for visible at the time of this measurement
+
+
+
+
+
+//    ----------------------------------------------------------------------------------
+//    FFFFF  U   U  N   N   CCCC  TTTTT  III   OOO   N   N
+//    F      U   U  NN  N  C        T     I   O   O  NN  N
+//    FFF    U   U  N N N  C        T     I   O   O  N N N
+//    F      U   U  N  NN  C        T     I   O   O  N  NN
+//    F       UUU   N   N   CCCC    T    III   OOO   N   N
+//
+//    PPPP   RRRR    OOO   TTTTT   OOO   TTTTT  Y   Y  PPPP   EEEEE   SSSS
+//    P   P  R   R  O   O    T    O   O    T     Y Y   P   P  E      S
+//    PPPP   RRRR   O   O    T    O   O    T      Y    PPPP   EEE     SSS
+//    P      R  R   O   O    T    O   O    T      Y    P      E          S
+//    P      R   R   OOO     T     OOO     T      Y    P      EEEEE  SSSS
+//    ----------------------------------------------------------------------------------
+
+// These function prototypes are not strictly required for this code to complile, but
+// adding the function prototypes here means the the functions can be written below in
+// any order. If the function prototypes are not included then the function need to
+// 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(float stateErrorBody[9], Controller::Request &request, Controller::Response &response);
+void calculateControlOutput_viaLQRforAngles(float stateErrorBody[9], 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);
+
+// CONVERSION FROM THRUST IN NEWTONS TO 16-BIT COMMAND
+float computeMotorPolyBackward(float thrust);
+
+// SETPOINT CHANGE CALLBACK
+void setpointCallback(const Setpoint& newSetpoint);
+void xyz_yaw_to_follow_callback(const Setpoint& newSetpoint);
+
+// LOAD PARAMETERS
+float getParameterFloat(ros::NodeHandle& nodeHandle, std::string name);
+void getParameterFloatVector(ros::NodeHandle& nodeHandle, std::string name, std::vector<float>& val, int length);
+int getParameterInt(ros::NodeHandle& nodeHandle, std::string name);
+void getParameterIntVectorWithKnownLength(ros::NodeHandle& nodeHandle, std::string name, std::vector<int>& val, int length);
+int getParameterIntVectorWithUnknownLength(ros::NodeHandle& nodeHandle, std::string name, std::vector<int>& val);
+bool getParameterBool(ros::NodeHandle& nodeHandle, std::string name);
+
+void yamlReadyForFetchCallback(const std_msgs::Int32& msg);
+void fetchYamlParameters(ros::NodeHandle& nodeHandle);
+void processFetchedParameters();
+//void customYAMLasMessageCallback(const CustomControllerYAML& newCustomControllerParameters);
+
+
+
+
+
+//    ----------------------------------------------------------------------------------
+//    FFFFF  U   U  N   N   CCCC  TTTTT  III   OOO   N   N
+//    F      U   U  NN  N  C        T     I   O   O  NN  N
+//    FFF    U   U  N N N  C        T     I   O   O  N N N
+//    F      U   U  N  NN  C        T     I   O   O  N  NN
+//    F       UUU   N   N   CCCC    T    III   OOO   N   N
+//
+//    III M   M PPPP  L     EEEEE M   M EEEEE N   N TTTTT   A   TTTTT III  OOO  N   N
+//     I  MM MM P   P L     E     MM MM E     NN  N   T    A A    T    I  O   O NN  N
+//     I  M M M PPPP  L     EEE   M M M EEE   N N N   T   A   A   T    I  O   O N N N
+//     I  M   M P     L     E     M   M E     N  NN   T   AAAAA   T    I  O   O N  NN
+//    III M   M P     LLLLL EEEEE M   M EEEEE N   N   T   A   A   T   III  OOO  N   N
+//    ----------------------------------------------------------------------------------
+
+
+
+
+
+//    ------------------------------------------------------------------------------
+//     OOO   U   U  TTTTT  EEEEE  RRRR 
+//    O   O  U   U    T    E      R   R
+//    O   O  U   U    T    EEE    RRRR
+//    O   O  U   U    T    E      R  R
+//     OOO    UUU     T    EEEEE  R   R
+//
+//     CCCC   OOO   N   N  TTTTT  RRRR    OOO   L           L       OOO    OOO   PPPP
+//    C      O   O  NN  N    T    R   R  O   O  L           L      O   O  O   O  P   P
+//    C      O   O  N N N    T    RRRR   O   O  L           L      O   O  O   O  PPPP
+//    C      O   O  N  NN    T    R  R   O   O  L           L      O   O  O   O  P
+//     CCCC   OOO   N   N    T    R   R   OOO   LLLLL       LLLLL   OOO    OOO   P
+//    ----------------------------------------------------------------------------------
+
+// This function is the callback that is linked to the "CustomController" service that
+// is advertised in the main function. This must have arguments that match the
+// "input-output" behaviour defined in the "Controller.srv" file (located in the "srv"
+// folder)
+//
+// The arument "request" is a structure provided to this service with the following two
+// properties:
+// request.ownCrazyflie
+// This property is itself a structure of type "CrazyflieData",  which is defined in the
+// file "CrazyflieData.msg", and has the following properties
+// string crazyflieName
+//     float64 x                         The x position of the Crazyflie [metres]
+//     float64 y                         The y position of the Crazyflie [metres]
+//     float64 z                         The z position of the Crazyflie [metres]
+//     float64 roll                      The roll component of the intrinsic Euler angles [radians]
+//     float64 pitch                     The pitch component of the intrinsic Euler angles [radians]
+//     float64 yaw                       The yaw component of the intrinsic Euler angles [radians]
+//     float64 acquiringTime #delta t    The time elapsed since the previous "CrazyflieData" was received [seconds]
+//     bool occluded                     A boolean indicted whether the Crazyflie for visible at the time of this measurement
+// The values in these properties are directly the measurement taken by the Vicon
+// motion capture system of the Crazyflie that is to be controlled by this service
+//
+// request.otherCrazyflies
+// This property is an array of "CrazyflieData" structures, what allows access to the
+// Vicon measurements of other Crazyflies.
+//
+// The argument "response" is a structure that is expected to be filled in by this
+// service by this function, it has only the following property
+// response.ControlCommand
+// This property is iteself a structure of type "ControlCommand", which is defined in
+// the file "ControlCommand.msg", and has the following properties:
+//     float32 roll                      The command sent to the Crazyflie for the body frame x-axis
+//     float32 pitch                     The command sent to the Crazyflie for the body frame y-axis
+//     float32 yaw                       The command sent to the Crazyflie for the body frame z-axis
+//     uint16 motorCmd1                  The command sent to the Crazyflie for motor 1
+//     uint16 motorCmd2                  The command sent to the Crazyflie for motor 1
+//     uint16 motorCmd3                  The command sent to the Crazyflie for motor 1
+//     uint16 motorCmd4                  The command sent to the Crazyflie for motor 1
+//     uint8 onboardControllerType       The flag sent to the Crazyflie for indicating how to implement the command
+// 
+// IMPORTANT NOTES FOR "onboardControllerType"  AND AXIS CONVENTIONS
+// > The allowed values for "onboardControllerType" are in the "Defines" section at the
+//   top of this file, they are MOTOR_MODE, RATE_MODE, OR ANGLE_MODE.
+// > In the PPS exercise we will only use the RATE_MODE.
+// > In RATE_MODE the ".roll", ".ptich", and ".yaw" properties of "response.ControlCommand"
+//   specify the angular rate in [radians/second] that will be requested from the
+//   PID controllers running in the Crazyflie 2.0 firmware.
+// > In RATE_MODE the ".motorCmd1" to ".motorCmd4" properties of "response.ControlCommand"
+//   are the baseline motor commands requested from the Crazyflie, with the adjustment
+//   for body rates being added on top of this in the firmware (i.e., as per the code
+//   of the "distribute_power" function provided in exercise sheet 2).
+// > In RATE_MODE the axis convention for the roll, pitch, and yaw body rates returned
+//   in "response.ControlCommand" should use right-hand coordinate axes with x-forward
+//   and z-upwards (i.e., the positive z-axis is aligned with the direction of positive
+//   thrust). To assist, teh following is an ASCII art of this convention:
+//
+// ASCII ART OF THE CRAZYFLIE 2.0 LAYOUT
+//
+//  > This is a top view,
+//  > M1 to M4 stand for Motor 1 to Motor 4,
+//  > "CW"  indicates that the motor rotates Clockwise,
+//  > "CCW" indicates that the motor rotates Counter-Clockwise,
+//  > By right-hand axis convention, the positive z-direction points our of the screen,
+//  > This being a "top view" means tha the direction of positive thrust produced
+//    by the propellers is also out of the screen.
+//
+//        ____                         ____
+//       /    \                       /    \
+//  (CW) | M4 |           x           | M1 | (CCW)
+//       \____/\          ^          /\____/
+//            \ \         |         / /
+//             \ \        |        / /
+//              \ \______ | ______/ /
+//               \        |        /
+//                |       |       |
+//        y <-------------o       |
+//                |               |
+//               / _______________ \
+//              / /               \ \
+//             / /                 \ \
+//        ____/ /                   \ \____
+//       /    \/                     \/    \
+// (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)
+{
+
+	// 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];
+	}
+
+
+
+	// 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;
+		}
+
+		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;
+		}
+
+
+
+	}
+
+
+
+	
+
+
+
+	//  ************************************************************************************************
+	//  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
+
+	// 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);
+	}
+
+
+
+
+	
+
+	// Return "true" to indicate that the control computation was performed successfully
+	return true;
+}
+
+
+
+
+
+void calculateControlOutput_viaLQRforRates(float stateErrorBody[9], 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;
+
+
+
+
+	//  **************************************
+	//  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 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)
+	{
+		pitchRate_forResponse -= gainMatrixPitchRate[i] * stateErrorBody[i];
+	}
+
+	// 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 -= gainMatrixRollRate[i] * stateErrorBody[i];
+	}
+
+	// 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;
+
+	//  ***********************************************************
+	//  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)
+    {
+		// 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);
+	}
+}
+
+
+
+
+void calculateControlOutput_viaLQRforAngles(float stateErrorBody[9], 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);
+
+
+
+
+	//  **************************************
+	//  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;
+}
+
+
+
+
+
+
+//    ------------------------------------------------------------------------------
+//    RRRR    OOO   TTTTT    A    TTTTT  EEEEE       III  N   N  TTTTT   OOO
+//    R   R  O   O    T     A A     T    E            I   NN  N    T    O   O
+//    RRRR   O   O    T    A   A    T    EEE          I   N N N    T    O   O
+//    R  R   O   O    T    AAAAA    T    E            I   N  NN    T    O   O
+//    R   R   OOO     T    A   A    T    EEEEE       III  N   N    T     OOO
+//
+//    BBBB    OOO   DDDD   Y   Y       FFFFF  RRRR     A    M   M  EEEEE
+//    B   B  O   O  D   D   Y Y        F      R   R   A A   MM MM  E
+//    BBBB   O   O  D   D    Y         FFF    RRRR   A   A  M M M  EEE
+//    B   B  O   O  D   D    Y         F      R  R   AAAAA  M   M  E
+//    BBBB    OOO   DDDD     Y         F      R   R  A   A  M   M  EEEEE
+//    ----------------------------------------------------------------------------------
+
+// The arguments for this function are as follows:
+// est
+// This is an array of length 9 with the estimates the error of of the following values
+// relative to the sepcifed setpoint:
+//     est[0]    x position of the Crazyflie relative to the inertial frame origin [meters]
+//     est[1]    y position of the Crazyflie relative to the inertial frame origin [meters]
+//     est[2]    z position of the Crazyflie relative to the inertial frame origin [meters]
+//     est[3]    x-axis component of the velocity of the Crazyflie in the inertial frame [meters/second]
+//     est[4]    y-axis component of the velocity of the Crazyflie in the inertial frame [meters/second]
+//     est[5]    z-axis component of the velocity of the Crazyflie in the inertial frame [meters/second]
+//     est[6]    The roll  component of the intrinsic Euler angles [radians]
+//     est[7]    The pitch component of the intrinsic Euler angles [radians]
+//     est[8]    The yaw   component of the intrinsic Euler angles [radians]
+// 
+// estBody
+// This is an empty array of length 9, this function should fill in all elements of this
+// array with the same ordering as for the "est" argument, expect that the (x,y) position
+// and (x,y) velocities are rotated into the body frame.
+//
+// yaw_measured
+// This is the yaw component of the intrinsic Euler angles in [radians] as measured by
+// the Vicon motion capture system
+//
+// This function WILL NEED TO BE edited for successful completion of the PPS exercise
+void convertIntoBodyFrame(float stateInertial[9], float (&stateBody)[9], float yaw_measured)
+{
+	if (shouldPerformConvertIntoBodyFrame)
+	{
+		float sinYaw = sin(yaw_measured);
+    	float cosYaw = cos(yaw_measured);
+
+    	// Fill in the (x,y,z) position estimates to be returned
+	    stateBody[0] = stateInertial[0] * cosYaw  +  stateInertial[1] * sinYaw;
+	    stateBody[1] = stateInertial[1] * cosYaw  -  stateInertial[0] * sinYaw;
+	    stateBody[2] = stateInertial[2];
+
+	    // Fill in the (x,y,z) velocity estimates to be returned
+	    stateBody[3] = stateInertial[3] * cosYaw  +  stateInertial[4] * sinYaw;
+	    stateBody[4] = stateInertial[4] * cosYaw  -  stateInertial[3] * sinYaw;
+	    stateBody[5] = stateInertial[5];
+
+	    // Fill in the (roll,pitch,yaw) estimates to be returned
+	    stateBody[6] = stateInertial[6];
+	    stateBody[7] = stateInertial[7];
+	    stateBody[8] = stateInertial[8];
+	}
+	else
+	{
+	    // Fill in the (x,y,z) position estimates to be returned
+	    stateBody[0] = stateInertial[0];
+	    stateBody[1] = stateInertial[1];
+	    stateBody[2] = stateInertial[2];
+
+	    // Fill in the (x,y,z) velocity estimates to be returned
+	    stateBody[3] = stateInertial[3];
+	    stateBody[4] = stateInertial[4];
+	    stateBody[5] = stateInertial[5];
+
+	    // Fill in the (roll,pitch,yaw) estimates to be returned
+	    stateBody[6] = stateInertial[6];
+	    stateBody[7] = stateInertial[7];
+	    stateBody[8] = stateInertial[8];
+	}
+}
+
+
+
+
+
+//    ------------------------------------------------------------------------------
+//    N   N  EEEEE  W     W   TTTTT   OOO   N   N        CCCC  M   M  DDDD
+//    NN  N  E      W     W     T    O   O  NN  N       C      MM MM  D   D
+//    N N N  EEE    W     W     T    O   O  N N N  -->  C      M M M  D   D
+//    N  NN  E       W W W      T    O   O  N  NN       C      M   M  D   D
+//    N   N  EEEEE    W W       T     OOO   N   N        CCCC  M   M  DDDD
+//
+//     CCCC   OOO   N   N  V   V  EEEEE  RRRR    SSSS  III   OOO   N   N
+//    C      O   O  NN  N  V   V  E      R   R  S       I   O   O  NN  N
+//    C      O   O  N N N  V   V  EEE    RRRR    SSS    I   O   O  N N N
+//    C      O   O  N  NN   V V   E      R  R       S   I   O   O  N  NN
+//     CCCC   OOO   N   N    V    EEEEE  R   R  SSSS   III   OOO   N   N
+//    ----------------------------------------------------------------------------------
+
+// This function DOES NOT NEED TO BE edited for successful completion of the PPS exercise
+float computeMotorPolyBackward(float thrust)
+{
+    return (-motorPoly[1] + sqrt(motorPoly[1] * motorPoly[1] - 4 * motorPoly[2] * (motorPoly[0] - thrust))) / (2 * motorPoly[2]);
+}
+
+
+
+
+
+//    ----------------------------------------------------------------------------------
+//    N   N  EEEEE  W     W        SSSS  EEEEE  TTTTT  PPPP    OOO   III  N   N  TTTTT
+//    NN  N  E      W     W       S      E        T    P   P  O   O   I   NN  N    T
+//    N N N  EEE    W     W        SSS   EEE      T    PPPP   O   O   I   N N N    T
+//    N  NN  E       W W W            S  E        T    P      O   O   I   N  NN    T
+//    N   N  EEEEE    W W         SSSS   EEEEE    T    P       OOO   III  N   N    T
+//
+//     GGG   U   U  III        CCCC    A    L      L      BBBB     A     CCCC  K   K
+//    G   G  U   U   I        C       A A   L      L      B   B   A A   C      K  K
+//    G      U   U   I        C      A   A  L      L      BBBB   A   A  C      KKK
+//    G   G  U   U   I        C      AAAAA  L      L      B   B  AAAAA  C      K  K
+//     GGGG   UUU   III        CCCC  A   A  LLLLL  LLLLL  BBBB   A   A   CCCC  K   K
+//    ----------------------------------------------------------------------------------
+
+// This function DOES NOT NEED TO BE edited for successful completion of the PPS exercise
+void setpointCallback(const Setpoint& newSetpoint)
+{
+    setpoint[0] = newSetpoint.x;
+    setpoint[1] = newSetpoint.y;
+    setpoint[2] = newSetpoint.z;
+    setpoint[3] = newSetpoint.yaw;
+}
+
+
+
+// This function DOES NOT NEED TO BE edited for successful completion of the PPS exercise
+// > This function is called anytime a message is published on the topic to which the
+//   class instance variable "xyz_yaw_to_follow_subscriber" is subscribed
+void xyz_yaw_to_follow_callback(const Setpoint& newSetpoint)
+{
+        //ROS_INFO("DEBUGGING: Received new setpoint from another agent");
+	// The setpoint should only be updated if allow by the respective booelan
+	if (shouldFollowAnotherAgent)
+	{
+	    setpoint[0] = newSetpoint.x;
+	    setpoint[1] = newSetpoint.y;
+	    setpoint[2] = newSetpoint.z;
+	    setpoint[3] = newSetpoint.yaw;
+	}
+}
+
+
+
+
+
+//    ----------------------------------------------------------------------------------
+//    L       OOO     A    DDDD
+//    L      O   O   A A   D   D
+//    L      O   O  A   A  D   D
+//    L      O   O  AAAAA  D   D
+//    LLLLL   OOO   A   A  DDDD
+//
+//    PPPP     A    RRRR     A    M   M  EEEEE  TTTTT  EEEEE  RRRR    SSSS
+//    P   P   A A   R   R   A A   MM MM  E        T    E      R   R  S
+//    PPPP   A   A  RRRR   A   A  M M M  EEE      T    EEE    RRRR    SSS
+//    P      AAAAA  R  R   AAAAA  M   M  E        T    E      R  R       S
+//    P      A   A  R   R  A   A  M   M  EEEEE    T    EEEEE  R   R  SSSS
+//    ----------------------------------------------------------------------------------
+
+
+// This function DOES NOT NEED TO BE edited for successful completion of the PPS exercise
+void yamlReadyForFetchCallback(const std_msgs::Int32& msg)
+{
+	// Extract from the "msg" for which controller the and from where to fetch the YAML
+	// parameters
+	int controller_to_fetch_yaml = msg.data;
+
+	// Switch between fetching for the different controllers and from different locations
+	switch(controller_to_fetch_yaml)
+	{
+
+		// > FOR FETCHING FROM THE AGENT'S OWN PARAMETER SERVICE
+		case FETCH_YAML_CUSTOM_CONTROLLER_AGENT:
+		{
+			// Let the user know that this message was received
+			ROS_INFO("The CustomControllerService received the message that YAML parameters were (re-)loaded. > Now fetching the parameter values from this agent.");
+			// Create a node handle to the parameter service running on this agent's machine
+			ros::NodeHandle nodeHandle_to_own_agent_parameter_service(namespace_to_own_agent_parameter_service);
+			// Call the function that fetches the parameters
+			fetchYamlParameters(nodeHandle_to_own_agent_parameter_service);
+			break;
+		}
+
+		// > FOR FETCHING FROM THE COORDINATOR'S PARAMETER SERVICE
+		case FETCH_YAML_CUSTOM_CONTROLLER_COORDINATOR:
+		{
+			// Let the user know that this message was received
+			ROS_INFO("The CustomControllerService received the message that YAML parameters were (re-)loaded. > Now fetching the parameter values from the coordinator.");
+			// Create a node handle to the parameter service running on the coordinator machine
+			ros::NodeHandle nodeHandle_to_coordinator_parameter_service(namespace_to_coordinator_parameter_service);
+			// Call the function that fetches the parameters
+			fetchYamlParameters(nodeHandle_to_coordinator_parameter_service);
+			break;
+		}
+
+		default:
+		{
+			// Let the user know that the command was not relevant
+			//ROS_INFO("The CustomControllerService received the message that YAML parameters were (re-)loaded");
+			//ROS_INFO("> However the parameters do not relate to this controller, hence nothing will be fetched.");
+			break;
+		}
+	}
+}
+
+
+// This function CAN BE edited for successful completion of the PPS exercise, and the
+// use of parameters fetched from the YAML file is highly recommended to make tuning of
+// your controller easier and quicker.
+void fetchYamlParameters(ros::NodeHandle& nodeHandle)
+{
+	// Here we load the parameters that are specified in the CustomController.yaml file
+
+	// Add the "CustomController" namespace to the "nodeHandle"
+	ros::NodeHandle nodeHandle_for_customController(nodeHandle, "CustomController");
+
+	// > The mass of the crazyflie
+	cf_mass = getParameterFloat(nodeHandle_for_customController , "mass");
+
+	// 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
+	control_frequency = getParameterFloat(nodeHandle_for_customController, "control_frequency");
+
+	// > The co-efficients of the quadratic conversation from 16-bit motor command to
+	//   thrust force in Newtons
+	getParameterFloatVector(nodeHandle_for_customController, "motorPoly", motorPoly, 3);
+
+	// > The boolean for whether to execute the convert into body frame function
+	shouldPerformConvertIntoBodyFrame = getParameterBool(nodeHandle_for_customController, "shouldPerformConvertIntoBodyFrame");
+
+	// > The boolean indicating whether the (x,y,z,yaw) of this agent should be published
+	//   or not
+	shouldPublishCurrent_xyz_yaw = getParameterBool(nodeHandle_for_customController, "shouldPublishCurrent_xyz_yaw");
+
+	// > The boolean indicating whether the (x,y,z,yaw) setpoint of this agent should adapted in
+	//   an attempt to follow the "my_current_xyz_yaw_topic" from another agent
+	shouldFollowAnotherAgent = getParameterBool(nodeHandle_for_customController, "shouldFollowAnotherAgent");
+
+	// > The ordered vector for ID's that specifies how the agents should follow eachother
+	follow_in_a_line_agentIDs.clear();
+	int temp_number_of_agents_in_a_line = getParameterIntVectorWithUnknownLength(nodeHandle_for_customController, "follow_in_a_line_agentIDs", follow_in_a_line_agentIDs);
+	// > Double check that the sizes agree
+	if ( temp_number_of_agents_in_a_line != follow_in_a_line_agentIDs.size() )
+	{
+		// Update the user if the sizes don't agree
+		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() );
+	}
+
+	// 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");
+
+
+	// THE CONTROLLER GAINS:
+
+	// A flag for which controller to use, defined as:
+	controller_type = getParameterInt( nodeHandle_for_customController , "controller_type" );
+
+	// The LQR Controller parameters for "LQR_RATE_MODE"
+	getParameterFloatVector(nodeHandle_for_customController, "gainMatrixRollRate",               gainMatrixRollRate,               9);
+	getParameterFloatVector(nodeHandle_for_customController, "gainMatrixPitchRate",              gainMatrixPitchRate,              9);
+	getParameterFloatVector(nodeHandle_for_customController, "gainMatrixYawRate",                gainMatrixYawRate,                9);
+	getParameterFloatVector(nodeHandle_for_customController, "gainMatrixThrust_NineStateVector", gainMatrixThrust_NineStateVector, 9);
+
+	// The LQR Controller parameters for "LQR_ANGLE_MODE"
+	getParameterFloatVector(nodeHandle_for_customController, "gainMatrixRollAngle",              gainMatrixRollAngle,              6);
+	getParameterFloatVector(nodeHandle_for_customController, "gainMatrixPitchAngle",             gainMatrixPitchAngle,             6);
+	getParameterFloatVector(nodeHandle_for_customController, "gainMatrixThrust_SixStateVector",  gainMatrixThrust_SixStateVector,  6);
+
+
+	// DEBUGGING: Print out one of the parameters that was loaded
+	ROS_INFO_STREAM("DEBUGGING: the fetched SafeController/mass = " << cf_mass);
+
+	// Call the function that computes details an values that are needed from these
+	// parameters loaded above
+	processFetchedParameters();
+
+}
+
+
+// This function CAN BE edited for successful completion of the PPS exercise, and the
+// use of parameters loaded from the YAML file is highly recommended to make tuning of
+// your controller easier and quicker.
+void processFetchedParameters()
+{
+    // Compute the feed-forward force that we need to counteract gravity (i.e., mg)
+    // > in units of [Newtons]
+    gravity_force = cf_mass * 9.81/(1000*4);
+
+    // Look-up which agent should be followed
+    if (shouldFollowAnotherAgent)
+    {
+    	// Only bother if the "follow_in_a_line_agentIDs" vector has a non-zero length
+    	if (follow_in_a_line_agentIDs.size() > 0)
+    	{
+    		// Instantiate a local boolean variable for checking whether we found
+    		// our own agent ID in the list
+    		bool foundMyAgentID = false;
+    		// Iterate through the vector of "follow_in_a_line_agentIDs"
+	    	for ( int i=0 ; i<follow_in_a_line_agentIDs.size() ; i++ )
+	    	{
+	    		// Check if the current entry matches the ID of this agent
+	    		if (follow_in_a_line_agentIDs[i] == my_agentID)
+	    		{
+	    			// Set the boolean flag that we have found out own agent ID
+	    			foundMyAgentID = true;
+                    //ROS_INFO_STREAM("DEBUGGING: found my agent ID at index " << i );
+	    			// If it is the first entry, then this agent is the leader
+	    			if (i==0)
+	    			{
+	    				// The leader does not follow anyone else
+	    				shouldFollowAnotherAgent = false;
+    					agentID_to_follow = 0;
+	    			}
+	    			else
+	    			{
+	    				// The agent ID to follow is the previous entry
+	    				agentID_to_follow = follow_in_a_line_agentIDs[i-1];	
+                        shouldFollowAnotherAgent = true;
+	    				// Subscribe to the "my_current_xyz_yaw_topic" of the agent ID
+	    				// that this agent should be following
+	    				ros::NodeHandle nodeHandle("~");
+	    				xyz_yaw_to_follow_subscriber = nodeHandle.subscribe("/" + std::to_string(agentID_to_follow) + "/my_current_xyz_yaw_topic", 1, xyz_yaw_to_follow_callback);
+	    				//ROS_INFO_STREAM("DEBUGGING: subscribed to agent ID = " << agentID_to_follow );
+	    			}
+	    			// Break out of the for loop as the assumption is that each agent ID
+	    			// appears only once in the "follow_in_a_line_agentIDs" vector of ID's
+	    			break;
+	    		}
+	    	}
+	    	// Check whether we found our own agent ID
+	    	if (!foundMyAgentID)
+	    	{
+                //ROS_INFO("DEBUGGING: not following because my ID was not found");
+	    		// Revert to the default of not following any agent
+    			shouldFollowAnotherAgent = false;
+    			agentID_to_follow = 0;
+	    	}
+    	}
+    	else
+    	{
+    		// As the "follow_in_a_line_agentIDs" vector has length zero, revert to the
+    		// default of not following any agent
+    		shouldFollowAnotherAgent = false;
+    		agentID_to_follow = 0;
+    		//ROS_INFO("DEBUGGING: not following because line vector has length zero");
+    	}
+    }
+    else
+    {
+    	// Set to its default value the integer specifying the ID of the agent that will
+    	// be followed by this agent
+		agentID_to_follow = 0;
+		//ROS_INFO("DEBUGGING: not following because I was asked not to follow");
+    }
+
+    if (shouldFollowAnotherAgent)
+    {
+    	ROS_INFO_STREAM("This agent (with ID " << my_agentID << ") will now follow agent ID " << agentID_to_follow );
+    }
+}
+
+
+/*
+// This function DOES NOT NEED TO BE edited for successful completion of the PPS exercise
+void customYAMLasMessageCallback(const CustomControllerYAML& newCustomControllerParameters)
+{
+	// This function puts all the same parameters as the "fetchYamlParameters" function
+	// above into the same variables.
+	// The difference is that this function allows us to send all parameters from one
+	// central coordinator node
+	cf_mass = newCustomControllerParameters.mass;
+	control_frequency = newCustomControllerParameters.control_frequency;
+	for (int i=0;i<3;i++)
+	{
+		motorPoly[i] = newCustomControllerParameters.motorPoly[i];
+	}
+
+	// > The boolean for whether to execute the convert into body frame function
+    shouldPerformConvertIntoBodyFrame = newCustomControllerParameters.shouldPerformConvertIntoBodyFrame;
+
+	shouldPublishCurrent_xyz_yaw = newCustomControllerParameters.shouldPublishCurrent_xyz_yaw;
+	shouldFollowAnotherAgent = newCustomControllerParameters.shouldFollowAnotherAgent;
+	follow_in_a_line_agentIDs.clear();
+	for ( int i=0 ; i<newCustomControllerParameters.follow_in_a_line_agentIDs.size() ; i++ )
+	{
+		follow_in_a_line_agentIDs.push_back( newCustomControllerParameters.follow_in_a_line_agentIDs[i] );
+	}
+
+	// Let the user know that the message was received with new YAML parameters
+	ROS_INFO("Received message containing a new set of Custom Controller YAML parameters");
+
+	// Display one of the YAML parameters to debug if it is working correctly
+	ROS_INFO_STREAM("DEBUGGING: mass received in message = " << newCustomControllerParameters.mass );	
+
+	// Call the function that computes details an values that are needed from these
+    // parameters loaded above
+    ros::NodeHandle nodeHandle("~");
+    processFetchedParameters(nodeHandle);
+
+}
+*/
+
+
+//    ----------------------------------------------------------------------------------
+//     GGGG  EEEEE  TTTTT  PPPP     A    RRRR     A    M   M   ( )
+//    G      E        T    P   P   A A   R   R   A A   MM MM  (   )
+//    G      EEE      T    PPPP   A   A  RRRR   A   A  M M M  (   )
+//    G   G  E        T    P      AAAAA  R  R   AAAAA  M   M  (   )
+//     GGGG  EEEEE    T    P      A   A  R   R  A   A  M   M   ( )
+//    ----------------------------------------------------------------------------------
+
+
+// This function DOES NOT NEED TO BE edited for successful completion of the PPS exercise
+float getParameterFloat(ros::NodeHandle& nodeHandle, std::string name)
+{
+    float val;
+    if(!nodeHandle.getParam(name, val))
+    {
+        ROS_ERROR_STREAM("missing parameter '" << name << "'");
+    }
+    return val;
+}
+// This function DOES NOT NEED TO BE edited for successful completion of the PPS exercise
+void getParameterFloatVector(ros::NodeHandle& nodeHandle, std::string name, std::vector<float>& val, int length)
+{
+    if(!nodeHandle.getParam(name, val)){
+        ROS_ERROR_STREAM("missing parameter '" << name << "'");
+    }
+    if(val.size() != length) {
+        ROS_ERROR_STREAM("parameter '" << name << "' has wrong array length, " << length << " needed");
+    }
+}
+// This function DOES NOT NEED TO BE edited for successful completion of the PPS exercise
+int getParameterInt(ros::NodeHandle& nodeHandle, std::string name)
+{
+    int val;
+    if(!nodeHandle.getParam(name, val))
+    {
+        ROS_ERROR_STREAM("missing parameter '" << name << "'");
+    }
+    return val;
+}
+// This function DOES NOT NEED TO BE edited for successful completion of the PPS exercise
+void getParameterIntVectorWithKnownLength(ros::NodeHandle& nodeHandle, std::string name, std::vector<int>& val, int length)
+{
+    if(!nodeHandle.getParam(name, val)){
+        ROS_ERROR_STREAM("missing parameter '" << name << "'");
+    }
+    if(val.size() != length) {
+        ROS_ERROR_STREAM("parameter '" << name << "' has wrong array length, " << length << " needed");
+    }
+}
+// This function DOES NOT NEED TO BE edited for successful completion of the PPS exercise
+int getParameterIntVectorWithUnknownLength(ros::NodeHandle& nodeHandle, std::string name, std::vector<int>& val)
+{
+    if(!nodeHandle.getParam(name, val)){
+        ROS_ERROR_STREAM("missing parameter '" << name << "'");
+    }
+    return val.size();
+}
+// This function DOES NOT NEED TO BE edited for successful completion of the PPS exercise
+bool getParameterBool(ros::NodeHandle& nodeHandle, std::string name)
+{
+    bool val;
+    if(!nodeHandle.getParam(name, val))
+    {
+        ROS_ERROR_STREAM("missing parameter '" << name << "'");
+    }
+    return val;
+}
+    
+
+
+
+
+
+//    ----------------------------------------------------------------------------------
+//    M   M    A    III  N   N
+//    MM MM   A A    I   NN  N
+//    M M M  A   A   I   N N N
+//    M   M  AAAAA   I   N  NN
+//    M   M  A   A  III  N   N
+//    ----------------------------------------------------------------------------------
+
+// This function DOES NOT NEED TO BE edited for successful completion of the PPS exercise
+int main(int argc, char* argv[]) {
+    
+    // Starting the ROS-node
+    ros::init(argc, argv, "CustomControllerService");
+
+    // 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 agent ID as the "ROS_NAMESPACE" this computer.
+    // NOTES:
+    // > If you look at the "Student.launch" file in the "launch" folder, you will see
+    //   the following line of code:
+    //   <param name="studentID" value="$(optenv ROS_NAMESPACE)" />
+    //   This line of code adds a parameter named "studentID" to the "PPSClient"
+    // > Thus, to get access to this "studentID" paremeter, we first need to get a handle
+    //   to the "PPSClient" node within which this controller service is nested.
+    // Get the namespace of this "CustomControllerService" node
+    std::string m_namespace = ros::this_node::getNamespace();
+    // Get the handle to the "PPSClient" node
+    ros::NodeHandle PPSClient_nodeHandle(m_namespace + "/PPSClient");
+    // Get the value of the "studentID" parameter into the instance variable "my_agentID"
+    if(!PPSClient_nodeHandle.getParam("studentID", my_agentID))
+    {
+    	// Throw an error if the student ID parameter could not be obtained
+		ROS_ERROR("Failed to get studentID from FollowN_1Service");
+	}
+
+
+	// *********************************************************************************
+	// EVERYTHING THAT RELATES TO FETCHING PARAMETERS FROM A YAML FILE
+
+
+	// EVERYTHING FOR THE CONNECTION TO THIS AGENT's OWN PARAMETER SERVICE:
+
+	// Set the class variable "namespace_to_own_agent_parameter_service" to be a the
+    // namespace string for the parameter service that is running on the machine of this
+    // agent
+    namespace_to_own_agent_parameter_service = m_namespace + "/ParameterService";
+
+    // Create a node handle to the parameter service running on this agent's machine
+    ros::NodeHandle nodeHandle_to_own_agent_parameter_service(namespace_to_own_agent_parameter_service);
+
+    // Instantiate the local variable "controllerYamlReadyForFetchSubscriber" to be a
+    // "ros::Subscriber" type variable that subscribes to the "controllerYamlReadyForFetch" topic
+    // and calls the class function "yamlReadyForFetchCallback" each time a message is
+    // received on this topic and the message is passed as an input argument to the
+    // "yamlReadyForFetchCallback" class function.
+    ros::Subscriber controllerYamlReadyForFetchSubscriber_to_agent = nodeHandle_to_own_agent_parameter_service.subscribe("controllerYamlReadyForFetch", 1, yamlReadyForFetchCallback);
+
+
+    // EVERYTHING FOR THE CONNECTION THE COORDINATOR'S PARAMETER SERVICE:
+
+    // Set the class variable "nodeHandle_to_coordinator_parameter_service" to be a node handle
+    // for the parameter service that is running on the coordinate machine
+    // NOTE: the backslash here (i.e., "/") before the name of the node ("ParameterService")
+    //       is very important because it specifies that the name is global
+    namespace_to_coordinator_parameter_service = "/ParameterService";
+
+    // Create a node handle to the parameter service running on the coordinator machine
+    ros::NodeHandle nodeHandle_to_coordinator = ros::NodeHandle();
+    //ros::NodeHandle nodeHandle_to_coordinator_parameter_service = ros::NodeHandle(namespace_to_own_agent_parameter_service);
+    
+
+    // Instantiate the local variable "controllerYamlReadyForFetchSubscriber" to be a
+    // "ros::Subscriber" type variable that subscribes to the "controllerYamlReadyForFetch" topic
+    // and calls the class function "yamlReadyForFetchCallback" each time a message is
+    // received on this topic and the message is passed as an input argument to the
+    // "yamlReadyForFetchCallback" class function.
+    ros::Subscriber controllerYamlReadyForFetchSubscriber_to_coordinator = nodeHandle_to_coordinator.subscribe("/ParameterService/controllerYamlReadyForFetch", 1, yamlReadyForFetchCallback);
+    //ros::Subscriber controllerYamlReadyForFetchSubscriber_to_coordinator = nodeHandle_to_coordinator_parameter_service.subscribe("controllerYamlReadyForFetch", 1, yamlReadyForFetchCallback);
+
+
+    // PRINT OUT SOME INFORMATION
+
+    // Let the user know what namespaces are being used for linking to the parameter service
+    ROS_INFO_STREAM("The namespace string for accessing the Paramter Services are:");
+    ROS_INFO_STREAM("namespace_to_own_agent_parameter_service    =  " << namespace_to_own_agent_parameter_service);
+    ROS_INFO_STREAM("namespace_to_coordinator_parameter_service  =  " << namespace_to_coordinator_parameter_service);
+
+
+    // FINALLY, FETCH ANY PARAMETERS REQUIRED FROM THESE "PARAMETER SERVICES"
+
+	// Call the class function that loads the parameters for this class.
+    fetchYamlParameters(nodeHandle_to_own_agent_parameter_service);
+
+    // *********************************************************************************
+
+
+
+    // Instantiate the instance variable "debugPublisher" to be a "ros::Publisher" that
+    // advertises under the name "DebugTopic" and is a message with the structure
+    // defined in the file "DebugMsg.msg" (located in the "msg" folder).
+    debugPublisher = nodeHandle.advertise<DebugMsg>("DebugTopic", 1);
+
+    // Instantiate the local variable "setpointSubscriber" to be a "ros::Subscriber"
+    // type variable that subscribes to the "Setpoint" topic and calls the class function
+    // "setpointCallback" each time a messaged is received on this topic and the message
+    // is passed as an input argument to the "setpointCallback" class function.
+    ros::Subscriber setpointSubscriber = nodeHandle.subscribe("Setpoint", 1, setpointCallback);
+
+    // Instantiate the local variable "service" to be a "ros::ServiceServer" type
+    // variable that advertises the service called "CustomController". This service has
+    // the input-output behaviour defined in the "Controller.srv" file (located in the
+    // "srv" folder). This service, when called, is provided with the most recent
+    // measurement of the Crazyflie and is expected to respond with the control action
+    // that should be sent via the Crazyradio and requested from the Crazyflie, i.e.,
+    // this is where the "outer loop" controller function starts. When a request is made
+    // of this service the "calculateControlOutput" function is called.
+    ros::ServiceServer service = nodeHandle.advertiseService("CustomController", calculateControlOutput);
+
+    // Create a "ros::NodeHandle" type local variable "namespace_nodeHandle" that points
+    // to the name space of this node, i.e., "d_fall_pps" as specified by the line:
+    //     "using namespace d_fall_pps;"
+    // in the "DEFINES" section at the top of this file.
+    ros::NodeHandle namespace_nodeHandle(ros::this_node::getNamespace());
+
+    // Instantiate the instance variable "my_current_xyz_yaw_publisher" to be a "ros::Publisher"
+    // that advertises under the name "<my_agentID>/my_current_xyz_yaw_topic" where <my_agentID>
+    // is filled in with the student ID number of this computer. The messages published will
+    // have the structure defined in the file "Setpoint.msg" (located in the "msg" folder).
+    my_current_xyz_yaw_publisher = nodeHandle.advertise<Setpoint>("/" + std::to_string(my_agentID) + "/my_current_xyz_yaw_topic", 1);
+
+    // Print out some information to the user.
+    ROS_INFO("CustomControllerService ready");
+
+    // Enter an endless while loop to keep the node alive.
+    ros::spin();
+
+    // Return zero if the "ross::spin" is cancelled.
+    return 0;
+}
diff --git a/pps_ws/src/d_fall_pps/src/FollowCrazyflieService.cpp b/pps_ws/src/d_fall_pps/src/FollowCrazyflieService.cpp
deleted file mode 100755
index 1b36613f44bb275636ceff2fc4adc2ee772efab9..0000000000000000000000000000000000000000
--- a/pps_ws/src/d_fall_pps/src/FollowCrazyflieService.cpp
+++ /dev/null
@@ -1,236 +0,0 @@
-//    Copyright (C) 2017, ETH Zurich, D-ITET, Cyrill Burgener, Marco Mueller, Philipp Friedli
-//
-//    This file is part of D-FaLL-System.
-//    
-//    D-FaLL-System is free software: you can redistribute it and/or modify
-//    it under the terms of the GNU General Public License as published by
-//    the Free Software Foundation, either version 3 of the License, or
-//    (at your option) any later version.
-//    
-//    D-FaLL-System is distributed in the hope that it will be useful,
-//    but WITHOUT ANY WARRANTY; without even the implied warranty of
-//    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-//    GNU General Public License for more details.
-//    
-//    You should have received a copy of the GNU General Public License
-//    along with D-FaLL-System.  If not, see <http://www.gnu.org/licenses/>.
-//    
-//
-//    ----------------------------------------------------------------------------------
-//    DDDD        FFFFF        L     L           SSSS  Y   Y   SSSS  TTTTT  EEEEE  M   M
-//    D   D       F      aaa   L     L          S       Y Y   S        T    E      MM MM
-//    D   D  ---  FFFF  a   a  L     L     ---   SSS     Y     SSS     T    EEE    M M M
-//    D   D       F     a  aa  L     L              S    Y        S    T    E      M   M
-//    DDDD        F      aa a  LLLL  LLLL       SSSS     Y    SSSS     T    EEEEE  M   M
-//
-//
-//    DESCRIPTION:
-//    Controller that follows the position of another Crazyflie
-//
-//    ----------------------------------------------------------------------------------
-
-
-#include <math.h>
-#include <stdlib.h>
-#include "ros/ros.h"
-#include <std_msgs/String.h>
-#include <ros/package.h>
-#include "std_msgs/Float32.h"
-
-#include "d_fall_pps/CrazyflieData.h"
-#include "d_fall_pps/Setpoint.h"
-#include "d_fall_pps/ControlCommand.h"
-#include "d_fall_pps/Controller.h"
-
-#define PI 3.1415926535
-#define RATE_CONTROLLER 7
-
-using namespace d_fall_pps;
-
-std::vector<float>  ffThrust(4);
-std::vector<float>  feedforwardMotor(4);
-std::vector<float>  motorPoly(3);
-
-std::vector<float>  gainMatrixRoll(9);
-std::vector<float>  gainMatrixPitch(9);
-std::vector<float>  gainMatrixYaw(9);
-std::vector<float>  gainMatrixThrust(9);
-
-//K_infinite of feedback
-std::vector<float> filterGain(6);
-//only for velocity calculation
-std::vector<float> estimatorMatrix(2);
-float prevEstimate[9];
-
-std::vector<float>  setpoint(4);
-float saturationThrust;
-
-CrazyflieData previousLocation;
-
-void loadParameterFloatVector(ros::NodeHandle& nodeHandle, std::string name, std::vector<float>& val, int length) {
-    if(!nodeHandle.getParam(name, val)){
-        ROS_ERROR_STREAM("missing parameter '" << name << "'");
-    }
-    if(val.size() != length) {
-        ROS_ERROR_STREAM("parameter '" << name << "' has wrong array length, " << length << " needed");
-    }
-}
-
-void loadParameters(ros::NodeHandle& nodeHandle) {
-    loadParameterFloatVector(nodeHandle, "feedforwardMotor", feedforwardMotor, 4);
-    loadParameterFloatVector(nodeHandle, "motorPoly", motorPoly, 3);
-
-    for(int i = 0; i < 4; ++i) {
-        ffThrust[i] = motorPoly[2] * feedforwardMotor[i] * feedforwardMotor[i] + motorPoly[1] * feedforwardMotor[i] + motorPoly[0];
-    }
-    saturationThrust = motorPoly[2] * 12000 * 12000 + motorPoly[1] * 12000 + motorPoly[0];
-
-    loadParameterFloatVector(nodeHandle, "gainMatrixRoll", gainMatrixRoll, 9);
-    loadParameterFloatVector(nodeHandle, "gainMatrixPitch", gainMatrixPitch, 9);
-    loadParameterFloatVector(nodeHandle, "gainMatrixYaw", gainMatrixYaw, 9);
-    loadParameterFloatVector(nodeHandle, "gainMatrixThrust", gainMatrixThrust, 9);
-
-    loadParameterFloatVector(nodeHandle, "filterGain", filterGain, 6);
-    loadParameterFloatVector(nodeHandle, "estimatorMatrix", estimatorMatrix, 2);
-
-    loadParameterFloatVector(nodeHandle, "defaultSetpoint", setpoint, 4);
-}
-
-float computeMotorPolyBackward(float thrust) {
-    return (-motorPoly[1] + sqrt(motorPoly[1] * motorPoly[1] - 4 * motorPoly[2] * (motorPoly[0] - thrust))) / (2 * motorPoly[2]);
-}
-
-
-//Kalman
-void estimateState(Controller::Request &request, float (&est)[9]) {
-    // attitude
-    est[6] = request.ownCrazyflie.roll;
-    est[7] = request.ownCrazyflie.pitch;
-    est[8] = request.ownCrazyflie.yaw;
-
-    //velocity & filtering
-    float ahat_x[6]; //estimator matrix times state (x, y, z, vx, vy, vz)
-    ahat_x[0] = 0; ahat_x[1]=0; ahat_x[2]=0;
-    ahat_x[3] = estimatorMatrix[0] * prevEstimate[0] + estimatorMatrix[1] * prevEstimate[3];
-    ahat_x[4] = estimatorMatrix[0] * prevEstimate[1] + estimatorMatrix[1] * prevEstimate[4];
-    ahat_x[5] = estimatorMatrix[0] * prevEstimate[2] + estimatorMatrix[1] * prevEstimate[5];
-
-    
-    float k_x[6]; //filterGain times state
-    k_x[0] = request.ownCrazyflie.x * filterGain[0];
-    k_x[1] = request.ownCrazyflie.y * filterGain[1];
-    k_x[2] = request.ownCrazyflie.z * filterGain[2];
-    k_x[3] = request.ownCrazyflie.x * filterGain[3];
-    k_x[4] = request.ownCrazyflie.y * filterGain[4];
-    k_x[5] = request.ownCrazyflie.z * filterGain[5];
-   
-    est[0] = ahat_x[0] + k_x[0];
-    est[1] = ahat_x[1] + k_x[1];
-	est[2] = ahat_x[2] + k_x[2];
-    est[3] = ahat_x[3] + k_x[3];
-    est[4] = ahat_x[4] + k_x[4];
-    est[5] = ahat_x[5] + k_x[5];
-
-    memcpy(prevEstimate, est, 9 * sizeof(float));
-    
-}
-
-
-void convertIntoBodyFrame(float est[9], float (&state)[9], float yaw_measured) {
-	float sinYaw = sin(yaw_measured);
-    float cosYaw = cos(yaw_measured);
-
-    state[0] = est[0] * cosYaw + est[1] * sinYaw;
-    state[1] = -est[0] * sinYaw + est[1] * cosYaw;
-    state[2] = est[2];
-
-    state[3] = est[3] * cosYaw + est[4] * sinYaw;
-    state[4] = -est[3] * sinYaw + est[4] * cosYaw;
-    state[5] = est[5];
-
-    state[6] = est[6];
-    state[7] = est[7];
-    state[8] = est[8];
-}
-
-bool calculateControlOutput(Controller::Request &request, Controller::Response &response) {
-    CrazyflieData vicon = request.ownCrazyflie;
-	
-	float yaw_measured = request.ownCrazyflie.yaw;
-
-    //move coordinate system to make setpoint origin
-    request.ownCrazyflie.x -= setpoint[0];
-    request.ownCrazyflie.y -= setpoint[1];
-    request.ownCrazyflie.z -= setpoint[2];
-    float yaw = request.ownCrazyflie.yaw - setpoint[3];
-
-    while(yaw > PI) {yaw -= 2 * PI;}
-    while(yaw < -PI) {yaw += 2 * PI;}
-    request.ownCrazyflie.yaw = yaw;
-
-    float est[9]; //px, py, pz, vx, vy, vz, roll, pitch, yaw
-    estimateState(request, est);
-	
-    float state[9]; //px, py, pz, vx, vy, vz, roll, pitch, yaw
-    convertIntoBodyFrame(est, state, yaw_measured);
-
-    //calculate feedback
-    float outRoll = 0;
-    float outPitch = 0;
-    float outYaw = 0;
-    float thrustIntermediate = 0;
-    for(int i = 0; i < 9; ++i) {
-    	outRoll -= gainMatrixRoll[i] * state[i];
-    	outPitch -= gainMatrixPitch[i] * state[i];
-    	outYaw -= gainMatrixYaw[i] * state[i];
-    	thrustIntermediate -= gainMatrixThrust[i] * state[i];
-    }
-
-    //INFORMATION: this ugly fix was needed for the older firmware
-    //outYaw *= 0.5;
-
-    response.controlOutput.roll = outRoll;
-    response.controlOutput.pitch = outPitch;
-    response.controlOutput.yaw = outYaw;
-
-    if(thrustIntermediate > saturationThrust)
-        thrustIntermediate = saturationThrust;
-    else if(thrustIntermediate < -saturationThrust)
-        thrustIntermediate = -saturationThrust;
-
-    response.controlOutput.motorCmd1 = computeMotorPolyBackward(thrustIntermediate + ffThrust[0]);
-    response.controlOutput.motorCmd2 = computeMotorPolyBackward(thrustIntermediate + ffThrust[1]);
-    response.controlOutput.motorCmd3 = computeMotorPolyBackward(thrustIntermediate + ffThrust[2]);
-    response.controlOutput.motorCmd4 = computeMotorPolyBackward(thrustIntermediate + ffThrust[3]);
-
-    response.controlOutput.onboardControllerType = RATE_CONTROLLER;
-
-    previousLocation = request.ownCrazyflie;
-   
-	return true;
-}
-
-//the setpoint is copied from the other crazyflie. This crazyflie should then make the same figure in its own area
-void followCallback(const Setpoint& newSetpoint) {
-    setpoint[0] = newSetpoint.x;
-    setpoint[1] = newSetpoint.y;
-    setpoint[2] = newSetpoint.z;
-    setpoint[3] = newSetpoint.yaw;
-}
-
-
-int main(int argc, char* argv[]) {
-    ros::init(argc, argv, "FollowControllerService");
-
-    ros::NodeHandle nodeHandle("~");
-    loadParameters(nodeHandle);
-
-    ros::Subscriber followSubscriber = nodeHandle.subscribe("/3/CircleControllerService/FollowTopic", 5, followCallback);
-
-    ros::ServiceServer service = nodeHandle.advertiseService("FollowController", calculateControlOutput);
-    ROS_INFO("FollowCrazyflieService ready");
-
-    ros::spin();
-
-    return 0;
-}
diff --git a/pps_ws/src/d_fall_pps/src/FollowN_1Service.cpp b/pps_ws/src/d_fall_pps/src/FollowN_1Service.cpp
deleted file mode 100644
index 84dec28c5a6ab657e49679213c809a84348e6ccf..0000000000000000000000000000000000000000
--- a/pps_ws/src/d_fall_pps/src/FollowN_1Service.cpp
+++ /dev/null
@@ -1,271 +0,0 @@
-//    Copyright (C) 2017, ETH Zurich, D-ITET, Angel Romero, Cyrill Burgener, Marco Mueller, Philipp Friedli
-//
-//    This file is part of D-FaLL-System.
-//    
-//    D-FaLL-System is free software: you can redistribute it and/or modify
-//    it under the terms of the GNU General Public License as published by
-//    the Free Software Foundation, either version 3 of the License, or
-//    (at your option) any later version.
-//    
-//    D-FaLL-System is distributed in the hope that it will be useful,
-//    but WITHOUT ANY WARRANTY; without even the implied warranty of
-//    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-//    GNU General Public License for more details.
-//    
-//    You should have received a copy of the GNU General Public License
-//    along with D-FaLL-System.  If not, see <http://www.gnu.org/licenses/>.
-//    
-//
-//    ----------------------------------------------------------------------------------
-//    DDDD        FFFFF        L     L           SSSS  Y   Y   SSSS  TTTTT  EEEEE  M   M
-//    D   D       F      aaa   L     L          S       Y Y   S        T    E      MM MM
-//    D   D  ---  FFFF  a   a  L     L     ---   SSS     Y     SSS     T    EEE    M M M
-//    D   D       F     a  aa  L     L              S    Y        S    T    E      M   M
-//    DDDD        F      aa a  LLLL  LLLL       SSSS     Y    SSSS     T    EEEEE  M   M
-//
-//
-//    DESCRIPTION:
-//    Controller that follows the Crazyflie with ID N-1
-//
-//    ----------------------------------------------------------------------------------
-
-
-#include <math.h>
-#include <stdlib.h>
-#include "ros/ros.h"
-#include <std_msgs/String.h>
-#include <ros/package.h>
-#include "std_msgs/Float32.h"
-
-#include "d_fall_pps/CrazyflieData.h"
-#include "d_fall_pps/Setpoint.h"
-#include "d_fall_pps/ControlCommand.h"
-#include "d_fall_pps/Controller.h"
-
-#define PI 3.1415926535
-#define RATE_CONTROLLER 7
-
-using namespace d_fall_pps;
-
-std::vector<float>  ffThrust(4);
-std::vector<float>  feedforwardMotor(4);
-std::vector<float>  motorPoly(3);
-
-std::vector<float>  gainMatrixRoll(9);
-std::vector<float>  gainMatrixPitch(9);
-std::vector<float>  gainMatrixYaw(9);
-std::vector<float>  gainMatrixThrust(9);
-
-//K_infinite of feedback
-std::vector<float> filterGain(6);
-//only for velocity calculation
-std::vector<float> estimatorMatrix(2);
-float prevEstimate[9];
-
-std::vector<float>  setpoint(4);
-float saturationThrust;
-ros::Publisher followPublisher;
-ros::Subscriber followSubscriber;
-
-CrazyflieData previousLocation;
-
-void loadParameterFloatVector(ros::NodeHandle& nodeHandle, std::string name, std::vector<float>& val, int length) {
-    if(!nodeHandle.getParam(name, val)){
-        ROS_ERROR_STREAM("missing parameter '" << name << "'");
-    }
-    if(val.size() != length) {
-        ROS_ERROR_STREAM("parameter '" << name << "' has wrong array length, " << length << " needed");
-    }
-}
-
-void loadParameters(ros::NodeHandle& nodeHandle) {
-    loadParameterFloatVector(nodeHandle, "feedforwardMotor", feedforwardMotor, 4);
-    loadParameterFloatVector(nodeHandle, "motorPoly", motorPoly, 3);
-
-    for(int i = 0; i < 4; ++i) {
-        ffThrust[i] = motorPoly[2] * feedforwardMotor[i] * feedforwardMotor[i] + motorPoly[1] * feedforwardMotor[i] + motorPoly[0];
-    }
-    saturationThrust = motorPoly[2] * 12000 * 12000 + motorPoly[1] * 12000 + motorPoly[0];
-
-    loadParameterFloatVector(nodeHandle, "gainMatrixRoll", gainMatrixRoll, 9);
-    loadParameterFloatVector(nodeHandle, "gainMatrixPitch", gainMatrixPitch, 9);
-    loadParameterFloatVector(nodeHandle, "gainMatrixYaw", gainMatrixYaw, 9);
-    loadParameterFloatVector(nodeHandle, "gainMatrixThrust", gainMatrixThrust, 9);
-
-    loadParameterFloatVector(nodeHandle, "filterGain", filterGain, 6);
-    loadParameterFloatVector(nodeHandle, "estimatorMatrix", estimatorMatrix, 2);
-
-    loadParameterFloatVector(nodeHandle, "defaultSetpoint", setpoint, 4);
-}
-
-float computeMotorPolyBackward(float thrust) {
-    return (-motorPoly[1] + sqrt(motorPoly[1] * motorPoly[1] - 4 * motorPoly[2] * (motorPoly[0] - thrust))) / (2 * motorPoly[2]);
-}
-
-
-//Kalman
-void estimateState(Controller::Request &request, float (&est)[9]) {
-    // attitude
-    est[6] = request.ownCrazyflie.roll;
-    est[7] = request.ownCrazyflie.pitch;
-    est[8] = request.ownCrazyflie.yaw;
-
-    //velocity & filtering
-    float ahat_x[6]; //estimator matrix times state (x, y, z, vx, vy, vz)
-    ahat_x[0] = 0; ahat_x[1]=0; ahat_x[2]=0;
-    ahat_x[3] = estimatorMatrix[0] * prevEstimate[0] + estimatorMatrix[1] * prevEstimate[3];
-    ahat_x[4] = estimatorMatrix[0] * prevEstimate[1] + estimatorMatrix[1] * prevEstimate[4];
-    ahat_x[5] = estimatorMatrix[0] * prevEstimate[2] + estimatorMatrix[1] * prevEstimate[5];
-
-    
-    float k_x[6]; //filterGain times state
-    k_x[0] = request.ownCrazyflie.x * filterGain[0];
-    k_x[1] = request.ownCrazyflie.y * filterGain[1];
-    k_x[2] = request.ownCrazyflie.z * filterGain[2];
-    k_x[3] = request.ownCrazyflie.x * filterGain[3];
-    k_x[4] = request.ownCrazyflie.y * filterGain[4];
-    k_x[5] = request.ownCrazyflie.z * filterGain[5];
-   
-    est[0] = ahat_x[0] + k_x[0];
-    est[1] = ahat_x[1] + k_x[1];
-	est[2] = ahat_x[2] + k_x[2];
-    est[3] = ahat_x[3] + k_x[3];
-    est[4] = ahat_x[4] + k_x[4];
-    est[5] = ahat_x[5] + k_x[5];
-
-    memcpy(prevEstimate, est, 9 * sizeof(float));
-    
-}
-
-
-void convertIntoBodyFrame(float est[9], float (&state)[9], float yaw_measured) {
-	float sinYaw = sin(yaw_measured);
-    float cosYaw = cos(yaw_measured);
-
-    state[0] = est[0] * cosYaw + est[1] * sinYaw;
-    state[1] = -est[0] * sinYaw + est[1] * cosYaw;
-    state[2] = est[2];
-
-    state[3] = est[3] * cosYaw + est[4] * sinYaw;
-    state[4] = -est[3] * sinYaw + est[4] * cosYaw;
-    state[5] = est[5];
-
-    state[6] = est[6];
-    state[7] = est[7];
-    state[8] = est[8];
-}
-
-bool calculateControlOutput(Controller::Request &request, Controller::Response &response) {
-    CrazyflieData vicon = request.ownCrazyflie;
-	
-	float yaw_measured = request.ownCrazyflie.yaw;
-
-    //publish setpoint for FollowController of another student group
-    Setpoint pubSetpoint;
-    pubSetpoint.x = request.ownCrazyflie.x;
-    pubSetpoint.y = request.ownCrazyflie.y;
-    pubSetpoint.z = request.ownCrazyflie.z;
-    pubSetpoint.yaw = request.ownCrazyflie.yaw;
-    followPublisher.publish(pubSetpoint);
-
-    //move coordinate system to make setpoint origin
-    request.ownCrazyflie.x -= setpoint[0];
-    request.ownCrazyflie.y -= setpoint[1];
-    request.ownCrazyflie.z -= setpoint[2];
-    float yaw = request.ownCrazyflie.yaw - setpoint[3];
-
-    while(yaw > PI) {yaw -= 2 * PI;}
-    while(yaw < -PI) {yaw += 2 * PI;}
-    request.ownCrazyflie.yaw = yaw;
-
-    float est[9]; //px, py, pz, vx, vy, vz, roll, pitch, yaw
-    estimateState(request, est);
-	
-    float state[9]; //px, py, pz, vx, vy, vz, roll, pitch, yaw
-    convertIntoBodyFrame(est, state, yaw_measured);
-
-    //calculate feedback
-    float outRoll = 0;
-    float outPitch = 0;
-    float outYaw = 0;
-    float thrustIntermediate = 0;
-    for(int i = 0; i < 9; ++i) {
-    	outRoll -= gainMatrixRoll[i] * state[i];
-    	outPitch -= gainMatrixPitch[i] * state[i];
-    	outYaw -= gainMatrixYaw[i] * state[i];
-    	thrustIntermediate -= gainMatrixThrust[i] * state[i];
-    }
-
-    //INFORMATION: this ugly fix was needed for the older firmware
-    //outYaw *= 0.5;
-
-    response.controlOutput.roll = outRoll;
-    response.controlOutput.pitch = outPitch;
-    response.controlOutput.yaw = outYaw;
-
-    if(thrustIntermediate > saturationThrust)
-        thrustIntermediate = saturationThrust;
-    else if(thrustIntermediate < -saturationThrust)
-        thrustIntermediate = -saturationThrust;
-
-    response.controlOutput.motorCmd1 = computeMotorPolyBackward(thrustIntermediate + ffThrust[0]);
-    response.controlOutput.motorCmd2 = computeMotorPolyBackward(thrustIntermediate + ffThrust[1]);
-    response.controlOutput.motorCmd3 = computeMotorPolyBackward(thrustIntermediate + ffThrust[2]);
-    response.controlOutput.motorCmd4 = computeMotorPolyBackward(thrustIntermediate + ffThrust[3]);
-
-    response.controlOutput.onboardControllerType = RATE_CONTROLLER;
-
-    previousLocation = request.ownCrazyflie;
-   
-	return true;
-}
-
-//the setpoint is copied from the other crazyflie. This crazyflie should then make the same figure in its own area
-void followCallback(const Setpoint& newSetpoint) {
-    setpoint[0] = newSetpoint.x;
-    setpoint[1] = newSetpoint.y;
-    setpoint[2] = newSetpoint.z;
-    setpoint[3] = newSetpoint.yaw;
-    ROS_INFO("received callback new setpoint from FollowN1Service/FollowTopic");
-}
-
-
-int main(int argc, char* argv[]) {
-    ros::init(argc, argv, "FollowN_1Service");
-
-    ros::NodeHandle nodeHandle("~");
-    loadParameters(nodeHandle);
-
-    int student_id;
-    std::string m_namespace = ros::this_node::getNamespace();
-    ros::NodeHandle PPSClient_nodeHandle(m_namespace + "/PPSClient");
-
-    if(!PPSClient_nodeHandle.getParam("studentID", student_id))
-    {
-		ROS_ERROR("Failed to get studentID from FollowN_1Service");
-	}
-
-    followPublisher = nodeHandle.advertise<Setpoint>("/" + std::to_string(student_id) + "/FollowN_1Service/FollowTopic", 1);
-
-    if(student_id != 1)
-    {
-        // subscribe to n-1 setpoint
-        followSubscriber = nodeHandle.subscribe("/" + std::to_string(student_id - 1) + "/FollowN_1Service/FollowTopic", 1, followCallback);
-    }
-    else
-    {
-        // what is the setpoint for 1? 0 0 0.5 0
-        setpoint[0] = 0;
-        setpoint[1] = 0;
-        setpoint[2] = 0.5;
-        setpoint[3] = 0;
-    }
-
-
-    ros::ServiceServer service = nodeHandle.advertiseService("FollowController", calculateControlOutput);
-    ROS_INFO("FollowN_1Service ready");
-
-    ros::spin();
-
-    return 0;
-}
diff --git a/pps_ws/src/d_fall_pps/src/CustomControllerService.cpp b/pps_ws/src/d_fall_pps/src/StudentControllerService.cpp
similarity index 100%
rename from pps_ws/src/d_fall_pps/src/CustomControllerService.cpp
rename to pps_ws/src/d_fall_pps/src/StudentControllerService.cpp