Subversion Repositories FlightCtrl

Rev

Details | Last modification | View Log | RSS feed

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