Subversion Repositories FlightCtrl

Rev

Rev 1002 | Rev 1039 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
1003 salvo 1
/*
2
This program (files gps.c and gps.h) is free software; you can redistribute it and/or modify
3
it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation;
4
either version 3 of the License, or (at your option) any later version.  
5
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
6
without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
7
GNU General Public License and GNU Lesser General Public License for more details.
8
You should have received a copy of GNU General Public License (License_GPL.txt)  and
9
GNU Lesser General Public License (License_LGPL.txt) along with this program.
10
If not, see <http://www.gnu.org/licenses/>.
11
 
12
Please note: All the other files for the project "Mikrokopter" by H.Buss are under the license (license_buss.txt) published by www.mikrokopter.de
13
*/
14
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
15
von Peter Muehlenbrock alias Salvo
16
Auswertung der Daten vom GPS im ublox Format
17
Hold Modus mit PID Regler
18
Rückstuerz zur Basis Funktion
19
Umstellung auf NaviParameter an Flight Version 00.70d
20
GPS_V durch gps_gain ersetzt, damit Einstellung durch MK Tool möglich wird
21
Stand 10.10.2008
22
 
23
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
24
*/
1 ingob 25
#include "main.h"
1003 salvo 26
#include "math.h"
27
//#include "gps.h"
1 ingob 28
 
1003 salvo 29
// Defines fuer ublox Messageformat um Auswertung zu steuern
30
#define                 UBLOX_IDLE      0
31
#define                 UBLOX_SYNC1     1
32
#define                 UBLOX_SYNC2     2
33
#define                 UBLOX_CLASS     3
34
#define                 UBLOX_ID        4
35
#define                 UBLOX_LEN1      5
36
#define                 UBLOX_LEN2      6
37
#define                 UBLOX_CKA       7
38
#define                 UBLOX_CKB       8
39
#define                 UBLOX_PAYLOAD   9
40
 
41
// ublox Protokoll Identifier 
42
#define                 UBLOX_NAV_POSUTM        0x08
43
#define                 UBLOX_NAV_STATUS        0x03
44
#define                 UBLOX_NAV_VELED         0x12
45
#define                 UBLOX_NAV_CLASS         0x01
46
#define                 UBLOX_SYNCH1_CHAR       0xB5
47
#define                 UBLOX_SYNCH2_CHAR       0x62
48
 
49
signed int              GPS_Nick = 0;
50
signed int              GPS_Roll = 0;
51
signed int              GPS_Nick2 = 0;
52
signed int              GPS_Roll2 = 0;
53
short int               ublox_msg_state = UBLOX_IDLE;
54
static                  uint8_t chk_a =0; //Checksum
55
static                  uint8_t chk_b =0;
56
short int               gps_state,gps_sub_state; //Zustaende der Statemachine
57
short int               gps_updte_flag;
58
static long signed  gps_reg_x,gps_reg_y;                               
59
static unsigned int rx_len;
60
static unsigned int ptr_payload_data_end;
61
unsigned int            gps_alive_cnt; // Wird bei jedem gueltigen GPS Telegramm hochgezaehlt
62
static signed int       hdng_2home,dist_2home; //Richtung und Entfernung zur home Position 
63
static signed           gps_tick; //wird bei jedem Update durch das GPS Modul hochgezaehlt 
64
static                  short int hold_fast,hold_reset_int; //Flags fuer Hold Regler
65
static                  uint8_t *ptr_payload_data;
66
static                  uint8_t *ptr_pac_status;
67
static  int             dist_flown;
68
//static unsigned int   int_ovfl_cnt; // Zaehler fuer Overflows des Integrators
69
static  int             gps_quiet_cnt; //  Zaehler fuer GPS Off Time beim Kameraausloesen
70
static  int             gps_gain;          //  // Teilerfaktor Regelabweichung zu Ausgabewert
71
 
72
 
73
short int Get_GPS_data(void);
74
 
75
NAV_POSUTM_t actual_pos;    // Aktuelle Nav Daten werden hier im ublox Format abgelegt
76
NAV_STATUS_t actual_status; // Aktueller Nav Status
77
NAV_VELNED_t actual_speed;  // Aktueller Geschwindigkeits und Richtungsdaten
78
 
79
GPS_ABS_POSITION_t              gps_act_position;               // Alle wichtigen Daten zusammengefasst
80
GPS_ABS_POSITION_t              gps_home_position;      // Die Startposition, beim Kalibrieren ermittelt
81
GPS_REL_POSITION_t              gps_rel_act_position;   // Die aktuelle relative Position bezogen auf Home Position
82
GPS_REL_POSITION_t              gps_rel_hold_position;  // Die gespeicherte Sollposition fuer GPS_ Hold Mode
83
GPS_REL_POSITION_t              gps_rel_start_position; // Die gespeicherte Ausgangsposition fuer GPS_ Home Mode
84
 
