Subversion Repositories NaviCtrl

Rev

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

Rev 185 Rev 187
Line 132... Line 132...
132
 
132
 
133
//-------------------------------------------------------------
133
//-------------------------------------------------------------
134
// Update GPSParamter
134
// Update GPSParamter
135
void GPS_UpdateParameter(void)
135
void GPS_UpdateParameter(void)
136
{
-
 
137
        #define SWITCH_DELAY 500
-
 
138
        static u8 wpclear = FALSE;
-
 
139
        static u32 SwitchDelay = 0;
-
 
140
        static GPS_FlightMode_t FlightMode_Old = GPS_FLIGHT_MODE_UNDEF;
-
 
141
 
-
 
142
        // in case of bad receiving conditions
-
 
143
        if(FC.RC_Quality < 100)
-
 
144
        {       // set fixed parameter
-
 
145
                GPS_Parameter.FlightMode = GPS_FLIGHT_MODE_WAYPOINT;
-
 
146
                GPS_Parameter.Gain      = (float) 100;
-
 
147
                GPS_Parameter.P         = (float) 90;
-
 
148
                GPS_Parameter.I         = (float) 90;
-
 
149
                GPS_Parameter.D         = (float) 90;
-
 
150
                GPS_Parameter.A         = (float) 90;
-
 
151
                GPS_Parameter.ACC       = (float) 0;
-
 
152
                GPS_Parameter.P_Limit = 90;
-
 
153
                GPS_Parameter.I_Limit = 90;
-
 
154
                GPS_Parameter.D_Limit = 90;
-
 
155
                GPS_Parameter.PID_Limit = 200;
-
 
156
                GPS_Parameter.BrakingDuration = 0;
-
 
157
                GPS_Parameter.SpeedCompensation = (float) 30;
-
 
158
                GPS_Parameter.MinSat = 6;
-
 
159
                GPS_Parameter.StickThreshold = 8;
-
 
160
                GPS_Parameter.WindCorrection = 0.0;
-
 
161
                GPS_Parameter.OperatingRadius = 0; // forces the aircraft to fly to home positon
-
 
162
 
-
 
163
        }
-
 
164
        else
-
 
165
        {
-
 
166
                // update parameter from FC
-
 
167
                if(StopNavigation) GPS_Parameter.FlightMode = GPS_FLIGHT_MODE_FREE;
-
 
168
                else
-
 
169
                {
-
 
170
                        if(Parameter.NaviGpsModeControl <  50)
-
 
171
                        {
-
 
172
                                if(FlightMode_Old == GPS_FLIGHT_MODE_FREE) SetDelay(SWITCH_DELAY);
-
 
173
                                if(CheckDelay(SwitchDelay))
-
 
174
                                {
-
 
175
                                        GPS_Parameter.FlightMode = GPS_FLIGHT_MODE_FREE;
-
 
176
                                }
-
 
177
                        }
-
 
178
                        else if(Parameter.NaviGpsModeControl < 180)
-
 
179
                        {
-
 
180
                                if(FlightMode_Old == GPS_FLIGHT_MODE_AID) SetDelay(SWITCH_DELAY);
-
 
181
                                if(CheckDelay(SwitchDelay))
-
 
182
                                {
-
 
183
                                        GPS_Parameter.FlightMode = GPS_FLIGHT_MODE_AID;
-
 
184
                                }
-
 
185
                        }
-
 
186
                        else
-
 
187
                        {
-
 
188
                                if(FlightMode_Old == GPS_FLIGHT_MODE_WAYPOINT) SetDelay(SWITCH_DELAY);
-
 
189
                                if(CheckDelay(SwitchDelay))
-
 
190
                                {
-
 
191
                                        GPS_Parameter.FlightMode = GPS_FLIGHT_MODE_WAYPOINT;
-
 
192
                                }
-
 
193
                        }
-
 
194
                }
-
 
195
                GPS_Parameter.Gain      = (float)Parameter.NaviGpsGain;
-
 
196
                GPS_Parameter.P         = (float)Parameter.NaviGpsP;
-
 
197
                GPS_Parameter.I         = (float)Parameter.NaviGpsI;
-
 
198
                GPS_Parameter.D         = (float)Parameter.NaviGpsD;
-
 
199
                GPS_Parameter.A         = (float)Parameter.NaviGpsD;
-
 
200
                GPS_Parameter.ACC       = (float)Parameter.NaviGpsACC;
-
 
201
                GPS_Parameter.P_Limit = (s32)Parameter.NaviGpsPLimit;
-
 
202
                GPS_Parameter.I_Limit = (s32)Parameter.NaviGpsILimit;
-
 
203
                GPS_Parameter.D_Limit = (s32)Parameter.NaviGpsDLimit;
-
 
204
                GPS_Parameter.PID_Limit = 2* (u32)Parameter.NaviAngleLimitation;
-
 
205
                GPS_Parameter.BrakingDuration = (u32)Parameter.NaviPH_LoginTime;
-
 
206
                GPS_Parameter.SpeedCompensation = (float)Parameter.NaviSpeedCompensation;
-
 
207
                GPS_Parameter.MinSat = (u8)Parameter.NaviGpsMinSat;
-
 
208
                GPS_Parameter.StickThreshold = (s8)Parameter.NaviStickThreshold;
-
 
209
                GPS_Parameter.WindCorrection = (float)Parameter.NaviWindCorrection;
-
 
210
                GPS_Parameter.OperatingRadius = (s32)Parameter.NaviOperatingRadius * 100; // conversion of m to cm
-
 
211
        }
-
 
212
        // FlightMode transitions
-
 
213
        if(GPS_Parameter.FlightMode != FlightMode_Old)
-
 
214
        {
-
 
215
                BeepTime = 100; // beep to indicate that mode has been switched
-
 
216
                NCFlags &= ~NC_FLAG_TARGET_REACHED;
-
 
217
                switch(GPS_Parameter.FlightMode)
-
 
218
                {
-
 
219
                        case GPS_FLIGHT_MODE_FREE:
-
 
220
                                NCFlags &= ~(NC_FLAG_PH | NC_FLAG_CH);
-
 
221
                                NCFlags |= NC_FLAG_FREE;
-
 
222
                                if(!StopNavigation && wpclear)
-
 
223
                                {
-
 
224
                                        WPList_Clear(); // clear WPList if mode has changed to Free
-
 
225
                                        wpclear = FALSE;
-
 
226
                                }
-
 
227
                                break;
-
 
228
 
-
 
229
                        case GPS_FLIGHT_MODE_AID:
-
 
230
                                NCFlags &= ~(NC_FLAG_FREE | NC_FLAG_CH);
-
 
231
                                NCFlags |= NC_FLAG_PH;
-
 
232
                                break;
-
 
233
 
-
 
234
                        case GPS_FLIGHT_MODE_WAYPOINT:
-
 
235
                                wpclear = TRUE; // clear WP's only if CH was once active
-
 
236
                                NCFlags &= ~(NC_FLAG_FREE | NC_FLAG_PH);
-
 
237
                                NCFlags |= NC_FLAG_CH;
-
 
238
                                break;
-
 
239
 
-
 
240
                        default: // should never happen
-
 
241
                                NCFlags = 0;
-
 
242
                                break;
-
 
243
                }
-
 
244
                FlightMode_Old = GPS_Parameter.FlightMode;
-
 
245
        }
136
{
Line 246... Line 137...
246
}
137
}
247
 
