Subversion Repositories Projects

Rev

Rev 2196 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2136 - 1
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3
 
4
//############################################################################
5
//# HISTORY  gps.c
6
//#
7
//# 03.08.2015 cebra
8
//# - add: Routine um aus gegebenen Koordinaten mit Abstand und Winkel eine ZielKoordinate zu berechnen
9
//#    int nmea_move_horz(
10
//#    const nmeaPOS *start_pos,   /**< Start position in radians */
11
//#    nmeaPOS *end_pos,           /**< Result position in radians */
12
//#    double azimuth,             /**< Azimuth (degree) [0, 359] */
13
//#    double distance)             /**< Distance (km) */
14
//#
15
//# 27.06.2014 OG - NEU
16
//# - chg: auf #include "../gps/mymath.h" angepasst
17
//#
18
//# 20.06.2014 OG - NEU
19
//############################################################################
20
 
21
 
22
#include "../cpu.h"
23
#include <string.h>
24
#include <util/delay.h>
25
#include <avr/interrupt.h>
26
#include <stdlib.h>
27
#include <math.h>
28
#include "../main.h"
29
 
30
#include "../mk-data-structs.h"
31
#include "../gps/mymath.h"
32
#include "gps.h"
33
 
34
 
35
/*
36
// definiert in: mk_data-stucts.h
37
typedef struct
38
{
39
    u16 Distance;       // distance to target in cm
40
    s16 Bearing;        // course to target in deg
41
} __attribute__((packed)) GPS_PosDev_t;
42
*/
43
 
44
/*
45
// definiert in: mk_data-stucts.h
46
typedef struct
47
{
48
    s32 Longitude;      // in 1E-7 deg
49
    s32 Latitude;       // in 1E-7 deg
50
    s32 Altitude;       // in mm
51
    u8 Status;          // validity of data
52
} __attribute__((packed)) GPS_Pos_t;
53
*/
54
 
55
 
56
//--------------------------------------------------------------
57
 
58
#define NMEA_PI                     (3.141592653589793)             /**< PI value */
59
#define NMEA_PI180                  (NMEA_PI / 180)                 /**< PI division by 180 */
60
#define NMEA_EARTHRADIUS_KM         (6378)                          /**< Earth's mean radius in km */
61
#define R                           (6371)
62
#define NMEA_EARTHRADIUS_M          (NMEA_EARTHRADIUS_KM * 1000)    /**< Earth's mean radius in m */
63
#define NMEA_EARTH_SEMIMAJORAXIS_M  (6378137.0)                     /**< Earth's semi-major axis in m according WGS84 */
64
#define NMEA_EARTH_SEMIMAJORAXIS_KM (NMEA_EARTHMAJORAXIS_KM / 1000) /**< Earth's semi-major axis in km according WGS 84 */
65
#define NMEA_EARTH_FLATTENING       (1 / 298.257223563)             /**< Earth's flattening according WGS 84 */
66
#define NMEA_DOP_FACTOR             (5)                             /**< Factor for translating DOP to meters */
67
 
2196 - 68
 
69
// Definitonen für FollowMeStep2
70
#define LONG_DIV                    10000000
71
#define LAT_DIV                     LONG_DIV
2199 - 72
#define FOLLOWME_M2DEG              111111
73
#define FOLLOWME_ROUND_100          100
2196 - 74
 
75
 
2136 - 76
# define NMEA_POSIX(x)  x
77
 
78
 
79
 
80
/**
81
 * \fn nmea_degree2radian
82
 * \brief Convert degree to radian
83
 */
84
double nmea_degree2radian(double val)
85
{ return (val * NMEA_PI180); }
86
 
87
 
88
//------------------------------------------------------------------------------------------
89
nmeaPOS NMEApos;
90
nmeaPOS NMEATarget;
91
 
92
/**
93
 * \brief Horizontal move of point position
94
 */
95
int nmea_move_horz(
96
    const nmeaPOS *start_pos,   /**< Start position in radians */
97
    nmeaPOS *end_pos,           /**< Result position in radians */
98
    double azimuth,             /**< Azimuth (degree) [0, 359] */
99
    double distance             /**< Distance (km) */
100
    )
101
{
102
    nmeaPOS p1 = *start_pos;
103
    int RetVal = 1;
104
 
105
    distance /= NMEA_EARTHRADIUS_KM; /* Angular distance covered on earth's surface */
106
    azimuth = nmea_degree2radian(azimuth);
107
 
108
    end_pos->lat = asin( sin(p1.lat) * cos(distance) + cos(p1.lat) * sin(distance) * cos(azimuth));
109
 
110
    end_pos->lon = p1.lon + atan2( sin(azimuth) * sin(distance) * cos(p1.lat), cos(distance) - sin(p1.lat) * sin(end_pos->lat));
111
 
112
    if(NMEA_POSIX(isnan)(end_pos->lat) || NMEA_POSIX(isnan)(end_pos->lon))
113
    {
114
        end_pos->lat = 0; end_pos->lon = 0;
115
        RetVal = 0;
116
    }
117
 
118
    return RetVal;
119
}
120
 
