Subversion Repositories FlightCtrl

Rev

Rev 626 | 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
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
15
Peter Muehlenbrock
16
Auswertung der Daten vom GPS im ublox Format
17
Hold Modus mit PID Regler
18
Rückstuerz zur Basis Funktion
628 salvo 19
Stand 8.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
628 salvo 80
static 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;
565 salvo 157
                        actual_pos.status                       = 0; //neue ublox Messages anfordern
622 salvo 158
                        gps_act_position.speed_gnd      = actual_speed.speed_gnd;
159
                        gps_act_position.speed_gnd      = actual_speed.speed_gnd;
160
                        gps_act_position.heading        = actual_speed.heading/100000;
565 salvo 161
                        actual_speed.status             = 0;
528 salvo 162
                        gps_act_position.status         = 1;
163
                        n                                                       = 0; //Daten gueltig
164
                }
165
                else
166
                {
565 salvo 167
                        gps_act_position.status         = 0; //Keine gueltigen Daten
168
                        actual_speed.status             = 0;
169
                        actual_status.status            = 0;
170
                        actual_pos.status                       = 0; //neue ublox Messages anfordern
171
                        n                                                       = 2;
528 salvo 172
                }
173
        }      
174
        return (n);    
175
}
176
 
177
/*
178
Daten vom GPS im ublox MSG Format auswerten
179
Die Routine wird bei jedem Empfang eines Zeichens vom GPS Modul durch den UART IRQ aufgerufen
180
// Die UBX Messages NAV_POSUTM, NAV_STATUS und NAV_VALED muessen aktiviert sein
181
*/
182
void Get_Ublox_Msg(uint8_t rx)
183
{
184
        switch (ublox_msg_state)
185
        {
186
 
187
                case UBLOX_IDLE: // Zuerst Synchcharacters pruefen
188
                        if ( rx == UBLOX_SYNCH1_CHAR ) ublox_msg_state = UBLOX_SYNC1;
189
                        else ublox_msg_state = UBLOX_IDLE;
190
                        break;
191
 
192
                case UBLOX_SYNC1:
193
 
194
                        if (rx == UBLOX_SYNCH2_CHAR) ublox_msg_state = UBLOX_SYNC2;
195
                        else ublox_msg_state = UBLOX_IDLE;
196
                        chk_a = 0,chk_b = 0;
197
                        break;
198
 
199
                case UBLOX_SYNC2:
200
                        if (rx == UBLOX_NAV_CLASS) ublox_msg_state = UBLOX_CLASS;      
201
                        else ublox_msg_state = UBLOX_IDLE;
202
                        break;
203
 
204
                case UBLOX_CLASS: // Nur NAV Meldungen auswerten
205
                        switch (rx)
206
                        {
207
                                case UBLOX_NAV_POSUTM:
208
                                        ptr_pac_status  =       &actual_pos.status;
209
                                        if (*ptr_pac_status > 0) ublox_msg_state = UBLOX_IDLE; //Abbruch weil Daten noch nicht verwendet wurden
210
                                        else
211
                                        {
212
                                                ptr_payload_data                = &actual_pos;
213
                                                ptr_payload_data_end    = &actual_pos.status;
214
                                                ublox_msg_state                 = UBLOX_LEN1;
215
                                        }
216
                                        break;
217
 
218
                                case UBLOX_NAV_STATUS:
219
                                        ptr_pac_status  =       &actual_status.status;
220
                                        if (*ptr_pac_status > 0) ublox_msg_state = UBLOX_IDLE;
221
                                        else
222
                                        {
223
                                                ptr_payload_data                = &actual_status;
224
                                                ptr_payload_data_end    = &actual_status.status;
225
                                                ublox_msg_state                 = UBLOX_LEN1;
226
                                        }
227
                                        break;
228
 
229
                                case UBLOX_NAV_VELED:
230
                                        ptr_pac_status          =       &actual_speed.status;
231
                                        if (*ptr_pac_status > 0) ublox_msg_state = UBLOX_IDLE;
232
                                        else
233
                                        {
234
                                                ptr_payload_data                = &actual_speed;
235
                                                ptr_payload_data_end    = &actual_speed.status;
236
                                                ublox_msg_state                 = UBLOX_LEN1;
237
                                        }
238
                                        break;
239
 
240
                                default:
241
                                        ublox_msg_state = UBLOX_IDLE;
242
                                        break; 
243
                        }
244
                        chk_a   = UBLOX_NAV_CLASS + rx;
245
                        chk_b   = UBLOX_NAV_CLASS + chk_a;                     
246
                        break;
247
 
248
                case UBLOX_LEN1: // Laenge auswerten
249
                        rx_len  = rx;
250
                        chk_a   += rx;
251
                        chk_b   += chk_a;              
252
                        ublox_msg_state = UBLOX_LEN2;
253
                        break;
254
 
255
 
256
                case UBLOX_LEN2: // Laenge auswerten
257
                        rx_len = rx_len + (rx *256); // Laenge ermitteln
258
                        chk_a   += rx;
259
                        chk_b   += chk_a;      
260
                        ublox_msg_state = UBLOX_PAYLOAD;
261
                        break;
262
 
263
                case UBLOX_PAYLOAD: // jetzt Nutzdaten einlesen
264
                        if (rx_len > 0)
265
                        {
266
                                *ptr_payload_data = rx;
267
                                chk_a   += rx;
268
                                chk_b   += chk_a;
269
                                --rx_len;      
270
                                if ((rx_len > 0) && (ptr_payload_data <= ptr_payload_data_end))                          
271
                                {
272
                                        ptr_payload_data++;
273
                                        ublox_msg_state = UBLOX_PAYLOAD;
274
                            }
275
                                else ublox_msg_state = UBLOX_CKA;
276
                        }      
277
                        else ublox_msg_state = UBLOX_IDLE; // Abbruch wegen Fehler
278
                        break;
279
 
280
                case UBLOX_CKA: // Checksum pruefen
281
                        if (rx == chk_a) ublox_msg_state = UBLOX_CKB;                          
282
                        else ublox_msg_state = UBLOX_IDLE; // Abbruch wegen Fehler
283
                        break;
284
 
285
                case UBLOX_CKB: // Checksum pruefen
286
                        if (rx == chk_b) *ptr_pac_status = 1; // Paket ok
287
                        ublox_msg_state    = UBLOX_IDLE;
288
                        break;
289
 
290
                default:
291
                        ublox_msg_state = UBLOX_IDLE;          
292
                        break;
293
        }
294
}
295
 
