summaryrefslogtreecommitdiff
path: root/TODO
blob: c58b349445ba211e81945ecce6c874be382e4731 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
This is the gpsd to-do list.  If you're viewing it with Emacs, try
doing Ctl-C Ctl-t and browsing through the outline headers.

** Supply geoidal separation for SiRF packet 2

Peter H. Dana <pdana@pdana.com>:
> 	The classic bi-linear interpolation method is published in Table 5.3
> of DMA TR8350.2 Supplement B (page 5.3)
> 
> Np(lat, lon) = a0 +a1*X + a2*Y +a3*X*Y
> 
> a0 = N1
> a1 = N2-N1
> a2 = N4-N1
> a3=N1+N3-N2-N4
> 
> X= (lon-lon1)/(lon2-lon1)
> Y = (lat-lat1)/(lat2-lat1)
> Whre 
> N1 (lat1, lon1) , N2 (lat1, lon2), N3( lat2,lon2), N4 (lat2, lon1) are known
> geoid heights 
> 
> Rather than deal with interpolation from a table, most folks use the EGM96
> coefficients and the formulas for direct computation of N at any point shown
> in NIMA TR8350.2
> http://earth-info.nga.mil/GandG/tr8350_2.html

** Hotplug interface problems

The hotplug interface works pretty nicely for telling gpsd which
device to look at, at least on my FC3 Linux machines.  The fly in the
ointment is that I'm using a deprecated version of the interface, the
old-style /etc/hotplug version with usermap files.

It is unlikely this interface will be dropped by distro makers any
time soon, because it's supporting a bunch of popular USB cameras.
Still, it would be nice not to be using a deprecated interface.

I tried moving to the new-style /etc/hotplug.d interface, but I ran
into a nasty race condition.  My hotplug agent got woken up on a USB
add event as it should, but in the new interface the creation of
/dev/ttyUSB* can be delayed arbitrarily long after the wakeup event.
Thus, it may not be there when gpsd goes to probe it unless I
busy-wait in the script.

Ultimately this should all be done through udev.  The problem is that at
the current state of udev, we'd need to do it through a script that would
fire every time a tty activates.  Because of virtual consoles firing up at
boot time, this would introduce significant boot lag.

This would be antisocial and I'm not willing to do it, so udev needs
to grow better filtering before I'll use it.

When and if udev supports HOTPLUG and ACTION keys, this will work:

# The Prolific Technology 2303 (commonly in tandem with SiRF chips)
BUS="usb" SYSFS{vendor}="067b" SYSFS{product}="2303" \
		NAME="gps%e" \
		HOTPLUG="/usr/bin/gps-probe"
# FTDI 8U232AM
BUS="usb" SYSFS{vendor}="0403" SYSFS{product}="6001" \
		NAME="gps%e" \
		HOTPLUG="/usr/bin/gps-probe"
# Cypress M8/CY7C64013 (DeLorme uses these)
BUS="usb" SYSFS{vendor}="1163" SYSFS{product}="0100" \
		NAME="gps%e" \
		HOTPLUG="/usr/bin/gps-probe"

More generally, the hotplug code we have is Linux-specific.  OpenBSD
(at least) features a hotplug daemon with similar capabilities.  There
has been some debate about going to the cross-platform libusb library
to do device scanning, but this would create a complex dependency that
gpsd doesn't now gave, and bring more complexity on board than is
probably desirable.

** Should sirfmon be part of the release?

SiRF GPSes have a lot of tuning knobs on them that are accessible
through the binary protocol but not the NMEA one.  Considering how
ubiquitous SiRF GPSes are today (over 80% market share) maybe sirfmon
should turn into a tool for twiddling those knobs and actually be
installed in /usr/bin along with gpsd/xgps/xgpsspeed.

Before that can happen, it needs documentation and more interface
tweaks.

** The mess near error modeling

One of my goals has been to report an uncertainty along with every
dimension of PVT, so that the return from the GPS actually (and
realistically) describes the volume of kinematic state space within
which it is located at 1-sigma or 66% confidence. (Because the errors
are taken to be normally distributed, we can square the error to get
2-sigma or 95% confidence.)

There are several problems with this. 

A. I don't know how to derive or estimate uncertainty of time in the
general case.  There are clock drift and bias fields in the SiRF
binary protocol, but I don't know how to interpret these.  Does
anyone?

B. SiRF binary reports HDOP, SiRF and other NMEA devices report
HDOP/VDOP/PDOP.

C. Only Garmin devices report estimated position errord in meters.
They won't say what the confidence interval is, but it is generally
believed to be 1-sigma.  See <http://gpsinformation.net/main/epenew.txt>.

Here is what I am presently doing in the new E command:

1. I pass up the Garmin PGRME fields (uncertainty in meters) if
   they're available.

2. Otherwise, I apply the error model described in gpsd.h.  See the
   comment near the definition of UERE.

