Subversion Repositories FlightCtrl

Compare Revisions

Ignore whitespace Rev 791 → Rev 792

/branches/V0.68d Code Redesign killagreg/GPS.c
81,8 → 81,10
GPS_Roll = 0;
}
 
// calculates the GPS control sticks values from the deviation to target position
void GPS_PDController(GPS_Pos_t *TargetPos)
// calculates the GPS control stick values from the deviation to target position
// if the pointer to the target positin is NULL or is the target position invalid
// then the P part of the controller is deactivated.
void GPS_PDController(GPS_Pos_t *pTargetPos)
{
int32_t coscompass, sincompass;
int32_t GPSPosDev_North, GPSPosDev_East; // Position deviation in cm
90,35 → 92,55
int32_t PD_North = 0, PD_East = 0;
static int32_t cos_target_latitude = 1;
 
// if GPS data and Compass are ok
if((GPSInfo.status == VALID) && (GPSInfo.satfix == SATFIX_3D) && (CompassHeading >= 0) )
{
 
if( (TargetPos->Status != INVALID) && (GPSInfo.status == VALID) && (GPSInfo.satfix == SATFIX_3D))
{
// calculate position deviation from latitude and longitude differences
GPSPosDev_North = (GPSInfo.latitude - TargetPos->Latitude); // to calculate real cm we would need *111/100 additionally
GPSPosDev_East = (GPSInfo.longitude - TargetPos->Longitude); // to calculate real cm we would need *111/100 additionally
// recalculate the target latitude projection only if the target data are updated
// to save time
if (TargetPos->Status != PROCESSED)
if(pTargetPos != NULL) // if there is a target position
{
cos_target_latitude = (int32_t)c_cos_8192((int16_t)(TargetPos->Latitude/10000000L));
TargetPos->Status = PROCESSED;
}
// calculate latitude projection
GPSPosDev_East *= cos_target_latitude;
GPSPosDev_East /= 8192;
if(pTargetPos->Status != INVALID) // and the position data are valid
{ // calculate position deviation from latitude and longitude differences
GPSPosDev_North = (GPSInfo.latitude - pTargetPos->Latitude); // to calculate real cm we would need *111/100 additionally
GPSPosDev_East = (GPSInfo.longitude - pTargetPos->Longitude); // to calculate real cm we would need *111/100 additionally
// recalculate the target latitude projection only if the target data are updated
// to save time
if (pTargetPos->Status != PROCESSED)
{
cos_target_latitude = (int32_t)c_cos_8192((int16_t)(pTargetPos->Latitude/10000000L));
pTargetPos->Status = PROCESSED;
}
// calculate latitude projection
GPSPosDev_East *= cos_target_latitude;
GPSPosDev_East /= 8192;
 
DebugOut.Analog[12] = GPSPosDev_North;
DebugOut.Analog[13] = GPSPosDev_East;
DebugOut.Analog[12] = GPSPosDev_North;
DebugOut.Analog[13] = GPSPosDev_East;
//DebugOut.Analog[12] = GPSInfo.velnorth;
//DebugOut.Analog[13] = GPSInfo.veleast;
 
//DebugOut.Analog[12] = GPSInfo.velnorth;
//DebugOut.Analog[13] = GPSInfo.veleast;
//Calculate P-components of the controller (negative sign for compensation)
P_North = -(GPS_P_Factor * GPSPosDev_North)/2048;
P_East = -(GPS_P_Factor * GPSPosDev_East)/2048;
}
else // not valid target position available
{
GPSPosDev_North = 0;
GPSPosDev_East = 0;
}
}
else // not target position available
{
GPSPosDev_North = 0;
GPSPosDev_East = 0;
}
 
//Calculate PD-components of the controller (negative sign for compensation)
P_North = -(GPS_P_Factor * GPSPosDev_North)/2048;
P_East = -(GPS_P_Factor * GPSPosDev_East)/2048;
D_North = -(GPS_D_Factor * GPSInfo.velnorth)/512;
P_East = -(GPS_P_Factor * GPSPosDev_East)/2048;
D_East = -(GPS_D_Factor * GPSInfo.veleast)/512;
 
// limit D-Part if position deviation is significant of the target position
// this accelerates flying to the target position
if( (abs(GPSPosDev_North) > GPS_D_LIMIT_DIST) || (abs(GPSPosDev_East) > GPS_D_LIMIT_DIST) )
{
if (D_North > GPS_D_LIMIT) D_North = GPS_D_LIMIT;
126,7 → 148,6
if (D_East > GPS_D_LIMIT) D_East = GPS_D_LIMIT;
else if (D_East < -GPS_D_LIMIT) D_East = -GPS_D_LIMIT;
}
 
// PD-controller
PD_North = P_North + D_North;
PD_East = P_East + D_East;
133,9 → 154,8
 
// GPS to pitch and roll settings
 
//A positive pitch angle moves head downwards (flying forward).
//A positive roll angle tilts left side downwards (flying left).
 
// A positive pitch angle moves head downwards (flying forward).
// A positive roll angle tilts left side downwards (flying left).
// If compass heading is 0 the head of the copter is in north direction.
// A positive pitch angle will fly to north and a positive roll angle will fly to west.
// In case of a positive north deviation/velocity the
142,23 → 162,15
// copter should fly to south (negative pitch).
// In case of a positive east position deviation and a positive east velocity the
// copter should fly to west (positive roll).
 
// The influence of the GPS_Pitch and GPS_Roll variable is contrarily to the stick values
// in the fc.c. Therefore a positive north deviation/velocity should result in a positive
// GPS_Pitch and a positive east deviation/velocity should result in a negative GPS_Roll.
 
// rotation transformation to compass heading to match any copter orientation
if (CompassHeading < 0) // no valid compass data
{ // disable GPS
GPS_Neutral();
}
else
{
coscompass = (int32_t)c_cos_8192(CompassHeading);
sincompass = (int32_t)c_sin_8192(CompassHeading);
GPS_Roll = (int16_t)((coscompass * PD_East - sincompass * PD_North) / 8192);
GPS_Pitch = -1*(int16_t)((sincompass * PD_East + coscompass * PD_North) / 8192);
}
coscompass = (int32_t)c_cos_8192(CompassHeading);
sincompass = (int32_t)c_sin_8192(CompassHeading);
GPS_Roll = (int16_t)((coscompass * PD_East - sincompass * PD_North) / 8192);
GPS_Pitch = -1*(int16_t)((sincompass * PD_East + coscompass * PD_North) / 8192);
 
// limit GPS controls
if (GPS_Pitch > GPS_STICK_LIMIT) GPS_Pitch = GPS_STICK_LIMIT;
else if (GPS_Pitch < -GPS_STICK_LIMIT) GPS_Pitch = -GPS_STICK_LIMIT;
165,10 → 177,9
if (GPS_Roll > GPS_STICK_LIMIT) GPS_Roll = GPS_STICK_LIMIT;
else if (GPS_Roll < -GPS_STICK_LIMIT) GPS_Roll = -GPS_STICK_LIMIT;
}
else // invalid input data
else // invalid GPS data
{
BeepTime = 50;
GPS_Neutral();
GPS_Neutral(); // do nothing
}
}
 