296
//Zentrale Statemachine fuer alle GPS relevanten Regelungsablauefe
297
short int GPS_CRTL(short int cmd)
298
{
621 salvo 299
        static unsigned int cnt;                                                //Zaehler fuer diverse Verzoegerungen 
300
        static signed int       dist_north,dist_east;           // Distanz zur Sollpoistion
301
        signed int                      n,n1;
302
        static signed int       gps_g2t_act_v; // Aktuelle Geschwindigkeitsvorgabe fuer Home Funktion
303
        long signed int         dev;
304
        signed int                      dist_frm_start_east,dist_frm_start_north;
626 salvo 305
        int                             amplfy_speed_east,amplfy_speed_north; //Verstaerkungsfaktoren fuer D-Anteil 
621 salvo 306
        static signed int       int_east,int_north;     //Integrierer 
622 salvo 307
        int                             speed_east,speed_north; //Aktuelle Geschwindigkeit 
308
        signed long             int_east1,int_north1;
621 salvo 309
//      signed long             dist;
602 salvo 310
 
528 salvo 311
        switch (cmd)
312
        {
313
 
314
                case GPS_CMD_REQ_HOME: // Es soll zum Startpunkt zurueckgeflogen werden. 
315
                        if ((gps_state != GPS_CRTL_HOLD_ACTIVE) && (gps_state != GPS_CRTL_HOME_ACTIVE))
316
                        {
317
                                cnt++;
565 salvo 318
                                if (cnt > 200) // erst nach Verzoegerung 
528 salvo 319
                                {
320
                                        // Erst mal initialisieren
321
                                        cnt                             = 0;
322
                                        gps_tick                = 0;                                   
323
                                        hold_fast               = 0;
324
                                        hold_reset_int  = 0; // Integrator enablen
325
                                        int_east                = 0, int_north  = 0;
326
                                        gps_reg_x               = 0, gps_reg_y  = 0;
327
                                        dist_east               = 0, dist_north = 0;
328
                                        dist_flown              = 0;
329
                                        gps_g2t_act_v   = 0;
330
                                        gps_sub_state   = GPS_CRTL_IDLE;
331
                                        // aktuelle positionsdaten abspeichern
332
                                        if (gps_rel_act_position.status > 0)
333
                                        {
334
                                                gps_rel_start_position.utm_east = gps_rel_act_position.utm_east;
335
                                                gps_rel_start_position.utm_north= gps_rel_act_position.utm_north;
336
                                                gps_rel_start_position.status   = 1; // gueltige Positionsdaten 
337
                                                gps_rel_hold_position.utm_east  = gps_rel_act_position.utm_east;
338
                                                gps_rel_hold_position.utm_north = gps_rel_act_position.utm_north;
339
                                                gps_rel_hold_position.status    = 1; // gueltige Positionsdaten 
340
                                                //Richtung zur Home Position bezogen auf Nordpol bestimmen
341
                                                hdng_2home = arctan_i(-gps_rel_start_position.utm_east,-gps_rel_start_position.utm_north);
342
                                                // in Winkel 0...360 Grad umrechnen
343
                                                if (( gps_rel_start_position.utm_east < 0)) hdng_2home = ( 90-hdng_2home);
344
                                                else  hdng_2home = (270 - hdng_2home);
345
                                                dist_2home = (int) get_dist(gps_rel_start_position.utm_east,gps_rel_start_position.utm_north,hdng_2home); //Entfernung zur Home Position bestimmen
346
                                                gps_state       = GPS_CRTL_HOME_ACTIVE;
347
                                                return (GPS_STST_OK);                          
348
                                        }
349
                                        else
350
                                        {
351
                                                gps_rel_start_position.status   =       0;  //Keine Daten verfuegbar
352
                                                gps_state                                               = GPS_CRTL_IDLE;
353
                                                return(GPS_STST_ERR); // Keine Daten da
354
                                        }
355
                                }
356
                                else return(GPS_STST_PEND); // noch warten
357
                        }
358
                   break;
359
// ******************************
360
 
361
                case GPS_CMD_REQ_HOLD: // Die Lageregelung soll aktiviert werden.
362
                        if (gps_state != GPS_CRTL_HOLD_ACTIVE)
363
                        {
364
                                cnt++;
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
373
                                                int_east        = 0, int_north  = 0;
374
                                                gps_reg_x       = 0, gps_reg_y  = 0;
375
                                                dist_east       = 0, dist_north = 0;
622 salvo 376
                                                speed_east      = 0; speed_north= 0;
602 salvo 377
                                                int_ovfl_cnt = 0;
528 salvo 378
                                                gps_rel_hold_position.utm_east  = gps_rel_act_position.utm_east;
379
                                                gps_rel_hold_position.utm_north = gps_rel_act_position.utm_north;
380
                                                gps_rel_hold_position.status    = 1; // gueltige Positionsdaten 
381
                                                gps_state                                               = GPS_CRTL_HOLD_ACTIVE;
382
                                                return (GPS_STST_OK);                          
383
                                        }
384
                                        else
385
                                        {
386
                                                gps_rel_hold_position.status    =       0;  //Keine Daten verfuegbar
387
                                                gps_state                                               = GPS_CRTL_IDLE;
388
                                                return(GPS_STST_ERR); // Keine Daten da
389
                                        }
390
                                }
391
                                else return(GPS_STST_PEND); // noch warten
392
                        }
