diff --git a/src/modules/interface/attitude_controller.h b/src/modules/interface/attitude_controller.h index fe25dc0..fd69bdc 100644 --- a/src/modules/interface/attitude_controller.h +++ b/src/modules/interface/attitude_controller.h @@ -63,6 +63,11 @@ void attitudeControllerResetRollAttitudePID(void); */ void attitudeControllerResetPitchAttitudePID(void); +/** + * Reset controller yaw attitude PID + */ +void attitudeControllerResetYawAttitudePID(void); + /** * Reset controller roll, pitch and yaw PID's. */ diff --git a/src/modules/interface/stabilizer_types.h b/src/modules/interface/stabilizer_types.h index fc3e378..272cc88 100644 --- a/src/modules/interface/stabilizer_types.h +++ b/src/modules/interface/stabilizer_types.h @@ -159,6 +159,10 @@ typedef struct control_s { int16_t pitch; int16_t yaw; float thrust; + uint16_t cmd1; + uint16_t cmd2; + uint16_t cmd3; + uint16_t cmd4; } control_t; typedef enum mode_e { @@ -167,6 +171,13 @@ typedef enum mode_e { modeVelocity } stab_mode_t; +typedef enum dfall_mode_e { + modeDfallDisable = 0, + modeDfallMotors, + modeDfallRate, + modeDfallAngle, +} dfall_mode_t; + typedef struct setpoint_s { uint32_t timestamp; @@ -174,6 +185,11 @@ typedef struct setpoint_s { attitude_t attitudeRate; // deg/s quaternion_t attitudeQuaternion; float thrust; + dfall_mode_t dfall_mode; + uint16_t cmd1; + uint16_t cmd2; + uint16_t cmd3; + uint16_t cmd4; point_t position; // m velocity_t velocity; // m/s acc_t acceleration; // m/s^2 diff --git a/src/modules/src/attitude_pid_controller.c b/src/modules/src/attitude_pid_controller.c index b7d707e..bcb02bc 100644 --- a/src/modules/src/attitude_pid_controller.c +++ b/src/modules/src/attitude_pid_controller.c @@ -145,6 +145,11 @@ void attitudeControllerResetPitchAttitudePID(void) pidReset(&pidPitch); } +void attitudeControllerResetYawAttitudePID(void) +{ + pidReset(&pidYaw); +} + void attitudeControllerResetAllPID(void) { pidReset(&pidRoll); diff --git a/src/modules/src/controller_pid.c b/src/modules/src/controller_pid.c index f4ecb75..4a9047c 100644 --- a/src/modules/src/controller_pid.c +++ b/src/modules/src/controller_pid.c @@ -74,7 +74,13 @@ void controllerPid(control_t *control, setpoint_t *setpoint, } if (RATE_DO_EXECUTE(POSITION_RATE, tick)) { - positionController(&actuatorThrust, &attitudeDesired, setpoint, state); + // Check if the "dfall_mode" needs the position controller to run + bool posControllIsNeeded_for_dfall_mode = (setpoint->dfall_mode != modeDfallMotors && setpoint->dfall_mode != modeDfallRate && setpoint->dfall_mode != modeDfallAngle); + // Hence run the position controller only if needed + if (posControllIsNeeded_for_dfall_mode) + { + positionController(&actuatorThrust, &attitudeDesired, setpoint, state); + } } if (RATE_DO_EXECUTE(ATTITUDE_RATE, tick)) { @@ -132,6 +138,9 @@ void controllerPid(control_t *control, setpoint_t *setpoint, control->thrust = actuatorThrust; } + // The following "if (control->thrust == 0)" block is commented + // out because it is replaced with what follows after. + /* if (control->thrust == 0) { control->thrust = 0; @@ -150,6 +159,89 @@ void controllerPid(control_t *control, setpoint_t *setpoint, // Reset the calculated YAW angle for rate control attitudeDesired.yaw = state->attitude.yaw; } + */ + + // This set of "if:then:else" statements is used to specify + // the "control->cmd{1,2,3,4}" depending on the "setpoint->dfall_mode" + // And in all cases perform the check if either: + // >> "control->thrust==0", or + // >> "control->cmd{1,2,3,4}==0" + // where the check performed is appropriate to the case. + // The result of the check is used to set all commands to zero and + // to reset all PIDs, if necessary. + + // Default the check to false + bool isZeroThrust = false; + + if (setpoint->dfall_mode == modeDfallMotors) + { + // Set the {roll,pitch,yaw} commands to zero + control->roll = 0; + control->pitch = 0; + control->yaw = 0; + // Copy across the per motor commands + control->cmd1 = setpoint->cmd1; + control->cmd2 = setpoint->cmd2; + control->cmd3 = setpoint->cmd3; + control->cmd4 = setpoint->cmd4; + // Perform check for all thrust being zero + if ((control->cmd1 == 0 && control->cmd2 == 0 && control->cmd3 == 0 && control->cmd4 == 0)) + { + // Set the flag to true that thrusts are zero + isZeroThrust = true; + } + } + else if(setpoint->dfall_mode == modeDfallRate || setpoint->dfall_mode == modeDfallAngle) + { + // Copy across the per motor commands + control->cmd1 = setpoint->cmd1; + control->cmd2 = setpoint->cmd2; + control->cmd3 = setpoint->cmd3; + control->cmd4 = setpoint->cmd4; + // Perform check for all thrust being zero + if ((control->cmd1 == 0 && control->cmd2 == 0 && control->cmd3 == 0 && control->cmd4 == 0)) + { + // Set the flag to true that thrusts are zero + isZeroThrust = true; + } + } + // Otherwise, "setpoint->dfall_mode == modeDfallDisable" + else + { + // Put the thrust value onto each motor + control->cmd1 = control->thrust; + control->cmd2 = control->thrust; + control->cmd3 = control->thrust; + control->cmd4 = control->thrust; + // If thrust is zero, then: + if (control->thrust == 0) + { + // Set the flag to true that thrusts are zero + isZeroThrust = true; + } + } + + // If the flag idicates that thrusts are zero, + // then set all commands to zero and reset the PIDs + if (isZeroThrust) + { + // Set all commands to zero + control->cmd1 = 0; + control->cmd2 = 0; + control->cmd3 = 0; + control->cmd4 = 0; + control->thrust = 0; + control->roll = 0; + control->pitch = 0; + control->yaw = 0; + + // Reset all PIDs + attitudeControllerResetAllPID(); + positionControllerResetAllPID(); + + // Reset the calculated YAW angle for rate control + attitudeDesired.yaw = state->attitude.yaw; + } } diff --git a/src/modules/src/crtp_commander_generic.c b/src/modules/src/crtp_commander_generic.c index 1662fe4..84d0631 100644 --- a/src/modules/src/crtp_commander_generic.c +++ b/src/modules/src/crtp_commander_generic.c @@ -71,6 +71,9 @@ enum packet_type { hoverType = 5, fullStateType = 6, positionType = 7, + dfallMotorsType = 8, + dfallRateType = 9, + dfallAngleType = 10, }; /* ---===== 2 - Decoding functions =====--- */ @@ -367,6 +370,180 @@ static void positionDecoder(setpoint_t *setpoint, uint8_t type, const void *data setpoint->attitude.yaw = values->yaw; } +/* dfall motors mode decoder + * disable all controllers, the motor commands provided are + * set directly to the motors + */ +struct dfallMotorsPacket_s { + uint16_t cmd1; + uint16_t cmd2; + uint16_t cmd3; + uint16_t cmd4; +} __attribute__((packed)); + +static void dfallMotorsDecoder(setpoint_t *setpoint, uint8_t type, const void *data, size_t datalen) +{ + const struct dfallMotorsPacket_s *values = data; + ASSERT(datalen == sizeof(struct dfallMotorsPacket_s)); + + // Disable the onboard position controllers + setpoint->mode.x = modeDisable; + setpoint->mode.y = modeDisable; + setpoint->mode.z = modeDisable; + + // And set their setpoint values to zero + setpoint->thrust = 0; + setpoint->position.x = 0; + setpoint->position.y = 0; + setpoint->position.z = 0; + setpoint->velocity.x = 0; + setpoint->velocity.y = 0; + setpoint->velocity.z = 0; + + // Disable the onboard orientation controllers + setpoint->mode.roll = modeDisable; + setpoint->mode.pitch = modeDisable; + setpoint->mode.yaw = modeDisable; + + // And set their setpoint values to zero + setpoint->attitude.roll = 0; + setpoint->attitude.pitch = 0; + setpoint->attitude.yaw = 0; + setpoint->attitudeRate.roll = 0; + setpoint->attitudeRate.pitch = 0; + setpoint->attitudeRate.yaw = 0; + + // Tranfer the per-motor commands from the packet + // to the respective setpoints + setpoint->cmd1 = limitUint16(values->cmd1); + setpoint->cmd2 = limitUint16(values->cmd2); + setpoint->cmd3 = limitUint16(values->cmd3); + setpoint->cmd4 = limitUint16(values->cmd4); + + // Set the "dfall_mode" accordingly + setpoint->dfall_mode = modeDfallMotors; +} + +/* dfall rate mode decoder + * disable the position controllers and use the attitude controllers + * in "velocity mode", i.e., use the onboard "rate controllers" + */ +struct dfallRatePacket_s { + uint16_t cmd1; + uint16_t cmd2; + uint16_t cmd3; + uint16_t cmd4; + float roll_rate; + float pitch_rate; + float yaw_rate; +} __attribute__((packed)); + +static void dfallRateDecoder(setpoint_t *setpoint, uint8_t type, const void *data, size_t datalen) +{ + const struct dfallRatePacket_s *values = data; + ASSERT(datalen == sizeof(struct dfallRatePacket_s)); + + // Disable the onboard position controllers + setpoint->mode.x = modeDisable; + setpoint->mode.y = modeDisable; + setpoint->mode.z = modeDisable; + + // And set their setpoint values to zero + setpoint->thrust = 0; + setpoint->position.x = 0; + setpoint->position.y = 0; + setpoint->position.z = 0; + setpoint->velocity.x = 0; + setpoint->velocity.y = 0; + setpoint->velocity.z = 0; + + // Enable the onboard orientation controllers in + // velocity mode, i.e., as rate controllers + setpoint->mode.roll = modeVelocity; + setpoint->mode.pitch = modeVelocity; + setpoint->mode.yaw = modeVelocity; + + // Set the angle setpoints to zero + setpoint->attitude.roll = 0; + setpoint->attitude.pitch = 0; + setpoint->attitude.yaw = 0; + // Transfer the angular rate commands from the packet + // to the respective setpoints + setpoint->attitudeRate.roll = values->roll_rate; + setpoint->attitudeRate.pitch = values->pitch_rate; + setpoint->attitudeRate.yaw = values->yaw_rate; + + // Tranfer the per-motor commands from the packet + // to the respective setpoints + setpoint->cmd1 = limitUint16(values->cmd1); + setpoint->cmd2 = limitUint16(values->cmd2); + setpoint->cmd3 = limitUint16(values->cmd3); + setpoint->cmd4 = limitUint16(values->cmd4); + + // Set the "dfall_mode" accordingly + setpoint->dfall_mode = modeDfallRate; +} + +/* dfall angle mode decoder + * disable the position controllers and use the attitude controllers + * in "absolute mode", i.e., use the onboard "angle controllers" + */ +struct dfallAnglePacket_s { + uint16_t cmd1; + uint16_t cmd2; + uint16_t cmd3; + uint16_t cmd4; + float roll; + float pitch; + float yaw; +} __attribute__((packed)); + +static void dfallAngleDecoder(setpoint_t *setpoint, uint8_t type, const void *data, size_t datalen) +{ + const struct dfallAnglePacket_s *values = data; + ASSERT(datalen == sizeof(struct dfallRatePacket_s)); + + // Disable the onboard position controllers + setpoint->mode.x = modeDisable; + setpoint->mode.y = modeDisable; + setpoint->mode.z = modeDisable; + + // And set their setpoint values to zero + setpoint->thrust = 0; + setpoint->position.x = 0; + setpoint->position.y = 0; + setpoint->position.z = 0; + setpoint->velocity.x = 0; + setpoint->velocity.y = 0; + setpoint->velocity.z = 0; + + // Enable the onboard orientation controllers in + // absolute mode, i.e., as angle controllers + setpoint->mode.roll = modeAbs; + setpoint->mode.pitch = modeAbs; + setpoint->mode.yaw = modeAbs; + + // Transfer the angle commands from the packet + // to the respective setpoints + setpoint->attitude.roll = values->roll; + setpoint->attitude.pitch = values->pitch; + setpoint->attitude.yaw = values->yaw; + // Set the angular rate setpoints to zero + setpoint->attitudeRate.roll = 0; + setpoint->attitudeRate.pitch = 0; + setpoint->attitudeRate.yaw = 0; + + // Tranfer the per-motor commands from the packet + // to the respective setpoints + setpoint->cmd1 = limitUint16(values->cmd1); + setpoint->cmd2 = limitUint16(values->cmd2); + setpoint->cmd3 = limitUint16(values->cmd3); + setpoint->cmd4 = limitUint16(values->cmd4); + + // Set the "dfall_mode" accordingly + setpoint->dfall_mode = modeDfallAngle; +} + /* ---===== 3 - packetDecoders array =====--- */ const static packetDecoder_t packetDecoders[] = { [stopType] = stopDecoder, @@ -377,6 +554,9 @@ const static packetDecoder_t packetDecoders[] = { [hoverType] = hoverDecoder, [fullStateType] = fullStateDecoder, [positionType] = positionDecoder, + [dfallMotorsType] = dfallMotorsDecoder, + [dfallRateType] = dfallRateDecoder, + [dfallAngleType] = dfallAngleDecoder, }; /* Decoder switch */ diff --git a/src/modules/src/power_distribution_stock.c b/src/modules/src/power_distribution_stock.c index d3b7d8d..4e7f311 100644 --- a/src/modules/src/power_distribution_stock.c +++ b/src/modules/src/power_distribution_stock.c @@ -80,18 +80,18 @@ void powerDistribution(const control_t *control) #ifdef QUAD_FORMATION_X int16_t r = control->roll / 2.0f; int16_t p = control->pitch / 2.0f; - motorPower.m1 = limitThrust(control->thrust - r + p + control->yaw); - motorPower.m2 = limitThrust(control->thrust - r - p - control->yaw); - motorPower.m3 = limitThrust(control->thrust + r - p + control->yaw); - motorPower.m4 = limitThrust(control->thrust + r + p - control->yaw); + motorPower.m1 = limitThrust(control->cmd1 - r + p + control->yaw); + motorPower.m2 = limitThrust(control->cmd2 - r - p - control->yaw); + motorPower.m3 = limitThrust(control->cmd3 + r - p + control->yaw); + motorPower.m4 = limitThrust(control->cmd4 + r + p - control->yaw); #else // QUAD_FORMATION_NORMAL - motorPower.m1 = limitThrust(control->thrust + control->pitch + + motorPower.m1 = limitThrust(control->cmd1 + control->pitch + control->yaw); - motorPower.m2 = limitThrust(control->thrust - control->roll - + motorPower.m2 = limitThrust(control->cmd2 - control->roll - control->yaw); - motorPower.m3 = limitThrust(control->thrust - control->pitch + + motorPower.m3 = limitThrust(control->cmd3 - control->pitch + control->yaw); - motorPower.m4 = limitThrust(control->thrust + control->roll - + motorPower.m4 = limitThrust(control->cmd4 + control->roll - control->yaw); #endif @@ -117,11 +117,11 @@ PARAM_ADD(PARAM_UINT16, m1, &motorPowerSet.m1) PARAM_ADD(PARAM_UINT16, m2, &motorPowerSet.m2) PARAM_ADD(PARAM_UINT16, m3, &motorPowerSet.m3) PARAM_ADD(PARAM_UINT16, m4, &motorPowerSet.m4) -PARAM_GROUP_STOP(ring) +PARAM_GROUP_STOP(motorPowerSet) LOG_GROUP_START(motor) -LOG_ADD(LOG_INT32, m4, &motorPower.m4) -LOG_ADD(LOG_INT32, m1, &motorPower.m1) -LOG_ADD(LOG_INT32, m2, &motorPower.m2) -LOG_ADD(LOG_INT32, m3, &motorPower.m3) +LOG_ADD(LOG_UINT32, m1, &motorPower.m1) +LOG_ADD(LOG_UINT32, m2, &motorPower.m2) +LOG_ADD(LOG_UINT32, m3, &motorPower.m3) +LOG_ADD(LOG_UINT32, m4, &motorPower.m4) LOG_GROUP_STOP(motor) diff --git a/src/modules/src/stabilizer.c b/src/modules/src/stabilizer.c index 372ec94..cb4f848 100644 --- a/src/modules/src/stabilizer.c +++ b/src/modules/src/stabilizer.c @@ -92,6 +92,10 @@ static struct { int16_t ax; int16_t ay; int16_t az; + // attitude - milliradians + int16_t roll; + int16_t pitch; + int16_t yaw; // compressed quaternion, see quatcompress.h int32_t quat; // angular velocity - milliradians / sec @@ -151,6 +155,11 @@ static void compressState() stateCompressed.ay = state.acc.y * 9.81f * 1000.0f; stateCompressed.az = (state.acc.z + 1) * 9.81f * 1000.0f; + float const deg2millirad = ((float)M_PI * 1000.0f) / 180.0f; + stateCompressed.roll = state.attitude.roll * deg2millirad; + stateCompressed.pitch = state.attitude.pitch * deg2millirad; + stateCompressed.yaw = state.attitude.yaw * deg2millirad; + float const q[4] = { state.attitudeQuaternion.x, state.attitudeQuaternion.y, @@ -158,7 +167,7 @@ static void compressState() state.attitudeQuaternion.w}; stateCompressed.quat = quatcompress(q); - float const deg2millirad = ((float)M_PI * 1000.0f) / 180.0f; + //float const deg2millirad = ((float)M_PI * 1000.0f) / 180.0f; stateCompressed.rateRoll = sensorData.gyro.x * deg2millirad; stateCompressed.ratePitch = -sensorData.gyro.y * deg2millirad; stateCompressed.rateYaw = sensorData.gyro.z * deg2millirad; @@ -670,6 +679,10 @@ LOG_ADD(LOG_INT16, ax, &stateCompressed.ax) // acceleration - mm / LOG_ADD(LOG_INT16, ay, &stateCompressed.ay) LOG_ADD(LOG_INT16, az, &stateCompressed.az) +LOG_ADD(LOG_INT16, roll, &stateCompressed.roll) // attitude - milliradians +LOG_ADD(LOG_INT16, pitch, &stateCompressed.pitch) +LOG_ADD(LOG_INT16, yaw, &stateCompressed.yaw) + LOG_ADD(LOG_UINT32, quat, &stateCompressed.quat) // compressed quaternion, see quatcompress.h LOG_ADD(LOG_INT16, rateRoll, &stateCompressed.rateRoll) // angular velocity - milliradians / sec