85
// Initialisierung
1 ingob 86
void GPS_Neutral(void)
87
{
1003 salvo 88
        ublox_msg_state                 =       UBLOX_IDLE;
89
        gps_state                               =       GPS_CRTL_IDLE;
90
        gps_sub_state                   =       GPS_CRTL_IDLE;
91
        actual_pos.status               =       0;
92
        actual_speed.status             =       0;
93
        actual_status.status            =       0;
94
        gps_home_position.status        =       0; // Noch keine gueltige Home Position
95
        gps_act_position.status         =       0;
96
        gps_rel_act_position.status     =       0;     
97
        GPS_Nick                        =       0;
98
        GPS_Roll                        =       0;
99
        gps_updte_flag                  =       0;
100
        gps_alive_cnt                   =       0;
101
 
1 ingob 102
}
103
 
1003 salvo 104
// Home Position sichern falls Daten verfuegbar sind. 
105
void GPS_Save_Home(void)
1 ingob 106
{
1003 salvo 107
        short int n;
108
        n = Get_GPS_data();
109
        if (n == 0)   // Gueltige  und aktuelle Daten ?   
110
        {
111
                // Neue GPS Daten liegen vor
112
                gps_home_position.utm_east      = gps_act_position.utm_east;   
113
                gps_home_position.utm_north     = gps_act_position.utm_north;  
114
                gps_home_position.utm_alt       = gps_act_position.utm_alt;
115
                gps_home_position.status        = 1; // Home Position gueltig                   
116
        }
1 ingob 117
}
118
 
1003 salvo 119
// Relative Position zur Home Position bestimmen
120
// Rueckgabewert 0= Daten sind aktuell und gueltig. 1= Keine Aenderung. 2= Daten ungueltig
121
short int Get_Rel_Position(void)
122
{
123
        short int n = 0;
124
        n = Get_GPS_data();
125
        if (n >=1) return (n); // nix zu tun, weil keine neue Daten da sind
126
        if (gps_alive_cnt < 1000) gps_alive_cnt += 600; // Timeoutzaehler. Wird in Motorregler Routine ueberwacht und dekrementiert
127
        if  (gps_home_position.status > 0) //Nur wenn Home Position vorliegt
128
        {
129
                gps_rel_act_position.utm_east   = (int)  (gps_act_position.utm_east - gps_home_position.utm_east);
130
                gps_rel_act_position.utm_north  = (int)  (gps_act_position.utm_north - gps_home_position.utm_north);
131
                gps_rel_act_position.utm_alt    = (int)  (gps_act_position.utm_alt - gps_home_position.utm_alt);
132
                gps_rel_act_position.status     = 1; // gueltige Positionsdaten
133
                n = 0;
134
                gps_updte_flag = 1; // zeigt an, dass neue Daten vorliegen.
135
        }
136
        else
137
        {
138
                n = 2; //keine gueltigen Daten vorhanden
139
                gps_rel_act_position.status = 0; //keine gueltige Position weil keine home Position da ist.
140
        }      
141
        return (n);
142
}
1 ingob 143
 
1003 salvo 144
// Daten aus aktuellen ublox Messages extrahieren 
145
// Rueckgabewert 0= Daten sind aktuell und gueltig. 1= Keine Aenderung. 2= Daten ungueltig
146
short int Get_GPS_data(void)
147
{
148
        short int n = 1;
1 ingob 149
 
1003 salvo 150
        if (actual_pos.status == 0) return (1); //damit es schnell geht, wenn nix zu tun ist
151
        gps_gain        =       Parameter_NaviGpsGain*8/100; //maximal Wert ist 20
152
//      debug_gp_0      = (int)gps_gain;  // zum Debuggen
1 ingob 153
 
1003 salvo 154
        if ((actual_pos.status > 0) && (actual_status.status > 0) && (actual_speed.status > 0))
155
        {
156
                if (((actual_status.gpsfix_type & 0x03) >=2) && ((actual_status.nav_status_flag & 0x01) >=1)) // nur wenn Daten aktuell und gueltig sind
157
                {
158
                        actual_status.status            = 0;
159
                        gps_act_position.utm_east       = actual_pos.utm_east/10;
160
                        gps_act_position.utm_north      = actual_pos.utm_north/10;
161
                        gps_act_position.utm_alt        = actual_pos.utm_alt/10;
162
                        actual_pos.status                       = 0; //neue ublox Messages anfordern
163
                        gps_act_position.speed_gnd      = actual_speed.speed_gnd;
164
                        gps_act_position.speed_gnd      = actual_speed.speed_gnd;
165
                        gps_act_position.heading        = actual_speed.heading/100000;
166
                        actual_speed.status             = 0;
167
                        gps_act_position.status         = 1;
168
                        n                                                       = 0; //Daten gueltig
169
                }
170
                else
171
                {
172
                        gps_act_position.status = 0; //Keine gueltigen Daten
173
                        actual_speed.status             = 0;
174
                        actual_status.status    = 0;
175
                        actual_pos.status               = 0; //neue ublox Messages anfordern
176
                        n                                               = 2;
177
                }
178
        }      
179
        return (n);    
180
}
181
 
