Subversion Repositories FlightCtrl

Rev

Rev 632 | 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
{
633 salvo 300
        static unsigned int cnt;                                                // Zaehler fuer diverse Verzoegerungen 
301
        static long int         delta_north,delta_east;         // Mass fuer Distanz zur Sollposition
621 salvo 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;
633 salvo 310
        int                             dist_east,dist_north;
311
        int diff_p;     //Vom Modus abhaengige zusaetzliche Verstaerkung
602 salvo 312
 
633 salvo 313
 
528 salvo 314
        switch (cmd)
315
        {
316
 
317
                case GPS_CMD_REQ_HOME: // Es soll zum Startpunkt zurueckgeflogen werden. 
318
                        if ((gps_state != GPS_CRTL_HOLD_ACTIVE) && (gps_state != GPS_CRTL_HOME_ACTIVE))
319
                        {
320
                                cnt++;
629 salvo 321
                                if (cnt > 50) // erst nach Verzoegerung 
528 salvo 322
                                {
323
                                        // Erst mal initialisieren
629 salvo 324
                                        cnt             = 0;
528 salvo 325
                                        gps_tick                = 0;                                   
326
                                        hold_fast               = 0;
327
                                        hold_reset_int  = 0; // Integrator enablen
328
                                        int_east                = 0, int_north  = 0;
329
                                        gps_reg_x               = 0, gps_reg_y  = 0;
633 salvo 330
                                        delta_east              = 0, delta_north        = 0;
528 salvo 331
                                        dist_flown              = 0;
332
                                        gps_g2t_act_v   = 0;
333
                                        gps_sub_state   = GPS_CRTL_IDLE;
334
                                        // aktuelle positionsdaten abspeichern
335
                                        if (gps_rel_act_position.status > 0)
336
                                        {
337
                                                gps_rel_start_position.utm_east = gps_rel_act_position.utm_east;
338
                                                gps_rel_start_position.utm_north= gps_rel_act_position.utm_north;
339
                                                gps_rel_start_position.status   = 1; // gueltige Positionsdaten 
340
                                                gps_rel_hold_position.utm_east  = gps_rel_act_position.utm_east;
341
                                                gps_rel_hold_position.utm_north = gps_rel_act_position.utm_north;
342
                                                gps_rel_hold_position.status    = 1; // gueltige Positionsdaten 
343
                                                //Richtung zur Home Position bezogen auf Nordpol bestimmen
344
                                                hdng_2home = arctan_i(-gps_rel_start_position.utm_east,-gps_rel_start_position.utm_north);
345
                                                // in Winkel 0...360 Grad umrechnen
346
                                                if (( gps_rel_start_position.utm_east < 0)) hdng_2home = ( 90-hdng_2home);
347
                                                else  hdng_2home = (270 - hdng_2home);
348
                                                dist_2home = (int) get_dist(gps_rel_start_position.utm_east,gps_rel_start_position.utm_north,hdng_2home); //Entfernung zur Home Position bestimmen
349
                                                gps_state       = GPS_CRTL_HOME_ACTIVE;
350
                                                return (GPS_STST_OK);                          
351
                                        }
352
                                        else
353
                                        {
354
                                                gps_rel_start_position.status   =       0;  //Keine Daten verfuegbar
629 salvo 355
                                                gps_state                       =       GPS_CRTL_IDLE;
528 salvo 356
                                                return(GPS_STST_ERR); // Keine Daten da
357
                                        }
358
                                }
359
                                else return(GPS_STST_PEND); // noch warten
360
                        }
361
                   break;
362
// ******************************
363
 
364
                case GPS_CMD_REQ_HOLD: // Die Lageregelung soll aktiviert werden.
365
                        if (gps_state != GPS_CRTL_HOLD_ACTIVE)
366
                        {
367
                                cnt++;
628 salvo 368
                                if (cnt > 700) // erst nach Verzoegerung 
528 salvo 369
                                {
370
                                        cnt     =       0;
371
                                        // aktuelle positionsdaten abspeichern
372
                                        if (gps_rel_act_position.status > 0)
373
                                        {
374
                                                hold_fast               = 0;
375
                                                hold_reset_int  = 0; // Integrator enablen
631 salvo 376
                                                int_east                = 0, int_north  = 0;
377
                                                gps_reg_x               = 0, gps_reg_y  = 0;
633 salvo 378
                                                delta_east              = 0, delta_north        = 0;
631 salvo 379
                                                speed_east              = 0; speed_north= 0;
380
                                                int_ovfl_cnt    = 0;
528 salvo 381
                                                gps_rel_hold_position.utm_east  = gps_rel_act_position.utm_east;
382
                                                gps_rel_hold_position.utm_north = gps_rel_act_position.utm_north;
383
                                                gps_rel_hold_position.status    = 1; // gueltige Positionsdaten 
384
                                                gps_state                                               = GPS_CRTL_HOLD_ACTIVE;
385
                                                return (GPS_STST_OK);                          
386
                                        }
387
                                        else
388
                                        {
631 salvo 389
                                                gps_rel_hold_position.status    = 0;  //Keine Daten verfuegbar
528 salvo 390
                                                gps_state                                               = GPS_CRTL_IDLE;
391
                                                return(GPS_STST_ERR); // Keine Daten da
392
                                        }
393
                                }
394
                                else return(GPS_STST_PEND); // noch warten
395
                        }
396
                        break;
397
 
398
                case GPS_CMD_STOP: // Lageregelung beenden
399
                        cnt                             =       0;
400
                        GPS_Nick                =       0;
401
                        GPS_Roll                =       0;
402
                        gps_int_x               =       0;
403
                        gps_int_y               =       0;
404
                        gps_sub_state   =       GPS_CRTL_IDLE;
405
                        gps_state               =       GPS_CRTL_IDLE;
406
                        return (GPS_STST_OK);
407
                        break;
408
 
409
                default:
410
                        return (GPS_STST_ERR);
411
                        break;
412
        }
413
 
414
        switch (gps_state)
415
        {      
416
                case GPS_CRTL_IDLE:
417
                        cnt             =       0;
418
                        return (GPS_STST_OK);
419
                        break;
420
 
421
                case GPS_CRTL_HOME_ACTIVE: // Rueckflug zur Basis
422
                //Der Sollwert des Lagereglers wird der Homeposition angenaehert
423
                        if (gps_rel_start_position.status >0)
424
                        {
425
                                if ((gps_updte_flag > 0) && (gps_sub_state !=GPS_HOME_FINISHED)) // nur wenn neue GPS Daten vorliegen und nicht schon alles fertig ist
426
                                {
427
                                        gps_tick++;
428
                                        int d1,d2,d3;
429
                                        d1      = abs (gps_rel_hold_position.utm_east - gps_rel_act_position.utm_east );
430
                                        d2      = abs (gps_rel_hold_position.utm_north - gps_rel_act_position.utm_north );
628 salvo 431
                                        d3      = (dist_2home - dist_flown); // Restdistanz zum Ziel    
632 salvo 432
//                                      debug_gp_2      = dist_2home;           // zum Debuggen
433
//                                      debug_gp_3      = dist_flown;           // zum Debuggen
434
//                                      debug_gp_4      = hdng_2home;           // zum Debuggen
628 salvo 435
//                                      debug_gp_5      = amplfy_speed_north; // zum Debuggen
528 salvo 436
 
437
                                        if (d3 > GPS_G2T_DIST_MAX_STOP) // Schneller Rueckflug, noch weit weg vom Ziel
438
                                        {
439
                                                if ((d1 < GPS_G2T_FAST_TOL)  && (d2 < GPS_G2T_FAST_TOL)) //nur weiter wenn Lage innerhalb der Toleranz
440
                                                {
633 salvo 441
                                                        if (gps_g2t_act_v < GPS_G2T_V_MAX-3) gps_g2t_act_v += 4; //Geschwindigkeit erhoehen
628 salvo 442
                                                        dist_flown              +=gps_g2t_act_v; // Vorgabe der Strecke anhand der Geschwindigkeit
528 salvo 443
                                                        gps_sub_state   = GPS_HOME_FAST_IN_TOL;
444
                                                }
445
                                                else    //Den Lageregler in Ruhe arbeiten lassen weil ausserhalb der Toleranz
446
                                                {
447
                                                        if (gps_g2t_act_v > 1) gps_g2t_act_v--; // Geschwindigkeit reduzieren
629 salvo 448
//                                                      dist_flown++;                           //Auch ausserhalb der Toleranz langsam erhoehen
528 salvo 449
                                                        gps_sub_state   = GPS_HOME_FAST_OUTOF_TOL;
450
                                                }
629 salvo 451
                                                hold_reset_int                  = 0; // Integrator einsschalten  
452
                                                hold_fast                               = 1; // Regler fuer schnellen Flug
453
                                                dist_frm_start_east             = (int)(((long)dist_flown * (long)sin_i(hdng_2home))/1000);
454
                                                dist_frm_start_north    = (int)(((long)dist_flown * (long)cos_i(hdng_2home))/1000);
528 salvo 455
                                                gps_rel_hold_position.utm_east  = gps_rel_start_position.utm_east  + dist_frm_start_east; //naechster Zielpunkt
456
                                                gps_rel_hold_position.utm_north = gps_rel_start_position.utm_north + dist_frm_start_north; //naechster Zielpunkt
457
                                        }
458
                                        else if (d3 > GPS_G2T_DIST_HOLD)   //Das Ziel naehert sich, deswegen abbremsen
459
                                        {
460
                                                if ((d1 < GPS_G2T_NRML_TOL)  && (d2 < GPS_G2T_NRML_TOL))  
461
                                                {
462
                                                        dist_flown              +=      GPS_G2T_V_RAMP_DWN; // Vorgabe der Strecke anhand der Geschwindigkeit
463
                                                        gps_sub_state   =       GPS_HOME_RMPDWN_IN_TOL;
464
                                                }
465
                                                else
466
                                                {
629 salvo 467
                                                        dist_flown++;   //Auch ausserhalb der Toleranz langsam erhoehen
528 salvo 468
                                                        gps_sub_state   = GPS_HOME_RMPDWN_OUTOF_TOL;
469
                                                }                                      
629 salvo 470
                                                hold_reset_int          = 0; // Integrator einsschalten           
471
                                                hold_fast                       = 1; // Regler fuer schnellen Flug
472
                                                dist_frm_start_east     = (int)(((long)dist_flown * (long)sin_i(hdng_2home))/1000);
473
                                                dist_frm_start_north    = (int)(((long)dist_flown * (long)cos_i(hdng_2home))/1000);
528 salvo 474
                                                gps_rel_hold_position.utm_east  = gps_rel_start_position.utm_east  + dist_frm_start_east; //naechster Zielpunkt
475
                                                gps_rel_hold_position.utm_north = gps_rel_start_position.utm_north + dist_frm_start_north; //naechster Zielpunkt
476
                                        }                                                      
477
                                        else  //Soll-Ziel fast erreicht, Jetzt noch Reste ausgleichen, weil Zielpunkt nicht exakt bestimmt werden konnte (Fehler in Winkelfkt) 
478
                                        {
479
                                                if ((d1 < GPS_G2T_NRML_TOL)  && (d2 < GPS_G2T_NRML_TOL)) // Jetzt bis zum Zielpunkt regeln
480
                                                {
481
                                                        gps_sub_state   = GPS_HOME_IN_TOL;
629 salvo 482
                                                        hold_fast               = 0;    // Wieder normal regeln
483
                                                        hold_reset_int  = 0;    // Integrator einsschalten                
528 salvo 484
                                                        if (gps_rel_hold_position.utm_east >= GPS_G2T_V_MIN) gps_rel_hold_position.utm_east -= GPS_G2T_V_MIN;
485
                                                        else if (gps_rel_hold_position.utm_east <= -GPS_G2T_V_MIN ) gps_rel_hold_position.utm_east += GPS_G2T_V_MIN;
486
                                                        if (gps_rel_hold_position.utm_north >= GPS_G2T_V_MIN) gps_rel_hold_position.utm_north -= GPS_G2T_V_MIN;
487
                                                        else if (gps_rel_hold_position.utm_north <= - GPS_G2T_V_MIN ) gps_rel_hold_position.utm_north += GPS_G2T_V_MIN;
488
                                                        if ((abs(gps_rel_hold_position.utm_east) <= GPS_G2T_V_MIN) && (abs(gps_rel_hold_position.utm_north) <=GPS_G2T_V_MIN))
489
                                                        {
490
                                                                gps_rel_hold_position.utm_east  = 0;
491
                                                                gps_rel_hold_position.utm_north = 0;
631 salvo 492
                                                                gps_sub_state                                   = GPS_HOME_FINISHED;
528 salvo 493
                                                        }
494
                                                }
495
                                                else gps_sub_state      = GPS_HOME_OUTOF_TOL;
496
                                        }                                      
497
                                }
498
                                gps_state = GPS_CRTL_HOLD_ACTIVE; //Zwischensprung
499
                                return (GPS_STST_OK);                                  
500
                        }
501
                        else  // Keine GPS Daten verfuegbar, deswegen Abbruch
502
                        {
629 salvo 503
                                gps_state       = GPS_CRTL_IDLE;       
528 salvo 504
                                return (GPS_STST_ERR);
505
                        }
506
                        break;
507
 
508
 
509
                case GPS_CRTL_HOLD_ACTIVE:  // Hier werden die Daten fuer Nick und Roll errechnet
510
                        if (gps_updte_flag >0)  // nur wenn neue GPS Daten vorliegen
511
                        {
512
                                // ab hier wird geregelt
633 salvo 513
                                delta_east      = (long) (gps_rel_act_position.utm_east - gps_rel_hold_position.utm_east);
514
                                delta_north     = (long) (gps_rel_act_position.utm_north - gps_rel_hold_position.utm_north);
515
                                int_east        += (int)delta_east;
516
                                int_north       += (int)delta_north;
632 salvo 517
                                speed_east      =  actual_speed.speed_e;
518
                                speed_north     =  actual_speed.speed_n;
629 salvo 519
                                gps_updte_flag  = 0;  // Neue Werte koennen vom GPS geholt werden
633 salvo 520
                                dist_east       = (int)delta_east; //merken
521
                                dist_north      = (int)delta_north;
632 salvo 522
 
528 salvo 523
 
602 salvo 524
                                #define GPSINT_MAX 3000 // Neues Verfahren ab  30.12.2007  bei Integratoroverflow
525
                                if ((abs(int_east) > GPSINT_MAX) || (abs(int_north)> GPSINT_MAX))
528 salvo 526
                                {
621 salvo 527
                                        if (int_ovfl_cnt < 40) int_ovfl_cnt += 1; // Zahl der Overflows zaehlen
528 salvo 528
                                }
621 salvo 529
                                if (int_ovfl_cnt > 0) //bei Overflow Wert Integratorwert reduzieren 
602 salvo 530
                                {
531
                                        int_ovfl_cnt    -= 1;
633 salvo 532
                                        int_east                = (int_east*7)/8; // Wert reduzieren
602 salvo 533
                                        int_north       = (int_north*7)/8;                                     
534
                                }
535
 
528 salvo 536
                                if (hold_reset_int > 0)  //Im Schnellen Mode Integrator abschalten
537
                                {
538
                                        int_east        = 0;   
539
                                        int_north       = 0;                                   
540
                                }
631 salvo 541
                                if (hold_fast > 0)  //schneller Coming Home Modus 
628 salvo 542
                                {
631 salvo 543
                                        // Verstaerkungsfaktor fuer D-Anteil ermitteln um exponentielles Verhalten zu erzielen
544
                                        amplfy_speed_east  = (((abs(speed_east)) *(DIFF_Y_F_MAX-1)*10)/DIFF_X_F_MAX) +10;
545
                                        amplfy_speed_north = (((abs(speed_north))*(DIFF_Y_F_MAX-1)*10)/DIFF_X_F_MAX) +10;
546
                                        if (amplfy_speed_east  > (DIFF_Y_F_MAX *10)) amplfy_speed_east  = DIFF_Y_F_MAX *10; // Begrenzung
547
                                        if (amplfy_speed_north > (DIFF_Y_F_MAX *10)) amplfy_speed_north = DIFF_Y_F_MAX *10; // Begrenzung
548
                                        amplfy_speed_east  *= (Parameter_UserParam3/GPS_USR_PAR_FKT);
549
                                        amplfy_speed_north *= (Parameter_UserParam3/GPS_USR_PAR_FKT);
633 salvo 550
                                        speed_east  = speed_east  * abs(speed_east)  /200; //quadrieren
551
                                        speed_north = speed_north * abs(speed_north) /200; //quadrieren
552
                                        diff_p = (Parameter_UserParam1 * GPS_PROP_FAST_V)/GPS_USR_PAR_FKT; //Verstaerkung fuer P-Anteil
628 salvo 553
                                }
554
                                else  //langsamer Holdmodus
555
                                {
631 salvo 556
                                        // Verstaerkungsfaktor fuer D-Anteil ermitteln um exponentielles Verhalten zu erzielen
557
                                        amplfy_speed_east  = (((abs(speed_east)) *(DIFF_Y_N_MAX-1)*10)/DIFF_X_N_MAX) +10;
558
                                        amplfy_speed_north = (((abs(speed_north))*(DIFF_Y_N_MAX-1)*10)/DIFF_X_N_MAX) +10;
559
                                        if (amplfy_speed_east  > (DIFF_Y_N_MAX *10)) amplfy_speed_east  = DIFF_Y_N_MAX *10; // Begrenzung
560
                                        if (amplfy_speed_north > (DIFF_Y_N_MAX *10)) amplfy_speed_north = DIFF_Y_N_MAX *10; // Begrenzung
628 salvo 561
                                        amplfy_speed_east  *= (Parameter_UserParam3/GPS_USR_PAR_FKT);
562
                                        amplfy_speed_north *= (Parameter_UserParam3/GPS_USR_PAR_FKT);
633 salvo 563
                                        speed_east  = speed_east  * abs(speed_east)  /100; //quadrieren
632 salvo 564
                                        speed_north = speed_north * abs(speed_north) /100; //quadrieren
633 salvo 565
                                        diff_p = (Parameter_UserParam1 * GPS_PROP_NRML_V)/GPS_USR_PAR_FKT; //Verstaerkung fuer P-Anteil
566
 
628 salvo 567
                                }
632 salvo 568
                                debug_gp_4      = (int)speed_east;              // zum Debuggen
569
                                debug_gp_5      = (int)speed_north; // zum Debuggen
528 salvo 570
 
571
                                //I Werte begrenzen
602 salvo 572
                                #define INT1_MAX (GPS_NICKROLL_MAX * GPS_V)/2 //ab 30.12.2007 auf Halben Maximalen Nick/Rollwert begrenzen
565 salvo 573
                                int_east1  =  ((((long)int_east)   * Parameter_UserParam2)/32)/GPS_USR_PAR_FKT;
631 salvo 574
                                int_north1 =  ((((long)int_north)  * Parameter_UserParam2)/32)/GPS_USR_PAR_FKT;  
528 salvo 575
                                if (int_east1 > INT1_MAX) int_east1 =  INT1_MAX; //begrenzen
576
                                else if (int_east1 < -INT1_MAX) int_east1 =  -INT1_MAX;
577
                                if (int_north1 > INT1_MAX) int_north1 =  INT1_MAX; //begrenzen
578
                                else if (int_north1 < -INT1_MAX) int_north1 =  -INT1_MAX;
579
 
633 salvo 580
                                //P-Werte quadrieren
581
                                delta_east      = (abs(delta_east)  * delta_east )/20; //quadrieren
582
                                delta_north     = (abs(delta_north) * delta_north)/20; //quadrieren
583
                                debug_gp_2      = (int)delta_east;              // zum Debuggen
584
                                debug_gp_3      = (int)delta_north;             // zum Debuggen
585
 
528 salvo 586
                                //PID Regler Werte aufsummieren
633 salvo 587
                                gps_reg_x = -(int_east1  + ((delta_east  * (long)diff_p)/(8*2))+ ((speed_east  * (long)amplfy_speed_east  )/(100L)));  // I + P +D  Anteil X Achse
588
                                gps_reg_y = -(int_north1 + ((delta_north * (long)diff_p)/(8*2))+ ((speed_north * (long)amplfy_speed_north )/(100L)));  // I + P +D  Anteil Y Achse
589
                                debug_gp_0      = (int)gps_reg_x; // zum Debuggen
632 salvo 590
                                debug_gp_1      = (int)gps_reg_y; // zum Debuggen
528 salvo 591
 
592
                                //Ziel-Richtung bezogen auf Nordpol bestimmen
632 salvo 593
                                GPS_hdng_abs_2trgt = arctan_i((int)gps_reg_x,(int)gps_reg_y);
528 salvo 594
 
595
                                // in Winkel 0...360 Grad umrechnen
596
                                if ((gps_reg_x >= 0)) GPS_hdng_abs_2trgt = ( 90-GPS_hdng_abs_2trgt);
597
                                else  GPS_hdng_abs_2trgt = (270 - GPS_hdng_abs_2trgt);
598
 
599
                                // Relative Richtung in bezug auf Nordachse des Kopters errechen
600
                                n= GyroKomp_Int/GYROKOMP_INC_GRAD_DEFAULT;
601
                                GPS_hdng_rel_2trgt      =       GPS_hdng_abs_2trgt - n;
602
                                if      ((GPS_hdng_rel_2trgt >180) && (GPS_hdng_abs_2trgt >=180)) GPS_hdng_rel_2trgt = GPS_hdng_rel_2trgt-360;
603
                                else if (GPS_hdng_rel_2trgt >180)  GPS_hdng_rel_2trgt = 360 - GPS_hdng_rel_2trgt;
604
                                else if (GPS_hdng_rel_2trgt <-180)  GPS_hdng_rel_2trgt = 360 + GPS_hdng_rel_2trgt;
605
 
606
                                // Regelabweichung aus x,y zu Ziel in Distanz umrechnen 
607
                                if (abs(gps_reg_x) > abs(gps_reg_y) )
608
                                {
632 salvo 609
                                        dev = gps_reg_x; //Groesseren Wert wegen besserer Genauigkeit nehmen
528 salvo 610
                                        dev = abs((dev *1000) / (long) sin_i(GPS_hdng_abs_2trgt));
611
                                }
612
                                else
613
                                {
614
                                        dev = (long)gps_reg_y;
615
                                        dev = abs((dev *1000) / (long) cos_i(GPS_hdng_abs_2trgt));
616
                                }
617
                                GPS_dist_2trgt  = (int) dev;
618
                                // Winkel und Distanz in Nick und Rollgroessen umrechnen
621 salvo 619
                                n  = (int) +( (dev * (long) sin_i(GPS_hdng_rel_2trgt))/1000); //Rollwert bestimmen
620
                                n1 = (int) -( (dev * (long) cos_i(GPS_hdng_rel_2trgt))/1000); //Nickwert bestimmen
528 salvo 621
 
621 salvo 622
                                if (n > (GPS_NICKROLL_MAX * GPS_V)) n = (GPS_NICKROLL_MAX * GPS_V);
623
                                else if (n < -(GPS_NICKROLL_MAX * GPS_V)) n = -(GPS_NICKROLL_MAX * GPS_V);
624
                                if (n1 > (GPS_NICKROLL_MAX * GPS_V)) n1 = (GPS_NICKROLL_MAX * GPS_V);
625
                                else if (n1 < -(GPS_NICKROLL_MAX * GPS_V)) n1 = -(GPS_NICKROLL_MAX * GPS_V);
626
                                n  = n/GPS_V;
627
                                n1 = n1/GPS_V;
528 salvo 628
                                //Kleine Werte verstaerken, Grosse abschwaechen
631 salvo 629
/*                              n                       = sin_i((GPS_Roll*90)/(GPS_NICKROLL_MAX * GPS_V));
630
                                n_l                     = ((long) GPS_NICKROLL_MAX  * (long) n)/1000;
528 salvo 631
                                GPS_Roll        = (int) n_l;
631 salvo 632
                                n                       = sin_i((GPS_Nick*90)/(GPS_NICKROLL_MAX * GPS_V));
633
                                n_l                     = ((long) GPS_NICKROLL_MAX  * (long) n)/1000;
629 salvo 634
                                GPS_Nick        = (int) n_l;
635
*/                               
621 salvo 636
 
528 salvo 637
                                if ((abs(dist_east) > GPS_DIST_MAX) || (abs(dist_north) > GPS_DIST_MAX))  // bei zu grossem Abstand abbrechen
638
                                {
639
                                        GPS_Roll        = 0;
640
                                        GPS_Nick        = 0;
641
                                        gps_state       = GPS_CRTL_IDLE;
642
                                        return (GPS_STST_ERR); 
643
                                        break;                                 
644
                                }
645
                                else
646
                                {
621 salvo 647
                                        GPS_Roll = n;
648
                                        GPS_Nick = n1;
528 salvo 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