Agra-GPS / FreePilot_V2-3

Dependencies:   FreePilot PinDetect mbed-src

Fork of FreePilot_V2-2 by Agra-GPS

gps.h

Committer:
maximbolduc
Date:
2015-03-14
Revision:
48:5d9c63364c94
Parent:
47:d3123bb4f673
Child:
50:07dfcda65732

File content as of revision 48:5d9c63364c94:


#define dot(u,v)   ((u).GetX() * (v).GetX()+ (u).GetY() * (v).GetY())
#define norm(v)     sqrt(dot(v,v))     // norm = length of  vector
#define d(u,v)      norm(point_sub(u,v))          // distance = norm of difference

//gga:
int num_of_gps_sats;
double decimal_latitude;
int  gps_satellite_quality;
double decimal_lon;

Point position;
//rmc:
Point old_position;
int  day;
int  hour;
int  minute;
int  second;
int  tenths;
int  hundreths;
char status;
double track;    // track made good . angle
char magvar_dir;
double magvar;
int  year;
int  month;
double speed_km = 0;
double speed_m_s = 0;
double velocity; // speed in knot
char *time_s   = (char *)NULL;
char *date   = (char *)NULL;
char *stat   = (char *)NULL;
char *vel    = (char *)NULL;
char *trk    = (char *)NULL;
char *magv   = (char *)NULL;
char *magd   = (char *)NULL;
char *latit  = "";
char *longit = "";
char *latitude_s  = (char *)NULL;
char *longitude_s = (char *)NULL;
char *lat_dir   = (char *)NULL;
char *lon_dir   = (char *)NULL;

Point point_add(Point a, Point b)
{
    return Point(a.GetX() + b.GetX(), a.GetY() + b.GetY());
}

Point point_sub(Point a , Point b)
{
    return Point(a.GetX() - b.GetX(),  a.GetY() - b.GetY());
}

double dist_Point_to_Line( Point P, Point line_start, Point line_end)
{
    Point v = point_sub(line_end,line_start);
    Point w = point_sub(P,line_start);

    double c1 = dot(w,v);
    double c2 = dot(v,v);
    double b = c1 / c2;

    Point resulting(b * v.GetX(),b*v.GetY());
    Point Pb = point_add(line_start, resulting);

    return d(P, Pb);
}

double lat_to_deg(char *s, char north_south)
{
    int deg, min, sec;
    double fsec, val;

    deg  = ( (s[0] - '0') * 10) + s[1] - '0';
    min  = ( (s[2] - '0') * 10) + s[3] - '0';
    sec  = ( ((s[5] - '0') * 1000) + ((s[6] - '0') * 100) + ((s[7] - '0') * 10) + (s[8] - '0'));
    fsec = (double)((double)sec /10000.0);
    val  = (double)deg + ((double)((double)min/60.0)) + (fsec/60.0);
    if (north_south == 'S') {
        val *= -1.0;
    }
    return val;
}

// isLeft(): test if a point is Left|On|Right of an infinite 2D line.
//    Input:  three points P0, P1, and P2
//    Return: >0 for P2 left of the line through P0 to P1
//          =0 for P2 on the line
//          <0 for P2 right of the line
int isLeft( Point P0, Point P1, Point P2 )
{
    double isleft = ( (P1.GetY() - P0.GetY()) * (P2.GetX() - P0.GetX()) - (P2.GetY() - P0.GetY()) * (P1.GetX() - P0.GetX()));
    if ( isleft > 0 ) {
        isleft = 1;
    } else {
        isleft = -1;
    }
    return (int)isleft;
}

double lon_to_deg(char *s, char east_west)
{
    int deg, min, sec;
    double fsec, val;
    deg  = ( (s[0] - '0') * 100) + ((s[1] - '0') * 10) + (s[2] - '0');
    min  = ( (s[3] - '0') * 10) + s[4] - '0';
    sec  = ( ((s[6] - '0') * 1000) + ((s[7] - '0') * 100) + ((s[8] - '0') * 10) + (s[9] - '0'));
    fsec = (double)((double)sec /10000.0);
    val  = (double)deg + ((double)((double)min/60.0)) + (fsec/60.0);

    if (east_west == 'W') {
        val *= -1.0;
    }
    return val;
}