What non-Garmin GPSes will return in the E command is UERE multiplied
by PDOP/HDOP/VDOP.  Annoyingly, SiRF binary mode only offers HDOP, the
one respect in which it is functionally inferior to SiRF NMEA.

I don't know, because my sources didn't give, the confidence level
associated with the range uncertainties in gpsd.h.  My educated guess
is that they are 1-sigma (66%), and that's what the gpsd documentation
now says, but it needs to be confirmed.

I don't currently pass back uncertainty of speed or track at all,
though SiRF chips make those available.  To do so would require yet
another protocol extension, which gets into "Does the GPSD protocol
need to be redesigned?".

This area needs some attention from somebody who cares a lot about
GPS accuracy and is willing to do research on error budgets to pin
down the numbers and confidence levels.

** Multi-session semantics

gpsd has been evolving away from being a simple device monitor towards
being a persistent agent whose job it is to impedance-match between
GPSes and applications (one which may talk to several devices in its
lifetime).  Steps in this evolution have been:

1. Automatic device reconnect, which already almost worked in 1.10.

2. The X command reporting on whether a GPS is available.

3. The B command allowing a client to change the connection baud rate.

4. The F command allowing GPS to switch devices when only the
   switch-requesting client is active.

An issue that came up in my conversation with David Zeuthen is that
HAL would (at least philosophically) like to support *multiple* GPSes.
Whether HAL integration happens or not, this started me thinking about
multi-GPS support in gpsd.

Implementing multi-GPS support would not be a large problem.  One
of my major goals in re-architecting the daemon code was to turn as
much of it as possible into a re-entrant library keeping its data in a
single session structure.  I achieved this so completely that the
entire daemon has only eight global variables, all of them visible
only within gpsd.c.  Of these, only two are potentially per-session.

At the implementation level, then, gpsd is already close to being
multi-GPS-ready. The real problem is at design level.  We need to
figure out what the right lifetime rules for GPS sessions should be.

At the moment, a GPS session begins when the first client connects.  The
daemon takes this as a cue to open the current GPS device, which may
have been set by the command-line -f option or an F command (the F
command will usually have been generated by a hotplug script).  When
the last client exits, the GPS device is closed and the session ends.   

There are two rules about F commands:

1. An F command fails if probing the specified device does not
confirm it is a GPS.  gpsd reverts to the previous device.

2. An F command also fails if there is more than one client attached.

3, All client sessions talk to the same device, the one specified by the
   last successful F command.

The effect of the combination of these rules is to prevent
denial-of-service attacks.  They mean that a rogue client cannot
prevent other processes from getting GPS service by pointing
gpsd at a bogus device.  A rogue client cannot even change 
which device another client sees.

Now, suppose we want to support multiple clients talking to multiple
GPSes using just one instance of gpsd?  The reason to want this is
that, ideally, access to all GPSes should go through the same
well-known port.  Also, a multi-session gpsd would be convenient for
supporting multiple GPSes in HAL.

Rule 1 would still be good.  But now we want a client to be able to switch
to a new device without affecting other clients, so rules 3 and 2 break.

We can't just use F for device switching, because hotplug scripts
need it in order to tell gpsd when a new device is available for
all clients.  F will need to have the semantics "add a GPS to gpsd's
internal search list (and switch this client to use that GPS)".  

We'll need to have a new command that removes a GPS from the GPS list
(hotplug scripts will use it to cue gpsd on a remove event).  For the
sake of the discussion, let's name that command K.

The interesting questions are these: 

(1) When a client connects to gpsd, and more than one GPS is hot, 
    which one does it get by default?

(2) What should happen to a client session when its GPS gets unplugged 
    *and other devices are available*?

** Subsecond polling

gpsd relies on the GPS to periodically send PVT reports to it.

Most GPSes send PVT reports once a second.  No GPS I am aware of
allows you to set a cycle time of less than a second.  This is because
at 4800bps, a full PVT report takes just under one second.

At 50km/h (31mi/h) that's 13.8 meters change in position between
updates, about the same as the uncertainty of position under typical
conditions.

There is, however, a way to sample GPSes at higher frequency.  SiRF
chips, and some others, allow you to shut down periodic notifications
and poll them for PVT.  At 57600bps we could poll a NMEA GPS 16 times
a second, and a SiRF one maybe 18 times a second.

Is this worth doing?  Maybe.  It would reduce fix latency, possibly
to good effect if your GPS is in motion.  Opinions?  Calculations?

** Can the o command replace most of the protocol?

Considered abstractly, what we really want a GPS to report is a
13-element vector describing an uncertainty volume in kinematic space:

time, timerr     = timestamp, estimated time error
lat, lon, alt    = latitude, longitude, altitude
herr, verr       = horizontal and vertical position error
speed, speederr  = groundspeed and groundspeed error
track, trackerr  = course over ground and course error
climb, climberr  = climb/sink and climb/sink error

