Subversion Repositories FlightCtrl

Rev

Rev 2045 | Rev 2047 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 2045 Rev 2046
Line 22... Line 22...
22
  GPS_FLIGHT_MODE_AID,
22
  GPS_FLIGHT_MODE_AID,
23
  GPS_FLIGHT_MODE_HOME,
23
  GPS_FLIGHT_MODE_HOME,
24
} FlightMode_t;
24
} FlightMode_t;
Line 25... Line 25...
25
 
25
 
26
#define GPS_POSINTEGRAL_LIMIT 32000
26
#define GPS_POSINTEGRAL_LIMIT 32000
27
#define GPS_STICK_LIMIT         45              // limit of gps stick control to avoid critical flight attitudes
27
#define GPS_STICK_LIMIT         400             // limit of gps stick control to avoid critical flight attitudes
Line 28... Line 28...
28
#define GPS_P_LIMIT                     25
28
#define GPS_P_LIMIT                     100
29
 
29
 
30
typedef struct {
30
typedef struct {
31
  int32_t longitude;
31
  int32_t longitude;
Line 40... Line 40...
40
GPS_Pos_t homePosition = { 0, 0, 0, INVALID };
40
GPS_Pos_t homePosition = { 0, 0, 0, INVALID };
41
// the current flight mode
41
// the current flight mode
42
FlightMode_t flightMode = GPS_FLIGHT_MODE_UNDEF;
42
FlightMode_t flightMode = GPS_FLIGHT_MODE_UNDEF;
Line 43... Line 43...
43
 
43
 
44
// ---------------------------------------------------------------------------------
44
// ---------------------------------------------------------------------------------
45
void GPS_updateFlightMode(void) {
45
void navi_updateFlightMode(void) {
Line 46... Line 46...
46
  static FlightMode_t flightModeOld = GPS_FLIGHT_MODE_UNDEF;
46
  static FlightMode_t flightModeOld = GPS_FLIGHT_MODE_UNDEF;
47
 
47
 
48
  if (controlMixer_getSignalQuality() <= SIGNAL_BAD
48
  if (controlMixer_getSignalQuality() <= SIGNAL_BAD
Line 65... Line 65...
65
  debugOut.analog[31] = flightMode;
65
  debugOut.analog[31] = flightMode;
66
}
66
}
Line 67... Line 67...
67
 
67
 
68
// ---------------------------------------------------------------------------------
68
// ---------------------------------------------------------------------------------
69
// This function defines a good GPS signal condition
69
// This function defines a good GPS signal condition
70
uint8_t GPS_isSignalOK(void) {
70
uint8_t navi_isGPSSignalOK(void) {
71
  static uint8_t GPSFix = 0;
71
  static uint8_t GPSFix = 0;
72
  if ((GPSInfo.status != INVALID) && (GPSInfo.satfix == SATFIX_3D)
72
  if ((GPSInfo.status != INVALID) && (GPSInfo.satfix == SATFIX_3D)
73
      && (GPSInfo.flags & FLAG_GPSFIXOK)
73
      && (GPSInfo.flags & FLAG_GPSFIXOK)
74
      && ((GPSInfo.satnum >= staticParams.GPSMininumSatellites) || GPSFix)) {
74
      && ((GPSInfo.satnum >= staticParams.GPSMininumSatellites) || GPSFix)) {
Line 78... Line 78...
78
    return (0);
78
    return (0);
79
}
79
}
Line 80... Line 80...
80
 
80
 
81
// ---------------------------------------------------------------------------------
81
// ---------------------------------------------------------------------------------
82
// rescale xy-vector length to  limit
82
// rescale xy-vector length to  limit
83
uint8_t GPS_limitXY(int32_t *x, int32_t *y, int32_t limit) {
83
uint8_t navi_limitXY(int32_t *x, int32_t *y, int32_t limit) {
84
  int32_t len;
84
  int32_t len;
85
  len = isqrt32(*x * *x + *y * *y);
85
  len = isqrt32(*x * *x + *y * *y);
86
  if (len > limit) {
86
  if (len > limit) {
87
    // normalize control vector components to the limit
87
    // normalize control vector components to the limit
Line 91... Line 91...
91
  }
91
  }
92
  return 0;
92
  return 0;
93
}
93
}
Line 94... Line 94...
94
 
94
 
95
// checks nick and roll sticks for manual control
95
// checks nick and roll sticks for manual control
96
uint8_t GPS_isManuallyControlled(int16_t* sticks) {
96
uint8_t navi_isManuallyControlled(int16_t* sticks) {
97
  if (sticks[CONTROL_PITCH] < staticParams.naviStickThreshold
97
  if (sticks[CONTROL_PITCH] < staticParams.naviStickThreshold
98
      && sticks[CONTROL_ROLL] < staticParams.naviStickThreshold)
98
      && sticks[CONTROL_ROLL] < staticParams.naviStickThreshold)
99
    return 0;
99
    return 0;
100
  else
100
  else
101
    return 1;
101
    return 1;
Line 102... Line 102...
102
}
102
}
103
 
103
 
104
// set given position to current gps position
104
// set given position to current gps position
105
uint8_t GPS_writeCurrPositionTo(GPS_Pos_t * pGPSPos) {
105
uint8_t navi_writeCurrPositionTo(GPS_Pos_t * pGPSPos) {
Line 106... Line 106...
106
  if (pGPSPos == NULL)
106
  if (pGPSPos == NULL)
107
    return 0; // bad pointer
107
    return 0; // bad pointer
108
 
108
 
109
  if (GPS_isSignalOK()) { // is GPS signal condition is fine
109
  if (navi_isGPSSignalOK()) { // is GPS signal condition is fine
110
    pGPSPos->longitude = GPSInfo.longitude;
110
    pGPSPos->longitude = GPSInfo.longitude;
111
    pGPSPos->latitude = GPSInfo.latitude;
111
    pGPSPos->latitude = GPSInfo.latitude;
Line 117... Line 117...
117
    return 0;
117
    return 0;
118
  }
118
  }
119
}
119
}
Line 120... Line 120...
120
 
120
 
121
// clear position
121
// clear position
122
uint8_t GPS_clearPosition(GPS_Pos_t * pGPSPos) {
122
uint8_t navi_clearPosition(GPS_Pos_t * pGPSPos) {
123
  if (pGPSPos == NULL)
123
  if (pGPSPos == NULL)
124
    return 0; // bad pointer
124
    return 0; // bad pointer
125
  else {
125
  else {
126
    pGPSPos->longitude = 0;
126
    pGPSPos->longitude = 0;
Line 132... Line 132...
132
}
132
}
Line 133... Line 133...
133
 
133
 
134
// calculates the GPS control stick values from the deviation to target position
134
// calculates the GPS control stick values from the deviation to target position
135
// if the pointer to the target positin is NULL or is the target position invalid
135
// if the pointer to the target positin is NULL or is the target position invalid
136
// then the P part of the controller is deactivated.
136
// then the P part of the controller is deactivated.
137
void GPS_PIDController(GPS_Pos_t *pTargetPos, int16_t* sticks) {
137
void navi_PIDController(GPS_Pos_t *pTargetPos, int16_t* sticks) {
138
  static int32_t PID_Nick, PID_Roll;
138
  static int32_t PID_Nick, PID_Roll;
139
  int32_t coscompass, sincompass;
139
  int32_t coscompass, sincompass;
140
  int32_t GPSPosDev_North, GPSPosDev_East; // Position deviation in cm
140
  int32_t GPSPosDev_North, GPSPosDev_East; // Position deviation in cm
141
  int32_t P_North = 0, D_North = 0, P_East = 0, D_East = 0, I_North = 0, I_East = 0;
141
  int32_t P_North = 0, D_North = 0, P_East = 0, D_East = 0, I_North = 0, I_East = 0;
142
  int32_t PID_North = 0, PID_East = 0;
142
  int32_t PID_North = 0, PID_East = 0;
143
  static int32_t cos_target_latitude = 1;
143
  static int32_t cos_target_latitude = 1;
144
  static int32_t GPSPosDevIntegral_North = 0, GPSPosDevIntegral_East = 0;
144
  static int32_t GPSPosDevIntegral_North = 0, GPSPosDevIntegral_East = 0;
Line 145... Line 145...
145
  static GPS_Pos_t *pLastTargetPos = 0;
145
  static GPS_Pos_t *pLastTargetPos = 0;
146
 
146
 
147
  // if GPS data and Compass are ok
147
  // if GPS data and Compass are ok
148
  if (GPS_isSignalOK() && (magneticHeading >= 0)) {
148
  if (navi_isGPSSignalOK() && (magneticHeading >= 0)) {
149
    if (pTargetPos != NULL) { // if there is a target position
149
    if (pTargetPos != NULL) { // if there is a target position
150
      if (pTargetPos->status != INVALID) { // and the position data are valid
150
      if (pTargetPos->status != INVALID) { // and the position data are valid
151
        // if the target data are updated or the target pointer has changed
151
        // if the target data are updated or the target pointer has changed
Line 185... Line 185...
185
    }
185
    }
Line 186... Line 186...
186
 
186
 
Line 187... Line 187...
187
    //Calculate PID-components of the controller
187
    //Calculate PID-components of the controller
188
 
188
 
189
    // D-Part
189
    // D-Part
Line 190... Line 190...
190
    D_North = ((int32_t) staticParams.naviD * GPSInfo.velnorth) / 512;
190
    D_North = ((int32_t) staticParams.naviD * GPSInfo.velnorth) >> 9;
191
    D_East = ((int32_t) staticParams.naviD * GPSInfo.veleast) / 512;
191
    D_East = ((int32_t) staticParams.naviD * GPSInfo.veleast) >> 9;
192
 
192
 
Line 193... Line 193...
193
    // P-Part
193
    // P-Part
194
    P_North = ((int32_t) staticParams.naviP * GPSPosDev_North) / 2048;
194
    P_North = ((int32_t) staticParams.naviP * GPSPosDev_North) >> 11;
195
    P_East = ((int32_t) staticParams.naviP * GPSPosDev_East) / 2048;
-
 
196
 
195
    P_East = ((int32_t) staticParams.naviP * GPSPosDev_East) >> 11;
Line 197... Line 196...
197
    // I-Part
196
 
198
    I_North = ((int32_t) staticParams.naviI * GPSPosDevIntegral_North)
197
    // I-Part
199
        / 8192;
198
    I_North = ((int32_t) staticParams.naviI * GPSPosDevIntegral_North) >> 13;
200
    I_East = ((int32_t) staticParams.naviI * GPSPosDevIntegral_East) / 8192;
199
    I_East = ((int32_t) staticParams.naviI * GPSPosDevIntegral_East) >> 13;
-
 
200
 
201
 
201
    // combine P & I
202
    // combine P & I
202
    PID_North = P_North + I_North;
203
    PID_North = P_North + I_North;
203
    PID_East = P_East + I_East;
204
    PID_East = P_East + I_East;
-
 
205
    if (!GPS_limitXY(&PID_North, &PID_East, GPS_P_LIMIT)) {
204
    if (!navi_limitXY(&PID_North, &PID_East, GPS_P_LIMIT)) {
Line 206... Line 205...
206
      GPSPosDevIntegral_North += GPSPosDev_North / 16;
205
      // within limit
207
      GPSPosDevIntegral_East += GPSPosDev_East / 16;
206
      GPSPosDevIntegral_North += GPSPosDev_North >> 4;
208
      GPS_limitXY(&GPSPosDevIntegral_North, &GPSPosDevIntegral_East,
207
      GPSPosDevIntegral_East += GPSPosDev_East >> 4;
Line 232... Line 231...
232
    // GPSStickNick and a positive east deviation/velocity should result in a negative GPSStickRoll.
231
    // GPSStickNick and a positive east deviation/velocity should result in a negative GPSStickRoll.
Line 233... Line 232...
233
 
232
 
234
    coscompass = cos_360(yawGyroHeading / GYRO_DEG_FACTOR_YAW);
233
    coscompass = cos_360(yawGyroHeading / GYRO_DEG_FACTOR_YAW);
Line 235... Line 234...
235
    sincompass = sin_360(yawGyroHeading / GYRO_DEG_FACTOR_YAW);
234
    sincompass = sin_360(yawGyroHeading / GYRO_DEG_FACTOR_YAW);
236
 
235
 
Line 237... Line 236...
237
    PID_Nick = (coscompass * PID_North + sincompass * PID_East) >> MATH_UNIT_FACTOR_LOG;
236
    PID_Nick = (coscompass * PID_North + sincompass * PID_East) >> (MATH_UNIT_FACTOR_LOG-2);
238
    PID_Roll = (sincompass * PID_North - coscompass * PID_East) >> MATH_UNIT_FACTOR_LOG;
237
    PID_Roll = (sincompass * PID_North - coscompass * PID_East) >> (MATH_UNIT_FACTOR_LOG-2);
Line 239... Line 238...
239
 
238
 
240
    // limit resulting GPS control vector
239
    // limit resulting GPS control vector
Line 241... Line 240...
241
    GPS_limitXY(&PID_Nick, &PID_Roll, GPS_STICK_LIMIT);
240
    navi_limitXY(&PID_Nick, &PID_Roll, GPS_STICK_LIMIT);
242
 
241
 
Line 243... Line 242...
243
    debugOut.analog[27] = PID_Nick;
242
    debugOut.analog[27] = -PID_Nick;
244
    debugOut.analog[28] = PID_Roll;
243
    debugOut.analog[28] = -PID_Roll;
245
 
244
 
246
    sticks[CONTROL_PITCH] += PID_Nick;
245
    sticks[CONTROL_PITCH] -= PID_Nick;
Line 255... Line 254...
255
 
254
 
256
void navigation_periodicTask(int16_t* sticks) {
255
void navigation_periodicTask(int16_t* sticks) {
257
  static uint8_t GPS_P_Delay = 0;
256
  static uint8_t GPS_P_Delay = 0;
Line 258... Line 257...
258
  static uint16_t beep_rythm = 0;
257
  static uint16_t beep_rythm = 0;
Line 259... Line 258...
259
 
258
 
260
  GPS_updateFlightMode();
259
  navi_updateFlightMode();
261
 
260
 
262
  // store home position if start of flight flag is set
261
  // store home position if start of flight flag is set
263
  if (MKFlags & MKFLAG_CALIBRATE) {
262
  if (MKFlags & MKFLAG_CALIBRATE) {
264
    MKFlags &= ~(MKFLAG_CALIBRATE);
263
    MKFlags &= ~(MKFLAG_CALIBRATE);
265
    if (GPS_writeCurrPositionTo(&homePosition)) {
264
    if (navi_writeCurrPositionTo(&homePosition)) {
266
        homePosition.latitude += 9000L;
265
        homePosition.latitude += 10000L;
Line 267... Line 266...
267
        beep(500);
266
        beep(500);
Line 285... Line 284...
285
    }
284
    }
286
    break;
285
    break;
287
  case NEWDATA: // new valid data from gps device
286
  case NEWDATA: // new valid data from gps device
288
    // if the gps data quality is good
287
    // if the gps data quality is good
289
    beep_rythm++;
288
    beep_rythm++;
290
    if (GPS_isSignalOK()) {
289
    if (navi_isGPSSignalOK()) {
291
      switch (flightMode) { // check what's to do
290
      switch (flightMode) { // check what's to do
292
      case GPS_FLIGHT_MODE_FREE:
291
      case GPS_FLIGHT_MODE_FREE:
293
        // update hold position to current gps position
292
        // update hold position to current gps position
294
        GPS_writeCurrPositionTo(&holdPosition); // can get invalid if gps signal is bad
293
        navi_writeCurrPositionTo(&holdPosition); // can get invalid if gps signal is bad
295
        // disable gps control
294
        // disable gps control
296
        break;
295
        break;
Line 297... Line 296...
297
 
296
 
298
      case GPS_FLIGHT_MODE_AID:
297
      case GPS_FLIGHT_MODE_AID:
299
        if (holdPosition.status != INVALID) {
298
        if (holdPosition.status != INVALID) {
300
          if (GPS_isManuallyControlled(sticks)) { // MK controlled by user
299
          if (navi_isManuallyControlled(sticks)) { // MK controlled by user
301
            // update hold point to current gps position
300
            // update hold point to current gps position
302
            GPS_writeCurrPositionTo(&holdPosition);
301
            navi_writeCurrPositionTo(&holdPosition);
303
            // disable gps control
302
            // disable gps control
304
            GPS_P_Delay = 0;
303
            GPS_P_Delay = 0;
305
          } else { // GPS control active
304
          } else { // GPS control active
306
            if (GPS_P_Delay < 7) {
305
            if (GPS_P_Delay < 7) {
307
              // delayed activation of P-Part for 8 cycles (8*0.25s = 2s)
306
              // delayed activation of P-Part for 8 cycles (8*0.25s = 2s)
308
              GPS_P_Delay++;
307
              GPS_P_Delay++;
309
              GPS_writeCurrPositionTo(&holdPosition); // update hold point to current gps position
308
              navi_writeCurrPositionTo(&holdPosition); // update hold point to current gps position
310
              GPS_PIDController(NULL, sticks); // activates only the D-Part
309
              navi_PIDController(NULL, sticks); // activates only the D-Part
311
            } else
310
            } else
312
              GPS_PIDController(&holdPosition, sticks); // activates the P&D-Part
311
              navi_PIDController(&holdPosition, sticks); // activates the P&D-Part
313
          }
312
          }
314
        } else // invalid Hold Position
313
        } else // invalid Hold Position
315
        { // try to catch a valid hold position from gps data input
314
        { // try to catch a valid hold position from gps data input
316
          GPS_writeCurrPositionTo(&holdPosition);
315
          navi_writeCurrPositionTo(&holdPosition);
317
        }
316
        }
Line 318... Line 317...
318
        break;
317
        break;
319
 
318
 
320
      case GPS_FLIGHT_MODE_HOME:
319
      case GPS_FLIGHT_MODE_HOME:
321
        if (homePosition.status != INVALID) {
320
        if (homePosition.status != INVALID) {
322
          // update hold point to current gps position
321
          // update hold point to current gps position
323
          // to avoid a flight back if home comming is deactivated
322
          // to avoid a flight back if home comming is deactivated
324
          GPS_writeCurrPositionTo(&holdPosition);
323
          navi_writeCurrPositionTo(&holdPosition);
325
          if (GPS_isManuallyControlled(sticks)) // MK controlled by user
324
          if (navi_isManuallyControlled(sticks)) // MK controlled by user
326
          {
325
          {
327
          } else {// GPS control active
326
          } else {// GPS control active
328
            GPS_PIDController(&homePosition, sticks);
327
            navi_PIDController(&homePosition, sticks);
329
          }
328
          }
330
        } else {
329
        } else {
331
          // bad home position
330
          // bad home position
Line 332... Line 331...
332
          beep(50); // signal invalid home position
331
          beep(50); // signal invalid home position
333
          // try to hold at least the position as a fallback option
332
          // try to hold at least the position as a fallback option
334
 
333
 
335
          if (holdPosition.status != INVALID) {
334
          if (holdPosition.status != INVALID) {
336
            if (GPS_isManuallyControlled(sticks)) {
335
            if (navi_isManuallyControlled(sticks)) {
337
              // MK controlled by user
336
              // MK controlled by user
338
            } else {
337
            } else {
339
              // GPS control active
338
              // GPS control active
340
              GPS_PIDController(&holdPosition, sticks);
339
              navi_PIDController(&holdPosition, sticks);
341
            }
340
            }
342
          } else { // try to catch a valid hold position
341
          } else { // try to catch a valid hold position
343
            GPS_writeCurrPositionTo(&holdPosition);
342
            navi_writeCurrPositionTo(&holdPosition);
344
          }
343
          }
345
        }
344
        }