From 3a9e1f3e854409b4e251edb39283ebfa223f16d3 Mon Sep 17 00:00:00 2001
From: Paul Beuchat <beuchatp@control.ee.ethz.ch>
Date: Wed, 25 Apr 2018 09:49:59 +0200
Subject: [PATCH] Added switching between four controller to PPSClient

---
 .../src/d_fall_pps/include/nodes/PPSClient.h  | 18 +++-
 pps_ws/src/d_fall_pps/param/ClientConfig.yaml |  8 +-
 .../src/nodes/MpcControllerService.cpp        |  2 +-
 pps_ws/src/d_fall_pps/src/nodes/PPSClient.cpp | 83 +++++++++++++++++--
 .../src/nodes/StudentControllerService.cpp    |  2 +-
 5 files changed, 98 insertions(+), 15 deletions(-)

diff --git a/pps_ws/src/d_fall_pps/include/nodes/PPSClient.h b/pps_ws/src/d_fall_pps/include/nodes/PPSClient.h
index 46a65d04..d87085d5 100644
--- a/pps_ws/src/d_fall_pps/include/nodes/PPSClient.h
+++ b/pps_ws/src/d_fall_pps/include/nodes/PPSClient.h
@@ -83,8 +83,10 @@
 #define CF_COMMAND_TYPE_ANGLE  8
 
 // Types of controllers being used:
-#define SAFE_CONTROLLER   0
-#define DEMO_CONTROLLER   1
+#define SAFE_CONTROLLER      0
+#define DEMO_CONTROLLER      1
+#define STUDENT_CONTROLLER   3
+#define MPC_CONTROLLER       4
 
 // The constants that "command" changes in the
 // operation state of this agent
@@ -139,10 +141,15 @@ using namespace d_fall_pps;
 // "agentID", gives namespace and identifier in CentralManagerService
 int agentID;
 
-// The safe controller specified in the ClientConfig.yaml, is considered stable
+// The safe controller specified in the ClientConfig.yaml
 ros::ServiceClient safeController;
-// The Demo controller specified in the ClientConfig.yaml, is considered potentially unstable
+// The Demo controller specified in the ClientConfig.yaml
 ros::ServiceClient demoController;
+// The Demo controller specified in the ClientConfig.yaml
+ros::ServiceClient studentController;
+// The Demo controller specified in the ClientConfig.yaml
+ros::ServiceClient mpcController;
+
 
 //values for safteyCheck
 bool strictSafety;
@@ -281,6 +288,9 @@ void CFBatteryCallback(const std_msgs::Float32& msg);
 
 void loadSafeController();
 void loadDemoController();
+void loadStudentController();
+void loadMpcController();
+
 void sendMessageUsingController(int controller);
 void setInstantController(int controller);
 int getInstantController();
diff --git a/pps_ws/src/d_fall_pps/param/ClientConfig.yaml b/pps_ws/src/d_fall_pps/param/ClientConfig.yaml
index a32012ed..101820c3 100755
--- a/pps_ws/src/d_fall_pps/param/ClientConfig.yaml
+++ b/pps_ws/src/d_fall_pps/param/ClientConfig.yaml
@@ -1,7 +1,11 @@
-safeController: "SafeControllerService/RateController"
-demoController: "DemoControllerService/DemoController"
+safeController:    "SafeControllerService/RateController"
+demoController:    "DemoControllerService/DemoController"
+studentController: "StudentControllerService/StudentController"
+mpcController:     "MpcControllerService/MpcController"
+
 strictSafety: false
 angleMargin: 0.6
+
 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/src/nodes/MpcControllerService.cpp b/pps_ws/src/d_fall_pps/src/nodes/MpcControllerService.cpp
