Pirate Ship : GPS Experiments
From Bob's Basement
GPS
I bought an extremely cheap USB GPS thingy from an eBay store (£25). I don't expect it to be great quality, but it'll do whilst I'm experimenting.
It's a UT-41 USB 12-Channel NMEA-0183 GPS Receiver, which I got from TekGems
I'm using Sabayon Linux and it seems that it has the correct modules already installed:
[11281.527000] usb 4-1: new full speed USB device using uhci_hcd and address 4 [11281.674000] usb 4-1: configuration #1 chosen from 1 choice [11281.677000] pl2303 4-1:1.0: pl2303 converter detected [11281.678000] usb 4-1: pl2303 converter now attached to ttyUSB0
I searched CPAN for a perl module to grab NMEA data, and found GPS::NMEA which looked promising. HOWEVER there is a problem with the one of the test scripts, namely connect.t
Here is the process I used to get the module installing properly
cpan> install GPS::NMEA - bla bla bla, FAIL! cpan> look GPS::NMEA
You get a shell prompt in the distribution's directory.
cd t/ nano connect.t
On line 26 there is a problem. It doesn't specify what serial port to use. Change this:
eval {
my $gps = GPS::Garmin->new(timeout => 1);
};
to
eval {
my $gps = GPS::Garmin->new(Port => '/dev/ttyUSB0',timeout => 1);
};
One last thing! At the root prompt:
chmod 776 /dev/ttyUSB0
Now exiting back to the cpan prompt...
cpan> install GPS::NMEA
And it installs perfectly.
Using the following code snarfed from the CPAN page...
#!/usr/bin/perl
use GPS::NMEA;
my $gps = GPS::NMEA->new(Port => '/dev/ttyUSB0',
Baud => 4800);
while(1) {
my($ns,$lat,$ew,$lon) = $gps->get_position;
print "($ns,$lat,$ew,$lon)\n";
}
You can output your GPS position. I modified it a bit so it would only output it when the position changes. As such:
#!/usr/bin/perl
use GPS::NMEA;
my $gps = GPS::NMEA->new(Port => '/dev/ttyUSB0',
Baud => 4800);
my @old_data = ();
while(1) {
my @data = $gps->get_position;
if (@data != @old_data) {
my($ns,$lat,$ew,$lon) = @data;
print "($ns,$lat,$ew,$lon)\n";
@old_data = @data;
}
}
This kinda works. I will post outputs of this code soon. From my preliminary tests, It places me at 51.369922N 0.455768W, which according to Google Maps is about 30 MILES away from my real position. I'm trying to work out what exactly the issue is - I have a feeling the format I'm outputting this in may be dodgey.
I also played with gpsd, which allows other apps to use the data. Unfortunately, I can't install Position as the distribution tarball has no config scripts and I can't be bothered to autoconf it up. There are other applications, like gpsdrive, which I've tried out. Unfortunately the maps are just too low res to come to any conclusions as to how accurate it may be.
I have a feeling when we implement this we'll use gpsd, as there are some nice C/C++ wrappers which makes life a lot easier.
gpsd
This is an odd one. Preliminaries, first...
# chmod 777 /dev/ttyUSB0 # ln -s /dev/ttyUSB0 /dev/gps
You need to do this every time you connect the device, or you cannot access it via gpsd or any other application for that matter.
If you don't do this, then gpsd will exit either straight away or when you connect to it - giving you no error whatsoever. Infuriating! To run gpsd in debug mode, you use the following:
$ gpsd -D 10 -F /dev/ttyUSB0 command line options: debug level: 10 gps file name: /dev/ttyUSB0 file line timing: 0.200 sec gpsd port: 2947 latitude: 3600.000N longitude: -12300.000W
This is what will come up when the device does not have a fix. Checking with the hardware, I see a frequently blinking light - which according to the manual means it has a fix. gpsd, even with the highest debug level, is a shy thing. To get a bit more out of it, I strace it. This is much more useful, however gives a hell of a lot of output which I won't post here.
However it does give you debug information when you connect to it. I throw together a simple perl script (ensure that you get Net::GPSD installed with cpan first). Note that I have included the ability to start gpsd automatically from the script itself, but currently it's been commented out to aid debugging.
#!/usr/bin/perl
use warnings;
use strict;
use Net::GPSD;
use Data::Dumper;
$SIG{'INT'} = 'CLEANUP';
print "[+] Starting gpsd ...";
# my $gpsd = system("gpsd -F /dev/ttyUSB0");
# my $gpsd_proc = $?;
# if ($gpsd == 0) {
# system("kill $gpsd_proc");
# die("FAILED TO START GPSD");
#}
print "done\n";
my $obj=Net::GPSD->new() or die("No device!");
print "Starting loop\n";
while (1) {
my $point = $obj->get();
if (!$point->fix) { print "Waiting to get fix ...\n"; }
while (!$point->fix) {
$point = $obj->get();
sleep(1);
}
print "\t".$point->latlon."\n";
sleep(1);
}
sub CLEANUP {
print "[+] Killing gpsd ... ";
# system("kill $gpsd_proc");
print "done\n";
exit(0);
}
Looking at gpsd, I get the following output:
1����6��6�f�v���&�F�v�YS6Vk Unknown exception: "1����6��6�f�v���&�F�v�YS6Vk" Lat: 0.000000 Lon: 0.000000 Alt: 0.000000 Sat: 0 Mod: 0 Time: $GPGGA,2034xx.00,5136.97xxx,N,00xx5.5xx8,W,1,04,05.0,00169.5,M,0046.4,M,,*4C Lat: 51.61xxxx Lon: -0.75xxxx Alt: 169.500000 Sat: 4 Mod: 0 Time: $GPGSA,A,3,,,,06,14,07,,,,09,,,09.0,05.0,07.4*00
This isn't at all what I was looking for. However, in the debug information the Lat's and longs are correct. (I've obscured the values in the output for privacy reasons).
However, over in the perl script, it reports having no fix. This is odd. Even when I try to output the lats and longs when there is no (supposed) fix, I still get nothing. I have an feeling that perhaps Net::GPSD doesn't work properly on my system.

