1
0
mirror of https://github.com/gnss-sdr/gnss-sdr synced 2024-11-15 22:34:58 +00:00

Merge with next

This commit is contained in:
Javier Arribas 2023-03-06 22:54:19 +01:00
commit bf1a7e8c2c
57 changed files with 2782 additions and 1474 deletions

79
.github/workflows/gnss-sdr_archs.yml vendored Normal file
View File

@ -0,0 +1,79 @@
# SPDX-License-Identifier: GPL-3.0-or-later
# SPDX-FileCopyrightText: 2023 Carles Fernandez-Prades <carles.fernandez@cttc.es>
name: Run gnss-sdr in non-x86 archs
on:
push:
branches:
- "**-archs"
- main
workflow_dispatch:
jobs:
gnss-sdr-non-x86:
runs-on: ubuntu-latest
name: ${{ matrix.distro }} ${{ matrix.arch }} ${{ matrix.compiler.name }}
# Run steps on a matrix of archs.
strategy:
fail-fast: false
matrix:
include:
- arch: aarch64
distro: ubuntu22.04
compiler: { name: g++-12, cc: gcc-12, cxx: g++-12 }
- arch: aarch64
distro: ubuntu22.04
compiler: { name: clang-14, cc: clang-14, cxx: clang++-14 }
- arch: armv7
distro: ubuntu22.04
compiler: { name: g++-12, cc: gcc-12, cxx: g++-12 }
- arch: ppc64le
distro: ubuntu22.04
compiler: { name: g++-12, cc: gcc-12, cxx: g++-12 }
- arch: s390x
distro: ubuntu22.04
compiler: { name: g++-12, cc: gcc-12, cxx: g++-12 }
- arch: riscv64
distro: ubuntu22.04
compiler: { name: g++-12, cc: gcc-12, cxx: g++-12 }
steps:
- uses: actions/checkout@v3.1.0
- uses: uraimo/run-on-arch-action@v2.5.0
name: Test in non-x86 container
continue-on-error: ${{ contains(fromJson('["ppc64le", "s390x"]'), matrix.arch) }}
id: test
with:
arch: ${{ matrix.arch }}
distro: ${{ matrix.distro }}
githubToken: ${{ github.token }} # Not required, but speeds up builds
setup: |
mkdir -p "${PWD}/testing"
dockerRunArgs: |
--volume "${PWD}:/gnss-sdr"
env: |
CC: ${{ matrix.compiler.cc }}
CXX: ${{ matrix.compiler.cxx }}
shell: /bin/sh
install: |
apt-get update -q -y
apt-get install -q -y ${{ matrix.compiler.name }} git ninja-build cmake \
libboost-dev libboost-date-time-dev libboost-system-dev libboost-filesystem-dev \
libboost-thread-dev libboost-chrono-dev libboost-serialization-dev \
liblog4cpp5-dev gnuradio-dev gr-osmosdr libpugixml-dev libpcap-dev libblas-dev \
liblapack-dev libarmadillo-dev libgflags-dev libgoogle-glog-dev \
libgnutls-openssl-dev libmatio-dev googletest protobuf-compiler libprotobuf-dev \
python3-mako liborc-0.4-dev
run: |
git config --global --add safe.directory /gnss-sdr
cd /gnss-sdr
cd testing
mkdir install
cmake -DENABLE_SYSTEM_TESTING_EXTRA=ON -DCMAKE_INSTALL_PREFIX=/gnss-sdr/testing/install -DENABLE_INSTALL_TESTS=ON ..
echo "Build with $(nproc) thread(s)"
make -j$(nproc)
make install
cd install/bin
./position_test

View File

@ -9,6 +9,7 @@ on:
push: push:
paths-ignore: paths-ignore:
- "**/CITATION.cff" - "**/CITATION.cff"
workflow_dispatch:
jobs: jobs:
build-ubuntu: build-ubuntu:
@ -113,7 +114,7 @@ jobs:
ln -s $(brew --prefix llvm)/bin/clang-apply-replacements /usr/local/bin ln -s $(brew --prefix llvm)/bin/clang-apply-replacements /usr/local/bin
ln -s $(brew --prefix llvm)/bin/run-clang-tidy /usr/local/bin ln -s $(brew --prefix llvm)/bin/run-clang-tidy /usr/local/bin
- name: Prepare run - name: Prepare run
run: cd build && cmake .. && make volk_gnsssdr_module gtest-1.12.1 core_monitor core_libs pvt_libs run: cd build && cmake .. && make volk_gnsssdr_module gtest-1.13.0 core_monitor core_libs pvt_libs
- name: run clang-tidy - name: run clang-tidy
run: cd build && run-clang-tidy -fix run: cd build && run-clang-tidy -fix
- name: check - name: check

View File

@ -4,12 +4,14 @@ on:
push: push:
paths: paths:
- "src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/**" - "src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/**"
- "CMakeLists.txt"
pull_request: pull_request:
paths: paths:
- "src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/**" - "src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/**"
- "CMakeLists.txt"
workflow_dispatch: workflow_dispatch:
name: Build volk-gnssdr on Android NDK name: Build volk_gnsssdr on Android NDK
jobs: jobs:
build: build:
name: Build on Android NDK ${{ matrix.arch.name }} name: Build on Android NDK ${{ matrix.arch.name }}

View File

@ -0,0 +1,80 @@
# SPDX-License-Identifier: GPL-3.0-or-later
# SPDX-FileCopyrightText: 2023 Carles Fernandez-Prades <carles.fernandez@cttc.es>
name: Run volk_gnsssdr tests
on:
push:
paths:
- "src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/**"
- "CMakeLists.txt"
pull_request:
paths:
- "src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/**"
- "CMakeLists.txt"
workflow_dispatch:
jobs:
build-ubuntu-non-x86:
runs-on: ubuntu-latest
name: ${{ matrix.distro }} ${{ matrix.arch }} ${{ matrix.compiler.name }}
# Run steps on a matrix of archs.
strategy:
fail-fast: false
matrix:
include:
- arch: aarch64
distro: ubuntu22.04
compiler: { name: g++-12, cc: gcc-12, cxx: g++-12 }
- arch: aarch64
distro: ubuntu22.04
compiler: { name: clang-14, cc: clang-14, cxx: clang++-14 }
- arch: armv7
distro: ubuntu22.04
compiler: { name: g++-12, cc: gcc-12, cxx: g++-12 }
- arch: ppc64le
distro: ubuntu22.04
compiler: { name: g++-12, cc: gcc-12, cxx: g++-12 }
- arch: s390x
distro: ubuntu22.04
compiler: { name: g++-12, cc: gcc-12, cxx: g++-12 }
- arch: riscv64
distro: ubuntu22.04
compiler: { name: g++-12, cc: gcc-12, cxx: g++-12 }
steps:
- uses: actions/checkout@v3.1.0
- uses: uraimo/run-on-arch-action@v2.5.0
name: Build in non-x86 container
# continue-on-error: ${{ contains(fromJson('["ppc64le", "s390x"]'), matrix.arch) }}
id: build
with:
arch: ${{ matrix.arch }}
distro: ${{ matrix.distro }}
githubToken: ${{ github.token }} # Not required, but speeds up builds
setup: |
mkdir -p "${PWD}/testing"
dockerRunArgs: |
--volume "${PWD}:/volk_gnsssdr"
env: |
CC: ${{ matrix.compiler.cc }}
CXX: ${{ matrix.compiler.cxx }}
shell: /bin/sh
install: |
apt-get update -q -y
apt-get install -q -y git cmake python3-mako liborc-dev ${{ matrix.compiler.name }}
run: |
git config --global --add safe.directory /volk_gnsssdr
cd /volk_gnsssdr
cd testing
cmake ../src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/
echo "Build with $(nproc) thread(s)"
make -j$(nproc)
./cpu_features/list_cpu_features
./apps/volk_gnsssdr-config-info --alignment
./apps/volk_gnsssdr-config-info --avail-machines
./apps/volk_gnsssdr-config-info --all-machines
./apps/volk_gnsssdr-config-info --malloc
./apps/volk_gnsssdr-config-info --cc
ctest -V

View File

