Mercurial > ublox > ublox8
changeset 56:3535be2e3824
print-state: print assembled Galileo state
Feed all Galileo related UBX-RXM-SFRBX messages into the Galileo state
parsing code, and print the resulting ephemeris and time info.
Signed-off-by: Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
author | Josef 'Jeff' Sipek <jeffpc@josefsipek.net> |
---|---|
date | Thu, 16 Jan 2020 18:28:59 -0500 |
parents | af7b01ad6d05 |
children | a259f88f6a11 |
files | .hgignore CMakeLists.txt print-state.c |
diffstat | 3 files changed, 226 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- a/.hgignore Thu Jan 16 18:25:07 2020 -0500 +++ b/.hgignore Thu Jan 16 18:28:59 2020 -0500 @@ -13,3 +13,4 @@ capture dump-ecef dump-ubx +print-state
--- a/CMakeLists.txt Thu Jan 16 18:25:07 2020 -0500 +++ b/CMakeLists.txt Thu Jan 16 18:28:59 2020 -0500 @@ -98,3 +98,13 @@ target_link_libraries(dump-ubx ublox8 ) + +add_executable(print-state + dump-common.c + print-state.c +) + +target_link_libraries(print-state + gnss + ublox8 +)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/print-state.c Thu Jan 16 18:28:59 2020 -0500 @@ -0,0 +1,215 @@ +/* + * Copyright (c) 2020 Josef 'Jeff' Sipek <jeffpc@josefsipek.net> + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include <time.h> +#include <math.h> + +#include "dump-common.h" +#include "gnss.h" +#include "gnss-galileo.h" + +struct info { + enum gnssid gnssid; + unsigned svid; + unsigned channel; + + union { + struct galileo_inav_page galileo; + struct { + int freqid; + } glonass; + }; +}; + +static bool msg2info(const struct ubx_rxm_sfrbx *msg, + const uint32_t *words, struct info *info) +{ + ASSERT3U(msg->version, ==, 0x02); + + info->gnssid = msg->gnssid; + info->svid = msg->svid; + info->channel = msg->channel; + + switch (info->gnssid) { + case GNSSID_GPS: + ASSERT3U(msg->num_words, ==, 10); + return true; + case GNSSID_SBAS: + ASSERT3U(msg->num_words, ==, 8); + return true; + case GNSSID_GALILEO: + return galileo_parse_inav_page(&info->galileo, words, + msg->num_words); + case GNSSID_BEIDOU: + ASSERT3U(msg->num_words, ==, 10); + return true; + case GNSSID_IMES: + case GNSSID_QZSS: + panic("not yet implemented - gnssid %u", info->gnssid); + case GNSSID_GLONASS: + ASSERT3U(msg->num_words, ==, 4); + + info->glonass.freqid = msg->freqid - 7; + return true; + } + + fprintf(stderr, "Unknown gnssid %u in ubx message\n", msg->gnssid); + + return false; +} + +static void galileo_update_eph(struct galileo_state *state, + const struct galileo_ephemeris *prev, + const struct galileo_ephemeris *new) +{ + double disco_now; + double disco_t0; + double prev_eph_age; + + if (!prev) { + /* nothing to do */ + disco_now = NAN; + disco_t0 = NAN; + prev_eph_age = NAN; + } else if (!memcmp(prev, new, sizeof(struct galileo_ephemeris))) { + /* The ephemeris is exactly the same - we don't care. */ + return; + } else { + /* + * A different ephemeris - must have a newer t0. + * + * Note: It is tempting to assert that the iod has changed + * (i.e., is not the same) but that would assume that we + * received all messages. It would fail if we just happened + * to see two ephemeris updates in a row with the same iod + * because we failed to receive all updates in between. + */ + ASSERT3U(prev->t0.gst, <, new->t0.gst); + + prev_eph_age = new->t0.gst - prev->t0.gst; + + /* calculate the discontinuity... */ + struct ecef prev_ecef; + struct ecef new_ecef; + struct ecef diff; + + /* ...at t0 for the new ephemeris */ + galileo_eph_ecef(prev, new->t0.gst, &prev_ecef); + galileo_eph_ecef(new, new->t0.gst, &new_ecef); + ecef_subtract(&diff, &new_ecef, &prev_ecef); + disco_t0 = ecef_magnitude(&diff); + + /* ...right now */ + galileo_eph_ecef(prev, state->time.gst, &prev_ecef); + galileo_eph_ecef(new, state->time.gst, &new_ecef); + ecef_subtract(&diff, &new_ecef, &prev_ecef); + disco_now = ecef_magnitude(&diff); + } + + printf("got %s eph for E%02u (prev %.1f hrs older): disco %f m @ t0, %f m now\n", + prev ? "updated" : "new", new->sv, prev_eph_age / 3600, + disco_t0, disco_now); + galileo_print_eph(new); +} + +static void galileo_time(struct galileo_state *state, + const unsigned int tx_sv, + const struct galileo_state_time *now, + const struct galileo_state_time *prev_sv_time) +{ + const time_t utc = now->gst + 935280000 - 13; + struct tm tm; + + ASSERT3U(prev_sv_time->gst, <, now->gst); + + gmtime_r(&utc, &tm); + + printf("E%02u GST %u (WN %u TOW %u): %04u-%02u-%02u %02u:%02u:%02u " + "(prev %svalid %u, missed %u)\n", + tx_sv, now->gst, now->wn, now->tow, + tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, + tm.tm_min, tm.tm_sec, + prev_sv_time->valid ? "" : "not ", prev_sv_time->gst, + (now->gst - prev_sv_time->gst) / 30 - 1); +} + +static const struct galileo_state_ops galileo_ops = { + .eph_update = galileo_update_eph, + .time = galileo_time, +}; + +void process_ubx_message(const struct ubx_header *header, + const uint8_t *raw, size_t len, + uint64_t tick) +{ + static struct galileo_state galileo_state; + static bool initialized; + struct ubx_rxm_sfrbx msg; + struct info info; + uint32_t *words; + int i; + + if ((header->class != UBX_CLASS_RXM) || (header->id != 0x13)) + return; + + /* initialize galileo gnss state as needed */ + if (!initialized) { + galileo_state_init(&galileo_state, &galileo_ops); + initialized = true; + } + + /* + * Parse UBX-RXM-SFRBX + */ + + memcpy(&msg, raw, sizeof(struct ubx_rxm_sfrbx)); + + /* sanity check */ + ASSERT3U(len, ==, sizeof(struct ubx_rxm_sfrbx) + + sizeof(uint32_t) * msg.num_words); + + /* allocate temp buffer */ + words = alloca(msg.num_words * sizeof(uint32_t)); + + /* copy into temp buffer */ + memcpy(words, &raw[offsetof(struct ubx_rxm_sfrbx, words)], + msg.num_words * sizeof(uint32_t)); + + /* byte order words */ + for (i = 0; i < msg.num_words; i++) + words[i] = le32_to_cpu(words[i]); + + /* parse */ + if (!msg2info(&msg, words, &info)) { + fprintf(stderr, "Failed to parse ubx message for gnss %u sv %u\n", + msg.gnssid, msg.svid); + return; + } + + /* + * Update state with parsed info + */ + + if ((info.gnssid == GNSSID_GALILEO) && + !galileo_state_apply_page(&galileo_state, info.svid, &info.galileo)) + printf("Galileo page application failure.\n"); +}