138
 
248
//-------------------------------------------------------------
139
//-------------------------------------------------------------
249
// This function defines a good GPS signal condition
140
// This function defines a good GPS signal condition
250
u8 GPS_IsSignalOK(void)
-
 
251
{
-
 
252
        if( (GPSData.Status != INVALID) && (GPSData.SatFix == SATFIX_3D) &&  (GPSData.NumOfSats >= GPS_Parameter.MinSat)) return(1);
141
u8 GPS_IsSignalOK(void)
Line 253... Line 142...
253
        else return(0);
142
{
254
}
143
}
255
 
144
 
256
//------------------------------------------------------------
145
//------------------------------------------------------------
257
// Checks for manual control action
-
 
258
u8 GPS_IsManuallyControlled(void)
-
 
259
{
-
 
260
        if( ( (abs(FC.StickNick) > GPS_Parameter.StickThreshold) || (abs(FC.StickRoll) > GPS_Parameter.StickThreshold)) && (GPS_Parameter.StickThreshold > 0) && (FC.RC_Quality > 150) )
-
 
261
        {
-
 
262
                NCFlags |= NC_FLAG_MANUAL_CONTROL;
-
 
263
                return(1);
-
 
264
        }
-
 
265
        else
-
 
266
        {
-
 
267
                NCFlags &= ~NC_FLAG_MANUAL_CONTROL;
146
// Checks for manual control action
Line 268... Line 147...
268
                return(0);
147
u8 GPS_IsManuallyControlled(void)
269
        }
148
{
270
}
149
}
271
 
150
 
272
//------------------------------------------------------------
-
 
273
// copy GPS position from source position to target position
-
 
274
u8 GPS_CopyPosition(GPS_Pos_t * pGPSPosSrc, GPS_Pos_t* pGPSPosTgt)
-
 
275
{
-
 
276
        u8 retval = 0;
-
 
277
        if((pGPSPosSrc == NULL) || (pGPSPosTgt == NULL)) return(retval);        // bad pointer
-
 
278
        // copy only valid positions
-
 
279
        if(pGPSPosSrc->Status != INVALID)
-
 
280
        {
-
 
281
                // if the source GPS position is not invalid
-
 
282
                pGPSPosTgt->Longitude   = pGPSPosSrc->Longitude;
-
 
283
                pGPSPosTgt->Latitude    = pGPSPosSrc->Latitude;
-
 
284
                pGPSPosTgt->Altitude    = pGPSPosSrc->Altitude;
-
 
285
                pGPSPosTgt->Status              = NEWDATA; // mark data in target position as new
151
//------------------------------------------------------------
Line 286... Line 152...
286
                retval = 1;
152
// copy GPS position from source position to target position
287
        }
153
u8 GPS_CopyPosition(GPS_Pos_t * pGPSPosSrc, GPS_Pos_t* pGPSPosTgt)
288
        return(retval);
154
{
289
}
155
}
290
 
