Subversion Repositories FlightCtrl

Rev

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