[Openstreetmap] How do I talk to the GPS to get the info we need?

Petter Reinholdtsen pere at hungry.com
Sat Nov 13 00:51:19 GMT 2004


[Jo Walsh]
> slightly arcane format, but there you are. gpsbabel definitely
> supports this. as for post-facto DGPS correction it's a good idea; the
> nearest DPGS server to london that i know of it in italy though. we'd
> toyed with the idea of having a whip-round to set one up in
> limehouse...

Do you know how to query the GPS using NMEA-0183 v2.20 in a way that
get it to report accuracy info and enough info to be able to
post-process the collected data with DGPS corrections?

At the moment, I use this perl script, but it do not collect accuracy
information and have no idea about the raw satellite measurements.


#!/usr/bin/perl
#
# Author:  Petter Reinholdtsen
# Date:    2004-10-07
# License: GPL
#
# Connect to gpsd, and store coordinate info into an SQL database.

use strict;
use warnings;
use DBI;
use Socket;
use Getopt::Std;

use vars qw($debug $gpsdhost $gpsdport %opts);

getopt("dh:", \%opts);

$debug = $opts{'d'} || 0;

$gpsdhost = $opts{h} | "localhost";
$gpsdport = "2947";

my $period = 1; # How many seconds between each position check?

# Connect to gpsd

my $socket = tcp_connect($gpsdhost, $gpsdport);
# Turn off buffering on $socket
my $old_fh = select($socket);
$| = 1;
select($old_fh);

# Connect to database

my $dbname  |= "pere";
my $dbuser  |= "" ; # "pere";
my $dbpass  |= "" ; # "pere";
my $dbtable |= "tempPoints";

my $dbh = DBI->connect("dbi:Pg:dbname=$dbname", $dbuser, $dbpass,
		       {'AutoCommit' => 1}) ||
    die "Unable to connect to database";

# Turn off buffering on stdout
$| = 1;

print "Starting $0\n";

while (1) {
    print $socket "aps\n";
    # flush socket
    my $line = <$socket>;
    if ( ! defined $line) {
	$socket->close();
	$socket = tcp_connect();
	next;
    }
    $line =~ s/\r\n//;
    print "\nL: '$line'\n" if $debug;
    my ($x, $y, $altitude, $status);
    my @token = split(/,/, $line);
    for (@token) {
	if (m/^P=(\S+) (\S+)/) {
	    $x = $1;
	    $y = $2;
	}
	$altitude = $1 if (m/^A=(\S+)/);
	$status = $1 if (m/^S=(\d+)/);
    }
    if (1 == $status) { # Satellites in view

	# This SQL is PostgreSQL specific
	my $sql = "INSERT INTO $dbtable (g, altitude) VALUES ".
	    "('($x, $y)'::point, '$altitude');";

	$dbh->do($sql) || print "S: '$sql'\n";
	print ".";
    } else {
	print "_";
    }
    sleep $period;
}

sub tcp_connect {
    my ($iaddr, $paddr, $proto);

    if ($gpsdport =~ /\D/) { $gpsdport = getservbyname($gpsdport, 'tcp') }
    die "No port" unless $gpsdport;
    $iaddr   = inet_aton($gpsdhost)             || die "no host: $gpsdhost";
    $paddr   = sockaddr_in($gpsdport, $iaddr);
    $proto   = getprotobyname('tcp');
    socket(SOCK, PF_INET, SOCK_STREAM, $proto)  || die "socket: $!";
    connect(SOCK, $paddr)                       || die "connect: $!";
    return *SOCK;
}

sub createTable {
    my $dbh = shift;
    # Postgresql table
    $dbh->do("CREATE TABLE $dbtable (g point, altitude float4,".
	     "stamp datetime default now());");
}




More information about the talk mailing list