In the course of implementing a GPS node for my Uavcan-For-Hobbiests project I found the handling of the fix status and gnss timestamping quite unclear, and thus spend a whole day just to inspect the zubax, AP-Uavcan and AP native GPS codes for these parts.
I’ve noted some inconsistencies, which I want to bring to attention. I lack the knowledge to judge on whether these are of practical relevance or not; I suspect they might lead to different behavior in e.g. GPS outages. I describe what I see from looking at the code, which implies that I might have read it incorrectly.
I refer to a ublox m8 gps, and compare its behavior when either connected natively (AP_GPS_UBLOX.cpp) or when a zubax gps is connected via uavcan (zubax_gnss…\ublox.cpp and AP_UAVCAN.cpp)
The inconsistencies are related to how the fields “valid” and “flags” of the ublox ubx NAV-PVT message are handled, or not handled. I’ll discuss that separately for the fix and the timestamp issue.
I refer to the document "“u-blox 8 / u-blox M8 Receiver Description Including Protocol Specification”.
FIX
zubax
runs the ubx packets NAV-PVT, NAV-SOL, NAV-DOP, NAV-SAT, NAV-TIMEGPS; fix state is taken from NAV-PVT.
ardupilot
for m8 it runs the ubx packets NAV-SOL, NAV-PVT, NAV-DOP; fix state is taken from NAV-PVT.
NAV-SOL, NAV-PVT, NAV-DOP all have a navigation flag field “flags”.
For NAV-STATUS the ublox docu says: “GPSfix Type, this value does not qualify a fix as valid and within the limits. See note on flag gpsFixOk below.” Such a comment is not found for NAV-SOL and NAV-PVT. However, one would think that this comment equally applies to NAV-PVT and NAV-SOL, especially as both also have a flags field.
I note this:
Neither the zubax code nor the AP code evaluate the flags field in determining the fix state.
(zubax: https://github.com/Zubax/zubax_gnss/blob/master/firmware/src/board/ublox.cpp#L374-L394)
(ap: https://github.com/ArduPilot/ardupilot/blob/master/libraries/AP_GPS/AP_GPS_UBLOX.cpp#L956-L987)
However, for the NAV-SOL and NAV-STATUS messages the AP code DOES evaluate the flags field! That is, for a non-PVT (e.g. m6) gps, where NAV-SOL is used, the AP code behaves differently than for a m8 gps.
(NAV-SOL: https://github.com/ArduPilot/ardupilot/blob/master/libraries/AP_GPS/AP_GPS_UBLOX.cpp#L875-L890)
(NAV-STATUS: https://github.com/ArduPilot/ardupilot/blob/master/libraries/AP_GPS/AP_GPS_UBLOX.cpp#L914-L929)
My 2 cents: I would think that that the “flags” field should also be considered for NAV-PVT.
GNSS TIME
zubax
runs the ubx packets NAV-PVT, NAV-SOL, NAV-DOP, NAV-SAT, NAV-TIMEGPS; gnss timestamp is taken from NAV-PVT (only UTC used)
ardupilot
for m8 it runs the ubx packets NAV-SOL, NAV-PVT, NAV-DOP; gnss timestamp is taken from NAV-SOL (week) and NAV-PVT (TOW)
AP seems to store the GPS time in the variables state.time_week and state.time_week_ms, which are filled from NAV-SOL and NAV-PVT, respectively, for a natively connected m8.
NAV-PVT has a Validity Flag “valid”, but not so NAV-SOL. The “valid” field indicates the validity of the time and date.
I note this:
zubax sets gnss.timestamp only if (pvt.valid & UtcValidFlags) == UtcValidFlags, that is, it evaluates the valid flag. In the AP UAVCAN module the state.time_week and state.time_week variables are set only if status == STATUS_NO_FIX and gnss_time_standard == GNSS_TIME_STANDARD_UTC. Thus, effectively, in setting the GPS time both the valid flag and the fix status are evaluated.
(zubax: https://github.com/Zubax/zubax_gnss/blob/master/firmware/src/board/ublox.cpp#L404-L422)
(AP_UAVCAN: https://github.com/ArduPilot/ardupilot/blob/master/libraries/AP_UAVCAN/AP_UAVCAN.cpp#L64-L84)
In contrast, for a m8 gps connected natively neither the valid flag nor the fix state are considered.
(week: https://github.com/ArduPilot/ardupilot/blob/master/libraries/AP_GPS/AP_GPS_UBLOX.cpp#L906-L913)
(TOW: https://github.com/ArduPilot/ardupilot/blob/master/libraries/AP_GPS/AP_GPS_UBLOX.cpp#L1016)
However, for a non-PVT (e.g. m6) gps, when AP extracts the time completely from NAV-SOL, both variables are set only if next_fix >= AP_GPS::GPS_OK_FIX_2D.
(https://github.com/ArduPilot/ardupilot/blob/master/libraries/AP_GPS/AP_GPS_UBLOX.cpp#L934-L938)
One thus obtains different behavior for the three cases, zubax, m8 natively, m6 natively.
My 2 cents: AP obviously must already be able to handle “jumps” in the gnss time. I would thus think that the correct gnss time (=derived from a gnss) should be used as soon as it’s available, i.e., when the valid flag suggests this, but would not add additional dependencies such as on the fix state.
Comment: Also the case when the gnss time is rejected/invalid should be considered. I note this:
zubax: If the UTC is not yet valid, it seems to deliver a “self-made” UTC time.
AP UAVCAN: If the timestamp is not of type UTC, it doesn’t seem to accept any time stamp. Not sure what time it when uses. IS THIS A BUG?
Very confusing, all this. To me it looks as if no one with sufficient knowledge (= not me) ever went over this consistently.
That’s what I concluded, might be correct or not.
Cheers, Olli