121
 
2196 - 122
// Berechnet die Position der Kopters für FollowMeStep2
123
// Momentan wird die gleich Position ausgegeben
2136 - 124
 
2196 - 125
int followme_calculate_offset(
126
    const nmeaPOS *pkt_pos,     /**< Start position in radians */
127
    nmeaPOS *target_pos,        /**< Result position in radians */
128
    int d_lat,                  /**< Distance lat(m) */
2199 - 129
    int d_long                   /**< Distance long(m) */
2196 - 130
    )
131
{
2199 - 132
        nmeaPOS p1 = *pkt_pos;
2196 - 133
        // only for test the "Debug-Mode"
2199 - 134
    target_pos->lat = ( d_lat * ( LAT_DIV  / FOLLOWME_M2DEG ) );  //p1.lat +
135
    target_pos->lon = 100 * (uint32_t)( (float)FOLLOWME_ROUND_100 / cos( (float)p1.lat / (float)LONG_DIV ) ) ; //  ( d_long * ( LONG_DIV  / FOLLOWME_M2DEG ) ); //
136
            //    10     * 10000000 / 111111
2196 - 137
 
138
 
2199 - 139
    // p1.lon +  / FOLLOWME_M2DEG / FOLLOWME_ROUND_100 *
140
 
141
 
142
 
2196 - 143
        return 1;
144
}
145
 
146
 
2136 - 147
//###############################################################################################
148
 
149
 
150
 
151
//--------------------------------------------------------------
152
GPS_PosDev_t gps_Deviation( GPS_Pos_t pos1, GPS_Pos_t pos2 )
153
{
154
    int32_t      lat1, lon1, lat2, lon2;
155
    int32_t      d1, dlat;
156
    GPS_PosDev_t PosDev;
157
 
158
    lon1 = pos1.Longitude;
159
    lat1 = pos1.Latitude;
160
 
161
    lon2 = pos2.Longitude;
162
    lat2 = pos2.Latitude;
163
 
164
    d1   = (1359 * (int32_t)(c_cos_8192((lat1 + lat2) / 20000000)) * ((lon1 - lon2)/10))/ 10000000;
165
    dlat = (1113 * (lat1 - lat2) / 10000);
166
 
167
    PosDev.Bearing  = (my_atan2(d1, dlat) + 540) % 360;         // 360 +180 besserer Vergleich mit MkCockpit
168
    PosDev.Distance = sqrt32( d1 * d1 + dlat * dlat );          //
169
    //PosDev.Distance = sqrt32( d1 * d1 + dlat * dlat ) * 10;       // *10 um von dm auf cm zu kommen
170
 
171
    return PosDev;
172
}
173
 
174
 
175
///**
176
// * \brief Calculate distance between two points
177
// * \return Distance in meters
178
// */
179
//int32_t nmea_distance(
180
//        const nmeaPOS *from_pos,    /**< From position in radians */
181
//        const nmeaPOS *to_pos       /**< To position in radians */
182
//        )
183
//{
184
//  int32_t dist = ((int32_t)NMEA_EARTHRADIUS_M) * acos(
185
//        sin(to_pos->lat) * sin(from_pos->lat) +
186
//        cos(to_pos->lat) * cos(from_pos->lat) * cos(to_pos->lon - from_pos->lon)
187
//        );
188
//    return dist;
189
//}
190
 
191
 
192
 
193
//// Berechnung von Distanz und Winkel aus GPS-Daten home(MK eingeschaltet)
194
//// zur aktuellen Position(nach Motorstart)
195
//geo_t calc_geo(HomePos_t *home, GPS_Pos_t *pos)
196
//{ double lat1, lon1, lat2, lon2, d1, dlat;
197
//        geo_t geo;
198
//
199
//        lon1 = MK_pos.Home_Lon;
200
//        lat1 = MK_pos.Home_Lat;
201
//        lon2 = (double)pos->Longitude   / 10000000.0;
202
//        lat2 = (double)pos->Latitude    / 10000000.0;
203
//
204
//        // Formel verwendet von http://www.kompf.de/gps/distcalc.html
205
//        // 111.3 km = Abstand zweier Breitenkreise und/oder zweier Längenkreise am Äquator
206
//        // es wird jedoch in Meter weiter gerechnet
207
//        d1       = 111300 * (double)cos((double)(lat1 + lat2) / 2 * DEG_TO_RAD) * (lon1 - lon2);
208
//        dlat = 111300 * (double)(lat1 - lat2);
209
//        // returns a value in metres http://www.kompf.de/gps/distcalc.html
210
//        geo.bearing = fmod((RAD_TO_DEG * (double)atan2(d1, dlat)) + 180, 360); // +180 besserer Vergleich mit MkCockpit
211
//        if (geo.bearing > 360) geo.bearing -= 360; // bekam schon Werte über 400
212
//        geo.distance = sqrt(d1 * d1 + dlat * dlat);
213
//        return(geo);
214
//}
215
 