182
/*
183
Daten vom GPS im ublox MSG Format auswerten
184
Die Routine wird bei jedem Empfang eines Zeichens vom GPS Modul durch den UART IRQ aufgerufen
185
// Die UBX Messages NAV_POSUTM, NAV_STATUS und NAV_VALED muessen aktiviert sein
186
*/
187
void Get_Ublox_Msg(uint8_t rx)
188
{
189
        switch (ublox_msg_state)
190
        {
191
 
192
                case UBLOX_IDLE: // Zuerst Synchcharacters pruefen
193
                        if ( rx == UBLOX_SYNCH1_CHAR ) ublox_msg_state = UBLOX_SYNC1;
194
                        else ublox_msg_state = UBLOX_IDLE;
195
                        break;
196
 
197
                case UBLOX_SYNC1:
198
 
199
                        if (rx == UBLOX_SYNCH2_CHAR) ublox_msg_state = UBLOX_SYNC2;
200
                        else ublox_msg_state = UBLOX_IDLE;
201
                        chk_a = 0,chk_b = 0;
202
                        break;
203
 
204
                case UBLOX_SYNC2:
205
                        if (rx == UBLOX_NAV_CLASS) ublox_msg_state = UBLOX_CLASS;      
206
                        else ublox_msg_state = UBLOX_IDLE;
207
                        break;
208
 
209
                case UBLOX_CLASS: // Nur NAV Meldungen auswerten
210
                        switch (rx)
211
                        {
212
                                case UBLOX_NAV_POSUTM:
213
                                        ptr_pac_status  =       &actual_pos.status;
214
                                        if (*ptr_pac_status > 0) ublox_msg_state = UBLOX_IDLE; //Abbruch weil Daten noch nicht verwendet wurden
215
                                        else
216
                                        {
217
                                                ptr_payload_data                = &actual_pos;
218
                                                ptr_payload_data_end    = &actual_pos.status;
219
                                                ublox_msg_state                 = UBLOX_LEN1;
220
                                        }
221
                                        break;
222
 
223
                                case UBLOX_NAV_STATUS:
224
                                        ptr_pac_status  =       &actual_status.status;
225
                                        if (*ptr_pac_status > 0) ublox_msg_state = UBLOX_IDLE;
226
                                        else
227
                                        {
228
                                                ptr_payload_data        = &actual_status;
229
                                                ptr_payload_data_end    = &actual_status.status;
230
                                                ublox_msg_state         = UBLOX_LEN1;
231
                                        }
232
                                        break;
233
 
234
                                case UBLOX_NAV_VELED:
235
                                        ptr_pac_status          =       &actual_speed.status;
236
                                        if (*ptr_pac_status > 0) ublox_msg_state = UBLOX_IDLE;
237
                                        else
238
                                        {
239
                                                ptr_payload_data        = &actual_speed;
240
                                                ptr_payload_data_end    = &actual_speed.status;
241
                                                ublox_msg_state         = UBLOX_LEN1;
242
                                        }
243
                                        break;
244
 
245
                                default:
246
                                        ublox_msg_state = UBLOX_IDLE;
247
                                        break; 
248
                        }
249
                        chk_a   = UBLOX_NAV_CLASS + rx;
250
                        chk_b   = UBLOX_NAV_CLASS + chk_a;                     
251
                        break;
252
 
253
                case UBLOX_LEN1: // Laenge auswerten
254
                        rx_len  = rx;
255
                        chk_a   += rx;
256
                        chk_b   += chk_a;              
257
                        ublox_msg_state = UBLOX_LEN2;
258
                        break;
259
 
260
 
261
                case UBLOX_LEN2: // Laenge auswerten
262
                        rx_len = rx_len + (rx *256); // Laenge ermitteln
263
                        chk_a   += rx;
264
                        chk_b   += chk_a;      
265
                        ublox_msg_state = UBLOX_PAYLOAD;
266
                        break;
267
 
268
                case UBLOX_PAYLOAD: // jetzt Nutzdaten einlesen
269
                        if (rx_len > 0)
270
                        {
271
                                *ptr_payload_data = rx;
272
                                chk_a   += rx;
273
                                chk_b   += chk_a;
274
                                --rx_len;      
275
                                if ((rx_len > 0) && (ptr_payload_data <= ptr_payload_data_end))                          
276
                                {
277
                                        ptr_payload_data++;
278
                                        ublox_msg_state = UBLOX_PAYLOAD;
279
                            }
280
                                else ublox_msg_state = UBLOX_CKA;
281
                        }      
282
                        else ublox_msg_state = UBLOX_IDLE; // Abbruch wegen Fehler
283
                        break;
284
 
285
                case UBLOX_CKA: // Checksum pruefen
286
                        if (rx == chk_a) ublox_msg_state = UBLOX_CKB;                          
287
                        else ublox_msg_state = UBLOX_IDLE; // Abbruch wegen Fehler
288
                        break;
289
 
290
                case UBLOX_CKB: // Checksum pruefen
291
                        if (rx == chk_b) *ptr_pac_status = 1; // Paket ok
292
                        ublox_msg_state    = UBLOX_IDLE;
293
                        break;
294
 
295
                default:
296
                        ublox_msg_state = UBLOX_IDLE;          
297
                        break;
298
        }
299
}
300
 