176,6 → 187,7
void GPS_Main(uint8_t ctrl)
{
static uint8_t GPS_Task = TSK_IDLE;
static uint8_t GPS_P_Delay = 0;
int16_t satbeep;
 
// ctrl enables the gps feature
222,7 → 234,13
// if sticks are centered (no manual control)
if ((MaxStickPitch < GPS_STICK_SENSE) && (MaxStickRoll < GPS_STICK_SENSE))
{
GPS_PDController(&HoldPosition);
if(GPS_P_Delay<7)
{ // delayed activation of P-Part for 8 cycles (8*0.25s = 2s)
GPS_P_Delay++;
GPS_SetHoldPosition(); // update hold point to current gps position
GPS_PDController(NULL); // activates only the D-Part
}
else GPS_PDController(&HoldPosition);// activates the P&D-Part
}
else // MK controlled by user
{
230,6 → 248,7
GPS_SetHoldPosition();
// disable gps control
GPS_Neutral();
GPS_P_Delay = 0;
}
}
else // invalid Hold Position
/branches/V0.68d Code Redesign killagreg/fc.c
91,7 → 91,7
volatile int32_t IntegralYaw = 0;
volatile int32_t Reading_IntegralGyroPitch = 0, Reading_IntegralGyroPitch2 = 0;
volatile int32_t Reading_IntegralGyroRoll = 0, Reading_IntegralGyroRoll2 = 0;
volatile int32_t Reading_IntegralGyroYaw = 0, Reading_IntegralGyroYaw2 = 0;
volatile int32_t Reading_IntegralGyroYaw = 0;
volatile int32_t MeanIntegralPitch;
volatile int32_t MeanIntegralRoll;
 
