##// END OF EJS Templates
codigo fuente de librería NMEAlib++ basado en el codigo original de:...
aaguilar -
r96:97
parent child
Show More
@@ -0,0 +1,34
1 /*
2 *
3 * NMEA library
4 * URL: http://nmea.sourceforge.net
5 * Author: Tim (xtimor@gmail.com)
6 * Licence: http://www.gnu.org/licenses/lgpl.html
7 * $Id: config.h 17 2008-03-11 11:56:11Z xtimor $
8 *
9 */
10
11 #ifndef __NMEA_CONFIG_H__
12 #define __NMEA_CONFIG_H__
13
14 #define NMEA_VERSION ("0.5.3")
15 #define NMEA_VERSION_MAJOR (0)
16 #define NMEA_VERSION_MINOR (5)
17 #define NMEA_VERSION_PATCH (3)
18
19 #define NMEA_CONVSTR_BUF (256)
20 #define NMEA_TIMEPARSE_BUF (256)
21
22 #define NMEA_UNI
23
24 #define NMEA_POSIX(x) x
25 #define NMEA_INLINE inline
26
27 #if !defined(NDEBUG) && !defined(NMEA_CE)
28 # include <assert.h>
29 # define NMEA_ASSERT(x) assert(x)
30 #else
31 # define NMEA_ASSERT(x)
32 #endif
33
34 #endif /* __NMEA_CONFIG_H__ */
@@ -0,0 +1,67
1 /*
2 *
3 * NMEA library
4 * URL: http://nmea.sourceforge.net
5 * Author: Tim (xtimor@gmail.com)
6 * Licence: http://www.gnu.org/licenses/lgpl.html
7 * $Id: context.c 17 2008-03-11 11:56:11Z xtimor $
8 *
9 */
10
11 #include "context.h"
12
13 #include <string.h>
14 #include <stdarg.h>
15 #include <stdio.h>
16
17 nmeaPROPERTY * nmea_property()
18 {
19 static nmeaPROPERTY prop = {
20 0, 0, NMEA_DEF_PARSEBUFF
21 };
22
23 return &prop;
24 }
25
26 void nmea_trace(const char *str, ...)
27 {
28 int size;
29 va_list arg_list;
30 char buff[NMEA_DEF_PARSEBUFF];
31 nmeaTraceFunc func = nmea_property()->trace_func;
32
33 if(func)
34 {
35 va_start(arg_list, str);
36 size = NMEA_POSIX(vsnprintf)(&buff[0], NMEA_DEF_PARSEBUFF - 1, str, arg_list);
37 va_end(arg_list);
38
39 if(size > 0)
40 (*func)(&buff[0], size);
41 }
42 }
43
44 void nmea_trace_buff(const char *buff, int buff_size)
45 {
46 nmeaTraceFunc func = nmea_property()->trace_func;
47 if(func && buff_size)
48 (*func)(buff, buff_size);
49 }
50
51 void nmea_error(const char *str, ...)
52 {
53 int size;
54 va_list arg_list;
55 char buff[NMEA_DEF_PARSEBUFF];
56 nmeaErrorFunc func = nmea_property()->error_func;
57
58 if(func)
59 {
60 va_start(arg_list, str);
61 size = NMEA_POSIX(vsnprintf)(&buff[0], NMEA_DEF_PARSEBUFF - 1, str, arg_list);
62 va_end(arg_list);
63
64 if(size > 0)
65 (*func)(&buff[0], size);
66 }
67 }
@@ -0,0 +1,44
1 /*
2 *
3 * NMEA library
4 * URL: http://nmea.sourceforge.net
5 * Author: Tim (xtimor@gmail.com)
6 * Licence: http://www.gnu.org/licenses/lgpl.html
7 * $Id: context.h 4 2007-08-27 13:11:03Z xtimor $
8 *
9 */
10
11 #ifndef __NMEA_CONTEXT_H__
12 #define __NMEA_CONTEXT_H__
13
14 #include "config.h"
15
16 #define NMEA_DEF_PARSEBUFF (1024)
17 #define NMEA_MIN_PARSEBUFF (256)
18
19 #ifdef __cplusplus
20 extern "C" {
21 #endif
22
23 typedef void (*nmeaTraceFunc)(const char *str, int str_size);
24 typedef void (*nmeaErrorFunc)(const char *str, int str_size);
25
26 typedef struct _nmeaPROPERTY
27 {
28 nmeaTraceFunc trace_func;
29 nmeaErrorFunc error_func;
30 int parse_buff_size;
31
32 } nmeaPROPERTY;
33
34 nmeaPROPERTY * nmea_property();
35
36 void nmea_trace(const char *str, ...);
37 void nmea_trace_buff(const char *buff, int buff_size);
38 void nmea_error(const char *str, ...);
39
40 #ifdef __cplusplus
41 }
42 #endif
43
44 #endif /* __NMEA_CONTEXT_H__ */
@@ -0,0 +1,48
1 /*
2 * nemeaCode.cpp
3 *
4 * Created on: Oct 21, 2014
5 * Author: Alan Aguilar Sologuren
6 */
7
8 #include "nmeaCode.h"
9
10 #include <string.h>
11 #include <stdarg.h>
12 #include <stdio.h>
13 #include <time.h>
14 #include <math.h>
15 #include <float.h>
16 #include <limits.h>
17 #include <ctype.h>
18 #include <stdlib.h>
19
20 nmeaCode::nmeaCode(char* name=nullptr):
21 codebuff(nullptr){
22
23 }
24
25 nmeaCode::~nmeaCode() {
26 // TODO Auto-generated destructor stub
27 }
28
29 virtual void nmeaCode::code_init() {
30
31 }
32 virtual int nmeaCode::code_gen(char *buff, int buff_sz) {
33 return 0;
34 }
35
36 virtual int nmeaCode::code_parse(const char *buff, int buff_sz) {
37 return 0;
38 }
39
40
41 ////////////////////////////////////////////////////////////////////////////////////////
42
43
44
45
46
47
48
@@ -0,0 +1,32
1 /*
2 * nemeaCode.h
3 *
4 * Created on: Oct 21, 2014
5 * Author: Alan Aguilar Sologuren
6 */
7
8 #ifndef NMEALIB_NMEALIB___NMEACODE_H_
9 #define NMEALIB_NMEALIB___NMEACODE_H_
10
11 #include "nmea_defs.h"
12
13 class nmeaCode {
14 public:
15 nmeaCode(char* name=nullptr);
16 virtual ~nmeaCode();
17
18 virtual void code_init(void);
19 virtual int code_gen(char *buff, int buff_sz);// TODO para generator
20 virtual int code_parse(const char *buff, int buff_sz);// TODO para parser
21
22
23
24
25 private:
26 const char codename[8];
27 const int type;
28 char *codebuff;
29
30 };
31
32 #endif /* NMEALIB_NMEALIB___NMEACODE_H_ */
@@ -0,0 +1,194
1 /*
2 * nmeaGenerator.cpp
3 *
4 * Created on: Oct 21, 2014
5 * Author: Alan Aguilar Sologuren
6 */
7
8 #include <string.h>
9 #include <stdlib.h>
10 #include "nmeaGenerator.h"
11
12
13 nmeaGenerator::nmeaGenerator() {
14 // TODO Auto-generated constructor stub
15
16 }
17
18 nmeaGenerator::~nmeaGenerator() {
19 // TODO Auto-generated destructor stub
20 }
21
22
23 virtual int nmeaGenerator::code_info2nmea(const nmeaInfo *info, nmeaCode* code)
24 {
25 return 1;
26 }
27
28
29 /*
30 * low level
31 */
32
33 int nmeaGenerator::nmea_gen_init(nmeaInfo *info)
34 {
35 int RetVal = 1; int smask = info->smask;
36
37 info->code_init_INFO();
38 info->smask = smask;
39
40 info->lat = NMEA_DEF_LAT;
41 info->lon = NMEA_DEF_LON;
42
43 if(init_call)
44 RetVal = (*init_call)(this, info);
45
46 if(RetVal && next)
47 RetVal = next->nmea_gen_init(info);
48
49 return RetVal;
50 }
51
52 int nmeaGenerator::nmea_gen_loop( nmeaInfo *info)
53 {
54 int RetVal = 1;
55
56 if(loop_call)
57 RetVal = (*loop_call)(this, info);
58
59 if(RetVal && next)
60 RetVal = next->nmea_gen_loop(info);
61
62 return RetVal;
63 }
64
65 int nmeaGenerator::nmea_gen_reset(nmeaInfo *info)
66 {
67 int RetVal = 1;
68
69 if(reset_call)
70 RetVal = (*reset_call)(this, info);
71
72 return RetVal;
73 }
74
75 void nmeaGenerator::nmea_gen_destroy()
76 {
77 if(next)
78 {
79 next->nmea_gen_destroy();
80 next = 0;
81 }
82
83 if(destroy_call)
84 (*destroy_call)(this);
85
86 free(this);
87 }
88
89 void nmeaGenerator::nmea_gen_add(nmeaGenerator *gen)
90 {
91 if(next)
92 next->nmea_gen_add(gen);
93 else
94 next = gen;
95 }
96
97 int nmeaGenerator::nmea_generate_from(
98 char *buff, int buff_sz,
99 nmeaInfo *info,
100 nmeaCode *code
101 )
102 {
103 int retval;
104
105 if(0 != (retval = nmea_gen_loop(info)))
106 retval = nmea_generate(buff, buff_sz, info, code);
107
108 return retval;
109 }
110
111
112
113 int nmeaGenerator::nmea_igen_pos_rmove_destroy(void)
114 {
115 return 1;
116 };
117
118 /*
119 * generator create
120 */
121
122 nmeaGenerator* nmeaGenerator::__nmea_create_generator(int type, nmeaInfo *info)
123 {
124 nmeaGenerator* gen = nullptr;
125 switch(type)
126 {
127 case NMEA_GEN_NOISE:
128 gen = new nmeaGenerator();
129 gen->init_call = &info->nmea_igen_noise_init;
130 gen->loop_call = &info->nmea_igen_noise_loop;
131 gen->reset_call = &info->nmea_igen_noise_reset;
132 break;
133 case NMEA_GEN_STATIC:
134 case NMEA_GEN_SAT_STATIC:
135 gen = new nmeaGenerator();
136 gen->init_call = &info->nmea_igen_static_init;
137 gen->loop_call = &info->nmea_igen_static_loop;
138 gen->reset_call = &info->nmea_igen_static_reset;
139 break;
140 case NMEA_GEN_SAT_ROTATE:
141 gen = new nmeaGenerator();
142 gen->init_call = &info->nmea_igen_rotate_init;
143 gen->loop_call = &info->nmea_igen_rotate_loop;
144 gen->reset_call = &info->nmea_igen_rotate_reset;
145 break;
146 case NMEA_GEN_POS_RANDMOVE:
147 gen = new nmeaGenerator();
148 gen->init_call = &info->nmea_igen_pos_rmove_init;
149 gen->loop_call = &info->nmea_igen_pos_rmove_loop;
150 gen->destroy_call = &nmea_igen_pos_rmove_destroy;
151 break;
152 case NMEA_GEN_ROTATE:
153 gen = new nmeaGenerator();
154 gen = __nmea_create_generator(NMEA_GEN_SAT_ROTATE, info);
155 gen->nmea_gen_add(__nmea_create_generator(NMEA_GEN_POS_RANDMOVE, info));
156 break;
157 };
158 return this;
159 }
160
161 nmeaGenerator * nmeaGenerator::nmea_create_generator(int type, nmeaInfo *info)
162 {
163 nmeaGenerator *gen = __nmea_create_generator(type, info);
164
165 if(gen)
166 gen->nmea_gen_init(info);
167
168 return gen;
169 }
170
171 void nmeaGenerator::nmea_destroy_generator(void)
172 {
173 nmea_gen_destroy();
174 }
175
176
177
178 int nmeaGenerator::nmea_generate(char *buff, int buff_sz, const nmeaInfo *info, nmeaCode *code)
179 {
180 int gen_count = 0;
181
182 if(!buff)
183 return 0;
184
185 while(code)
186 {
187 code_info2nmea(info, code)
188 gen_count += code->code_gen(buff + gen_count, buff_sz - gen_count);
189 code += 1;
190 if(buff_sz - gen_count <= 0)
191 break;
192 }
193 return gen_count;
194 }
@@ -0,0 +1,70
1 /*
2 * nmeaGenerator.h
3 *
4 * Created on: Oct 21, 2014
5 * Author: Alan Aguilar Sologuren
6 */
7
8 #ifndef NMEALIB_NMEALIB___NMEAGENERATOR_H_
9 #define NMEALIB_NMEALIB___NMEAGENERATOR_H_
10
11 #include "nmea_defs.h"
12 #include "nmeaCode.h"
13 #include "nmeaInfo.h"
14
15 /*
16 * low level
17 */
18
19 typedef int (*nmeaNMEA_GEN_INIT)(nmeaGenerator *gen, nmeaInfo *info);
20 typedef int (*nmeaNMEA_GEN_LOOP)(nmeaGenerator *gen, nmeaInfo *info);
21 typedef int (*nmeaNMEA_GEN_RESET)(nmeaGenerator *gen, nmeaInfo *info);
22 typedef int (*nmeaNMEA_GEN_DESTROY)(nmeaGenerator *gen);
23
24 enum nmeaGENTYPE
25 {
26 NMEA_GEN_NOISE = 0,
27 NMEA_GEN_STATIC,
28 NMEA_GEN_ROTATE,
29
30 NMEA_GEN_SAT_STATIC,
31 NMEA_GEN_SAT_ROTATE,
32 NMEA_GEN_POS_RANDMOVE,
33
34 NMEA_GEN_LAST
35 };
36
37 class nmeaGenerator {
38 public:
39 nmeaGenerator();
40 virtual ~nmeaGenerator();
41
42
43 virtual int code_info2nmea(const nmeaInfo *info, nmeaCode* code);
44
45 int nmea_gen_init(nmeaInfo *info);
46 int nmea_gen_loop(nmeaInfo *info);
47 int nmea_gen_reset(nmeaInfo *info);
48 void nmea_gen_destroy(void);
49 void nmea_gen_add(nmeaGenerator *from);
50 int nmea_generate(char *buff, int buff_sz, const nmeaInfo *info, nmeaCode* code);
51
52 private:
53 void *gen_data;
54 nmeaNMEA_GEN_INIT init_call;
55 nmeaNMEA_GEN_LOOP loop_call;
56 nmeaNMEA_GEN_RESET reset_call;
57 nmeaNMEA_GEN_DESTROY destroy_call;
58 nmeaGenerator *next;
59
60 int nmea_generate_from(char *buff, int buff_sz,nmeaInfo *info, nmeaCode *code);
61 int nmea_igen_pos_rmove_destroy(void);
62
63
64 nmeaGenerator * __nmea_create_generator(int type, nmeaInfo *info);
65 nmeaGenerator * nmea_create_generator(int type, nmeaInfo *info);
66 void nmea_destroy_generator(void);
67
68 };
69
70 #endif /* NMEALIB_NMEALIB___NMEAGENERATOR_H_ */
@@ -0,0 +1,257
1 /*
2 * nmeaInfo.cpp
3 *
4 * Created on: Oct 21, 2014
5 * Author: Alan Aguilar Sologuren
6 */
7
8 #include "utils.h"
9 #include "nmeaInfo.h"
10
11 nmeaInfo::nmeaInfo() {
12 // TODO Auto-generated constructor stub
13
14 }
15
16 nmeaInfo::~nmeaInfo() {
17 // TODO Auto-generated destructor stub
18 }
19
20 void nmeaInfo::code_init_INFO()
21 {
22
23 code_time_now();
24 sig = NMEA_SIG_BAD;
25 fix = NMEA_FIX_BAD;
26 }
27
28 static void nmeaInfo::code_time_now() {
29 time_t lt;
30 struct tm *tt;
31
32 time(&lt);
33 tt = gmtime(&lt);
34
35 utc.year = tt->tm_year;
36 utc.mon = tt->tm_mon;
37 utc.day = tt->tm_mday;
38 utc.hour = tt->tm_hour;
39 utc.min = tt->tm_min;
40 utc.sec = tt->tm_sec;
41 utc.hsec = 0;
42 }
43
44 /**
45 * \brief Convert position from INFO to radians position
46 */
47 void nmeaInfo::code_info2pos(nmeaPOS *pos) {
48 pos->lat = code_ndeg2radian(lat);
49 pos->lon = code_ndeg2radian(lon);
50 }
51
52 /**
53 * \brief Convert radians position to INFOs position
54 */
55 void nmeaInfo::code_pos2info(const nmeaPOS *pos) {
56 lat = code_radian2ndeg(pos->lat);
57 lon = code_radian2ndeg(pos->lon);
58 }
59
60
61
62 /*
63 * NOISE generator
64 */
65
66 int nmeaInfo::nmea_igen_noise_init()
67 {
68 return 1;
69 }
70
71 int nmeaInfo::nmea_igen_noise_loop()
72 {
73 int it;
74 int in_use;
75
76 sig = (int)nmea_random(1, 3);
77 PDOP = nmea_random(0, 9);
78 HDOP = nmea_random(0, 9);
79 VDOP = nmea_random(0, 9);
80 fix = (int)nmea_random(2, 3);
81 lat = nmea_random(0, 100);
82 lon = nmea_random(0, 100);
83 speed = nmea_random(0, 100);
84 direction = nmea_random(0, 360);
85 declination = nmea_random(0, 360);
86 elv = (int)nmea_random(-100, 100);
87
88 satinfo.inuse = 0;
89 satinfo.inview = 0;
90
91 for(it = 0; it < 12; ++it)
92 {
93 satinfo.sat[it].id = it;
94 satinfo.sat[it].in_use = in_use = (int)nmea_random(0, 3);
95 satinfo.sat[it].elv = (int)nmea_random(0, 90);
96 satinfo.sat[it].azimuth = (int)nmea_random(0, 359);
97 satinfo.sat[it].sig = (int)(in_use?nmea_random(40, 99):nmea_random(0, 40));
98
99 if(in_use)
100 satinfo.inuse++;
101 if(satinfo.sat[it].sig > 0)
102 satinfo.inview++;
103 }
104
105 return 1;
106 }
107
108 int nmeaInfo::nmea_igen_noise_reset()
109 {
110 return 1;
111 }
112
113 /*
114 * STATIC generator
115 */
116
117 int nmeaInfo::nmea_igen_static_loop()
118 {
119 code_time_now();
120 return 1;
121 };
122
123 int nmeaInfo::nmea_igen_static_reset()
124 {
125 satinfo.inuse = 4;
126 satinfo.inview = 4;
127
128 satinfo.sat[0].id = 1;
129 satinfo.sat[0].in_use = 1;
130 satinfo.sat[0].elv = 50;
131 satinfo.sat[0].azimuth = 0;
132 satinfo.sat[0].sig = 99;
133
134 satinfo.sat[1].id = 2;
135 satinfo.sat[1].in_use = 1;
136 satinfo.sat[1].elv = 50;
137 satinfo.sat[1].azimuth = 90;
138 satinfo.sat[1].sig = 99;
139
140 satinfo.sat[2].id = 3;
141 satinfo.sat[2].in_use = 1;
142 satinfo.sat[2].elv = 50;
143 satinfo.sat[2].azimuth = 180;
144 satinfo.sat[2].sig = 99;
145
146 satinfo.sat[3].id = 4;
147 satinfo.sat[3].in_use = 1;
148 satinfo.sat[3].elv = 50;
149 satinfo.sat[3].azimuth = 270;
150 satinfo.sat[3].sig = 99;
151
152 return 1;
153 }
154
155 int nmeaInfo::nmea_igen_static_init()
156 {
157 sig = 3;
158 fix = 3;
159
160 nmea_igen_static_reset();
161
162 return 1;
163 }
164
165 /*
166 * SAT_ROTATE generator
167 */
168
169 int nmeaInfo::nmea_igen_rotate_loop()
170 {
171 int it;
172 int count = satinfo.inview;
173 double deg = 360 / (count?count:1);
174 double srt = (count?(satinfo.sat[0].azimuth):0) + 5;
175
176 code_time_now();
177
178 for(it = 0; it < count; ++it)
179 {
180 satinfo.sat[it].azimuth =
181 (int)((srt >= 360)?srt - 360:srt);
182 srt += deg;
183 }
184
185 return 1;
186 };
187
188 int nmeaInfo::nmea_igen_rotate_reset()
189 {
190 int it;
191 double deg = 360 / 8;
192 double srt = 0;
193
194 satinfo.inuse = 8;
195 satinfo.inview = 8;
196
197 for(it = 0; it < satinfo.inview; ++it)
198 {
199 satinfo.sat[it].id = it + 1;
200 satinfo.sat[it].in_use = 1;
201 satinfo.sat[it].elv = 5;
202 satinfo.sat[it].azimuth = (int)srt;
203 satinfo.sat[it].sig = 80;
204 srt += deg;
205 }
206
207 return 1;
208 }
209
210 int nmeaInfo::nmea_igen_rotate_init()
211 {
212 sig = 3;
213 fix = 3;
214
215 nmea_igen_rotate_reset();
216
217 return 1;
218 }
219
220 /*
221 * POS_RANDMOVE generator
222 */
223
224 int nmeaInfo::nmea_igen_pos_rmove_init()
225 {
226 sig = 3;
227 fix = 3;
228 direction = declination = 0;
229 speed = 20;
230 return 1;
231 }
232
233 int nmeaInfo::nmea_igen_pos_rmove_loop()
234 {
235 nmeaPOS crd;
236
237 direction += nmea_random(-10, 10);
238 speed += nmea_random(-2, 3);
239
240 if(direction < 0)
241 direction = 359 + direction;
242 if(direction > 359)
243 direction -= 359;
244
245 if(speed > 40)
246 speed = 40;
247 if(speed < 1)
248 speed = 1;
249
250 code_info2pos(&crd);
251 code_move_horz(&crd, &crd, direction, speed / 3600);
252 code_pos2info(&crd);
253
254 declination = direction;
255
256 return 1;
257 };
@@ -0,0 +1,84
1 /*
2 * nmeaInfo.h
3 *
4 * Created on: Oct 21, 2014
5 * Author: Alan Aguilar Sologuren
6 */
7
8 #ifndef NMEALIB___NMEAINFO_H_
9 #define NMEALIB___NMEAINFO_H_
10
11 #include "nmea_defs.h"
12 /**
13 * Information about satellite
14 * @see nmeaSATINFO
15 * @see nmeaGPGSV
16 */
17 typedef struct _nmeaSATELLITE
18 {
19 int id; /**< Satellite PRN number */
20 int in_use; /**< Used in position fix */
21 int elv; /**< Elevation in degrees, 90 maximum */
22 int azimuth; /**< Azimuth, degrees from true north, 000 to 359 */
23 int sig; /**< Signal, 00-99 dB */
24
25 } nmeaSATELLITE;
26
27 /**
28 * Information about all satellites in view
29 * @see nmeaINFO
30 * @see nmeaGPGSV
31 */
32 typedef struct _nmeaSATINFO
33 {
34 int inuse; /**< Number of satellites in use (not those in view) */
35 int inview; /**< Total number of satellites in view */
36 nmeaSATELLITE sat[NMEA_MAXSAT]; /**< Satellites information */
37
38 } nmeaSATINFO;
39
40 /**
41 * Summary GPS information from all parsed packets,
42 * used also for generating NMEA stream
43 * @see nmea_parse
44 * @see nmea_GPGGA2info, nmea_...2info
45 */
46 class nmeaInfo {
47 public:
48 nmeaInfo();
49 virtual ~nmeaInfo();
50 void code_init_INFO();
51 static void code_time_now();
52 void code_info2pos(nmeaPOS *pos);
53 void code_pos2info(const nmeaPOS *pos);
54
55 int nmea_igen_noise_init();
56 int nmea_igen_noise_loop();
57 int nmea_igen_noise_reset();
58 int nmea_igen_static_loop();
59 int nmea_igen_static_reset();
60 int nmea_igen_static_init();
61 int nmea_igen_rotate_loop();
62 int nmea_igen_rotate_reset();
63 int nmea_igen_rotate_init();
64 int nmea_igen_pos_rmove_init();
65 int nmea_igen_pos_rmove_loop();
66
67 private:
68 int smask; /**< Mask specifying types of packages from which data have been obtained */
69 nmeaTIME utc; /**< UTC of position */
70 int sig; /**< GPS quality indicator (0 = Invalid; 1 = Fix; 2 = Differential, 3 = Sensitive) */
71 int fix; /**< Operating mode, used for navigation (1 = Fix not available; 2 = 2D; 3 = 3D) */
72 double PDOP; /**< Position Dilution Of Precision */
73 double HDOP; /**< Horizontal Dilution Of Precision */
74 double VDOP; /**< Vertical Dilution Of Precision */
75 double lat; /**< Latitude in NDEG - +/-[degree][min].[sec/60] */
76 double lon; /**< Longitude in NDEG - +/-[degree][min].[sec/60] */
77 double elv; /**< Antenna altitude above/below mean sea level (geoid) in meters */
78 double speed; /**< Speed over the ground in kilometers/hour */
79 double direction; /**< Track angle in degrees True */
80 double declination; /**< Magnetic variation degrees (Easterly var. subtracts from true course) */
81 nmeaSATINFO satinfo; /**< Satellites information */
82 };
83
84 #endif /* NMEALIB___NMEAINFO_H_ */
@@ -0,0 +1,309
1 /*
2 * nmeaParser.cpp
3 *
4 * Created on: Oct 21, 2014
5 * Author: Alan Aguilar Sologuren
6 */
7
8 #include "nmea_defs.h"
9 #include "nmeaParser.h"
10
11 /**
12 * \brief Initialization of parser object
13 */
14 nmeaParser::nmeaParser():
15 top_node(nullptr),end_node(nullptr),
16 buffer(nullptr),buff_size(0),
17 buff_use(0){
18 int buff_sz = nmea_property()->parse_buff_size;
19 NMEA_ASSERT(this);
20
21 if(buff_sz < NMEA_MIN_PARSEBUFF)
22 buff_sz = NMEA_MIN_PARSEBUFF;
23
24 if(0 == (buffer = malloc(buff_size)))
25 nmea_error("Insufficient memory!");
26 delete this;
27 else
28 {
29 buff_size = buff_sz;
30
31 }
32 }
33
34 /**
35 * \brief Destroy parser object
36 */
37 nmeaParser::~nmeaParser() {
38 NMEA_ASSERT(this && buffer);
39 free(buffer);
40 nmea_parser_queue_clear();
41 }
42
43 /**
44 * \brief Analysis of buffer and put results to information structure
45 * @return Number of packets wos parsed
46 */
47 int nmeaParser::nmea_parse(const char *buff, int buff_sz, nmeaInfo *info )
48 {
49 int ptype, nread = 0;
50 nmeaCode *pack = 0;
51
52 NMEA_ASSERT(this && buffer);
53
54 nmea_parser_push(buff, buff_sz);
55
56 while(GPNON != (ptype = nmea_parser_pop(&pack)))
57 {
58 nread++;
59 code_2info(pack, info);
60 free(pack);
61 }
62
63 return nread;
64 }
65
66 /*
67 * low level
68 */
69
70 int nmeaParser::nmea_parser_real_push(const char *buff, int buff_sz)
71 {
72 int nparsed = 0, crc, sen_sz, ptype;
73 nmeaParserNODE *node = 0;
74
75 NMEA_ASSERT(this && buffer);
76
77 /* add */
78 if(buff_use + buff_sz >= buff_size)
79 nmea_parser_buff_clear(parser);
80
81 memcpy(buffer + buff_use, buff, buff_sz);
82 buff_use += buff_sz;
83
84 /* parse */
85 for(;;node = 0)
86 {
87 sen_sz = nmea_find_tail(
88 (const char *)buffer + nparsed,
89 (int)buff_use - nparsed, &crc);
90
91 if(!sen_sz)
92 {
93 if(nparsed)
94 memcpy(
95 buffer,
96 buffer + nparsed,
97 buff_use -= nparsed);
98 break;
99 }
100 else if(crc >= 0)
101 {
102 if(!node->pack->code_parse( (const char *)buffer + nparsed,
103 sen_sz)
104 {
105 free(node);
106 node = 0;
107 }
108
109 if(node)
110 {
111 if(end_node)
112 ((nmeaParserNODE *)end_node)->next_node = node;
113 end_node = node;
114 if(!top_node)
115 top_node = node;
116 node->next_node = 0;
117 }
118 }
119
120 nparsed += sen_sz;
121 }
122 return nparsed;
123 }
124
125 /**
126 * \brief Analysis of buffer and keep results into parser
127 * @return Number of bytes wos parsed from buffer
128 */
129 int nmeaParser::nmea_parser_push(const char *buff, int buff_sz)
130 {
131 int nparse, nparsed = 0;
132
133 do
134 {
135 if(buff_sz > buff_size)
136 nparse = buff_size;
137 else
138 nparse = buff_sz;
139
140 nparsed += nmea_parser_real_push(
141 buff, nparse);
142
143 buff_sz -= nparse;
144
145 } while(buff_sz);
146
147 return nparsed;
148 }
149
150 /**
151 * \brief Get type of top packet keeped into parser
152 * @return Type of packet
153 * @see nmeaPACKTYPE
154 */
155 int nmeaParser::nmea_parser_top()
156 {
157 int retval = GPNON;
158 nmeaParserNODE *node = (nmeaParserNODE *)top_node;
159
160 NMEA_ASSERT(this && buffer);
161
162 if(node)
163 retval = node->pack->type;
164
165 return retval;
166 }
167
168 /**
169 * \brief Withdraw top packet from parser
170 * @return Received packet type
171 * @see nmeaPACKTYPE
172 */
173 int nmeaParser::nmea_parser_pop( nmeaCode **pack_ptr)
174 {
175 int retval = GPNON;
176 nmeaParserNODE *node = (nmeaParserNODE *)top_node;
177
178 NMEA_ASSERT(this && buffer);
179
180 if(node)
181 {
182 *pack_ptr = node->pack;
183 retval = node->pack->type;
184 top_node = node->next_node;
185 if(!top_node)
186 end_node = 0;
187 free(node);
188 }
189 return retval;
190 }
191
192 /**
193 * \brief Get top packet from parser without withdraw
194 * @return Received packet type
195 * @see nmeaPACKTYPE
196 */
197 int nmeaParser::nmea_parser_peek(nmeaCode **pack_ptr)
198 {
199 int retval = GPNON;
200 nmeaParserNODE *node = (nmeaParserNODE *)top_node;
201
202 NMEA_ASSERT(this && buffer);
203
204 if(node)
205 {
206 *pack_ptr = node->pack;
207 retval = node->pack->type;
208 }
209
210 return retval;
211 }
212
213 /**
214 * \brief Delete top packet from parser
215 * @return Deleted packet type
216 * @see nmeaPACKTYPE
217 */
218 int nmeaParser::nmea_parser_drop()
219 {
220 int retval = GPNON;
221 nmeaParserNODE *node = (nmeaParserNODE *)top_node;
222
223 NMEA_ASSERT(this && buffer);
224
225 if(node)
226 {
227 if(node->pack)
228 free(node->pack);
229 retval = node->pack->type;
230 top_node = node->next_node;
231 if(!top_node)
232 end_node = 0;
233 free(node);
234 }
235
236 return retval;
237 }
238
239 /**
240 * \brief Clear cache of parser
241 * @return true (1) - success
242 */
243 int nmeaParser::nmea_parser_buff_clear()
244 {
245 NMEA_ASSERT(this && buffer);
246 buff_use = 0;
247 return 1;
248 }
249
250 /**
251 * \brief Clear packets queue into parser
252 * @return true (1) - success
253 */
254 int nmeaParser::nmea_parser_queue_clear()
255 {
256 NMEA_ASSERT(this);
257 while(top_node)
258 nmea_parser_drop();
259 return 1;
260 }
261
262 virtual void nmeaParser::code_2info(nmeaCode* code, nmeaInfo* info) {
263
264 }
265
266
267 int nmeaParser::nmea_find_tail(const char *buff, int buff_sz, int *res_crc)
268 {
269 static const int tail_sz = 3 /* *[CRC] */ + 2 /* \r\n */;
270
271 const char *end_buff = buff + buff_sz;
272 int nread = 0;
273 int crc = 0;
274
275 NMEA_ASSERT(buff && res_crc);
276
277 *res_crc = -1;
278
279 for(;buff < end_buff; ++buff, ++nread)
280 {
281 if(('$' == *buff) && nread)
282 {
283 buff = 0;
284 break;
285 }
286 else if('*' == *buff)
287 {
288 if(buff + tail_sz <= end_buff && '\r' == buff[3] && '\n' == buff[4])
289 {
290 *res_crc = code_atoi(buff + 1, 2, 16);
291 nread = buff_sz - (int)(end_buff - (buff + tail_sz));
292 if(*res_crc != crc)
293 {
294 *res_crc = -1;
295 buff = 0;
296 }
297 }
298
299 break;
300 }
301 else if(nread)
302 crc ^= (int)*buff;
303 }
304
305 if(*res_crc < 0 && buff)
306 nread = 0;
307
308 return nread;
309 }
@@ -0,0 +1,46
1 /*
2 * nmeaParser.h
3 *
4 * Created on: Oct 21, 2014
5 * Author: Alan Aguilar Sologuren
6 */
7
8 #ifndef NMEALIB_NMEALIB___NMEAPARSER_H_
9 #define NMEALIB_NMEALIB___NMEAPARSER_H_
10
11 typedef struct _nmeaParserNODE
12 {
13 nmeaCode* pack;
14 struct _nmeaParserNODE *next_node;
15
16 } nmeaParserNODE;
17
18 class nmeaParser {
19 public:
20 nmeaParser();
21 virtual ~nmeaParser();
22
23 int nmea_find_tail(const char *buff, int buff_sz, int *res_crc)
24 int nmea_parse( const char *buff, int buff_sz, nmeaInfo *info );
25
26 int nmea_parser_push(const char *buff, int buff_sz);
27 int nmea_parser_top(void);
28 int nmea_parser_pop(nmeaCode **pack_ptr);
29 int nmea_parser_peek(nmeaCode **pack_ptr);
30 int nmea_parser_drop(void);
31 int nmea_parser_buff_clear(void);
32 int nmea_parser_queue_clear(void);
33
34 virtual void code_2info(nmeaCode* code, nmeaInfo* info);
35
36 private:
37 void *top_node;
38 void *end_node;
39 unsigned char *buffer;
40 int buff_size;
41 int buff_use;
42
43 int nmea_parser_real_push(const char *buff, int buff_sz);
44 };
45
46 #endif /* NMEALIB_NMEALIB___NMEAPARSER_H_ */
@@ -0,0 +1,107
1 /*
2 * nmea_defs.h
3 *
4 * Created on: Oct 21, 2014
5 * Author: Alan Aguilar Sologuren
6 */
7
8 #ifndef NMEALIB_NMEALIB___NMEA_DEFS_H_
9 #define NMEALIB_NMEALIB___NMEA_DEFS_H_
10
11 #include "context.h"
12 /**
13 *
14 */
15 #define code_PI (3.141592653589793) /**< PI value */
16 #define code_PI180 (code_PI / 180) /**< PI division by 180 */
17 #define code_EARTHRADIUS_KM (6378) /**< Earth's mean radius in km */
18 #define code_EARTHRADIUS_M (code_EARTHRADIUS_KM * 1000) /**< Earth's mean radius in m */
19 #define code_EARTH_SEMIMAJORAXIS_M (6378137.0) /**< Earth's semi-major axis in m according WGS84 */
20 #define code_EARTH_SEMIMAJORAXIS_KM (code_EARTHMAJORAXIS_KM / 1000) /**< Earth's semi-major axis in km according WGS 84 */
21 #define code_EARTH_FLATTENING (1 / 298.257223563) /**< Earth's flattening according WGS 84 */
22 #define code_DOP_FACTOR (5) /**< Factor for translating DOP to meters */
23
24
25 /*
26 * Distance units
27 */
28 #define NMEA_TUD_YARDS (1.0936) /**< Yeards, meter * NMEA_TUD_YARDS = yard */
29 #define NMEA_TUD_KNOTS (1.852) /**< Knots, kilometer / NMEA_TUD_KNOTS = knot */
30 #define NMEA_TUD_MILES (1.609) /**< Miles, kilometer / NMEA_TUD_MILES = mile */
31
32 /*
33 * Speed units
34 */
35 #define NMEA_TUS_MS (3.6) /**< Meters per seconds, (k/h) / NMEA_TUS_MS= (m/s) */
36
37
38 #define NMEA_SIG_BAD (0)
39 #define NMEA_SIG_LOW (1)
40 #define NMEA_SIG_MID (2)
41 #define NMEA_SIG_HIGH (3)
42
43 #define NMEA_FIX_BAD (1)
44 #define NMEA_FIX_2D (2)
45 #define NMEA_FIX_3D (3)
46
47 #define NMEA_MAXSAT (12)
48 #define NMEA_SATINPACK (4)
49 #define NMEA_NSATPACKS (NMEA_MAXSAT / NMEA_SATINPACK)
50
51 #define NMEA_DEF_LAT (5001.2621)
52 #define NMEA_DEF_LON (3613.0595)
53
54 #define NMEA_TOKS_COMPARE (1)
55 #define NMEA_TOKS_PERCENT (2)
56 #define NMEA_TOKS_WIDTH (3)
57 #define NMEA_TOKS_TYPE (4)
58
59
60 /**
61 * NMEA packets type which parsed and generated by library
62 */
63 enum nmeaPACKTYPE
64 {
65 GPNON = 0x0000, /**< Unknown packet type. */
66 GPGGA = 0x0001, /**< GGA - Essential fix data which provide 3D location and accuracy data. */
67 GPGSA = 0x0002, /**< GSA - GPS receiver operating mode, SVs used for navigation, and DOP values. */
68 GPGSV = 0x0004, /**< GSV - Number of SVs in view, PRN numbers, elevation, azimuth & SNR values. */
69 GPRMC = 0x0008, /**< RMC - Recommended Minimum Specific GPS/TRANSIT Data. */
70 GPVTG = 0x0010, /**< VTG - Actual track made good and speed over ground. */
71 GPALM = 0x0020,
72 GPGLL = 0x0040,
73 PGRMI = 0x0080,
74 PGRMC = 0x0100,
75 PGRMC1 = 0x0200,
76 PGRMO = 0x0400
77 };
78
79
80 /**
81 * Position data in fractional degrees or radians
82 */
83 typedef struct _nmeaPOS
84 {
85 double lat; /**< Latitude */
86 double lon; /**< Longitude */
87
88 } nmeaPOS;
89
90
91 /**
92 * Date and time data
93 * @see nmea_time_now
94 */
95 typedef struct _nmeaTIME
96 {
97 int year; /**< Years since 1900 */
98 int mon; /**< Months since January - [0,11] */
99 int day; /**< Day of the month - [1,31] */
100 int hour; /**< Hours since midnight - [0,23] */
101 int min; /**< Minutes after the hour - [0,59] */
102 int sec; /**< Seconds after the minute - [0,59] */
103 int hsec; /**< Hundredth part of second - [0,99] */
104
105 } nmeaTIME;
106
107 #endif /* NMEALIB_NMEALIB___NMEA_DEFS_H_ */
This diff has been collapsed as it changes many lines, (590 lines changed) Show them Hide them
@@ -0,0 +1,590
1 /*
2 * utils.cpp
3 *
4 * Created on: Oct 21, 2014
5 * Author: Alan Aguilar Sologuren
6 */
7
8 #include <stdlib.h>
9 #include <stdarg.h>
10 #include "utils.h"
11
12 /**
13 * \fn code_degree2radian
14 * \brief Convert degree to radian
15 */
16 double code_degree2radian(double val) {
17 return (val * code_PI180);
18 }
19
20 /**
21 * \fn code_radian2degree
22 * \brief Convert radian to degree
23 */
24 double code_radian2degree(double val) {
25 return (val / code_PI180);
26 }
27
28 /**
29 * \brief Convert NDEG (NMEA degree) to fractional degree
30 */
31 double code_ndeg2degree(double val) {
32 double deg = ((int)(val / 100));
33 val = deg + (val - deg * 100) / 60;
34 return val;
35 }
36
37 /**
38 * \brief Convert fractional degree to NDEG (NMEA degree)
39 */
40 double code_degree2ndeg(double val) {
41 double int_part;
42 double fra_part;
43 fra_part = modf(val, &int_part);
44 val = int_part * 100 + fra_part * 60;
45 return val;
46 }
47
48 /**
49 * \fn code_ndeg2radian
50 * \brief Convert NDEG (NMEA degree) to radian
51 */
52 double code_ndeg2radian(double val) {
53 return code_degree2radian(code_ndeg2degree(val));
54 }
55
56 /**
57 * \fn code_radian2ndeg
58 * \brief Convert radian to NDEG (NMEA degree)
59 */
60 double code_radian2ndeg(double val) {
61 return code_degree2ndeg(code_radian2degree(val));
62 }
63
64 /**
65 * \brief Calculate PDOP (Position Dilution Of Precision) factor
66 */
67 double code_calc_pdop(double hdop, double vdop) {
68 return sqrt(pow(hdop, 2) + pow(vdop, 2));
69 }
70
71 double code_dop2meters(double dop) {
72 return (dop * code_DOP_FACTOR);
73 }
74
75 double code_meters2dop(double meters) {
76 return (meters / code_DOP_FACTOR);
77 }
78
79 /**
80 * \brief Calculate distance between two points
81 * \return Distance in meters
82 */
83 double code_distance(
84 const nmeaPOS *from_pos, /**< From position in radians */
85 const nmeaPOS *to_pos /**< To position in radians */
86 )
87 {
88 double dist = ((double)code_EARTHRADIUS_M) * acos(
89 sin(to_pos->lat) * sin(from_pos->lat) +
90 cos(to_pos->lat) * cos(from_pos->lat) * cos(to_pos->lon - from_pos->lon)
91 );
92 return dist;
93 }
94
95 /**
96 * \brief Calculate distance between two points
97 * This function uses an algorithm for an oblate spheroid earth model.
98 * The algorithm is described here:
99 * http://www.ngs.noaa.gov/PUBS_LIB/inverse.pdf
100 * \return Distance in meters
101 */
102 double code_distance_ellipsoid(
103 const nmeaPOS *from_pos, /**< From position in radians */
104 const nmeaPOS *to_pos, /**< To position in radians */
105 double *from_azimuth, /**< (O) azimuth at "from" position in radians */
106 double *to_azimuth /**< (O) azimuth at "to" position in radians */
107 )
108 {
109 /* All variables */
110 double f, a, b, sqr_a, sqr_b;
111 double L, phi1, phi2, U1, U2, sin_U1, sin_U2, cos_U1, cos_U2;
112 double sigma, sin_sigma, cos_sigma, cos_2_sigmam, sqr_cos_2_sigmam, sqr_cos_alpha, lambda, sin_lambda, cos_lambda, delta_lambda;
113 int remaining_steps;
114 double sqr_u, A, B, delta_sigma;
115
116 /* Check input */
117 NMEA_ASSERT(from_pos != 0);
118 NMEA_ASSERT(to_pos != 0);
119
120 if ((from_pos->lat == to_pos->lat) && (from_pos->lon == to_pos->lon))
121 { /* Identical points */
122 if ( from_azimuth != 0 )
123 *from_azimuth = 0;
124 if ( to_azimuth != 0 )
125 *to_azimuth = 0;
126 return 0;
127 } /* Identical points */
128
129 /* Earth geometry */
130 f = code_EARTH_FLATTENING;
131 a = code_EARTH_SEMIMAJORAXIS_M;
132 b = (1 - f) * a;
133 sqr_a = a * a;
134 sqr_b = b * b;
135
136 /* Calculation */
137 L = to_pos->lon - from_pos->lon;
138 phi1 = from_pos->lat;
139 phi2 = to_pos->lat;
140 U1 = atan((1 - f) * tan(phi1));
141 U2 = atan((1 - f) * tan(phi2));
142 sin_U1 = sin(U1);
143 sin_U2 = sin(U2);
144 cos_U1 = cos(U1);
145 cos_U2 = cos(U2);
146
147 /* Initialize iteration */
148 sigma = 0;
149 sin_sigma = sin(sigma);
150 cos_sigma = cos(sigma);
151 cos_2_sigmam = 0;
152 sqr_cos_2_sigmam = cos_2_sigmam * cos_2_sigmam;
153 sqr_cos_alpha = 0;
154 lambda = L;
155 sin_lambda = sin(lambda);
156 cos_lambda = cos(lambda);
157 delta_lambda = lambda;
158 remaining_steps = 20;
159
160 while ((delta_lambda > 1e-12) && (remaining_steps > 0))
161 { /* Iterate */
162 /* Variables */
163 double tmp1, tmp2, tan_sigma, sin_alpha, cos_alpha, C, lambda_prev;
164
165 /* Calculation */
166 tmp1 = cos_U2 * sin_lambda;
167 tmp2 = cos_U1 * sin_U2 - sin_U1 * cos_U2 * cos_lambda;
168 sin_sigma = sqrt(tmp1 * tmp1 + tmp2 * tmp2);
169 cos_sigma = sin_U1 * sin_U2 + cos_U1 * cos_U2 * cos_lambda;
170 tan_sigma = sin_sigma / cos_sigma;
171 sin_alpha = cos_U1 * cos_U2 * sin_lambda / sin_sigma;
172 cos_alpha = cos(asin(sin_alpha));
173 sqr_cos_alpha = cos_alpha * cos_alpha;
174 cos_2_sigmam = cos_sigma - 2 * sin_U1 * sin_U2 / sqr_cos_alpha;
175 sqr_cos_2_sigmam = cos_2_sigmam * cos_2_sigmam;
176 C = f / 16 * sqr_cos_alpha * (4 + f * (4 - 3 * sqr_cos_alpha));
177 lambda_prev = lambda;
178 sigma = asin(sin_sigma);
179 lambda = L +
180 (1 - C) * f * sin_alpha
181 * (sigma + C * sin_sigma * (cos_2_sigmam + C * cos_sigma * (-1 + 2 * sqr_cos_2_sigmam)));
182 delta_lambda = lambda_prev - lambda;
183 if ( delta_lambda < 0 ) delta_lambda = -delta_lambda;
184 sin_lambda = sin(lambda);
185 cos_lambda = cos(lambda);
186 remaining_steps--;
187 } /* Iterate */
188
189 /* More calculation */
190 sqr_u = sqr_cos_alpha * (sqr_a - sqr_b) / sqr_b;
191 A = 1 + sqr_u / 16384 * (4096 + sqr_u * (-768 + sqr_u * (320 - 175 * sqr_u)));
192 B = sqr_u / 1024 * (256 + sqr_u * (-128 + sqr_u * (74 - 47 * sqr_u)));
193 delta_sigma = B * sin_sigma * (
194 cos_2_sigmam + B / 4 * (
195 cos_sigma * (-1 + 2 * sqr_cos_2_sigmam) -
196 B / 6 * cos_2_sigmam * (-3 + 4 * sin_sigma * sin_sigma) * (-3 + 4 * sqr_cos_2_sigmam)
197 ));
198
199 /* Calculate result */
200 if ( from_azimuth != 0 )
201 {
202 double tan_alpha_1 = cos_U2 * sin_lambda / (cos_U1 * sin_U2 - sin_U1 * cos_U2 * cos_lambda);
203 *from_azimuth = atan(tan_alpha_1);
204 }
205 if ( to_azimuth != 0 )
206 {
207 double tan_alpha_2 = cos_U1 * sin_lambda / (-sin_U1 * cos_U2 + cos_U1 * sin_U2 * cos_lambda);
208 *to_azimuth = atan(tan_alpha_2);
209 }
210
211 return b * A * (sigma - delta_sigma);
212
213 }
214 /**
215 * \brief Horizontal move of point position
216 */
217 int code_move_horz(
218 const nmeaPOS *start_pos, /**< Start position in radians */
219 nmeaPOS *end_pos, /**< Result position in radians */
220 double azimuth, /**< Azimuth (degree) [0, 359] */
221 double distance /**< Distance (km) */
222 )
223 {
224 nmeaPOS p1 = *start_pos;
225 int RetVal = 1;
226
227 distance /= code_EARTHRADIUS_KM; /* Angular distance covered on earth's surface */
228 azimuth = code_degree2radian(azimuth);
229
230 end_pos->lat = asin(
231 sin(p1.lat) * cos(distance) + cos(p1.lat) * sin(distance) * cos(azimuth));
232 end_pos->lon = p1.lon + atan2(
233 sin(azimuth) * sin(distance) * cos(p1.lat), cos(distance) - sin(p1.lat) * sin(end_pos->lat));
234
235 if(NMEA_POSIX(isnan)(end_pos->lat) || NMEA_POSIX(isnan)(end_pos->lon))
236 {
237 end_pos->lat = 0; end_pos->lon = 0;
238 RetVal = 0;
239 }
240
241 return RetVal;
242 }
243
244 /**
245 * \brief Horizontal move of point position
246 * This function uses an algorithm for an oblate spheroid earth model.
247 * The algorithm is described here:
248 * http://www.ngs.noaa.gov/PUBS_LIB/inverse.pdf
249 */
250 int code_move_horz_ellipsoid(
251 const nmeaPOS *start_pos, /**< Start position in radians */
252 nmeaPOS *end_pos, /**< (O) Result position in radians */
253 double azimuth, /**< Azimuth in radians */
254 double distance, /**< Distance (km) */
255 double *end_azimuth /**< (O) Azimuth at end position in radians */
256 )
257 {
258 /* Variables */
259 double f, a, b, sqr_a, sqr_b;
260 double phi1, tan_U1, sin_U1, cos_U1, s, alpha1, sin_alpha1, cos_alpha1;
261 double tan_sigma1, sigma1, sin_alpha, cos_alpha, sqr_cos_alpha, sqr_u, A, B;
262 double sigma_initial, sigma, sigma_prev, sin_sigma, cos_sigma, cos_2_sigmam, sqr_cos_2_sigmam, delta_sigma;
263 int remaining_steps;
264 double tmp1, phi2, lambda, C, L;
265
266 /* Check input */
267 NMEA_ASSERT(start_pos != 0);
268 NMEA_ASSERT(end_pos != 0);
269
270 if (fabs(distance) < 1e-12)
271 { /* No move */
272 *end_pos = *start_pos;
273 if ( end_azimuth != 0 ) *end_azimuth = azimuth;
274 return ! (NMEA_POSIX(isnan)(end_pos->lat) || NMEA_POSIX(isnan)(end_pos->lon));
275 } /* No move */
276
277 /* Earth geometry */
278 f = code_EARTH_FLATTENING;
279 a = code_EARTH_SEMIMAJORAXIS_M;
280 b = (1 - f) * a;
281 sqr_a = a * a;
282 sqr_b = b * b;
283
284 /* Calculation */
285 phi1 = start_pos->lat;
286 tan_U1 = (1 - f) * tan(phi1);
287 cos_U1 = 1 / sqrt(1 + tan_U1 * tan_U1);
288 sin_U1 = tan_U1 * cos_U1;
289 s = distance;
290 alpha1 = azimuth;
291 sin_alpha1 = sin(alpha1);
292 cos_alpha1 = cos(alpha1);
293 tan_sigma1 = tan_U1 / cos_alpha1;
294 sigma1 = atan2(tan_U1, cos_alpha1);
295 sin_alpha = cos_U1 * sin_alpha1;
296 sqr_cos_alpha = 1 - sin_alpha * sin_alpha;
297 cos_alpha = sqrt(sqr_cos_alpha);
298 sqr_u = sqr_cos_alpha * (sqr_a - sqr_b) / sqr_b;
299 A = 1 + sqr_u / 16384 * (4096 + sqr_u * (-768 + sqr_u * (320 - 175 * sqr_u)));
300 B = sqr_u / 1024 * (256 + sqr_u * (-128 + sqr_u * (74 - 47 * sqr_u)));
301
302 /* Initialize iteration */
303 sigma_initial = s / (b * A);
304 sigma = sigma_initial;
305 sin_sigma = sin(sigma);
306 cos_sigma = cos(sigma);
307 cos_2_sigmam = cos(2 * sigma1 + sigma);
308 sqr_cos_2_sigmam = cos_2_sigmam * cos_2_sigmam;
309 delta_sigma = 0;
310 sigma_prev = 2 * code_PI;
311 remaining_steps = 20;
312
313 while ((fabs(sigma - sigma_prev) > 1e-12) && (remaining_steps > 0))
314 { /* Iterate */
315 cos_2_sigmam = cos(2 * sigma1 + sigma);
316 sqr_cos_2_sigmam = cos_2_sigmam * cos_2_sigmam;
317 sin_sigma = sin(sigma);
318 cos_sigma = cos(sigma);
319 delta_sigma = B * sin_sigma * (
320 cos_2_sigmam + B / 4 * (
321 cos_sigma * (-1 + 2 * sqr_cos_2_sigmam) -
322 B / 6 * cos_2_sigmam * (-3 + 4 * sin_sigma * sin_sigma) * (-3 + 4 * sqr_cos_2_sigmam)
323 ));
324 sigma_prev = sigma;
325 sigma = sigma_initial + delta_sigma;
326 remaining_steps --;
327 } /* Iterate */
328
329 /* Calculate result */
330 tmp1 = (sin_U1 * sin_sigma - cos_U1 * cos_sigma * cos_alpha1);
331 phi2 = atan2(
332 sin_U1 * cos_sigma + cos_U1 * sin_sigma * cos_alpha1,
333 (1 - f) * sqrt(sin_alpha * sin_alpha + tmp1 * tmp1)
334 );
335 lambda = atan2(
336 sin_sigma * sin_alpha1,
337 cos_U1 * cos_sigma - sin_U1 * sin_sigma * cos_alpha1
338 );
339 C = f / 16 * sqr_cos_alpha * (4 + f * (4 - 3 * sqr_cos_alpha));
340 L = lambda -
341 (1 - C) * f * sin_alpha * (
342 sigma + C * sin_sigma *
343 (cos_2_sigmam + C * cos_sigma * (-1 + 2 * sqr_cos_2_sigmam))
344 );
345
346 /* Result */
347 end_pos->lon = start_pos->lon + L;
348 end_pos->lat = phi2;
349 if ( end_azimuth != 0 )
350 {
351 *end_azimuth = atan2(
352 sin_alpha, -sin_U1 * sin_sigma + cos_U1 * cos_sigma * cos_alpha1
353 );
354 }
355 return ! (NMEA_POSIX(isnan)(end_pos->lat) || NMEA_POSIX(isnan)(end_pos->lon));
356 }
357
358 /**
359 * \brief Calculate control sum of binary buffer
360 */
361 int code_calc_crc(const char *buff, int buff_sz)
362 {
363 int chsum = 0,
364 it;
365
366 for(it = 0; it < buff_sz; ++it)
367 chsum ^= (int)buff[it];
368
369 return chsum;
370 }
371
372 /**
373 * \brief Convert string to number
374 */
375 int code_atoi(const char *str, int str_sz, int radix)
376 {
377 char *tmp_ptr;
378 char buff[NMEA_CONVSTR_BUF];
379 int res = 0;
380
381 if(str_sz < NMEA_CONVSTR_BUF)
382 {
383 memcpy(&buff[0], str, str_sz);
384 buff[str_sz] = '\0';
385 res = strtol(&buff[0], &tmp_ptr, radix);
386 }
387
388 return res;
389 }
390
391 /**
392 * \brief Convert string to fraction number
393 */
394 double code_atof(const char *str, int str_sz)
395 {
396 char *tmp_ptr;
397 char buff[NMEA_CONVSTR_BUF];
398 double res = 0;
399
400 if(str_sz < NMEA_CONVSTR_BUF)
401 {
402 memcpy(&buff[0], str, str_sz);
403 buff[str_sz] = '\0';
404 res = strtod(&buff[0], &tmp_ptr);
405 }
406
407 return res;
408 }
409
410 /**
411 * \brief Formating string (like standart printf) with CRC tail (*CRC)
412 */
413 int code_printf(char *buff, int buff_sz, const char *format, ...)
414 {
415 int retval, add = 0;
416 va_list arg_ptr;
417
418 if(buff_sz <= 0)
419 return 0;
420
421 va_start(arg_ptr, format);
422
423 retval = NMEA_POSIX(vsnprintf)(buff, buff_sz, format, arg_ptr);
424
425 if(retval > 0)
426 {
427 add = NMEA_POSIX(snprintf)(
428 buff + retval, buff_sz - retval, "*%02x\r\n",
429 code_calc_crc(buff + 1, retval - 1));
430 }
431
432 retval += add;
433
434 if(retval < 0 || retval > buff_sz)
435 {
436 memset(buff, ' ', buff_sz);
437 retval = buff_sz;
438 }
439
440 va_end(arg_ptr);
441
442 return retval;
443 }
444
445 /**
446 * \brief Analyse string (specificate for NMEA sentences)
447 */
448 int code_scanf(const char *buff, int buff_sz, const char *format, ...)
449 {
450 const char *beg_tok;
451 const char *end_buf = buff + buff_sz;
452
453 va_list arg_ptr;
454 int tok_type = NMEA_TOKS_COMPARE;
455 int width = 0;
456 const char *beg_fmt = 0;
457 int snum = 0, unum = 0;
458
459 int tok_count = 0;
460 void *parg_target;
461
462 va_start(arg_ptr, format);
463
464 for(; *format && buff < end_buf; ++format)
465 {
466 switch(tok_type)
467 {
468 case NMEA_TOKS_COMPARE:
469 if('%' == *format)
470 tok_type = NMEA_TOKS_PERCENT;
471 else if(*buff++ != *format)
472 goto fail;
473 break;
474 case NMEA_TOKS_PERCENT:
475 width = 0;
476 beg_fmt = format;
477 tok_type = NMEA_TOKS_WIDTH;
478 case NMEA_TOKS_WIDTH:
479 if(isdigit(*format))
480 break;
481 {
482 tok_type = NMEA_TOKS_TYPE;
483 if(format > beg_fmt)
484 width = code_atoi(beg_fmt, (int)(format - beg_fmt), 10);
485 }
486 case NMEA_TOKS_TYPE:
487 beg_tok = buff;
488
489 if(!width && ('c' == *format || 'C' == *format) && *buff != format[1])
490 width = 1;
491
492 if(width)
493 {
494 if(buff + width <= end_buf)
495 buff += width;
496 else
497 goto fail;
498 }
499 else
500 {
501 if(!format[1] || (0 == (buff = (char *)memchr(buff, format[1], end_buf - buff))))
502 buff = end_buf;
503 }
504
505 if(buff > end_buf)
506 goto fail;
507
508 tok_type = NMEA_TOKS_COMPARE;
509 tok_count++;
510
511 parg_target = 0; width = (int)(buff - beg_tok);
512
513 switch(*format)
514 {
515 case 'c':
516 case 'C':
517 parg_target = (void *)va_arg(arg_ptr, char *);
518 if(width && 0 != (parg_target))
519 *((char *)parg_target) = *beg_tok;
520 break;
521 case 's':
522 case 'S':
523 parg_target = (void *)va_arg(arg_ptr, char *);
524 if(width && 0 != (parg_target))
525 {
526 memcpy(parg_target, beg_tok, width);
527 ((char *)parg_target)[width] = '\0';
528 }
529 break;
530 case 'f':
531 case 'g':
532 case 'G':
533 case 'e':
534 case 'E':
535 parg_target = (void *)va_arg(arg_ptr, double *);
536 if(width && 0 != (parg_target))
537 *((double *)parg_target) = code_atof(beg_tok, width);
538 break;
539 };
540
541 if(parg_target)
542 break;
543 if(0 == (parg_target = (void *)va_arg(arg_ptr, int *)))
544 break;
545 if(!width)
546 break;
547
548 switch(*format)
549 {
550 case 'd':
551 case 'i':
552 snum = code_atoi(beg_tok, width, 10);
553 memcpy(parg_target, &snum, sizeof(int));
554 break;
555 case 'u':
556 unum = code_atoi(beg_tok, width, 10);
557 memcpy(parg_target, &unum, sizeof(unsigned int));
558 break;
559 case 'x':
560 case 'X':
561 unum = code_atoi(beg_tok, width, 16);
562 memcpy(parg_target, &unum, sizeof(unsigned int));
563 break;
564 case 'o':
565 unum = code_atoi(beg_tok, width, 8);
566 memcpy(parg_target, &unum, sizeof(unsigned int));
567 break;
568 default:
569 goto fail;
570 };
571
572 break;
573 };
574 }
575
576 fail:
577
578 va_end(arg_ptr);
579
580 return tok_count;
581 }
582
583
584 double nmeaGenerator::nmea_random(double min, double max)
585 {
586 static double rand_max = RAND_MAX;
587 double rand_val = rand();
588 double bounds = max - min;
589 return min + (rand_val * bounds) / rand_max;
590 }
@@ -0,0 +1,38
1 /*
2 * utils.h
3 *
4 * Created on: Oct 21, 2014
5 * Author: Alan Aguilar Sologuren
6 */
7
8 #ifndef NMEALIB___UTILS_H_
9 #define NMEALIB___UTILS_H_
10
11 #include "nmea_defs.h"
12
13 double code_degree2radian(double val);
14 double code_radian2degree(double val);
15 double code_ndeg2degree(double val);
16 double code_degree2ndeg(double val);
17 double code_ndeg2radian(double val);
18 double code_radian2ndeg(double val);
19 double code_calc_pdop(double hdop, double vdop);
20 double code_dop2meters(double dop);
21 double code_meters2dop(double meters);
22 double code_distance(const nmeaPOS *from_pos, const nmeaPOS *to_pos);
23 double code_distance_ellipsoid(const nmeaPOS *from_pos, const nmeaPOS *to_pos,
24 double *from_azimuth, double *to_azimuth);
25 int code_move_horz(const nmeaPOS *start_pos, nmeaPOS *end_pos,
26 double azimuth, double distance);
27 int code_move_horz_ellipsoid(const nmeaPOS *start_pos, nmeaPOS *end_pos,
28 double azimuth, double distance, double *end_azimuth );
29
30 int code_calc_crc(const char *buff, int buff_sz);
31 int code_atoi(const char *str, int str_sz, int radix);
32 double code_atof(const char *str, int str_sz);
33 int code_printf(char *buff, int buff_sz, const char *format, ...);
34 int code_scanf(const char *buff, int buff_sz, const char *format, ...);
35
36 double nmea_random(double min, double max);
37
38 #endif /* NMEALIB___UTILS_H_ */
General Comments 0
You need to be logged in to leave comments. Login now