Reading Velocity from a GPS (Emlid Navio2 Hardware (Ublox GPS))

True Story Follows

So I’m on the grind now at my real work getting my foot in the door with the GPS game. It turns out there’s a lot of ins, a lot of outs, and a lot of what-have-you’s going on there. I checked out The Uber Engineering Blog to see some of what my company is currently doing to best estimate accuracy, and in doing so I noticed that doppler shift is being used to compute velocity directly from the GPS. “Wow, that sounds really complicated,” I thought. But it turns that’s just what the GPS is already doing. That’s like me starting to talk about how I use radio waves at particular frequencies to create vibrations in molecules that have two opposing poles in order to heat up food, but really I’m just turning on the microwave. In the same way, velocity is included by default in GPS readings, but I just didn’t know it, and it wasn’t exposed by default in the off the shelf code I was using. Moreover though, it’s interesting to note that velocity from GPS should be more accurate than the actual position provided since velocity can be inferred more directly, and the actual margin of error is included in the reading.

In my quest to modify the off the shelf code included in the Emlid Navio2 repo, I ran into none other than Lars Soltmann on the internets, who as it turned out had done all the work already I’d set out to do. He’s clearly the most badass flight test engineer I’ve ever met online.

The Code

Well, what can I say? Lars already wrote all the code. I just refactored it to my own tastes. The repo is here: UBlox GPS code with velocity

It should be noted though that the API provided has a few important assumptions made. First, in my case I’m working in a multi-threaded environment; in particular, I’m using Go as a wrapper around C++ code, so the commands sent to interface with the GPS hardware are completely independent of the reads to the API. And in this case, the I/O to the GPS hardware is inside of an infinite loop that mutates variables in memory. So in my case, I simply spawn a goroutine that blocks indefinitely to foster GPS I/O, and a separate Goroutine will read the actual values ascertained from the hardware. The actual collective output from the GPS hardware is not atomic, so I did nothing to prevent the possibility of, say, reading a latitude that doesn’t actually correspond to an immediately subsequent read of a longitude.

Another interesting piece I learned was about GPS navigation modes which Lars had warned me about. Coincidentally though, my use case was identical so I didn’t need to change anything. Anyway, you can apparently set different types of navigation modes to your GPS reader. In essence, you can allow the GPS to make certain assumptions about your use case in order to obtain better results. For example, if you’re driving on the freeway in the middle of Arizona on a long and lonesome highway daydreaming about the woman you left back home (or man; I don’t want to assume anything here), then you can safely assume that your altitude will not change significantly, and you should therefore be able to get better estimations on a 2 dimensional plane.