242,7 → 242,6
// Yaw
// calculate yaw gyro intergral (~ to rotation angle)
Reading_IntegralGyroYaw += Reading_GyroYaw;
Reading_IntegralGyroYaw2 += Reading_GyroYaw;
// Coupling fraction
if(!Looping_Pitch && !Looping_Roll && (ParamSet.GlobalConfig & CFG_AXIS_COUPLING_ACTIVE))
{
436,7 → 435,7
static uint8_t HeightControlActive = 0;
static int16_t HeightControlThrust = 0;
static int8_t TimerDebugOut = 0;
static int8_t StoreNewCompassCourse = 0;
static uint16_t UpdateCompassCourse = 0;
static int32_t CorrectionPitch, CorrectionRoll;
 
Mean();
504,7 → 503,6
SumPitch = 0;
SumRoll = 0;
Reading_IntegralGyroYaw = 0;
Reading_IntegralGyroYaw2 = 0;
}
 
if(Poti1 < PPM_in[ParamSet.ChannelAssignment[CH_POTI1]] + 110) Poti1++; else if(Poti1 > PPM_in[ParamSet.ChannelAssignment[CH_POTI1]] + 110 && Poti1) Poti1--;
576,18 → 574,18
// save the ACC neutral setting to eeprom
else if(PPM_in[ParamSet.ChannelAssignment[CH_YAW]] < -75)
{
if(++delay_neutral > 200) // not immediately (wait 200 loops = 200 * 2ms = 0.4 s)
if(++delay_neutral > 200) // not immediately (wait 200 loops = 200 * 2ms = 0.4 s)
{
delay_neutral = 0;
GRN_OFF;
SetParamWord(PID_ACC_PITCH, 0xFFFF); // make value invalid
Model_Is_Flying = 0;
SetNeutral();
// Save ACC neutral settings to eeprom
SetParamWord(PID_ACC_PITCH, (uint16_t)NeutralAccX);
SetParamWord(PID_ACC_ROLL, (uint16_t)NeutralAccY);
SetParamWord(PID_ACC_Z, (uint16_t)NeutralAccZ);
Beep(GetActiveParamSet());
delay_neutral = 0;
GRN_OFF;
SetParamWord(PID_ACC_PITCH, 0xFFFF); // make value invalid
Model_Is_Flying = 0;
SetNeutral();
// Save ACC neutral settings to eeprom
SetParamWord(PID_ACC_PITCH, (uint16_t)NeutralAccX);
SetParamWord(PID_ACC_ROLL, (uint16_t)NeutralAccY);
SetParamWord(PID_ACC_Z, (uint16_t)NeutralAccZ);
Beep(GetActiveParamSet());
}
}
else delay_neutral = 0;
609,7 → 607,6
MotorsOn = 1;
SetPointYaw = 0;
Reading_IntegralGyroYaw = 0;
Reading_IntegralGyroYaw2 = 0;
Reading_IntegralGyroPitch = 0;
Reading_IntegralGyroRoll = 0;
Reading_IntegralGyroPitch2 = IntegralPitch;
1011,15 → 1008,14
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// Yawing
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
if(abs(PPM_in[ParamSet.ChannelAssignment[CH_YAW]]) > 20) // yaw stick is activated
{ // if not fixed compass course is set update compass course
if(!(ParamSet.GlobalConfig & CFG_COMPASS_FIX)) StoreNewCompassCourse = 1;
if(abs(StickYaw) > 20 ) // yaw stick is activated
{ // if not fixed compass course is set update compass course for 1s
if(!(ParamSet.GlobalConfig & CFG_COMPASS_FIX)) UpdateCompassCourse = 500;
}
// exponential stick sensitivity in yawring rate
tmp_int = (int32_t) ParamSet.Yaw_P * ((int32_t)StickYaw * abs(StickYaw)) / 512L; // expo y = ax + bx²
tmp_int += (ParamSet.Yaw_P * StickYaw) / 4;
SetPointYaw = tmp_int;
Reading_IntegralGyroYaw -= tmp_int;
// limit the effect
if(Reading_IntegralGyroYaw > 50000) Reading_IntegralGyroYaw = 50000;
if(Reading_IntegralGyroYaw <-50000) Reading_IntegralGyroYaw =-50000;
1043,7 → 1039,6
#ifdef USE_CMPS03
CompassHeading = CMPS03_Heading();
#endif
 
if (CompassHeading < 0) // no compass data available
{
CompassOffCourse = 0; // disables gyro compass correction
1051,17 → 1046,17
else // calculate OffCourse (angular deviation from heading to course)
CompassOffCourse = ((540 + CompassHeading - CompassCourse) % 360) - 180;
}
 
// reduce compass effect with increasing declination
w = abs(IntegralPitch / 512);
v = abs(IntegralRoll / 512);
if(v > w) w = v; // get maximum declination
// if declination is small enough then update compass course if neccessary
if((w < 35) && StoreNewCompassCourse && (CompassHeading>=0) ) // 35 corresponds to a declination of ~14 deg
if((w < 70) && UpdateCompassCourse && (CompassHeading>=0) ) // 70 corresponds to a declination of ~28 deg
{
CompassCourse = CompassHeading;
StoreNewCompassCourse = 0;
CompassOffCourse = 0; // should be set immediatly because the CompassOffCourse is otherwise only refreshed if new compass heading is calulated
}
if(UpdateCompassCourse) UpdateCompassCourse--;
w = (w * FCParam.CompassYawEffect) / 64; // (w=0 for 64->~25 deg, 128->~50 deg) for higher declinaions the compass drift compensation is disabled
w = FCParam.CompassYawEffect - w; // reduce compass effect with increasing declination
if(w > 0) // if there is any compass effect (avoid negative compass feedback)
/branches/V0.68d Code Redesign killagreg/ubx.c
139,19 → 139,19
{
case UBX_ID_POSLLH: // geodetic position
ubxP = (int8_t *)&GpsPosLlh; // data start pointer
ubxEp = ((int8_t *)&GpsPosLlh) + sizeof(GPS_POSLLH_t); // data end pointer
ubxEp = (int8_t *)(&GpsPosLlh + 1); // data end pointer
ubxSp = (int8_t *)&GpsPosLlh.Status; // status pointer
break;
 
case UBX_ID_SOL: // navigation solution
ubxP = (int8_t *)&GpsSol; // data start pointer
ubxEp = ((int8_t *)&GpsSol) + sizeof(GPS_SOL_t); // data end pointer
ubxEp = (int8_t *)(&GpsSol + 1); // data end pointer
ubxSp = (int8_t *)&GpsSol.Status; // status pointer
break;
 
case UBX_ID_VELNED: // velocity vector in tangent plane
ubxP = (int8_t *)&GpsVelNed; // data start pointer
ubxEp = ((int8_t *)&GpsVelNed) + sizeof(GPS_VELNED_t); // data end pointer
ubxEp = (int8_t *)(&GpsVelNed + 1); // data end pointer
ubxSp = (int8_t *)&GpsVelNed.Status; // status pointer
break;