The experimental 'o' command approximates this. The 'o' and 'y' commands
together span all the information that gpsd can get (minor exception;
'o' doesn't report total spherical uncertainty of position, just the
horizontal and vertical uncertainties).

There are two issues connected with 'o'.  One is how to fill in the
currently missing fields: speederr, trackerr, and climberr.  The other
is trickier and has to do with what timestamp the o return should have.

Internally, a GPS typically takes a fix once in its basic cycle time 
(typically once per second).  It then generates a report.  A SiRF chip
reporting in binary mode ships almost everything we want in a single
packet with a single timestamp.  When reporting in NMEA mode, the
report consists of several sentences, all normally with the same 
timestamp.

There are exceptions, however.  The Garmin 48 is one -- it seems to
have two 1-second half-cycles, one that ships GPMRC/GGA and another
that ships GLL, with a different timestamp and possibly a different
latitude/longitude.

Un-exceptional GPSes could have the information from the entire cycle
bundled into one 'o' report with a single timestamp, that of the
start of cycle.

** Explicitly turn on WAAS/EGNOS on SiRF chips

Chris Kuethe reports that some firmware versions leave it off.

** HAL integration

David Zeuthen is the lead programmer on the Hardware Abstraction
Layer.  HAL aims to be at least two things: 

(1) An attempt to centralize and/or coordinate device probes and 
hardware autoconfiguration.  

(2) A standard interface for reading and writing hardware
configuration info on D-BUS.

David wants to include GPSes in HAL.  The functional implication is
that gpsd should publish PVT and status information on the D-BUS 
through the HAL libraries.  

Here is the state of our exchange about publishing PVT data:

> > So, should I compose a 'gps' namespace?
> 
> Yeah, that would be helpful - the hal spec is a little bit out of date
> but basically your properties are key/value pairs where keys are ASCII
> strings and the values assumes one of the following types
> 
>  o  int32
>  o  uint64
>  o  double
>  o  boolean
>  o  UTF-8 string
>  o  List of UTF-8 strings
> 
> I think it would be pretty easy to write this code, it is somewhat
> exemplified here
 
>  http://cvs.freedesktop.org/hal/hal/hald/linux2/addons/addon-hid-ups.c?rev=1.2&view=auto
> 
> So, basically, it would go like this
> 
> 	dbus_error_init (&error);
> 	if ((conn = dbus_bus_get (DBUS_BUS_SYSTEM, &error)) == NULL)
> 		goto out;
> 	if ((ctx = libhal_ctx_new ()) == NULL)
> 		goto out;
> 	if (!libhal_ctx_set_dbus_connection (ctx, conn))
> 		goto out;
> 	if (!libhal_ctx_init (ctx, &error))
> 		goto out;
> 
> 	dbus_error_init (&error);
> 	if ((gps_udis = libhal_manager_find_device_string_match (
> 		    ctx, "serial.device", your_device_file_for_the_gps,
>                     &num_udis_found, &error)) == NULL || num_udis_found != 1)
> 		goto out;
> 
> 	libhal_device_set_property_double (ctx, udi, "gps.longitude", the_longitude);
> 	libhal_device_set_property_double (ctx, udi, "gps.latitude", the_latitude);
> 	/* and so on */
> 	libhal_device_add_capability (ctx, udi, "gps"), &error);
> 
> You probably also want to rate limit how often you write these properties, 
> e.g. only every few seconds or so. You can then check this with 
> hal-device-manager.

We are also discussing hotplug integration.  The issue there is that HAL
wants to centralize all device probing into itself so that devices see
as few probes as possible and the probes don't step on each other

Playing nice in the HAL world may require that we replace our hotplug
script with launcher code that lives in the HAL daemon.

** Do the research to figure out just what is going on with status bits

NMEA actually has *four* kinds of validity bits: Mode, Status, the
Active/Void bit (some sources interpret 'V' as 'Navigation receiver
warning'), and in later versions the FAA indicator mode.  Sentences
that have an Active/Void send V when there is no fix, so the position
data is no good.

Let's look at which sentences send what:

                GPRMC     GPGLL     GPGGA     GPGSA
Returns fix      Yes       Yes       Yes        No
Returns status   No        Yes       Yes        No
Returns mode     No        No        No         Yes
Returns A/V      Yes       Yes       No         No

In addition, some sentences use empty fields to signify invalid data.

My first conclusion from looking at this table is that the designers
of NMEA 0183 should be hung for galloping incompetence.  But never mind that.
What are we to make of this mess?

The fact that the FV18 sends GPMRC/GPGLL/GPGGA but not GPGSA
argues that GPGSA is optional.  I don't see how it can be, since it
seems to be the only status bit that applies to altitude.  Just how are
we supposed to know when altitude is valid if it doesn't ship GSA?  
Can a receiver ever ship a non-empty but invalid altitude?

Which of these override which other bits?  I don't think status is ever
nonzero when mode is zero. So status overrides mode.  What other such
relationships are there?

Local variables:
mode: outline
paragraph-separate: "[ 	]*$"
end: