Subversion Repositories FlightCtrl

Rev

Details | Last modification | View Log | RSS feed

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