index f2aa6049..a4a2eb6a 100644
--- a/pps_ws/src/d_fall_pps/src/nodes/MpcControllerService.cpp
+++ b/pps_ws/src/d_fall_pps/src/nodes/MpcControllerService.cpp
@@ -1013,7 +1013,7 @@ int main(int argc, char* argv[]) {
     // 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);
+    ros::ServiceServer service = nodeHandle.advertiseService("MpcController", 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:
diff --git a/pps_ws/src/d_fall_pps/src/nodes/PPSClient.cpp b/pps_ws/src/d_fall_pps/src/nodes/PPSClient.cpp
index ef718af6..abccda99 100755
--- a/pps_ws/src/d_fall_pps/src/nodes/PPSClient.cpp
+++ b/pps_ws/src/d_fall_pps/src/nodes/PPSClient.cpp
@@ -278,15 +278,36 @@ void viconCallback(const ViconData& viconData) {
             {
                 if(!global.occluded)    //if it is not occluded, then proceed to compute the controller output.
                 {
-                    // only enter in demo controller if we are not using safe controller AND the flying state is FLYING
-                    if(getInstantController() == DEMO_CONTROLLER && flying_state == STATE_FLYING)
+                    // Only call an "non-safe" controller if:
+                    // 1) we are not currently using safe controller, AND
+                    // 2) the flying state is FLYING
+                    if( (getInstantController() != SAFE_CONTROLLER) && (flying_state == STATE_FLYING) )
                     {
-                        bool success = demoController.call(controllerCall);
+                        // Initialise a local boolean success variable
+                        bool success = false;
+
+                        switch(getInstantController())
+                        {
+                            case DEMO_CONTROLLER:
+                                success = demoController.call(controllerCall);
+                                break;
+                            case STUDENT_CONTROLLER:
+                                success = studentController.call(controllerCall);
+                                break;
+                            case MPC_CONTROLLER:
+                                success = mpcController.call(controllerCall);
+                                break;
+                            default:
+                                ROS_ERROR("[PPS CLIENT] the current controller was not recognised");
+                                break;
+                        }
+
+                        // Ensure success and enforce safety
                         if(!success)
                         {
-                            ROS_ERROR("[PPS CLIENT] Failed to call demo controller, switching to safe controller");
-                            ROS_ERROR_STREAM("[PPS CLIENT] demo controller status: valid: " << demoController.isValid() << ", exists: " << demoController.exists());
-                            ROS_ERROR_STREAM("[PPS CLIENT] demo controller name: " << demoController.getService());
+                            ROS_ERROR("[PPS CLIENT] Failed to call a 'non-safe' controller, switching to safe controller");
+                            //ROS_ERROR_STREAM("[PPS CLIENT] 'non-safe' controller status: valid: " << demoController.isValid() << ", exists: " << demoController.exists());
+                            //ROS_ERROR_STREAM("[PPS CLIENT] 'non-safe' controller name: " << demoController.getService());
                             setInstantController(SAFE_CONTROLLER);
                         }
                         else if(!safetyCheck(global, controllerCall.response.controlOutput))
@@ -294,8 +315,11 @@ void viconCallback(const ViconData& viconData) {
                             setInstantController(SAFE_CONTROLLER);
                             ROS_INFO_STREAM("[PPS CLIENT] safety check failed, switching to safe controller");
                         }
+
+                        
                     }
-                    else        //SAFE_CONTROLLER and state is different from flying
+                    // SAFE_CONTROLLER and state is different from flying
+                    else
                     {
                         calculateDistanceToCurrentSafeSetpoint(local); // update distance, it also updates the unit vector
                         // ROS_INFO_STREAM("distance: " << distance);
@@ -414,6 +438,16 @@ void commandCallback(const std_msgs::Int32& commandMsg) {
             setControllerUsed(DEMO_CONTROLLER);
     		break;
 
+        case CMD_USE_STUDENT_CONTROLLER:
+            ROS_INFO("[PPS CLIENT] USE_STUDENT_CONTROLLER Command received");
+            setControllerUsed(STUDENT_CONTROLLER);
+            break;
+
+        case CMD_USE_MPC_CONTROLLER:
+            ROS_INFO("[PPS CLIENT] USE_MPC_CONTROLLER Command received");
+            setControllerUsed(MPC_CONTROLLER);
+            break;
+
     	case CMD_CRAZYFLY_TAKE_OFF:
             if(flying_state == STATE_MOTORS_OFF)
             {
@@ -744,6 +778,35 @@ void loadDemoController()
     ROS_INFO_STREAM("[PPS CLIENT] Loaded demo controller " << demoController.getService());
 }
 
+void loadStudentController()
+{
+    ros::NodeHandle nodeHandle("~");
+
+    std::string studentControllerName;
+    if(!nodeHandle.getParam("studentController", studentControllerName))
+    {
+        ROS_ERROR("[PPS CLIENT] Failed to get student controller name");
+        return;
+    }
+
+    studentController = ros::service::createClient<Controller>(studentControllerName, true);
+    ROS_INFO_STREAM("[PPS CLIENT] Loaded student controller " << studentController.getService());
+}
+
+void loadMpcController()
+{
+    ros::NodeHandle nodeHandle("~");
+
+    std::string mpcControllerName;
+    if(!nodeHandle.getParam("mpcController", mpcControllerName))
+    {
+        ROS_ERROR("[PPS CLIENT] Failed to get mpc controller name");
+        return;
+    }
+
+    mpcController = ros::service::createClient<Controller>(mpcControllerName, true);
+    ROS_INFO_STREAM("[PPS CLIENT] Loaded mpc controller " << mpcController.getService());
+}
 
 void sendMessageUsingController(int controller)
 {
@@ -765,6 +828,12 @@ void setInstantController(int controller) //for right now, temporal use
         case DEMO_CONTROLLER:
             loadDemoController();
             break;
+        case STUDENT_CONTROLLER:
+            loadStudentController();
+            break;
+        case MPC_CONTROLLER:
+            loadMpcController();
+            break;
         default:
             break;
     }
diff --git a/pps_ws/src/d_fall_pps/src/nodes/StudentControllerService.cpp b/pps_ws/src/d_fall_pps/src/nodes/StudentControllerService.cpp
index e31a3b81..1bfb40a7 100644
--- a/pps_ws/src/d_fall_pps/src/nodes/StudentControllerService.cpp
+++ b/pps_ws/src/d_fall_pps/src/nodes/StudentControllerService.cpp
@@ -830,7 +830,7 @@ int main(int argc, char* argv[]) {
     // 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);
+    ros::ServiceServer service = nodeHandle.advertiseService("StudentController", 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:
-- 
GitLab