From 0abb84b9a4599f2d0d6c0cc3dbe8d8ac211b4136 Mon Sep 17 00:00:00 2001 From: Carles Fernandez Date: Sat, 10 Nov 2018 19:16:13 +0100 Subject: [PATCH] Read Galileo almanac data from XML file in the format provided at https://www.gsc-europa.eu/system-status/almanac-data Requires PugiXML, feature only available if the library is found on the system at building time The format detection is transparent to the user. Just configure GNSS-SDR.AGNSS_gal_almanac_xml=./2018-11-06.xml --- CMakeLists.txt | 5 ++ README.md | 10 ++-- cmake/Modules/FindPugiXML.cmake | 67 +++++++++++++++++++++++++++ src/core/libs/CMakeLists.txt | 11 ++++- src/core/libs/gnss_sdr_supl_client.cc | 61 +++++++++++++++++++++++- src/core/libs/gnss_sdr_supl_client.h | 1 + src/core/receiver/control_thread.cc | 7 +-- 7 files changed, 152 insertions(+), 10 deletions(-) create mode 100644 cmake/Modules/FindPugiXML.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index 62f3cec71..15432d2d3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1216,6 +1216,11 @@ if(NOT MATIO_FOUND OR MATIO_VERSION_STRING VERSION_LESS ${GNSSSDR_MATIO_MIN_VERS endif(NOT MATIO_FOUND OR MATIO_VERSION_STRING VERSION_LESS ${GNSSSDR_MATIO_MIN_VERSION}) +################################################################################ +# PugiXML - https://pugixml.org/ +################################################################################ +find_package(PugiXML QUIET) + ################################################################################ # USRP Hardware Driver (UHD) - OPTIONAL diff --git a/README.md b/README.md index 6624d618d..c632b9ab2 100644 --- a/README.md +++ b/README.md @@ -64,7 +64,8 @@ $ sudo apt-get install build-essential cmake git libboost-dev libboost-date-time libboost-system-dev libboost-filesystem-dev libboost-thread-dev libboost-chrono-dev \ libboost-serialization-dev liblog4cpp5-dev libuhd-dev gnuradio-dev gr-osmosdr \ libblas-dev liblapack-dev libarmadillo-dev libgflags-dev libgoogle-glog-dev \ - libgnutls-openssl-dev libpcap-dev python-mako python-six libmatio-dev libgtest-dev + libgnutls-openssl-dev libpcap-dev python-mako python-six libmatio-dev libpugixml-dev \ + libgtest-dev ~~~~~~ Please note that the required files from `libgtest-dev` were moved to `googletest` in Debian 9 "stretch" and Ubuntu 18.04 "bionic", and moved back again to `libgtest-dev` in Debian 10 "buster" and Ubuntu 18.10 "cosmic". @@ -85,7 +86,7 @@ $ sudo yum install make automake gcc gcc-c++ kernel-devel cmake git boost-devel boost-date-time boost-system boost-filesystem boost-thread boost-chrono \ boost-serialization log4cpp-devel gnuradio-devel gr-osmosdr-devel \ blas-devel lapack-devel matio-devel armadillo-devel gflags-devel \ - glog-devel openssl-devel libpcap-devel python-mako python-six + glog-devel openssl-devel libpcap-devel python-mako python-six pugixml-devel ~~~~~~ Once you have installed these packages, you can jump directly to [download the source code and build GNSS-SDR](#download-and-build-linux). @@ -102,7 +103,7 @@ $ sudo yum install make automake gcc gcc-c++ kernel-devel libtool \ hdf5-devel cmake git boost-devel boost-date-time boost-system \ boost-filesystem boost-thread boost-chrono boost-serialization \ log4cpp-devel gnuradio-devel gr-osmosdr-devel blas-devel lapack-devel \ - armadillo-devel openssl-devel libpcap-devel python-mako python-six + armadillo-devel openssl-devel libpcap-devel python-mako python-six pugixml-devel ~~~~~~ Once you have installed these packages, you can jump directly to [download the source code and build GNSS-SDR](#download-and-build-linux). @@ -113,7 +114,7 @@ If you are using Arch Linux (with base-devel group installed): ~~~~~~ $ pacman -S cmake git boost boost-libs log4cpp libvolk gnuradio gnuradio-osmosdr \ - blas lapack gflags google-glog openssl python2-mako python2-six \ + blas lapack gflags google-glog openssl pugixml python2-mako python2-six \ libmatio libpcap gtest ~~~~~~ @@ -547,6 +548,7 @@ $ sudo port install google-glog +gflags $ sudo port install py27-mako $ sudo port install py27-six $ sudo port install matio +$ sudo port install pugixml ~~~~~~ You also might need to activate a Python installation. The list of installed versions can be retrieved with: diff --git a/cmake/Modules/FindPugiXML.cmake b/cmake/Modules/FindPugiXML.cmake new file mode 100644 index 000000000..f60b441c8 --- /dev/null +++ b/cmake/Modules/FindPugiXML.cmake @@ -0,0 +1,67 @@ +# Copyright (C) 2011-2018 (see AUTHORS file for a list of contributors) +# +# This file is part of GNSS-SDR. +# +# GNSS-SDR is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# GNSS-SDR is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNSS-SDR. If not, see . + + +# Find the pugixml XML parsing library. +# +# Sets the usual variables expected for find_package scripts: +# +# PUGIXML_INCLUDE_DIR - header location +# PUGIXML_LIBRARIES - library to link against +# PUGIXML_FOUND - true if pugixml was found. + + +find_path (PUGIXML_INCLUDE_DIR + NAMES pugixml.hpp + PATHS ${PUGIXML_HOME}/include + /usr/include + /usr/local/include + /opt/local/include) + +find_library (PUGIXML_LIBRARY + NAMES pugixml + PATHS ${PUGIXML_HOME}/lib + /usr/lib/x86_64-linux-gnu + /usr/lib/aarch64-linux-gnu + /usr/lib/arm-linux-gnueabi + /usr/lib/arm-linux-gnueabihf + /usr/lib/i386-linux-gnu + /usr/lib/mips-linux-gnu + /usr/lib/mips64el-linux-gnuabi64 + /usr/lib/mipsel-linux-gnu + /usr/lib/powerpc64le-linux-gnu + /usr/lib/s390x-linux-gnu + /usr/local/lib + /opt/local/lib + /usr/lib ) + +# Support the REQUIRED and QUIET arguments, and set PUGIXML_FOUND if found. +include (FindPackageHandleStandardArgs) +FIND_PACKAGE_HANDLE_STANDARD_ARGS (PugiXML DEFAULT_MSG PUGIXML_LIBRARY + PUGIXML_INCLUDE_DIR) + +if (PUGIXML_FOUND) + set (PUGIXML_LIBRARIES ${PUGIXML_LIBRARY}) + if (NOT PugiXML_FIND_QUIETLY) + message (STATUS "PugiXML include = ${PUGIXML_INCLUDE_DIR}") + message (STATUS "PugiXML library = ${PUGIXML_LIBRARY}") + endif (NOT PugiXML_FIND_QUIETLY) +else (PUGIXML_FOUND) + message (STATUS "PugiXML not found.") +endif(PUGIXML_FOUND) + +mark_as_advanced (PUGIXML_LIBRARY PUGIXML_INCLUDE_DIR) \ No newline at end of file diff --git a/src/core/libs/CMakeLists.txt b/src/core/libs/CMakeLists.txt index f8b7f7dc0..c901ea715 100644 --- a/src/core/libs/CMakeLists.txt +++ b/src/core/libs/CMakeLists.txt @@ -35,6 +35,14 @@ set(CORE_LIBS_HEADERS string_converter.h gnss_sdr_supl_client.h ) + +if(PugiXML_FOUND) + message(STATUS "PugiXML has been found. Reading of GSA Galileo almanac XML files enabled.") + add_definitions( -DPUGIXML_FOUND=1 ) +else(PugiXML_FOUND) + set(PUGIXML_INCLUDE_DIR "") + set(PUGIXML_LIBRARIES "") +endif(PugiXML_FOUND) include_directories( ${CMAKE_CURRENT_SOURCE_DIR} @@ -45,6 +53,7 @@ include_directories( ${GLOG_INCLUDE_DIRS} ${GFlags_INCLUDE_DIRS} ${Boost_INCLUDE_DIRS} + ${PUGIXML_INCLUDE_DIR} ) list(SORT CORE_LIBS_HEADERS) @@ -52,4 +61,4 @@ list(SORT CORE_LIBS_SOURCES) add_library(rx_core_lib ${CORE_LIBS_SOURCES} ${CORE_LIBS_HEADERS}) source_group(Headers FILES ${CORE_LIBS_HEADERS}) -target_link_libraries(rx_core_lib supl_library) +target_link_libraries(rx_core_lib supl_library ${PUGIXML_LIBRARIES}) diff --git a/src/core/libs/gnss_sdr_supl_client.cc b/src/core/libs/gnss_sdr_supl_client.cc index 7494d2f3f..30de44cdf 100644 --- a/src/core/libs/gnss_sdr_supl_client.cc +++ b/src/core/libs/gnss_sdr_supl_client.cc @@ -32,6 +32,9 @@ */ #include "gnss_sdr_supl_client.h" +#ifdef PUGIXML_FOUND +#include +#endif #include #include @@ -842,14 +845,68 @@ bool gnss_sdr_supl_client::load_gal_almanac_xml(const std::string file_name) boost::archive::xml_iarchive xml(ifs); gal_almanac_map.clear(); xml >> boost::serialization::make_nvp("GNSS-SDR_gal_almanac_map", this->gal_almanac_map); - LOG(INFO) << "Loaded Galileo almanac map data with " << this->gal_almanac_map.size() << " satellites"; } catch (std::exception& e) { - LOG(WARNING) << e.what() << "File: " << file_name; + // Maybe the file is from https://www.gsc-europa.eu/system-status/almanac-data ? + return this->read_gal_almanac_from_gsa(file_name); + } + LOG(INFO) << "Loaded Galileo almanac map data with " << this->gal_almanac_map.size() << " satellites"; + return true; +} + + +bool gnss_sdr_supl_client::read_gal_almanac_from_gsa(const std::string file_name) +{ +#ifdef PUGIXML_FOUND + pugi::xml_document doc; + pugi::xml_parse_result result = doc.load_file(file_name.c_str()); + if (!result) + { + LOG(WARNING) << "Error loading file " << file_name << ":" << result.description(); + return false; + } + for (pugi::xml_node almanac : doc.child("signalData") + .child("body") + .child("Almanacs") + .children("svAlmanac")) + { + Galileo_Almanac gal_alm; + try + { + uint32_t prn = static_cast(std::stoi(almanac.child_value("SVID"))); + gal_alm.i_satellite_PRN = prn; + gal_alm.i_Toa = std::stoi(almanac.child("almanac").child_value("t0a")); + gal_alm.i_WNa = std::stoi(almanac.child("almanac").child_value("wna")); + gal_alm.i_IODa = std::stoi(almanac.child("almanac").child_value("iod")); + gal_alm.d_Delta_i = std::stod(almanac.child("almanac").child_value("deltai")); + gal_alm.d_M_0 = std::stod(almanac.child("almanac").child_value("deltai")); + gal_alm.d_e_eccentricity = std::stod(almanac.child("almanac").child_value("ecc")); + gal_alm.d_Delta_sqrt_A = std::stod(almanac.child("almanac").child_value("aSqRoot")); + gal_alm.d_OMEGA0 = std::stod(almanac.child("almanac").child_value("omega0")); + gal_alm.d_OMEGA = std::stod(almanac.child("almanac").child_value("w")); + gal_alm.d_OMEGA_DOT = std::stod(almanac.child("almanac").child_value("omegaDot")); + gal_alm.d_A_f0 = std::stod(almanac.child("almanac").child_value("af0")); + gal_alm.d_A_f1 = std::stod(almanac.child("almanac").child_value("af1")); + gal_alm.E5b_HS = std::stoi(almanac.child("svINavSignalStatus").child_value("statusE5b")); + gal_alm.E1B_HS = std::stoi(almanac.child("svINavSignalStatus").child_value("statusE1B")); + gal_alm.E5a_HS = std::stoi(almanac.child("svFNavSignalStatus").child_value("statusE5a")); + + this->gal_almanac_map[static_cast(prn)] = gal_alm; + } + catch (const std::exception& e) + { + std::cerr << e.what() << std::endl; + } + } + if (this->gal_almanac_map.empty()) + { return false; } return true; +#else + return false; +#endif } diff --git a/src/core/libs/gnss_sdr_supl_client.h b/src/core/libs/gnss_sdr_supl_client.h index 52e4ed371..d20779d33 100644 --- a/src/core/libs/gnss_sdr_supl_client.h +++ b/src/core/libs/gnss_sdr_supl_client.h @@ -77,6 +77,7 @@ private: supl_ctx_t ctx; // assistance data supl_assist_t assist; + bool read_gal_almanac_from_gsa(const std::string file_name); public: // SUPL SERVER INFO diff --git a/src/core/receiver/control_thread.cc b/src/core/receiver/control_thread.cc index b21f68ff8..e4e6ce91d 100644 --- a/src/core/receiver/control_thread.cc +++ b/src/core/receiver/control_thread.cc @@ -241,8 +241,8 @@ bool ControlThread::read_assistance_from_XML() std::string cnav_utc_xml_filename = configuration_->property("GNSS-SDR.SUPL_cnav_utc_model_xml", cnav_utc_default_xml_filename); std::string eph_glo_xml_filename = configuration_->property("GNSS-SDR.SUPL_glo_ephemeris_xml", eph_glo_gnav_default_xml_filename); std::string glo_utc_xml_filename = configuration_->property("GNSS-SDR.SUPL_glo_utc_model_xml", glo_utc_default_xml_filename); - std::string gal_almanac_xml_filename = configuration_->property("GNSS-SDR.SUPL_gal_almanacl_xml", gal_almanac_default_xml_filename); - std::string gps_almanac_xml_filename = configuration_->property("GNSS-SDR.SUPL_gps_almanacl_xml", gps_almanac_default_xml_filename); + std::string gal_almanac_xml_filename = configuration_->property("GNSS-SDR.SUPL_gal_almanac_xml", gal_almanac_default_xml_filename); + std::string gps_almanac_xml_filename = configuration_->property("GNSS-SDR.SUPL_gps_almanac_xml", gps_almanac_default_xml_filename); if (configuration_->property("GNSS-SDR.AGNSS_XML_enabled", false) == true) { @@ -258,7 +258,8 @@ bool ControlThread::read_assistance_from_XML() cnav_utc_xml_filename = configuration_->property("GNSS-SDR.AGNSS_cnav_utc_model_xml", cnav_utc_default_xml_filename); eph_glo_xml_filename = configuration_->property("GNSS-SDR.AGNSS_glo_ephemeris_xml", eph_glo_gnav_default_xml_filename); glo_utc_xml_filename = configuration_->property("GNSS-SDR.AGNSS_glo_utc_model_xml", glo_utc_default_xml_filename); - gal_almanac_xml_filename = configuration_->property("GNSS-SDR.AGNSS_gal_almanacl_xml", gal_almanac_default_xml_filename); + gal_almanac_xml_filename = configuration_->property("GNSS-SDR.AGNSS_gal_almanac_xml", gal_almanac_default_xml_filename); + gps_almanac_xml_filename = configuration_->property("GNSS-SDR.AGNSS_gps_almanac_xml", gps_almanac_default_xml_filename); } std::cout << "Trying to read GNSS ephemeris from XML file(s)..." << std::endl;