393
                        break;
394
 
395
                case GPS_CMD_STOP: // Lageregelung beenden
396
                        cnt                             =       0;
397
                        GPS_Nick                =       0;
398
                        GPS_Roll                =       0;
399
                        gps_int_x               =       0;
400
                        gps_int_y               =       0;
401
                        gps_sub_state   =       GPS_CRTL_IDLE;
402
                        gps_state               =       GPS_CRTL_IDLE;
403
                        return (GPS_STST_OK);
404
                        break;
405
 
406
                default:
407
                        return (GPS_STST_ERR);
408
                        break;
409
        }
410
 
411
        switch (gps_state)
412
        {      
413
                case GPS_CRTL_IDLE:
414
                        cnt             =       0;
415
                        return (GPS_STST_OK);
416
                        break;
417
 
418
                case GPS_CRTL_HOME_ACTIVE: // Rueckflug zur Basis
419
                //Der Sollwert des Lagereglers wird der Homeposition angenaehert
420
                        if (gps_rel_start_position.status >0)
421
                        {
422
                                if ((gps_updte_flag > 0) && (gps_sub_state !=GPS_HOME_FINISHED)) // nur wenn neue GPS Daten vorliegen und nicht schon alles fertig ist
423
                                {
424
                                        gps_tick++;
425
                                        int d1,d2,d3;
426
                                        d1      = abs (gps_rel_hold_position.utm_east - gps_rel_act_position.utm_east );
427
                                        d2      = abs (gps_rel_hold_position.utm_north - gps_rel_act_position.utm_north );
628 salvo 428
                                        d3      = (dist_2home - dist_flown); // Restdistanz zum Ziel    
429
                                        debug_gp_2      = dist_2home;  // zum Debuggen
430
                                        debug_gp_3      = dist_flown; // zum Debuggen
431
                                        debug_gp_4      = hdng_2home;  // zum Debuggen
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
                                                {
628 salvo 438
                                                        if (gps_g2t_act_v < GPS_G2T_V_MAX-2) gps_g2t_act_v +=2;    //Geschwindigkeit langsam erhoehen
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
445
                                                        dist_flown++;                                                   //Auch ausserhalb der Toleranz langsam erhoehen
446
                                                        gps_sub_state   = GPS_HOME_FAST_OUTOF_TOL;
447
                                                }
448
                                                hold_reset_int                                  = 0; // Integrator einsschalten  
449
                                                hold_fast                                               = 1; // Regler fuer schnellen Flug
628 salvo 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
                                                {
464
                                                        dist_flown++; //Auch ausserhalb der Toleranz langsam erhoehen
465
                                                        gps_sub_state   = GPS_HOME_RMPDWN_OUTOF_TOL;
466
                                                }                                      
467
                                                hold_reset_int                                  = 0; // Integrator ausschalten            
468
                                                hold_fast                                               = 1; // Wieder normal regeln
628 salvo 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;
479
                                                        hold_fast               = 0; // Wieder normal regeln
480
                                                        hold_reset_int  = 0; // Integrator wieder aktivieren              
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;
489
                                                                gps_sub_state                                   = GPS_HOME_FINISHED;
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
                        {
500
                                gps_state       =       GPS_CRTL_IDLE; 
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;
513
                                int_north   += dist_north;
626 salvo 514
                                speed_east      =  (int) (-actual_speed.speed_e);
515
                                speed_north     =  (int) (-actual_speed.speed_n);
622 salvo 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;
526
                                        int_east                = (int_east*7)/8; // Wert reduzieren
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
                                }
628 salvo 535
                                if (hold_fast > 0)  //schneller Coming Home Modus
536
                                {
537
                                        amplfy_speed_east  = (Parameter_UserParam3/GPS_USR_PAR_FKT);
538
                                        amplfy_speed_north = (Parameter_UserParam3/GPS_USR_PAR_FKT);
539
                                }
540
                                else  //langsamer Holdmodus
541
                                {
542
                                        // Verstaerkungsfaktor fuer Geschwindigkeit ermitteln um exponentielles Verhalten zu erzielen
543
                                        amplfy_speed_east  = (((abs(speed_east)) *(DIFF_Y_MAX-1)*10)/DIFF_X_MAX) +10;
544
                                        amplfy_speed_north = (((abs(speed_north))*(DIFF_Y_MAX-1)*10)/DIFF_X_MAX) +10;
545
                                        if (amplfy_speed_east  > (DIFF_Y_MAX *10)) amplfy_speed_east  = DIFF_Y_MAX *10; // Begrenzung
546
                                        if (amplfy_speed_north > (DIFF_Y_MAX *10)) amplfy_speed_north = DIFF_Y_MAX *10; // Begrenzung
547
                                        amplfy_speed_east  *= (Parameter_UserParam3/GPS_USR_PAR_FKT);
548
                                        amplfy_speed_north *= (Parameter_UserParam3/GPS_USR_PAR_FKT);
549
                                        amplfy_speed_east   /= 10; //Faktor 10 wieder rausnehmen
550
                                        amplfy_speed_north  /= 10; //Faktor 10 wieder rausnehmen
551
                                }
528 salvo 552
 
628 salvo 553
 
626 salvo 554
                                #define GPS_SPEED_SCALE 5
555
                                speed_east  /= GPS_SPEED_SCALE; // Wegen overflow Gefahr Wert jetzt schon runterskalieren
556
                                speed_north /= GPS_SPEED_SCALE; // Wegen overflow Gefahr Wert jetzt schon runterskalieren
528 salvo 557
 
558
 
559
                                int diff_p;  //Vom Modus abhaengige zusaetzliche Verstaerkung
560
                                if (hold_fast > 0) diff_p = GPS_PROP_FAST_V;
561
                                else diff_p = GPS_PROP_NRML_V;
562
 
563
                                //I Werte begrenzen
602 salvo 564
                                #define INT1_MAX (GPS_NICKROLL_MAX * GPS_V)/2 //ab 30.12.2007 auf Halben Maximalen Nick/Rollwert begrenzen
565 salvo 565
                                int_east1  =  ((((long)int_east)   * Parameter_UserParam2)/32)/GPS_USR_PAR_FKT;
566
                                int_north1 =  ((((long)int_north)  * Parameter_UserParam2)/32)/GPS_USR_PAR_FKT;  //Fehler behoben am 17.12.2007 vorher int_north= 
528 salvo 567
                                if (int_east1 > INT1_MAX) int_east1 =  INT1_MAX; //begrenzen
568
                                else if (int_east1 < -INT1_MAX) int_east1 =  -INT1_MAX;
569
                                if (int_north1 > INT1_MAX) int_north1 =  INT1_MAX; //begrenzen
570
                                else if (int_north1 < -INT1_MAX) int_north1 =  -INT1_MAX;
571
 
572
                                //PID Regler Werte aufsummieren
626 salvo 573
                                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
574
                                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 575
                                debug_gp_0      = gps_reg_x;  // zum Debuggen
576
                                debug_gp_1      = gps_reg_y; // zum Debuggen
528 salvo 577
 
578
                                //Ziel-Richtung bezogen auf Nordpol bestimmen
579
                                GPS_hdng_abs_2trgt = arctan_i(gps_reg_x,gps_reg_y);
580
 
581
                                // in Winkel 0...360 Grad umrechnen
582
                                if ((gps_reg_x >= 0)) GPS_hdng_abs_2trgt = ( 90-GPS_hdng_abs_2trgt);
583
                                else  GPS_hdng_abs_2trgt = (270 - GPS_hdng_abs_2trgt);
584
 
585
                                // Relative Richtung in bezug auf Nordachse des Kopters errechen
586
                                n= GyroKomp_Int/GYROKOMP_INC_GRAD_DEFAULT;
587
                                GPS_hdng_rel_2trgt      =       GPS_hdng_abs_2trgt - n;
588
                                if      ((GPS_hdng_rel_2trgt >180) && (GPS_hdng_abs_2trgt >=180)) GPS_hdng_rel_2trgt = GPS_hdng_rel_2trgt-360;
589
                                else if (GPS_hdng_rel_2trgt >180)  GPS_hdng_rel_2trgt = 360 - GPS_hdng_rel_2trgt;
590
                                else if (GPS_hdng_rel_2trgt <-180)  GPS_hdng_rel_2trgt = 360 + GPS_hdng_rel_2trgt;
591
 
592
                                // Regelabweichung aus x,y zu Ziel in Distanz umrechnen 
593
                                if (abs(gps_reg_x) > abs(gps_reg_y) )
594
                                {
595
                                        dev = (long)gps_reg_x; //Groesseren Wert wegen besserer Genauigkeit nehmen
596
                                        dev = abs((dev *1000) / (long) sin_i(GPS_hdng_abs_2trgt));
597
                                }
598
                                else
599
                                {
600
                                        dev = (long)gps_reg_y;
601
                                        dev = abs((dev *1000) / (long) cos_i(GPS_hdng_abs_2trgt));
602
                                }
603
                                GPS_dist_2trgt  = (int) dev;
604
                                // Winkel und Distanz in Nick und Rollgroessen umrechnen
621 salvo 605
                                n  = (int) +( (dev * (long) sin_i(GPS_hdng_rel_2trgt))/1000); //Rollwert bestimmen
606
                                n1 = (int) -( (dev * (long) cos_i(GPS_hdng_rel_2trgt))/1000); //Nickwert bestimmen
528 salvo 607
 
621 salvo 608
                                if (n > (GPS_NICKROLL_MAX * GPS_V)) n = (GPS_NICKROLL_MAX * GPS_V);
609
                                else if (n < -(GPS_NICKROLL_MAX * GPS_V)) n = -(GPS_NICKROLL_MAX * GPS_V);
610
                                if (n1 > (GPS_NICKROLL_MAX * GPS_V)) n1 = (GPS_NICKROLL_MAX * GPS_V);
611
                                else if (n1 < -(GPS_NICKROLL_MAX * GPS_V)) n1 = -(GPS_NICKROLL_MAX * GPS_V);
612
                                n  = n/GPS_V;
613
                                n1 = n1/GPS_V;
528 salvo 614
                                //Kleine Werte verstaerken, Grosse abschwaechen
621 salvo 615
/*                              n                       = sin_i((GPS_Roll*90)/(GPS_NICKROLL_MAX * GPS_V));
528 salvo 616
                                n_l                     = ((long) GPS_NICKROLL_MAX  * (long) n)/1000;
617
                                GPS_Roll        = (int) n_l;
618
                                n                       = sin_i((GPS_Nick*90)/(GPS_NICKROLL_MAX * GPS_V));
619
                                n_l                     = ((long) GPS_NICKROLL_MAX  * (long) n)/1000;
628 salvo 620
                                GPS_Nick        = (int) n_l;*/                           
621 salvo 621
 
528 salvo 622
                                if ((abs(dist_east) > GPS_DIST_MAX) || (abs(dist_north) > GPS_DIST_MAX))  // bei zu grossem Abstand abbrechen
623
                                {
624
                                        GPS_Roll        = 0;
625
                                        GPS_Nick        = 0;
626
                                        gps_state       = GPS_CRTL_IDLE;
627
                                        return (GPS_STST_ERR); 
628
                                        break;                                 
629
                                }
630
                                else
631
                                {
621 salvo 632
                                        GPS_Roll = n;
633
                                        GPS_Nick = n1;
528 salvo 634
                                        if ( cmd == GPS_CMD_REQ_HOME ) gps_state = GPS_CRTL_HOME_ACTIVE; // State umsetzen
635
                                        return (GPS_STST_OK);
636
                                }
637
                        }
638
                        else
639
                        {
640
                                if ( cmd == GPS_CMD_REQ_HOME ) gps_state = GPS_CRTL_HOME_ACTIVE; // State umsetzen
641
                                return (GPS_STST_OK);
642
                        }
643
                        break;
644
 
645
                default:
646
                        gps_state = GPS_CRTL_IDLE;
647
                        return (GPS_STST_ERR);
648
                        break;
649
        }      
650
        return (GPS_STST_ERR);
651
 
652
}
653