I wrote my own quadcopter firmware which is based on some older code. This code shall stabilize the copter to be always in equilibrium. The model is behaving relatively nice. I can control it with my laptop. However I noticed, that the copter is hovering to the side (if not manually controlled), likely because of wind, not well balanced or turbulence.
My idea was maybe to fuse GPS and accelerometer data to implement a function which shall help to hold the position. But this will likely only work if I have a hold altitude function, because changes in pitch or roll change the height, because the thrust is changed slightly. This is why I recently added a routine which shall allow to hold the altitude.
Is someone having experiences with this? I mean with avoiding side drifts of the model because of whatever by software? The problem is in my opinion, that I don't know whether the position change is wanted (by remote control) or not. Additionally it is hard to localize the correct position and calculate the distance caused by drift from it (just with GPS, but this is not precise).
void hold_altitude(int_fast16_t &iFL, int_fast16_t &iBL, int_fast16_t &iFR, int_fast16_t &iBR,
const int_fast32_t rcalt_m)
{
// Enhance the performance:
// This function is only needed for (semi-)autonomous flight mode like:
// * Hold altitude
// * GPS auto-navigation
if(_RECVR.m_Waypoint.m_eMode == GPSPosition::NOTHING_F) {
return;
}
// Return estimated altitude by GPS and barometer
float fCurAlti_cm = _HAL_BOARD.get_alti_m() * 100.f;
// Estimate current climb rate
float fBaroClimb_cms = _HAL_BOARD.get_baro().climb_rate_ms * 100;
float fAcclClimb_cms = _HAL_BOARD.get_accel_ms().z * 100;
// calculate the
float fAltStabOut = _HAL_BOARD.m_rgPIDS[PID_THR_STAB].get_pid(fCurAlti_cm - (float)(rcalt_m*100), 1);
float fBarAcclOut = _HAL_BOARD.m_rgPIDS[PID_THR_ACCL].get_pid(fAltStabOut - fBaroClimb_cms, 1);
float fAccAcclOut = _HAL_BOARD.m_rgPIDS[PID_THR_ACCL].get_pid(fAltStabOut - fAcclClimb_cms, 1);
int_fast16_t iAltOutput = _HAL_BOARD.m_rgPIDS[PID_THR_RATE].get_pid(fAltStabOut - (fBarAcclOut + fAccAcclOut), 1);
// Modify the speed of the motors
iFL += iAltOutput;
iBL += iAltOutput;
iFR += iAltOutput;
iBR += iAltOutput;
}
Copter control:
// Stabilise PIDS
float pit_stab_output = constrain_float(_HAL_BOARD.m_rgPIDS[PID_PIT_STAB].get_pid((float)rcpit - vAtti.x, 1), -250, 250);
float rol_stab_output = constrain_float(_HAL_BOARD.m_rgPIDS[PID_ROL_STAB].get_pid((float)rcrol - vAtti.y, 1), -250, 250);
float yaw_stab_output = constrain_float(_HAL_BOARD.m_rgPIDS[PID_YAW_STAB].get_pid(wrap180_f(targ_yaw - vAtti.z), 1), -360, 360);
// is pilot asking for yaw change - if so feed directly to rate pid (overwriting yaw stab output)
if(abs(rcyaw ) > 5.f) {
yaw_stab_output = rcyaw;
targ_yaw = vAtti.z; // remember this yaw for when pilot stops
}
// rate PIDS
int_fast16_t pit_output = (int_fast16_t)constrain_float(_HAL_BOARD.m_rgPIDS[PID_PIT_RATE].get_pid(pit_stab_output - vGyro.x, 1), -500, 500);
int_fast16_t rol_output = (int_fast16_t)constrain_float(_HAL_BOARD.m_rgPIDS[PID_ROL_RATE].get_pid(rol_stab_output - vGyro.y, 1), -500, 500);
int_fast16_t yaw_output = (int_fast16_t)constrain_float(_HAL_BOARD.m_rgPIDS[PID_YAW_RATE].get_pid(yaw_stab_output - vGyro.z, 1), -500, 500);
int_fast16_t iFL = rcthr + rol_output + pit_output - yaw_output;
int_fast16_t iBL = rcthr + rol_output - pit_output + yaw_output;
int_fast16_t iFR = rcthr - rol_output + pit_output + yaw_output;
int_fast16_t iBR = rcthr - rol_output - pit_output - yaw_output;
// Hold the altitude
hold_altitude(iFL, iBL, iFR, iBR, rcalt);
hal.rcout->write(MOTOR_FL, iFL);
hal.rcout->write(MOTOR_BL, iBL);
hal.rcout->write(MOTOR_FR, iFR);
hal.rcout->write(MOTOR_BR, iBR);