PDA

View Full Version : Google Earth and GPS



Mjolinor
27th April, 2009, 11:00 AM
The Linux version of Google Earth doesn't support GPS.

I have been writing some NMEA parsing software and converting to KML files for import to Google Earth and the KML "commands" support auto refresh.

This gives a fairly simple way of getting your GPS data into Google Earth


<?xml version="1.0" encoding="UTF-8"?>
<kml xmlns="http://earth.google.com/kml/2.1">
<NetworkLink>
<name>GPS</name>
<flyToView>1</flyToView>
<Url>
<href>./gps_pos.kml</href>
<refreshMode>onInterval</refreshMode>
<refreshInterval>2</refreshInterval>
</Url>
</NetworkLink>
</kml>


The above file needs to be saved as "something". kml, suggest gps.kml and opened with Google Earth.
That file auto reloads another file called "gps_pos.kml" every 2 seconds and flies to the waypoint in the file.



#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <time.h>
#include <math.h>

char *latitude;
char *longtitude;
int x=0;
FILE *dataout_xml;
float lat, longt;

int xml_create()
{
dataout_xml = fopen("./gps_pos.kml", "w+");

fprintf (dataout_xml, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");

fprintf (dataout_xml, "<kml xmlns=\"http://www.opengis.net/kml/2.2\" xmlns:gx=\"http://www.google.com/kml/ext/2.2\" xmlns:kml=\"http://www.opengis.net/kml/2.2\" xmlns:atom=\"http://www.w3.org/2005/Atom\">\n");
fprintf (dataout_xml, "<Document>\n");
fprintf (dataout_xml, " <name>");
fprintf (dataout_xml, "Gps position");
fprintf (dataout_xml, "</name>\n");
///////////////////////////////////////////////////////////////
// definitions for little black circle
fprintf (dataout_xml, " <Style id=\"sh_placemark_circle_highlight\">\n");
fprintf (dataout_xml, " <IconStyle>\n");
fprintf (dataout_xml, " <scale>1.2</scale>\n");
fprintf (dataout_xml, " <Icon>\n");
fprintf (dataout_xml, " <href>http://maps.google.com/mapfiles/kml/shapes/placemark_circle_highlight.png</href>\n");
fprintf (dataout_xml, " </Icon>\n");
fprintf (dataout_xml, " </IconStyle>\n");
fprintf (dataout_xml, " <ListStyle>\n");
fprintf (dataout_xml, " </ListStyle>\n");
fprintf (dataout_xml, " </Style>\n");
fprintf (dataout_xml, " <Style id=\"sn_placemark_circle\">\n");
fprintf (dataout_xml, " <IconStyle>\n");
fprintf (dataout_xml, " <scale>1.2</scale>\n");
fprintf (dataout_xml, " <Icon>\n");
fprintf (dataout_xml, " <href>http://maps.google.com/mapfiles/kml/shapes/placemark_circle.png</href>\n");
fprintf (dataout_xml, " </Icon>\n");
fprintf (dataout_xml, " </IconStyle>\n");
fprintf (dataout_xml, " <ListStyle>\n");
fprintf (dataout_xml, " </ListStyle>\n");
fprintf (dataout_xml, " </Style>\n");
fprintf (dataout_xml, " <StyleMap id=\"msn_placemark_circle\">\n");
fprintf (dataout_xml, " <Pair>\n");
fprintf (dataout_xml, " <key>normal</key>\n");
fprintf (dataout_xml, " <styleUrl>#sn_placemark_circle</styleUrl>\n");
fprintf (dataout_xml, " </Pair>\n");
fprintf (dataout_xml, " <Pair>\n");
fprintf (dataout_xml, " <key>highlight</key>\n");
fprintf (dataout_xml, " <styleUrl>#sh_placemark_circle_highlight</styleUrl>\n");
fprintf (dataout_xml, " </Pair>\n");
fprintf (dataout_xml, " </StyleMap>\n");
fclose (dataout_xml);
return(0);
}

int place_to_xml()
{
dataout_xml = fopen("./gps_pos.kml", "a");
fprintf (dataout_xml, " <Placemark>\n");
fprintf (dataout_xml, " <name>");
fprintf (dataout_xml, "Pos");
fprintf (dataout_xml, "</name>\n");
fprintf (dataout_xml, " <styleUrl>#msn_placemark_circle</styleUrl>\n");
fprintf (dataout_xml, " <Point>\n");
fprintf (dataout_xml, " <LineString>\n");
fprintf (dataout_xml, " <tessellate>1</tessellate>\n");
fprintf (dataout_xml, " </LineString>\n");
fprintf (dataout_xml, " <coordinates>");
fprintf (dataout_xml, "%s,%s", longtitude, latitude);
fprintf (dataout_xml, ",0</coordinates>\n");
fprintf (dataout_xml, " </Point>\n");
fprintf (dataout_xml, " </Placemark>\n");
fprintf (dataout_xml, "</Document>\n");
fprintf (dataout_xml, "</kml>");
fclose (dataout_xml);
return(0);
}


//************************************************** ************************************
static void callback()
{
int y, z;
FILE *input;
char fromrf[200], nmea_bits[40], minutes[20], latit[15], longti[15];
float min2deg, deg;
float latmin, longtmin;

input = fopen("/dev/rfcomm4", "r");
if (input == NULL)
{
printf ("\nNo GPS\n");
return;
}

while ((strcmp(nmea_bits, "$GPGGA"))!= 0)
{
fgets(fromrf, 100, input);
for (x = 0; x <= 6; x++) nmea_bits[x] = fromrf[x];
nmea_bits[6] = '\0';
}
// At this point I have a valid GPGGA string in fromrf
// Check the GPS has a fix
y=0;
for (x=0;x<=5;x++)
{
while (fromrf[y++] != ',');
}
// y has the position of the "fix or no fix" digit
if (fromrf[y] != '1')
{
printf ("\n No fix %c\n", fromrf[y]);
return;
}
// Got here, have a fix
// I need to extract lat and long, here is a valid line
// $GPGGA,141733.000,3742.434306,N,02403.104390,E,1,4 ,5.25,53.819,M,35.179,M,,*68
// $GPGGA,064733.327,3742.4148,N,02403.0913,E,1,03,12 .8,0.0,M,35.2,M,0.0,0000*48
// Time: 141733.000, 14:17:33, 1000ths of seconds, not needed
// 3742.434306,N, 37 degrees, 42.434306 minutes, North. 11 digits needed and the N (it maybe S sometimes)
// 02403.104390,E, 24 degrees, 03.104390 minutes East. 12 digits needed and the E (it may be W sometimes)
// 1 have GPS fix, anything else means no fix
// The rest are of no interest, maybe checksum at the end if we have problems

//printf ("%s", fromrf); // print all of the string
y=0;
for (x=0;x<=2;x++)
{
while (fromrf[y++] != ',');
}
y--;
x=0;
z=y;
while (fromrf[--z] != ',');

// y is the comma at the end of the latitude
// z is the comma at the beginning of latitude

if (fromrf[y+1] != 'N') nmea_bits[x++] = '-';

z++;
//These two for the whole degrees
nmea_bits[x++] = fromrf[z++];
nmea_bits[x++] = fromrf[z++];
nmea_bits[x++] = '\0';

// z points at the MS minutes digit
x=0;
if (nmea_bits[0] == '-') minutes[x++] = '-'; // if degrees are negative make minutes negative
while (z++ < y)
{
minutes[x++] = fromrf[z-1];
}
minutes[x++] = '\0';

// We have number of whole degrees in "nmea_bits", minutes in "minutes"
// "minutes[]" and "nmea_bits[]" needs converting to floats
// divide minutes by 60, add to nmea_bits
// and converting to a string stored in latit[]
// that will give us the latitude in degrees and decimal degrees

// Get previous lat and long for path and distance
// As floats here
min2deg = atof(minutes);
min2deg = min2deg / 60;
deg = atof(nmea_bits);
lat = deg + min2deg;
sprintf (latit, "%f", lat);
latitude = latit;
// latitude as degrees now stored in latit[] and displayed in latitude box
// x is not needed, y and z are the same and are the comma before the N
// nmea_bits[] is not needed, minutes[] is not needed
y=y+3;
// We should now be at the first digit of the longtitude with y
x=0;
z=y; // and z
// need to find sign (East or West)
while (fromrf[y++] != ',');
// y is now the sign, East or West
if (fromrf[y] != 'E') nmea_bits[x++] = '-';
// sign sorted
// whole longtitude degrees into nmea_bits
nmea_bits[x++] = fromrf[z++];
nmea_bits[x++] = fromrf[z++];
nmea_bits[x++] = fromrf[z++];
nmea_bits[x]= '\0';
// whole degrees sorted
x=0;
if (nmea_bits[0] == '-') minutes[x++] = '-'; // if degrees are negative make minutes negative
while (z++ < y)
{
minutes[x++] = fromrf[z-1];
}
minutes[x++] = '\0';
min2deg = atof(minutes);
min2deg = min2deg / 60;
longt = atof(nmea_bits);
longt = longt + min2deg;
sprintf (longti, "%f", longt);
longtitude = longti;
// Latitude, Longitude, N, S E and W now sorted
place_to_xml();
}

int main( int argc,
char *argv[] )
{
latitude = "No data";
longtitude = "No data";
printf ("%s, %s\n", latitude, longtitude);
while (1)
{
xml_create();
callback();
printf ("%f, %f\n", lat, longt);
sleep(2);
}
return 0;
}

The above is the C source to make the "gps_pos.kml" file with 2 second update on the GPS data.

The serial port is defined as /dev/rfcomm4 in the source so your BT GPS has to be there.

It should be pretty portable so here is the binary.

No responsibility accepted for trashed PCs and keep the comments about my C programming abilities on the humourous side, I know I am pretty crap at it. Maybe someone wants to do it properly from here. :)