-
 
291
//------------------------------------------------------------
-
 
292
// clear position data
-
 
293
u8 GPS_ClearPosition(GPS_Pos_t * pGPSPos)
-
 
294
{
-
 
295
        u8 retval = FALSE;
-
 
296
        if(pGPSPos == NULL) return(retval);     // bad pointer
-
 
297
        else
-
 
298
        {
-
 
299
                pGPSPos->Longitude      = 0;
-
 
300
                pGPSPos->Latitude       = 0;
-
 
301
                pGPSPos->Altitude       = 0;
156
 
Line 302... Line 157...
302
                pGPSPos->Status         = INVALID;
157
//------------------------------------------------------------
303
                retval = TRUE;
158
// clear position data
304
        }
159
u8 GPS_ClearPosition(GPS_Pos_t * pGPSPos)
305
        return (retval);
-
 
306
}
-
 
307
 
-
 
308
 
160
{
Line 309... Line 161...
309
//------------------------------------------------------------
161
}
310
void GPS_Neutral(void)
162
 
311
{
163
 
312
        GPS_Stick.Nick  = 0;
-
 
313
        GPS_Stick.Roll  = 0;
-
 
314
        GPS_Stick.Yaw   = 0;
-
 
315
}
-
 
316
 
-
 
317
//------------------------------------------------------------
-
 
318
void GPS_Init(void)
-
 
319
{
-
 
320
        UART1_PutString("\r\n GPS init...");
-
 
321
        UBX_Init();
-
 
322
        GPS_Neutral();
164
//------------------------------------------------------------
Line 323... Line 165...
323
        GPS_ClearPosition(&GPS_HoldPosition);
165
void GPS_Neutral(void)
324
        GPS_ClearPosition(&GPS_HomePosition);
166
{
325
        GPS_pTargetPosition = NULL;
167
}
326
        WPList_Init();
168
 
327
        GPS_pWaypoint = NULL;
-
 
328
        GPS_UpdateParameter();
-
 
329
        UART1_PutString("ok");
-
 
330
}
-
 
331
 
169
//------------------------------------------------------------
Line 332... Line 170...
332
//------------------------------------------------------------
170
void GPS_Init(void)
333
// calculate the bearing to target position from its deviation
171
{
334
s32 DirectionToTarget_N_E(float northdev, float eastdev)
172
}
335
{
173
 
336
        s32 bearing;
174
//------------------------------------------------------------
337
        bearing = (s32)(atan2(northdev, eastdev) / M_PI_180);
-
 
338
        bearing = (270L - bearing)%360L;
-
 
339
        return(bearing);
-
 
340
}
-
 
341
 
-
 
342
 
-
 
343
//------------------------------------------------------------
-
 
344
// Rescale xy-vector length if length limit is violated
-
 
345
// returns vector len after scaling
-
 
346
s32 GPS_LimitXY(s32 *x, s32 *y, s32 limit)
-
 
347
{
-
 
348
        s32 dist;
175
// calculate the bearing to target position from its deviation
Line 349... Line 176...
349
 
176
s32 DirectionToTarget_N_E(float northdev, float eastdev)
350
        dist = (s32)hypot(*x,*y);       // the length of the vector
177
{
351
        if (dist > limit)
178
}
352
        // if vector length is larger than the given limit
179
 
353
        {       // scale vector compontents so that the length is cut off to limit
-
 
354
                *x = (s32)(( (double)(*x) * (double)limit ) / (double)dist);
180
 
Line 355... Line 181...
355
                *y = (s32)(( (double)(*y) * (double)limit ) / (double)dist);
181
//------------------------------------------------------------
356
                dist = limit;
182
// Rescale xy-vector length if length limit is violated
357
        }
183
// returns vector len after scaling
358
        return(dist);
184
s32 GPS_LimitXY(s32 *x, s32 *y, s32 limit)
359
}
-
 
360
 
185
{
Line 361... Line 186...
361
//------------------------------------------------------------
186
}
362
// transform the integer deg into float radians
187
 
363
inline double RadiansFromGPS(s32 deg)
188
//------------------------------------------------------------
364
{
189
// transform the integer deg into float radians
365
  return ((double)deg * 1e-7f * M_PI_180); // 1E-7 because deg is the value in ° * 1E7
-
 
366
}
-
 
367
 
-
 
368
//------------------------------------------------------------
-
 
369
// transform the integer deg into float deg
-
 
370
inline double DegFromGPS(s32 deg)
-
 
371
{
-
 
372
  return ((double)deg  * 1e-7f); // 1E-7 because deg is the value in ° * 1E7
-
 
373
}
-
 
374
 
-
 
375
//------------------------------------------------------------
-
 
376
// calculate the deviation from the current position to the target position
-
 
377
u8 GPS_CalculateDeviation(GPS_Pos_t * pCurrentPos, GPS_Pos_t * pTargetPos, GPS_Deviation_t* pDeviationFromTarget)
-
 
