Subversion Repositories FlightCtrl

Rev

Details | Last modification | View Log | RSS feed

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