Giter Club home page Giter Club logo

lwgps's Introduction

Lightweight GPS NMEA parser

Platform independent GPS NMEA parser for embedded systems.

Read first: Documentation

Features

  • Written in C (C11)
  • Platform independent, easy to use
  • Built-in support for 4 GPS statements
    • GPGGA or GNGGA: GPS fix data
    • GPGSA or GNGSA: GPS active satellites and dillusion of position
    • GPGSV or GNGSV: List of satellites in view zone
    • GPRMC or GNRMC: Recommended minimum specific GPS/Transit data
  • Optional float or double floating point units
  • Low-level layer is separated from application layer, thus allows you to add custom communication with GPS device
  • Works with operating systems
  • Works with different communication interfaces
  • User friendly MIT license

Contribute

Fresh contributions are always welcome. Simple instructions to proceed:

  1. Fork Github repository
  2. Follow C style & coding rules already used in the project
  3. Create a pull request to develop branch with new features or bug fixes

Alternatively you may:

  1. Report a bug
  2. Ask for a feature request

Test

To build the code and run basic tests on your host::

    cd examples
    make test

lwgps's People

Contributors

b4yuan avatar dependabot[bot] avatar glbsalazar avatar jackorobot avatar majerle avatar robamu avatar siriobalmelli avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

lwgps's Issues

GPS geoid calculation

Hi there,

Great parser, easy to use. I found problem with the altitude calculation. I seems that you have to subtract the geoid from the altitude. (https://eos-gnss.com/elevation-for-beginners/) In your code at line 191: gh->p.data.gga.altitude += parse_double_number(gh, NULL);
Should it not be gh->p.data.gga.altitude -= parse_double_number(gh, NULL); ?
Thanks
Marco

Unable to compile on a ESP-IDF environment.

Hi ,
I've included gps.c gps.h in my project , but it seems that gps_t structure is not recognised by the environment.

GCC_NOT_5_2_0 -DESP_PLATFORM -MD -MT esp-idf/main/CMakeFiles/__idf_main.dir/nas_core.c.obj -MF esp-idf/main/CMakeFiles/__idf_main.dir/nas_core.c.obj.d -o esp-idf/main/CMakeFiles/__idf_main.dir/nas_core.c.obj -c ../main/nas_core.c
../main/src/gps_control.c:58:9: error: unknown type name 'gps_t'; did you mean 'fpos_t'?
../main/src/gps_control.c:60:9: error: implicit declaration of function 'gps_init'; did you mean 'nvs_init'? [-Werror=implicit-function-declaration]
../main/src/gps_control.c:62:9: error: implicit declaration of function 'gps_process' [-Werror=implicit-function-declaration]
../main/src/gps_control.c:65:44: error: request for member 'is_valid' in something not a structure or union
../main/src/gps_control.c:66:48: error: request for member 'latitude' in something not a structure or union
../main/src/gps_control.c:67:49: error: request for member 'longitude' in something not a structure or union
../main/src/gps_control.c:68:47: error: request for member 'altitude' in something not a structure or union
../main/gps/gps.h:392:13: error: conflicting types for 'gps_init'
../main/gps/gps.h:396:13: error: conflicting types for 'gps_process'
cc1: some warnings being treated as errors

typo in the "for" loop

The last commit introduced a syntax error:

...
    /* Strip leading spaces */
for (; t != NULL && *t == ' ', t++) {}
...

should be

...
    /* Strip leading spaces */
for (; t != NULL && *t == ' '; t++) {}
...

Header not found

@MaJerle Looks like header is present in the directory - Still the issue is there. Can you guide ?

root@db-ubuntu:/home/vboxuser/Downloads/lwgps-main/examples# make test
cc -o example.exe -Wall -DDEBUG=1 -I../lwgps/src/include -I./ ../lwgps/src/lwgps/lwgps.c example.c
In file included from ../lwgps/src/include/lwgps/lwgps.h:40,
from ../lwgps/src/lwgps/lwgps.c:36:
../lwgps/src/include/lwgps/lwgps_opt.h:42:10: fatal error: lwgps_opts.h: No such file or directory
42 | #include "lwgps_opts.h"
| ^~~~~~~~~~~~~~
compilation terminated.
In file included from ../lwgps/src/include/lwgps/lwgps.h:40,
from example.c:7:
../lwgps/src/include/lwgps/lwgps_opt.h:42:10: fatal error: lwgps_opts.h: No such file or directory
42 | #include "lwgps_opts.h"
| ^~~~~~~~~~~~~~
compilation terminated.
make: *** [Makefile:40: example.exe] Error 1

Floating Point Types

There are some issues that I can see coming from the fact that GPS_NMEA_parser is supporting two types of floating point numbers (float and double).

When using doubles we might lose some precision because of this:

    #define D2R(x)              (float)((x) * 0.01745329251994f)    /*!< Degrees to radians */
    #define R2D(x)              (float)((x) * 57.29577951308232f)   /*!< Radians to degrees */
    #define EARTH_RADIUS (6371.0f) /*!< Earth radius in units of kilometers */

For example, even if df, lae and las are all double in this line from gps_distance_bearing function, df will have float's precision:

df = D2R(lae - las);

I suggest to change the three lines above to this:

    #define D2R(x)       ((gps_float_t)(x) * (gps_float_t)0.01745329251994)  /*!< Degrees to radians */
    #define R2D(x)       ((gps_float_t)(x) * (gps_float_t)57.29577951308232) /*!< Radians to degrees */
    #define EARTH_RADIUS ((gps_float_t)6371.0)                               /*!< Earth radius in units of kilometers */

Not only here, but everywhere else we should replace the "f"-suffixed values to (gps_float_t)value.

In gps_to_speed function we are for some reason using "L"-suffix values (long double!). Again I would suggest to change them to explicit type setting with (gps_float_t) and removing the suffix.

atan2, sin, cos, sqrt and other functions from <math.h> used by this library are using double precision calculation even if our gps_float_t is set to float. For a small microcontroller device this gives a heavy penalty. We must use the "f"-suffixed functions when our gps_float_t is set to float: atan2f, sinf, cosf, sqrtf, etc..

Thank you.

Incorrect Calculation of Long and Latitude

static gps_float_t parse_lat_long(gps_t* gh) in gps.c has an issue with the calculation of deg, where it is returning a float with a remainder (not an integer number as required). This affects the calculation of ll later on by adding this remainder. Should read deg = (int)(ll / FLT(100));
Made the change and tested with real location data and the longitude and latitude returned are now correct.

buffer overflow risk in ParseValue

Hi, thanks for the library. Sorry, no time & connection for a pull request, but in

static void ParseValue(GPS_t* GPS)
the call to
strcpy(Int.Statement, Int.Term); /* Copy active string as term statement */

will trigger hard fault when Term is bigger than Statement - that can happen while reading broken input. So better use

strncpy(Int.Statement, Int.Term, 6); /* Copy active string as term statement */

I'm not sure if 0-termination is required, therefore "6" by now. I'm also not sure if the rest of the fields is error-proof, but that was the first issue I faced.

Best regards, thanks for sharing the code, happy new year,
Rene``

Library not updated on Platform IO registry

I was planning on using the library via Platform IO but noticed that the registry does not have the latest version (it only has 2.1.0)
It should be automatically updated but it seems it wasn't and version 2.2.0 was already published several weeks ago (it should only take a couple of days)

Could there be an issue with the library.json file or with the integration with PlatformIO registry?

Parsing GPS valid status in RMC bug

Hello,

the Quectel L86 GNSS module is sending RMC in this format:
$GPRMC,190138.000,A,4005.9147,N,01523.0933,E,0.59,268.30,220221,,,A,V*0E
and the library is parsing the status as invalid. It has problem with the decimal point in the UTC time.
The UTC time is sent in format "hhmmss.sss" (the number 190138.000). If I remove the decimal point part, making the time only "190138", it parses correctly the signal validity status.

Coordinate parsing bug introduced when unifying the floating point types

    ll = parse_float_number(gh, NULL);          /* Parse value as double */
    deg = ((int)ll) / FLT(100);                 /* Get absolute degrees value */
    min = ll - (deg * FLT(100));                /* Get remaining part, minutes */
    ll = deg + min / FLT(60.0);                 /* Calculate latitude/longitude */

should become:

    ll = parse_float_number(gh, NULL);          /* Parse value as double */
    deg = ((int)ll) / 100;                      /* Get absolute degrees value */
    min = ll - (deg * FLT(100));                /* Get remaining part, minutes */
    ll = deg + (min / FLT(60));                 /* Calculate latitude/longitude */

or maybe:

    ll = parse_float_number(gh, NULL);          /* Parse value as double */
#if GPS_CFG_DOUBLE
    deg = floor(ll / FLT(100));                 /* Get absolute degrees value */
#else
    deg = floorf(ll / FLT(100));                /* Get absolute degrees value */
#endif
    min = ll - (deg * FLT(100));                /* Get remaining part, minutes */
    ll = deg + (min / FLT(60));                 /* Calculate latitude/longitude */

Undefined Behavior in prv_parse_lat_long() and prv_parse_number()

prv_parse_lat_long()

lwgps.c:142:11: runtime error: 3.33333e+09 is outside the range of representable values of type 'int'

Code location:

deg = FLT((int)((int)ll / 100)); /* Get absolute degrees value, interested in integer part only */

Hexdump of problematic input:

00000000  24 47 4e 47 47 41 2c 2c  33 33 33 33 33 33 33 33  |$GNGGA,,33333333|
00000010  37 32 2c                                          |72,|

prv_parse_number()

lwgps.c:90:18: runtime error: signed integer overflow: 10 * 666666666 cannot be represented in type 'int'

Code location:

res = 10 * res + CTN(*t);

Hexdump of problematic input:

00000000  24 47 4e 47 53 41 2c 2c  36 36 2c 36 36 36 36 36  |$GNGSA,,66,66666|
00000010  36 36 36 36 36 32 37 2a                           |6666627*|

libFuzzer harness in use

Derived from example.c and published under same license.

#include "lwgps.h"

int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {

  lwgps_t hgps;
  lwgps_init(&hgps);

  /* Process all input data */
  lwgps_process(&hgps, data, size);

  return 0;
}

How lightweight is lightweight? Does not fit in flash

Hi,

Thanks for this library. I am trying to use it in a project with an STM32G030 (which has only 32 kB of flash), and it looks like lwGPS needs around 24kB of flash?

Before using library: 22136 Bytes used
After using library : 13720 Bytes of flash overflowed at compilation so that's 32000+13720 - 22136 = 23485 Bytes of flash just for lwGPS.

It does not make a lot of sense. Am I missing something?

CRC calculation

Hi

First of all thank you for providing this source code!
It was easy to implement it in my project.
I just made a few changes to get all necessary informations (date, time, position) only from GPRMC messages.

But I'm a little bit confused about the CRC calculation. From my gps device (Tersus BX306) I receive messages like this:

$GNRMC,074546.00,A,4729.8111766,N,00843.7848026,E,0.094, 0.0,160818,0.0,E,A*0A

When I check the checksum with an online calculator like this one,
the checksum seems to be valid. But when I check this sentence with the crc calculator in your nmea parser, the checksum seems to be incorrect because the space sign is omited for the crc calculation.
Why is the space sign omited in this crc calculation? I can't find any definitions like this for the crc calculation.

Thanks for your info :)

Continuously receive serial data

hi!
When reading GPS data through serial port, when using this library, it is found that the data fault tolerance is not very good, and it is easy to cause the process to crash

How to extend to more sentences?

Hello!
I want to know you have a guide or any suggestions for extending the parsing to sentences like $GPGLL, $GPZDA. I plan on extending parsing to sentences like $GPZDA soon and want to seen if you had any ideas that could help.

More importantly, would it be a good idea to use the library in mission critical systems were speed, memory footprint and accuracy would be immensely important? I understand that 'speed, memory footprint and accuracy' is a bit vague but I do not have the exact specifications as of now. But can you give an example where it was used in a mission critical system like in a satellite?

Header file not found when included via Platform IO

While adding the library via PlatformIO with lib_deps = majerle/LwGPS@^2.1.0

The following error is produced during the build:

.pio\libdeps\swo_demo\LwGPS\lwgps\src\lwgps\lwgps.c:36:10: fatal error: lwgps/lwgps.h: No such file or directory
   36 | #include "lwgps/lwgps.h"

It seems that the header file cannot be found, neither to build the library nor to include it in the project.

ZIP Download Issue

When downloading this library using Github's ZIP download feature instead of manually cloning, I'm getting a really old version of the library (commit 75c511d).

Is this a Github bug or something is wrong with this repository?

Knots Conversion

According to this website 1 knot is 1.852 km/h but this library is using 1.852 to convert knots to miles, and something else for km/h:

    ...
    case gps_speed_kph:     return (gps_float_t)(sik * 0.5144L);
    case gps_speed_mps: return (gps_float_t)(sik * 1.852L);
    ...

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.