378
{
-
 
379
        double temp1, temp2;
-
 
380
        // if given pointer is NULL
-
 
381
        if((pCurrentPos == NULL) || (pTargetPos == NULL)) goto baddata;
-
 
382
        // if positions are invalid
-
 
383
        if((pCurrentPos->Status == INVALID) || (pTargetPos->Status == INVALID)) goto baddata;
-
 
384
 
-
 
385
        // The deviation from the current to the target position along north and east direction is
-
 
386
        // simple the lat/lon difference. To convert that angular deviation into an
-
 
387
        // arc length the spherical projection has to be considered.
-
 
388
        // The mean earth radius is 6371km. Therfore the arc length per latitude degree
-
 
389
        // is always 6371km * 2 * Pi / 360deg =  111.2 km/deg.
-
 
390
        // The arc length per longitude degree depends on the correspondig latitude and
-
 
391
        // is 111.2km * cos(latitude).
-
 
392
 
-
 
393
        // calculate the shortest longitude deviation from target
-
 
394
        temp1 = DegFromGPS(pCurrentPos->Longitude) - DegFromGPS(pTargetPos->Longitude);
-
 
395
        // outside an angular difference of -180 deg ... +180 deg its shorter to go the other way around
-
 
396
        // In our application we wont fly more than 20.000 km but along the date line this is important.
-
 
397
        if(temp1 > 180.0f) temp1 -= 360.0f;
-
 
398
        else if (temp1 < -180.0f) temp1 += 360.0f;
-
 
399
        temp1 *= cos((RadiansFromGPS(pTargetPos->Latitude) + RadiansFromGPS(pCurrentPos->Latitude))/2);
-
 
400
        // calculate latitude deviation from target
-
 
401
        // this is allways within -180 deg ... 180 deg
-
 
402
        temp2 = DegFromGPS(pCurrentPos->Latitude) - DegFromGPS(pTargetPos->Latitude);
-
 
403
        // deviation from target position in cm
-
 
404
        // i.e. the distance to walk from the target in northern and eastern direction to reach the current position
-
 
405
 
-
 
406
        pDeviationFromTarget->Status = INVALID;
-
 
407
        pDeviationFromTarget->North = (s32)(11119492.7f * temp2);
-
 
408
        pDeviationFromTarget->East  = (s32)(11119492.7f * temp1);
-
 
409
        // If the position deviation is small enough to neglect the earth curvature
-
 
410
        // (this is for our application always fulfilled) the distance to target
-
 
411
        // can be calculated by the pythagoras of north and east deviation.
-
 
412
        pDeviationFromTarget->Distance = (s32)(11119492.7f * hypot(temp1, temp2));
-
 
413
        if (pDeviationFromTarget->Distance == 0L) pDeviationFromTarget->Bearing = 0L;
-
 
414
        else pDeviationFromTarget->Bearing = DirectionToTarget_N_E(temp2, temp1);
-
 
415
        pDeviationFromTarget->Status = NEWDATA;
-
 
416
        return TRUE;
-
 
417
 
-
 
418
        baddata:
-
 
419
        pDeviationFromTarget->North     = 0L;
-
 
420
        pDeviationFromTarget->East              = 0L;
-
 
421
        pDeviationFromTarget->Distance  = 0L;
-
 
422
        pDeviationFromTarget->Bearing   = 0L;
-
 
423
        pDeviationFromTarget->Status = INVALID;
-
 
424
        return FALSE;
-
 
425
}
-
 
426
 
-
 
427
//------------------------------------------------------------
-
 
428
void GPS_Navigation(void)
-
 
