From 67970ddf7fff690279f5897952b6367828262448 Mon Sep 17 00:00:00 2001 From: Paul Beuchat <beuchatp@control.ee.ethz.ch> Date: Fri, 27 Mar 2020 10:55:44 +0100 Subject: [PATCH] Added a flag in the controller call so that the flying agent client node notifies the controller being call of whether this is the first call or not. The default controller and student controller correctly respond to this flag, while the other controllers need to be updated to take it into account --- .../include/nodes/DefaultControllerService.h | 6 +-- .../include/nodes/FlyingAgentClient.h | 9 ++-- .../src/nodes/DefaultControllerService.cpp | 47 ++++++++++++++----- .../dfall_pkg/src/nodes/FlyingAgentClient.cpp | 19 ++++++++ .../src/nodes/StudentControllerService.cpp | 19 ++++++-- dfall_ws/src/dfall_pkg/srv/Controller.srv | 1 + 6 files changed, 80 insertions(+), 21 deletions(-) diff --git a/dfall_ws/src/dfall_pkg/include/nodes/DefaultControllerService.h b/dfall_ws/src/dfall_pkg/include/nodes/DefaultControllerService.h index 17079bc7..a838f2f2 100644 --- a/dfall_ws/src/dfall_pkg/include/nodes/DefaultControllerService.h +++ b/dfall_ws/src/dfall_pkg/include/nodes/DefaultControllerService.h @@ -426,7 +426,7 @@ bool requestManoeuvreCallback(IntIntService::Request &request, IntIntService::Re bool calculateControlOutput(Controller::Request &request, Controller::Response &response); // > For the normal state -void computeResponse_for_normal(Controller::Response &response); +void computeResponse_for_normal(bool isFirstControllerCall, Controller::Response &response); // > For the standby state (also used for unknown state) void computeResponse_for_standby(Controller::Response &response); // > For the take-off phases @@ -449,8 +449,8 @@ void calculateControlOutput_viaLQR_givenError(float stateErrorBody[9], Controlle // ESTIMATOR COMPUTATIONS void performEstimatorUpdate_forStateInterial(Controller::Request &request); -void performEstimatorUpdate_forStateInterial_viaFiniteDifference(); -void performEstimatorUpdate_forStateInterial_viaPointMassKalmanFilter(); +void performEstimatorUpdate_forStateInterial_viaFiniteDifference(bool isFirstUpdate); +void performEstimatorUpdate_forStateInterial_viaPointMassKalmanFilter(bool isFirstUpdate); // PUBLISHING OF THE DEBUG MESSAGE void construct_and_publish_debug_message(Controller::Request &request, Controller::Response &response); diff --git a/dfall_ws/src/dfall_pkg/include/nodes/FlyingAgentClient.h b/dfall_ws/src/dfall_pkg/include/nodes/FlyingAgentClient.h index ade107f9..61b6d330 100644 --- a/dfall_ws/src/dfall_pkg/include/nodes/FlyingAgentClient.h +++ b/dfall_ws/src/dfall_pkg/include/nodes/FlyingAgentClient.h @@ -175,15 +175,18 @@ ros::Timer m_timer_land_complete; // VARIABLES RELATING TO CONTROLLER SELECTION +// > Boolean indicating that the controller service clients +// have been successfully created +bool m_controllers_avialble = false; // > Integer indicating the controller that is to be // used in when motion capture data is received int m_instant_controller; // > Pointer to the controller service client that // agrees with the "m_instant_controller" variable ros::ServiceClient* m_instant_controller_service_client; -// > Boolean indicating that the controller service clients -// have been successfully created -bool m_controllers_avialble = false; +// > Boolean indicating that this is the first call to +// the instant controller +bool m_isFirstCall_to_instant_controller = false; // > Timer for creating the controller service client after // some delay ros::Timer m_timer_for_createAllControllerServiceClients; diff --git a/dfall_ws/src/dfall_pkg/src/nodes/DefaultControllerService.cpp b/dfall_ws/src/dfall_pkg/src/nodes/DefaultControllerService.cpp index 985e50d7..3e6cd6d9 100644 --- a/dfall_ws/src/dfall_pkg/src/nodes/DefaultControllerService.cpp +++ b/dfall_ws/src/dfall_pkg/src/nodes/DefaultControllerService.cpp @@ -188,7 +188,7 @@ bool calculateControlOutput(Controller::Request &request, Controller::Response & switch (m_current_state) { case DEFAULT_CONTROLLER_STATE_NORMAL: - computeResponse_for_normal(response); + computeResponse_for_normal(request.isFirstControllerCall, response); break; case DEFAULT_CONTROLLER_STATE_TAKEOFF_SPIN_MOTORS: @@ -295,10 +295,10 @@ void computeResponse_for_standby(Controller::Response &response) } -void computeResponse_for_normal(Controller::Response &response) +void computeResponse_for_normal(bool isFirstControllerCall,Controller::Response &response) { // Check if the state "just recently" changed - if (m_current_state_changed) + if (m_current_state_changed || isFirstControllerCall) { // PERFORM "ONE-OFF" OPERATIONS HERE // Set the "m_setpoint_for_controller" variable @@ -794,11 +794,11 @@ void performEstimatorUpdate_forStateInterial(Controller::Request &request) // RUN THE FINITE DIFFERENCE ESTIMATOR - performEstimatorUpdate_forStateInterial_viaFiniteDifference(); + performEstimatorUpdate_forStateInterial_viaFiniteDifference(request.isFirstControllerCall); // RUN THE POINT MASS KALMAN FILTER ESTIMATOR - performEstimatorUpdate_forStateInterial_viaPointMassKalmanFilter(); + performEstimatorUpdate_forStateInterial_viaPointMassKalmanFilter(request.isFirstControllerCall); // FILLE IN THE STATE INERTIAL ESTIMATE TO BE USED FOR CONTROL @@ -853,7 +853,7 @@ void performEstimatorUpdate_forStateInterial(Controller::Request &request) -void performEstimatorUpdate_forStateInterial_viaFiniteDifference() +void performEstimatorUpdate_forStateInterial_viaFiniteDifference(bool isFirstUpdate) { // PUT IN THE CURRENT MEASUREMENT DIRECTLY // > for (x,y,z) position @@ -866,15 +866,26 @@ void performEstimatorUpdate_forStateInterial_viaFiniteDifference() m_stateInterialEstimate_viaFiniteDifference[8] = m_current_xzy_rpy_measurement[5]; // COMPUTE THE VELOCITIES VIA FINITE DIFFERENCE - // > for (x,y,z) velocities - m_stateInterialEstimate_viaFiniteDifference[3] = (m_current_xzy_rpy_measurement[0] - m_previous_xzy_rpy_measurement[0]) * m_estimator_frequency; - m_stateInterialEstimate_viaFiniteDifference[4] = (m_current_xzy_rpy_measurement[1] - m_previous_xzy_rpy_measurement[1]) * m_estimator_frequency; - m_stateInterialEstimate_viaFiniteDifference[5] = (m_current_xzy_rpy_measurement[2] - m_previous_xzy_rpy_measurement[2]) * m_estimator_frequency; + // > Only if this is NOT the first call to the controller + if (!isFirstUpdate) + { + // > for (x,y,z) velocities + m_stateInterialEstimate_viaFiniteDifference[3] = (m_current_xzy_rpy_measurement[0] - m_previous_xzy_rpy_measurement[0]) * m_estimator_frequency; + m_stateInterialEstimate_viaFiniteDifference[4] = (m_current_xzy_rpy_measurement[1] - m_previous_xzy_rpy_measurement[1]) * m_estimator_frequency; + m_stateInterialEstimate_viaFiniteDifference[5] = (m_current_xzy_rpy_measurement[2] - m_previous_xzy_rpy_measurement[2]) * m_estimator_frequency; + } + else + { + // Set the velocities to zero + m_stateInterialEstimate_viaFiniteDifference[3] = 0.0; + m_stateInterialEstimate_viaFiniteDifference[4] = 0.0; + m_stateInterialEstimate_viaFiniteDifference[5] = 0.0; + } } -void performEstimatorUpdate_forStateInterial_viaPointMassKalmanFilter() +void performEstimatorUpdate_forStateInterial_viaPointMassKalmanFilter(bool isFirstUpdate) { // PERFORM THE KALMAN FILTER UPDATE STEP // > First take a copy of the estimator state @@ -883,6 +894,18 @@ void performEstimatorUpdate_forStateInterial_viaPointMassKalmanFilter() { temp_PMKFstate[i] = m_stateInterialEstimate_viaPointMassKalmanFilter[i]; } + // If this is the "first update", then: + if (isFirstUpdate) + { + // Set the positions to the current measurement + temp_PMKFstate[0] = m_current_xzy_rpy_measurement[0]; + temp_PMKFstate[1] = m_current_xzy_rpy_measurement[1]; + temp_PMKFstate[2] = m_current_xzy_rpy_measurement[2]; + // Set the velocities to zero + temp_PMKFstate[3] = 0.0; + temp_PMKFstate[4] = 0.0; + temp_PMKFstate[5] = 0.0; + } // > Now perform update for: // > x position and velocity: m_stateInterialEstimate_viaPointMassKalmanFilter[0] = yaml_PMKF_Ahat_row1_for_positions[0]*temp_PMKFstate[0] + yaml_PMKF_Ahat_row1_for_positions[1]*temp_PMKFstate[3] + yaml_PMKF_Kinf_for_positions[0]*m_current_xzy_rpy_measurement[0]; @@ -1358,6 +1381,8 @@ void setNewSetpoint(float x, float y, float z, float yaw) msg.y = m_setpoint[1]; msg.z = m_setpoint[2]; msg.yaw = m_setpoint[3]; + // Put the current state into the "buttonID" field + msg.buttonID = m_current_state; // Publish the message m_setpointChangedPublisher.publish(msg); } diff --git a/dfall_ws/src/dfall_pkg/src/nodes/FlyingAgentClient.cpp b/dfall_ws/src/dfall_pkg/src/nodes/FlyingAgentClient.cpp index e0613830..63445d1b 100755 --- a/dfall_ws/src/dfall_pkg/src/nodes/FlyingAgentClient.cpp +++ b/dfall_ws/src/dfall_pkg/src/nodes/FlyingAgentClient.cpp @@ -190,6 +190,17 @@ void viconCallback(const ViconData& viconData) { controllerCall.request.otherCrazyflies.push_back(poseDataForOtherAgent); } + + // Fill in the "isFirstControllerCall" field + if (m_isFirstCall_to_instant_controller) + { + controllerCall.request.isFirstControllerCall = true; + m_isFirstCall_to_instant_controller = false; + } + else + { + controllerCall.request.isFirstControllerCall = false; + } // PERFORM THE SAFTY CHECK (IF NOT THE DEFAULT CONTROLLER) @@ -220,6 +231,9 @@ void viconCallback(const ViconData& viconData) { // Set the DEFAULT controller to be active setInstantController(DEFAULT_CONTROLLER); + // Update the "isFirstControllerCall" field + controllerCall.request.isFirstControllerCall = true; + m_isFirstCall_to_instant_controller = false; // Try the controller call isSuccessful_controllerCall = m_instant_controller_service_client->call(controllerCall); // Inform the user is not successful @@ -823,6 +837,11 @@ void setInstantController(int controller) // Update the class variable m_instant_controller = controller; + // Set the class variable indicating that the next + // controller call should be flagged as the first + // call for this instant controller + m_isFirstCall_to_instant_controller = true; + // Point to the correct service client switch(controller) { diff --git a/dfall_ws/src/dfall_pkg/src/nodes/StudentControllerService.cpp b/dfall_ws/src/dfall_pkg/src/nodes/StudentControllerService.cpp index 5a901340..4266a77b 100644 --- a/dfall_ws/src/dfall_pkg/src/nodes/StudentControllerService.cpp +++ b/dfall_ws/src/dfall_pkg/src/nodes/StudentControllerService.cpp @@ -188,10 +188,21 @@ bool calculateControlOutput(Controller::Request &request, Controller::Response & stateErrorInertial[2] = request.ownCrazyflie.z - m_setpoint[2]; // Compute an estimate of the velocity - // > As simply the derivative between the current and previous position - stateErrorInertial[3] = (stateErrorInertial[0] - m_previous_stateErrorInertial[0]) * yaml_control_frequency; - stateErrorInertial[4] = (stateErrorInertial[1] - m_previous_stateErrorInertial[1]) * yaml_control_frequency; - stateErrorInertial[5] = (stateErrorInertial[2] - m_previous_stateErrorInertial[2]) * yaml_control_frequency; + // > But only if this is NOT the first call to the controller + if (!request.isFirstControllerCall) + { + // > Compute as simply the derivative between the current and previous position + stateErrorInertial[3] = (stateErrorInertial[0] - m_previous_stateErrorInertial[0]) * yaml_control_frequency; + stateErrorInertial[4] = (stateErrorInertial[1] - m_previous_stateErrorInertial[1]) * yaml_control_frequency; + stateErrorInertial[5] = (stateErrorInertial[2] - m_previous_stateErrorInertial[2]) * yaml_control_frequency; + } + else + { + // Set the velocities to zero + stateErrorInertial[3] = 0.0; + stateErrorInertial[4] = 0.0; + stateErrorInertial[5] = 0.0; + } // Fill in the roll and pitch angle measurements directly stateErrorInertial[6] = request.ownCrazyflie.roll; diff --git a/dfall_ws/src/dfall_pkg/srv/Controller.srv b/dfall_ws/src/dfall_pkg/srv/Controller.srv index ff3dead3..979abc5c 100644 --- a/dfall_ws/src/dfall_pkg/srv/Controller.srv +++ b/dfall_ws/src/dfall_pkg/srv/Controller.srv @@ -1,3 +1,4 @@ +bool isFirstControllerCall CrazyflieData ownCrazyflie CrazyflieData[] otherCrazyflies --- -- GitLab