void nmea_gga(char *s)
{
    char *token;
    int  token_counter = 0;
    char *latitude  = (char *)NULL;
    char *longitude = (char *)NULL;
    char *lat_dir   = (char *)NULL;
    char *lon_dir   = (char *)NULL;
    char *qual      = (char *)NULL;
    char *altitude  = (char *)NULL;
    char *sats      = (char *)NULL;

    token = strtok(s, ",");
    while (token) {
        switch (token_counter) {
            case 2:
                latitude  = token;
                break;
            case 4:
                longitude = token;
                break;
            case 3:
                lat_dir   = token;
                break;
            case 5:
                lon_dir   = token;
                break;
            case 6:
                qual      = token;
                break;
            case 7:
                sats      = token;
                break;
            case 9:
                altitude  = token;
                break;
        }
        token = strtok((char *)NULL, ",");
        token_counter++;
    }
    if (latitude && longitude && altitude && sats) {
        decimal_latitude = lat_to_deg(latitude,  lat_dir[0]);
        decimal_lon = lon_to_deg(longitude, lon_dir[0]);
        num_of_gps_sats = atoi(sats);
        gps_satellite_quality = atoi(qual);
    } else {
        gps_satellite_quality = 0;
    }
}

char dms[128];
char* To_DMS(double dec_deg)
{
    dec_deg = abs(dec_deg);
    int d = (int)(dec_deg);
    sprintf(dms,"%0.2i\0",d);
    double m = (double)(((double)dec_deg - (double)d) * 60.0);
    if (m < 10 ) {
        sprintf(dms,"%s0%0.9f\0",dms,m);
    } else {
        sprintf(dms,"%s%0.9f\0",dms,m);
    }
    return dms;
}

char* To_DMS_lon(double dec_deg)
{
    dec_deg = abs(dec_deg);
    int d = (int)(dec_deg);
    sprintf(dms,"%0.3i\0",d);
    double m = (double)(((double)dec_deg - (double)d) * 60.0);
    if (m < 10 ) {
        sprintf(dms,"%s0%0.9f\0",dms,m);
    } else {
        sprintf(dms,"%s%0.9f\0",dms,m);
    }
    return dms;
}

//from farmerGPS code
void get_latlon_byangle(double lat1, double lon1, double distance,double angle, double &lon2, double &lat2)
{
    double ydist = 0;
    double xdist = 0;
    angle = angle + 180;
    double radiant = angle * 3.14159265359 / 180;
    double sinr = sin(radiant);
    double cosr = cos(radiant);
    xdist = cosr * distance;
    ydist = sinr * distance;
    lat2 = lat1 + (ydist / (69.09 * -1609.344));
    lon2 = lon1 - (xdist / (69.09 * 1609.344 * cos(lat1/57.295779513)));
}

bool nmea_rmc(char *s)
{
    char *token;
    int  token_counter = 0;
    time_s   = (char *)NULL;
    date   = (char *)NULL;
    stat   = (char *)NULL;
    vel    = (char *)NULL;
    trk    = (char *)NULL;
    magv   = (char *)NULL;
    magd   = (char *)NULL;
    latit  = "";
    longit = "";
    latitude_s  = (char *)NULL;
    longitude_s = (char *)NULL;
    lat_dir   = (char *)NULL;
    lon_dir   = (char *)NULL;
    while ((token = strsep(&s, ",")) != NULL) {
        switch (token_counter) {
            case 1:
                time_s   = token;
                break;
            case 2:
                stat   = token;
                break;
            case 3:
                if ( token ) {
                    latit  = token;
                    latitude_s  = token;
                }
                break;
            case 4:
                lat_dir   = token;
                break;
            case 5:
                longit = token;
                longitude_s = token;
                break;
            case 6:
                lon_dir   = token;
                break;
            case 7:
                vel    = token;
                break;
            case 8:
                trk    = token;
                break;
            case 9:
                date   = token;
                break;
            case 10:
                magv   = token;
                break;
            case 11:
                magd = token;
                break;
        }
        token_counter++;
    }
    if (stat!= '\0' && date!= '\0' && time_s!= '\0') {
        hour       = (char)((time_s[0] - '0') * 10) + (time_s[1] - '0');
        minute     = (char)((time_s[2] - '0') * 10) + (time_s[3] - '0');
        second     = (char)((time_s[4] - '0') * 10) + (time_s[5] - '0');
        day        = (char)((date[0] - '0') * 10) + (date[1] - '0');
        month      = (char)((date[2] - '0') * 10) + (date[3] - '0');
        year       =  (int)((date[4] - '0') * 10) + (date[5] - '0') + 2000;
        status     = stat[0];
        velocity   = atof(vel);
        speed_km = velocity * 1.852;
        speed_m_s = speed_km * 3600.0 / 1000.0;
        track      = atof(trk);
        magvar     = atof(magv);
        return true;
    }
    if ( longit != '\0' && latit != '\0' ) {
        old_position = position;
        position.SetX(lat_to_deg(latitude_s,  lat_dir[0]));
        position.SetY(lon_to_deg(longitude_s, lon_dir[0]));
        return true;
    } else {
        return false;
    }
}