diff --git a/dfall_ws/src/dfall_pkg/include/nodes/DefaultControllerConstants.h b/dfall_ws/src/dfall_pkg/include/nodes/DefaultControllerConstants.h index cf6d6cee985dda19defb0fc475f38cdb621070b2..e32c39e22a3328d17fc99d0f31459e8d836a75bd 100644 --- a/dfall_ws/src/dfall_pkg/include/nodes/DefaultControllerConstants.h +++ b/dfall_ws/src/dfall_pkg/include/nodes/DefaultControllerConstants.h @@ -35,7 +35,7 @@ // TO REQUEST MANOEUVRES -#define DEFAULT_CONTROLLER_REQUEST_TAKE_OFF 1 +#define DEFAULT_CONTROLLER_REQUEST_TAKEOFF 1 #define DEFAULT_CONTROLLER_REQUEST_LANDING 2 @@ -45,9 +45,9 @@ #define DEFAULT_CONTROLLER_STATE_STANDBY 99 // > The sequence of states for a TAKE-OFF manoeuvre -#define DEFAULT_CONTROLLER_STATE_TAKE_OFF_SPIN_MOTORS 11 -#define DEFAULT_CONTROLLER_STATE_TAKE_OFF_MOVE_UP 12 -#define DEFAULT_CONTROLLER_STATE_TAKE_OFF_GOTO_SETPOINT 13 +#define DEFAULT_CONTROLLER_STATE_TAKEOFF_SPIN_MOTORS 11 +#define DEFAULT_CONTROLLER_STATE_TAKEOFF_MOVE_UP 12 +#define DEFAULT_CONTROLLER_STATE_TAKEOFF_GOTO_SETPOINT 13 // > The sequence of states for a LANDING manoeuvre #define DEFAULT_CONTROLLER_STATE_LANDING_MOVE_DOWN 21 diff --git a/dfall_ws/src/dfall_pkg/include/nodes/DefaultControllerService.h b/dfall_ws/src/dfall_pkg/include/nodes/DefaultControllerService.h index 12e9add738047345367f8d7027766914fdb1c553..8900c471a72532ecc9012fbfb4fbf0d681e6380a 100644 --- a/dfall_ws/src/dfall_pkg/include/nodes/DefaultControllerService.h +++ b/dfall_ws/src/dfall_pkg/include/nodes/DefaultControllerService.h @@ -102,7 +102,30 @@ using namespace dfall_pkg; // These constants are defined to make the code more readable and adaptable. -// NOTE: manz constants are already defined in the "Constant.h" header file +// NOTE: many constants are already defined in the "Constant.h" header file + +// These constants define the method used for estimating the Inertial +// frame state. +// All methods are run at all times, this flag indicates which estimate +// is passed onto the controller. +// The following is a short description about each mode: +// +// ESTIMATOR_METHOD_FINITE_DIFFERENCE +// Takes the poisition and angles directly as measured, +// and estimates the velocities as a finite different to the +// previous measurement +// +// ESTIMATOR_METHOD_POINT_MASS_PER_DIMENSION +// Uses a 2nd order random walk estimator independently for +// each of (x,y,z,roll,pitch,yaw) +// +// ESTIMATOR_METHOD_QUADROTOR_MODEL_BASED +// Uses the model of the quad-rotor and the previous inputs +// +#define ESTIMATOR_METHOD_FINITE_DIFFERENCE 1 +#define ESTIMATOR_METHOD_POINT_MASS_PER_DIMENSION 2 // (DEFAULT) + + @@ -116,13 +139,62 @@ using namespace dfall_pkg; // V A A R R III A A BBBB LLLLL EEEEE SSSS // ---------------------------------------------------------------------------------- + +// VARIABLES FOR PERFORMING THE TAKE-OFF AND LANDING MANOEUVRES + // The current state of the Default Controller int m_current_state = DEFAULT_CONTROLLER_STATE_STANDBY; +// A flag for when the state is changed, this is used +// so that a "one-off" operation can be performed +// the first time after changing that state +bool m_current_state_changed = false; + // The elapased time, incremented by counting the motion // capture callbacks float m_time_in_seconds = 0.0; +// PARAMETERS FROM THE YAML FILE + +// Max setpoint change per second +float yaml_max_setpoint_change_per_second_horizontal = 0.1; +float yaml_max_setpoint_change_per_second_vertical = 0.1; + +// Max error for yaw angle +float yaml_max_setpoint_error_yaw_degrees = 60.0; +float yaml_max_setpoint_error_yaw_radians = 60.0 * DEG2RAD; + +// The thrust for take off spin motors +float yaml_takeoff_spin_motors_thrust = 8000; +// The time for the take off spin(-up) motors +float takoff_spin_motots_time = 0.8; + +// Height change for the take off move-up +float yaml_takeoff_move_up_start_height = 0.1; +float yaml_takeoff_move_up_end_height = 0.4; +// The time for the take off spin motors +float yaml_takoff_move_up_time = 1.2; + + + +// The setpoint to be tracked, the ordering is (x,y,z,yaw), +// with units [meters,meters,meters,radians] +float m_setpoint[4] = {0.0,0.0,0.4,0.0}; + +// The setpoint that is actually used by the controller, this +// differs from the setpoint when smoothing is turned on +float m_setpoint_for_controller[4] = {0.0,0.0,0.4,0.0}; + +// Boolean for whether to limit rate of change of the setpoint +bool m_shouldSmoothSetpointChanges = true; + + + + + + +// ------------------------------------------------------ +// VARIABLES THAT ARE STANDARD FOR A "CONTROLLER SERVICE" // The ID of the agent that this node is monitoring int m_agentID; @@ -142,15 +214,16 @@ std::string m_namespace_to_coordinator_parameter_service; // VARAIBLES FOR VALUES LOADED FROM THE YAML FILE // > the mass of the crazyflie, in [grams] float yaml_cf_mass_in_grams = 25.0; - -// > the coefficients of the 16-bit command to thrust conversion -//std::vector<float> yaml_motorPoly(3); -std::vector<float> yaml_motorPoly = {5.484560e-4, 1.032633e-6, 2.130295e-11}; +// > the weight of the Crazyflie in Newtons, i.e., mg +float m_cf_weight_in_newtons = 0.0; // > the frequency at which the controller is running float yaml_control_frequency = 200.0; float m_control_deltaT = (1.0/200.0); +// > the coefficients of the 16-bit command to thrust conversion +std::vector<float> yaml_motorPoly = {5.484560e-4, 1.032633e-6, 2.130295e-11}; + // > the min and max for saturating 16 bit thrust commands float yaml_command_sixteenbit_min = 1000; float yaml_command_sixteenbit_max = 65000; @@ -159,25 +232,66 @@ float yaml_command_sixteenbit_max = 65000; // with units [meters,meters,meters,radians] std::vector<float> yaml_default_setpoint = {0.0,0.0,0.4,0.0}; +// Boolean indiciating whether the "Debug Message" of this +// agent should be published or not +bool yaml_shouldPublishDebugMessage = false; +// Boolean indiciating whether the debugging ROS_INFO_STREAM +// should be displayed or not +bool yaml_shouldDisplayDebugInfo = false; -// The weight of the Crazyflie in Newtons, i.e., mg -float m_cf_weight_in_newtons = 0.0; -// The location error of the Crazyflie at the "previous" time step -float m_previous_stateErrorInertial[9]; -// The setpoint to be tracked, the ordering is (x,y,z,yaw), -// with units [meters,meters,meters,radians] -std::vector<float> m_setpoint{0.0,0.0,0.4,0.0}; +// VARIABLES FOR THE CONTROLLER + +// The LQR Controller parameters for "CONTROLLER_MODE_LQR_RATE" +std::vector<float> yaml_gainMatrixThrust_NineStateVector = { 0.00, 0.00, 0.98, 0.00, 0.00, 0.25, 0.00, 0.00, 0.00}; +std::vector<float> yaml_gainMatrixRollRate = { 0.00,-6.20, 0.00, 0.00,-3.00, 0.00, 5.20, 0.00, 0.00}; +std::vector<float> yaml_gainMatrixPitchRate = { 6.20, 0.00, 0.00, 3.00, 0.00, 0.00, 0.00, 5.20, 0.00}; +std::vector<float> yaml_gainMatrixYawRate = { 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 2.30}; + + + +// VARIABLES FOR THE ESTIMATOR + +// Frequency at which the controller is running +float m_estimator_frequency = 200.0; +// > A flag for which estimator to use: +int yaml_estimator_method = ESTIMATOR_METHOD_FINITE_DIFFERENCE; +// > The current state interial estimate, +// for use by the controller +float m_current_stateInertialEstimate[12]; -// The LQR Controller parameters for "LQR_RATE_MODE" -std::vector<float> m_gainMatrixRollRate = { 0.00,-1.71, 0.00, 0.00,-1.33, 0.00, 5.12, 0.00, 0.00}; -std::vector<float> m_gainMatrixPitchRate = { 1.71, 0.00, 0.00, 1.33, 0.00, 0.00, 0.00, 5.12, 0.00}; -std::vector<float> m_gainMatrixYawRate = { 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 2.84}; -std::vector<float> m_gainMatrixThrust = { 0.00, 0.00, 0.19, 0.00, 0.00, 0.08, 0.00, 0.00, 0.00}; +// > The measurement of the Crazyflie at the "current" time step, +// to avoid confusion +float m_current_xzy_rpy_measurement[6]; +// > The measurement of the Crazyflie at the "previous" time step, +// used for computing finite difference velocities +float m_previous_xzy_rpy_measurement[6]; + +// > The full 12 state estimate maintained by the finite +// difference state estimator +float m_stateInterialEstimate_viaFiniteDifference[12]; + +// > The full 12 state estimate maintained by the point mass +// kalman filter state estimator +float m_stateInterialEstimate_viaPointMassKalmanFilter[12]; + +// THE POINT MASS KALMAN FILTER (PMKF) GAINS AND ERROR EVOLUATION +// > For the (x,y,z) position +std::vector<float> yaml_PMKF_Ahat_row1_for_positions = { 0.6723, 0.0034}; +std::vector<float> yaml_PMKF_Ahat_row2_for_positions = {-12.9648, 0.9352}; +std::vector<float> yaml_PMKF_Kinf_for_positions = { 0.3277,12.9648}; +// > For the (roll,pitch,yaw) angles +std::vector<float> yaml_PMKF_Ahat_row1_for_angles = { 0.6954, 0.0035}; +std::vector<float> yaml_PMKF_Ahat_row2_for_angles = {-11.0342, 0.9448}; +std::vector<float> yaml_PMKF_Kinf_for_angles = { 0.3046,11.0342}; + + + +// VARIABLES RELATING TO PUBLISHING // ROS Publisher for debugging variables ros::Publisher m_debugPublisher; @@ -190,6 +304,10 @@ ros::Publisher m_setpointChangedPublisher; + + + + // ---------------------------------------------------------------------------------- // FFFFF U U N N CCCC TTTTT III OOO N N // F U U NN N C T I O O NN N @@ -217,6 +335,20 @@ bool requestManoeuvreCallback(IntIntService::Request &request, IntIntService::Re // CONTROLLER COMPUTATIONS bool calculateControlOutput(Controller::Request &request, Controller::Response &response); +// > This function constructs the error in the body frame +// before calling the appropriate control function +void calculateControlOutput_viaLQR_givenSetpoint(float setpoint[4], float stateInertial[12], Controller::Response &response) +// > The various functions that implement an LQR controller +void calculateControlOutput_viaLQRforRates(float stateErrorBody[12], Controller::Response &response); + +// ESTIMATOR COMPUTATIONS +void performEstimatorUpdate_forStateInterial(Controller::Request &request); +void performEstimatorUpdate_forStateInterial_viaFiniteDifference(); +void performEstimatorUpdate_forStateInterial_viaPointMassKalmanFilter(); + +// PUBLISHING OF THE DEBUG MESSAGE +void construct_and_publish_debug_message(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); diff --git a/dfall_ws/src/dfall_pkg/include/nodes/PickerControllerService.h b/dfall_ws/src/dfall_pkg/include/nodes/PickerControllerService.h index f0d015afeed077db8ff354e12cd72f533ee9642e..37528947f52b3f399bbad44ba047e89070d536cd 100644 --- a/dfall_ws/src/dfall_pkg/include/nodes/PickerControllerService.h +++ b/dfall_ws/src/dfall_pkg/include/nodes/PickerControllerService.h @@ -254,13 +254,13 @@ float m_stateInterialEstimate_viaPointMassKalmanFilter[12]; // THE POINT MASS KALMAN FILTER (PMKF) GAINS AND ERROR EVOLUATION // > For the (x,y,z) position -std::vector<float> yaml_PMKF_Ahat_row1_for_positions (2,0.0); -std::vector<float> yaml_PMKF_Ahat_row2_for_positions (2,0.0); -std::vector<float> yaml_PMKF_Kinf_for_positions (2,0.0); +std::vector<float> yaml_PMKF_Ahat_row1_for_positions = { 0.6723, 0.0034}; +std::vector<float> yaml_PMKF_Ahat_row2_for_positions = {-12.9648, 0.9352}; +std::vector<float> yaml_PMKF_Kinf_for_positions = { 0.3277,12.9648}; // > For the (roll,pitch,yaw) angles -std::vector<float> yaml_PMKF_Ahat_row1_for_angles (2,0.0); -std::vector<float> yaml_PMKF_Ahat_row2_for_angles (2,0.0); -std::vector<float> yaml_PMKF_Kinf_for_angles (2,0.0); +std::vector<float> yaml_PMKF_Ahat_row1_for_angles = { 0.6954, 0.0035}; +std::vector<float> yaml_PMKF_Ahat_row2_for_angles = {-11.0342, 0.9448}; +std::vector<float> yaml_PMKF_Kinf_for_angles = { 0.3046,11.0342}; @@ -285,7 +285,7 @@ ros::Publisher m_debugPublisher; // VARIABLES RELATING TO COMMUNICATING THE SETPOINT // ROS Publisher for inform the network about -// changes to the setpoin +// changes to the setpoint ros::Publisher m_setpointChangedPublisher; diff --git a/dfall_ws/src/dfall_pkg/param/DefaultController.yaml b/dfall_ws/src/dfall_pkg/param/DefaultController.yaml index 3c208ca7a7f77c05e4570bee4e0c62a0eb02ae3b..d64bc24ba812dd14c5bca9150d5f75387247eec8 100644 --- a/dfall_ws/src/dfall_pkg/param/DefaultController.yaml +++ b/dfall_ws/src/dfall_pkg/param/DefaultController.yaml @@ -1,5 +1,30 @@ +# ------------------------------------------------------ +# PARAMTERS FOR THE TAKE-OFF AND LANDING MANOEUVRES + +# Max setpoint change per second +max_setpoint_change_per_second_horizontal : 0.20 # [meters] +max_setpoint_change_per_second_vertical : 0.10 # [meters] + +# Max error for yaw angle +max_setpoint_error_yaw_degrees: 60 + +# The thrust for take off spin motors +takeoff_spin_motors_thrust: 8000 +# The time for the take off spin motors +takoff_spin_motots_time: 0.8 + +# Height change for the take off move-up +takeoff_move_up_start_height: 0.1 +takeoff_move_up_end_height: 0.4 +# The time for the take off spin motors +takoff_move_up_time: 1.2 + + +# ------------------------------------------------------ +# PARAMTERS THAT ARE STANDARD FOR A "CONTROLLER SERVICE" + # The mass of the crazyflie, in [grams] -mass : 28 +mass : 30 # Frequency of the controller, in [hertz] control_frequency : 200 @@ -9,8 +34,48 @@ motorPoly : [5.484560e-4, 1.032633e-6, 2.130295e-11] # The min and max for saturating 16 bit thrust commands command_sixteenbit_min : 1000 -command_sixteenbit_max : 65000 +command_sixteenbit_max : 60000 # The default setpoint, the ordering is (x,y,z,yaw), # with unit [meters,meters,meters,radians] -default_setpoint : [0.0, 0.0, 0.4, 0.0] \ No newline at end of file +default_setpoint : [0.0, 0.0, 0.4, 0.0] + +# 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 + +# The LQR Controller parameters for "mode = 3" +gainMatrixThrust_NineStateVector : [ 0.00, 0.00, 0.98, 0.00, 0.00, 0.25, 0.00, 0.00, 0.00] +gainMatrixRollRate : [ 0.00,-6.20, 0.00, 0.00,-3.00, 0.00, 5.20, 0.00, 0.00] +gainMatrixPitchRate : [ 6.20, 0.00, 0.00, 3.00, 0.00, 0.00, 0.00, 5.20, 0.00] +gainMatrixYawRate : [ 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 2.30] + +# A flag for which estimator to use, defined as: +# 1 - Finite Different Method, +# Takes the poisition and angles directly as measured, +# and estimates the velocities as a finite different to the +# previous measurement +# 2 - Point Mass Per Dimension Method +# Uses a 2nd order random walk estimator independently for +# each of (x,y,z,roll,pitch,yaw) +# 3 - Quad-rotor Model Based Method +# Uses the model of the quad-rotor and the previous inputs +estimator_method : 1 + +# THE POINT MASS KALMAN FILTER (PMKF) GAINS AND ERROR EVOLUATION +# > For the (x,y,z) position +PMKF_Ahat_row1_for_positions : [ 0.6723, 0.0034] +PMKF_Ahat_row2_for_positions : [-12.9648, 0.9352] +PMKF_Kinf_for_positions : [ 0.3277,12.9648] +# > For the (roll,pitch,yaw) angles +PMKF_Ahat_row1_for_angles : [ 0.6954, 0.0035] +PMKF_Ahat_row2_for_angles : [-11.0342, 0.9448] +PMKF_Kinf_for_angles : [ 0.3046,11.0342] + +#PMKF_Ahat_row1_for_angles : [ 0.6723, 0.0034] +#PMKF_Ahat_row2_for_angles : [-12.9648, 0.9352] +#PMKF_Kinf_for_angles : [ 0.3277,12.9648] + + diff --git a/dfall_ws/src/dfall_pkg/src/nodes/DefaultControllerService.cpp b/dfall_ws/src/dfall_pkg/src/nodes/DefaultControllerService.cpp index be6ec8343035316885513735508c3ffb611e9b89..96711b818b4a02c5158931d0396cfef43ac7909b 100644 --- a/dfall_ws/src/dfall_pkg/src/nodes/DefaultControllerService.cpp +++ b/dfall_ws/src/dfall_pkg/src/nodes/DefaultControllerService.cpp @@ -90,6 +90,7 @@ bool requestManoeuvreCallback(IntIntService::Request &request, IntIntService::Re m_time_in_seconds = 0.0; // Update the state accordingly m_current_state = DEFAULT_CONTROLLER_STATE_TAKE_OFF_SPIN_MOTORS; + m_current_state_changed = true; // Fill in the response duration in milliseconds response.data = 3000; break; @@ -103,6 +104,7 @@ bool requestManoeuvreCallback(IntIntService::Request &request, IntIntService::Re m_time_in_seconds = 0.0; // Update the state accordingly m_current_state = DEFAULT_CONTROLLER_STATE_LANDING_MOVE_DOWN; + m_current_state_changed = true; // Fill in the response duration in milliseconds response.data = 2000; break; @@ -114,6 +116,7 @@ bool requestManoeuvreCallback(IntIntService::Request &request, IntIntService::Re ROS_INFO("[DEFAULT CONTROLLER] The requested manoeuvre is not recognised. Hence switching to stand-by state."); // Update the state to standby m_current_state = DEFAULT_CONTROLLER_STATE_STANDBY; + m_current_state_changed = true; // Fill in the response duration in milliseconds response.data = 0; break; @@ -162,185 +165,452 @@ bool calculateControlOutput(Controller::Request &request, Controller::Response & m_time_in_seconds += m_control_deltaT; - // Define a local array to fill in with the state error - float stateErrorInertial[9]; + // PERFORM THE ESTIMATOR UPDATE FOR THE INTERIAL FRAME STATE + // > After this function is complete the class variable + // "m_current_stateInertialEstimate" is updated and ready + // to be used for subsequent controller copmutations + performEstimatorUpdate_forStateInterial(request); - // Fill in the (x,y,z) position error - stateErrorInertial[0] = request.ownCrazyflie.x - m_setpoint[0]; - stateErrorInertial[1] = request.ownCrazyflie.y - m_setpoint[1]; - 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; + // Switch between the possible states + switch (m_current_state) + { + case DEFAULT_CONTROLLER_STATE_TAKE_OFF_SPIN_MOTORS: + computeResponse_for_takeoff_spin_motors(response); + break; - // Fill in the roll and pitch angle measurements directly - stateErrorInertial[6] = request.ownCrazyflie.roll; - stateErrorInertial[7] = request.ownCrazyflie.pitch; + case DEFAULT_CONTROLLER_STATE_TAKEOFF_MOVE_UP: + computeResponse_for_takeoff_move_up(response); + break; - // 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 - m_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 classroom exercise - float stateErrorBody[9]; - convertIntoBodyFrame(stateErrorInertial, stateErrorBody, request.ownCrazyflie.yaw); + // CARRY OUT THE CONTROLLER COMPUTATIONS + // Call the function that performs the control computations for this mode + calculateControlOutput_viaLQRforRates(current_bodyFrameError,request,response); - // 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) + // PUBLISH THE DEBUG MESSAGE (if required) + if (yaml_shouldPublishDebugMessage) { - m_previous_stateErrorInertial[i] = stateErrorInertial[i]; + construct_and_publish_debug_message(request,response); } + // Return "true" to indicate that the control computation was performed successfully + return true; +} - if (m_current_state == DEFAULT_CONTROLLER_STATE_TAKE_OFF_SPIN_MOTORS) + + +void computeResponse_for_takeoff_spin_motors(Controller::Response &response) +{ + // Check if the state "just recently" changed + if (m_current_state_changed) { - // Compute the "spinning" thrust - float thrust_for_spinning = 1000.0; - if (m_time_in_seconds < 0.8) - thrust_for_spinning += m_time_in_seconds * 10000.0; - else - thrust_for_spinning += 8000.0; - - response.controlOutput.roll = 0.0; - response.controlOutput.pitch = 0.0; - response.controlOutput.yaw = 0.0; - response.controlOutput.motorCmd1 = thrust_for_spinning; - response.controlOutput.motorCmd2 = thrust_for_spinning; - response.controlOutput.motorCmd3 = thrust_for_spinning; - response.controlOutput.motorCmd4 = thrust_for_spinning; - response.controlOutput.onboardControllerType = CF_COMMAND_TYPE_MOTORS; + // PERFORM "ONE-OFF" OPERATIONS HERE + // Nothing to perform for this state + // Set the change flag back to false + m_current_state_changed = false; } + + // Compute the "spinning" thrust + float thrust_for_spinning = 1000.0; + if (m_time_in_seconds < takoff_spin_motots_time) + thrust_for_spinning += yaml_takeoff_spin_motors_thrust * (m_time_in_seconds/takoff_spin_motots_time); else + thrust_for_spinning += yaml_takeoff_spin_motors_thrust; + + // Fill in zero for the angle parts + response.controlOutput.roll = 0.0; + response.controlOutput.pitch = 0.0; + response.controlOutput.yaw = 0.0; + + // Fill in all motor thrusts as the same + response.controlOutput.motorCmd1 = thrust_for_spinning; + response.controlOutput.motorCmd2 = thrust_for_spinning; + response.controlOutput.motorCmd3 = thrust_for_spinning; + response.controlOutput.motorCmd4 = thrust_for_spinning; + + // Specify that using a "motor type" of command + response.controlOutput.onboardControllerType = CF_COMMAND_TYPE_MOTORS; + + // Change to next state after specified time + if (m_time_in_seconds > takoff_spin_motots_time) { + // Inform the user + ROS_INFO("[DEFAULT CONTROLLER] Switch to state: take-off move up"); + // Reset the time variable + m_time_in_seconds = 0.0; + // Update the state accordingly + m_current_state = DEFAULT_CONTROLLER_STATE_TAKEOFF_MOVE_UP; + m_current_state_changed = true; + } +} - - // YAW CONTROLLER - // Perform the "-Kx" LQR computation for the yaw rate - // to respond with - float yawRate_forResponse = 0; - for(int i = 0; i < 9; ++i) - { - yawRate_forResponse -= m_gainMatrixYawRate[i] * stateErrorBody[i]; - } - // Put the computed yaw rate into the "response" variable - response.controlOutput.yaw = yawRate_forResponse; +void computeResponse_for_takeoff_move_up(Controller::Response &response) +{ + // Initialise a static variable for the starting height and yaw + static float initial_height = 0.0; + static float initial_yaw = 0.0; + // Initialise a static variable for the yaw change + static float yaw_start_to_end_diff = 0.0; + + // Check if the state "just recently" changed + if (m_current_state_changed) + { + // PERFORM "ONE-OFF" OPERATIONS HERE + // Set the current (x,y) location as the setpoint + m_setpoint_for_controller[0] = m_current_stateInertialEstimate[0]; + m_setpoint_for_controller[1] = m_current_stateInertialEstimate[1]; + // Store the current (z,yaw) + initial_height = m_current_stateInertialEstimate[2]; + initial_yaw = m_current_stateInertialEstimate[8]; + // Compute the yaw "start-to-end-difference" unwrapped + yaw_start_to_end_diff = m_setpoint[3] - initial_yaw; + while(yaw_start_to_end_diff > PI) {yaw_start_to_end_diff -= 2 * PI;} + while(yaw_start_to_end_diff < -PI) {yaw_start_to_end_diff += 2 * PI;} + // Set the change flag back to false + m_current_state_changed = false; + } + // Compute the time elapsed as a proportion + float time_elapsed_proportion = m_time_in_seconds / (0.8*yaml_takoff_move_up_time); + if (time_elapsed_proportion > 1.0) + time_elapsed_proportion = 1.0; + // Compute the z-height setpoint + m_setpoint_for_controller[2] = initial_height + yaml_takeoff_move_up_start_height + time_elapsed_proportion * (yaml_takeoff_move_up_end_height-yaml_takeoff_move_up_start_height); + // Compute the yaw-setpoint + m_setpoint_for_controller[3] = initial_yaw + time_elapsed_proportion * yaw_start_to_end_diff; - // ALITUDE CONTROLLER (i.e., z-controller) - - // Perform the "-Kx" LQR computation for the thrust adjustment - // to use for computing the response with - float thrustAdjustment = 0; - for(int i = 0; i < 9; ++i) - { - thrustAdjustment -= m_gainMatrixThrust[i] * stateErrorBody[i]; - } + // Call the LQR control function + calculateControlOutput_viaLQR_givenSetpoint(m_setpoint_for_controller, m_current_stateInertialEstimate, response) - // Add the feed-forward thrust before putting in the response - float feed_forward_thrust_per_motor = m_cf_weight_in_newtons / 4.0; - float thrust_per_motor = thrustAdjustment + feed_forward_thrust_per_motor; +} - // > NOTE: the function "computeMotorPolyBackward" converts the - // input argument from Newtons to the 16-bit command - // expected by the Crazyflie. - response.controlOutput.motorCmd1 = computeMotorPolyBackward(thrust_per_motor); - response.controlOutput.motorCmd2 = computeMotorPolyBackward(thrust_per_motor); - response.controlOutput.motorCmd3 = computeMotorPolyBackward(thrust_per_motor); - response.controlOutput.motorCmd4 = computeMotorPolyBackward(thrust_per_motor); - - // BODY FRAME X CONTROLLER - // Perform the "-Kx" LQR computation for the pitch rate - // to respoond with - float pitchRate_forResponse = 0; - for(int i = 0; i < 9; ++i) - { - pitchRate_forResponse -= m_gainMatrixPitchRate[i] * stateErrorBody[i]; - } - // Put the computed pitch rate into the "response" variable - response.controlOutput.pitch = pitchRate_forResponse; - // 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 - - // Perform the "-Kx" LQR computation for the roll rate - // to respoond with - float rollRate_forResponse = 0; - for(int i = 0; i < 9; ++i) + + + +// ------------------------------------------------------------------------------ +// EEEEE SSSS TTTTT III M M A TTTTT III OOO N N +// E S T I MM MM A A T I O O NN N +// EEE SSS T I M M M A A T I O O N N N +// E S T I M M AAAAA T I O O N NN +// EEEEE SSSS T III M M A A T III OOO N N +// ------------------------------------------------------------------------------ +void performEstimatorUpdate_forStateInterial(Controller::Request &request) +{ + + // PUT THE CURRENT MEASURED DATA INTO THE CLASS VARIABLE + // > for (x,y,z) position + m_current_xzy_rpy_measurement[0] = request.ownCrazyflie.x; + m_current_xzy_rpy_measurement[1] = request.ownCrazyflie.y; + m_current_xzy_rpy_measurement[2] = request.ownCrazyflie.z; + // > for (roll,pitch,yaw) angles + m_current_xzy_rpy_measurement[3] = request.ownCrazyflie.roll; + m_current_xzy_rpy_measurement[4] = request.ownCrazyflie.pitch; + m_current_xzy_rpy_measurement[5] = request.ownCrazyflie.yaw; + + + // RUN THE FINITE DIFFERENCE ESTIMATOR + performEstimatorUpdate_forStateInterial_viaFiniteDifference(); + + + // RUN THE POINT MASS KALMAN FILTER ESTIMATOR + performEstimatorUpdate_forStateInterial_viaPointMassKalmanFilter(); + + + // FILLE IN THE STATE INERTIAL ESTIMATE TO BE USED FOR CONTROL + switch (yaml_estimator_method) + { + // Estimator based on finte differences + case ESTIMATOR_METHOD_FINITE_DIFFERENCE: { - rollRate_forResponse -= m_gainMatrixRollRate[i] * stateErrorBody[i]; + // Transfer the estimate + for(int i = 0; i < 12; ++i) + { + m_current_stateInertialEstimate[i] = m_stateInterialEstimate_viaFiniteDifference[i]; + } + break; + } + // Estimator based on Point Mass Kalman Filter + case ESTIMATOR_METHOD_POINT_MASS_PER_DIMENSION: + { + // Transfer the estimate + for(int i = 0; i < 12; ++i) + { + m_current_stateInertialEstimate[i] = m_stateInterialEstimate_viaPointMassKalmanFilter[i]; + } + break; + } + // Handle the exception + default: + { + // Display that the "yaml_estimator_method" was not recognised + ROS_INFO_STREAM("[PICKER CONTROLLER] ERROR: in the 'calculateControlOutput' function of the 'PickerControllerService': the 'yaml_estimator_method' is not recognised."); + // Transfer the finite difference estimate by default + for(int i = 0; i < 12; ++i) + { + m_current_stateInertialEstimate[i] = m_stateInterialEstimate_viaFiniteDifference[i]; + } + break; } - // 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 = CF_COMMAND_TYPE_MOTORS; - response.controlOutput.onboardControllerType = CF_COMMAND_TYPE_RATE; - // response.controlOutput.onboardControllerType = CF_COMMAND_TYPE_ANGLE; } + // NOW THAT THE ESTIMATORS HAVE ALL BEEN RUN, PUT THE CURRENT + // MEASURED DATA INTO THE CLASS VARIABLE FOR THE PREVIOUS + // > for (x,y,z) position + m_previous_xzy_rpy_measurement[0] = m_current_xzy_rpy_measurement[0]; + m_previous_xzy_rpy_measurement[1] = m_current_xzy_rpy_measurement[1]; + m_previous_xzy_rpy_measurement[2] = m_current_xzy_rpy_measurement[2]; + // > for (roll,pitch,yaw) angles + m_previous_xzy_rpy_measurement[3] = m_current_xzy_rpy_measurement[3]; + m_previous_xzy_rpy_measurement[4] = m_current_xzy_rpy_measurement[4]; + m_previous_xzy_rpy_measurement[5] = m_current_xzy_rpy_measurement[5]; +} + + +void performEstimatorUpdate_forStateInterial_viaFiniteDifference() +{ + // PUT IN THE CURRENT MEASUREMENT DIRECTLY + // > for (x,y,z) position + m_stateInterialEstimate_viaFiniteDifference[0] = m_current_xzy_rpy_measurement[0]; + m_stateInterialEstimate_viaFiniteDifference[1] = m_current_xzy_rpy_measurement[1]; + m_stateInterialEstimate_viaFiniteDifference[2] = m_current_xzy_rpy_measurement[2]; + // > for (roll,pitch,yaw) angles + m_stateInterialEstimate_viaFiniteDifference[6] = m_current_xzy_rpy_measurement[3]; + m_stateInterialEstimate_viaFiniteDifference[7] = m_current_xzy_rpy_measurement[4]; + 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; + // > for (roll,pitch,yaw) velocities + m_stateInterialEstimate_viaFiniteDifference[9] = (m_current_xzy_rpy_measurement[3] - m_previous_xzy_rpy_measurement[3]) * m_estimator_frequency; + m_stateInterialEstimate_viaFiniteDifference[10] = (m_current_xzy_rpy_measurement[4] - m_previous_xzy_rpy_measurement[4]) * m_estimator_frequency; + m_stateInterialEstimate_viaFiniteDifference[11] = (m_current_xzy_rpy_measurement[5] - m_previous_xzy_rpy_measurement[5]) * m_estimator_frequency; +} - // *********************************************************** - // 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 +void performEstimatorUpdate_forStateInterial_viaPointMassKalmanFilter() +{ + // PERFORM THE KALMAN FILTER UPDATE STEP + // > First take a copy of the estimator state + float temp_PMKFstate[12]; + for(int i = 0; i < 12; ++i) + { + temp_PMKFstate[i] = m_stateInterialEstimate_viaPointMassKalmanFilter[i]; + } + // > 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]; + m_stateInterialEstimate_viaPointMassKalmanFilter[3] = yaml_PMKF_Ahat_row2_for_positions[0]*temp_PMKFstate[0] + yaml_PMKF_Ahat_row2_for_positions[1]*temp_PMKFstate[3] + yaml_PMKF_Kinf_for_positions[1]*m_current_xzy_rpy_measurement[0]; + // > y position and velocity: + m_stateInterialEstimate_viaPointMassKalmanFilter[1] = yaml_PMKF_Ahat_row1_for_positions[0]*temp_PMKFstate[1] + yaml_PMKF_Ahat_row1_for_positions[1]*temp_PMKFstate[4] + yaml_PMKF_Kinf_for_positions[0]*m_current_xzy_rpy_measurement[1]; + m_stateInterialEstimate_viaPointMassKalmanFilter[4] = yaml_PMKF_Ahat_row2_for_positions[0]*temp_PMKFstate[1] + yaml_PMKF_Ahat_row2_for_positions[1]*temp_PMKFstate[4] + yaml_PMKF_Kinf_for_positions[1]*m_current_xzy_rpy_measurement[1]; + // > z position and velocity: + m_stateInterialEstimate_viaPointMassKalmanFilter[2] = yaml_PMKF_Ahat_row1_for_positions[0]*temp_PMKFstate[2] + yaml_PMKF_Ahat_row1_for_positions[1]*temp_PMKFstate[5] + yaml_PMKF_Kinf_for_positions[0]*m_current_xzy_rpy_measurement[2]; + m_stateInterialEstimate_viaPointMassKalmanFilter[5] = yaml_PMKF_Ahat_row2_for_positions[0]*temp_PMKFstate[2] + yaml_PMKF_Ahat_row2_for_positions[1]*temp_PMKFstate[5] + yaml_PMKF_Kinf_for_positions[1]*m_current_xzy_rpy_measurement[2]; + + // > roll position and velocity: + m_stateInterialEstimate_viaPointMassKalmanFilter[6] = yaml_PMKF_Ahat_row1_for_angles[0]*temp_PMKFstate[6] + yaml_PMKF_Ahat_row1_for_angles[1]*temp_PMKFstate[9] + yaml_PMKF_Kinf_for_angles[0]*m_current_xzy_rpy_measurement[3]; + m_stateInterialEstimate_viaPointMassKalmanFilter[9] = yaml_PMKF_Ahat_row2_for_angles[0]*temp_PMKFstate[6] + yaml_PMKF_Ahat_row2_for_angles[1]*temp_PMKFstate[9] + yaml_PMKF_Kinf_for_angles[1]*m_current_xzy_rpy_measurement[3]; + // > pitch position and velocity: + m_stateInterialEstimate_viaPointMassKalmanFilter[7] = yaml_PMKF_Ahat_row1_for_angles[0]*temp_PMKFstate[7] + yaml_PMKF_Ahat_row1_for_angles[1]*temp_PMKFstate[10] + yaml_PMKF_Kinf_for_angles[0]*m_current_xzy_rpy_measurement[4]; + m_stateInterialEstimate_viaPointMassKalmanFilter[10] = yaml_PMKF_Ahat_row2_for_angles[0]*temp_PMKFstate[7] + yaml_PMKF_Ahat_row2_for_angles[1]*temp_PMKFstate[10] + yaml_PMKF_Kinf_for_angles[1]*m_current_xzy_rpy_measurement[4]; + // > yaw position and velocity: + m_stateInterialEstimate_viaPointMassKalmanFilter[8] = yaml_PMKF_Ahat_row1_for_angles[0]*temp_PMKFstate[8] + yaml_PMKF_Ahat_row1_for_angles[1]*temp_PMKFstate[11] + yaml_PMKF_Kinf_for_angles[0]*m_current_xzy_rpy_measurement[5]; + m_stateInterialEstimate_viaPointMassKalmanFilter[11] = yaml_PMKF_Ahat_row2_for_angles[0]*temp_PMKFstate[8] + yaml_PMKF_Ahat_row2_for_angles[1]*temp_PMKFstate[11] + yaml_PMKF_Kinf_for_angles[1]*m_current_xzy_rpy_measurement[5]; +} + + + + + +// ---------------------------------------------------------------------------------- +// L QQQ RRRR +// L Q Q R R +// L Q Q RRRR +// L Q Q R R +// LLLLL QQ Q R R +// ---------------------------------------------------------------------------------- + +// > This function constructs the error in the body frame +// before calling the appropriate control function +void calculateControlOutput_viaLQR_givenSetpoint(float setpoint[4], float stateInertial[12], Controller::Response &response) +{ + // Store the current YAW in a local variable + float temp_stateInertial_yaw = stateInertial[8]; + + // Adjust the INERTIAL (x,y,z) position for the setpoint + stateInertial[0] = stateInertial[0] - setpoint[0]; + stateInertial[1] = stateInertial[1] - setpoint[1]; + stateInertial[2] = stateInertial[2] - setpoint[2]; + + // Clip the z-coordination to within the specified bounds + if (stateInertial[2] > 0.40f) + { + stateInertial[2] = 0.40f; + } + else if (stateInertial[2] < -0.40f) + { + stateInertial[2] = -0.40f; + } + + // Fill in the yaw angle error + // > This error should be "unwrapped" to be in the range + // ( -pi , pi ) + // > Det the yaw error into a local variable + float yawError = stateInertial[8] - setpoint[3]; + // > "Unwrap" the yaw error to the interval ( -pi , pi ) + while(yawError > PI) {yawError -= 2 * PI;} + while(yawError < -PI) {yawError += 2 * PI;} + // Clip the error to within the specified bounds + if (yawError>(PI/3)) + { + yawError = (PI/3); + } + else if (yawError<(-PI/3)) + { + yawError = (-PI/3); + } + // > Finally, put the "yawError" into the "stateError" variable + stateInertial[8] = yawError; + + // CONVERSION INTO BODY FRAME + // Convert the state erorr from the Inertial frame into the Body frame + convertIntoBodyFrame(stateInertial, bodyFrameError, temp_stateInertial_yaw); + + calculateControlOutput_viaLQRforRates(bodyFrameError, response); +} + +void calculateControlOutput_viaLQRforRates(float stateErrorBody[12], Controller::Response &response) +{ + // PERFORM THE "u=Kx" LQR CONTROLLER COMPUTATION + + // Instantiate the local variables for the following: + // > body frame roll rate, + // > body frame pitch rate, + // > body frame yaw rate, + // > total thrust adjustment. + // These will be requested from the Crazyflie's on-baord "inner-loop" controller + float rollRate_forResponse = 0; + float pitchRate_forResponse = 0; + float yawRate_forResponse = 0; + float thrustAdjustment = 0; + + // Perform the "-Kx" LQR computation for the rates and thrust: + for(int i = 0; i < 9; ++i) + { + // BODY FRAME Y CONTROLLER + rollRate_forResponse -= yaml_gainMatrixRollRate[i] * stateErrorBody[i]; + // BODY FRAME X CONTROLLER + pitchRate_forResponse -= yaml_gainMatrixPitchRate[i] * stateErrorBody[i]; + // BODY FRAME YAW CONTROLLER + yawRate_forResponse -= yaml_gainMatrixYawRate[i] * stateErrorBody[i]; + // > ALITUDE CONTROLLER (i.e., z-controller): + thrustAdjustment -= yaml_gainMatrixThrust_NineStateVector[i] * stateErrorBody[i]; + } + + + // UPDATE THE "RETURN" THE VARIABLE NAMED "response" + + // Put the computed rates and thrust into the "response" variable + // > For roll, pitch, and yaw: + response.controlOutput.roll = rollRate_forResponse; + response.controlOutput.pitch = pitchRate_forResponse; + response.controlOutput.yaw = yawRate_forResponse; + // > For the thrust adjustment we must add the feed-forward thrust to counter-act gravity. + // > NOTE: remember that the thrust is commanded per motor, so you sohuld + // consider whether the "thrustAdjustment" computed by your + // controller needed to be divided by 4 or not. + thrustAdjustment = thrustAdjustment / 4.0; + // > Compute the feed-forward force + float feed_forward_thrust_per_motor = m_cf_weight_in_newtons / 4.0; + // > Put in the per motor commands + response.controlOutput.motorCmd1 = computeMotorPolyBackward(thrustAdjustment + feed_forward_thrust_per_motor); + response.controlOutput.motorCmd2 = computeMotorPolyBackward(thrustAdjustment + feed_forward_thrust_per_motor); + response.controlOutput.motorCmd3 = computeMotorPolyBackward(thrustAdjustment + feed_forward_thrust_per_motor); + response.controlOutput.motorCmd4 = computeMotorPolyBackward(thrustAdjustment + feed_forward_thrust_per_motor); + + + // Specify that this controller is a rate controller + // response.controlOutput.onboardControllerType = CF_COMMAND_TYPE_MOTOR; + response.controlOutput.onboardControllerType = CF_COMMAND_TYPE_RATE; + // response.controlOutput.onboardControllerType = CF_COMMAND_TYPE_ANGLE; + + + // An alternate debugging technique is to print out data directly to the + // command line from which this node was launched. + if (yaml_shouldDisplayDebugInfo) + { + // 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:" << yaml_motorPoly[0]); + ROS_INFO_STREAM("motorPoly 1:" << yaml_motorPoly[1]); + ROS_INFO_STREAM("motorPoly 2:" << yaml_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); + } +} + + + +// *********************************************************** +// 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 + +void construct_and_publish_debug_message(Controller::Request &request, Controller::Response &response) +{ + + // DEBUGGING CODE: + // As part of the D-FaLL-System we have defined a message type names"DebugMsg". + // By fill this message with data and publishing it you can display the data in + // real time using rpt plots. Instructions for using rqt plots can be found on + // the wiki of the D-FaLL-System repository + // Instantiate a local variable of type "DebugMsg", see the file "DebugMsg.msg" // (located in the "msg" folder) to see the full structure of this message. DebugMsg debugMsg; // Fill the debugging message with the data provided by Vicon - debugMsg.vicon_x = request.ownCrazyflie.x; - debugMsg.vicon_y = request.ownCrazyflie.y; - debugMsg.vicon_z = request.ownCrazyflie.z; - debugMsg.vicon_roll = request.ownCrazyflie.roll; - debugMsg.vicon_pitch = request.ownCrazyflie.pitch; - debugMsg.vicon_yaw = request.ownCrazyflie.yaw; + 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 @@ -354,40 +624,8 @@ bool calculateControlOutput(Controller::Request &request, Controller::Response & // Publish the "debugMsg" m_debugPublisher.publish(debugMsg); +} - // An alternate debugging technique is to print out data directly to the - // command line from which this node was launched. - - // An example of "printing out" the data from the "request" argument to the - // command line. This might be useful for debugging. - // ROS_INFO_STREAM("x-coordinates: " << request.ownCrazyflie.x); - // ROS_INFO_STREAM("y-coordinates: " << request.ownCrazyflie.y); - // ROS_INFO_STREAM("z-coordinates: " << request.ownCrazyflie.z); - // ROS_INFO_STREAM("roll: " << request.ownCrazyflie.roll); - // ROS_INFO_STREAM("pitch: " << request.ownCrazyflie.pitch); - // ROS_INFO_STREAM("yaw: " << request.ownCrazyflie.yaw); - // ROS_INFO_STREAM("Delta t: " << request.ownCrazyflie.acquiringTime); - - // An example of "printing out" the control actions computed. - // ROS_INFO_STREAM("thrustAdjustment = " << thrustAdjustment); - // ROS_INFO_STREAM("controlOutput.roll = " << response.controlOutput.roll); - // ROS_INFO_STREAM("controlOutput.pitch = " << response.controlOutput.pitch); - // ROS_INFO_STREAM("controlOutput.yaw = " << response.controlOutput.yaw); - - // An example of "printing out" the "thrust-to-command" conversion parameters. - // ROS_INFO_STREAM("motorPoly 0:" << yaml_motorPoly[0]); - // ROS_INFO_STREAM("motorPoly 1:" << yaml_motorPoly[1]); - // ROS_INFO_STREAM("motorPoly 2:" << yaml_motorPoly[2]); - - // An example of "printing out" the per motor 16-bit command computed. - // ROS_INFO_STREAM("controlOutput.cmd1 = " << response.controlOutput.motorCmd1); - // ROS_INFO_STREAM("controlOutput.cmd3 = " << response.controlOutput.motorCmd2); - // ROS_INFO_STREAM("controlOutput.cmd2 = " << response.controlOutput.motorCmd3); - // ROS_INFO_STREAM("controlOutput.cmd4 = " << response.controlOutput.motorCmd4); - - // Return "true" to indicate that the control computation was performed successfully - return true; - } @@ -732,6 +970,31 @@ void fetchDefaultControllerYamlParameters(ros::NodeHandle& nodeHandle) // GET THE PARAMETERS: + // ------------------------------------------------------ + // PARAMTERS FOR THE TAKE-OFF AND LANDING MANOEUVRES + + // Max setpoint change per second + yaml_max_setpoint_change_per_second_horizontal = getParameterFloat(nodeHandle_for_paramaters , "max_setpoint_change_per_second_horizontal"); + yaml_max_setpoint_change_per_second_vertical = getParameterFloat(nodeHandle_for_paramaters , "max_setpoint_change_per_second_vertical"); + + // Max error for yaw angle + yaml_max_setpoint_error_yaw_degrees = getParameterFloat(nodeHandle_for_paramaters , "max_setpoint_error_yaw_degrees"); + + // The thrust for take off spin motors + yaml_takeoff_spin_motors_thrust = getParameterFloat(nodeHandle_for_paramaters , "takeoff_spin_motors_thrust"); + // The time for the take off spin(-up) motors + yaml_takoff_spin_motots_time = getParameterFloat(nodeHandle_for_paramaters , "takoff_spin_motots_time"); + + // Height change for the take off move-up + yaml_takeoff_move_up_height = getParameterFloat(nodeHandle_for_paramaters , "takeoff_move_up_height"); + // The time for the take off spin motors + yaml_takoff_move_up_time = getParameterFloat(nodeHandle_for_paramaters , "takoff_move_up_time"); + + + + // ------------------------------------------------------ + // PARAMTERS THAT ARE STANDARD FOR A "CONTROLLER SERVICE" + // The mass of the crazyflie, in [grams] yaml_cf_mass_in_grams = getParameterFloat(nodeHandle_for_paramaters , "mass"); @@ -753,6 +1016,32 @@ void fetchDefaultControllerYamlParameters(ros::NodeHandle& nodeHandle) // with unit [meters,meters,meters,radians] getParameterFloatVector(nodeHandle_for_paramaters, "default_setpoint", yaml_default_setpoint, 4); + // Boolean indiciating whether the "Debug Message" of this agent should be published or not + yaml_shouldPublishDebugMessage = getParameterBool(nodeHandle_for_paramaters, "shouldPublishDebugMessage"); + + // Boolean indiciating whether the debugging ROS_INFO_STREAM should be displayed or not + yaml_shouldDisplayDebugInfo = getParameterBool(nodeHandle_for_paramaters, "shouldDisplayDebugInfo"); + + // The LQR Controller parameters for "LQR_MODE_RATE" + getParameterFloatVector(nodeHandle_for_paramaters, "gainMatrixThrust_NineStateVector", yaml_gainMatrixThrust_NineStateVector, 9); + getParameterFloatVector(nodeHandle_for_paramaters, "gainMatrixRollRate", yaml_gainMatrixRollRate, 9); + getParameterFloatVector(nodeHandle_for_paramaters, "gainMatrixPitchRate", yaml_gainMatrixPitchRate, 9); + getParameterFloatVector(nodeHandle_for_paramaters, "gainMatrixYawRate", yaml_gainMatrixYawRate, 9); + + // A flag for which estimator to use: + yaml_estimator_method = getParameterInt( nodeHandle_for_paramaters , "estimator_method" ); + + // THE POINT MASS KALMAN FILTER (PMKF) GAINS AND ERROR EVOLUATION + // > For the (x,y,z) position + getParameterFloatVector(nodeHandle_for_paramaters, "PMKF_Ahat_row1_for_positions", yaml_PMKF_Ahat_row1_for_positions, 2); + getParameterFloatVector(nodeHandle_for_paramaters, "PMKF_Ahat_row2_for_positions", yaml_PMKF_Ahat_row2_for_positions, 2); + getParameterFloatVector(nodeHandle_for_paramaters, "PMKF_Kinf_for_positions" , yaml_PMKF_Kinf_for_positions , 2); + // > For the (roll,pitch,yaw) angles + getParameterFloatVector(nodeHandle_for_paramaters, "PMKF_Ahat_row1_for_angles", yaml_PMKF_Ahat_row1_for_angles, 2); + getParameterFloatVector(nodeHandle_for_paramaters, "PMKF_Ahat_row2_for_angles", yaml_PMKF_Ahat_row2_for_angles, 2); + getParameterFloatVector(nodeHandle_for_paramaters, "PMKF_Kinf_for_angles" , yaml_PMKF_Kinf_for_angles , 2); + + // > DEBUGGING: Print out one of the parameters that was loaded to