@ -48,7 +48,7 @@ option(ENABLE_FLEXIBAND "Enable the use of the signal source adater for the Tele
option(ENABLE_ARRAY "Enable the use of CTTC's antenna array front-end as signal source (experimental)" OFF) option(ENABLE_ARRAY "Enable the use of CTTC's antenna array front-end as signal source (experimental)" OFF)
option(ENABLE_ZMQ "Enable GNU Radio ZeroMQ Messaging, requires gr-zeromq" OFF) option(ENABLE_ZMQ "Enable GNU Radio ZeroMQ Messaging, requires gr-zeromq" ON)
# Performance analysis tools # Performance analysis tools
option(ENABLE_GPERFTOOLS "Enable linking to Gperftools libraries (tcmalloc and profiler)" OFF) option(ENABLE_GPERFTOOLS "Enable linking to Gperftools libraries (tcmalloc and profiler)" OFF)
@ -68,8 +68,6 @@ option(ENABLE_CUDA "Enable building of processing blocks implemented with CUDA (
option(ENABLE_FPGA "Enable building of processing blocks implementing FPGA offloading" OFF) option(ENABLE_FPGA "Enable building of processing blocks implementing FPGA offloading" OFF)
# Building and packaging options # Building and packaging options
option(ENABLE_GENERIC_ARCH "Builds a portable binary" OFF)
option(ENABLE_PACKAGING "Enable software packaging" OFF) option(ENABLE_PACKAGING "Enable software packaging" OFF)
option(ENABLE_OWN_GLOG "Download glog and link it to gflags" OFF) option(ENABLE_OWN_GLOG "Download glog and link it to gflags" OFF)
@ -85,7 +83,6 @@ option(ENABLE_STRIP "Create stripped binaries without debugging symbols (in Rele
option(Boost_USE_STATIC_LIBS "Use Boost static libs" OFF) option(Boost_USE_STATIC_LIBS "Use Boost static libs" OFF)
if(ENABLE_PACKAGING) if(ENABLE_PACKAGING)
set(ENABLE_GENERIC_ARCH ON)
set(ENABLE_ARMA_NO_DEBUG ON) set(ENABLE_ARMA_NO_DEBUG ON)
set(CMAKE_VERBOSE_MAKEFILE ON) set(CMAKE_VERBOSE_MAKEFILE ON)
set(ENABLE_STRIP OFF) set(ENABLE_STRIP OFF)
@ -344,7 +341,7 @@ if((CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND CMAKE_CXX_COMPILER_VERSION VERSION_
CMAKE_VERSION VERSION_LESS 3.5) CMAKE_VERSION VERSION_LESS 3.5)
set(GNSSSDR_GTEST_LOCAL_VERSION "1.10.x") set(GNSSSDR_GTEST_LOCAL_VERSION "1.10.x")
else() else()
set(GNSSSDR_GTEST_LOCAL_VERSION "1.12.1") set(GNSSSDR_GTEST_LOCAL_VERSION "1.13.0")
endif() endif()
set(GNSSSDR_GNSS_SIM_LOCAL_VERSION "master") set(GNSSSDR_GNSS_SIM_LOCAL_VERSION "master")
if(CMAKE_VERSION VERSION_GREATER 3.17.0) if(CMAKE_VERSION VERSION_GREATER 3.17.0)
@ -442,7 +439,6 @@ endif()
################################################################################ ################################################################################
# Set minimal C and C++ standards # Set minimal C and C++ standards
################################################################################ ################################################################################
@ -501,23 +497,19 @@ endif()
################################################################################ ################################################################################
# Check if the compiler defines the architecture as ARM # Check if the compiler defines the architecture as ARM
################################################################################ ################################################################################
if(CMAKE_SYSTEM_PROCESSOR MATCHES "(^arm)|(^aarch64)")
set(IS_ARM TRUE)
endif()
if(NOT (${CMAKE_SYSTEM_NAME} MATCHES "Darwin")) if(NOT (${CMAKE_SYSTEM_NAME} MATCHES "Darwin"))
if(CMAKE_CROSSCOMPILING) if(CMAKE_CROSSCOMPILING)
set(IS_ARM TRUE)
if(NOT CMAKE_NO_SYSTEM_FROM_IMPORTED) if(NOT CMAKE_NO_SYSTEM_FROM_IMPORTED)
set(CMAKE_NO_SYSTEM_FROM_IMPORTED TRUE) set(CMAKE_NO_SYSTEM_FROM_IMPORTED TRUE)
endif() endif()
else()
if(NOT IS_ARM)
include(TestForARM)
endif()
endif()
else()
if(CMAKE_SYSTEM_PROCESSOR MATCHES "(^aarch64)|(arm64)")
set(IS_ARM TRUE)
endif() endif()
endif() endif()
################################################################################ ################################################################################
# pkg-config - Helper tool used when compiling applications and libraries. # pkg-config - Helper tool used when compiling applications and libraries.
################################################################################ ################################################################################
@ -526,6 +518,7 @@ set(FPHSA_NAME_MISMATCHED ON)
find_package(PkgConfig) find_package(PkgConfig)
################################################################################ ################################################################################
# Find the POSIX thread (pthread) libraries # Find the POSIX thread (pthread) libraries
################################################################################ ################################################################################
@ -620,8 +613,17 @@ if(ENABLE_UHD)
endif() endif()
endif() endif()
find_package(ZEROMQ)
set_package_properties(ZEROMQ PROPERTIES
PURPOSE "Used by the ZMQ_Signal_Source."
TYPE OPTIONAL
)
if(ENABLE_ZMQ) if(ENABLE_ZMQ)
if(NOT ZEROMQ_FOUND)
set(ENABLE_ZMQ OFF)
else()
list(APPEND GR_REQUIRED_COMPONENTS ZEROMQ) list(APPEND GR_REQUIRED_COMPONENTS ZEROMQ)
endif()
endif() endif()
find_package(GNURADIO) find_package(GNURADIO)
@ -1193,7 +1195,7 @@ if(NOT VOLKGNSSSDR_FOUND)
include(GNUInstallDirs) include(GNUInstallDirs)
set(SUPPORTED_CPU_FEATURES_ARCH FALSE) set(SUPPORTED_CPU_FEATURES_ARCH FALSE)
if(CMAKE_SYSTEM_PROCESSOR MATCHES if(CMAKE_SYSTEM_PROCESSOR MATCHES
"(^mips)|(^arm)|(^aarch64)|(x86_64)|(AMD64|amd64)|(^i.86$)|(^powerpc)|(^ppc)|(^s390x)") "(^mips)|(^arm)|(^aarch64)|(x86_64)|(AMD64|amd64)|(^i.86$)|(^powerpc)|(^ppc)|(^s390x)|^riscv")
set(SUPPORTED_CPU_FEATURES_ARCH TRUE) set(SUPPORTED_CPU_FEATURES_ARCH TRUE)
endif() endif()
if(${CMAKE_INSTALL_LIBDIR} MATCHES lib64) if(${CMAKE_INSTALL_LIBDIR} MATCHES lib64)
@ -1232,11 +1234,14 @@ if(NOT VOLKGNSSSDR_FOUND)
set_package_properties(CPUFEATURES PROPERTIES set_package_properties(CPUFEATURES PROPERTIES
DESCRIPTION "A cross platform C99 library to get CPU features at runtime (version: ${CPUFEATURES_VERSION})" DESCRIPTION "A cross platform C99 library to get CPU features at runtime (version: ${CPUFEATURES_VERSION})"
) )
if((CMAKE_SYSTEM_PROCESSOR MATCHES "(^s390x)|^riscv") AND (CPUFEATURES_VERSION VERSION_LESS "0.8.0")) # detect cpu_features without s390x / riscv support
set(ENABLE_CPUFEATURES OFF)
endif()
else() else()
set_package_properties(CPUFEATURES PROPERTIES set_package_properties(CPUFEATURES PROPERTIES
DESCRIPTION "A cross platform C99 library to get CPU features at runtime" DESCRIPTION "A cross platform C99 library to get CPU features at runtime"
) )
if(VOLK_VERSION AND VOLK_VERSION VERSION_GREATER "2.3" AND VOLK_VERSION VERSION_LESS "2.5.2") # detect "hidden" cpu_features 0.6.0 if(DEFINED VOLK_VERSION AND VOLK_VERSION VERSION_GREATER "2.3") # avoid clash with volk's cpufeatures.
set(ENABLE_CPUFEATURES OFF) set(ENABLE_CPUFEATURES OFF)
else() else()
set_package_properties(CPUFEATURES PROPERTIES set_package_properties(CPUFEATURES PROPERTIES
@ -1805,6 +1810,9 @@ else()
if(NOT BLA_VENDOR) if(NOT BLA_VENDOR)
set(BLA_VENDOR "Generic") set(BLA_VENDOR "Generic")
endif() endif()
if(NOT CMAKE_CROSSCOMPILING AND NOT DEFINED BLA_PREFER_PKGCONFIG)
set(BLA_PREFER_PKGCONFIG ON) # Required by riscv64 arch
endif()
find_package(BLAS) find_package(BLAS)
set_package_properties(BLAS PROPERTIES set_package_properties(BLAS PROPERTIES
URL "https://www.netlib.org/blas/" URL "https://www.netlib.org/blas/"
@ -2903,9 +2911,9 @@ if(ENABLE_OPENCL)
message(STATUS " You can disable OpenCL use by doing 'cmake -DENABLE_OPENCL=OFF ..'") message(STATUS " You can disable OpenCL use by doing 'cmake -DENABLE_OPENCL=OFF ..'")
endif() endif()
endif() endif()
if(ENABLE_GENERIC_ARCH) if(ENABLE_PACKAGING)
set(ENABLE_OPENCL OFF) set(ENABLE_OPENCL OFF)
message(STATUS "ENABLE_GENERIC_ARCH is set to ON so the use of OpenCL has been disabled.") message(STATUS "ENABLE_PACKAGING is set to ON so the use of OpenCL has been disabled.")
endif() endif()
if(NOT OPENCL_FOUND) if(NOT OPENCL_FOUND)
message(STATUS "Processing blocks using OpenCL will not be built.") message(STATUS "Processing blocks using OpenCL will not be built.")
@ -3282,36 +3290,6 @@ if(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
endif() endif()
endif() endif()
# Processor-architecture related flags
# See https://gcc.gnu.org/onlinedocs/gcc/x86-Options.html
if((CMAKE_CXX_COMPILER_ID STREQUAL "GNU") AND NOT WIN32)
if(NOT ENABLE_GENERIC_ARCH)
if(IS_ARM)
# ARM-specific options
# See https://gcc.gnu.org/onlinedocs/gcc/ARM-Options.html
if(NOT CMAKE_CROSSCOMPILING AND NOT CMAKE_TOOLCHAIN_FILE)
add_compile_options(-mtune=native)
endif()
else()
if(NOT ENABLE_CUDA)
add_compile_options(-march=native)
endif()
endif()
endif()
endif()
if(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
if(NOT ENABLE_GENERIC_ARCH)
if(IS_ARM)
# ARM-specific options
if(NOT CMAKE_CROSSCOMPILING AND NOT CMAKE_TOOLCHAIN_FILE)
add_compile_options(-mcpu=native)
endif()
else()
add_compile_options(-march=native)
endif()
endif()
endif()
################################################################################ ################################################################################
@ -3384,7 +3362,6 @@ add_feature_info(ENABLE_OPENCL ENABLE_OPENCL "Enables GPS_L1_CA_PCPS_OpenCl_Acqu
add_feature_info(ENABLE_CUDA ENABLE_CUDA "Enables GPS_L1_CA_DLL_PLL_Tracking_GPU (experimental). Requires CUDA.") add_feature_info(ENABLE_CUDA ENABLE_CUDA "Enables GPS_L1_CA_DLL_PLL_Tracking_GPU (experimental). Requires CUDA.")
add_feature_info(ENABLE_FPGA ENABLE_FPGA "Enables building of processing blocks for FPGA offloading.") add_feature_info(ENABLE_FPGA ENABLE_FPGA "Enables building of processing blocks for FPGA offloading.")
add_feature_info(ENABLE_ARMA_NO_DEBUG ENABLE_ARMA_NO_DEBUG "Enables passing the ARMA_NO_DEBUG macro to Armadillo, hence disabling bound checking.") add_feature_info(ENABLE_ARMA_NO_DEBUG ENABLE_ARMA_NO_DEBUG "Enables passing the ARMA_NO_DEBUG macro to Armadillo, hence disabling bound checking.")
add_feature_info(ENABLE_GENERIC_ARCH ENABLE_GENERIC_ARCH "When disabled, flags such as '-march=native' are passed to the compiler.")
add_feature_info(ENABLE_PACKAGING ENABLE_PACKAGING "Enables software packaging.") add_feature_info(ENABLE_PACKAGING ENABLE_PACKAGING "Enables software packaging.")
add_feature_info(ENABLE_OWN_GLOG ENABLE_OWN_GLOG "Forces the downloading and building of Google glog.") add_feature_info(ENABLE_OWN_GLOG ENABLE_OWN_GLOG "Forces the downloading and building of Google glog.")
add_feature_info(ENABLE_OWN_ARMADILLO ENABLE_OWN_ARMADILLO "Forces the downloading and building of Armadillo.") add_feature_info(ENABLE_OWN_ARMADILLO ENABLE_OWN_ARMADILLO "Forces the downloading and building of Armadillo.")

View File

@ -64,11 +64,12 @@ information about this open-source, software-defined GNSS receiver.
1. [GNU/Linux](#gnulinux) 1. [GNU/Linux](#gnulinux)
1. [Alternative 1: Install dependencies using software packages](#alternative-1-install-dependencies-using-software-packages) 1. [Alternative 1: Install dependencies using software packages](#alternative-1-install-dependencies-using-software-packages)
1. [Debian / Ubuntu](#debian--ubuntu) 1. [Debian / Ubuntu](#debian--ubuntu)
2. [Arch Linux](#arch-linux) 2. [AlmaLinux](#almalinux)
3. [CentOS](#centos) 3. [Arch Linux](#arch-linux)
4. [Fedora](#fedora) 4. [CentOS](#centos)
5. [openSUSE](#opensuse) 5. [Fedora](#fedora)
6. [Rocky Linux](#rocky-linux) 6. [openSUSE](#opensuse)
7. [Rocky Linux](#rocky-linux)
2. [Alternative 2: Install dependencies using PyBOMBS](#alternative-2-install-dependencies-using-pybombs) 2. [Alternative 2: Install dependencies using PyBOMBS](#alternative-2-install-dependencies-using-pybombs)
3. [Manual installation of other required dependencies](#manual-installation-of-other-required-dependencies) 3. [Manual installation of other required dependencies](#manual-installation-of-other-required-dependencies)
1. [Install Armadillo, a C++ linear algebra library](#install-armadillo-a-c-linear-algebra-library) 1. [Install Armadillo, a C++ linear algebra library](#install-armadillo-a-c-linear-algebra-library)
@ -85,7 +86,6 @@ information about this open-source, software-defined GNSS receiver.
2. [Build FMCOMMS2 based SDR Hardware support (OPTIONAL)](#build-fmcomms2-based-sdr-hardware-support-optional) 2. [Build FMCOMMS2 based SDR Hardware support (OPTIONAL)](#build-fmcomms2-based-sdr-hardware-support-optional)
3. [Build OpenCL support (OPTIONAL)](#build-opencl-support-optional) 3. [Build OpenCL support (OPTIONAL)](#build-opencl-support-optional)
4. [Build CUDA support (OPTIONAL)](#build-cuda-support-optional) 4. [Build CUDA support (OPTIONAL)](#build-cuda-support-optional)
5. [Build a portable binary](#build-a-portable-binary)
2. [macOS](#macos) 2. [macOS](#macos)
1. [Macports](#macports) 1. [Macports](#macports)
2. [Homebrew](#homebrew) 2. [Homebrew](#homebrew)
@ -142,6 +142,7 @@ This section describes how to set up the compilation environment in GNU/Linux or
Motorola (now Freescale), and Apple. Motorola (now Freescale), and Apple.
- ppc64: 64-bit big-endian PowerPC architecture. - ppc64: 64-bit big-endian PowerPC architecture.
- ppc64el: 64-bit little-endian PowerPC architecture. - ppc64el: 64-bit little-endian PowerPC architecture.
- riscv64: 64-bit RISC-V open standard instruction set architecture.
- s390x: IBM System z architecture for mainframe computers. - s390x: IBM System z architecture for mainframe computers.
Older distribution releases might work as well, but you will need GCC 4.7 or Older distribution releases might work as well, but you will need GCC 4.7 or
@ -201,6 +202,26 @@ need `python-six`.
Once you have installed these packages, you can jump directly to Once you have installed these packages, you can jump directly to
[download the source code and build GNSS-SDR](#clone-gnss-sdrs-git-repository). [download the source code and build GNSS-SDR](#clone-gnss-sdrs-git-repository).
#### AlmaLinux
If you are using AlmaLinux:
```
# dnf update -y
# dnf install -y 'dnf-command(config-manager)'
# dnf config-manager --set-enabled powertools
# dnf install -y epel-release
# dnf install -y make gcc gcc-c++ kernel-devel cmake git boost-devel \
boost-date-time boost-system boost-thread boost-chrono \
boost-serialization log4cpp-devel gmp-devel uhd-devel gnuradio-devel \
pugixml-devel matio-devel protobuf-devel glog-devel libpcap-devel \
blas-devel lapack-devel armadillo-devel openssl-devel python3-mako \
libarchive
```
Once you have installed these packages, you can jump directly to
[download the source code and build GNSS-SDR](#clone-gnss-sdrs-git-repository).
#### Arch Linux #### Arch Linux
If you are using Arch Linux: If you are using Arch Linux:
@ -496,8 +517,8 @@ $ sudo ldconfig
#### Download [GoogleTest](https://github.com/google/googletest "Googletest Homepage") #### Download [GoogleTest](https://github.com/google/googletest "Googletest Homepage")
``` ```
$ wget https://github.com/google/googletest/archive/release-1.12.1.zip $ wget https://github.com/google/googletest/archive/refs/tags/v1.13.0.zip
$ unzip release-1.12.1.zip $ unzip v1.13.0.zip
``` ```
Please **DO NOT build or install** Google Test. Every user needs to compile Please **DO NOT build or install** Google Test. Every user needs to compile
@ -521,10 +542,10 @@ downloaded resides. Just type in your terminal (or add it to your
`$HOME/.bashrc` file for a permanent solution) the following line: `$HOME/.bashrc` file for a permanent solution) the following line:
``` ```
export GTEST_DIR=/home/username/googletest-release-1.12.1 export GTEST_DIR=/home/username/googletest-1.13.0
``` ```
changing `/home/username/googletest-release-1.12.1` by the actual path where you changing `/home/username/googletest-1.13.0` by the actual path where you
unpacked Google Test. If the CMake script does not find that folder, or the unpacked Google Test. If the CMake script does not find that folder, or the
environment variable is not defined, or the source code is not installed by a environment variable is not defined, or the source code is not installed by a
package, then it will download a fresh copy of the Google Test source code and package, then it will download a fresh copy of the Google Test source code and
@ -790,26 +811,6 @@ $ sudo make install
Of course, you will also need a GPU that Of course, you will also need a GPU that
[supports CUDA](https://developer.nvidia.com/cuda-gpus "CUDA GPUs"). [supports CUDA](https://developer.nvidia.com/cuda-gpus "CUDA GPUs").
#### Build a portable binary
In order to build an executable that not depends on the specific SIMD
instruction set that is present in the processor of the compiling machine, so
other users can execute it in other machines without those particular sets, use:
```
$ cmake -DENABLE_GENERIC_ARCH=ON ..
$ make
$ sudo make install
```
Using this option, all SIMD instructions are exclusively accessed via VOLK,
which automatically includes versions of each function for different SIMD
instruction sets, then detects at runtime which to use, or if there are none,
substitutes a generic, non-SIMD implementation.
More details can be found in our tutorial about
[GNSS-SDR configuration options at building time](https://gnss-sdr.org/docs/tutorials/using-git/ "Configuration options at building time").
## macOS ## macOS
GNSS-SDR can be built on macOS (or the former Mac OS X), starting from 10.9 GNSS-SDR can be built on macOS (or the former Mac OS X), starting from 10.9

View File

@ -20,7 +20,7 @@ if(DEFINED ENV{GFORTRAN_ROOT})
) )
endif() endif()
set(GCC_MAJOR_SERIES 12 11 10 9 8 7 6 5) set(GCC_MAJOR_SERIES 13 12 11 10 9 8 7 6 5)
set(GCC4_SERIES 4.9.1 4.9 4.8.3 4.8.1 4.7.2 4.7 4.8.2 4.8 4.7 4.6 4.5 4.4.4 4.4) set(GCC4_SERIES 4.9.1 4.9 4.8.3 4.8.1 4.7.2 4.7 4.8.2 4.8 4.7 4.6 4.5 4.4.4 4.4)
set(GCC_SERIES ${GCC_MAJOR_SERIES} ${GCC4_SERIES}) set(GCC_SERIES ${GCC_MAJOR_SERIES} ${GCC4_SERIES})

View File

@ -0,0 +1,82 @@
# GNSS-SDR is a Global Navigation Satellite System software-defined receiver.
# This file is part of GNSS-SDR.
#
# SPDX-FileCopyrightText: 2023 C. Fernandez-Prades cfernandez(at)cttc.es
# SPDX-License-Identifier: BSD-3-Clause
#
# Provides the following imported target:
# ZeroMQ::ZeroMQ
#
if(NOT COMMAND feature_summary)
include(FeatureSummary)
endif()
if(NOT PKG_CONFIG_FOUND)
include(FindPkgConfig)
endif()
find_package(PkgConfig)
pkg_check_modules(PC_ZEROMQ "libzmq")
find_path(ZEROMQ_INCLUDE_DIRS
NAMES zmq.hpp
HINTS ${PC_ZEROMQ_INCLUDE_DIR} ${CMAKE_INSTALL_PREFIX}/include
PATHS /usr/local/include /usr/include /opt/local/include
)
find_library(ZEROMQ_LIBRARIES
NAMES zmq libzmq.so.5 ${ZEROMQ_LIBRARY_NAME}
HINTS ${PC_ZEROMQ_LIBDIR} ${CMAKE_INSTALL_PREFIX}/lib ${CMAKE_INSTALL_PREFIX}/lib64
PATHS /usr/lib
/usr/lib64
/usr/lib/alpha-linux-gnu
/usr/lib/x86_64-linux-gnu
/usr/lib/aarch64-linux-gnu
/usr/lib/arm-linux-gnueabi
/usr/lib/arm-linux-gnueabihf
/usr/lib/hppa-linux-gnu
/usr/lib/i386-linux-gnu
/usr/lib/m68k-linux-gnu
/usr/lib/mips-linux-gnu
/usr/lib/mips64el-linux-gnuabi64
/usr/lib/mipsel-linux-gnu
/usr/lib/powerpc-linux-gnuspe
/usr/lib/powerpc64-linux-gnu
/usr/lib/powerpc64le-linux-gnu
/usr/lib/riscv64-linux-gnu
/usr/lib/s390x-linux-gnu
/usr/lib/sh4-linux-gnu
/usr/lib/sparc64-linux-gnu
/usr/lib/x86_64-linux-gnux32
/usr/lib/x86_64-kfreebsd-gnu
/usr/lib/i386-kfreebsd-gnu
/usr/local/lib
/usr/local/lib64
/opt/local/lib
)
include(FindPackageHandleStandardArgs)
# This is just to detect presence, include files not required
find_package_handle_standard_args(ZEROMQ DEFAULT_MSG ZEROMQ_LIBRARIES)
mark_as_advanced(ZEROMQ_LIBRARIES ZEROMQ_INCLUDE_DIRS)
set_package_properties(ZEROMQ PROPERTIES URL "https://zeromq.org/")
if(PC_ZEROMQ_VERSION)
set_package_properties(ZEROMQ PROPERTIES
DESCRIPTION "An open-source universal messaging library (found: v${PC_ZEROMQ_VERSION})"
)
else()
set_package_properties(ZEROMQ PROPERTIES
DESCRIPTION "An open-source universal messaging library"
)
endif()
if(ZEROMQ_FOUND AND ZEROMQ_INCLUDE_DIRS AND NOT TARGET ZeroMQ::ZeroMQ)
add_library(ZeroMQ::ZeroMQ INTERFACE IMPORTED)
set_target_properties(ZeroMQ::ZeroMQ PROPERTIES
INTERFACE_INCLUDE_DIRECTORIES "${ZEROMQ_INCLUDE_DIRS}"
INTERFACE_LINK_LIBRARIES "${ZEROMQ_LIBRARIES}"
)
endif()

View File

@ -12,13 +12,22 @@
# - cmd an additional command to run # - cmd an additional command to run
# - have the result variable to set # - have the result variable to set
######################################################################## ########################################################################
macro(GNSSSDR_PYTHON_CHECK_MODULE_RAW desc python_code have) macro(GNSSSDR_PYTHON_CHECK_MODULE desc mod cmd have)
message(STATUS "Python checking for ${desc}")
execute_process( execute_process(
COMMAND ${PYTHON_EXECUTABLE} -c "${python_code}" COMMAND ${PYTHON_EXECUTABLE} -c "
#########################################
try: import ${mod}
except:
try: ${mod}
except: exit(-1)
try: assert ${cmd}
except: exit(-1)
#########################################"
OUTPUT_QUIET ERROR_QUIET OUTPUT_QUIET ERROR_QUIET
RESULT_VARIABLE return_code RESULT_VARIABLE ${have}
) )
if(return_code EQUAL 0) if(${have} EQUAL 0)
message(STATUS "Python checking for ${desc} - found") message(STATUS "Python checking for ${desc} - found")
set(${have} TRUE) set(${have} TRUE)
else() else()
@ -27,19 +36,6 @@ macro(GNSSSDR_PYTHON_CHECK_MODULE_RAW desc python_code have)
endif() endif()
endmacro() endmacro()
macro(GNSSSDR_PYTHON_CHECK_MODULE desc mod cmd have)
gnsssdr_python_check_module_raw(
"${desc}" "
#########################################
try:
import ${mod}
assert ${cmd}
except (ImportError, AssertionError): exit(-1)
except: pass
#########################################"
"${have}")
endmacro()
######################################################################## ########################################################################
# Setup the python interpreter: # Setup the python interpreter:

View File

@ -1,115 +0,0 @@
# GNSS-SDR is a Global Navigation Satellite System software-defined receiver.
# This file is part of GNSS-SDR.
#
# SPDX-FileCopyrightText: 2011-2020 C. Fernandez-Prades cfernandez(at)cttc.es
# SPDX-License-Identifier: BSD-3-Clause
##############################################################################
# check if the compiler defines the architecture as ARM and set the
# version, if found.
#
# - Anthony Arnold
##############################################################################
if(__TEST_FOR_ARM_INCLUDED)
return()
endif()
set(__TEST_FOR_ARM_INCLUDED TRUE)
# Function checks if the input string defines ARM version and sets the
# output variable if found.
function(check_arm_version ppdef input_string version output_var)
string(REGEX MATCH "${ppdef}" _VERSION_MATCH "${input_string}")
if(NOT _VERSION_MATCH STREQUAL "")
set(${output_var} "${version}" PARENT_SCOPE)
endif()
endfunction()
message(STATUS "Checking for ARM")
set(IS_ARM FALSE)
set(ARM_VERSION "")
if(ENABLE_PACKAGING)
set(VERBOSE_BUILDING "-v")
else()
set(VERBOSE_BUILDING "")
endif()
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
execute_process(COMMAND echo "int main(){}"
COMMAND ${CMAKE_CXX_COMPILER} ${CMAKE_CXX_COMPILER_ARG1} -dM ${VERBOSE_BUILDING} -E -
OUTPUT_VARIABLE TEST_FOR_ARM_RESULTS
)
string(REGEX MATCH "__arm" ARM_FOUND "${TEST_FOR_ARM_RESULTS}")
if(ARM_FOUND STREQUAL "")
string(REGEX MATCH "__aarch64" ARM_FOUND "${TEST_FOR_ARM_RESULTS}")
endif()
if(ARM_FOUND STREQUAL "")
if(CMAKE_HOST_SYSTEM_PROCESSOR MATCHES "arm")
set(ARM_FOUND ${CMAKE_HOST_SYSTEM_PROCESSOR})
endif()
endif()
if(NOT ARM_FOUND STREQUAL "")
set(IS_ARM TRUE)
message(STATUS "ARM system detected.")
# detect the version
check_arm_version("__ARM_ARCH_2__" ${TEST_FOR_ARM_RESULTS} "armv2" ARM_VERSION)
check_arm_version("__ARM_ARCH_2A__" ${TEST_FOR_ARM_RESULTS} "armv2a" ARM_VERSION)
check_arm_version("__ARM_ARCH_3__" ${TEST_FOR_ARM_RESULTS} "armv3" ARM_VERSION)
check_arm_version("__ARM_ARCH_3M__" ${TEST_FOR_ARM_RESULTS} "armv3m" ARM_VERSION)
check_arm_version("__ARM_ARCH_4__" ${TEST_FOR_ARM_RESULTS} "armv4" ARM_VERSION)
check_arm_version("__ARM_ARCH_4T__" ${TEST_FOR_ARM_RESULTS} "armv4t" ARM_VERSION)
check_arm_version("__ARM_ARCH_5__" ${TEST_FOR_ARM_RESULTS} "armv5" ARM_VERSION)
check_arm_version("__ARM_ARCH_5T__" ${TEST_FOR_ARM_RESULTS} "armv5t" ARM_VERSION)
check_arm_version("__ARM_ARCH_5E__" ${TEST_FOR_ARM_RESULTS} "armv5e" ARM_VERSION)
check_arm_version("__ARM_ARCH_5TE__" ${TEST_FOR_ARM_RESULTS} "armv5te" ARM_VERSION)
check_arm_version("__ARM_ARCH_6__" ${TEST_FOR_ARM_RESULTS} "armv6" ARM_VERSION)
check_arm_version("__ARM_ARCH_6J__" ${TEST_FOR_ARM_RESULTS} "armv6j" ARM_VERSION)
check_arm_version("__ARM_ARCH_6K__" ${TEST_FOR_ARM_RESULTS} "armv6k" ARM_VERSION)
check_arm_version("__ARM_ARCH_6T2__" ${TEST_FOR_ARM_RESULTS} "armv6t2" ARM_VERSION)
check_arm_version("__ARM_ARCH_6Z__" ${TEST_FOR_ARM_RESULTS} "armv6z" ARM_VERSION)
check_arm_version("__ARM_ARCH_6ZK__" ${TEST_FOR_ARM_RESULTS} "armv6zk" ARM_VERSION)
check_arm_version("__ARM_ARCH_6M__" ${TEST_FOR_ARM_RESULTS} "armv6-m" ARM_VERSION)
check_arm_version("__ARM_ARCH_7__" ${TEST_FOR_ARM_RESULTS} "armv7" ARM_VERSION)
check_arm_version("__ARM_ARCH_7A__" ${TEST_FOR_ARM_RESULTS} "armv7-a" ARM_VERSION)
check_arm_version("__ARM_ARCH_7M__" ${TEST_FOR_ARM_RESULTS} "armv7-m" ARM_VERSION)
check_arm_version("__ARM_ARCH_7R__" ${TEST_FOR_ARM_RESULTS} "armv7-r" ARM_VERSION)
check_arm_version("__ARM_ARCH_7EM_" ${TEST_FOR_ARM_RESULTS} "armv7e-m" ARM_VERSION)
check_arm_version("__ARM_ARCH_7VE__" ${TEST_FOR_ARM_RESULTS} "armv7ve" ARM_VERSION)
check_arm_version("__ARM_ARCH_8A__" ${TEST_FOR_ARM_RESULTS} "armv8-a" ARM_VERSION)
check_arm_version("__ARM_ARCH_8A" ${TEST_FOR_ARM_RESULTS} "armv8-a" ARM_VERSION)
# anything else just define as unknown
if(ARM_VERSION STREQUAL "")
message(STATUS "Couldn't detect ARM version.")
set(ARM_VERSION "unknown")
else()
message(STATUS "ARM version ${ARM_VERSION} detected.")
endif()
else()
message(STATUS "System is not ARM.")
endif()
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
if(CMAKE_HOST_SYSTEM_PROCESSOR MATCHES "arm")
set(IS_ARM TRUE)
set(ARM_VERSION ${CMAKE_HOST_SYSTEM_PROCESSOR})
message(STATUS "ARM version ${ARM_VERSION} detected.")
endif()
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "ARMClang")
set(IS_ARM TRUE)
set(ARM_VERSION "arm")
if(CMAKE_HOST_SYSTEM_PROCESSOR MATCHES "arm")
set(ARM_VERSION ${CMAKE_HOST_SYSTEM_PROCESSOR})
message(STATUS "ARM version ${ARM_VERSION} detected.")
endif()
else()
message(STATUS "Not detecting ARM on non-GNUCXX or non-Clang compiler. Defaulting to false.")
message(STATUS "If you are compiling for ARM, set -DIS_ARM=ON manually.")
endif()
set(IS_ARM ${IS_ARM} CACHE BOOL "Compiling for ARM")
set(ARM_VERSION ${ARM_VERSION} CACHE STRING "ARM version")

View File

@ -14,6 +14,15 @@ All notable changes to GNSS-SDR will be documented in this file.
## [Unreleased](https://github.com/gnss-sdr/gnss-sdr/tree/next) ## [Unreleased](https://github.com/gnss-sdr/gnss-sdr/tree/next)
### Improvements in Accuracy:
- Processing and application of the corrections provided by the Galileo High
Accuracy Service (HAS) to the PVT solution. It requires at least a Galileo E1
(or E5a) + Galileo E6B configuration. A new configuration parameter
`PVT.use_has_corrections`, set to `true` by default, can be used to deactivate
the application of HAS corrections but still retrieve the HAS data if set to
`false`.
### Improvements in Availability: ### Improvements in Availability:
- Fixed bug that made the PVT block to not resolve position anymore after a loss - Fixed bug that made the PVT block to not resolve position anymore after a loss
@ -70,11 +79,14 @@ All notable changes to GNSS-SDR will be documented in this file.
- Improved passing of compiler flags to `volk_gnsssdr` if the corresponding - Improved passing of compiler flags to `volk_gnsssdr` if the corresponding
environment variables are defined. This fixes warnings in some packaging environment variables are defined. This fixes warnings in some packaging
systems. systems.
- Improved support for the RISC-V architecture.
- Test files are now donwloaded at configuration time instead of being included - Test files are now donwloaded at configuration time instead of being included
in the source tree. This allows for a smaller package and fixes Lintian in the source tree. This allows for a smaller package and fixes Lintian
`very-long-line-length-in-source-file` warnings since those files were not `very-long-line-length-in-source-file` warnings since those files were not
recognized as binaries. The configuration flag `-DENABLE_PACKAGING=ON` passed recognized as binaries. The configuration flag `-DENABLE_PACKAGING=ON` passed
to CMake deactivates file downloading. to CMake deactivates file downloading.
- The `ENABLE_GENERIC_ARCH` building option was removed, simplifying the process
of buiding the software in non-x86 processor architectures.
### Improvements in Usability: ### Improvements in Usability:
@ -96,6 +108,9 @@ All notable changes to GNSS-SDR will be documented in this file.
manually set the bandwidth of the bandpass filter on the radio frontend. manually set the bandwidth of the bandpass filter on the radio frontend.
- The new configuration parameter `Channels_XX.RF_channel_ID` allows to specify - The new configuration parameter `Channels_XX.RF_channel_ID` allows to specify
the signal source per channel group. the signal source per channel group.
- New configuration parameter `PVT.use_unhealthy_sats`, set by default to
`false`, allows processing observables of satellites that report an unhealthy
status in the navigation message if set to `true`.
- Allowed the CMake project to be a sub-project. - Allowed the CMake project to be a sub-project.
See the definitions of concepts and metrics at See the definitions of concepts and metrics at

View File

@ -878,6 +878,10 @@ Rtklib_Pvt::Rtklib_Pvt(const ConfigurationInterface* configuration,
// Use E6 for PVT // Use E6 for PVT
pvt_output_parameters.use_e6_for_pvt = configuration->property(role + ".use_e6_for_pvt", pvt_output_parameters.use_e6_for_pvt); pvt_output_parameters.use_e6_for_pvt = configuration->property(role + ".use_e6_for_pvt", pvt_output_parameters.use_e6_for_pvt);
pvt_output_parameters.use_has_corrections = configuration->property(role + ".use_has_corrections", pvt_output_parameters.use_has_corrections);
// Use unhealthy satellites
pvt_output_parameters.use_unhealthy_sats = configuration->property(role + ".use_unhealthy_sats", pvt_output_parameters.use_unhealthy_sats);
// Vector Tracking Loop (VTL) // Vector Tracking Loop (VTL)
pvt_output_parameters.enable_vtl = configuration->property(role + ".enable_vtl", pvt_output_parameters.enable_vtl); pvt_output_parameters.enable_vtl = configuration->property(role + ".enable_vtl", pvt_output_parameters.enable_vtl);

View File

@ -178,7 +178,9 @@ rtklib_pvt_gs::rtklib_pvt_gs(uint32_t nchannels,
d_log_timetag(conf_.log_source_timetag), d_log_timetag(conf_.log_source_timetag),
d_use_e6_for_pvt(conf_.use_e6_for_pvt), d_use_e6_for_pvt(conf_.use_e6_for_pvt),
d_enable_vtl(conf_.enable_vtl), d_enable_vtl(conf_.enable_vtl),
d_close_vtl_loop(conf_.close_vtl_loop) d_close_vtl_loop(conf_.close_vtl_loop),
d_use_has_corrections(conf_.use_has_corrections),
d_use_unhealthy_sats(conf_.use_unhealthy_sats)
{ {
// Send feedback message to observables block with the receiver clock offset // Send feedback message to observables block with the receiver clock offset
this->message_port_register_out(pmt::mp("pvt_to_observables")); this->message_port_register_out(pmt::mp("pvt_to_observables"));
@ -553,19 +555,6 @@ rtklib_pvt_gs::rtklib_pvt_gs(uint32_t nchannels,
d_user_pvt_solver = d_internal_pvt_solver; d_user_pvt_solver = d_internal_pvt_solver;
} }
d_mapStringValues["1C"] = evGPS_1C;
d_mapStringValues["2S"] = evGPS_2S;
d_mapStringValues["L5"] = evGPS_L5;
d_mapStringValues["1B"] = evGAL_1B;
d_mapStringValues["5X"] = evGAL_5X;
d_mapStringValues["E6"] = evGAL_E6;
d_mapStringValues["7X"] = evGAL_7X;
d_mapStringValues["1G"] = evGLO_1G;
d_mapStringValues["2G"] = evGLO_2G;
d_mapStringValues["B1"] = evBDS_B1;
d_mapStringValues["B2"] = evBDS_B2;
d_mapStringValues["B3"] = evBDS_B3;
// set the RTKLIB trace (debug) level // set the RTKLIB trace (debug) level
tracelevel(conf_.rtk_trace_level); tracelevel(conf_.rtk_trace_level);
@ -1209,7 +1198,15 @@ void rtklib_pvt_gs::msg_handler_telemetry(const pmt::pmt_t& msg)
if (gps_eph->SV_health != 0) if (gps_eph->SV_health != 0)
{ {
std::cout << TEXT_RED << "Satellite " << Gnss_Satellite(std::string("GPS"), gps_eph->PRN) std::cout << TEXT_RED << "Satellite " << Gnss_Satellite(std::string("GPS"), gps_eph->PRN)
<< " is not healthy, not used for navigation" << TEXT_RESET << '\n'; << " reports an unhealthy status,";
if (d_use_unhealthy_sats)
{
std::cout << " use PVT solutions at your own risk" << TEXT_RESET << '\n';
}
else
{
std::cout << " not used for navigation" << TEXT_RESET << '\n';
}
} }
} }
else if (msg_type_hash_code == d_gps_iono_sptr_type_hash_code) else if (msg_type_hash_code == d_gps_iono_sptr_type_hash_code)
@ -1269,8 +1266,15 @@ void rtklib_pvt_gs::msg_handler_telemetry(const pmt::pmt_t& msg)
if (gps_cnav_ephemeris->signal_health != 0) if (gps_cnav_ephemeris->signal_health != 0)
{ {
std::cout << "Satellite " << Gnss_Satellite(std::string("GPS"), gps_cnav_ephemeris->PRN) std::cout << "Satellite " << Gnss_Satellite(std::string("GPS"), gps_cnav_ephemeris->PRN)
<< " does not report a healthy status in the CNAV message," << " reports an unhealthy status in the CNAV message,";
<< " use PVT solutions at your own risk.\n"; if (d_use_unhealthy_sats)
{
std::cout << " use PVT solutions at your own risk.\n";
}
else
{
std::cout << " not used for navigation.\n";
}
} }
DLOG(INFO) << "New GPS CNAV ephemeris record has arrived"; DLOG(INFO) << "New GPS CNAV ephemeris record has arrived";
} }
@ -1356,7 +1360,15 @@ void rtklib_pvt_gs::msg_handler_telemetry(const pmt::pmt_t& msg)
((galileo_eph->E5b_HS != 0) || (galileo_eph->E5b_DVS == true))) ((galileo_eph->E5b_HS != 0) || (galileo_eph->E5b_DVS == true)))
{ {
std::cout << TEXT_RED << "Satellite " << Gnss_Satellite(std::string("Galileo"), galileo_eph->PRN) std::cout << TEXT_RED << "Satellite " << Gnss_Satellite(std::string("Galileo"), galileo_eph->PRN)
<< " is not healthy, not used for navigation" << TEXT_RESET << '\n'; << " reports an unhealthy status,";
if (d_use_unhealthy_sats)
{
std::cout << " use PVT solutions at your own risk" << TEXT_RESET << '\n';
}
else
{
std::cout << " not used for navigation" << TEXT_RESET << '\n';
}
} }
} }
else if (msg_type_hash_code == d_galileo_iono_sptr_type_hash_code) else if (msg_type_hash_code == d_galileo_iono_sptr_type_hash_code)
@ -1532,7 +1544,15 @@ void rtklib_pvt_gs::msg_handler_telemetry(const pmt::pmt_t& msg)
if (bds_dnav_eph->SV_health != 0) if (bds_dnav_eph->SV_health != 0)
{ {
std::cout << TEXT_RED << "Satellite " << Gnss_Satellite(std::string("Beidou"), bds_dnav_eph->PRN) std::cout << TEXT_RED << "Satellite " << Gnss_Satellite(std::string("Beidou"), bds_dnav_eph->PRN)
<< " is not healthy, not used for navigation" << TEXT_RESET << '\n'; << " reports an unhealthy status,";
if (d_use_unhealthy_sats)
{
std::cout << " use PVT solutions at your own risk" << TEXT_RESET << '\n';
}
else
{
std::cout << " not used for navigation" << TEXT_RESET << '\n';
}
} }
} }
else if (msg_type_hash_code == d_beidou_dnav_iono_sptr_type_hash_code) else if (msg_type_hash_code == d_beidou_dnav_iono_sptr_type_hash_code)
@ -1580,7 +1600,7 @@ void rtklib_pvt_gs::msg_handler_telemetry(const pmt::pmt_t& msg)
} }
void rtklib_pvt_gs::msg_handler_has_data(const pmt::pmt_t& msg) const void rtklib_pvt_gs::msg_handler_has_data(const pmt::pmt_t& msg)
{ {
try try
{ {
@ -1588,6 +1608,14 @@ void rtklib_pvt_gs::msg_handler_has_data(const pmt::pmt_t& msg) const
if (msg_type_hash_code == d_galileo_has_data_sptr_type_hash_code) if (msg_type_hash_code == d_galileo_has_data_sptr_type_hash_code)
{ {
const auto has_data = wht::any_cast<std::shared_ptr<Galileo_HAS_data>>(pmt::any_ref(msg)); const auto has_data = wht::any_cast<std::shared_ptr<Galileo_HAS_data>>(pmt::any_ref(msg));
if (d_use_has_corrections && (has_data->has_status == 1)) // operational mode
{
d_internal_pvt_solver->store_has_data(*has_data);
if (d_enable_rx_clock_correction == true)
{
d_user_pvt_solver->store_has_data(*has_data);
}
}
if (d_has_simple_printer) if (d_has_simple_printer)
{ {
d_has_simple_printer->print_message(has_data.get()); d_has_simple_printer->print_message(has_data.get());
@ -1810,44 +1838,10 @@ void rtklib_pvt_gs::apply_rx_clock_offset(std::map<int, Gnss_Synchro>& observabl
// all observables in the map are valid // all observables in the map are valid
observables_iter->second.RX_time -= rx_clock_offset_s; observables_iter->second.RX_time -= rx_clock_offset_s;
observables_iter->second.Pseudorange_m -= rx_clock_offset_s * SPEED_OF_LIGHT_M_S; observables_iter->second.Pseudorange_m -= rx_clock_offset_s * SPEED_OF_LIGHT_M_S;
const auto it_freq_map = SIGNAL_FREQ_MAP.find(std::string(observables_iter->second.Signal, 2));
switch (d_mapStringValues[observables_iter->second.Signal]) if (it_freq_map != SIGNAL_FREQ_MAP.cend())
{ {
case evGPS_1C: observables_iter->second.Carrier_phase_rads -= rx_clock_offset_s * it_freq_map->second * TWO_PI;
case evSBAS_1C:
case evGAL_1B:
observables_iter->second.Carrier_phase_rads -= rx_clock_offset_s * FREQ1 * TWO_PI;
break;
case evGPS_L5:
case evGAL_5X:
observables_iter->second.Carrier_phase_rads -= rx_clock_offset_s * FREQ5 * TWO_PI;
break;
case evGAL_E6:
observables_iter->second.Carrier_phase_rads -= rx_clock_offset_s * FREQ6 * TWO_PI;
break;
case evGAL_7X:
observables_iter->second.Carrier_phase_rads -= rx_clock_offset_s * FREQ7 * TWO_PI;
break;
case evGPS_2S:
observables_iter->second.Carrier_phase_rads -= rx_clock_offset_s * FREQ2 * TWO_PI;
break;
case evBDS_B3:
observables_iter->second.Carrier_phase_rads -= rx_clock_offset_s * FREQ3_BDS * TWO_PI;
break;
case evGLO_1G:
observables_iter->second.Carrier_phase_rads -= rx_clock_offset_s * FREQ1_GLO * TWO_PI;
break;
case evGLO_2G:
observables_iter->second.Carrier_phase_rads -= rx_clock_offset_s * FREQ2_GLO * TWO_PI;
break;
case evBDS_B1:
observables_iter->second.Carrier_phase_rads -= rx_clock_offset_s * FREQ1_BDS * TWO_PI;
break;
case evBDS_B2:
observables_iter->second.Carrier_phase_rads -= rx_clock_offset_s * FREQ2_BDS * TWO_PI;
break;
default:
break;
} }
} }
} }
@ -1912,44 +1906,11 @@ void rtklib_pvt_gs::initialize_and_apply_carrier_phase_offset()
// it is set to false by the work function if the gnss_synchro is not valid // it is set to false by the work function if the gnss_synchro is not valid
if (d_channel_initialized.at(observables_iter->second.Channel_ID) == false) if (d_channel_initialized.at(observables_iter->second.Channel_ID) == false)
{ {
double wavelength_m = 0; double wavelength_m = 1.0;
switch (d_mapStringValues[observables_iter->second.Signal]) const auto it_freq_map = SIGNAL_FREQ_MAP.find(std::string(observables_iter->second.Signal, 2));
if (it_freq_map != SIGNAL_FREQ_MAP.cend())
{ {
case evGPS_1C: wavelength_m = SPEED_OF_LIGHT_M_S / it_freq_map->second;
case evSBAS_1C:
case evGAL_1B:
wavelength_m = SPEED_OF_LIGHT_M_S / FREQ1;
break;
case evGPS_L5:
case evGAL_5X:
wavelength_m = SPEED_OF_LIGHT_M_S / FREQ5;
break;
case evGAL_E6:
wavelength_m = SPEED_OF_LIGHT_M_S / FREQ6;
break;
case evGAL_7X:
wavelength_m = SPEED_OF_LIGHT_M_S / FREQ7;
break;
case evGPS_2S:
wavelength_m = SPEED_OF_LIGHT_M_S / FREQ2;
break;
case evBDS_B3:
wavelength_m = SPEED_OF_LIGHT_M_S / FREQ3_BDS;
break;
case evGLO_1G:
wavelength_m = SPEED_OF_LIGHT_M_S / FREQ1_GLO;
break;
case evGLO_2G:
wavelength_m = SPEED_OF_LIGHT_M_S / FREQ2_GLO;
break;
case evBDS_B1:
wavelength_m = SPEED_OF_LIGHT_M_S / FREQ1_BDS;
break;
case evBDS_B2:
wavelength_m = SPEED_OF_LIGHT_M_S / FREQ2_BDS;
break;
default:
break;
} }
const double wrap_carrier_phase_rad = fmod(observables_iter->second.Carrier_phase_rads, TWO_PI); const double wrap_carrier_phase_rad = fmod(observables_iter->second.Carrier_phase_rads, TWO_PI);
d_initial_carrier_phase_offset_estimation_rads.at(observables_iter->second.Channel_ID) = TWO_PI * round(observables_iter->second.Pseudorange_m / wavelength_m) - observables_iter->second.Carrier_phase_rads + wrap_carrier_phase_rad; d_initial_carrier_phase_offset_estimation_rads.at(observables_iter->second.Channel_ID) = TWO_PI * round(observables_iter->second.Pseudorange_m / wavelength_m) - observables_iter->second.Carrier_phase_rads + wrap_carrier_phase_rad;
@ -1962,6 +1923,16 @@ void rtklib_pvt_gs::initialize_and_apply_carrier_phase_offset()
} }
void rtklib_pvt_gs::update_HAS_corrections()
{
this->d_internal_pvt_solver->update_has_corrections(this->d_gnss_observables_map);
if (d_enable_rx_clock_correction == true)
{
this->d_user_pvt_solver->update_has_corrections(this->d_gnss_observables_map);
}
}
int rtklib_pvt_gs::work(int noutput_items, gr_vector_const_void_star& input_items, int rtklib_pvt_gs::work(int noutput_items, gr_vector_const_void_star& input_items,
gr_vector_void_star& output_items __attribute__((unused))) gr_vector_void_star& output_items __attribute__((unused)))
{ {
@ -2023,7 +1994,7 @@ int rtklib_pvt_gs::work(int noutput_items, gr_vector_const_void_star& input_item
if (tmp_eph_iter_gps != d_internal_pvt_solver->gps_ephemeris_map.cend()) if (tmp_eph_iter_gps != d_internal_pvt_solver->gps_ephemeris_map.cend())
{ {
const uint32_t prn_aux = tmp_eph_iter_gps->second.PRN; const uint32_t prn_aux = tmp_eph_iter_gps->second.PRN;
if ((prn_aux == in[i][epoch].PRN) && (std::string(in[i][epoch].Signal) == std::string("1C")) && (tmp_eph_iter_gps->second.SV_health == 0)) if ((prn_aux == in[i][epoch].PRN) && (std::string(in[i][epoch].Signal, 2) == std::string("1C")) && (d_use_unhealthy_sats || (tmp_eph_iter_gps->second.SV_health == 0)))
{ {
store_valid_observable = true; store_valid_observable = true;
} }
@ -2032,9 +2003,9 @@ int rtklib_pvt_gs::work(int noutput_items, gr_vector_const_void_star& input_item
{ {
const uint32_t prn_aux = tmp_eph_iter_gal->second.PRN; const uint32_t prn_aux = tmp_eph_iter_gal->second.PRN;
if ((prn_aux == in[i][epoch].PRN) && if ((prn_aux == in[i][epoch].PRN) &&
(((std::string(in[i][epoch].Signal) == std::string("1B")) && (tmp_eph_iter_gal->second.E1B_DVS == false) && (tmp_eph_iter_gal->second.E1B_HS == 0)) || (((std::string(in[i][epoch].Signal, 2) == std::string("1B")) && (d_use_unhealthy_sats || ((tmp_eph_iter_gal->second.E1B_DVS == false) && (tmp_eph_iter_gal->second.E1B_HS == 0)))) ||
((std::string(in[i][epoch].Signal) == std::string("5X")) && (tmp_eph_iter_gal->second.E5a_DVS == false) && (tmp_eph_iter_gal->second.E5a_HS == 0)) || ((std::string(in[i][epoch].Signal, 2) == std::string("5X")) && (d_use_unhealthy_sats || ((tmp_eph_iter_gal->second.E5a_DVS == false) && (tmp_eph_iter_gal->second.E5a_HS == 0)))) ||
((std::string(in[i][epoch].Signal) == std::string("7X")) && (tmp_eph_iter_gal->second.E5b_DVS == false) && (tmp_eph_iter_gal->second.E5b_HS == 0)))) ((std::string(in[i][epoch].Signal, 2) == std::string("7X")) && (d_use_unhealthy_sats || ((tmp_eph_iter_gal->second.E5b_DVS == false) && (tmp_eph_iter_gal->second.E5b_HS == 0))))))
{ {
store_valid_observable = true; store_valid_observable = true;
} }
@ -2042,7 +2013,7 @@ int rtklib_pvt_gs::work(int noutput_items, gr_vector_const_void_star& input_item
if (tmp_eph_iter_cnav != d_internal_pvt_solver->gps_cnav_ephemeris_map.cend()) if (tmp_eph_iter_cnav != d_internal_pvt_solver->gps_cnav_ephemeris_map.cend())
{ {
const uint32_t prn_aux = tmp_eph_iter_cnav->second.PRN; const uint32_t prn_aux = tmp_eph_iter_cnav->second.PRN;
if ((prn_aux == in[i][epoch].PRN) && (((std::string(in[i][epoch].Signal) == std::string("2S")) || (std::string(in[i][epoch].Signal) == std::string("L5"))))) if ((prn_aux == in[i][epoch].PRN) && (((std::string(in[i][epoch].Signal, 2) == std::string("2S")) || (std::string(in[i][epoch].Signal, 2) == std::string("L5")))))
{ {
store_valid_observable = true; store_valid_observable = true;
} }
@ -2050,7 +2021,7 @@ int rtklib_pvt_gs::work(int noutput_items, gr_vector_const_void_star& input_item
if (tmp_eph_iter_glo_gnav != d_internal_pvt_solver->glonass_gnav_ephemeris_map.cend()) if (tmp_eph_iter_glo_gnav != d_internal_pvt_solver->glonass_gnav_ephemeris_map.cend())
{ {
const uint32_t prn_aux = tmp_eph_iter_glo_gnav->second.PRN; const uint32_t prn_aux = tmp_eph_iter_glo_gnav->second.PRN;
if ((prn_aux == in[i][epoch].PRN) && ((std::string(in[i][epoch].Signal) == std::string("1G")) || (std::string(in[i][epoch].Signal) == std::string("2G")))) if ((prn_aux == in[i][epoch].PRN) && ((std::string(in[i][epoch].Signal, 2) == std::string("1G")) || (std::string(in[i][epoch].Signal, 2) == std::string("2G"))))
{ {
store_valid_observable = true; store_valid_observable = true;
} }
@ -2058,12 +2029,12 @@ int rtklib_pvt_gs::work(int noutput_items, gr_vector_const_void_star& input_item
if (tmp_eph_iter_bds_dnav != d_internal_pvt_solver->beidou_dnav_ephemeris_map.cend()) if (tmp_eph_iter_bds_dnav != d_internal_pvt_solver->beidou_dnav_ephemeris_map.cend())
{ {
const uint32_t prn_aux = tmp_eph_iter_bds_dnav->second.PRN; const uint32_t prn_aux = tmp_eph_iter_bds_dnav->second.PRN;
if ((prn_aux == in[i][epoch].PRN) && (((std::string(in[i][epoch].Signal) == std::string("B1")) || (std::string(in[i][epoch].Signal) == std::string("B3"))) && (tmp_eph_iter_bds_dnav->second.SV_health == 0))) if ((prn_aux == in[i][epoch].PRN) && (((std::string(in[i][epoch].Signal, 2) == std::string("B1")) || (std::string(in[i][epoch].Signal, 2) == std::string("B3"))) && (d_use_unhealthy_sats || (tmp_eph_iter_bds_dnav->second.SV_health == 0))))
{ {
store_valid_observable = true; store_valid_observable = true;
} }
} }
if (std::string(in[i][epoch].Signal) == std::string("E6")) if (std::string(in[i][epoch].Signal, 2) == std::string("E6"))
{ {
store_valid_observable = true; store_valid_observable = true;
} }
@ -2125,6 +2096,12 @@ int rtklib_pvt_gs::work(int noutput_items, gr_vector_const_void_star& input_item
} }
} }
// ############ 2. APPLY HAS CORRECTIONS IF AVAILABLE ####
if (d_use_has_corrections && !d_gnss_observables_map.empty())
{
this->update_HAS_corrections();
}
// ############ 2 COMPUTE THE PVT ################################ // ############ 2 COMPUTE THE PVT ################################
bool flag_pvt_valid = false; bool flag_pvt_valid = false;
if (d_gnss_observables_map.empty() == false) if (d_gnss_observables_map.empty() == false)
@ -2524,7 +2501,7 @@ int rtklib_pvt_gs::work(int noutput_items, gr_vector_const_void_star& input_item
// p_time += boost::posix_time::microseconds(round(rtklib_utc_time.sec * 1e6)); // p_time += boost::posix_time::microseconds(round(rtklib_utc_time.sec * 1e6));
// std::cout << TEXT_MAGENTA << "Observable RX time (GPST) " << boost::posix_time::to_simple_string(p_time) << TEXT_RESET << '\n'; // std::cout << TEXT_MAGENTA << "Observable RX time (GPST) " << boost::posix_time::to_simple_string(p_time) << TEXT_RESET << '\n';
DLOG(INFO) << "Position at " << boost::posix_time::to_simple_string(d_user_pvt_solver->get_position_UTC_time()) LOG(INFO) << "Position at " << boost::posix_time::to_simple_string(d_user_pvt_solver->get_position_UTC_time())
<< " UTC using " << d_user_pvt_solver->get_num_valid_observations() << " observations is Lat = " << d_user_pvt_solver->get_latitude() << " [deg], Long = " << d_user_pvt_solver->get_longitude() << " UTC using " << d_user_pvt_solver->get_num_valid_observations() << " observations is Lat = " << d_user_pvt_solver->get_latitude() << " [deg], Long = " << d_user_pvt_solver->get_longitude()
<< " [deg], Height = " << d_user_pvt_solver->get_height() << " [m]"; << " [deg], Height = " << d_user_pvt_solver->get_height() << " [m]";

View File

@ -49,6 +49,7 @@ class Beidou_Dnav_Almanac;
class Beidou_Dnav_Ephemeris; class Beidou_Dnav_Ephemeris;
class Galileo_Almanac; class Galileo_Almanac;
class Galileo_Ephemeris; class Galileo_Ephemeris;
class Galileo_HAS_data;
class GeoJSON_Printer; class GeoJSON_Printer;
class Gps_Almanac; class Gps_Almanac;
class Gps_Ephemeris; class Gps_Ephemeris;
@ -140,13 +141,15 @@ private:
void msg_handler_telemetry(const pmt::pmt_t& msg); void msg_handler_telemetry(const pmt::pmt_t& msg);
void msg_handler_has_data(const pmt::pmt_t& msg) const; void msg_handler_has_data(const pmt::pmt_t& msg);
void initialize_and_apply_carrier_phase_offset(); void initialize_and_apply_carrier_phase_offset();
void apply_rx_clock_offset(std::map<int, Gnss_Synchro>& observables_map, void apply_rx_clock_offset(std::map<int, Gnss_Synchro>& observables_map,
double rx_clock_offset_s); double rx_clock_offset_s);
void update_HAS_corrections();
std::map<int, Gnss_Synchro> interpolate_observables(const std::map<int, Gnss_Synchro>& observables_map_t0, std::map<int, Gnss_Synchro> interpolate_observables(const std::map<int, Gnss_Synchro>& observables_map_t0,
const std::map<int, Gnss_Synchro>& observables_map_t1, const std::map<int, Gnss_Synchro>& observables_map_t1,
double rx_time_s); double rx_time_s);
@ -160,7 +163,7 @@ private:
typedef struct typedef struct
{ {
long mtype; // NOLINT(google-runtime-int) required by SysV queue messaging long mtype; // NOLINT(google-runtime-int)
double ttff; double ttff;
} d_ttff_msgbuf; } d_ttff_msgbuf;
bool send_sys_v_ttff_msg(d_ttff_msgbuf ttff) const; bool send_sys_v_ttff_msg(d_ttff_msgbuf ttff) const;
@ -194,23 +197,6 @@ private:
std::vector<bool> d_channel_initialized; std::vector<bool> d_channel_initialized;
std::vector<double> d_initial_carrier_phase_offset_estimation_rads; std::vector<double> d_initial_carrier_phase_offset_estimation_rads;
enum StringValue_
{
evGPS_1C,
evGPS_2S,
evGPS_L5,
evSBAS_1C,
evGAL_1B,
evGAL_5X,
evGAL_E6,
evGAL_7X,
evGLO_1G,
evGLO_2G,
evBDS_B1,
evBDS_B2,
evBDS_B3
};
std::map<std::string, StringValue_> d_mapStringValues;
std::map<int, Gnss_Synchro> d_gnss_observables_map; std::map<int, Gnss_Synchro> d_gnss_observables_map;
std::map<int, Gnss_Synchro> d_gnss_observables_map_t0; std::map<int, Gnss_Synchro> d_gnss_observables_map_t0;
std::map<int, Gnss_Synchro> d_gnss_observables_map_t1; std::map<int, Gnss_Synchro> d_gnss_observables_map_t1;
@ -292,6 +278,8 @@ private:
bool d_enable_vtl; bool d_enable_vtl;
bool d_close_vtl_loop; bool d_close_vtl_loop;
std::map<int, uint64_t> d_last_sent_vtl_cmd_samplestamp_map; std::map<int, uint64_t> d_last_sent_vtl_cmd_samplestamp_map;
bool d_use_has_corrections;
bool d_use_unhealthy_sats;
}; };

View File

@ -1,74 +0,0 @@
/*!
* \file pvt_conf.cc
* \brief Class that contains all the configuration parameters for a PVT block
* \author Carles Fernandez, 2018. cfernandez(at)cttc.es
*
* -----------------------------------------------------------------------------
*
* GNSS-SDR is a Global Navigation Satellite System software-defined receiver.
* This file is part of GNSS-SDR.
*
* Copyright (C) 2010-2020 (see AUTHORS file for a list of contributors)
* SPDX-License-Identifier: GPL-3.0-or-later
*
* -----------------------------------------------------------------------------
*/
#include "pvt_conf.h"
Pvt_Conf::Pvt_Conf()
{
type_of_receiver = 0U;
observable_interval_ms = 20U;
output_rate_ms = 0;
display_rate_ms = 0;
kml_rate_ms = 1000;
gpx_rate_ms = 1000;
geojson_rate_ms = 1000;
nmea_rate_ms = 1000;
max_obs_block_rx_clock_offset_ms = 40;
rinex_version = 0;
rinexobs_rate_ms = 0;
rinex_name = std::string("-");
dump = false;
dump_mat = true;
flag_nmea_tty_port = false;
flag_rtcm_server = false;
flag_rtcm_tty_port = false;
rtcm_tcp_port = 0U;
rtcm_station_id = 0U;
output_enabled = true;
rinex_output_enabled = true;
gpx_output_enabled = true;
geojson_output_enabled = true;
nmea_output_file_enabled = true;
kml_output_enabled = true;
xml_output_enabled = true;
rtcm_output_file_enabled = true;
output_path = std::string(".");
rinex_output_path = std::string(".");
gpx_output_path = std::string(".");
geojson_output_path = std::string(".");
nmea_output_file_path = std::string(".");
kml_output_path = std::string(".");
xml_output_path = std::string(".");
rtcm_output_file_path = std::string(".");
log_source_timetag_file = "PVT_timetag.dat";
enable_rx_clock_correction = true;
monitor_enabled = false;
monitor_ephemeris_enabled = false;
protobuf_enabled = true;
udp_port = 0;
udp_eph_port = 0;
pre_2009_file = false;
show_local_time_zone = false;
log_source_timetag = false;
}

View File

@ -94,6 +94,8 @@ public:
bool use_e6_for_pvt = true; bool use_e6_for_pvt = true;
bool enable_vtl = false; bool enable_vtl = false;
bool close_vtl_loop = true; bool close_vtl_loop = true;
bool use_has_corrections = true;
bool use_unhealthy_sats = false;
}; };

View File

@ -4,7 +4,7 @@
* data flow and structures * data flow and structures
* \authors <ul> * \authors <ul>
* <li> 2017-2019, Javier Arribas * <li> 2017-2019, Javier Arribas
* <li> 2017-2019, Carles Fernandez * <li> 2017-2023, Carles Fernandez
* <li> 2007-2013, T. Takasu * <li> 2007-2013, T. Takasu
* </ul> * </ul>
* *
@ -23,7 +23,7 @@
* ----------------------------------------------------------------------------- * -----------------------------------------------------------------------------
* Copyright (C) 2007-2013, T. Takasu * Copyright (C) 2007-2013, T. Takasu
* Copyright (C) 2017-2019, Javier Arribas * Copyright (C) 2017-2019, Javier Arribas
* Copyright (C) 2017-2019, Carles Fernandez * Copyright (C) 2017-2023, Carles Fernandez
* All rights reserved. * All rights reserved.
* *
* SPDX-License-Identifier: BSD-2-Clause * SPDX-License-Identifier: BSD-2-Clause
@ -40,6 +40,8 @@
#include <glog/logging.h> #include <glog/logging.h>
#include <matio.h> #include <matio.h>
#include "iostream" #include "iostream"
#include <algorithm>
#include <cmath>
#include <exception> #include <exception>
#include <utility> #include <utility>
#include <vector> #include <vector>
@ -141,6 +143,8 @@ Rtklib_Solver::Rtklib_Solver(const rtk_t &rtk,
d_rtklib_freq_index[1] = 3; d_rtklib_freq_index[1] = 3;
break; break;
} }
// auto empty_map = std::map < int, HAS_obs_corrections >> ();
// d_has_obs_corr_map["L1 C/A"] = empty_map;
// ############# ENABLE DATA FILE LOG ################# // ############# ENABLE DATA FILE LOG #################
if (d_flag_dump_enabled == true) if (d_flag_dump_enabled == true)
@ -210,7 +214,7 @@ bool Rtklib_Solver::save_matfile() const
const int32_t number_of_uint8_vars = 3; const int32_t number_of_uint8_vars = 3;
const int32_t number_of_float_vars = 2; const int32_t number_of_float_vars = 2;
const int32_t epoch_size_bytes = sizeof(double) * number_of_double_vars + const int32_t epoch_size_bytes = sizeof(double) * number_of_double_vars +
sizeof(double) * number_of_double_vars_sat*6+ sizeof(double) * number_of_double_vars_sat * 6 +
sizeof(uint32_t) * number_of_uint32_vars + sizeof(uint32_t) * number_of_uint32_vars +
sizeof(uint8_t) * number_of_uint8_vars + sizeof(uint8_t) * number_of_uint8_vars +
sizeof(float) * number_of_float_vars; sizeof(float) * number_of_float_vars;
@ -563,6 +567,446 @@ Monitor_Pvt Rtklib_Solver::get_monitor_pvt() const
return d_monitor_pvt; return d_monitor_pvt;
} }
void Rtklib_Solver::store_has_data(const Galileo_HAS_data &new_has_data)
{
// Compute time of application HAS SIS ICD, Issue 1.0, Section 7.7
uint16_t toh = new_has_data.header.toh;
uint32_t hr = std::floor(new_has_data.tow / 3600);
uint32_t tmt = 0;
if ((hr * 3600 + toh) <= new_has_data.tow)
{
tmt = hr * 3600 + toh;
}
else
{
tmt = (hr - 1) * 3600 + toh;
}
const std::string gps_str("GPS");
const std::string gal_str("Galileo");
if (new_has_data.header.orbit_correction_flag)
{
LOG(INFO) << "Received HAS orbit corrections";
// for each satellite in GPS ephemeris
for (const auto &gpseph : gps_ephemeris_map)
{
int prn = gpseph.second.PRN;
int32_t sis_iod = gpseph.second.IODE_SF3;
uint16_t gnss_iod = new_has_data.get_gnss_iod(gps_str, prn);
if (static_cast<int32_t>(gnss_iod) == sis_iod)
{
float radial_m = new_has_data.get_delta_radial_m(gps_str, prn);
if (std::fabs(radial_m + 10.24) < 0.001) // -10.24 means not available
{
radial_m = 0.0;
}
float in_track_m = new_has_data.get_delta_in_track_m(gps_str, prn);
if (std::fabs(in_track_m + 16.384) < 0.001) // -16.384 means not available
{
in_track_m = 0.0;
}
float cross_track_m = new_has_data.get_delta_in_track_m(gps_str, prn);
if (std::fabs(cross_track_m + 16.384) < 0.001) // -16.384 means not available
{
cross_track_m = 0.0;
}
d_has_orbit_corrections_store_map[gps_str][prn].radial_m = radial_m;
d_has_orbit_corrections_store_map[gps_str][prn].in_track_m = in_track_m;
d_has_orbit_corrections_store_map[gps_str][prn].cross_track_m = cross_track_m;
d_has_orbit_corrections_store_map[gps_str][prn].valid_until = tmt +
new_has_data.get_validity_interval_s(new_has_data.validity_interval_index_orbit_corrections);
d_has_orbit_corrections_store_map[gps_str][prn].iod = gnss_iod;
// TODO: check for end of week
}
}
// for each satellite in Galileo ephemeris
for (const auto &galeph : galileo_ephemeris_map)
{
int prn = galeph.second.PRN;
int32_t sis_iod = galeph.second.IOD_ephemeris;
uint16_t gnss_iod = new_has_data.get_gnss_iod(gal_str, prn);
if (static_cast<int32_t>(gnss_iod) == sis_iod)
{
float radial_m = new_has_data.get_delta_radial_m(gal_str, prn);
if (std::fabs(radial_m + 10.24) < 0.001) // -10.24 means not available
{
radial_m = 0.0;
}
float in_track_m = new_has_data.get_delta_in_track_m(gal_str, prn);
if (std::fabs(in_track_m + 16.384) < 0.001) // -16.384 means not available
{
in_track_m = 0.0;
}
float cross_track_m = new_has_data.get_delta_in_track_m(gal_str, prn);
if (std::fabs(cross_track_m + 16.384) < 0.001) // -16.384 means not available
{
cross_track_m = 0.0;
}
d_has_orbit_corrections_store_map[gal_str][prn].radial_m = radial_m;
d_has_orbit_corrections_store_map[gal_str][prn].in_track_m = in_track_m;
d_has_orbit_corrections_store_map[gal_str][prn].cross_track_m = cross_track_m;
d_has_orbit_corrections_store_map[gal_str][prn].valid_until = tmt +
new_has_data.get_validity_interval_s(new_has_data.validity_interval_index_orbit_corrections);
d_has_orbit_corrections_store_map[gal_str][prn].iod = gnss_iod;
// TODO: check for end of week
}
}
}
if (new_has_data.header.clock_fullset_flag)
{
LOG(INFO) << "Received HAS clock fullset corrections";
for (const auto &gpseph : gps_ephemeris_map)
{
int prn = gpseph.second.PRN;
int32_t sis_iod = gpseph.second.IODE_SF3;
auto it = d_has_orbit_corrections_store_map[gps_str].find(prn);
if (it != d_has_orbit_corrections_store_map[gps_str].end())
{
uint16_t gnss_iod = it->second.iod;
if (static_cast<int32_t>(gnss_iod) == sis_iod)
{
float clock_correction_mult_m = new_has_data.get_clock_correction_mult_m(gps_str, prn);
if ((std::fabs(clock_correction_mult_m + 10.24) < 0.001) ||
(std::fabs(clock_correction_mult_m + 20.48) < 0.001) ||
(std::fabs(clock_correction_mult_m + 30.72) < 0.001) ||
(std::fabs(clock_correction_mult_m + 40.96) < 0.001))
{
clock_correction_mult_m = 0.0;
}
if ((std::fabs(clock_correction_mult_m - 10.2375) < 0.001) ||
(std::fabs(clock_correction_mult_m - 20.475) < 0.001) ||
(std::fabs(clock_correction_mult_m - 30.7125) < 0.001) ||
(std::fabs(clock_correction_mult_m - 40.95) < 0.001))
{
// Satellite should not be used!
clock_correction_mult_m = 0.0;
}
d_has_clock_corrections_store_map[gps_str][prn].clock_correction_m = clock_correction_mult_m;
d_has_clock_corrections_store_map[gps_str][prn].valid_until = tmt +
new_has_data.get_validity_interval_s(new_has_data.validity_interval_index_clock_fullset_corrections);
// TODO: check for end of week
}
}
}
// for each satellite in Galileo ephemeris
for (const auto &galeph : galileo_ephemeris_map)
{
int prn = galeph.second.PRN;
int32_t iod_sis = galeph.second.IOD_ephemeris;
auto it = d_has_orbit_corrections_store_map[gal_str].find(prn);
if (it != d_has_orbit_corrections_store_map[gal_str].end())
{
uint16_t gnss_iod = it->second.iod;
if (static_cast<int32_t>(gnss_iod) == iod_sis)
{
float clock_correction_mult_m = new_has_data.get_clock_correction_mult_m(gal_str, prn);
// std::cout << "Galileo Satellite " << prn
// << " clock correction=" << new_has_data.get_clock_correction_mult_m(gal_str, prn)
// << std::endl;
if ((std::fabs(clock_correction_mult_m + 10.24) < 0.001) ||
(std::fabs(clock_correction_mult_m + 20.48) < 0.001) ||
(std::fabs(clock_correction_mult_m + 30.72) < 0.001) ||
(std::fabs(clock_correction_mult_m + 40.96) < 0.001))
{
clock_correction_mult_m = 0.0;
}
d_has_clock_corrections_store_map[gal_str][prn].clock_correction_m = clock_correction_mult_m;
d_has_clock_corrections_store_map[gal_str][prn].valid_until = tmt +
new_has_data.get_validity_interval_s(new_has_data.validity_interval_index_clock_fullset_corrections);
// TODO: check for end of week
}
}
}
}
if (new_has_data.header.clock_subset_flag)
{
LOG(INFO) << "Received HAS clock subset corrections";
for (const auto &gpseph : gps_ephemeris_map)
{
int prn = gpseph.second.PRN;
int32_t sis_iod = gpseph.second.IODE_SF3;
int32_t gnss_iod = d_has_orbit_corrections_store_map[gps_str][prn].iod;
if (gnss_iod == sis_iod)
{
// d_has_clock_corrections_store_map[gps_str][prn].clock_correction_m = new_has_data.get_clock_subset_correction_mult_m(gps_str, prn);
// d_has_clock_corrections_store_map[gps_str][prn].valid_until = tmt + new_has_data.get_validity_interval_s(new_has_data.validity_interval_index_clock_subset_corrections);
// TODO: check for end of week
}
}
}
if (new_has_data.header.code_bias_flag)
{
LOG(INFO) << "Received HAS code bias corrections";
uint32_t valid_until = tmt +
new_has_data.get_validity_interval_s(new_has_data.validity_interval_index_code_bias_corrections);
auto signals_gal = new_has_data.get_signals_in_mask(gal_str);
for (const auto &it : signals_gal)
{
auto prns = new_has_data.get_PRNs_in_mask(gal_str);
for (auto prn : prns)
{
float code_bias_m = new_has_data.get_code_bias_m(it, prn);
if ((std::fabs(code_bias_m + 20.48) < 0.01)) // -20.48 means not available
{
code_bias_m = 0.0;
}
d_has_code_bias_store_map[it][prn] = {code_bias_m, valid_until};
}
}
auto signals_gps = new_has_data.get_signals_in_mask(gps_str);
for (const auto &it : signals_gps)
{
auto prns = new_has_data.get_PRNs_in_mask(gps_str);
for (auto prn : prns)
{
float code_bias_m = new_has_data.get_code_bias_m(it, prn);
if ((std::fabs(code_bias_m + 20.48) < 0.01)) // -20.48 means not available
{
code_bias_m = 0.0;
}
d_has_code_bias_store_map[it][prn] = {code_bias_m, valid_until};
}
}
}
if (new_has_data.header.phase_bias_flag)
{
LOG(INFO) << "Received HAS phase bias corrections";
uint32_t valid_until = tmt +
new_has_data.get_validity_interval_s(new_has_data.validity_interval_index_phase_bias_corrections);
auto signals_gal = new_has_data.get_signals_in_mask(gal_str);
for (const auto &it : signals_gal)
{
auto prns = new_has_data.get_PRNs_in_mask(gal_str);
for (auto prn : prns)
{
float phase_bias_correction_cycles = new_has_data.get_phase_bias_cycle(it, prn);
if (std::fabs(phase_bias_correction_cycles + 10.24) < 0.001) // -10.24 means not available
{
phase_bias_correction_cycles = 0.0;
}
d_has_phase_bias_store_map[it][prn] = {phase_bias_correction_cycles, valid_until};
// TODO: process Phase Discontinuity Indicator
}
}
auto signals_gps = new_has_data.get_signals_in_mask(gps_str);
for (const auto &it : signals_gps)
{
auto prns = new_has_data.get_PRNs_in_mask(gps_str);
for (auto prn : prns)
{
float phase_bias_correction_cycles = new_has_data.get_phase_bias_cycle(it, prn);
if (std::fabs(phase_bias_correction_cycles + 10.24) < 0.001) // -10.24 means not available
{
phase_bias_correction_cycles = 0.0;
}
d_has_phase_bias_store_map[it][prn] = {phase_bias_correction_cycles, valid_until};
// TODO: process Phase Discontinuity Indicator
}
}
}
}
void Rtklib_Solver::update_has_corrections(const std::map<int, Gnss_Synchro> &obs_map)
{
this->check_has_orbit_clock_validity(obs_map);
this->get_has_biases(obs_map);
}
void Rtklib_Solver::check_has_orbit_clock_validity(const std::map<int, Gnss_Synchro> &obs_map)
{
for (const auto &it : obs_map)
{
uint32_t obs_tow = it.second.interp_TOW_ms / 1000.0;
auto prn = static_cast<int>(it.second.PRN);
if (it.second.System == 'G')
{
auto it_sys = d_has_orbit_corrections_store_map.find("GPS");
if (it_sys != d_has_orbit_corrections_store_map.end())
{
auto it_map_corr = it_sys->second.find(prn);
if (it_map_corr != it_sys->second.end())
{
auto has_data_valid_until = it_map_corr->second.valid_until;
if (has_data_valid_until < obs_tow)
{
// Delete outdated data
it_sys->second.erase(prn);
}
}
}
auto it_sys_clock = d_has_clock_corrections_store_map.find("GPS");
if (it_sys_clock != d_has_clock_corrections_store_map.end())
{
auto it_map_corr = it_sys_clock->second.find(prn);
if (it_map_corr != it_sys_clock->second.end())
{
auto has_data_valid_until = it_map_corr->second.valid_until;
if (has_data_valid_until < obs_tow)
{
// Delete outdated data
it_sys_clock->second.erase(prn);
}
}
}
}
if (it.second.System == 'E')
{
auto it_sys = d_has_orbit_corrections_store_map.find("Galileo");
if (it_sys != d_has_orbit_corrections_store_map.end())
{
auto it_map_corr = it_sys->second.find(prn);
if (it_map_corr != it_sys->second.end())
{
auto has_data_valid_until = it_map_corr->second.valid_until;
if (has_data_valid_until < obs_tow)
{
// Delete outdated data
it_sys->second.erase(prn);
}
}
}
auto it_sys_clock = d_has_clock_corrections_store_map.find("Galileo");
if (it_sys_clock != d_has_clock_corrections_store_map.end())
{
auto it_map_corr = it_sys_clock->second.find(prn);
if (it_map_corr != it_sys_clock->second.end())
{
auto has_data_valid_until = it_map_corr->second.valid_until;
if (has_data_valid_until < obs_tow)
{
// Delete outdated data
it_sys_clock->second.erase(prn);
}
}
}
}
}
}
void Rtklib_Solver::get_has_biases(const std::map<int, Gnss_Synchro> &obs_map)
{
d_has_obs_corr_map.clear();
if (!d_has_clock_corrections_store_map.empty() && !d_has_orbit_corrections_store_map.empty())
{
const std::vector<std::string> e1b_signals = {"E1-B I/NAV OS", "E1-C", "E1-B + E1-C"};
const std::vector<std::string> e6_signals = {"E6-B C/NAV HAS", "E6-C", "E6-B + E6-C"};
const std::vector<std::string> e5_signals = {"E5a-I F/NAV OS", "E5a-Q", "E5a-I+E5a-Q"};
const std::vector<std::string> e7_signals = {"E5bI I/NAV OS", "E5b-Q", "E5b-I+E5b-Q"};
const std::vector<std::string> g1c_signals = {"L1 C/A"};
const std::vector<std::string> g2s_signals = {"L2 CM", "L2 CL", "L2 CM+CL", "L2 P"};
const std::vector<std::string> g5_signals = {"L5 I", "L5 Q", "L5 I + L5 Q"};
for (const auto &it : obs_map)
{
uint32_t obs_tow = it.second.interp_TOW_ms / 1000.0;
int prn = static_cast<int>(it.second.PRN);
std::string sig(it.second.Signal, 2);
if (it.second.System == 'E')
{
auto it_sys_clock = d_has_clock_corrections_store_map.find("Galileo");
if (it_sys_clock != d_has_clock_corrections_store_map.end())
{
auto it_map_corr = it_sys_clock->second.find(prn);
if (it_map_corr != it_sys_clock->second.end())
{
if (sig == "1B")
{
for (const auto &has_signal : e1b_signals)
{
this->get_current_has_obs_correction(has_signal, obs_tow, prn);
}
}
else if (sig == "E6")
{
for (const auto &has_signal : e6_signals)
{
this->get_current_has_obs_correction(has_signal, obs_tow, prn);
}
}
else if (sig == "5X")
{
for (const auto &has_signal : e5_signals)
{
this->get_current_has_obs_correction(has_signal, obs_tow, prn);
}
}
else if (sig == "7X")
{
for (const auto &has_signal : e7_signals)
{
this->get_current_has_obs_correction(has_signal, obs_tow, prn);
}
}
}
}
}
if (it.second.System == 'G')
{
auto it_sys_clock = d_has_clock_corrections_store_map.find("GPS");
if (it_sys_clock != d_has_clock_corrections_store_map.end())
{
auto it_map_corr = it_sys_clock->second.find(prn);
if (it_map_corr != it_sys_clock->second.end())
{
if (sig == "1C")
{
for (const auto &has_signal : g1c_signals)
{
this->get_current_has_obs_correction(has_signal, obs_tow, prn);
}
}
else if (sig == "2S")
{
for (const auto &has_signal : g2s_signals)
{
this->get_current_has_obs_correction(has_signal, obs_tow, prn);
}
}
else if (sig == "L5")
{
for (const auto &has_signal : g5_signals)
{
this->get_current_has_obs_correction(has_signal, obs_tow, prn);
}
}
}
}
}
}
}
}
void Rtklib_Solver::get_current_has_obs_correction(const std::string &signal, uint32_t tow_obs, int prn)
{
auto code_bias_pair_it = this->d_has_code_bias_store_map[signal].find(prn);
if (code_bias_pair_it != this->d_has_code_bias_store_map[signal].end())
{
uint32_t valid_until = code_bias_pair_it->second.second;
if (valid_until > tow_obs)
{
this->d_has_obs_corr_map[signal][prn].code_bias_m = code_bias_pair_it->second.first;
}
}
auto phase_bias_pair_it = this->d_has_phase_bias_store_map[signal].find(prn);
if (phase_bias_pair_it != this->d_has_phase_bias_store_map[signal].end())
{
uint32_t valid_until = phase_bias_pair_it->second.second;
if (valid_until > tow_obs)
{
this->d_has_obs_corr_map[signal][prn].phase_bias_cycle = phase_bias_pair_it->second.first;
}
}
}
bool Rtklib_Solver::get_PVT(const std::map<int, Gnss_Synchro> &gnss_observables_map, bool flag_averaging, bool enable_vtl, bool close_vtl_loop) bool Rtklib_Solver::get_PVT(const std::map<int, Gnss_Synchro> &gnss_observables_map, bool flag_averaging, bool enable_vtl, bool close_vtl_loop)
{ {
std::map<int, Gnss_Synchro>::const_iterator gnss_observables_iter; std::map<int, Gnss_Synchro>::const_iterator gnss_observables_iter;
@ -599,7 +1043,7 @@ bool Rtklib_Solver::get_PVT(const std::map<int, Gnss_Synchro> &gnss_observables_
{ {
case 'G': case 'G':
{ {
const std::string sig_(gnss_observables_iter->second.Signal); const std::string sig_(gnss_observables_iter->second.Signal, 2);
if (sig_ == "1C") if (sig_ == "1C")
{ {
band1 = true; band1 = true;
@ -628,7 +1072,8 @@ bool Rtklib_Solver::get_PVT(const std::map<int, Gnss_Synchro> &gnss_observables_
{ {
case 'E': case 'E':
{ {
const std::string sig_(gnss_observables_iter->second.Signal); const std::string gal_str("Galileo");
const std::string sig_(gnss_observables_iter->second.Signal, 2);
// Galileo E1 // Galileo E1
if (sig_ == "1B") if (sig_ == "1B")
{ {
@ -637,11 +1082,14 @@ bool Rtklib_Solver::get_PVT(const std::map<int, Gnss_Synchro> &gnss_observables_
if (galileo_ephemeris_iter != galileo_ephemeris_map.cend()) if (galileo_ephemeris_iter != galileo_ephemeris_map.cend())
{ {
// convert ephemeris from GNSS-SDR class to RTKLIB structure // convert ephemeris from GNSS-SDR class to RTKLIB structure
eph_data[valid_obs] = eph_to_rtklib(galileo_ephemeris_iter->second); eph_data[valid_obs] = eph_to_rtklib(galileo_ephemeris_iter->second,
this->d_has_orbit_corrections_store_map[gal_str],
this->d_has_clock_corrections_store_map[gal_str]);
// convert observation from GNSS-SDR class to RTKLIB structure // convert observation from GNSS-SDR class to RTKLIB structure
obsd_t newobs{}; obsd_t newobs{};
d_obs_data[valid_obs + glo_valid_obs] = insert_obs_to_rtklib(newobs, d_obs_data[valid_obs + glo_valid_obs] = insert_obs_to_rtklib(newobs,
gnss_observables_iter->second, gnss_observables_iter->second,
d_has_obs_corr_map,
galileo_ephemeris_iter->second.WN, galileo_ephemeris_iter->second.WN,
d_rtklib_band_index[sig_]); d_rtklib_band_index[sig_]);
valid_obs++; valid_obs++;
@ -666,6 +1114,7 @@ bool Rtklib_Solver::get_PVT(const std::map<int, Gnss_Synchro> &gnss_observables_
{ {
d_obs_data[i + glo_valid_obs] = insert_obs_to_rtklib(d_obs_data[i + glo_valid_obs], d_obs_data[i + glo_valid_obs] = insert_obs_to_rtklib(d_obs_data[i + glo_valid_obs],
gnss_observables_iter->second, gnss_observables_iter->second,
d_has_obs_corr_map,
galileo_ephemeris_iter->second.WN, galileo_ephemeris_iter->second.WN,
d_rtklib_band_index[sig_]); d_rtklib_band_index[sig_]);
found_E1_obs = true; found_E1_obs = true;
@ -676,7 +1125,9 @@ bool Rtklib_Solver::get_PVT(const std::map<int, Gnss_Synchro> &gnss_observables_
{ {
// insert Galileo E5 obs as new obs and also insert its ephemeris // insert Galileo E5 obs as new obs and also insert its ephemeris
// convert ephemeris from GNSS-SDR class to RTKLIB structure // convert ephemeris from GNSS-SDR class to RTKLIB structure
eph_data[valid_obs] = eph_to_rtklib(galileo_ephemeris_iter->second); eph_data[valid_obs] = eph_to_rtklib(galileo_ephemeris_iter->second,
this->d_has_orbit_corrections_store_map[gal_str],
this->d_has_clock_corrections_store_map[gal_str]);
// convert observation from GNSS-SDR class to RTKLIB structure // convert observation from GNSS-SDR class to RTKLIB structure
const auto default_code_ = static_cast<unsigned char>(CODE_NONE); const auto default_code_ = static_cast<unsigned char>(CODE_NONE);
obsd_t newobs = {{0, 0}, '0', '0', {}, {}, obsd_t newobs = {{0, 0}, '0', '0', {}, {},
@ -684,6 +1135,7 @@ bool Rtklib_Solver::get_PVT(const std::map<int, Gnss_Synchro> &gnss_observables_
{}, {0.0, 0.0, 0.0}, {}}; {}, {0.0, 0.0, 0.0}, {}};
d_obs_data[valid_obs + glo_valid_obs] = insert_obs_to_rtklib(newobs, d_obs_data[valid_obs + glo_valid_obs] = insert_obs_to_rtklib(newobs,
gnss_observables_iter->second, gnss_observables_iter->second,
d_has_obs_corr_map,
galileo_ephemeris_iter->second.WN, galileo_ephemeris_iter->second.WN,
d_rtklib_band_index[sig_]); d_rtklib_band_index[sig_]);
valid_obs++; valid_obs++;
@ -706,6 +1158,7 @@ bool Rtklib_Solver::get_PVT(const std::map<int, Gnss_Synchro> &gnss_observables_
{ {
d_obs_data[i + glo_valid_obs] = insert_obs_to_rtklib(d_obs_data[i + glo_valid_obs], d_obs_data[i + glo_valid_obs] = insert_obs_to_rtklib(d_obs_data[i + glo_valid_obs],
gnss_observables_iter->second, gnss_observables_iter->second,
d_has_obs_corr_map,
galileo_ephemeris_iter->second.WN, galileo_ephemeris_iter->second.WN,
d_rtklib_band_index[sig_]); d_rtklib_band_index[sig_]);
found_E1_obs = true; found_E1_obs = true;
@ -716,7 +1169,9 @@ bool Rtklib_Solver::get_PVT(const std::map<int, Gnss_Synchro> &gnss_observables_
{ {
// insert Galileo E6 obs as new obs and also insert its ephemeris // insert Galileo E6 obs as new obs and also insert its ephemeris
// convert ephemeris from GNSS-SDR class to RTKLIB structure // convert ephemeris from GNSS-SDR class to RTKLIB structure
eph_data[valid_obs] = eph_to_rtklib(galileo_ephemeris_iter->second); eph_data[valid_obs] = eph_to_rtklib(galileo_ephemeris_iter->second,
this->d_has_orbit_corrections_store_map[gal_str],
this->d_has_clock_corrections_store_map[gal_str]);
// convert observation from GNSS-SDR class to RTKLIB structure // convert observation from GNSS-SDR class to RTKLIB structure
const auto default_code_ = static_cast<unsigned char>(CODE_NONE); const auto default_code_ = static_cast<unsigned char>(CODE_NONE);
obsd_t newobs = {{0, 0}, '0', '0', {}, {}, obsd_t newobs = {{0, 0}, '0', '0', {}, {},
@ -724,6 +1179,7 @@ bool Rtklib_Solver::get_PVT(const std::map<int, Gnss_Synchro> &gnss_observables_
{}, {0.0, 0.0, 0.0}, {}}; {}, {0.0, 0.0, 0.0}, {}};
d_obs_data[valid_obs + glo_valid_obs] = insert_obs_to_rtklib(newobs, d_obs_data[valid_obs + glo_valid_obs] = insert_obs_to_rtklib(newobs,
gnss_observables_iter->second, gnss_observables_iter->second,
d_has_obs_corr_map,
galileo_ephemeris_iter->second.WN, galileo_ephemeris_iter->second.WN,
d_rtklib_band_index[sig_]); d_rtklib_band_index[sig_]);
valid_obs++; valid_obs++;
@ -740,18 +1196,23 @@ bool Rtklib_Solver::get_PVT(const std::map<int, Gnss_Synchro> &gnss_observables_
{ {
// GPS L1 // GPS L1
// 1 GPS - find the ephemeris for the current GPS SV observation. The SV PRN ID is the map key // 1 GPS - find the ephemeris for the current GPS SV observation. The SV PRN ID is the map key
const std::string sig_(gnss_observables_iter->second.Signal); const std::string gps_str("GPS");
const std::string sig_(gnss_observables_iter->second.Signal, 2);
if (sig_ == "1C") if (sig_ == "1C")
{ {
gps_ephemeris_iter = gps_ephemeris_map.find(gnss_observables_iter->second.PRN); gps_ephemeris_iter = gps_ephemeris_map.find(gnss_observables_iter->second.PRN);
if (gps_ephemeris_iter != gps_ephemeris_map.cend()) if (gps_ephemeris_iter != gps_ephemeris_map.cend())
{ {
// convert ephemeris from GNSS-SDR class to RTKLIB structure // convert ephemeris from GNSS-SDR class to RTKLIB structure
eph_data[valid_obs] = eph_to_rtklib(gps_ephemeris_iter->second, this->is_pre_2009()); eph_data[valid_obs] = eph_to_rtklib(gps_ephemeris_iter->second,
this->d_has_orbit_corrections_store_map[gps_str],
this->d_has_clock_corrections_store_map[gps_str],
this->is_pre_2009());
// convert observation from GNSS-SDR class to RTKLIB structure // convert observation from GNSS-SDR class to RTKLIB structure
obsd_t newobs{}; obsd_t newobs{};
d_obs_data[valid_obs + glo_valid_obs] = insert_obs_to_rtklib(newobs, d_obs_data[valid_obs + glo_valid_obs] = insert_obs_to_rtklib(newobs,
gnss_observables_iter->second, gnss_observables_iter->second,
d_has_obs_corr_map,
gps_ephemeris_iter->second.WN, gps_ephemeris_iter->second.WN,
d_rtklib_band_index[sig_], d_rtklib_band_index[sig_],
this->is_pre_2009()); this->is_pre_2009());
@ -848,6 +1309,7 @@ bool Rtklib_Solver::get_PVT(const std::map<int, Gnss_Synchro> &gnss_observables_
{}, {0.0, 0.0, 0.0}, {}}; {}, {0.0, 0.0, 0.0}, {}};
d_obs_data[valid_obs + glo_valid_obs] = insert_obs_to_rtklib(newobs, d_obs_data[valid_obs + glo_valid_obs] = insert_obs_to_rtklib(newobs,
gnss_observables_iter->second, gnss_observables_iter->second,
d_has_obs_corr_map,
gps_cnav_ephemeris_iter->second.WN, gps_cnav_ephemeris_iter->second.WN,
d_rtklib_band_index[sig_]); d_rtklib_band_index[sig_]);
valid_obs++; valid_obs++;
@ -1221,7 +1683,7 @@ bool Rtklib_Solver::get_PVT(const std::map<int, Gnss_Synchro> &gnss_observables_
//To.Do: check it VTL uses all the information as in rtklib rescode function: v[nv] = P - (r + dtr - SPEED_OF_LIGHT_M_S * dts[i * 2] + dion + dtrp); //To.Do: check it VTL uses all the information as in rtklib rescode function: v[nv] = P - (r + dtr - SPEED_OF_LIGHT_M_S * dts[i * 2] + dion + dtrp);
//corrected pr with code bias, iono and tropo. Still needs the dtr(rx clock bias) and satellite clock bias (dts) //corrected pr with code bias, iono and tropo. Still needs the dtr(rx clock bias) and satellite clock bias (dts)
vtl_data.pr_m(n) = pr_corrected_code_bias_vec[n] - tropo_vec[n] - iono_vec[n] + SPEED_OF_LIGHT_M_S * dts[n * 2]; vtl_data.pr_m(n) = pr_corrected_code_bias_vec[n] - tropo_vec[n] - iono_vec[n] + SPEED_OF_LIGHT_M_S * dts[n * 2];
vtl_data.doppler_hz(n) = d_obs_data.at(n).D[0] - SPEED_OF_LIGHT_M_S *dts[1 + 2 * n] / Lambda_GPS_L1; vtl_data.doppler_hz(n) = d_obs_data.at(n).D[0] - SPEED_OF_LIGHT_M_S * dts[1 + 2 * n] / Lambda_GPS_L1;
vtl_data.carrier_phase_rads(n) = d_obs_data.at(n).L[0]; vtl_data.carrier_phase_rads(n) = d_obs_data.at(n).L[0];
vtl_data.pr_res(n) = pr_residual_vec[n]; vtl_data.pr_res(n) = pr_residual_vec[n];
} }
@ -1259,7 +1721,8 @@ bool Rtklib_Solver::get_PVT(const std::map<int, Gnss_Synchro> &gnss_observables_
// pvt_sol.rr[4] = vtl_data.kf_state[4]; // pvt_sol.rr[4] = vtl_data.kf_state[4];
// pvt_sol.rr[5] = vtl_data.kf_state[5]; // pvt_sol.rr[5] = vtl_data.kf_state[5];
} }
else{ else
{
//MAGL: the code should not enter here once the vtl has started //MAGL: the code should not enter here once the vtl has started
// .. but it does! // .. but it does!
//and not only that but pvt_sol.rr seems to have NOT reasonable values //and not only that but pvt_sol.rr seems to have NOT reasonable values
@ -1418,7 +1881,7 @@ bool Rtklib_Solver::get_PVT(const std::map<int, Gnss_Synchro> &gnss_observables_
d_dump_file.write(reinterpret_cast<char *>(&tmp_double), sizeof(double)); d_dump_file.write(reinterpret_cast<char *>(&tmp_double), sizeof(double));
tmp_double = vtl_data.rx_dts(1); tmp_double = vtl_data.rx_dts(1);
d_dump_file.write(reinterpret_cast<char *>(&tmp_double), sizeof(double)); d_dump_file.write(reinterpret_cast<char *>(&tmp_double), sizeof(double));
for (int n = 0; n<6; n++) for (int n = 0; n < 6; n++)
{ {
tmp_double = vtl_data.sat_p(n, 0); tmp_double = vtl_data.sat_p(n, 0);
d_dump_file.write(reinterpret_cast<char *>(&tmp_double), sizeof(double)); d_dump_file.write(reinterpret_cast<char *>(&tmp_double), sizeof(double));

View File

@ -4,7 +4,7 @@
* data flow and structures * data flow and structures
* \authors <ul> * \authors <ul>
* <li> 2017, Javier Arribas * <li> 2017, Javier Arribas
* <li> 2017, Carles Fernandez * <li> 2017-2023, Carles Fernandez
* <li> 2007-2013, T. Takasu * <li> 2007-2013, T. Takasu
* </ul> * </ul>
* *
@ -23,7 +23,7 @@
* ----------------------------------------------------------------------------- * -----------------------------------------------------------------------------
* Copyright (C) 2007-2013, T. Takasu * Copyright (C) 2007-2013, T. Takasu
* Copyright (C) 2017-2019, Javier Arribas * Copyright (C) 2017-2019, Javier Arribas
* Copyright (C) 2017-2019, Carles Fernandez * Copyright (C) 2017-2023, Carles Fernandez
* All rights reserved. * All rights reserved.
* *
* SPDX-License-Identifier: BSD-2-Clause * SPDX-License-Identifier: BSD-2-Clause
@ -41,6 +41,7 @@
#include "beidou_dnav_utc_model.h" #include "beidou_dnav_utc_model.h"
#include "galileo_almanac.h" #include "galileo_almanac.h"
#include "galileo_ephemeris.h" #include "galileo_ephemeris.h"
#include "galileo_has_data.h"
#include "galileo_iono.h" #include "galileo_iono.h"
#include "galileo_utc_model.h" #include "galileo_utc_model.h"
#include "glonass_gnav_almanac.h" #include "glonass_gnav_almanac.h"
@ -57,6 +58,7 @@
#include "monitor_pvt.h" #include "monitor_pvt.h"
#include "pvt_solution.h" #include "pvt_solution.h"
#include "rtklib.h" #include "rtklib.h"
#include "rtklib_conversions.h"
#include "vtl_data.h" #include "vtl_data.h"
#include "vtl_engine.h" #include "vtl_engine.h"
#include <array> #include <array>
@ -64,6 +66,7 @@
#include <fstream> #include <fstream>
#include <map> #include <map>
#include <string> #include <string>
#include <utility>
/** \addtogroup PVT /** \addtogroup PVT
* \{ */ * \{ */
@ -95,6 +98,8 @@ public:
double get_pdop() const override; double get_pdop() const override;
double get_gdop() const override; double get_gdop() const override;
Monitor_Pvt get_monitor_pvt() const; Monitor_Pvt get_monitor_pvt() const;
void store_has_data(const Galileo_HAS_data& new_has_data);
void update_has_corrections(const std::map<int, Gnss_Synchro>& obs_map);
sol_t pvt_sol{}; sol_t pvt_sol{};
std::array<ssat_t, MAXSAT> pvt_ssat{}; std::array<ssat_t, MAXSAT> pvt_ssat{};
@ -128,10 +133,23 @@ public:
private: private:
bool save_matfile() const; bool save_matfile() const;
void check_has_orbit_clock_validity(const std::map<int, Gnss_Synchro>& obs_map);
void get_has_biases(const std::map<int, Gnss_Synchro>& obs_map);
void get_current_has_obs_correction(const std::string& signal, uint32_t tow_obs, int prn);
std::array<obsd_t, MAXOBS> d_obs_data{}; std::array<obsd_t, MAXOBS> d_obs_data{};
std::array<double, 4> d_dop{}; std::array<double, 4> d_dop{};
std::map<int, int> d_rtklib_freq_index; std::map<int, int> d_rtklib_freq_index;
std::map<std::string, int> d_rtklib_band_index; std::map<std::string, int> d_rtklib_band_index;
std::map<std::string, std::map<int, HAS_orbit_corrections>> d_has_orbit_corrections_store_map; // first key is system, second key is PRN
std::map<std::string, std::map<int, HAS_clock_corrections>> d_has_clock_corrections_store_map; // first key is system, second key is PRN
std::map<std::string, std::map<int, std::pair<float, uint32_t>>> d_has_code_bias_store_map; // first key is signal, second key is PRN
std::map<std::string, std::map<int, std::pair<float, uint32_t>>> d_has_phase_bias_store_map; // first key is signal, second key is PRN
std::map<std::string, std::map<int, HAS_obs_corrections>> d_has_obs_corr_map; // first key is signal, second key is PRN
std::string d_dump_filename; std::string d_dump_filename;
std::ofstream d_dump_file; std::ofstream d_dump_file;
rtk_t d_rtk{}; rtk_t d_rtk{};

View File

@ -4,7 +4,7 @@
* \authors <ul> * \authors <ul>
* <li> 2007-2013, T. Takasu * <li> 2007-2013, T. Takasu
* <li> 2017, Javier Arribas * <li> 2017, Javier Arribas
* <li> 2017, Carles Fernandez * <li> 2017-2023, Carles Fernandez
* </ul> * </ul>
* *
* This is a derived work from RTKLIB http://www.rtklib.com/ * This is a derived work from RTKLIB http://www.rtklib.com/
@ -22,7 +22,7 @@
* ----------------------------------------------------------------------------- * -----------------------------------------------------------------------------
* Copyright (C) 2007-2013, T. Takasu * Copyright (C) 2007-2013, T. Takasu
* Copyright (C) 2017, Javier Arribas * Copyright (C) 2017, Javier Arribas
* Copyright (C) 2017, Carles Fernandez * Copyright (C) 2017-2023, Carles Fernandez
* All rights reserved. * All rights reserved.
* *
* SPDX-License-Identifier: BSD-2-Clause * SPDX-License-Identifier: BSD-2-Clause
@ -451,6 +451,11 @@ typedef struct
/* BDS :tgd[0]=BGD1,tgd[1]=BGD2 */ /* BDS :tgd[0]=BGD1,tgd[1]=BGD2 */
double isc[4]; /* GPS :isc[0]=ISCL1, isc[1]=ISCL2, isc[2]=ISCL5I, isc[3]=ISCL5Q */ double isc[4]; /* GPS :isc[0]=ISCL1, isc[1]=ISCL2, isc[2]=ISCL5I, isc[3]=ISCL5Q */
double Adot, ndot; /* Adot,ndot for CNAV */ double Adot, ndot; /* Adot,ndot for CNAV */
float has_clock_correction_m; /* Galileo High Accuracy Service clock correction, in [m] */
float has_orbit_radial_correction_m; /* Galileo High Accuracy Service orbit radial correction, in [m] */
float has_orbit_in_track_correction_m; /* Galileo High Accuracy Service orbit in-track correction, in [m] */
float has_orbit_cross_track_correction_m; /* Galileo High Accuracy Service orbit cross-track correction, in [m] */
bool apply_has_corrections;
} eph_t; } eph_t;

View File

@ -28,13 +28,17 @@
#include "gps_ephemeris.h" // for Gps_Ephemeris #include "gps_ephemeris.h" // for Gps_Ephemeris
#include "rtklib_rtkcmn.h" #include "rtklib_rtkcmn.h"
#include <cmath> #include <cmath>
#include <cstdint>
#include <string>
obsd_t insert_obs_to_rtklib(obsd_t& rtklib_obs, const Gnss_Synchro& gnss_synchro, int week, int band, bool pre_2009_file)
obsd_t insert_obs_to_rtklib(obsd_t& rtklib_obs,
const Gnss_Synchro& gnss_synchro,
const std::map<std::string, std::map<int, HAS_obs_corrections>>& has_obs_corr,
int week,
int band,
bool pre_2009_file)
{ {
// Get signal type info to adjust code type based on constellation // Get signal type info to adjust code type based on constellation
std::string sig_ = gnss_synchro.Signal; const std::string sig_(gnss_synchro.Signal, 2);
rtklib_obs.D[band] = gnss_synchro.Carrier_Doppler_hz; rtklib_obs.D[band] = gnss_synchro.Carrier_Doppler_hz;
rtklib_obs.P[band] = gnss_synchro.Pseudorange_m; rtklib_obs.P[band] = gnss_synchro.Pseudorange_m;
@ -127,10 +131,275 @@ obsd_t insert_obs_to_rtklib(obsd_t& rtklib_obs, const Gnss_Synchro& gnss_synchro
} }
rtklib_obs.rcv = 1; rtklib_obs.rcv = 1;
if (!has_obs_corr.empty())
{
float has_pseudorange_correction_m = 0.0;
float has_bias_correction_cycle = 0.0;
switch (gnss_synchro.System)
{
case 'G':
{
if (sig_ == "1C")
{
const auto it = has_obs_corr.find("L1 C/A");
if (it != has_obs_corr.cend())
{
const auto it2 = it->second.find(static_cast<int>(gnss_synchro.PRN));
if (it2 != it->second.cend())
{
has_pseudorange_correction_m = it2->second.code_bias_m;
has_bias_correction_cycle = it2->second.phase_bias_cycle;
}
}
}
else if (sig_ == "2S")
{
const auto it = has_obs_corr.find("L2 CM");
if (it != has_obs_corr.cend())
{
const auto it2 = it->second.find(static_cast<int>(gnss_synchro.PRN));
if (it2 != it->second.cend())
{
has_pseudorange_correction_m = it2->second.code_bias_m;
has_bias_correction_cycle = it2->second.phase_bias_cycle;
}
}
}
else if (sig_ == "L5")
{
// TODO: determine which one
const auto it = has_obs_corr.find("L5 I");
if (it != has_obs_corr.cend())
{
const auto it2 = it->second.find(static_cast<int>(gnss_synchro.PRN));
if (it2 != it->second.cend())
{
has_pseudorange_correction_m = it2->second.code_bias_m;
has_bias_correction_cycle = it2->second.phase_bias_cycle;
}
}
else
{
const auto it_2nd_attempt = has_obs_corr.find("L5 Q");
if (it_2nd_attempt != has_obs_corr.cend())
{
const auto it2 = it_2nd_attempt->second.find(static_cast<int>(gnss_synchro.PRN));
if (it2 != it_2nd_attempt->second.cend())
{
has_pseudorange_correction_m = it2->second.code_bias_m;
has_bias_correction_cycle = it2->second.phase_bias_cycle;
}
}
else
{
const auto it_3rd_attempt = has_obs_corr.find("L5 I + L5 Q");
if (it_3rd_attempt != has_obs_corr.cend())
{
const auto it2 = it_3rd_attempt->second.find(static_cast<int>(gnss_synchro.PRN));
if (it2 != it_3rd_attempt->second.cend())
{
has_pseudorange_correction_m = it2->second.code_bias_m;
has_bias_correction_cycle = it2->second.phase_bias_cycle;
}
}
}
}
}
}
break;
case 'E':
{
if (sig_ == "1B")
{
// TODO: determine which one
const auto it = has_obs_corr.find("E1-B I/NAV OS");
if (it != has_obs_corr.cend())
{
const auto it2 = it->second.find(static_cast<int>(gnss_synchro.PRN));
if (it2 != it->second.cend())
{
has_pseudorange_correction_m = it2->second.code_bias_m;
has_bias_correction_cycle = it2->second.phase_bias_cycle;
}
}
else
{
const auto it_2nd_attempt = has_obs_corr.find("E1-C");
if (it_2nd_attempt != has_obs_corr.cend())
{
const auto it2 = it_2nd_attempt->second.find(static_cast<int>(gnss_synchro.PRN));
if (it2 != it_2nd_attempt->second.cend())
{
has_pseudorange_correction_m = it2->second.code_bias_m;
has_bias_correction_cycle = it2->second.phase_bias_cycle;
}
}
else
{
const auto it_3rd_attempt = has_obs_corr.find("E1-B + E1-C");
if (it_3rd_attempt != has_obs_corr.cend())
{
const auto it2 = it_3rd_attempt->second.find(static_cast<int>(gnss_synchro.PRN));
if (it2 != it_3rd_attempt->second.cend())
{
has_pseudorange_correction_m = it2->second.code_bias_m;
has_bias_correction_cycle = it2->second.phase_bias_cycle;
}
}
}
}
}
else if (sig_ == "5X")
{
// TODO: determine which one
const auto it = has_obs_corr.find("E5a-I F/NAV OS");
if (it != has_obs_corr.cend())
{
const auto it2 = it->second.find(static_cast<int>(gnss_synchro.PRN));
if (it2 != it->second.cend())
{
has_pseudorange_correction_m = it2->second.code_bias_m;
has_bias_correction_cycle = it2->second.phase_bias_cycle;
}
}
else
{
const auto it_2nd_attempt = has_obs_corr.find("E5a-Q");
if (it_2nd_attempt != has_obs_corr.cend())
{
const auto it2 = it_2nd_attempt->second.find(static_cast<int>(gnss_synchro.PRN));
if (it2 != it_2nd_attempt->second.cend())
{
has_pseudorange_correction_m = it2->second.code_bias_m;
has_bias_correction_cycle = it2->second.phase_bias_cycle;
}
}
else
{
const auto it_3rd_attempt = has_obs_corr.find("E5a-I+E5a-Q");
if (it_3rd_attempt != has_obs_corr.cend())
{
const auto it2 = it_3rd_attempt->second.find(static_cast<int>(gnss_synchro.PRN));
if (it2 != it_3rd_attempt->second.cend())
{
has_pseudorange_correction_m = it2->second.code_bias_m;
has_bias_correction_cycle = it2->second.phase_bias_cycle;
}
}
}
}
}
else if (sig_ == "7X")
{
// TODO: determine which one
const auto it = has_obs_corr.find("E5bI I/NAV OS");
if (it != has_obs_corr.cend())
{
const auto it2 = it->second.find(static_cast<int>(gnss_synchro.PRN));
if (it2 != it->second.cend())
{
has_pseudorange_correction_m = it2->second.code_bias_m;
has_bias_correction_cycle = it2->second.phase_bias_cycle;
}
}
else
{
const auto it_2nd_attempt = has_obs_corr.find("E5b-Q");
if (it_2nd_attempt != has_obs_corr.cend())
{
const auto it2 = it_2nd_attempt->second.find(static_cast<int>(gnss_synchro.PRN));
if (it2 != it_2nd_attempt->second.cend())
{
has_pseudorange_correction_m = it2->second.code_bias_m;
has_bias_correction_cycle = it2->second.phase_bias_cycle;
}
}
else
{
const auto it_3rd_attempt = has_obs_corr.find("E5b-I+E5b-Q");
if (it_3rd_attempt != has_obs_corr.cend())
{
const auto it2 = it_3rd_attempt->second.find(static_cast<int>(gnss_synchro.PRN));
if (it2 != it_3rd_attempt->second.cend())
{
has_pseudorange_correction_m = it2->second.code_bias_m;
has_bias_correction_cycle = it2->second.phase_bias_cycle;
}
}
}
}
}
else if (sig_ == "6B")
{
// TODO: determine which one
const auto it = has_obs_corr.find("E6-B C/NAV HAS");
if (it != has_obs_corr.cend())
{
const auto it2 = it->second.find(static_cast<int>(gnss_synchro.PRN));
if (it2 != it->second.cend())
{
has_pseudorange_correction_m = it2->second.code_bias_m;
has_bias_correction_cycle = it2->second.phase_bias_cycle;
}
}
else
{
const auto it_2nd_attempt = has_obs_corr.find("E6-C");
if (it_2nd_attempt != has_obs_corr.cend())
{
const auto it2 = it_2nd_attempt->second.find(static_cast<int>(gnss_synchro.PRN));
if (it2 != it_2nd_attempt->second.cend())
{
has_pseudorange_correction_m = it2->second.code_bias_m;
has_bias_correction_cycle = it2->second.phase_bias_cycle;
}
}
else
{
const auto it_3rd_attempt = has_obs_corr.find("E6-B + E6-C");
if (it_3rd_attempt != has_obs_corr.cend())
{
const auto it2 = it_3rd_attempt->second.find(static_cast<int>(gnss_synchro.PRN));
if (it2 != it_3rd_attempt->second.cend())
{
has_pseudorange_correction_m = it2->second.code_bias_m;
has_bias_correction_cycle = it2->second.phase_bias_cycle;
}
}
}
}
}
}
break;
default:
break;
}
rtklib_obs.P[band] += has_pseudorange_correction_m;
rtklib_obs.L[band] += has_bias_correction_cycle;
}
return rtklib_obs; return rtklib_obs;
} }
obsd_t insert_obs_to_rtklib(obsd_t& rtklib_obs,
const Gnss_Synchro& gnss_synchro,
int week,
int band,
bool pre_2009_file)
{
std::map<std::string, std::map<int, HAS_obs_corrections>> empty_map;
return insert_obs_to_rtklib(rtklib_obs,
gnss_synchro,
empty_map,
week,
band,
pre_2009_file);
}
geph_t eph_to_rtklib(const Glonass_Gnav_Ephemeris& glonass_gnav_eph, const Glonass_Gnav_Utc_Model& gnav_clock_model) geph_t eph_to_rtklib(const Glonass_Gnav_Ephemeris& glonass_gnav_eph, const Glonass_Gnav_Utc_Model& gnav_clock_model)
{ {
int week; int week;
@ -172,9 +441,19 @@ geph_t eph_to_rtklib(const Glonass_Gnav_Ephemeris& glonass_gnav_eph, const Glona
eph_t eph_to_rtklib(const Galileo_Ephemeris& gal_eph) eph_t eph_to_rtklib(const Galileo_Ephemeris& gal_eph)
{
std::map<int, HAS_orbit_corrections> empty_orbit_map;
std::map<int, HAS_clock_corrections> empty_clock_map;
return eph_to_rtklib(gal_eph, empty_orbit_map, empty_clock_map);
}
eph_t eph_to_rtklib(const Galileo_Ephemeris& gal_eph,
const std::map<int, HAS_orbit_corrections>& orbit_correction_map,
const std::map<int, HAS_clock_corrections>& clock_correction_map)
{ {
eph_t rtklib_sat = {0, 0, 0, 0, 0, 0, 0, 0, {0, 0}, {0, 0}, {0, 0}, 0.0, 0.0, 0.0, 0.0, 0.0, eph_t rtklib_sat = {0, 0, 0, 0, 0, 0, 0, 0, {0, 0}, {0, 0}, {0, 0}, 0.0, 0.0, 0.0, 0.0, 0.0,
0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, {}, {}, 0.0, 0.0}; 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, {}, {}, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, false};
// Galileo is the third satellite system for RTKLIB, so, add the required offset to discriminate Galileo ephemeris // Galileo is the third satellite system for RTKLIB, so, add the required offset to discriminate Galileo ephemeris
rtklib_sat.sat = gal_eph.PRN + NSATGPS + NSATGLO; rtklib_sat.sat = gal_eph.PRN + NSATGPS + NSATGLO;
rtklib_sat.A = gal_eph.sqrtA * gal_eph.sqrtA; rtklib_sat.A = gal_eph.sqrtA * gal_eph.sqrtA;
@ -226,14 +505,54 @@ eph_t eph_to_rtklib(const Galileo_Ephemeris& gal_eph)
rtklib_sat.toc = gpst2time(rtklib_sat.week, toc); rtklib_sat.toc = gpst2time(rtklib_sat.week, toc);
rtklib_sat.ttr = gpst2time(rtklib_sat.week, tow); rtklib_sat.ttr = gpst2time(rtklib_sat.week, tow);
if (!orbit_correction_map.empty() && !clock_correction_map.empty())
{
int count_has_corrections = 0;
const auto it_orbit = orbit_correction_map.find(static_cast<int>(gal_eph.PRN));
if (it_orbit != orbit_correction_map.cend())
{
rtklib_sat.has_orbit_radial_correction_m = it_orbit->second.radial_m;
rtklib_sat.has_orbit_in_track_correction_m = it_orbit->second.in_track_m;
rtklib_sat.has_orbit_cross_track_correction_m = it_orbit->second.cross_track_m;
count_has_corrections++;
}
const auto it_clock = clock_correction_map.find(static_cast<int>(gal_eph.PRN));
if (it_clock != clock_correction_map.cend())
{
rtklib_sat.has_clock_correction_m = it_clock->second.clock_correction_m;
count_has_corrections++;
}
rtklib_sat.apply_has_corrections = (count_has_corrections == 2) ? true : false;
if (rtklib_sat.apply_has_corrections)
{
rtklib_sat.tgd[0] = 0.0;
rtklib_sat.tgd[1] = 0.0;
}
}
else
{
rtklib_sat.apply_has_corrections = false;
}
return rtklib_sat; return rtklib_sat;
} }
eph_t eph_to_rtklib(const Gps_Ephemeris& gps_eph, bool pre_2009_file) eph_t eph_to_rtklib(const Gps_Ephemeris& gps_eph, bool pre_2009_file)
{
std::map<int, HAS_orbit_corrections> empty_orbit_map;
std::map<int, HAS_clock_corrections> empty_clock_map;
return eph_to_rtklib(gps_eph, empty_orbit_map, empty_clock_map, pre_2009_file);
}
eph_t eph_to_rtklib(const Gps_Ephemeris& gps_eph,
const std::map<int, HAS_orbit_corrections>& orbit_correction_map,
const std::map<int, HAS_clock_corrections>& clock_correction_map,
bool pre_2009_file)
{ {
eph_t rtklib_sat = {0, 0, 0, 0, 0, 0, 0, 0, {0, 0}, {0, 0}, {0, 0}, 0.0, 0.0, 0.0, 0.0, 0.0, eph_t rtklib_sat = {0, 0, 0, 0, 0, 0, 0, 0, {0, 0}, {0, 0}, {0, 0}, 0.0, 0.0, 0.0, 0.0, 0.0,
0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, {}, {}, 0.0, 0.0}; 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, {}, {}, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, false};
rtklib_sat.sat = gps_eph.PRN; rtklib_sat.sat = gps_eph.PRN;
rtklib_sat.A = gps_eph.sqrtA * gps_eph.sqrtA; rtklib_sat.A = gps_eph.sqrtA * gps_eph.sqrtA;
rtklib_sat.M0 = gps_eph.M_0; rtklib_sat.M0 = gps_eph.M_0;
@ -284,6 +603,40 @@ eph_t eph_to_rtklib(const Gps_Ephemeris& gps_eph, bool pre_2009_file)
rtklib_sat.toc = gpst2time(rtklib_sat.week, toc); rtklib_sat.toc = gpst2time(rtklib_sat.week, toc);
rtklib_sat.ttr = gpst2time(rtklib_sat.week, tow); rtklib_sat.ttr = gpst2time(rtklib_sat.week, tow);
if (!orbit_correction_map.empty() && !clock_correction_map.empty())
{
int count_has_corrections = 0;
const auto it_orbit = orbit_correction_map.find(static_cast<int>(gps_eph.PRN));
if (it_orbit != orbit_correction_map.cend())
{
rtklib_sat.has_orbit_radial_correction_m = it_orbit->second.radial_m;
rtklib_sat.has_orbit_in_track_correction_m = it_orbit->second.in_track_m;
rtklib_sat.has_orbit_cross_track_correction_m = it_orbit->second.cross_track_m;
count_has_corrections++;
}
const auto it_clock = clock_correction_map.find(static_cast<int>(gps_eph.PRN));
if (it_clock != clock_correction_map.cend())
{
rtklib_sat.has_clock_correction_m = it_clock->second.clock_correction_m;
count_has_corrections++;
}
rtklib_sat.apply_has_corrections = (count_has_corrections == 2) ? true : false;
if (rtklib_sat.apply_has_corrections)
{
rtklib_sat.tgd[0] = 0.0;
rtklib_sat.tgd[1] = 0.0;
}
}
else
{
rtklib_sat.has_orbit_radial_correction_m = 0.0;
rtklib_sat.has_orbit_in_track_correction_m = 0.0;
rtklib_sat.has_orbit_cross_track_correction_m = 0.0;
rtklib_sat.has_clock_correction_m = 0.0;
rtklib_sat.apply_has_corrections = false;
}
return rtklib_sat; return rtklib_sat;
} }
@ -291,7 +644,7 @@ eph_t eph_to_rtklib(const Gps_Ephemeris& gps_eph, bool pre_2009_file)
eph_t eph_to_rtklib(const Beidou_Dnav_Ephemeris& bei_eph) eph_t eph_to_rtklib(const Beidou_Dnav_Ephemeris& bei_eph)
{ {
eph_t rtklib_sat = {0, 0, 0, 0, 0, 0, 0, 0, {0, 0}, {0, 0}, {0, 0}, 0.0, 0.0, 0.0, 0.0, 0.0, eph_t rtklib_sat = {0, 0, 0, 0, 0, 0, 0, 0, {0, 0}, {0, 0}, {0, 0}, 0.0, 0.0, 0.0, 0.0, 0.0,
0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, {}, {}, 0.0, 0.0}; 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, {}, {}, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, false};
rtklib_sat.sat = bei_eph.PRN + NSATGPS + NSATGLO + NSATGAL + NSATQZS; rtklib_sat.sat = bei_eph.PRN + NSATGPS + NSATGLO + NSATGAL + NSATQZS;
rtklib_sat.A = bei_eph.sqrtA * bei_eph.sqrtA; rtklib_sat.A = bei_eph.sqrtA * bei_eph.sqrtA;
rtklib_sat.M0 = bei_eph.M_0; rtklib_sat.M0 = bei_eph.M_0;
@ -353,6 +706,12 @@ eph_t eph_to_rtklib(const Beidou_Dnav_Ephemeris& bei_eph)
rtklib_sat.toc = gpst2time(rtklib_sat.week, toc); rtklib_sat.toc = gpst2time(rtklib_sat.week, toc);
rtklib_sat.ttr = gpst2time(rtklib_sat.week, tow); rtklib_sat.ttr = gpst2time(rtklib_sat.week, tow);
rtklib_sat.has_orbit_radial_correction_m = 0.0;
rtklib_sat.has_orbit_in_track_correction_m = 0.0;
rtklib_sat.has_orbit_cross_track_correction_m = 0.0;
rtklib_sat.has_clock_correction_m = 0.0;
rtklib_sat.apply_has_corrections = false;
return rtklib_sat; return rtklib_sat;
} }
@ -360,7 +719,7 @@ eph_t eph_to_rtklib(const Beidou_Dnav_Ephemeris& bei_eph)
eph_t eph_to_rtklib(const Gps_CNAV_Ephemeris& gps_cnav_eph) eph_t eph_to_rtklib(const Gps_CNAV_Ephemeris& gps_cnav_eph)
{ {
eph_t rtklib_sat = {0, 0, 0, 0, 0, 0, 0, 0, {0, 0}, {0, 0}, {0, 0}, 0.0, 0.0, 0.0, 0.0, 0.0, eph_t rtklib_sat = {0, 0, 0, 0, 0, 0, 0, 0, {0, 0}, {0, 0}, {0, 0}, 0.0, 0.0, 0.0, 0.0, 0.0,
0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, {}, {}, 0.0, 0.0}; 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, {}, {}, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, false};
rtklib_sat.sat = gps_cnav_eph.PRN; rtklib_sat.sat = gps_cnav_eph.PRN;
rtklib_sat.A = gps_cnav_eph.sqrtA * gps_cnav_eph.sqrtA; rtklib_sat.A = gps_cnav_eph.sqrtA * gps_cnav_eph.sqrtA;
rtklib_sat.M0 = gps_cnav_eph.M_0; rtklib_sat.M0 = gps_cnav_eph.M_0;
@ -415,6 +774,12 @@ eph_t eph_to_rtklib(const Gps_CNAV_Ephemeris& gps_cnav_eph)
rtklib_sat.toc = gpst2time(rtklib_sat.week, toc); rtklib_sat.toc = gpst2time(rtklib_sat.week, toc);
rtklib_sat.ttr = gpst2time(rtklib_sat.week, tow); rtklib_sat.ttr = gpst2time(rtklib_sat.week, tow);
rtklib_sat.has_orbit_radial_correction_m = 0.0;
rtklib_sat.has_orbit_in_track_correction_m = 0.0;
rtklib_sat.has_orbit_cross_track_correction_m = 0.0;
rtklib_sat.has_clock_correction_m = 0.0;
rtklib_sat.apply_has_corrections = false;
return rtklib_sat; return rtklib_sat;
} }

View File

@ -18,6 +18,9 @@
#define GNSS_SDR_RTKLIB_CONVERSIONS_H #define GNSS_SDR_RTKLIB_CONVERSIONS_H
#include "rtklib.h" #include "rtklib.h"
#include <cstdint>
#include <map>
#include <string>
/** \addtogroup PVT /** \addtogroup PVT
* \{ */ * \{ */
@ -35,8 +38,48 @@ class Gps_Almanac;
class Gps_CNAV_Ephemeris; class Gps_CNAV_Ephemeris;
class Gps_Ephemeris; class Gps_Ephemeris;
class HAS_clock_corrections
{
public:
HAS_clock_corrections() = default;
float clock_correction_m{};
uint32_t valid_until{};
};
class HAS_orbit_corrections
{
public:
HAS_orbit_corrections() = default;
float radial_m{};
float in_track_m{};
float cross_track_m{};
uint32_t valid_until{};
uint16_t iod{};
};
class HAS_obs_corrections
{
public:
HAS_obs_corrections() = default;
float code_bias_m{};
float phase_bias_cycle{};
};
eph_t eph_to_rtklib(const Galileo_Ephemeris& gal_eph); eph_t eph_to_rtklib(const Galileo_Ephemeris& gal_eph);
eph_t eph_to_rtklib(const Gps_Ephemeris& gps_eph, bool pre_2009_file);
eph_t eph_to_rtklib(const Galileo_Ephemeris& gal_eph,
const std::map<int, HAS_orbit_corrections>& orbit_correction_map,
const std::map<int, HAS_clock_corrections>& clock_correction_map);
eph_t eph_to_rtklib(const Gps_Ephemeris& gps_eph,
bool pre_2009_file = false);
eph_t eph_to_rtklib(const Gps_Ephemeris& gps_eph,
const std::map<int, HAS_orbit_corrections>& orbit_correction_map,
const std::map<int, HAS_clock_corrections>& clock_correction_map,
bool pre_2009_file = false);
eph_t eph_to_rtklib(const Gps_CNAV_Ephemeris& gps_cnav_eph); eph_t eph_to_rtklib(const Gps_CNAV_Ephemeris& gps_cnav_eph);
eph_t eph_to_rtklib(const Beidou_Dnav_Ephemeris& bei_eph); eph_t eph_to_rtklib(const Beidou_Dnav_Ephemeris& bei_eph);
@ -50,6 +93,13 @@ alm_t alm_to_rtklib(const Galileo_Almanac& gal_alm);
*/ */
geph_t eph_to_rtklib(const Glonass_Gnav_Ephemeris& glonass_gnav_eph, const Glonass_Gnav_Utc_Model& gnav_clock_model); geph_t eph_to_rtklib(const Glonass_Gnav_Ephemeris& glonass_gnav_eph, const Glonass_Gnav_Utc_Model& gnav_clock_model);
obsd_t insert_obs_to_rtklib(obsd_t& rtklib_obs,
const Gnss_Synchro& gnss_synchro,
const std::map<std::string, std::map<int, HAS_obs_corrections>>& has_obs_corr,
int week,
int band,
bool pre_2009_file = false);
obsd_t insert_obs_to_rtklib(obsd_t& rtklib_obs, const Gnss_Synchro& gnss_synchro, int week, int band, bool pre_2009_file = false); obsd_t insert_obs_to_rtklib(obsd_t& rtklib_obs, const Gnss_Synchro& gnss_synchro, int week, int band, bool pre_2009_file = false);

View File

@ -4,7 +4,7 @@
* \authors <ul> * \authors <ul>
* <li> 2007-2013, T. Takasu * <li> 2007-2013, T. Takasu
* <li> 2017, Javier Arribas * <li> 2017, Javier Arribas
* <li> 2017, Carles Fernandez * <li> 2017-2023, Carles Fernandez
* </ul> * </ul>
* *
* This is a derived work from RTKLIB http://www.rtklib.com/ * This is a derived work from RTKLIB http://www.rtklib.com/
@ -22,7 +22,7 @@
* ----------------------------------------------------------------------------- * -----------------------------------------------------------------------------
* Copyright (C) 2007-2013, T. Takasu * Copyright (C) 2007-2013, T. Takasu
* Copyright (C) 2017, Javier Arribas * Copyright (C) 2017, Javier Arribas
* Copyright (C) 2017, Carles Fernandez * Copyright (C) 2017-2023, Carles Fernandez
* All rights reserved. * All rights reserved.
* *
* SPDX-License-Identifier: BSD-2-Clause * SPDX-License-Identifier: BSD-2-Clause
@ -231,6 +231,7 @@ void eph2pos(gtime_t time, const eph_t *eph, double *rs, double *dts,
int sys; int sys;
int prn; int prn;
double has_relativistic_correction = 0.0;
trace(4, "eph2pos : time=%s sat=%2d\n", time_str(time, 3), eph->sat); trace(4, "eph2pos : time=%s sat=%2d\n", time_str(time, 3), eph->sat);
if (eph->A <= 0.0) if (eph->A <= 0.0)
@ -307,12 +308,102 @@ void eph2pos(gtime_t time, const eph_t *eph, double *rs, double *dts,
rs[0] = x * cosO - y * cosi * sinO; rs[0] = x * cosO - y * cosi * sinO;
rs[1] = x * sinO + y * cosi * cosO; rs[1] = x * sinO + y * cosi * cosO;
rs[2] = y * sin(i); rs[2] = y * sin(i);
// Apply HAS orbit correction if available
if (eph->apply_has_corrections)
{
// HAS SIS ICD, Issue 1.0, Section 7.2
double vel_sat[3]{};
double cross_pos_vel[3]{};
double et[3]{};
double ew[3]{};
double en[3]{};
double R[3][3]{};
double corrections[3]{};
double rotated_corrections[3]{};
// Compute satellite velocity
const double OneMinusecosE = 1.0 - (eph->e * cosE);
const double ekdot = (sqrt(mu / (eph->A * eph->A * eph->A)) + eph->deln) / OneMinusecosE;
const double pkdot = sqrt(1.0 - eph->e * eph->e) * ekdot / OneMinusecosE;
const double ukdot = pkdot * (1.0 + 2.0 * (eph->cus * cos2u - eph->cuc * sin2u));
const double ikdot = eph->idot + 2.0 * pkdot * (eph->cis * cos2u - eph->cic * sin2u);
const double rkdot = eph->A * eph->e * sinE * ekdot + 2.0 * pkdot * (eph->crs * cos2u - eph->crc * sin2u);
const double xpkdot = rkdot * cos(u) - y * ukdot;
const double ypkdot = rkdot * sin(u) + x * ukdot;
const double tmp = ypkdot * cosi - rs[2] * ikdot;
vel_sat[0] = -(eph->OMGd - omge) * rs[1] + xpkdot * cosO - tmp * sinO;
vel_sat[1] = (eph->OMGd - omge) * rs[0] + xpkdot * sinO + tmp * cosO;
vel_sat[2] = y * cosi * ikdot + ypkdot * sin(i);
// Compute HAS relativistic clock correction (HAS SIS ICD, Issue 1.0, Section 7.3)
const double pos_by_vel = rs[0] * vel_sat[0] + rs[1] * vel_sat[1] + rs[2] * vel_sat[2];
has_relativistic_correction = -(2.0 * pos_by_vel) / (SPEED_OF_LIGHT_M_S * SPEED_OF_LIGHT_M_S);
// Compute rotation matrix
const double norm_velocity = sqrt(vel_sat[0] * vel_sat[0] + vel_sat[1] * vel_sat[1] + vel_sat[2] * vel_sat[2]);
et[0] = vel_sat[0] / norm_velocity;
et[1] = vel_sat[1] / norm_velocity;
et[2] = vel_sat[2] / norm_velocity;
cross_pos_vel[0] = rs[1] * vel_sat[2] - rs[2] * vel_sat[1];
cross_pos_vel[1] = rs[2] * vel_sat[0] - rs[0] * vel_sat[2];
cross_pos_vel[2] = rs[0] * vel_sat[1] - rs[1] * vel_sat[0];
const double norm_cross_pos_vel = sqrt(cross_pos_vel[0] * cross_pos_vel[0] + cross_pos_vel[1] * cross_pos_vel[1] + cross_pos_vel[2] * cross_pos_vel[2]);
ew[0] = cross_pos_vel[0] / norm_cross_pos_vel;
ew[1] = cross_pos_vel[1] / norm_cross_pos_vel;
ew[2] = cross_pos_vel[2] / norm_cross_pos_vel;
en[0] = et[1] * ew[2] - et[2] * ew[1];
en[1] = et[2] * ew[0] - et[0] * ew[2];
en[2] = et[0] * ew[1] - et[1] * ew[0];
R[0][0] = en[0];
R[0][1] = et[0];
R[0][2] = ew[0];
R[1][0] = en[1];
R[1][1] = et[1];
R[1][2] = ew[1];
R[2][0] = en[2];
R[2][1] = et[2];
R[2][2] = ew[2];
// Compute rotated corrections
corrections[0] = eph->has_orbit_radial_correction_m;
corrections[1] = eph->has_orbit_in_track_correction_m;
corrections[2] = eph->has_orbit_cross_track_correction_m;
for (int row = 0; row < 3; row++)
{
for (int col = 0; col < 3; col++)
{
rotated_corrections[row] = R[row][col] * corrections[col];
}
}
// Apply HAS orbit corrections
rs[0] += rotated_corrections[0];
rs[1] += rotated_corrections[1];
rs[2] += rotated_corrections[2];
}
} }
tk = timediffweekcrossover(time, eph->toc); tk = timediffweekcrossover(time, eph->toc);
*dts = eph->f0 + eph->f1 * tk + eph->f2 * tk * tk; *dts = eph->f0 + eph->f1 * tk + eph->f2 * tk * tk;
/* relativity correction */ /* relativity correction */
*dts -= 2.0 * sqrt(mu * eph->A) * eph->e * sinE / std::pow(SPEED_OF_LIGHT_M_S, 2.0); if (eph->apply_has_corrections)
{
// Apply HAS clock correction (HAS SIS ICD, Issue 1.0, Section 7.3)
*dts += (has_relativistic_correction + (eph->has_clock_correction_m / SPEED_OF_LIGHT_M_S));
// Note: This is referred to the GST for Galileo satellites. The user must account for
// a possible common offset in the broadcast HAS GPS clock corrections
}
else
{
*dts -= 2.0 * sqrt(mu * eph->A) * eph->e * sinE / (SPEED_OF_LIGHT_M_S * SPEED_OF_LIGHT_M_S);
}
/* position and clock error variance */ /* position and clock error variance */
*var = var_uraeph(eph->sva); *var = var_uraeph(eph->sva);

View File

@ -49,7 +49,7 @@ int init_rtcm(rtcm_t *rtcm)
obsd_t data0 = {{0, 0.0}, 0, 0, {0}, {0}, {0}, {0.0}, {0.0}, {0.0}}; obsd_t data0 = {{0, 0.0}, 0, 0, {0}, {0}, {0}, {0.0}, {0.0}, {0.0}};
eph_t eph0 = {0, -1, -1, 0, 0, 0, 0, 0, {0, 0.0}, {0, 0.0}, {0, 0.0}, eph_t eph0 = {0, -1, -1, 0, 0, 0, 0, 0, {0, 0.0}, {0, 0.0}, {0, 0.0},
0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, {0.0}, {0.0}, 0.0, 0.0}; 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, {0.0}, {0.0}, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, false};
geph_t geph0 = {0, -1, 0, 0, 0, 0, {0, 0.0}, {0, 0.0}, {0.0}, {0.0}, {0.0}, geph_t geph0 = {0, -1, 0, 0, 0, 0, {0, 0.0}, {0, 0.0}, {0.0}, {0.0}, {0.0},
0.0, 0.0, 0.0}; 0.0, 0.0, 0.0};
ssr_t ssr0 = {{{0, 0.0}}, {0.0}, {0}, 0, 0, 0, 0, {0.0}, {0.0}, {0.0}, 0.0, {0.0}, {0.0}, {0.0}, 0.0, 0.0, '0'}; ssr_t ssr0 = {{{0, 0.0}}, {0.0}, {0}, 0, 0, 0, 0, {0.0}, {0.0}, {0.0}, 0.0, {0.0}, {0.0}, {0.0}, 0.0, 0.0, '0'};

View File

@ -228,7 +228,7 @@ int decode_type17(rtcm_t *rtcm, bool pre_2009_file)
{ {
eph_t eph = {0, -1, -1, 0, 0, 0, 0, 0, {0, 0.0}, {0, 0.0}, {0, 0.0}, eph_t eph = {0, -1, -1, 0, 0, 0, 0, 0, {0, 0.0}, {0, 0.0}, {0, 0.0},
0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, {0.0}, {0.0}, 0.0, 0.0}; 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, {0.0}, {0.0}, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, false};
double toc; double toc;
double sqrtA; double sqrtA;
int i = 48; int i = 48;

View File

@ -1019,7 +1019,7 @@ int decode_type1019(rtcm_t *rtcm, bool pre_2009_file)
{ {
eph_t eph = {0, -1, -1, 0, 0, 0, 0, 0, {0, 0.0}, {0, 0.0}, {0, 0.0}, eph_t eph = {0, -1, -1, 0, 0, 0, 0, 0, {0, 0.0}, {0, 0.0}, {0, 0.0},
0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, {0.0}, {0.0}, 0.0, 0.0}; 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, {0.0}, {0.0}, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, false};
double toc; double toc;
double sqrtA; double sqrtA;
char *msg; char *msg;
@ -1518,7 +1518,7 @@ int decode_type1044(rtcm_t *rtcm, bool pre_2009_file)
{ {
eph_t eph = {0, -1, -1, 0, 0, 0, 0, 0, {0, 0.0}, {0, 0.0}, {0, 0.0}, eph_t eph = {0, -1, -1, 0, 0, 0, 0, 0, {0, 0.0}, {0, 0.0}, {0, 0.0},
0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, {0.0}, {0.0}, 0.0, 0.0}; 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, {0.0}, {0.0}, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, false};
double toc; double toc;
double sqrtA; double sqrtA;
char *msg; char *msg;
@ -1631,7 +1631,7 @@ int decode_type1045(rtcm_t *rtcm)
{ {
eph_t eph = {0, -1, -1, 0, 0, 0, 0, 0, {0, 0.0}, {0, 0.0}, {0, 0.0}, eph_t eph = {0, -1, -1, 0, 0, 0, 0, 0, {0, 0.0}, {0, 0.0}, {0, 0.0},
0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, {0.0}, {0.0}, 0.0, 0.0}; 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, {0.0}, {0.0}, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, false};
double toc; double toc;
double sqrtA; double sqrtA;
char *msg; char *msg;
@ -1745,7 +1745,7 @@ int decode_type1046(rtcm_t *rtcm)
{ {
eph_t eph = {0, -1, -1, 0, 0, 0, 0, 0, {0, 0.0}, {0, 0.0}, {0, 0.0}, eph_t eph = {0, -1, -1, 0, 0, 0, 0, 0, {0, 0.0}, {0, 0.0}, {0, 0.0},
0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, {0.0}, {0.0}, 0.0, 0.0}; 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, {0.0}, {0.0}, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, false};
double toc; double toc;
double sqrtA; double sqrtA;
char *msg; char *msg;
@ -1859,7 +1859,7 @@ int decode_type1047(rtcm_t *rtcm)
{ {
eph_t eph = {0, -1, -1, 0, 0, 0, 0, 0, {0, 0.0}, {0, 0.0}, {0, 0.0}, eph_t eph = {0, -1, -1, 0, 0, 0, 0, 0, {0, 0.0}, {0, 0.0}, {0, 0.0},
0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, {0.0}, {0.0}, 0.0, 0.0}; 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, {0.0}, {0.0}, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, false};
double toc; double toc;
double sqrtA; double sqrtA;
char *msg; char *msg;
@ -1976,7 +1976,7 @@ int decode_type63(rtcm_t *rtcm)
{ {
eph_t eph = {0, -1, -1, 0, 0, 0, 0, 0, {0, 0.0}, {0, 0.0}, {0, 0.0}, eph_t eph = {0, -1, -1, 0, 0, 0, 0, 0, {0, 0.0}, {0, 0.0}, {0, 0.0},
0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, {0.0}, {0.0}, 0.0, 0.0}; 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, {0.0}, {0.0}, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, false};
double toc; double toc;
double sqrtA; double sqrtA;
char *msg; char *msg;

View File

@ -3610,7 +3610,7 @@ int readnav(const char *file, nav_t *nav)
{ {
FILE *fp; FILE *fp;
eph_t eph0 = {0, 0, 0, 0, 0, 0, 0, 0, {0, 0}, {0, 0}, {0, 0}, 0.0, 0.0, 0.0, 0.0, 0.0, eph_t eph0 = {0, 0, 0, 0, 0, 0, 0, 0, {0, 0}, {0, 0}, {0, 0}, 0.0, 0.0, 0.0, 0.0, 0.0,
0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, {}, {}, 0.0, 0.0}; 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, {}, {}, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, false};
geph_t geph0 = {0, 0, 0, 0, 0, 0, {0, 0}, {0, 0}, {}, {}, {}, 0.0, 0.0, 0.0}; geph_t geph0 = {0, 0, 0, 0, 0, 0, {0, 0}, {0, 0}, {}, {}, {}, 0.0, 0.0, 0.0};
char buff[4096]; char buff[4096];
char *p; char *p;

View File

@ -688,7 +688,7 @@ int rtksvrinit(rtksvr_t *svr)
'0', '0', '0', 0, 0, 0}; '0', '0', '0', 0, 0, 0};
eph_t eph0 = {0, -1, -1, 0, 0, 0, 0, 0, {0, 0.0}, {0, 0.0}, {0, 0.0}, eph_t eph0 = {0, -1, -1, 0, 0, 0, 0, 0, {0, 0.0}, {0, 0.0}, {0, 0.0},
0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, {0.0}, {0.0}, 0.0, 0.0}; 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, {0.0}, {0.0}, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, false};
geph_t geph0 = {0, -1, 0, 0, 0, 0, {0, 0.0}, {0, 0.0}, {0.0}, {0.0}, {0.0}, geph_t geph0 = {0, -1, 0, 0, 0, 0, {0, 0.0}, {0, 0.0}, {0.0}, {0.0}, {0.0},
0.0, 0.0, 0.0}; 0.0, 0.0, 0.0};
seph_t seph0 = {0, {0, 0.0}, {0, 0.0}, 0, 0, {0.0}, {0.0}, {0.0}, 0.0, 0.0}; seph_t seph0 = {0, {0, 0.0}, {0, 0.0}, 0, 0, {0.0}, {0.0}, {0.0}, 0.0, 0.0};

View File

@ -258,7 +258,7 @@ endif()
# cpu_features - sensible defaults, user settable option # cpu_features - sensible defaults, user settable option
if(CMAKE_SYSTEM_PROCESSOR MATCHES if(CMAKE_SYSTEM_PROCESSOR MATCHES
"(^mips)|(^arm)|(^aarch64)|(x86_64)|(AMD64|amd64)|(^i.86$)|(^powerpc)|(^ppc)|(^s390x)") "(^mips)|(^arm)|(^aarch64)|(x86_64)|(AMD64|amd64)|(^i.86$)|(^powerpc)|(^ppc)|(^s390x)|^riscv")
option(VOLK_CPU_FEATURES "volk-gnsssdr uses cpu_features" ON) option(VOLK_CPU_FEATURES "volk-gnsssdr uses cpu_features" ON)
else() else()
option(VOLK_CPU_FEATURES "volk-gnsssdr uses cpu_features" OFF) option(VOLK_CPU_FEATURES "volk-gnsssdr uses cpu_features" OFF)
@ -266,7 +266,13 @@ endif()
if(CMAKE_VERSION VERSION_GREATER 3.0 AND VOLK_CPU_FEATURES) if(CMAKE_VERSION VERSION_GREATER 3.0 AND VOLK_CPU_FEATURES)
find_package(CPUFEATURES) find_package(CPUFEATURES)
if(CPUFEATURES_FOUND AND (CMAKE_SYSTEM_PROCESSOR MATCHES "(^s390x)|^riscv") AND (CPUFEATURES_VERSION VERSION_LESS "0.8.0"))
set(USE_CPU_FEATURES OFF)
unset(CPUFEATURES_FOUND CACHE)
message(STATUS "Building volk-gnsssdr without cpu_features, installed version v${CPUFEATURES_VERSION} does not support the ${CMAKE_SYSTEM_PROCESSOR} architecture")
else()
set(USE_CPU_FEATURES ON) set(USE_CPU_FEATURES ON)
endif()
if(NOT CPUFEATURES_FOUND) if(NOT CPUFEATURES_FOUND)
message(STATUS "Building volk-gnsssdr with cpu_features") message(STATUS "Building volk-gnsssdr with cpu_features")
set(BUILD_TESTING OFF CACHE BOOL "Build cpu_features without tests." FORCE) set(BUILD_TESTING OFF CACHE BOOL "Build cpu_features without tests." FORCE)
@ -290,13 +296,8 @@ endif()
# Python # Python
include(VolkPython) # sets PYTHON_EXECUTABLE include(VolkPython) # sets PYTHON_EXECUTABLE
volk_python_check_module("python >= 2.7" sys "sys.version.split()[0] >= '2.7'" PYTHON_MIN_VER_FOUND)
volk_python_check_module("mako >= 0.4.2" mako "mako.__version__ >= '0.4.2'" MAKO_FOUND)
if(Python2_VERSION OR (PYTHON_VERSION_STRING VERSION_LESS "3.0"))
volk_python_check_module("six - python 2 and 3 compatibility library" six "True" SIX_FOUND)
endif()
if(NOT PYTHON_MIN_VER_FOUND) if(NOT PYTHON_EXECUTABLE)
message(FATAL_ERROR "Python 2.7 or greater required to build VOLK_GNSSSDR") message(FATAL_ERROR "Python 2.7 or greater required to build VOLK_GNSSSDR")
endif() endif()

View File

@ -16,13 +16,22 @@ set(__INCLUDED_VOLK_PYTHON_CMAKE TRUE)
# - cmd an additional command to run # - cmd an additional command to run
# - have the result variable to set # - have the result variable to set
######################################################################## ########################################################################
macro(VOLK_PYTHON_CHECK_MODULE_RAW desc python_code have) macro(VOLK_PYTHON_CHECK_MODULE desc mod cmd have)
message(STATUS "Python checking for ${desc}")
execute_process( execute_process(
COMMAND ${PYTHON_EXECUTABLE} -c "${python_code}" COMMAND ${PYTHON_EXECUTABLE} -c "
#########################################
try: import ${mod}
except:
try: ${mod}
except: exit(-1)
try: assert ${cmd}
except: exit(-1)
#########################################"
OUTPUT_QUIET ERROR_QUIET OUTPUT_QUIET ERROR_QUIET
RESULT_VARIABLE return_code RESULT_VARIABLE ${have}
) )
if(return_code EQUAL 0) if(${have} EQUAL 0)
message(STATUS "Python checking for ${desc} - found") message(STATUS "Python checking for ${desc} - found")
set(${have} TRUE) set(${have} TRUE)
else() else()
@ -31,19 +40,6 @@ macro(VOLK_PYTHON_CHECK_MODULE_RAW desc python_code have)
endif() endif()
endmacro() endmacro()
macro(VOLK_PYTHON_CHECK_MODULE desc mod cmd have)
volk_python_check_module_raw(
"${desc}" "
#########################################
try:
import ${mod}
assert ${cmd}
except (ImportError, AssertionError): exit(-1)
except: pass
#########################################"
"${have}")
endmacro()
######################################################################## ########################################################################
# Setup the python interpreter: # Setup the python interpreter:
@ -57,6 +53,9 @@ if(CMAKE_VERSION VERSION_LESS 3.12 OR CMAKE_CROSSCOMPILING)
if(PYTHON_EXECUTABLE) if(PYTHON_EXECUTABLE)
message(STATUS "User set python executable ${PYTHON_EXECUTABLE}") message(STATUS "User set python executable ${PYTHON_EXECUTABLE}")
find_package(PythonInterp ${VOLK_PYTHON_MIN_VERSION} REQUIRED) find_package(PythonInterp ${VOLK_PYTHON_MIN_VERSION} REQUIRED)
if(PYTHON_VERSION_STRING VERSION_LESS "3.0")
volk_python_check_module("six - python 2 and 3 compatibility library" six "True" SIX_FOUND)
endif()
else() else()
message(STATUS "PYTHON_EXECUTABLE not set - trying by default python3") message(STATUS "PYTHON_EXECUTABLE not set - trying by default python3")
message(STATUS "Use -DPYTHON_EXECUTABLE=/path/to/python to build for python 2.7") message(STATUS "Use -DPYTHON_EXECUTABLE=/path/to/python to build for python 2.7")
@ -65,12 +64,18 @@ if(CMAKE_VERSION VERSION_LESS 3.12 OR CMAKE_CROSSCOMPILING)
if(NOT PYTHONINTERP_FOUND) if(NOT PYTHONINTERP_FOUND)
message(STATUS "python3 not found - trying with python2.7") message(STATUS "python3 not found - trying with python2.7")
find_package(PythonInterp ${VOLK_PYTHON_MIN_VERSION} REQUIRED) find_package(PythonInterp ${VOLK_PYTHON_MIN_VERSION} REQUIRED)
volk_python_check_module("six - python 2 and 3 compatibility library" six "True" SIX_FOUND)
endif() endif()
endif() endif()
volk_python_check_module("mako >= 0.4.2" mako "mako.__version__ >= '0.4.2'" MAKO_FOUND)
else() else()
if(PYTHON_EXECUTABLE) if(PYTHON_EXECUTABLE)
message(STATUS "User set python executable ${PYTHON_EXECUTABLE}") message(STATUS "User set python executable ${PYTHON_EXECUTABLE}")
find_package(PythonInterp ${VOLK_PYTHON_MIN_VERSION} REQUIRED) find_package(PythonInterp ${VOLK_PYTHON_MIN_VERSION} REQUIRED)
volk_python_check_module("mako >= 0.4.2" mako "mako.__version__ >= '0.4.2'" MAKO_FOUND)
if(PYTHON_VERSION_STRING VERSION_LESS "3.0")
volk_python_check_module("six - python 2 and 3 compatibility library" six "True" SIX_FOUND)
endif()
else() else()
if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
set(_previous ${CMAKE_FIND_FRAMEWORK}) set(_previous ${CMAKE_FIND_FRAMEWORK})
@ -98,6 +103,7 @@ else()
if(NOT MAKO_FOUND OR NOT SIX_FOUND) if(NOT MAKO_FOUND OR NOT SIX_FOUND)
unset(PYTHON_EXECUTABLE) unset(PYTHON_EXECUTABLE)
find_package(PythonInterp ${VOLK_PYTHON_MIN_VERSION}) find_package(PythonInterp ${VOLK_PYTHON_MIN_VERSION})
volk_python_check_module("mako >= 0.4.2" mako "mako.__version__ >= '0.4.2'" MAKO_FOUND)
endif() endif()
endif() endif()
endif() endif()

View File

@ -56,6 +56,7 @@ set(PROCESSOR_IS_AARCH64 FALSE)
set(PROCESSOR_IS_X86 FALSE) set(PROCESSOR_IS_X86 FALSE)
set(PROCESSOR_IS_POWER FALSE) set(PROCESSOR_IS_POWER FALSE)
set(PROCESSOR_IS_S390X FALSE) set(PROCESSOR_IS_S390X FALSE)
set(PROCESSOR_IS_RISCV FALSE)
if(CMAKE_SYSTEM_PROCESSOR MATCHES "^mips") if(CMAKE_SYSTEM_PROCESSOR MATCHES "^mips")
set(PROCESSOR_IS_MIPS TRUE) set(PROCESSOR_IS_MIPS TRUE)
@ -69,6 +70,8 @@ elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^(powerpc|ppc)")
set(PROCESSOR_IS_POWER TRUE) set(PROCESSOR_IS_POWER TRUE)
elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^(s390x)") elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^(s390x)")
set(PROCESSOR_IS_S390X TRUE) set(PROCESSOR_IS_S390X TRUE)
elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^riscv")
set(PROCESSOR_IS_RISCV TRUE)
endif() endif()
macro(add_cpu_features_headers_and_sources HDRS_LIST_NAME SRCS_LIST_NAME) macro(add_cpu_features_headers_and_sources HDRS_LIST_NAME SRCS_LIST_NAME)
@ -90,6 +93,8 @@ macro(add_cpu_features_headers_and_sources HDRS_LIST_NAME SRCS_LIST_NAME)
list(APPEND ${HDRS_LIST_NAME} ${PROJECT_SOURCE_DIR}/include/cpuinfo_ppc.h) list(APPEND ${HDRS_LIST_NAME} ${PROJECT_SOURCE_DIR}/include/cpuinfo_ppc.h)
elseif(PROCESSOR_IS_S390X) elseif(PROCESSOR_IS_S390X)
list(APPEND ${HDRS_LIST_NAME} ${PROJECT_SOURCE_DIR}/include/cpuinfo_s390x.h) list(APPEND ${HDRS_LIST_NAME} ${PROJECT_SOURCE_DIR}/include/cpuinfo_s390x.h)
elseif(PROCESSOR_IS_RISCV)
list(APPEND ${HDRS_LIST_NAME} ${PROJECT_SOURCE_DIR}/include/cpuinfo_riscv.h)
else() else()
message(FATAL_ERROR "Unsupported architectures ${CMAKE_SYSTEM_PROCESSOR}") message(FATAL_ERROR "Unsupported architectures ${CMAKE_SYSTEM_PROCESSOR}")
endif() endif()

View File

@ -158,14 +158,14 @@ flags : aes,avx,cx16,smx,sse4_1,sse4_2,ssse3
## What's supported ## What's supported
| | x86³ | AArch64 | ARM | MIPS⁴ | s390x | POWER | | | x86³ | AArch64 | ARM | MIPS⁴ | POWER | RISCV | s390x |
| ------- | :--: | :-----: | :-----: | :-----: | :-----: | :-----: | | ------- | :--: | :-----: | :-----: | :-----: | :-----: | :---: | :-----: |
| Linux | yes² | yes¹ | yes¹ | yes¹ | yes¹ | yes¹ | | Linux | yes² | yes¹ | yes¹ | yes¹ | yes¹ | yes¹ | yes¹ |
| FreeBSD | yes² | not yet | not yet | not yet | not yet | not yet | | FreeBSD | yes² | not yet | not yet | not yet | not yet | N/A | not yet |
| MacOs | yes² | not yet | N/A | N/A | no | no | | MacOs | yes² | not yet | N/A | N/A | no | N/A | no |
| Windows | yes² | not yet | not yet | N/A | N/A | N/A | | Windows | yes² | not yet | not yet | N/A | N/A | N/A | N/A |
| Android | yes² | yes¹ | yes¹ | yes¹ | N/A | N/A | | Android | yes² | yes¹ | yes¹ | yes¹ | N/A | N/A | N/A |
| iOS | N/A | not yet | not yet | N/A | N/A | N/A | | iOS | N/A | not yet | not yet | N/A | N/A | N/A | N/A |
1. **Features revealed from Linux.** We gather data from several sources 1. **Features revealed from Linux.** We gather data from several sources
depending on availability: depending on availability:

View File

@ -0,0 +1,62 @@
// SPDX-FileCopyrightText: 2022 Google LLC
// SPDX-License-Identifier: Apache-2.0
#ifndef CPU_FEATURES_INCLUDE_CPUINFO_RISCV_H_
#define CPU_FEATURES_INCLUDE_CPUINFO_RISCV_H_
#include "cpu_features_cache_info.h"
#include "cpu_features_macros.h"
#if !defined(CPU_FEATURES_ARCH_RISCV)
#error "Including cpuinfo_riscv.h from a non-riscv target."
#endif
CPU_FEATURES_START_CPP_NAMESPACE
typedef struct
{
// Base
int RV32I : 1; // Base Integer Instruction Set, 32-bit
int RV64I : 1; // Base Integer Instruction Set, 64-bit
// Extension
int M : 1; // Standard Extension for Integer Multiplication/Division
int A : 1; // Standard Extension for Atomic Instructions
int F : 1; // Standard Extension for Single-Precision Floating-Point
int D : 1; // Standard Extension for Double-Precision Floating-Point
int Q : 1; // Standard Extension for Quad-Precision Floating-Point
int C : 1; // Standard Extension for Compressed Instructions
int Zicsr : 1; // Control and Status Register (CSR)
int Zifencei : 1; // Instruction-Fetch Fence
} RiscvFeatures;
typedef struct
{
RiscvFeatures features;
char uarch[64]; // 0 terminated string
char vendor[64]; // 0 terminated string
} RiscvInfo;
typedef enum
{
RISCV_RV32I,
RISCV_RV64I,
RISCV_M,
RISCV_A,
RISCV_F,
RISCV_D,
RISCV_Q,
RISCV_C,
RISCV_Zicsr,
RISCV_Zifencei,
RISCV_LAST_,
} RiscvFeaturesEnum;
RiscvInfo GetRiscvInfo(void);
int GetRiscvFeaturesEnumValue(const RiscvFeatures* features,
RiscvFeaturesEnum value);
const char* GetRiscvFeaturesEnumName(RiscvFeaturesEnum);
CPU_FEATURES_END_CPP_NAMESPACE
#endif // CPU_FEATURES_INCLUDE_CPUINFO_RISCV_H_

View File

@ -193,15 +193,15 @@ CPU_FEATURES_START_CPP_NAMESPACE
#define HWCAP_S390_SIE 4194304 #define HWCAP_S390_SIE 4194304
// https://elixir.bootlin.com/linux/latest/source/arch/riscv/include/uapi/asm/hwcap.h // https://elixir.bootlin.com/linux/latest/source/arch/riscv/include/uapi/asm/hwcap.h
#define RISCV_HWCAP_A (1UL << ('A' - 'A')) #define RISCV_HWCAP_32 0x32
#define RISCV_HWCAP_C (1UL << ('C' - 'A')) #define RISCV_HWCAP_64 0x64
#define RISCV_HWCAP_D (1UL << ('D' - 'A')) #define RISCV_HWCAP_128 0x128
#define RISCV_HWCAP_E (1UL << ('E' - 'A'))
#define RISCV_HWCAP_F (1UL << ('F' - 'A'))
#define RISCV_HWCAP_I (1UL << ('I' - 'A'))
#define RISCV_HWCAP_M (1UL << ('M' - 'A')) #define RISCV_HWCAP_M (1UL << ('M' - 'A'))
#define RISCV_HWCAP_V (1UL << ('V' - 'A')) #define RISCV_HWCAP_A (1UL << ('A' - 'A'))
#define RISCV_HWCAP_F (1UL << ('F' - 'A'))
#define RISCV_HWCAP_D (1UL << ('D' - 'A'))
#define RISCV_HWCAP_Q (1UL << ('Q' - 'A')) #define RISCV_HWCAP_Q (1UL << ('Q' - 'A'))
#define RISCV_HWCAP_C (1UL << ('C' - 'A'))
typedef struct typedef struct
{ {

View File

@ -0,0 +1,109 @@
// SPDX-FileCopyrightText: 2022 Google LLC
// SPDX-License-Identifier: Apache-2.0
#include "cpu_features_macros.h"
#ifdef CPU_FEATURES_ARCH_RISCV
#if defined(CPU_FEATURES_OS_LINUX)
#include "cpuinfo_riscv.h"
// According to
// https://elixir.bootlin.com/linux/latest/source/Documentation/devicetree/bindings/riscv/cpus.yaml
// isa string should match the following regex
// ^rv(?:64|32)imaf?d?q?c?b?v?k?h?(?:_[hsxz](?:[a-z])+)*$
//
// This means we can test for features in this exact order except for Z
// extensions.
////////////////////////////////////////////////////////////////////////////////
// Definitions for introspection.
////////////////////////////////////////////////////////////////////////////////
#define INTROSPECTION_TABLE \
LINE(RISCV_RV32I, RV32I, "rv32i", RISCV_HWCAP_32, 0) \
LINE(RISCV_RV64I, RV64I, "rv64i", RISCV_HWCAP_64, 0) \
LINE(RISCV_M, M, "m", RISCV_HWCAP_M, 0) \
LINE(RISCV_A, A, "a", RISCV_HWCAP_A, 0) \
LINE(RISCV_F, F, "f", RISCV_HWCAP_F, 0) \
LINE(RISCV_D, D, "d", RISCV_HWCAP_D, 0) \
LINE(RISCV_Q, Q, "q", RISCV_HWCAP_Q, 0) \
LINE(RISCV_C, C, "c", RISCV_HWCAP_C, 0) \
LINE(RISCV_Zicsr, Zicsr, "_zicsr", 0, 0) \
LINE(RISCV_Zifencei, Zifencei, "_zifencei", 0, 0)
#define INTROSPECTION_PREFIX Riscv
#define INTROSPECTION_ENUM_PREFIX RISCV
#include "define_introspection_and_hwcaps.inl"
////////////////////////////////////////////////////////////////////////////////
// Implementation.
////////////////////////////////////////////////////////////////////////////////
#include "internal/filesystem.h"
#include "internal/stack_line_reader.h"
#include <stdbool.h>
#include <stdio.h>
static const RiscvInfo kEmptyRiscvInfo;
static void HandleRiscVIsaLine(StringView line, RiscvFeatures* const features)
{
for (size_t i = 0; i < RISCV_LAST_; ++i)
{
StringView flag = str(kCpuInfoFlags[i]);
int index_of_flag = CpuFeatures_StringView_IndexOf(line, flag);
bool is_set = index_of_flag != -1;
kSetters[i](features, is_set);
if (is_set)
line = CpuFeatures_StringView_PopFront(line, index_of_flag + flag.size);
}
}
static bool HandleRiscVLine(const LineResult result, RiscvInfo* const info)
{
StringView line = result.line;
StringView key, value;
if (CpuFeatures_StringView_GetAttributeKeyValue(line, &key, &value))
{
if (CpuFeatures_StringView_IsEquals(key, str("isa")))
{
HandleRiscVIsaLine(value, &info->features);
}
else if (CpuFeatures_StringView_IsEquals(key, str("uarch")))
{
int index = CpuFeatures_StringView_IndexOfChar(value, ',');
if (index == -1) return true;
StringView vendor = CpuFeatures_StringView_KeepFront(value, index);
StringView uarch = CpuFeatures_StringView_PopFront(value, index + 1);
CpuFeatures_StringView_CopyString(vendor, info->vendor,
sizeof(info->vendor));
CpuFeatures_StringView_CopyString(uarch, info->uarch,
sizeof(info->uarch));
}
}
return !result.eof;
}
static void FillProcCpuInfoData(RiscvInfo* const info)
{
const int fd = CpuFeatures_OpenFile("/proc/cpuinfo");
if (fd >= 0)
{
StackLineReader reader;
StackLineReader_Initialize(&reader, fd);
for (;;)
{
if (!HandleRiscVLine(StackLineReader_NextLine(&reader), info)) break;
}
CpuFeatures_CloseFile(fd);
}
}
RiscvInfo GetRiscvInfo(void)
{
RiscvInfo info = kEmptyRiscvInfo;
FillProcCpuInfoData(&info);
return info;
}
#endif // defined(CPU_FEATURES_OS_LINUX) || defined(CPU_FEATURES_OS_ANDROID)
#endif // CPU_FEATURES_ARCH_RISCV

View File

@ -25,6 +25,8 @@
#include "cpuinfo_ppc.h" #include "cpuinfo_ppc.h"
#elif defined(CPU_FEATURES_ARCH_S390X) #elif defined(CPU_FEATURES_ARCH_S390X)
#include "cpuinfo_s390x.h" #include "cpuinfo_s390x.h"
#elif defined(CPU_FEATURES_ARCH_RISCV)
#include "cpuinfo_riscv.h"
#endif #endif
// Design principles // Design principles
@ -217,6 +219,9 @@ DEFINE_ADD_FLAGS(GetPPCFeaturesEnumValue, GetPPCFeaturesEnumName, PPCFeatures,
#elif defined(CPU_FEATURES_ARCH_S390X) #elif defined(CPU_FEATURES_ARCH_S390X)
DEFINE_ADD_FLAGS(GetS390XFeaturesEnumValue, GetS390XFeaturesEnumName, S390XFeatures, DEFINE_ADD_FLAGS(GetS390XFeaturesEnumValue, GetS390XFeaturesEnumName, S390XFeatures,
S390X_LAST_) S390X_LAST_)
#elif defined(CPU_FEATURES_ARCH_RISCV)
DEFINE_ADD_FLAGS(GetRiscvFeaturesEnumValue, GetRiscvFeaturesEnumName, RiscvFeatures,
RISCV_LAST_)
#endif #endif
// Prints a json string with characters escaping. // Prints a json string with characters escaping.
@ -447,6 +452,12 @@ static Node* CreateTree(void)
AddMapEntry(root, "model", CreateString(strings.type.platform)); AddMapEntry(root, "model", CreateString(strings.type.platform));
AddMapEntry(root, "# processors", CreateInt(strings.num_processors)); AddMapEntry(root, "# processors", CreateInt(strings.num_processors));
AddFlags(root, &info.features); AddFlags(root, &info.features);
#elif defined(CPU_FEATURES_ARCH_RISCV)
const RiscvInfo info = GetRiscvInfo();
AddMapEntry(root, "arch", CreateString("risc-v"));
AddMapEntry(root, "vendor", CreateString(info.vendor));
AddMapEntry(root, "microarchitecture", CreateString(info.uarch));
AddFlags(root, &info.features);
#endif #endif
return root; return root;
} }

View File

@ -99,3 +99,10 @@ if(PROCESSOR_IS_S390X)
target_link_libraries(cpuinfo_s390x_test all_libraries) target_link_libraries(cpuinfo_s390x_test all_libraries)
add_test(NAME cpuinfo_s390x_test COMMAND cpuinfo_s390x_test) add_test(NAME cpuinfo_s390x_test COMMAND cpuinfo_s390x_test)
endif() endif()
##------------------------------------------------------------------------------
## cpuinfo_riscv_test
if(PROCESSOR_IS_RISCV)
add_executable(cpuinfo_riscv_test cpuinfo_riscv_test.cc ../src/impl_riscv_linux.c)
target_link_libraries(cpuinfo_riscv_test all_libraries)
add_test(NAME cpuinfo_riscv_test COMMAND cpuinfo_riscv_test)
endif()

View File

@ -0,0 +1,141 @@
// SPDX-FileCopyrightText: 2022 Google LLC
// SPDX-License-Identifier: Apache-2.0
#include "cpuinfo_riscv.h"
#include "filesystem_for_testing.h"
#include "gtest/gtest.h"
#include "hwcaps_for_testing.h"
namespace cpu_features
{
namespace
{
TEST(CpuinfoRiscvTest, Sipeed_Lichee_RV_FromCpuInfo)
{
ResetHwcaps();
auto& fs = GetEmptyFilesystem();
fs.CreateFile("/proc/cpuinfo", R"(processor : 0
hart : 0
isa : rv64imafdc
mmu : sv39
uarch : thead,c906)");
const auto info = GetRiscvInfo();
EXPECT_STREQ(info.uarch, "c906");
EXPECT_STREQ(info.vendor, "thead");
EXPECT_FALSE(info.features.RV32I);
EXPECT_TRUE(info.features.RV64I);
EXPECT_TRUE(info.features.M);
EXPECT_TRUE(info.features.A);
EXPECT_TRUE(info.features.F);
EXPECT_TRUE(info.features.D);
EXPECT_FALSE(info.features.Q);
EXPECT_TRUE(info.features.C);
}
// https://github.com/ThomasKaiser/sbc-bench/blob/284e82b016ec1beeac42a5fcbe556b670f68441a/results/Kendryte-K510-4.17.0.cpuinfo
TEST(CpuinfoRiscvTest, Kendryte_K510_FromCpuInfo)
{
ResetHwcaps();
auto& fs = GetEmptyFilesystem();
fs.CreateFile("/proc/cpuinfo", R"(
hart : 0
isa : rv64i2p0m2p0a2p0f2p0d2p0c2p0xv5-0p0
mmu : sv39
hart : 1
isa : rv64i2p0m2p0a2p0f2p0d2p0c2p0xv5-0p0
mmu : sv39");
const auto info = GetRiscvInfo();
EXPECT_STREQ(info.uarch, "");
EXPECT_STREQ(info.vendor, "");
EXPECT_FALSE(info.features.RV32I);
EXPECT_TRUE(info.features.RV64I);
EXPECT_TRUE(info.features.M);
EXPECT_TRUE(info.features.A);
EXPECT_TRUE(info.features.F);
EXPECT_TRUE(info.features.D);
EXPECT_FALSE(info.features.Q);
EXPECT_TRUE(info.features.C);
}
// https://github.com/ThomasKaiser/sbc-bench/blob/284e82b016ec1beeac42a5fcbe556b670f68441a/results/T-Head-C910-5.10.4.cpuinfo
TEST(CpuinfoRiscvTest, T_Head_C910_FromCpuInfo) {
ResetHwcaps();
auto& fs = GetEmptyFilesystem();
fs.CreateFile("/proc/cpuinfo", R"(
processor : 0
hart : 0
isa : rv64imafdcsu
mmu : sv39
cpu-freq : 1.2Ghz
cpu-icache : 64KB
cpu-dcache : 64KB
cpu-l2cache : 2MB
cpu-tlb : 1024 4-ways
cpu-cacheline : 64Bytes
cpu-vector : 0.7.1
processor : 1
hart : 1
isa : rv64imafdcsu
mmu : sv39
cpu-freq : 1.2Ghz
cpu-icache : 64KB
cpu-dcache : 64KB
cpu-l2cache : 2MB
cpu-tlb : 1024 4-ways
cpu-cacheline : 64Bytes
cpu-vector : 0.7.1");
const auto info = GetRiscvInfo();
EXPECT_STREQ(info.uarch, "");
EXPECT_STREQ(info.vendor, "");
EXPECT_FALSE(info.features.RV32I);
EXPECT_TRUE(info.features.RV64I);
EXPECT_TRUE(info.features.M);
EXPECT_TRUE(info.features.A);
EXPECT_TRUE(info.features.F);
EXPECT_TRUE(info.features.D);
EXPECT_FALSE(info.features.Q);
EXPECT_TRUE(info.features.C);
}
TEST(CpuinfoRiscvTest, UnknownFromCpuInfo) {
ResetHwcaps();
auto& fs = GetEmptyFilesystem();
fs.CreateFile("/proc/cpuinfo", R"(
processor : 0
hart : 2
isa : rv64imafdc
mmu : sv39
uarch : sifive,bullet0
processor : 1
hart : 1
isa : rv64imafdc
mmu : sv39
uarch : sifive,bullet0
processor : 2
hart : 3
isa : rv64imafdc
mmu : sv39
uarch : sifive,bullet0
processor : 3
hart : 4
isa : rv64imafdc
mmu : sv39
uarch : sifive,bullet0)");
const auto info = GetRiscvInfo();
EXPECT_STREQ(info.uarch, "bullet0");
EXPECT_STREQ(info.vendor, "sifive");
EXPECT_FALSE(info.features.RV32I);
EXPECT_TRUE(info.features.RV64I);
EXPECT_TRUE(info.features.M);
EXPECT_TRUE(info.features.A);
EXPECT_TRUE(info.features.F);
EXPECT_TRUE(info.features.D);
EXPECT_FALSE(info.features.Q);
EXPECT_TRUE(info.features.C);
}
} // namespace
} // namespace cpu_features

View File

@ -23,7 +23,6 @@
\li \subpage volk_gnsssdr_8ic_magnitude_squared_8i \li \subpage volk_gnsssdr_8ic_magnitude_squared_8i
\li \subpage volk_gnsssdr_8ic_x2_dot_prod_8ic \li \subpage volk_gnsssdr_8ic_x2_dot_prod_8ic
\li \subpage volk_gnsssdr_8ic_x2_multiply_8ic \li \subpage volk_gnsssdr_8ic_x2_multiply_8ic
\li \subpage volk_gnsssdr_8ic_s8ic_multiply_8ic
\li \subpage volk_gnsssdr_8i_accumulator_s8i \li \subpage volk_gnsssdr_8i_accumulator_s8i
\li \subpage volk_gnsssdr_8i_index_max_16u \li \subpage volk_gnsssdr_8i_index_max_16u
\li \subpage volk_gnsssdr_8i_max_s8i \li \subpage volk_gnsssdr_8i_max_s8i

View File

@ -1,27 +0,0 @@
#
# ORC implementation: calculates the conjugate of a 16 bits vector
#
# Andres Cecilia, 2014. a.cecilia.luque(at)gmail.com
#
# ORC code that calculates the conjugate of a
# 16 bits vector (8 bits the real part and 8 bits the imaginary part)
# result = (real*real) + (imag*imag)
#
#
# ------------------------------------------------------------------------------
#
# GNSS-SDR is a Global Navigation Satellite System software-defined receiver.
# This file is part of GNSS-SDR.
#
# Copyright (C) 2010-2020 (see AUTHORS file for a list of contributors)
# SPDX-License-Identifier: GPL-3.0-or-later
#
# ------------------------------------------------------------------------------
#
.function volk_gnsssdr_8ic_conjugate_8ic_a_orc_impl
.source 2 src1
.dest 2 dst
.temp 2 merged
mergebw merged, 1, -1
x2 mullb dst, merged, src1

View File

@ -1,39 +0,0 @@
#
# ORC implementation: multiplies a group of 16 bits vectors by one constant vector
#
# Andres Cecilia, 2014. a.cecilia.luque(at)gmail.com
#
#
# ORC code that multiplies a group of 16 bits vectors
# (8 bits the real part and 8 bits the imaginary part) by one constant vector
#
# ------------------------------------------------------------------------------
#
# GNSS-SDR is a Global Navigation Satellite System software-defined receiver.
# This file is part of GNSS-SDR.
#
# Copyright (C) 2010-2020 (see AUTHORS file for a list of contributors)
# SPDX-License-Identifier: GPL-3.0-or-later
#
# ------------------------------------------------------------------------------
#
.function volk_gnsssdr_8ic_s8ic_multiply_8ic_a_orc_impl
.source 2 src1
.param 2 src2real
.param 2 src2imag
.dest 2 dst
.temp 2 iqprod
.temp 1 real
.temp 1 imag
.temp 1 rr
.temp 1 ii
.temp 1 ri
.temp 1 ir
x2 mullb iqprod, src1, src2real
splitwb ir, rr, iqprod
x2 mullb iqprod, src1, src2imag
splitwb ii, ri, iqprod
subb real, rr, ii
addb imag, ri, ir
mergebw dst, real, imag

View File

@ -324,16 +324,6 @@ static inline void volk_gnsssdr_8ic_conjugate_8ic_a_sse3(lv_8sc_t* cVector, cons
#endif /* LV_HAVE_SSE3 */ #endif /* LV_HAVE_SSE3 */
#ifdef LV_HAVE_ORC
extern void volk_gnsssdr_8ic_conjugate_8ic_a_orc_impl(lv_8sc_t* cVector, const lv_8sc_t* aVector, unsigned int num_points);
static inline void volk_gnsssdr_8ic_conjugate_8ic_u_orc(lv_8sc_t* cVector, const lv_8sc_t* aVector, unsigned int num_points)
{
volk_gnsssdr_8ic_conjugate_8ic_a_orc_impl(cVector, aVector, num_points);
}
#endif /* LV_HAVE_ORC */
#ifdef LV_HAVE_NEON #ifdef LV_HAVE_NEON
#include <arm_neon.h> #include <arm_neon.h>

View File

@ -1,205 +0,0 @@
/*!
* \file volk_gnsssdr_8ic_s8ic_multiply_8ic.h
* \brief VOLK_GNSSSDR kernel: multiplies a group of 16 bits vectors by one constant vector.
* \authors <ul>
* <li> Andres Cecilia, 2014. a.cecilia.luque(at)gmail.com
* </ul>
*
* VOLK_GNSSSDR kernel that multiplies a group of 16 bits vectors
* (8 bits the real part and 8 bits the imaginary part) by one constant vector
*
* -----------------------------------------------------------------------------
*
* GNSS-SDR is a Global Navigation Satellite System software-defined receiver.
* This file is part of GNSS-SDR.
*
* Copyright (C) 2010-2020 (see AUTHORS file for a list of contributors)
* SPDX-License-Identifier: GPL-3.0-or-later
*
* -----------------------------------------------------------------------------
*/
/*!
* \page volk_gnsssdr_8ic_s8ic_multiply_8ic
*
* \b Overview
*
* Multiplies the input vector by a scalar and stores the results in the third vector
*
* <b>Dispatcher Prototype</b>
* \code
* void volk_gnsssdr_8ic_s8ic_multiply_8ic(lv_8sc_t* cVector, const lv_8sc_t* aVector, const lv_8sc_t scalar, unsigned int num_points);
* \endcode
*
* \b Inputs
* \li aVector: The vector to be multiplied.
* \li scalar The complex scalar to multiply \p aVector
* \li num_points: The number of complex values in \p aVector to be multiplied by \p scalar and stored into \p cVector.
*
* \b Outputs
* \li cVector: The vector where the results will be stored
*
*/
#ifndef INCLUDED_volk_gnsssdr_8ic_s8ic_multiply_8ic_H
#define INCLUDED_volk_gnsssdr_8ic_s8ic_multiply_8ic_H
#include <volk_gnsssdr/volk_gnsssdr_complex.h>
#ifdef LV_HAVE_SSE3
#include <pmmintrin.h>
static inline void volk_gnsssdr_8ic_s8ic_multiply_8ic_u_sse3(lv_8sc_t* cVector, const lv_8sc_t* aVector, const lv_8sc_t scalar, unsigned int num_points)
{
unsigned int number = 0;
const unsigned int sse_iters = num_points / 8;
__m128i x, y, mult1, realx, imagx, realy, imagy, realx_mult_realy, imagx_mult_imagy, realx_mult_imagy, imagx_mult_realy, realc, imagc, totalc;
lv_8sc_t* c = cVector;
const lv_8sc_t* a = aVector;
mult1 = _mm_set_epi8(0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF);
y = _mm_set1_epi16(*(short*)&scalar);
imagy = _mm_srli_si128(y, 1);
imagy = _mm_and_si128(imagy, mult1);
realy = _mm_and_si128(y, mult1);
for (; number < sse_iters; number++)
{
x = _mm_lddqu_si128((__m128i*)a);
imagx = _mm_srli_si128(x, 1);
imagx = _mm_and_si128(imagx, mult1);
realx = _mm_and_si128(x, mult1);
realx_mult_realy = _mm_mullo_epi16(realx, realy);
imagx_mult_imagy = _mm_mullo_epi16(imagx, imagy);
realx_mult_imagy = _mm_mullo_epi16(realx, imagy);
imagx_mult_realy = _mm_mullo_epi16(imagx, realy);
realc = _mm_sub_epi16(realx_mult_realy, imagx_mult_imagy);
realc = _mm_and_si128(realc, mult1);
imagc = _mm_add_epi16(realx_mult_imagy, imagx_mult_realy);
imagc = _mm_and_si128(imagc, mult1);
imagc = _mm_slli_si128(imagc, 1);
totalc = _mm_or_si128(realc, imagc);
_mm_storeu_si128((__m128i*)c, totalc);
a += 8;
c += 8;
}
for (number = sse_iters * 8; number < num_points; ++number)
{
*c++ = (*a++) * scalar;
}
}
#endif /* LV_HAVE_SSE3 */
#ifdef LV_HAVE_GENERIC
static inline void volk_gnsssdr_8ic_s8ic_multiply_8ic_generic(lv_8sc_t* cVector, const lv_8sc_t* aVector, const lv_8sc_t scalar, unsigned int num_points)
{
/*lv_8sc_t* cPtr = cVector;
const lv_8sc_t* aPtr = aVector;
for (int i = 0; i<num_points; ++i)
{
*cPtr++ = (*aPtr++) * scalar;
}*/
lv_8sc_t* cPtr = cVector;
const lv_8sc_t* aPtr = aVector;
unsigned int number = num_points;
// unwrap loop
while (number >= 8)
{
*cPtr++ = (*aPtr++) * scalar;
*cPtr++ = (*aPtr++) * scalar;
*cPtr++ = (*aPtr++) * scalar;
*cPtr++ = (*aPtr++) * scalar;
*cPtr++ = (*aPtr++) * scalar;
*cPtr++ = (*aPtr++) * scalar;
*cPtr++ = (*aPtr++) * scalar;
*cPtr++ = (*aPtr++) * scalar;
number -= 8;
}
// clean up any remaining
while (number-- > 0)
*cPtr++ = *aPtr++ * scalar;
}
#endif /* LV_HAVE_GENERIC */
#ifdef LV_HAVE_SSE3
#include <pmmintrin.h>
static inline void volk_gnsssdr_8ic_s8ic_multiply_8ic_a_sse3(lv_8sc_t* cVector, const lv_8sc_t* aVector, const lv_8sc_t scalar, unsigned int num_points)
{
unsigned int number = 0;
const unsigned int sse_iters = num_points / 8;
__m128i x, y, mult1, realx, imagx, realy, imagy, realx_mult_realy, imagx_mult_imagy, realx_mult_imagy, imagx_mult_realy, realc, imagc, totalc;
lv_8sc_t* c = cVector;
const lv_8sc_t* a = aVector;
mult1 = _mm_set_epi8(0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF);
y = _mm_set1_epi16(*(short*)&scalar);
imagy = _mm_srli_si128(y, 1);
imagy = _mm_and_si128(imagy, mult1);
realy = _mm_and_si128(y, mult1);
for (; number < sse_iters; number++)
{
x = _mm_load_si128((__m128i*)a);
imagx = _mm_srli_si128(x, 1);
imagx = _mm_and_si128(imagx, mult1);
realx = _mm_and_si128(x, mult1);
realx_mult_realy = _mm_mullo_epi16(realx, realy);
imagx_mult_imagy = _mm_mullo_epi16(imagx, imagy);
realx_mult_imagy = _mm_mullo_epi16(realx, imagy);
imagx_mult_realy = _mm_mullo_epi16(imagx, realy);
realc = _mm_sub_epi16(realx_mult_realy, imagx_mult_imagy);
realc = _mm_and_si128(realc, mult1);
imagc = _mm_add_epi16(realx_mult_imagy, imagx_mult_realy);
imagc = _mm_and_si128(imagc, mult1);
imagc = _mm_slli_si128(imagc, 1);
totalc = _mm_or_si128(realc, imagc);
_mm_store_si128((__m128i*)c, totalc);
a += 8;
c += 8;
}
for (number = sse_iters * 8; number < num_points; ++number)
{
*c++ = (*a++) * scalar;
}
}
#endif /* LV_HAVE_SSE3 */
#ifdef LV_HAVE_ORC
extern void volk_gnsssdr_8ic_s8ic_multiply_8ic_a_orc_impl(lv_8sc_t* cVector, const lv_8sc_t* aVector, const char scalarreal, const char scalarimag, unsigned int num_points);
static inline void volk_gnsssdr_8ic_s8ic_multiply_8ic_u_orc(lv_8sc_t* cVector, const lv_8sc_t* aVector, const lv_8sc_t scalar, unsigned int num_points)
{
volk_gnsssdr_8ic_s8ic_multiply_8ic_a_orc_impl(cVector, aVector, lv_creal(scalar), lv_cimag(scalar), num_points);
}
#endif /* LV_HAVE_ORC */
#endif /* INCLUDED_volk_gnsssdr_32fc_x2_multiply_32fc_H */

View File

@ -51,7 +51,8 @@ std::vector<volk_gnsssdr_test_case_t> init_test_list(volk_gnsssdr_test_params_t
volk_gnsssdr_test_params_t test_params_inacc2 = volk_gnsssdr_test_params_t(2e-1, test_params.scalar(), volk_gnsssdr_test_params_t test_params_inacc2 = volk_gnsssdr_test_params_t(2e-1, test_params.scalar(),
test_params.vlen(), test_params.iter(), test_params.benchmark_mode(), test_params.kernel_regex()); test_params.vlen(), test_params.iter(), test_params.benchmark_mode(), test_params.kernel_regex());
std::vector<volk_gnsssdr_test_case_t> test_cases; std::vector<volk_gnsssdr_test_case_t>
test_cases;
QA(VOLK_INIT_TEST(volk_gnsssdr_8i_accumulator_s8i, test_params_more_iters)) QA(VOLK_INIT_TEST(volk_gnsssdr_8i_accumulator_s8i, test_params_more_iters))
QA(VOLK_INIT_TEST(volk_gnsssdr_8i_index_max_16u, test_params_more_iters)) QA(VOLK_INIT_TEST(volk_gnsssdr_8i_index_max_16u, test_params_more_iters))
@ -61,7 +62,6 @@ std::vector<volk_gnsssdr_test_case_t> init_test_list(volk_gnsssdr_test_params_t
QA(VOLK_INIT_TEST(volk_gnsssdr_8ic_magnitude_squared_8i, test_params_more_iters)) QA(VOLK_INIT_TEST(volk_gnsssdr_8ic_magnitude_squared_8i, test_params_more_iters))
QA(VOLK_INIT_TEST(volk_gnsssdr_8ic_x2_dot_prod_8ic, test_params)) QA(VOLK_INIT_TEST(volk_gnsssdr_8ic_x2_dot_prod_8ic, test_params))
QA(VOLK_INIT_TEST(volk_gnsssdr_8ic_x2_multiply_8ic, test_params)) QA(VOLK_INIT_TEST(volk_gnsssdr_8ic_x2_multiply_8ic, test_params))
QA(VOLK_INIT_TEST(volk_gnsssdr_8ic_s8ic_multiply_8ic, test_params))
QA(VOLK_INIT_TEST(volk_gnsssdr_8u_x2_multiply_8u, test_params_more_iters)) QA(VOLK_INIT_TEST(volk_gnsssdr_8u_x2_multiply_8u, test_params_more_iters))
QA(VOLK_INIT_TEST(volk_gnsssdr_64f_accumulator_64f, test_params)) QA(VOLK_INIT_TEST(volk_gnsssdr_64f_accumulator_64f, test_params))
QA(VOLK_INIT_TEST(volk_gnsssdr_32f_sincos_32fc, test_params_inacc)) QA(VOLK_INIT_TEST(volk_gnsssdr_32f_sincos_32fc, test_params_inacc))

View File

@ -26,6 +26,10 @@
#include "cpuinfo_mips.h" #include "cpuinfo_mips.h"
#elif defined(CPU_FEATURES_ARCH_PPC) #elif defined(CPU_FEATURES_ARCH_PPC)
#include "cpuinfo_ppc.h" #include "cpuinfo_ppc.h"
#elif defined(CPU_FEATURES_ARCH_S390X)
#include "cpuinfo_s390x.h"
#elif defined(CPU_FEATURES_ARCH_RISCV)
#include "cpuinfo_riscv.h"
#endif #endif
// This is required for MSVC // This is required for MSVC
@ -44,6 +48,22 @@ static int i_can_has_${arch.name} (void) {
%if "neon" in arch.name: %if "neon" in arch.name:
#if defined(CPU_FEATURES_ARCH_ARM) #if defined(CPU_FEATURES_ARCH_ARM)
if (GetArmInfo().features.${check} == 0){ return 0; } if (GetArmInfo().features.${check} == 0){ return 0; }
#endif
%elif "mips" in arch.name:
#if defined(CPU_FEATURES_ARCH_MIPS)
if (GetMipsInfo().features.${check} == 0){ return 0; }
#endif
%elif "ppc" in arch.name:
#if defined(CPU_FEATURES_ARCH_PPC)
if (GetPPCInfo().features.${check} == 0){ return 0; }
#endif
%elif "s390x" in arch.name:
#if defined(CPU_FEATURES_ARCH_S390X)
if (GetS390XInfo().features.${check} == 0){ return 0; }
#endif
%elif "riscv" in arch.name:
#if defined(CPU_FEATURES_ARCH_RISCV)
if (GetRiscvInfo().features.${check} == 0){ return 0; }
#endif #endif
%else: %else:
#if defined(CPU_FEATURES_ARCH_X86) #if defined(CPU_FEATURES_ARCH_X86)

View File

@ -100,19 +100,6 @@ hybrid_observables_gs::hybrid_observables_gs(const Obs_Conf &conf_)
d_channel_last_pseudorange_smooth = std::vector<double>(d_nchannels_out, 0.0); d_channel_last_pseudorange_smooth = std::vector<double>(d_nchannels_out, 0.0);
d_channel_last_carrier_phase_rads = std::vector<double>(d_nchannels_out, 0.0); d_channel_last_carrier_phase_rads = std::vector<double>(d_nchannels_out, 0.0);
d_mapStringValues["1C"] = evGPS_1C;
d_mapStringValues["2S"] = evGPS_2S;
d_mapStringValues["L5"] = evGPS_L5;
d_mapStringValues["1B"] = evGAL_1B;
d_mapStringValues["5X"] = evGAL_5X;
d_mapStringValues["E6"] = evGAL_E6;
d_mapStringValues["7X"] = evGAL_7X;
d_mapStringValues["1G"] = evGLO_1G;
d_mapStringValues["2G"] = evGLO_2G;
d_mapStringValues["B1"] = evBDS_B1;
d_mapStringValues["B2"] = evBDS_B2;
d_mapStringValues["B3"] = evBDS_B3;
d_SourceTagTimestamps = std::vector<std::queue<GnssTime>>(d_nchannels_out); d_SourceTagTimestamps = std::vector<std::queue<GnssTime>>(d_nchannels_out);
set_tag_propagation_policy(TPP_DONT); // no tag propagation, the time tag will be adjusted and regenerated in work() set_tag_propagation_policy(TPP_DONT); // no tag propagation, the time tag will be adjusted and regenerated in work()
@ -581,44 +568,11 @@ void hybrid_observables_gs::smooth_pseudoranges(std::vector<Gnss_Synchro> &data)
if (it->Flag_valid_pseudorange) if (it->Flag_valid_pseudorange)
{ {
// 0. get wavelength for the current signal // 0. get wavelength for the current signal
double wavelength_m = 0; double wavelength_m = 0.0;
switch (d_mapStringValues[it->Signal]) const auto it_freq_map = SIGNAL_FREQ_MAP.find(std::string(it->Signal, 2));
if (it_freq_map != SIGNAL_FREQ_MAP.cend())
{ {
case evGPS_1C: wavelength_m = SPEED_OF_LIGHT_M_S / it_freq_map->second;
case evSBAS_1C:
case evGAL_1B:
wavelength_m = SPEED_OF_LIGHT_M_S / FREQ1;
break;
case evGPS_L5:
case evGAL_5X:
wavelength_m = SPEED_OF_LIGHT_M_S / FREQ5;
break;
case evGAL_E6:
wavelength_m = SPEED_OF_LIGHT_M_S / FREQ6;
break;
case evGAL_7X:
wavelength_m = SPEED_OF_LIGHT_M_S / FREQ7;
break;
case evGPS_2S:
wavelength_m = SPEED_OF_LIGHT_M_S / FREQ2;
break;
case evBDS_B3:
wavelength_m = SPEED_OF_LIGHT_M_S / FREQ3_BDS;
break;
case evGLO_1G:
wavelength_m = SPEED_OF_LIGHT_M_S / FREQ1_GLO;
break;
case evGLO_2G:
wavelength_m = SPEED_OF_LIGHT_M_S / FREQ2_GLO;
break;
case evBDS_B1:
wavelength_m = SPEED_OF_LIGHT_M_S / FREQ1_BDS;
break;
case evBDS_B2:
wavelength_m = SPEED_OF_LIGHT_M_S / FREQ2_BDS;
break;
default:
break;
} }
// todo: propagate the PLL lock status in Gnss_Synchro // todo: propagate the PLL lock status in Gnss_Synchro

View File

@ -29,9 +29,8 @@
#include <cstddef> // for size_t #include <cstddef> // for size_t
#include <cstdint> // for int32_t #include <cstdint> // for int32_t
#include <fstream> // for std::ofstream #include <fstream> // for std::ofstream
#include <map> // for std::map
#include <memory> // for std::shared, std:unique_ptr #include <memory> // for std::shared, std:unique_ptr
#include <queue> #include <queue> // for std::queue
#include <string> // for std::string #include <string> // for std::string
#include <typeinfo> // for typeid #include <typeinfo> // for typeid
#include <vector> // for std::vector #include <vector> // for std::vector
@ -84,24 +83,6 @@ private:
Obs_Conf d_conf; Obs_Conf d_conf;
enum StringValue_
{
evGPS_1C,
evGPS_2S,
evGPS_L5,
evSBAS_1C,
evGAL_1B,
evGAL_5X,
evGAL_E6,
evGAL_7X,
evGLO_1G,
evGLO_2G,
evBDS_B1,
evBDS_B2,
evBDS_B3
};
std::map<std::string, StringValue_> d_mapStringValues;
std::unique_ptr<Gnss_circular_deque<Gnss_Synchro>> d_gnss_synchro_history; // Tracking observable history std::unique_ptr<Gnss_circular_deque<Gnss_Synchro>> d_gnss_synchro_history; // Tracking observable history
boost::circular_buffer<uint64_t> d_Rx_clock_buffer; // time history boost::circular_buffer<uint64_t> d_Rx_clock_buffer; // time history

View File

@ -44,6 +44,7 @@ ZmqSignalSource::ZmqSignalSource(const ConfigurationInterface* configuration,
LOG(INFO) << "Connecting to ZMQ pub at " << endpoint; LOG(INFO) << "Connecting to ZMQ pub at " << endpoint;
// work around gnuradio interface deficiency // work around gnuradio interface deficiency
d_source_block = gr::zeromq::sub_source::make(d_item_size, vlen, const_cast<char*>(endpoint.data()), timeout_ms, pass_tags, hwm); d_source_block = gr::zeromq::sub_source::make(d_item_size, vlen, const_cast<char*>(endpoint.data()), timeout_ms, pass_tags, hwm);
d_source_block->set_tag_propagation_policy(gr::block::TPP_DONT); // GNSS-SDR doesn't do well with tags/
} }
else else
{ {
@ -94,9 +95,13 @@ auto ZmqSignalSource::get_right_block() -> gr::basic_block_sptr
auto result = gr::basic_block_sptr(); auto result = gr::basic_block_sptr();
if (d_vec_block) if (d_vec_block)
result = d_vec_block; // NOLINT {
result = d_vec_block;
}
else else
result = d_source_block; // NOLINT {
result = d_source_block;
}
return result; return result;
} }

View File

@ -23,6 +23,7 @@
#ifndef GNSS_SDR_FPGA_SWITCH_H #ifndef GNSS_SDR_FPGA_SWITCH_H
#define GNSS_SDR_FPGA_SWITCH_H #define GNSS_SDR_FPGA_SWITCH_H
#include <cstdint>
#include <string> #include <string>
/** \addtogroup Signal_Source /** \addtogroup Signal_Source

View File

@ -664,6 +664,7 @@ void galileo_telemetry_decoder_gs::set_satellite(const Gnss_Satellite &satellite
d_received_tow_ms = std::numeric_limits<uint32_t>::max(); d_received_tow_ms = std::numeric_limits<uint32_t>::max();
d_E6_TOW_set = false; d_E6_TOW_set = false;
d_valid_timetag = false; d_valid_timetag = false;
d_inav_nav.init_PRN(d_satellite.get_PRN());
if (d_there_are_e6_channels) if (d_there_are_e6_channels)
{ {
const std::pair<uint32_t, uint64_t> tow_and_sample{d_received_tow_ms, 0ULL}; const std::pair<uint32_t, uint64_t> tow_and_sample{d_received_tow_ms, 0ULL};
@ -684,6 +685,7 @@ void galileo_telemetry_decoder_gs::reset()
d_fnav_nav.set_flag_TOW_set(false); d_fnav_nav.set_flag_TOW_set(false);
d_inav_nav.set_flag_TOW_set(false); d_inav_nav.set_flag_TOW_set(false);
d_inav_nav.set_TOW0_flag(false); d_inav_nav.set_TOW0_flag(false);
d_inav_nav.init_PRN(d_satellite.get_PRN());
d_last_valid_preamble = d_symbol_counter; d_last_valid_preamble = d_symbol_counter;
d_sent_tlm_failed_msg = false; d_sent_tlm_failed_msg = false;
d_E6_TOW_set = false; d_E6_TOW_set = false;

View File

@ -149,7 +149,7 @@ std::shared_ptr<Galileo_HAS_data> galileo_e6_has_msg_receiver::process_test_page
{ {
d_HAS_data.has_status = d_current_has_status; d_HAS_data.has_status = d_current_has_status;
d_HAS_data.message_id = d_current_message_id; d_HAS_data.message_id = d_current_message_id;
d_HAS_data.tow = tow - static_cast<uint32_t>(std::remainder(tow, 3600)) + d_HAS_data.header.toh; d_HAS_data.tow = tow;
auto has_data_ptr = std::make_shared<Galileo_HAS_data>(d_HAS_data); auto has_data_ptr = std::make_shared<Galileo_HAS_data>(d_HAS_data);
d_new_message = false; d_new_message = false;
d_printed_mids[d_current_message_id] = true; d_printed_mids[d_current_message_id] = true;
@ -201,7 +201,7 @@ void galileo_e6_has_msg_receiver::msg_handler_galileo_e6_has(const pmt::pmt_t& m
{ {
d_HAS_data.has_status = d_current_has_status; d_HAS_data.has_status = d_current_has_status;
d_HAS_data.message_id = d_current_message_id; d_HAS_data.message_id = d_current_message_id;
d_HAS_data.tow = tow - static_cast<uint32_t>(std::remainder(tow, 3600)) + d_HAS_data.header.toh; d_HAS_data.tow = tow;
d_printed_mids[d_current_message_id] = true; d_printed_mids[d_current_message_id] = true;
d_printed_timestamps[d_current_message_id] = timestamp; d_printed_timestamps[d_current_message_id] = timestamp;
auto has_data_ptr = std::make_shared<Galileo_HAS_data>(d_HAS_data); auto has_data_ptr = std::make_shared<Galileo_HAS_data>(d_HAS_data);
@ -699,8 +699,7 @@ void galileo_e6_has_msg_receiver::read_MT1_body(const std::string& message_body)
// count satellites in the mask // count satellites in the mask
std::bitset<HAS_MSG_SATELLITE_MASK_LENGTH> satellite_mask_bits(satellite_mask); std::bitset<HAS_MSG_SATELLITE_MASK_LENGTH> satellite_mask_bits(satellite_mask);
std::string satellite_mask_string = satellite_mask_bits.to_string(); int number_sats_this_gnss_id = satellite_mask_bits.count();
int number_sats_this_gnss_id = std::count(satellite_mask_string.begin(), satellite_mask_string.end(), '1');
d_HAS_data.satellite_submask[i] = read_has_message_body_uint64(message.substr(0, number_sats_this_gnss_id)); d_HAS_data.satellite_submask[i] = read_has_message_body_uint64(message.substr(0, number_sats_this_gnss_id));
message = std::string(message.begin() + number_sats_this_gnss_id, message.end()); message = std::string(message.begin() + number_sats_this_gnss_id, message.end());

File diff suppressed because it is too large Load Diff

View File

@ -53,9 +53,12 @@ public:
Galileo_HAS_data() = default; Galileo_HAS_data() = default;
std::vector<std::string> get_signals_in_mask(uint8_t nsys) const; //!< Get a vector of Nsys std::string with signals in mask for system nsys, with 0 <= nsys < Nsys std::vector<std::string> get_signals_in_mask(uint8_t nsys) const; //!< Get a vector of Nsys std::string with signals in mask for system nsys, with 0 <= nsys < Nsys
std::vector<std::string> get_signals_in_mask(const std::string& system) const; //!< Get a vector of Nsys std::string with signals in mask for system ("GPS"/"Galileo")
std::vector<std::string> get_systems_string() const; //!< Get Nsys system name strings std::vector<std::string> get_systems_string() const; //!< Get Nsys system name strings
std::vector<std::string> get_systems_subset_string() const; //!< Get Nsat system name strings present in clock corrections subset
std::vector<std::vector<float>> get_code_bias_m() const; //!< Get Nsat x Ncodes code biases in [m] std::vector<std::vector<float>> get_code_bias_m() const; //!< Get Nsat x Ncodes code biases in [m]
std::vector<std::vector<float>> get_phase_bias_cycle() const; //!< Get Nsat x Nphases phase biases in [cycles] std::vector<std::vector<float>> get_phase_bias_cycle() const; //!< Get Nsat x Nphases phase biases in [cycles]
std::vector<std::vector<float>> get_delta_clock_subset_correction_m() const; //!< Get Nsys_sub vectors with Nsat_sub delta clock C0 corrections in [m]
std::vector<float> get_delta_radial_m() const; //!< Get Nsat delta radial corrections in [m] std::vector<float> get_delta_radial_m() const; //!< Get Nsat delta radial corrections in [m]
std::vector<float> get_delta_radial_m(uint8_t nsys) const; //!< Get delta radial corrections in [m] for system nsys, with 0 <= nsys < Nsys std::vector<float> get_delta_radial_m(uint8_t nsys) const; //!< Get delta radial corrections in [m] for system nsys, with 0 <= nsys < Nsys
std::vector<float> get_delta_in_track_m() const; //!< Get Nsat delta in-track corrections in [m] std::vector<float> get_delta_in_track_m() const; //!< Get Nsat delta in-track corrections in [m]
@ -64,13 +67,24 @@ public:
std::vector<float> get_delta_cross_track_m(uint8_t nsys) const; //!< Get delta cross-track corrections in [m] for system nsys, with 0 <= nsys < Nsys std::vector<float> get_delta_cross_track_m(uint8_t nsys) const; //!< Get delta cross-track corrections in [m] for system nsys, with 0 <= nsys < Nsys
std::vector<float> get_delta_clock_correction_m() const; //!< Get Nsat delta clock C0 corrections in [m] std::vector<float> get_delta_clock_correction_m() const; //!< Get Nsat delta clock C0 corrections in [m]
std::vector<float> get_delta_clock_correction_m(uint8_t nsys) const; //!< Get delta clock C0 corrections in [m] for system nsys, with 0 <= nsys < Nsys std::vector<float> get_delta_clock_correction_m(uint8_t nsys) const; //!< Get delta clock C0 corrections in [m] for system nsys, with 0 <= nsys < Nsys
std::vector<float> get_delta_clock_subset_correction_m(uint8_t nsys) const; //!< Get delta clock C0 subset corrections in [m] for system nsys, with 0 <= nsys < Nsys
std::vector<int> get_PRNs_in_mask(uint8_t nsys) const; //!< Get PRNs in mask for system nsys, with 0 <= nsys < Nsys std::vector<int> get_PRNs_in_mask(uint8_t nsys) const; //!< Get PRNs in mask for system nsys, with 0 <= nsys < Nsys
std::vector<int> get_PRNs_in_mask(const std::string& system) const; //!< Get PRNs in mask for system ("GPS"/"Galileo")
std::vector<int> get_PRNs_in_submask(uint8_t nsys) const; //!< Get PRNs in submask for system nsys, with 0 <= nsys < Nsys std::vector<int> get_PRNs_in_submask(uint8_t nsys) const; //!< Get PRNs in submask for system nsys, with 0 <= nsys < Nsys
std::vector<uint16_t> get_gnss_iod(uint8_t nsys) const; //!< Get GNSS IODs for for system nsys, with 0 <= nsys < Nsys std::vector<uint16_t> get_gnss_iod(uint8_t nsys) const; //!< Get GNSS IODs for for system nsys, with 0 <= nsys < Nsys
std::vector<uint8_t> get_num_satellites() const; //!< Get Nsys number of satellites std::vector<uint8_t> get_num_satellites() const; //!< Get Nsys number of satellites
std::vector<uint8_t> get_num_subset_satellites() const; //!< Get Nsys_sub number of satellites
float get_code_bias_m(const std::string& signal, int PRN) const; //!< Get code bias in [m] for a given signal and PRN satellite
float get_phase_bias_cycle(const std::string& signal, int PRN) const; //!< Get phase bias in [cycles] for a given signal and PRN satellite
float get_delta_radial_m(const std::string& system, int prn) const; //!< Get orbital radial correction in [m] for a given system ("GPS"/"Galileo") and PRN
float get_delta_in_track_m(const std::string& system, int prn) const; //!< Get orbital in_track correction in [m] for a given system ("GPS"/"Galileo") and PRN
float get_delta_cross_track_m(const std::string& system, int prn) const; //!< Get orbital cross_track correction in [m] for a given system ("GPS"/"Galileo") and PRN
float get_clock_correction_mult_m(const std::string& system, int prn) const; //!< Get clock correction in [m], already multiplied by its Delta Clock Multiplier, for a given system ("GPS"/"Galileo") and PRN
float get_clock_subset_correction_mult_m(const std::string& system, int prn) const; //!< Get clock correction subset in [m], already multiplied by its Delta Clock Multiplier
uint16_t get_nsat() const; //!< Get total number of satellites with corrections uint16_t get_nsat() const; //!< Get total number of satellites with corrections
uint16_t get_nsat_sub() const; //!< Get number of satellites in clock subset corrections uint16_t get_nsat_sub() const; //!< Get number of satellites in clock subset corrections
uint16_t get_validity_interval_s(uint8_t validity_interval_index) const; //!< Get validity interval in [s] from the validity_interval_index uint16_t get_validity_interval_s(uint8_t validity_interval_index) const; //!< Get validity interval in [s] from the validity_interval_index
uint16_t get_gnss_iod(const std::string& system, int prn) const; //!< Get GNSS IOD from a given system ("GPS"/"Galileo") and PRN
uint8_t get_gnss_id(int nsat) const; //!< Get GNSS ID from the nsat satellite uint8_t get_gnss_id(int nsat) const; //!< Get GNSS ID from the nsat satellite
// Mask // Mask

View File

@ -19,6 +19,9 @@
#ifndef GNSS_SDR_GNSS_FREQUENCIES_H #ifndef GNSS_SDR_GNSS_FREQUENCIES_H
#define GNSS_SDR_GNSS_FREQUENCIES_H #define GNSS_SDR_GNSS_FREQUENCIES_H
#include <string>
#include <unordered_map>
/** \addtogroup Core /** \addtogroup Core
* \{ */ * \{ */
/** \addtogroup System_Parameters /** \addtogroup System_Parameters
@ -41,6 +44,21 @@ constexpr double FREQ1_BDS = 1.561098e9; //!< BeiDou B1 frequency (Hz)
constexpr double FREQ2_BDS = 1.20714e9; //!< BeiDou B2 frequency (Hz) constexpr double FREQ2_BDS = 1.20714e9; //!< BeiDou B2 frequency (Hz)
constexpr double FREQ3_BDS = 1.26852e9; //!< BeiDou B3 frequency (Hz) constexpr double FREQ3_BDS = 1.26852e9; //!< BeiDou B3 frequency (Hz)
const std::unordered_map<std::string, double> SIGNAL_FREQ_MAP = {
{"1C", FREQ1},
{"2S", FREQ2},
{"L5", FREQ5},
{"1B", FREQ1},
{"5X", FREQ5},
{"E6", FREQ6},
{"7X", FREQ7},
{"1G", FREQ1_GLO},
{"2G", FREQ2_GLO},
{"B1", FREQ1_BDS},
{"B2", FREQ2_BDS},
{"B3", FREQ3_BDS},
};
/** \} */ /** \} */
/** \} */ /** \} */

View File

@ -11,7 +11,7 @@
* GNSS-SDR is a Global Navigation Satellite System software-defined receiver. * GNSS-SDR is a Global Navigation Satellite System software-defined receiver.
* This file is part of GNSS-SDR. * This file is part of GNSS-SDR.
* *
* Copyright (C) 2010-2019 (see AUTHORS file for a list of contributors) * Copyright (C) 2010-2013 (see AUTHORS file for a list of contributors)
* SPDX-License-Identifier: GPL-3.0-or-later * SPDX-License-Identifier: GPL-3.0-or-later
* *
* ----------------------------------------------------------------------------- * -----------------------------------------------------------------------------
@ -65,9 +65,11 @@ Concurrent_Map<Gps_Acq_Assist> global_gps_acq_assist_map;
int main(int argc, char** argv) int main(int argc, char** argv)
{ {
try
{
const std::string intro_help( const std::string intro_help(
std::string("\nGNSS-SDR is an Open Source GNSS Software Defined Receiver\n") + std::string("\nGNSS-SDR is an Open Source GNSS Software Defined Receiver\n") +
"Copyright (C) 2010-2022 (see AUTHORS file for a list of contributors)\n" + "Copyright (C) 2010-2023 (see AUTHORS file for a list of contributors)\n" +
"This program comes with ABSOLUTELY NO WARRANTY;\n" + "This program comes with ABSOLUTELY NO WARRANTY;\n" +
"See COPYING file to see a copy of the General Public License\n \n"); "See COPYING file to see a copy of the General Public License\n \n");
@ -76,6 +78,13 @@ int main(int argc, char** argv)
gflags::SetVersionString(gnss_sdr_version); gflags::SetVersionString(gnss_sdr_version);
gflags::ParseCommandLineFlags(&argc, &argv, true); gflags::ParseCommandLineFlags(&argc, &argv, true);
std::cout << "Initializing GNSS-SDR v" << gnss_sdr_version << " ... Please wait.\n"; std::cout << "Initializing GNSS-SDR v" << gnss_sdr_version << " ... Please wait.\n";
}
catch (const std::exception& e)
{
std::cerr << e.what() << '\n';
std::cout << "GNSS-SDR program ended.\n";
return 1;
}
#if CUDA_GPU_ACCEL #if CUDA_GPU_ACCEL
// Reset the device // Reset the device
@ -99,6 +108,8 @@ int main(int argc, char** argv)
<< "Use gnss-sdr --log_dir=/path/to/log to change that.\n"; << "Use gnss-sdr --log_dir=/path/to/log to change that.\n";
} }
else else
{
try
{ {
const fs::path p(FLAGS_log_dir); const fs::path p(FLAGS_log_dir);
if (!fs::exists(p)) if (!fs::exists(p))
@ -116,6 +127,14 @@ int main(int argc, char** argv)
} }
std::cout << "Logging will be written at " << FLAGS_log_dir << '\n'; std::cout << "Logging will be written at " << FLAGS_log_dir << '\n';
} }
catch (const std::exception& e)
{
std::cerr << e.what() << '\n';
std::cerr << "Could not create the " << FLAGS_log_dir << " folder. GNSS-SDR program ended.\n";
gflags::ShutDownCommandLineFlags();
return 1;
}
}
} }
std::chrono::time_point<std::chrono::system_clock> start; std::chrono::time_point<std::chrono::system_clock> start;
@ -132,9 +151,7 @@ int main(int argc, char** argv)
catch (const boost::thread_resource_error& e) catch (const boost::thread_resource_error& e)
{ {
std::cerr << "Failed to create boost thread.\n"; std::cerr << "Failed to create boost thread.\n";
gflags::ShutDownCommandLineFlags(); return_code = 1;
std::cout << "GNSS-SDR program ended.\n";
return 1;
} }
catch (const boost::exception& e) catch (const boost::exception& e)
{ {
@ -147,9 +164,7 @@ int main(int argc, char** argv)
{ {
std::cerr << "Boost exception: " << boost::diagnostic_information(e) << '\n'; std::cerr << "Boost exception: " << boost::diagnostic_information(e) << '\n';
} }
gflags::ShutDownCommandLineFlags(); return_code = 1;
std::cout << "GNSS-SDR program ended.\n";
return 1;
} }
catch (const std::exception& ex) catch (const std::exception& ex)
{ {
@ -162,9 +177,7 @@ int main(int argc, char** argv)
{ {
std::cerr << "C++ Standard Library exception: " << ex.what() << '\n'; std::cerr << "C++ Standard Library exception: " << ex.what() << '\n';
} }
gflags::ShutDownCommandLineFlags(); return_code = 1;
std::cout << "GNSS-SDR program ended.\n";
return 1;
} }
catch (...) catch (...)
{ {
@ -177,9 +190,7 @@ int main(int argc, char** argv)
{ {
std::cerr << "Unexpected catch. This should not happen.\n"; std::cerr << "Unexpected catch. This should not happen.\n";
} }
gflags::ShutDownCommandLineFlags(); return_code = 1;
std::cout << "GNSS-SDR program ended.\n";
return 1;
} }
// report the elapsed time // report the elapsed time

View File

@ -37,12 +37,6 @@ if(NOT GOOGLETEST_FOUND)
if(CMAKE_GENERATOR STREQUAL Xcode) if(CMAKE_GENERATOR STREQUAL Xcode)
set(GTEST_BUILD_COMMAND "xcodebuild" "-configuration" $<$<CONFIG:Debug>:Debug>$<$<CONFIG:Release>:Release>$<$<CONFIG:RelWithDebInfo>:RelWithDebInfo>$<$<CONFIG:MinSizeRel>:MinSizeRel> "-target" "gtest_main") set(GTEST_BUILD_COMMAND "xcodebuild" "-configuration" $<$<CONFIG:Debug>:Debug>$<$<CONFIG:Release>:Release>$<$<CONFIG:RelWithDebInfo>:RelWithDebInfo>$<$<CONFIG:MinSizeRel>:MinSizeRel> "-target" "gtest_main")
endif() endif()
if((CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 5.0) OR
(CMAKE_CXX_COMPILER_ID STREQUAL "Clang" AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 5.0))
set(GOOGLETEST_GIT_TAG v${GNSSSDR_GTEST_LOCAL_VERSION})
else()
set(GOOGLETEST_GIT_TAG release-${GNSSSDR_GTEST_LOCAL_VERSION})
endif()
if(GNSSSDR_GTEST_LOCAL_VERSION VERSION_LESS 1.12.0) if(GNSSSDR_GTEST_LOCAL_VERSION VERSION_LESS 1.12.0)
set(DEBUG_DECORATION "d") set(DEBUG_DECORATION "d")
else() else()
@ -51,7 +45,7 @@ if(NOT GOOGLETEST_FOUND)
if(CMAKE_VERSION VERSION_LESS 3.2) if(CMAKE_VERSION VERSION_LESS 3.2)
ExternalProject_Add(gtest-${GNSSSDR_GTEST_LOCAL_VERSION} ExternalProject_Add(gtest-${GNSSSDR_GTEST_LOCAL_VERSION}
GIT_REPOSITORY https://github.com/google/googletest GIT_REPOSITORY https://github.com/google/googletest
GIT_TAG ${GOOGLETEST_GIT_TAG} GIT_TAG v${GNSSSDR_GTEST_LOCAL_VERSION}
SOURCE_DIR ${GNSSSDR_BINARY_DIR}/thirdparty/gtest/gtest-${GNSSSDR_GTEST_LOCAL_VERSION} SOURCE_DIR ${GNSSSDR_BINARY_DIR}/thirdparty/gtest/gtest-${GNSSSDR_GTEST_LOCAL_VERSION}
BINARY_DIR ${GNSSSDR_BINARY_DIR}/gtest-${GNSSSDR_GTEST_LOCAL_VERSION} BINARY_DIR ${GNSSSDR_BINARY_DIR}/gtest-${GNSSSDR_GTEST_LOCAL_VERSION}
CMAKE_ARGS ${GTEST_COMPILER} CMAKE_ARGS ${GTEST_COMPILER}
@ -80,7 +74,7 @@ if(NOT GOOGLETEST_FOUND)
endif() endif()
ExternalProject_Add(gtest-${GNSSSDR_GTEST_LOCAL_VERSION} ExternalProject_Add(gtest-${GNSSSDR_GTEST_LOCAL_VERSION}
GIT_REPOSITORY https://github.com/google/googletest GIT_REPOSITORY https://github.com/google/googletest
GIT_TAG ${GOOGLETEST_GIT_TAG} GIT_TAG v${GNSSSDR_GTEST_LOCAL_VERSION}
SOURCE_DIR ${GNSSSDR_BINARY_DIR}/thirdparty/gtest/gtest-${GNSSSDR_GTEST_LOCAL_VERSION} SOURCE_DIR ${GNSSSDR_BINARY_DIR}/thirdparty/gtest/gtest-${GNSSSDR_GTEST_LOCAL_VERSION}
BINARY_DIR ${GNSSSDR_BINARY_DIR}/gtest-${GNSSSDR_GTEST_LOCAL_VERSION} BINARY_DIR ${GNSSSDR_BINARY_DIR}/gtest-${GNSSSDR_GTEST_LOCAL_VERSION}
CMAKE_ARGS ${GTEST_COMPILER} CMAKE_ARGS ${GTEST_COMPILER}
@ -369,12 +363,14 @@ if(ENABLE_UNIT_TESTING_EXTRA OR ENABLE_SYSTEM_TESTING_EXTRA OR ENABLE_FPGA)
if(CMAKE_VERSION VERSION_GREATER 3.17.0) if(CMAKE_VERSION VERSION_GREATER 3.17.0)
set(GNSSTK_PATCH_COMMAND set(GNSSTK_PATCH_COMMAND
cd ${GNSSSDR_BINARY_DIR}/thirdparty/gnsstk-${GNSSSDR_GNSSTK_LOCAL_VERSION} && cd ${GNSSSDR_BINARY_DIR}/thirdparty/gnsstk-${GNSSSDR_GNSSTK_LOCAL_VERSION} &&
${Patch_EXECUTABLE} ${GNSSSDR_BINARY_DIR}/thirdparty/gnsstk-${GNSSSDR_GNSSTK_LOCAL_VERSION}/CMakeLists.txt < ${GNSSSDR_SOURCE_DIR}/src/tests/data/gnsstk_static14.patch ${Patch_EXECUTABLE} ${GNSSSDR_BINARY_DIR}/thirdparty/gnsstk-${GNSSSDR_GNSSTK_LOCAL_VERSION}/CMakeLists.txt < ${GNSSSDR_SOURCE_DIR}/src/tests/data/gnsstk_static14.patch &&
${Patch_EXECUTABLE} ${GNSSSDR_BINARY_DIR}/thirdparty/gnsstk-${GNSSSDR_GNSSTK_LOCAL_VERSION}/core/lib/GNSSCore/ObsID.hpp < ${GNSSSDR_SOURCE_DIR}/src/tests/data/gnsstk_gcc13.patch
) )
else() else()
set(GNSSTK_PATCH_COMMAND set(GNSSTK_PATCH_COMMAND
cd ${GNSSSDR_BINARY_DIR}/thirdparty/gnsstk-${GNSSSDR_GNSSTK_LOCAL_VERSION} && cd ${GNSSSDR_BINARY_DIR}/thirdparty/gnsstk-${GNSSSDR_GNSSTK_LOCAL_VERSION} &&
${Patch_EXECUTABLE} ${GNSSSDR_BINARY_DIR}/thirdparty/gnsstk-${GNSSSDR_GNSSTK_LOCAL_VERSION}/CMakeLists.txt < ${GNSSSDR_SOURCE_DIR}/src/tests/data/gnsstk_static13.patch ${Patch_EXECUTABLE} ${GNSSSDR_BINARY_DIR}/thirdparty/gnsstk-${GNSSSDR_GNSSTK_LOCAL_VERSION}/CMakeLists.txt < ${GNSSSDR_SOURCE_DIR}/src/tests/data/gnsstk_static13.patch &&
${Patch_EXECUTABLE} ${GNSSSDR_BINARY_DIR}/thirdparty/gnsstk-${GNSSSDR_GNSSTK_LOCAL_VERSION}/core/lib/GNSSCore/ObsID.hpp < ${GNSSSDR_SOURCE_DIR}/src/tests/data/gnsstk_gcc13.patch
) )
endif() endif()
# Patch only once # Patch only once
@ -408,6 +404,9 @@ if(ENABLE_UNIT_TESTING_EXTRA OR ENABLE_SYSTEM_TESTING_EXTRA OR ENABLE_FPGA)
set(GNSSTK_PARALLEL_BUILD "-j${NUMBER_OF_PROCESSORS}") set(GNSSTK_PARALLEL_BUILD "-j${NUMBER_OF_PROCESSORS}")
endif() endif()
endif() endif()
if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
set(GNSSTK_FLAGS "-DCMAKE_CXX_FLAGS:STRING=-w") # Fix for clang in aarch64
endif()
if(CMAKE_VERSION VERSION_GREATER 3.17.0) if(CMAKE_VERSION VERSION_GREATER 3.17.0)
ExternalProject_Add(gnsstk-${GNSSSDR_GNSSTK_LOCAL_VERSION} ExternalProject_Add(gnsstk-${GNSSSDR_GNSSTK_LOCAL_VERSION}
GIT_REPOSITORY https://github.com/SGL-UT/gnsstk GIT_REPOSITORY https://github.com/SGL-UT/gnsstk
@ -425,6 +424,7 @@ if(ENABLE_UNIT_TESTING_EXTRA OR ENABLE_SYSTEM_TESTING_EXTRA OR ENABLE_FPGA)
-DCMAKE_CXX_EXTENSIONS=ON -DCMAKE_CXX_EXTENSIONS=ON
-DCMAKE_C_STANDARD=11 -DCMAKE_C_STANDARD=11
-DCMAKE_C_EXTENSIONS=ON -DCMAKE_C_EXTENSIONS=ON
"${GNSSTK_FLAGS}"
BUILD_COMMAND ${GNSSTK_BUILD_COMMAND} ${GNSSTK_PARALLEL_BUILD} BUILD_COMMAND ${GNSSTK_BUILD_COMMAND} ${GNSSTK_PARALLEL_BUILD}
BUILD_BYPRODUCTS ${GNSSSDR_BINARY_DIR}/gnsstk-${GNSSSDR_GNSSTK_LOCAL_VERSION}/install/lib/${CMAKE_FIND_LIBRARY_PREFIXES}gnsstk${CMAKE_STATIC_LIBRARY_SUFFIX} BUILD_BYPRODUCTS ${GNSSSDR_BINARY_DIR}/gnsstk-${GNSSSDR_GNSSTK_LOCAL_VERSION}/install/lib/${CMAKE_FIND_LIBRARY_PREFIXES}gnsstk${CMAKE_STATIC_LIBRARY_SUFFIX}
UPDATE_COMMAND "" UPDATE_COMMAND ""

View File

@ -0,0 +1,12 @@
SPDX-License-Identifier: GPL-3.0-or-later
SPDX-FileCopyrightText: 2022 Carles Fernandez-Prades <carles.fernandez@cttc.es>
--- ObsID.hpp 2023-01-23 16:53:25.000000000 +0100
+++ ObsID.hpp 2023-01-23 16:55:14.000000000 +0100
@@ -47,6 +47,7 @@
#ifndef OBSID_HPP
#define OBSID_HPP
+#include <cstdint>
#include <iostream>
#include <iomanip>
#include <sstream>

View File

@ -353,6 +353,10 @@ TEST(HAS_Test, Decoder)
EXPECT_EQ(has_message->phase_discontinuity_indicator[has_message->get_PRNs_in_mask(0).size() + i][2], phase_discontinuity_indicator_expected_gal[i]); EXPECT_EQ(has_message->phase_discontinuity_indicator[has_message->get_PRNs_in_mask(0).size() + i][2], phase_discontinuity_indicator_expected_gal[i]);
EXPECT_EQ(has_message->phase_discontinuity_indicator[has_message->get_PRNs_in_mask(0).size() + i][3], phase_discontinuity_indicator_expected_gal[i]); EXPECT_EQ(has_message->phase_discontinuity_indicator[has_message->get_PRNs_in_mask(0).size() + i][3], phase_discontinuity_indicator_expected_gal[i]);
} }
EXPECT_FLOAT_EQ(has_message->get_code_bias_m("L1 C/A", 10), -2.64 * HAS_MSG_CODE_BIAS_SCALE_FACTOR);
EXPECT_FLOAT_EQ(has_message->get_code_bias_m("L1 C/A", 11), 0.0);
EXPECT_FLOAT_EQ(has_message->get_code_bias_m("E1-C", 36), -1.98 * HAS_MSG_CODE_BIAS_SCALE_FACTOR);
EXPECT_FLOAT_EQ(has_message->get_code_bias_m("E1-C", 37), 0.0);
} }
else else
{ {