216
// Berechnung von Distanz und Winkel aus GPS-Daten home(MK eingeschaltet)
217
// zur aktuellen Position(nach Motorstart)
218
//--------------------------------------------------------------
219
//--------------------------------------------------------------
220
 
221
/*
222
geo_t calc_geo( HomePos_t *home, GPS_Pos_t *pos )
223
{
224
    int32_t lat1, lon1, lat2, lon2;
225
        int32_t d1, dlat;
226
        geo_t geo;
227
 
228
        lon1 = home->Home_Lon;
229
        lat1 = home->Home_Lat;
230
        lon2 = pos->Longitude;
231
        lat2 = pos->Latitude;
232
 
233
        if( !CheckGPS )
234
        {
235
            writex_gpspos(  0, 3, home->Home_Lat , MNORMAL,  0,0);    // Anzeige: Breitengrad (Latitude)
236
            writex_gpspos( 11, 3, home->Home_Lon , MNORMAL,  0,0);    // Anzeige: Laengengrad (Longitude)
237
            writex_gpspos(  0, 4, pos->Latitude  , MNORMAL,  0,0);    // Anzeige: Breitengrad (Latitude)
238
            writex_gpspos( 11, 4, pos->Longitude , MNORMAL,  0,0);    // Anzeige: Laengengrad (Longitude)
239
 
240
            //lcd_puts_at (0, 3, my_itoa(home->Home_Lat, 10, 7, 7), 0);     // 30.05.2014 OG: my_itoa() gibt es nicht mehr
241
            //lcd_puts_at (11, 3, my_itoa(home->Home_Lon, 10, 7, 7), 0);    // 30.05.2014 OG: my_itoa() gibt es nicht mehr
242
            //lcd_puts_at (0, 4, my_itoa(pos->Latitude, 10, 7, 7), 0);      // 30.05.2014 OG: my_itoa() gibt es nicht mehr
243
            //lcd_puts_at (11, 4, my_itoa(pos->Longitude, 10, 7, 7), 0);    // 30.05.2014 OG: my_itoa() gibt es nicht mehr
244
        }
245
 
246
        // Formel verwendet von http://www.kompf.de/gps/distcalc.html
247
        // 111.3 km = Abstand zweier Breitenkreise und/oder zweier Langenkreise am Äquator
248
        // es wird jedoch in dm Meter weiter gerechnet
249
        // (tlon1 - tlon2)/10) sonst uint32_t-Ãœberlauf bei cos(0) gleich 1
250
        d1       = (1359 * (int32_t)(c_cos_8192((lat1 + lat2) / 20000000)) * ((lon1 - lon2)/10))/ 10000000;
251
        dlat = 1113 * (lat1 - lat2) / 10000;
252
        geo.bearing = (my_atan2(d1, dlat) + 540) % 360; // 360 +180 besserer Vergleich mit MkCockpit
253
        geo.distance = sqrt32(d1 * d1 + dlat * dlat);
254
        if( !CheckGPS )
255
        {
256
            lcd_printp_at (0, 5, PSTR("Bear:"), 0);
257
 
258
            lcdx_printf_at_P( 5, 5, MNORMAL, 0,0, PSTR("%3d"), geo.bearing );
259
            //lcd_puts_at (5, 5, my_itoa((uint32_t)geo.bearing, 3, 0, 0), 0);       // 30.05.2014 OG: my_itoa() gibt es nicht mehr
260
 
261
            lcd_printp_at (8, 5, PSTR("\x1e"), 0);
262
            lcd_printp_at (9, 5, PSTR("Dist:"), 0);
263
 
264
            lcdx_printf_at_P( 15, 5, MNORMAL, 0,0, PSTR("%3d"), geo.distance );
265
            //lcd_puts_at (15, 5, my_itoa((uint32_t)geo.distance, 3, 1, 1), 0);     // 30.05.2014 OG: my_itoa() gibt es nicht mehr
266
 
267
            lcd_printp_at (20, 5, PSTR("m"), 0);
268
        }
269
 
270
 
271
        return(geo);
272
}
273
*/
274