429
{
-
 
430
        static u32 beep_rythm;
-
 
431
        static u32 GPSDataTimeout = 0;
-
 
432
        float compassheading, sin_h, cos_h;
-
 
433
 
-
 
434
        // pointer to current target position
-
 
435
        static GPS_Pos_t * pTargetPositionOld = NULL;
-
 
436
 
-
 
437
        static GPS_Pos_t RangedTargetPosition = {0,0,0, INVALID};               // the limited target position, this is derived from the target position with repect to the operating radius
-
 
438
        static s32 OperatingRadiusOld = -1;
-
 
439
        static u32 WPTime = 0;
-
 
440
 
-
 
441
 
-
 
442
 
-
 
443
        // get current heading from the FC gyro compass heading
-
 
444
        if(abs(FC.StickYaw) > 20 || FromFlightCtrl.GyroHeading > 3600) compassheading = (float)I2C_Heading.Heading * M_PI_180;
-
 
445
        else compassheading = ((float)FromFlightCtrl.GyroHeading * M_PI_180) / 10.0;
-
 
446
 
-
 
447
        sin_h = sin(compassheading);
-
 
448
        cos_h = cos(compassheading);
-
 
449
 
-
 
450
 
-
 
451
        //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-
 
452
        //+ Check for new data from GPS-receiver
-
 
453
        //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-
 
454
        switch(GPSData.Status)
-
 
455
        {
-
 
456
                case INVALID: // no gps data available
-
 
457
                        // do nothing
-
 
458
                        GPS_Parameter.PID_Limit = 0; // disables PID output
-
 
459
                        break;
-
 
460
 
-
 
461
                case PROCESSED: // the current data have been allready processed
-
 
462
                        // if no new data are available within the timeout switch to invalid state.
-
 
463
                        if(CheckDelay(GPSDataTimeout)) GPSData.Status = INVALID;
-
 
464
                        // wait for new gps data
-
 
465
                        break;
-
 
466
 
-
 
467
                case NEWDATA: // handle new gps data
-
 
468
 
-
 
469
                // update GPS Parameter from FC-Data via SPI interface
-
 
470
                GPS_UpdateParameter();
-
 
471
 
-
 
472
                        // wait maximum of 3 times the normal data update time before data timemout
-
 
473
                        GPSDataTimeout = SetDelay(3 * GPS_UPDATETIME_MS);
-
 
474
                        beep_rythm++;
-
 
475
 
-
 
476
                        // debug
-
 
477
                        DebugOut.Analog[21] = (s16)GPSData.Speed_North;
-
 
478
                        DebugOut.Analog[22] = (s16)GPSData.Speed_East;
-
 
479
                        DebugOut.Analog[31] = (s16)GPSData.NumOfSats;
-
 
480
 
-
 
481
                        // If GPS signal condition is sufficient for a reliable position measurement
-
 
482
                        if(GPS_IsSignalOK())
-
 
483
                        {
-
 
484
                                // update home deviation info
-
 
485
                                GPS_CalculateDeviation(&(GPSData.Position), &GPS_HomePosition, &CurrentHomeDeviation);
-
 
486
 
-
 
487
                                // if the MK is starting or the home position is invalid then store the home position
-
 
488
                                if((FC.MKFlags & MKFLAG_START) || (GPS_HomePosition.Status == INVALID))
-
 
489
                                {       // try to update the home position from the current position
-
 
490
                                        if(GPS_CopyPosition(&(GPSData.Position), &GPS_HomePosition))
-
 
491
                                        {
-
 
492
                                                BeepTime = 700; // beep on success
-
 
493
                                                GPS_CopyPosition(&GPS_HomePosition, &(NaviData.HomePosition));
-
 
494
                                        }
-
 
495
                                        GPS_pWaypoint = WPList_Begin(); // go to start of waypoint list, return NULL of the list is empty
-
 
496
                                        if(GPS_pWaypoint != NULL) // if new WP exist
-
 
497
                                        {   // update WP hold time stamp immediately!
-
 
498
                                                WPTime = SetDelay(GPS_pWaypoint->HoldTime * 1000); // update hold time stamp
-
 
499
                                                NCFlags &= ~NC_FLAG_TARGET_REACHED;
-
 
500
                                        }
-
 
501
                                }
-
 
502
 
-
 
503
                                /* The selected flight mode influences the target position pointer and therefore the behavior */
-
 
504
 
-
 
505
                                // check for current flight mode and set the target pointer GPS_pTargetPosition respectively
-
 
506
                                switch(GPS_Parameter.FlightMode)
-
 
507
                                {
-
 
508
                                        // the GPS control is deactived
-
 
509
                                        case GPS_FLIGHT_MODE_FREE:
-
 
510
 
-
 
511
                                                GPS_Parameter.PID_Limit = 0; // disables PID output
-
 
512
                                                // update hold position
-
 
513
                                                GPS_CopyPosition(&(GPSData.Position), &GPS_HoldPosition);
-
 
514
                                                // no target position
-
 
515
                                                GPS_pTargetPosition = NULL;
-
 
516
                                                GPS_TargetRadius = 0;
-
 
517
                                                break;
-
 
518
 
-
 
519
                                        // the GPS supports the position hold, if the pilot takes no action
-
 
520
                                        case GPS_FLIGHT_MODE_AID:
-
 
521
 
-
 
522
                                                if(GPS_IsManuallyControlled())
-
 
523
                                                {
-
 
524
                                                        GPS_Parameter.PID_Limit = 0; // disables PID output, as long as the manual conrol is active
-
 
525
                                                        GPS_CopyPosition(&(GPSData.Position), &GPS_HoldPosition);
-
 
526
                                                        GPS_pTargetPosition = NULL;
-
 
527
                                                        GPS_TargetRadius = 0;
-
 
528
                                                }
-
 
529
                                                else
-
 
530
                                                {
-
 
531
                                                        /*
-
 
532
                                                        #define PH_MOVE_THRESHOLD 8
-
 
533
                                                        if( ((abs(FC.StickNick) > PH_MOVE_THRESHOLD) || (abs(FC.StickRoll) > PH_MOVE_THRESHOLD) ) && (FC.RC_Quality > 150))
-
 
534
                                                        {   // indirect control by moving the hold position with rc sticks
-
 
535
                                                                // rc sticks have a range of +/-127 counts
-
 
536
                                                                // GPS Coordinates are in 1-E7 deg, i.e. 1 counts is 1E-7°/360°*40E+8cm = 1.11 cm
-
 
537
                                                                // normal manual activtion threshold is 8 counts that results in a change of the hold position
-
 
538
                                                                // of min 8*1.11cm * 5Hz = 8.88 = 44.4cm/s an max 127*1.11cm *5Hz = 705cm/s
-
 
539
                                                                GPS_HoldPosition.Latitude +=  (s32)(cos_h*FC.StickNick + sin_h*FC.StickRoll);
-
 
540
                                                                GPS_HoldPosition.Longitude +=  (s32)((sin_h*FC.StickNick - cos_h*FC.StickRoll) / cos(RadiansFromGPS(GPS_HoldPosition.Latitude)) );
-
 
541
                                                        }*/
-
 
542
                                                        // set target position
-
 
543
                                                        GPS_pTargetPosition = &GPS_HoldPosition;
-
 
544
                                                        GPS_TargetRadius = 100; // 1 meter
-
 
545
                                                }
-
 
546
                                                break;
-
 
547
 
-
 
548
                                        // the GPS control is directed to a target position
-
 
549
                                        // given by a waypoint or by the home position
-
 
550
                                        case GPS_FLIGHT_MODE_WAYPOINT:
-
 
551
 
-
 
552
                                                if(GPS_IsManuallyControlled()) // the human pilot takes the action
-
 
553
                                                {
-
 
554
                                                        GPS_Parameter.PID_Limit = 0; // disables PID output, as long as the manual conrol is active
-
 
555
                                                    GPS_CopyPosition(&(GPSData.Position), &GPS_HoldPosition);  // update hold position
-
 
556
                                                        GPS_pTargetPosition = NULL;     // set target position invalid
-
 
557
                                                        GPS_TargetRadius = 0;
-
 
558
                                                }
-
 
559
                                                else // no manual control  -> gps position hold active
-
 
560
                                                {
-
 
561
                                                        // waypoint trigger logic
-
 
562
                                                        if(GPS_pWaypoint != NULL) // pointer to waypoint exist
-
 
563
                                                        {
-
 
564
                                                                if(GPS_pWaypoint->Position.Status == INVALID) // should never happen
-
 
565
                                                                {
-
 
566
                                                                        GPS_pWaypoint = WPList_Next(); // goto to next WP
-
 
567
                                                                        if(GPS_pWaypoint != NULL) // if new WP exist
-
 
568
                                                                        {   // update WP hold time stamp immediately!
-
 
569
                                                                                WPTime = SetDelay(GPS_pWaypoint->HoldTime * 1000); // update hold time stamp
-
 
570
                                                                                NCFlags &= ~NC_FLAG_TARGET_REACHED;
-
 
571
                                                                        }
-
 
572
                                                                        BeepTime = 255;
-
 
573
                                                                }
-
 
574
                                                                else // waypoint position is valid
-
 
575
                                                                {
-
 
576
                                                                        // if WP has been reached once, wait hold time before trigger to next one
-
 
577
                                                                        if(NCFlags & NC_FLAG_TARGET_REACHED)
-
 
578
                                                                        {
-
 
579
                                                                                /* ToDo: Adjust GPS_pWaypoint->Heading, GPS_pWaypoint->Event handling */
-
 
580
                                                                                if(CheckDelay(WPTime))
-
 
581
                                                                                {
-
 
582
                                                                                        GPS_pWaypoint = WPList_Next(); // goto to next waypoint, return NULL if end of list has been reached
-
 
583
                                                                                        if(GPS_pWaypoint == NULL) GPS_pWaypoint = WPList_End(); // goto last WP if next one not exist
-
 
584
                                                                                        if(GPS_pWaypoint != NULL) // if new WP exist
-
 
585
                                                                                        {   // update WP hold time stamp immediately!
-
 
586
                                                                                                WPTime = SetDelay(GPS_pWaypoint->HoldTime * 1000); // update hold time stamp
-
 
587
                                                                                                NCFlags &= ~NC_FLAG_TARGET_REACHED;
-
 
588
                                                                                        }
-
 
589
                                                                                }
-
 
590
                                                                        } // EOF target reached
-
 
591
                                                                        else
-
 
592
                                                                        {
-
 
593
                                                                                WPTime = SetDelay(GPS_pWaypoint->HoldTime * 1000); // set hold time stamp
-
 
594
                                                                        }
-
 
595
                                                                }
-
 
596
                                                        }
-
 
597
                                                        else // pointer to waypoint does not exist
-
 
598
                                                        {
-
 
599
                                                                // try to catch the first waypoint from the list
-
 
600
                                                                GPS_pWaypoint = WPList_Begin();
-
 
601
                                                                if(GPS_pWaypoint != NULL) // if new WP exist
-
 
602
                                                                {   // update WP hold time stamp immediately!
-
 
603
                                                                        WPTime = SetDelay(GPS_pWaypoint->HoldTime * 1000); // update hold time stamp
-
 
604
                                                                        NCFlags &= ~NC_FLAG_TARGET_REACHED;
-
 
605
                                                                }
-
 
606
                                                        }
-
 
607
                                                        // EOF waypoint trigger logic
-
 
608
 
-
 
609
                                                        if(GPS_pWaypoint != NULL) // Waypoint exist
-
 
610
                                                        {
-
 
611
                                                                // possible new data have been put into wp-list
-
 
612
                                                                if(GPS_pWaypoint->Position.Status == NEWDATA)
-
 
613
                                                                {
-
 
614
                                                                        WPTime = SetDelay(GPS_pWaypoint->HoldTime * 1000); // update hold time stamp
-
 
615
                                                                        NCFlags &= ~NC_FLAG_TARGET_REACHED;
-
 
616
                                                                }
-
 
617
                                                                // update the hold position
-
 
618
                                                                GPS_CopyPosition(&(GPSData.Position), &GPS_HoldPosition);
-
 
619
                                                                // set target to the waypoint
-
 
620
                                                                GPS_pTargetPosition = &(GPS_pWaypoint->Position);
-
 
621
                                                                // update target radius
-
 
622
                                                                GPS_TargetRadius = (s32)(GPS_pWaypoint->ToleranceRadius) * 100L;
-
 
623
 
-
 
624
                                                        }
-
 
625
                                                        else // no waypoint info available, i.e. the WPList is empty or the end of the list has been reached
-
 
626
                                                        {
-
 
627
                                                                // fly back to home postion
-
 
628
                                                                if(GPS_HomePosition.Status == INVALID)
-
 
629
                                                                {
-
 
630
                                                                        GPS_pTargetPosition = &GPS_HoldPosition; // fall back to hold mode if home position is not available
-
 
631
                                                                        GPS_TargetRadius = 100;
-
 
632
                                                                        BeepTime = 255; // beep to indicate missin home position
-
 
633
                                                                }
-
 
634
                                                                else // the home position is valid
-
 
635
                                                                {
-
 
636
                                                                        // update the hold position
-
 
637
                                                                        GPS_CopyPosition(&(GPSData.Position), &GPS_HoldPosition);
-
 
638
                                                                        // set target to home position
-
 
639
                                                                        GPS_pTargetPosition = &GPS_HomePosition;
-
 
640
                                                                        GPS_TargetRadius = 100;
-
 
641
                                                                }
-
 
642
                                                        }
-
 
643
                                                } // EOF no manual control
-
 
644
                                                break;
-
 
645
 
-
 
646
                                        case GPS_FLIGHT_MODE_UNDEF:
-
 
647
                                        default:
-
 
648
                                                GPS_Parameter.PID_Limit = 0; // disables PID output
-
 
649
                                                // update hold position
-
 
650
                                                GPS_CopyPosition(&(GPSData.Position), &GPS_HoldPosition);
-
 
651
                                                // no target position
-
 
652
                                                GPS_pTargetPosition = NULL;
-
 
653
                                                GPS_TargetRadius = 0;
-
 
654
                                                break;
-
 
655
 
-
 
656
                                }// EOF GPS Mode Handling
-
 
657
 
-
 
658
 
-
 
659
                                /* Calculation of range target based on the real target */
-
 
660
 
-
 
661
                                // if no target position exist clear the ranged target position
-
 
662
                                if(GPS_pTargetPosition == NULL) GPS_ClearPosition(&RangedTargetPosition);
-
 
663
                                else
-
 
664
                                {       // if the target position has been changed or the value has been updated or the OperatingRadius has changed
-
 
665
                                        if((GPS_pTargetPosition != pTargetPositionOld)  || (GPS_pTargetPosition->Status == NEWDATA) || (GPS_Parameter.OperatingRadius != OperatingRadiusOld) )
-
 
666
                                        {
-
 
667
                                                BeepTime = 255; // beep to indicate setting of a new target position
-
 
668
                                                NCFlags &= ~NC_FLAG_TARGET_REACHED;     // clear target reached flag
-
 
669
                                                // calculate deviation of new target position from home position
-
 
670
                                                if(GPS_CalculateDeviation(GPS_pTargetPosition, &GPS_HomePosition, &TargetHomeDeviation))
-
 
671
                                                {
-
 
672
                                                        // check distance from home position
-
 
673
                                                        if(TargetHomeDeviation.Distance > GPS_Parameter.OperatingRadius)
-
 
674
                                                        {
-
 
675
                                                                //calculate ranged target position to be within the operation radius area
-
 
676
                                                                NCFlags |= NC_FLAG_RANGE_LIMIT;
-
 
677
 
-
 
678
                                                                TargetHomeDeviation.North = (s32)(((float)TargetHomeDeviation.North * (float)GPS_Parameter.OperatingRadius) / (float)TargetHomeDeviation.Distance);
-
 
679
                                                                TargetHomeDeviation.East = (s32)(((float)TargetHomeDeviation.East * (float)GPS_Parameter.OperatingRadius) / (float)TargetHomeDeviation.Distance);
-
 
680
                                                                TargetHomeDeviation.Distance = GPS_Parameter.OperatingRadius;
-
 
681
 
-
 
682
                                                                RangedTargetPosition.Status = INVALID;
-
 
683
                                                                RangedTargetPosition.Latitude = GPS_HomePosition.Latitude;
-
 
684
                                                                RangedTargetPosition.Latitude += (s32)((float)TargetHomeDeviation.North / 1.11194927f);
-
 
685
                                                                RangedTargetPosition.Longitude = GPS_HomePosition.Longitude;
-
 
686
                                                                RangedTargetPosition.Longitude += (s32)((float)TargetHomeDeviation.East / (1.11194927f * cos(RadiansFromGPS(GPS_HomePosition.Latitude))) );
-
 
687
                                                                RangedTargetPosition.Altitude = GPS_pTargetPosition->Altitude;
-
 
688
                                                                RangedTargetPosition.Status = NEWDATA;
-
 
689
                                                        }
-
 
690
                                                        else
-
 
691
                                                        {       // the target is located within the operation radius area
-
 
692
                                                                // simple copy the loaction to the ranged target position
-
 
693
                                                                GPS_CopyPosition(GPS_pTargetPosition, &RangedTargetPosition);
-
 
694
                                                                NCFlags &= ~NC_FLAG_RANGE_LIMIT;
-
 
695
                                                        }
-
 
696
                                                }
-
 
697
                                                else
-
 
698
                                                {       // deviation could not be determined
-
 
699
                                                        GPS_ClearPosition(&RangedTargetPosition);
-
 
700
                                                }
-
 
701
                                                GPS_pTargetPosition->Status = PROCESSED;        // mark current target as processed!
-
 
702
                                        }
-
 
703
                                }
-
 
704
                                OperatingRadiusOld = GPS_Parameter.OperatingRadius;
-
 
705
                                // remember last target position pointer
-
 
706
                                pTargetPositionOld = GPS_pTargetPosition;
-
 
707
 
-
 
708
                                /* Calculate position deviation from ranged target */
-
 
709
 
-
 
710
                                // calculate deviation of current position to ranged target position in cm
-
 
711
                                if(GPS_CalculateDeviation(&(GPSData.Position), &RangedTargetPosition, &CurrentTargetDeviation))
-
 
712
                                {       // set target reached flag of we once reached the target point
-
 
713
                                        if(!(NCFlags & NC_FLAG_TARGET_REACHED) && (CurrentTargetDeviation.Distance < GPS_TargetRadius))
-
 
714
                                        {
-
 
715
                                                NCFlags |= NC_FLAG_TARGET_REACHED;      // set target reached flag
-
 
716
                                        }
-
 
717
                                        // implement your control code here based
-
 
718
                                        // in the info available in the CurrentTargetDeviation, GPSData and FromFlightCtrl.GyroHeading
-
 
719
                                        GPS_Stick.Nick = 0;
-
 
720
                                        GPS_Stick.Roll = 0;
-
 
721
                                        GPS_Stick.Yaw  = 0;
-
 
722
                                }
-
 
723
                                else // deviation could not be calculated
-
 
724
                                {   // do nothing on gps sticks!
-
 
725
                                        GPS_Neutral();
-
 
726
                                        NCFlags &= ~NC_FLAG_TARGET_REACHED;     // clear target reached
-
 
727
                                }
-
 
728
 
-
 
729
                        }// eof if GPSSignal is OK
-
 
730
                        else // GPSSignal not OK
-
 
731
                        {
-
 
732
                                GPS_Neutral();
-
 
733
                                // beep if signal is not sufficient
-
 
734
                                if(GPS_Parameter.FlightMode != GPS_FLIGHT_MODE_FREE)
-
 
735
                                {
-
 
736
                                        if(!(GPSData.Flags & FLAG_GPSFIXOK) && !(beep_rythm % 5)) BeepTime = 100;
-
 
737
                                        else if (GPSData.NumOfSats < GPS_Parameter.MinSat && !(beep_rythm % 5)) BeepTime = 10;
-
 
738
                                }
-
 
739
                        }
-
 
740
                        GPSData.Status = PROCESSED; // mark as processed
-
 
741
                        break;
-
 
742
        }
-
 
743
 
-
 
744
        DebugOut.Analog[6] = NCFlags;
-
 
745
        DebugOut.Analog[27] = (s16)CurrentTargetDeviation.North;
-
 
746
        DebugOut.Analog[28] = (s16)CurrentTargetDeviation.East;
-
 
747
        DebugOut.Analog[29] = GPS_Stick.Nick;
-
 
748
        DebugOut.Analog[30] = GPS_Stick.Roll;
-
 
749
 
-
 
750
        // update navi data, send back to ground station
-
 
751
        GPS_CopyPosition(&(GPSData.Position),   &(NaviData.CurrentPosition));
-
 
752
        GPS_CopyPosition(&RangedTargetPosition, &(NaviData.TargetPosition));
-
 
753
        GPS_CopyPosition(&GPS_HomePosition,     &(NaviData.HomePosition));
-
 
754
        NaviData.SatsInUse = GPSData.NumOfSats;
-
 
755
        NaviData.TargetPositionDeviation.Distance = (u16)CurrentTargetDeviation.Distance/10; // dm
-
 
756
        NaviData.TargetPositionDeviation.Bearing  = (s16)CurrentTargetDeviation.Bearing;
-
 
757
        NaviData.HomePositionDeviation.Distance   = (u16)CurrentHomeDeviation.Distance/10; // dm
-
 
758
        NaviData.HomePositionDeviation.Bearing    = (s16)CurrentHomeDeviation.Bearing;
-
 
759
        NaviData.UBat = FC.UBat;
190
inline double RadiansFromGPS(s32 deg)
760
        NaviData.GroundSpeed = (u16)GPSData.Speed_Ground;
191
{