301
//Zentrale Statemachine fuer alle GPS relevanten Regelungsablauefe
302
short int GPS_CRTL(short int cmd)
303
{
304
        static unsigned int cnt;                                                // Zaehler fuer diverse Verzoegerungen 
305
        static long int         delta_north,delta_east;         // Mass fuer Distanz zur Sollposition
306
        signed int              n;
307
        static signed int       gps_g2t_act_v; // Aktuelle Geschwindigkeitsvorgabe fuer Home Funktion
308
        signed int              dist_frm_start_east,dist_frm_start_north;
309
        int                     amplfy_speed_east,amplfy_speed_north; //Verstaerkungsfaktoren fuer D-Anteil 
310
        static signed int       int_east,int_north;     //Integrierer 
311
        long int                speed_east,speed_north; //Aktuelle Geschwindigkeit 
312
        signed long             int_east1,int_north1;
313
        int                     dist_east,dist_north;
314
        int                     diff_p;                 //Vom Modus abhaengige zusaetzliche Verstaerkung
315
        long                    ni,ro;                  // Nick und Roll Zwischenwerte
316
 
317
 
318
        switch (cmd)
319
        {
320
 
321
                case GPS_CMD_REQ_HOME: // Es soll zum Startpunkt zurueckgeflogen werden. 
322
                        if ((gps_state != GPS_CRTL_HOLD_ACTIVE) && (gps_state != GPS_CRTL_HOME_ACTIVE))
323
                        {
324
                                cnt++;
325
                                if (cnt > 100) // erst nach Verzoegerung 
326
                                {
327
                                        // Erst mal initialisieren
328
                                        cnt             = 0;
329
                                        gps_tick        = 0;                                   
330
                                        hold_fast       = 0;
331
                                        hold_reset_int  = 0; // Integrator enablen
332
                                        int_east        = 0, int_north          = 0;
333
                                        gps_reg_x       = 0, gps_reg_y          = 0;
334
                                        delta_east      = 0, delta_north        = 0;
335
                                        dist_flown      = 0;
336
                                        gps_g2t_act_v   = 0;
337
                                        gps_sub_state   = GPS_CRTL_IDLE;
338
                                        // aktuelle positionsdaten abspeichern
339
                                        if (gps_rel_act_position.status > 0)
340
                                        {
341
                                                gps_rel_start_position.utm_east = gps_rel_act_position.utm_east;
342
                                                gps_rel_start_position.utm_north= gps_rel_act_position.utm_north;
343
                                                gps_rel_start_position.status   = 1; // gueltige Positionsdaten 
344
                                                gps_rel_hold_position.utm_east  = gps_rel_act_position.utm_east;
345
                                                gps_rel_hold_position.utm_north = gps_rel_act_position.utm_north;
346
                                                gps_rel_hold_position.status    = 1; // gueltige Positionsdaten 
347
                                                //Richtung zur Home Position bezogen auf Nordpol bestimmen
348
                                                hdng_2home = arctan_i(-gps_rel_start_position.utm_east,-gps_rel_start_position.utm_north);
349
                                                // in Winkel 0...360 Grad umrechnen
350
                                                if (( gps_rel_start_position.utm_east < 0)) hdng_2home = ( 90-hdng_2home);
351
                                                else  hdng_2home = (270 - hdng_2home);
352
                                                dist_2home = (int) get_dist(gps_rel_start_position.utm_east,gps_rel_start_position.utm_north,hdng_2home); //Entfernung zur Home Position bestimmen
353
                                                gps_state       = GPS_CRTL_HOME_ACTIVE;
354
                                                return (GPS_STST_OK);                          
355
                                        }
356
                                        else
357
                                        {
358
                                                gps_rel_start_position.status   =       0;  //Keine Daten verfuegbar
359
                                                gps_state                       =       GPS_CRTL_IDLE;
360
                                                return(GPS_STST_ERR); // Keine Daten da
361
                                        }
362
                                }
363
                                else return(GPS_STST_PEND); // noch warten
364
                        }
365
                   break;
366
// ******************************
367
 
368
                case GPS_CMD_REQ_HOLD: // Die Lageregelung soll aktiviert werden.
369
                        if (gps_state != GPS_CRTL_HOLD_ACTIVE)
370
                        {
371
                                cnt++;
372
                                if (cnt > 600) // erst nach Verzoegerung 
373
                                {
374
                                        cnt     =       0;
375
                                        // aktuelle positionsdaten abspeichern
376
                                        if (gps_rel_act_position.status > 0)
377
                                        {
378
                                                hold_fast               = 0;
379
                                                hold_reset_int          = 0; // Integrator enablen
380
                                                int_east                = 0, int_north  = 0;
381
                                                gps_reg_x               = 0, gps_reg_y  = 0;
382
                                                delta_east              = 0, delta_north        = 0;
383
                                                speed_east              = 0; speed_north= 0;
384
//                                              int_ovfl_cnt            = 0;
385
                                                gps_quiet_cnt           = 0;
386
                                                gps_rel_hold_position.utm_east  = gps_rel_act_position.utm_east;
387
                                                gps_rel_hold_position.utm_north = gps_rel_act_position.utm_north;
388
                                                gps_rel_hold_position.status    = 1; // gueltige Positionsdaten 
389
                                                gps_state                                               = GPS_CRTL_HOLD_ACTIVE;
390
                                                return (GPS_STST_OK);                          
391
                                        }
392
                                        else
393
                                        {
394
                                                gps_rel_hold_position.status    = 0;  //Keine Daten verfuegbar
395
                                                gps_state                                               = GPS_CRTL_IDLE;
396
                                                return(GPS_STST_ERR); // Keine Daten da
397
                                        }
398
                                }
399
                                else return(GPS_STST_PEND); // noch warten
400
                        }
401
                        break;
402
 
403
                case GPS_CMD_STOP: // Lageregelung beenden
404
                        cnt                             =       0;
405
                        GPS_Nick                =       0;
406
                        GPS_Roll                =       0;
407
                        gps_sub_state   =       GPS_CRTL_IDLE;
408
                        gps_state               =       GPS_CRTL_IDLE;
409
                        return (GPS_STST_OK);
410
                        break;
411
 
412
                default:
413
                        return (GPS_STST_ERR);
414
                        break;
415
        }
416
 
417
        switch (gps_state)
418
        {      
419
                case GPS_CRTL_IDLE:
420
                        cnt             =       0;
421
                        return (GPS_STST_OK);
422
                        break;
423
 
424
                case GPS_CRTL_HOME_ACTIVE: // Rueckflug zur Basis
425
                //Der Sollwert des Lagereglers wird der Homeposition angenaehert
426
                        if (gps_rel_start_position.status >0)
427
                        {
428
                                if ((gps_updte_flag > 0) && (gps_sub_state !=GPS_HOME_FINISHED)) // nur wenn neue GPS Daten vorliegen und nicht schon alles fertig ist
429
                                {
430
                                        gps_tick++;
431
                                        int d1,d2,d3;
432
                                        d1      = abs (gps_rel_hold_position.utm_east - gps_rel_act_position.utm_east );
433
                                        d2      = abs (gps_rel_hold_position.utm_north - gps_rel_act_position.utm_north );
434
                                        d3      = (dist_2home - dist_flown); // Restdistanz zum Ziel    
435
 
436
                                        if (d3 > GPS_G2T_DIST_MAX_STOP) // Schneller Rueckflug, noch weit weg vom Ziel
437
                                        {
438
                                                if ((d1 < (GPS_G2T_FAST_TOL/2))  && (d2 < (GPS_G2T_FAST_TOL/2))) //voll Stoff weiter wenn Lage gut innerhalb der Toleranz
439
                                                {
440
                                                        if (gps_g2t_act_v < GPS_G2T_V_MAX-3) gps_g2t_act_v += 4; //Geschwindigkeit erhoehen
441
                                                        dist_flown              +=gps_g2t_act_v; // Vorgabe der Strecke anhand der Geschwindigkeit
442
                                                        gps_sub_state   = GPS_HOME_FAST_IN_TOL;
443
                                                }
444
                                                else if ((d1 < GPS_G2T_FAST_TOL)  && (d2 < GPS_G2T_FAST_TOL)) //nur weiter wenn Lage innerhalb der Toleranz
445
                                                {
446
                                                        if (gps_g2t_act_v > (GPS_G2T_V_MAX/2)) gps_g2t_act_v -= 1; //Geschwindigkeit auf Haelfte runter oder rauffahren
447
                                                        else if (gps_g2t_act_v < (GPS_G2T_V_MAX/2)) gps_g2t_act_v += 1;
448
                                                        dist_flown              +=gps_g2t_act_v; // Vorgabe der Strecke anhand der Geschwindigkeit
449
                                                        gps_sub_state   = GPS_HOME_FAST_IN_TOL;
450
                                                }
451
                                                else    //Den Lageregler in Ruhe arbeiten lassen weil ausserhalb der Toleranz
452
                                                {
453
                                                        if (gps_g2t_act_v > 1) gps_g2t_act_v--; // Geschwindigkeit reduzieren
454
//                                                      dist_flown++;                           //Auch ausserhalb der Toleranz langsam erhoehen
455
                                                        gps_sub_state   = GPS_HOME_FAST_OUTOF_TOL;
456
                                                }
457
                                                hold_reset_int                  = 0; // Integrator einsschalten  
458
                                                hold_fast                               = 1; // Regler fuer schnellen Flug
459
                                                dist_frm_start_east             = (int)(((long)dist_flown * (long)sin_i(hdng_2home))/1000);
460
                                                dist_frm_start_north    = (int)(((long)dist_flown * (long)cos_i(hdng_2home))/1000);
461
                                                gps_rel_hold_position.utm_east  = gps_rel_start_position.utm_east  + dist_frm_start_east; //naechster Zielpunkt
462
                                                gps_rel_hold_position.utm_north = gps_rel_start_position.utm_north + dist_frm_start_north; //naechster Zielpunkt
463
                                        }
464
                                        else if (d3 > GPS_G2T_DIST_HOLD)   //Das Ziel naehert sich, deswegen abbremsen
465
                                        {
466
                                                if ((d1 < GPS_G2T_NRML_TOL)  && (d2 < GPS_G2T_NRML_TOL))  
467
                                                {
468
                                                        dist_flown              +=      GPS_G2T_V_RAMP_DWN; // Vorgabe der Strecke anhand der Geschwindigkeit
469
                                                        gps_sub_state   =       GPS_HOME_RMPDWN_IN_TOL;
470
                                                }
471
                                                else
472
                                                {
473
                                                        dist_flown++;   //Auch ausserhalb der Toleranz langsam erhoehen
474
                                                        gps_sub_state   = GPS_HOME_RMPDWN_OUTOF_TOL;
475
                                                }                                      
476
                                                hold_reset_int          = 0; // Integrator einsschalten           
477
                                                hold_fast                       = 1; // Regler fuer schnellen Flug
478
                                                dist_frm_start_east     = (int)(((long)dist_flown * (long)sin_i(hdng_2home))/1000);
479
                                                dist_frm_start_north    = (int)(((long)dist_flown * (long)cos_i(hdng_2home))/1000);
480
                                                gps_rel_hold_position.utm_east  = gps_rel_start_position.utm_east  + dist_frm_start_east; //naechster Zielpunkt
481
                                                gps_rel_hold_position.utm_north = gps_rel_start_position.utm_north + dist_frm_start_north; //naechster Zielpunkt
482
                                        }                                                      
483
                                        else  //Soll-Ziel fast erreicht, Jetzt noch Reste ausgleichen, weil Zielpunkt nicht exakt bestimmt werden konnte (Fehler in Winkelfkt) 
484
                                        {
485
                                                if ((d1 < GPS_G2T_NRML_TOL)  && (d2 < GPS_G2T_NRML_TOL)) // Jetzt bis zum Zielpunkt regeln
486
                                                {
487
                                                        gps_sub_state   = GPS_HOME_IN_TOL;
488
                                                        hold_fast               = 0;    // Wieder normal regeln
489
                                                        hold_reset_int  = 0;    // Integrator einsschalten                
490
                                                        if (gps_rel_hold_position.utm_east >= GPS_G2T_V_MIN) gps_rel_hold_position.utm_east -= GPS_G2T_V_MIN;
491
                                                        else if (gps_rel_hold_position.utm_east <= -GPS_G2T_V_MIN ) gps_rel_hold_position.utm_east += GPS_G2T_V_MIN;
492
                                                        if (gps_rel_hold_position.utm_north >= GPS_G2T_V_MIN) gps_rel_hold_position.utm_north -= GPS_G2T_V_MIN;
493
                                                        else if (gps_rel_hold_position.utm_north <= - GPS_G2T_V_MIN ) gps_rel_hold_position.utm_north += GPS_G2T_V_MIN;
494
                                                        if ((abs(gps_rel_hold_position.utm_east) <= GPS_G2T_V_MIN) && (abs(gps_rel_hold_position.utm_north) <=GPS_G2T_V_MIN))
495
                                                        {
496
                                                                gps_rel_hold_position.utm_east  = 0;
497
                                                                gps_rel_hold_position.utm_north = 0;
498
                                                                gps_sub_state                   = GPS_HOME_FINISHED;
499
                                                        }
500
                                                }
501
                                                else gps_sub_state      = GPS_HOME_OUTOF_TOL;
502
                                        }                                      
503
                                }
504
                                gps_state = GPS_CRTL_HOLD_ACTIVE; //Zwischensprung
505
                                return (GPS_STST_OK);                                  
506
                        }
507
                        else  // Keine GPS Daten verfuegbar, deswegen Abbruch
508
                        {
509
                                gps_state       = GPS_CRTL_IDLE;       
510
                                return (GPS_STST_ERR);
511
                        }
512
                        break;
513
 
514
 
515
                case GPS_CRTL_HOLD_ACTIVE:  // Hier werden die Daten fuer Nick und Roll errechnet
516
                        if (gps_updte_flag >0)  // nur wenn neue GPS Daten vorliegen
517
                        {
518
                                gps_quiet_cnt++;
519
                                // ab hier wird geregelt
520
                                delta_east      = (long) (gps_rel_act_position.utm_east - gps_rel_hold_position.utm_east);
521
                                delta_north     = (long) (gps_rel_act_position.utm_north - gps_rel_hold_position.utm_north);
522
                                int_east        += (int)delta_east;
523
                                int_north       += (int)delta_north;
524
                                speed_east      =  actual_speed.speed_e;
525
                                speed_north     =  actual_speed.speed_n;
526
                                gps_updte_flag  = 0;  // Neue Werte koennen vom GPS geholt werden
527
                                dist_east       = (int)delta_east; //merken
528
                                dist_north      = (int)delta_north;
529
 
530
 
531
//                              #define GPSINT_MAX 3000 // Neues Verfahren ab  30.12.2007  bei Integratoroverflow
532
                                long int gpsintmax;
533
                                if (Parameter_NaviGpsI > 0)
534
                                {
535
                                        gpsintmax = (GPS_NICKROLL_MAX * gps_gain * GPS_USR_PAR_FKT * ((32*3)/10))/(long)Parameter_NaviGpsI; //auf ungefeahren Maximalwert begrenzen
536
                                        if ((abs(int_east) > (int)gpsintmax) || (abs(int_north)> (int)gpsintmax))
537
                                        {
538
//                                              //      = 1; // Zahl der Overflows zaehlen
539
//                                              int_ovfl_cnt    -= 1; 
540
                                                int_east        = (int_east * 6)/8; // Wert reduzieren
541
                                                int_north       = (int_north* 6)/8;                                    
542
                                        }
543
 
544
                                        if (hold_reset_int > 0)  //Im Schnellen Mode Integrator abschalten
545
                                        {
546
                                                int_east        = 0;   
547
                                                int_north       = 0;                                   
548
                                        }
549
                                }
550
                                else  // Integrator deaktiviert
551
                                {
552
                                        int_east  = 0;
553
                                        int_north = 0;
554
                                }
555
 
556
                                debug_gp_4      = (int)int_east;  // zum Debuggen
557
                                debug_gp_5      = (int)int_north; // zum Debuggen
558
 
559
                                //I Werte begrenzen 
560
                                #define INT1_MAX (GPS_NICKROLL_MAX * gps_gain*3)/10// auf 30 Prozent des maximalen Nick/Rollwert begrenzen
561
                                int_east1  =  ((((long)int_east)   * Parameter_NaviGpsI)/32)/GPS_USR_PAR_FKT;
562
                                int_north1 =  ((((long)int_north)  * Parameter_NaviGpsI)/32)/GPS_USR_PAR_FKT;  
563
                                if (int_east1 > INT1_MAX) int_east1 =  INT1_MAX; //begrenzen
564
                                else if (int_east1 < -INT1_MAX) int_east1 =  -INT1_MAX;
565
                                if (int_north1 > INT1_MAX) int_north1 =  INT1_MAX; //begrenzen
566
                                else if (int_north1 < -INT1_MAX) int_north1 =  -INT1_MAX;
567
 
568
                                if (hold_fast > 0)  //schneller Coming Home Modus 
569
                                {
570
                                        amplfy_speed_east  = DIFF_Y_F_MAX;
571
                                        amplfy_speed_north = DIFF_Y_F_MAX;
572
                                        amplfy_speed_east  *= (Parameter_NaviGpsD/GPS_USR_PAR_FKT);
573
                                        amplfy_speed_north *= (Parameter_NaviGpsD/GPS_USR_PAR_FKT);
574
                                        speed_east  = (speed_east   * (long)amplfy_speed_east) /50;
575
                                        speed_north = (speed_north  * (long)amplfy_speed_north)/50;
576
                                        // D Werte begrenzen 
577
                                        #define D_F_MAX (GPS_NICKROLL_MAX * gps_gain*7)/10 // auf 70 Prozent des Maximalen Nick/Rollwert begrenzen
578
                                        if (speed_east  > D_F_MAX) speed_east = D_F_MAX;
579
                                        else if (speed_east < -D_F_MAX) speed_east = -D_F_MAX;
580
                                        if (speed_north > D_F_MAX) speed_north = D_F_MAX;
581
                                        else if (speed_north < -D_F_MAX) speed_north = -D_F_MAX;
582
 
583
                                        diff_p          = (Parameter_NaviGpsP * GPS_PROP_FAST_V)/GPS_USR_PAR_FKT; //Verstaerkung fuer P-Anteil
584
                                }
585
                                else  //langsamer Holdmodus
586
                                {
587
                                        amplfy_speed_east  = DIFF_Y_N_MAX;
588
                                        amplfy_speed_north = DIFF_Y_N_MAX;
589
                                        amplfy_speed_east  *= (Parameter_NaviGpsD/GPS_USR_PAR_FKT);
590
                                        amplfy_speed_north *= (Parameter_NaviGpsD/GPS_USR_PAR_FKT);
591
                                        speed_east  = (speed_east   * (long)amplfy_speed_east) /25;
592
                                        speed_north = (speed_north  * (long)amplfy_speed_north)/25;
593
                                        // D Werte begrenzen 
594
                                        #define D_N_MAX (GPS_NICKROLL_MAX * gps_gain*8)/10 // auf 80 Prozent des Maximalen Nick/Rollwert begrenzen
595
                                        if (speed_east  > D_N_MAX) speed_east = D_N_MAX;
596
                                        else if (speed_east < -D_N_MAX) speed_east = -D_N_MAX;
597
                                        if (speed_north > D_N_MAX) speed_north = D_N_MAX;
598
                                        else if (speed_north < -D_N_MAX) speed_north = -D_N_MAX;
599
 
600
                                        diff_p  = (Parameter_NaviGpsP * GPS_PROP_NRML_V)/GPS_USR_PAR_FKT; //Verstaerkung fuer P-Anteil
601
                                }
602
 
603
//                              debug_gp_4      = (int)speed_east;      // zum Debuggen
604
//                              debug_gp_5      = (int)speed_north; // zum Debuggen
605
 
606
                                //P-Werte verstaerken
607
                                delta_east      = (delta_east   * (long)diff_p)/(40);
608
                                delta_north     = (delta_north  * (long)diff_p)/(40);
609
 
610
                                if (hold_fast > 0)  //schneller Coming Home Modus 
611
                                {
612
                                        // P Werte begrenzen 
613
                                        #define P1_F_MAX (GPS_NICKROLL_MAX * gps_gain*7)/10 // auf 70 Prozent des Maximalen Nick/Rollwert begrenzen
614
                                        if (delta_east   > P1_F_MAX) delta_east = P1_F_MAX;
615
                                        else if (delta_east < -P1_F_MAX) delta_east = -P1_F_MAX;
616
                                        if (delta_north > P1_F_MAX) delta_north = P1_F_MAX;
617
                                        else if (delta_north < -P1_F_MAX) delta_north = -P1_F_MAX;
618
                                }
619
                                else // Hold modus
620
                                {
621
                                        // P Werte begrenzen 
622
                                        #define P1_N_MAX (GPS_NICKROLL_MAX * gps_gain*7)/10 // auf 70 Prozent des Maximalen Nick/Rollwert begrenzen
623
                                        if (delta_east   > P1_N_MAX) delta_east = P1_N_MAX;
624
                                        else if (delta_east < -P1_N_MAX) delta_east = -P1_N_MAX;
625
                                        if (delta_north > P1_N_MAX) delta_north = P1_N_MAX;
626
                                        else if (delta_north < -P1_N_MAX) delta_north = -P1_N_MAX;
627
                                }
628
 
629
                                debug_gp_2      = (int)delta_east;              // zum Debuggen
630
                                debug_gp_3      = (int)delta_north;             // zum Debuggen
631
 
632
 
633
                                //PID Regler Werte aufsummieren
634
                                gps_reg_x = -(int_east1  + delta_east  + speed_east);   // I + P +D  Anteil X Achse
635
                                gps_reg_y = -(int_north1 + delta_north + speed_north);  // I + P +D  Anteil Y Achse
636
                                debug_gp_0      = (int)gps_reg_x; // zum Debuggen
637
                                debug_gp_1      = (int)gps_reg_y; // zum Debuggen
638
 
639
                                // Werte fuer Nick und Roll direkt aus gps_reg_x und gps_reg_y bestimmen
640
                                n  = GyroKomp_Int/GIER_GRAD_FAKTOR; //Ausrichtung Kopter 
641
                                ni = -((gps_reg_y * (long)cos_i(n)) + (gps_reg_x * (long)sin_i(n)))/(1000*gps_gain);
642
                                ro =  ((gps_reg_x * (long)cos_i(n)) - (gps_reg_y * (long)sin_i(n)))/(1000*gps_gain);
643
 
644
                                if (ni > (GPS_NICKROLL_MAX )) ni = (GPS_NICKROLL_MAX);
645
                                else if (ni < -(GPS_NICKROLL_MAX )) ni = -(GPS_NICKROLL_MAX );
646
                                if (ro > (GPS_NICKROLL_MAX )) ro = (GPS_NICKROLL_MAX );
647
                                else if (ro < -(GPS_NICKROLL_MAX)) ro = -(GPS_NICKROLL_MAX );
648
 
649
                                if ((abs(dist_east) > GPS_DIST_MAX) || (abs(dist_north) > GPS_DIST_MAX))  // bei zu grossem Abstand abbrechen
650
                                {
651
                                        GPS_Roll        = 0;
652
                                        GPS_Nick        = 0;
653
                                        gps_state       = GPS_CRTL_IDLE;
654
                                        return (GPS_STST_ERR); 
655
                                        break;                                 
656
                                }
657
                                else if ((PPM_in[7] > 100) && (CAM_GPS_QUIET > 0) && (gps_quiet_cnt <=4) )  // Wenn Fotoausloeser gedruckt wird, GPS Stellwerte kurzzeitig auf 0 setzen
658
                                {
659
                                        gps_quiet_cnt++;
660
                                        GPS_Roll = 0;
661
                                        GPS_Nick = 0;
662
                                        if ( cmd == GPS_CMD_REQ_HOME ) gps_state = GPS_CRTL_HOME_ACTIVE; // State umsetzen
663
                                        return (GPS_STST_OK);
664
                                }
665
                                else if ((PPM_in[7] < 50) && (CAM_GPS_QUIET > 0)  && (gps_quiet_cnt >= 4))
666
                                {
667
                                        gps_quiet_cnt = 0;
668
                                        if ( cmd == GPS_CMD_REQ_HOME ) gps_state = GPS_CRTL_HOME_ACTIVE; // State umsetzen
669
                                        return (GPS_STST_OK);
670
                                }
671
                                else
672
                                {
673
                                        GPS_Roll = (int)ro;
674
                                        GPS_Nick = (int)ni;
675
                                        if ( cmd == GPS_CMD_REQ_HOME ) gps_state = GPS_CRTL_HOME_ACTIVE; // State umsetzen
676
                                        return (GPS_STST_OK);
677
                                }
678
                        }
679
                        else
680
                        {
681
                                if ( cmd == GPS_CMD_REQ_HOME ) gps_state = GPS_CRTL_HOME_ACTIVE; // State umsetzen
682
                                return (GPS_STST_OK);
683
                        }
684
                        break;
685
 
686
                default:
687
                        gps_state = GPS_CRTL_IDLE;
688
                        return (GPS_STST_ERR);
689
                        break;
690
        }      
691
        return (GPS_STST_ERR);
692
 
693
}
694