2017-06-21 04:44:44 +00:00
|
|
|
/*!
|
2017-08-17 04:40:05 +00:00
|
|
|
* \file glonass_gnav_navigation_message.cc
|
2017-06-21 04:44:44 +00:00
|
|
|
* \brief Implementation of a GLONASS GNAV Data message decoder as described in GLONASS ICD (Edition 5.1)
|
2017-08-17 04:40:05 +00:00
|
|
|
* \note Code added as part of GSoC 2017 program
|
2017-06-21 04:44:44 +00:00
|
|
|
* \author Damian Miralles, 2017. dmiralles2009(at)gmail.com
|
2017-08-17 04:40:05 +00:00
|
|
|
* \see <a href="http://russianspacesystems.ru/wp-content/uploads/2016/08/ICD_GLONASS_eng_v5.1.pdf">GLONASS ICD</a>
|
2017-06-21 04:44:44 +00:00
|
|
|
*
|
2020-07-28 14:57:15 +00:00
|
|
|
* -----------------------------------------------------------------------------
|
2017-06-21 04:44:44 +00:00
|
|
|
*
|
2020-12-30 12:35:06 +00:00
|
|
|
* GNSS-SDR is a Global Navigation Satellite System software-defined receiver.
|
2017-06-21 04:44:44 +00:00
|
|
|
* This file is part of GNSS-SDR.
|
|
|
|
*
|
2020-12-30 12:35:06 +00:00
|
|
|
* Copyright (C) 2010-2020 (see AUTHORS file for a list of contributors)
|
2020-02-08 00:20:02 +00:00
|
|
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
2017-06-21 04:44:44 +00:00
|
|
|
*
|
2020-07-28 14:57:15 +00:00
|
|
|
* -----------------------------------------------------------------------------
|
2017-06-21 04:44:44 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
#include "glonass_gnav_navigation_message.h"
|
2019-03-05 07:59:04 +00:00
|
|
|
#include "MATH_CONSTANTS.h" // for TWO_N20, TWO_N30, TWO_N14, TWO_N15, TWO_N18
|
2018-02-26 02:15:53 +00:00
|
|
|
#include "gnss_satellite.h"
|
2017-08-29 23:32:34 +00:00
|
|
|
#include <glog/logging.h>
|
2019-08-24 15:34:12 +00:00
|
|
|
#include <cstddef> // for size_t
|
2019-03-05 07:59:04 +00:00
|
|
|
#include <ostream> // for operator<<
|
2017-06-21 04:44:44 +00:00
|
|
|
|
|
|
|
|
2020-06-10 08:15:59 +00:00
|
|
|
Glonass_Gnav_Navigation_Message::Glonass_Gnav_Navigation_Message()
|
2017-06-21 04:44:44 +00:00
|
|
|
{
|
|
|
|
auto gnss_sat = Gnss_Satellite();
|
2018-03-03 01:03:39 +00:00
|
|
|
std::string _system("GLONASS");
|
2019-08-18 20:16:13 +00:00
|
|
|
// TODO SHould number of channels be hardcoded?
|
2018-08-13 23:13:07 +00:00
|
|
|
for (uint32_t i = 1; i < 14; i++)
|
2018-01-26 11:40:58 +00:00
|
|
|
{
|
|
|
|
satelliteBlock[i] = gnss_sat.what_block(_system, i);
|
|
|
|
}
|
2017-06-21 04:44:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2022-08-26 13:27:01 +00:00
|
|
|
bool Glonass_Gnav_Navigation_Message::CRC_test(std::bitset<GLONASS_GNAV_STRING_BITS>& bits) const
|
2017-07-07 06:02:50 +00:00
|
|
|
{
|
2019-07-19 16:23:36 +00:00
|
|
|
uint32_t sum_bits = 0;
|
2018-08-13 23:13:07 +00:00
|
|
|
int32_t sum_hamming = 0;
|
2019-07-19 16:23:36 +00:00
|
|
|
std::vector<uint32_t> string_bits(GLONASS_GNAV_STRING_BITS);
|
2018-08-13 23:13:07 +00:00
|
|
|
|
|
|
|
// Populate data and hamming code vectors
|
2019-08-24 15:34:12 +00:00
|
|
|
for (size_t i = 0; i < string_bits.size(); i++)
|
2018-01-26 11:40:58 +00:00
|
|
|
{
|
2019-07-19 16:23:36 +00:00
|
|
|
string_bits[i] = static_cast<uint32_t>(bits[i]);
|
2018-01-26 11:40:58 +00:00
|
|
|
}
|
2017-07-12 20:11:53 +00:00
|
|
|
|
2018-08-13 23:13:07 +00:00
|
|
|
// Compute C1 term
|
2017-07-10 06:00:49 +00:00
|
|
|
sum_bits = 0;
|
2018-12-03 17:03:25 +00:00
|
|
|
for (int i : GLONASS_GNAV_CRC_I_INDEX)
|
2017-07-07 06:02:50 +00:00
|
|
|
{
|
2018-12-03 17:03:25 +00:00
|
|
|
sum_bits += string_bits[i - 1];
|
2017-07-07 06:02:50 +00:00
|
|
|
}
|
2020-07-19 12:26:15 +00:00
|
|
|
const int32_t C1 = string_bits[0] ^ (sum_bits % 2);
|
2017-07-07 06:02:50 +00:00
|
|
|
|
2018-08-13 23:13:07 +00:00
|
|
|
// Compute C2 term
|
2017-07-10 06:00:49 +00:00
|
|
|
sum_bits = 0;
|
2018-12-03 17:03:25 +00:00
|
|
|
for (int j : GLONASS_GNAV_CRC_J_INDEX)
|
2017-07-07 06:02:50 +00:00
|
|
|
{
|
2018-12-03 17:03:25 +00:00
|
|
|
sum_bits += string_bits[j - 1];
|
2017-07-07 06:02:50 +00:00
|
|
|
}
|
2020-07-19 12:26:15 +00:00
|
|
|
const int32_t C2 = (string_bits[1]) ^ (sum_bits % 2);
|
2017-07-07 06:02:50 +00:00
|
|
|
|
2018-08-13 23:13:07 +00:00
|
|
|
// Compute C3 term
|
2017-07-10 06:00:49 +00:00
|
|
|
sum_bits = 0;
|
2018-12-03 17:03:25 +00:00
|
|
|
for (int k : GLONASS_GNAV_CRC_K_INDEX)
|
2017-07-07 06:02:50 +00:00
|
|
|
{
|
2018-12-03 17:03:25 +00:00
|
|
|
sum_bits += string_bits[k - 1];
|
2017-07-07 06:02:50 +00:00
|
|
|
}
|
2020-07-19 12:26:15 +00:00
|
|
|
const int32_t C3 = string_bits[2] ^ (sum_bits % 2);
|
2017-07-07 06:02:50 +00:00
|
|
|
|
2018-08-13 23:13:07 +00:00
|
|
|
// Compute C4 term
|
2017-07-10 06:00:49 +00:00
|
|
|
sum_bits = 0;
|
2018-12-03 17:03:25 +00:00
|
|
|
for (int l : GLONASS_GNAV_CRC_L_INDEX)
|
2017-07-07 06:02:50 +00:00
|
|
|
{
|
2018-12-03 17:03:25 +00:00
|
|
|
sum_bits += string_bits[l - 1];
|
2017-07-07 06:02:50 +00:00
|
|
|
}
|
2020-07-19 12:26:15 +00:00
|
|
|
const int32_t C4 = string_bits[3] ^ (sum_bits % 2);
|
2017-07-07 06:02:50 +00:00
|
|
|
|
2018-08-13 23:13:07 +00:00
|
|
|
// Compute C5 term
|
2017-07-10 06:00:49 +00:00
|
|
|
sum_bits = 0;
|
2018-12-03 17:03:25 +00:00
|
|
|
for (int m : GLONASS_GNAV_CRC_M_INDEX)
|
2017-07-07 06:02:50 +00:00
|
|
|
{
|
2018-12-03 17:03:25 +00:00
|
|
|
sum_bits += string_bits[m - 1];
|
2017-07-07 06:02:50 +00:00
|
|
|
}
|
2020-07-19 12:26:15 +00:00
|
|
|
const int32_t C5 = string_bits[4] ^ (sum_bits % 2);
|
2017-07-07 06:02:50 +00:00
|
|
|
|
2018-08-13 23:13:07 +00:00
|
|
|
// Compute C6 term
|
2017-07-10 06:00:49 +00:00
|
|
|
sum_bits = 0;
|
2018-12-03 17:03:25 +00:00
|
|
|
for (int n : GLONASS_GNAV_CRC_N_INDEX)
|
2017-07-07 06:02:50 +00:00
|
|
|
{
|
2018-12-03 17:03:25 +00:00
|
|
|
sum_bits += string_bits[n - 1];
|
2017-07-07 06:02:50 +00:00
|
|
|
}
|
2020-07-19 12:26:15 +00:00
|
|
|
const int32_t C6 = string_bits[5] ^ (sum_bits % 2);
|
2017-07-07 06:02:50 +00:00
|
|
|
|
2018-08-13 23:13:07 +00:00
|
|
|
// Compute C7 term
|
2017-07-10 06:00:49 +00:00
|
|
|
sum_bits = 0;
|
2018-12-03 17:03:25 +00:00
|
|
|
for (int p : GLONASS_GNAV_CRC_P_INDEX)
|
2017-07-07 06:02:50 +00:00
|
|
|
{
|
2018-12-03 17:03:25 +00:00
|
|
|
sum_bits += string_bits[p - 1];
|
2017-07-07 06:02:50 +00:00
|
|
|
}
|
2020-07-19 12:26:15 +00:00
|
|
|
const int32_t C7 = string_bits[6] ^ (sum_bits % 2);
|
2017-07-07 06:02:50 +00:00
|
|
|
|
2018-08-13 23:13:07 +00:00
|
|
|
// Compute C_Sigma term
|
2017-07-10 06:00:49 +00:00
|
|
|
sum_bits = 0;
|
2018-12-03 17:03:25 +00:00
|
|
|
for (int q : GLONASS_GNAV_CRC_Q_INDEX)
|
2017-07-07 06:02:50 +00:00
|
|
|
{
|
2018-12-03 17:03:25 +00:00
|
|
|
sum_bits += string_bits[q - 1];
|
2017-07-07 06:02:50 +00:00
|
|
|
}
|
2018-08-13 23:13:07 +00:00
|
|
|
for (int32_t q = 0; q < 8; q++)
|
2017-07-10 06:00:49 +00:00
|
|
|
{
|
2017-08-19 21:04:14 +00:00
|
|
|
sum_hamming += string_bits[q];
|
2017-07-10 06:00:49 +00:00
|
|
|
}
|
2020-07-19 12:26:15 +00:00
|
|
|
const int32_t C_Sigma = (sum_hamming % 2) ^ (sum_bits % 2);
|
2017-07-10 06:00:49 +00:00
|
|
|
|
2018-08-13 23:13:07 +00:00
|
|
|
// Verification of the data
|
2017-09-16 04:25:37 +00:00
|
|
|
// (a-i) All checksums (C1,...,C7 and C_Sigma) are equal to zero
|
2018-03-03 01:03:39 +00:00
|
|
|
if ((C1 + C2 + C3 + C4 + C5 + C6 + C7 + C_Sigma) == 0)
|
2017-07-10 06:00:49 +00:00
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
2020-04-10 11:44:45 +00:00
|
|
|
// (a-ii) Only one of the checksums (C1,...,C7) is equal to 1 and C_Sigma = 1
|
|
|
|
if (C_Sigma == 1 && C1 + C2 + C3 + C4 + C5 + C6 + C7 == 1)
|
2017-07-10 06:00:49 +00:00
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
2018-12-04 12:20:49 +00:00
|
|
|
|
2022-08-26 13:27:01 +00:00
|
|
|
if (C_Sigma && (sum_bits & 1))
|
|
|
|
{
|
|
|
|
int32_t syndrome = C1;
|
|
|
|
syndrome |= (C2 ? 2 : 0);
|
|
|
|
syndrome |= (C3 ? 4 : 0);
|
|
|
|
syndrome |= (C4 ? 8 : 0);
|
|
|
|
syndrome |= (C5 ? 16 : 0);
|
|
|
|
syndrome |= (C6 ? 32 : 0);
|
|
|
|
syndrome |= (C7 ? 64 : 0);
|
|
|
|
if (syndrome < 85)
|
|
|
|
{
|
|
|
|
const int32_t locator = GLONASS_GNAV_ECC_LOCATOR[syndrome];
|
|
|
|
bits[locator] = !bits[locator];
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// All other conditions are assumed errors.
|
2018-12-04 12:20:49 +00:00
|
|
|
return false;
|
2017-07-07 06:02:50 +00:00
|
|
|
}
|
|
|
|
|
2017-06-21 04:44:44 +00:00
|
|
|
|
2021-04-11 12:47:36 +00:00
|
|
|
bool Glonass_Gnav_Navigation_Message::read_navigation_bool(const std::bitset<GLONASS_GNAV_STRING_BITS>& bits, const std::vector<std::pair<int32_t, int32_t>>& parameter) const
|
2017-06-21 04:44:44 +00:00
|
|
|
{
|
2024-01-13 11:07:06 +00:00
|
|
|
bool value = bits[GLONASS_GNAV_STRING_BITS - parameter[0].first];
|
2017-06-21 04:44:44 +00:00
|
|
|
return value;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-04-11 12:47:36 +00:00
|
|
|
uint64_t Glonass_Gnav_Navigation_Message::read_navigation_unsigned(const std::bitset<GLONASS_GNAV_STRING_BITS>& bits, const std::vector<std::pair<int32_t, int32_t>>& parameter) const
|
2017-06-21 04:44:44 +00:00
|
|
|
{
|
2018-08-14 12:07:37 +00:00
|
|
|
uint64_t value = 0ULL;
|
2024-01-13 11:07:06 +00:00
|
|
|
for (const auto& p : parameter)
|
2017-06-21 04:44:44 +00:00
|
|
|
{
|
2024-01-13 11:07:06 +00:00
|
|
|
for (int32_t j = 0; j < p.second; j++)
|
2017-06-21 04:44:44 +00:00
|
|
|
{
|
2024-01-13 11:07:06 +00:00
|
|
|
value = (value << 1U) | static_cast<uint64_t>(bits[GLONASS_GNAV_STRING_BITS - p.first - j]);
|
2017-06-21 04:44:44 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return value;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-04-11 12:47:36 +00:00
|
|
|
int64_t Glonass_Gnav_Navigation_Message::read_navigation_signed(const std::bitset<GLONASS_GNAV_STRING_BITS>& bits, const std::vector<std::pair<int32_t, int32_t>>& parameter) const
|
2017-06-21 04:44:44 +00:00
|
|
|
{
|
2018-08-14 12:07:37 +00:00
|
|
|
int64_t value = 0LL;
|
2024-01-13 11:07:06 +00:00
|
|
|
int64_t sign = (bits[GLONASS_GNAV_STRING_BITS - parameter[0].first] == 1) ? -1LL : 1LL;
|
|
|
|
|
|
|
|
// const int32_t num_of_slices = parameter.size();
|
|
|
|
for (const auto& p : parameter)
|
2017-06-21 04:44:44 +00:00
|
|
|
{
|
2024-01-13 11:07:06 +00:00
|
|
|
for (int32_t j = 1; j < p.second; j++)
|
2017-06-21 04:44:44 +00:00
|
|
|
{
|
2024-01-13 11:07:06 +00:00
|
|
|
value = (value << 1) + bits[GLONASS_GNAV_STRING_BITS - p.first - j];
|
2017-06-21 04:44:44 +00:00
|
|
|
}
|
|
|
|
}
|
2018-03-03 01:03:39 +00:00
|
|
|
return (sign * value);
|
2017-06-21 04:44:44 +00:00
|
|
|
}
|
|
|
|
|
2017-07-10 06:00:49 +00:00
|
|
|
|
2018-08-13 23:13:07 +00:00
|
|
|
uint32_t Glonass_Gnav_Navigation_Message::get_frame_number(uint32_t satellite_slot_number)
|
2017-07-07 06:02:50 +00:00
|
|
|
{
|
2018-08-17 16:10:53 +00:00
|
|
|
uint32_t frame_ID = 0U;
|
2017-07-07 06:02:50 +00:00
|
|
|
|
2018-03-03 01:03:39 +00:00
|
|
|
if (satellite_slot_number >= 1 and satellite_slot_number <= 5)
|
2017-07-07 06:02:50 +00:00
|
|
|
{
|
2018-08-17 16:10:53 +00:00
|
|
|
frame_ID = 1U;
|
2017-07-07 06:02:50 +00:00
|
|
|
}
|
2018-03-03 01:03:39 +00:00
|
|
|
else if (satellite_slot_number >= 6 and satellite_slot_number <= 10)
|
2017-07-07 06:02:50 +00:00
|
|
|
{
|
2018-08-17 16:10:53 +00:00
|
|
|
frame_ID = 2U;
|
2017-07-07 06:02:50 +00:00
|
|
|
}
|
2018-03-03 01:03:39 +00:00
|
|
|
else if (satellite_slot_number >= 11 and satellite_slot_number <= 15)
|
2017-07-07 06:02:50 +00:00
|
|
|
{
|
2018-08-17 16:10:53 +00:00
|
|
|
frame_ID = 3U;
|
2017-07-07 06:02:50 +00:00
|
|
|
}
|
2018-03-03 01:03:39 +00:00
|
|
|
else if (satellite_slot_number >= 16 and satellite_slot_number <= 20)
|
2017-07-07 06:02:50 +00:00
|
|
|
{
|
2018-08-17 16:10:53 +00:00
|
|
|
frame_ID = 4U;
|
2017-07-07 06:02:50 +00:00
|
|
|
}
|
2018-03-03 01:03:39 +00:00
|
|
|
else if (satellite_slot_number >= 21 and satellite_slot_number <= 24)
|
2017-07-07 06:02:50 +00:00
|
|
|
{
|
2018-08-17 16:10:53 +00:00
|
|
|
frame_ID = 5U;
|
2017-07-07 06:02:50 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2017-09-16 04:25:37 +00:00
|
|
|
LOG(WARNING) << "GLONASS GNAV: Invalid Satellite Slot Number";
|
2018-08-17 16:10:53 +00:00
|
|
|
frame_ID = 0U;
|
2017-07-07 06:02:50 +00:00
|
|
|
}
|
2017-07-12 14:35:57 +00:00
|
|
|
|
|
|
|
return frame_ID;
|
2017-07-07 06:02:50 +00:00
|
|
|
}
|
|
|
|
|
2017-08-31 22:51:50 +00:00
|
|
|
|
2018-12-03 18:01:47 +00:00
|
|
|
int32_t Glonass_Gnav_Navigation_Message::string_decoder(const std::string& frame_string)
|
2017-06-21 04:44:44 +00:00
|
|
|
{
|
2018-08-13 23:13:07 +00:00
|
|
|
int32_t J = 0;
|
2018-08-17 16:10:53 +00:00
|
|
|
d_frame_ID = 0U;
|
2022-08-15 16:25:13 +00:00
|
|
|
uint64_t P_1_tmp = 0;
|
2017-06-21 04:44:44 +00:00
|
|
|
|
2017-09-16 04:25:37 +00:00
|
|
|
// Unpack bytes to bits
|
2022-08-26 13:27:01 +00:00
|
|
|
std::bitset<GLONASS_GNAV_STRING_BITS> string_bits(frame_string);
|
2017-06-21 04:44:44 +00:00
|
|
|
|
2017-09-16 04:25:37 +00:00
|
|
|
// Perform data verification and exit code if error in bit sequence
|
2017-08-31 22:51:50 +00:00
|
|
|
flag_CRC_test = CRC_test(string_bits);
|
2018-03-03 01:03:39 +00:00
|
|
|
if (flag_CRC_test == false)
|
2019-02-11 20:13:02 +00:00
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
2017-07-12 20:11:53 +00:00
|
|
|
|
2017-06-21 04:44:44 +00:00
|
|
|
// Decode all 15 string messages
|
2018-08-13 23:13:07 +00:00
|
|
|
d_string_ID = static_cast<uint32_t>(read_navigation_unsigned(string_bits, STRING_ID));
|
2018-01-26 11:40:58 +00:00
|
|
|
switch (d_string_ID)
|
2018-03-03 01:03:39 +00:00
|
|
|
{
|
|
|
|
case 1:
|
2018-08-13 23:13:07 +00:00
|
|
|
// --- It is string 1 -----------------------------------------------
|
2022-08-15 16:25:13 +00:00
|
|
|
P_1_tmp = read_navigation_unsigned(string_bits, P1);
|
|
|
|
gnav_ephemeris.d_P_1 = (P_1_tmp == 0) ? 0. : (P_1_tmp + 1) * 15;
|
2018-03-03 01:03:39 +00:00
|
|
|
gnav_ephemeris.d_t_k = static_cast<double>(read_navigation_unsigned(string_bits, T_K_HR)) * 3600 +
|
|
|
|
static_cast<double>(read_navigation_unsigned(string_bits, T_K_MIN)) * 60 +
|
|
|
|
static_cast<double>(read_navigation_unsigned(string_bits, T_K_SEC)) * 30;
|
|
|
|
gnav_ephemeris.d_VXn = static_cast<double>(read_navigation_signed(string_bits, X_N_DOT)) * TWO_N20;
|
|
|
|
gnav_ephemeris.d_AXn = static_cast<double>(read_navigation_signed(string_bits, X_N_DOT_DOT)) * TWO_N30;
|
|
|
|
gnav_ephemeris.d_Xn = static_cast<double>(read_navigation_signed(string_bits, X_N)) * TWO_N11;
|
|
|
|
|
|
|
|
flag_ephemeris_str_1 = true;
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 2:
|
2018-08-13 23:13:07 +00:00
|
|
|
// --- It is string 2 -----------------------------------------------
|
2018-03-03 01:03:39 +00:00
|
|
|
if (flag_ephemeris_str_1 == true)
|
|
|
|
{
|
|
|
|
gnav_ephemeris.d_B_n = static_cast<double>(read_navigation_unsigned(string_bits, B_N));
|
2023-11-14 12:42:44 +00:00
|
|
|
gnav_ephemeris.d_P_2 = read_navigation_bool(string_bits, P2);
|
2018-03-03 01:03:39 +00:00
|
|
|
gnav_ephemeris.d_t_b = static_cast<double>(read_navigation_unsigned(string_bits, T_B)) * 15 * 60;
|
|
|
|
gnav_ephemeris.d_VYn = static_cast<double>(read_navigation_signed(string_bits, Y_N_DOT)) * TWO_N20;
|
|
|
|
gnav_ephemeris.d_AYn = static_cast<double>(read_navigation_signed(string_bits, Y_N_DOT_DOT)) * TWO_N30;
|
|
|
|
gnav_ephemeris.d_Yn = static_cast<double>(read_navigation_signed(string_bits, Y_N)) * TWO_N11;
|
|
|
|
|
|
|
|
gnav_ephemeris.d_iode = read_navigation_unsigned(string_bits, T_B);
|
|
|
|
flag_ephemeris_str_2 = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 3:
|
|
|
|
// --- It is string 3 ----------------------------------------------
|
|
|
|
if (flag_ephemeris_str_2 == true)
|
|
|
|
{
|
2023-11-14 12:42:44 +00:00
|
|
|
gnav_ephemeris.d_P_3 = read_navigation_bool(string_bits, P3);
|
2018-03-03 01:03:39 +00:00
|
|
|
gnav_ephemeris.d_gamma_n = static_cast<double>(read_navigation_signed(string_bits, GAMMA_N)) * TWO_N40;
|
|
|
|
gnav_ephemeris.d_P = static_cast<double>(read_navigation_unsigned(string_bits, P));
|
2023-11-14 12:42:44 +00:00
|
|
|
gnav_ephemeris.d_l3rd_n = read_navigation_bool(string_bits, EPH_L_N);
|
2018-03-03 01:03:39 +00:00
|
|
|
gnav_ephemeris.d_VZn = static_cast<double>(read_navigation_signed(string_bits, Z_N_DOT)) * TWO_N20;
|
|
|
|
gnav_ephemeris.d_AZn = static_cast<double>(read_navigation_signed(string_bits, Z_N_DOT_DOT)) * TWO_N30;
|
|
|
|
gnav_ephemeris.d_Zn = static_cast<double>(read_navigation_signed(string_bits, Z_N)) * TWO_N11;
|
|
|
|
|
|
|
|
flag_ephemeris_str_3 = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 4:
|
|
|
|
// --- It is string 4 ----------------------------------------------
|
|
|
|
if (flag_ephemeris_str_3 == true)
|
|
|
|
{
|
|
|
|
gnav_ephemeris.d_tau_n = static_cast<double>(read_navigation_signed(string_bits, TAU_N)) * TWO_N30;
|
|
|
|
gnav_ephemeris.d_Delta_tau_n = static_cast<double>(read_navigation_signed(string_bits, DELTA_TAU_N)) * TWO_N30;
|
|
|
|
gnav_ephemeris.d_E_n = static_cast<double>(read_navigation_unsigned(string_bits, E_N));
|
2023-11-14 12:42:44 +00:00
|
|
|
gnav_ephemeris.d_P_4 = read_navigation_bool(string_bits, P4);
|
2018-03-03 01:03:39 +00:00
|
|
|
gnav_ephemeris.d_F_T = static_cast<double>(read_navigation_unsigned(string_bits, F_T));
|
|
|
|
gnav_ephemeris.d_N_T = static_cast<double>(read_navigation_unsigned(string_bits, N_T));
|
|
|
|
gnav_ephemeris.d_n = static_cast<double>(read_navigation_unsigned(string_bits, N));
|
|
|
|
gnav_ephemeris.d_M = static_cast<double>(read_navigation_unsigned(string_bits, M));
|
|
|
|
|
|
|
|
// Fill in ephemeris deliverables in the code
|
|
|
|
flag_update_slot_number = true;
|
2018-08-13 23:13:07 +00:00
|
|
|
gnav_ephemeris.i_satellite_slot_number = static_cast<uint32_t>(gnav_ephemeris.d_n);
|
2021-02-20 23:01:56 +00:00
|
|
|
gnav_ephemeris.PRN = static_cast<uint32_t>(gnav_ephemeris.d_n);
|
2018-03-03 01:03:39 +00:00
|
|
|
|
|
|
|
flag_ephemeris_str_4 = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 5:
|
|
|
|
// --- It is string 5 ----------------------------------------------
|
|
|
|
if (flag_ephemeris_str_4 == true)
|
|
|
|
{
|
2019-02-22 09:47:24 +00:00
|
|
|
gnav_utc_model.d_N_A = static_cast<double>(read_navigation_unsigned(string_bits, DAY_NUMBER_A));
|
2018-03-03 01:03:39 +00:00
|
|
|
gnav_utc_model.d_tau_c = static_cast<double>(read_navigation_signed(string_bits, TAU_C)) * TWO_N31;
|
|
|
|
gnav_utc_model.d_N_4 = static_cast<double>(read_navigation_unsigned(string_bits, N_4));
|
|
|
|
gnav_utc_model.d_tau_gps = static_cast<double>(read_navigation_signed(string_bits, TAU_GPS)) * TWO_N30;
|
2023-11-14 12:42:44 +00:00
|
|
|
gnav_ephemeris.d_l5th_n = read_navigation_bool(string_bits, ALM_L_N);
|
2018-03-03 01:03:39 +00:00
|
|
|
|
|
|
|
flag_utc_model_str_5 = true;
|
|
|
|
|
|
|
|
// Compute Year and DoY based on Algorithm A3.11 of GLONASS ICD
|
|
|
|
// 1). Current year number J in the four-year interval is calculated
|
|
|
|
if (gnav_ephemeris.d_N_T >= 1 && gnav_ephemeris.d_N_T <= 366)
|
|
|
|
{
|
|
|
|
J = 1;
|
|
|
|
}
|
|
|
|
else if (gnav_ephemeris.d_N_T >= 367 && gnav_ephemeris.d_N_T <= 731)
|
|
|
|
{
|
|
|
|
J = 2;
|
|
|
|
}
|
|
|
|
else if (gnav_ephemeris.d_N_T >= 732 && gnav_ephemeris.d_N_T <= 1096)
|
|
|
|
{
|
|
|
|
J = 3;
|
|
|
|
}
|
|
|
|
else if (gnav_ephemeris.d_N_T >= 1097 && gnav_ephemeris.d_N_T <= 1461)
|
|
|
|
{
|
|
|
|
J = 4;
|
|
|
|
}
|
|
|
|
// 2). Current year in common form is calculated by the following formula:
|
|
|
|
gnav_ephemeris.d_yr = 1996 + 4.0 * (gnav_utc_model.d_N_4 - 1.0) + (J - 1.0);
|
|
|
|
gnav_ephemeris.d_tau_c = gnav_utc_model.d_tau_c;
|
|
|
|
|
|
|
|
// 3). Set TOW once the year has been defined, it helps with leap second determination
|
|
|
|
if (flag_ephemeris_str_1 == true)
|
|
|
|
{
|
|
|
|
gnav_ephemeris.glot_to_gpst(gnav_ephemeris.d_t_k + 10, gnav_utc_model.d_tau_c, gnav_utc_model.d_tau_gps, &gnav_ephemeris.d_WN, &gnav_ephemeris.d_TOW);
|
|
|
|
flag_TOW_set = true;
|
|
|
|
flag_TOW_new = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 4) Set time of day (tod) when ephemeris data is complety decoded
|
|
|
|
gnav_ephemeris.d_tod = gnav_ephemeris.d_t_k + 2 * d_string_ID;
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 6:
|
|
|
|
// --- It is string 6 ----------------------------------------------
|
2019-02-22 09:47:24 +00:00
|
|
|
i_alm_satellite_slot_number = static_cast<uint32_t>(read_navigation_unsigned(string_bits, N_A));
|
2018-03-03 01:03:39 +00:00
|
|
|
d_frame_ID = get_frame_number(i_alm_satellite_slot_number);
|
|
|
|
// Make sure a valid frame_ID or satellite slot number is returned
|
|
|
|
if (d_frame_ID == 0)
|
2019-02-11 20:13:02 +00:00
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
2018-03-03 01:03:39 +00:00
|
|
|
|
2023-11-14 12:42:44 +00:00
|
|
|
gnav_almanac[i_alm_satellite_slot_number - 1].d_C_n = read_navigation_bool(string_bits, C_N);
|
2018-03-03 01:03:39 +00:00
|
|
|
gnav_almanac[i_alm_satellite_slot_number - 1].d_M_n_A = static_cast<double>(read_navigation_unsigned(string_bits, M_N_A));
|
2019-02-22 09:47:24 +00:00
|
|
|
gnav_almanac[i_alm_satellite_slot_number - 1].d_n_A = static_cast<double>(read_navigation_unsigned(string_bits, N_A));
|
2018-03-03 01:03:39 +00:00
|
|
|
gnav_almanac[i_alm_satellite_slot_number - 1].d_tau_n_A = static_cast<double>(read_navigation_unsigned(string_bits, TAU_N_A)) * TWO_N18;
|
2020-07-05 18:20:02 +00:00
|
|
|
gnav_almanac[i_alm_satellite_slot_number - 1].d_lambda_n_A = static_cast<double>(read_navigation_signed(string_bits, LAMBDA_N_A)) * TWO_N20 * GNSS_PI;
|
|
|
|
gnav_almanac[i_alm_satellite_slot_number - 1].d_Delta_i_n_A = static_cast<double>(read_navigation_signed(string_bits, DELTA_I_N_A)) * TWO_N20 * GNSS_PI;
|
2018-03-03 01:03:39 +00:00
|
|
|
gnav_almanac[i_alm_satellite_slot_number - 1].d_epsilon_n_A = static_cast<double>(read_navigation_unsigned(string_bits, EPSILON_N_A)) * TWO_N20;
|
|
|
|
|
|
|
|
flag_almanac_str_6 = true;
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 7:
|
|
|
|
// --- It is string 7 ----------------------------------------------
|
|
|
|
if (flag_almanac_str_6 == true)
|
|
|
|
{
|
2020-07-05 18:20:02 +00:00
|
|
|
gnav_almanac[i_alm_satellite_slot_number - 1].d_omega_n_A = static_cast<double>(read_navigation_signed(string_bits, OMEGA_N_A)) * TWO_N15 * GNSS_PI;
|
2018-03-03 01:03:39 +00:00
|
|
|
gnav_almanac[i_alm_satellite_slot_number - 1].d_t_lambda_n_A = static_cast<double>(read_navigation_unsigned(string_bits, T_LAMBDA_N_A)) * TWO_N5;
|
|
|
|
gnav_almanac[i_alm_satellite_slot_number - 1].d_Delta_T_n_A = static_cast<double>(read_navigation_signed(string_bits, DELTA_T_N_A)) * TWO_N9;
|
|
|
|
gnav_almanac[i_alm_satellite_slot_number - 1].d_Delta_T_n_A_dot = static_cast<double>(read_navigation_signed(string_bits, DELTA_T_DOT_N_A)) * TWO_N14;
|
|
|
|
gnav_almanac[i_alm_satellite_slot_number - 1].d_H_n_A = static_cast<double>(read_navigation_unsigned(string_bits, H_N_A));
|
2023-11-14 12:42:44 +00:00
|
|
|
gnav_almanac[i_alm_satellite_slot_number - 1].d_l_n = read_navigation_bool(string_bits, ALM_L_N);
|
2018-03-03 01:03:39 +00:00
|
|
|
|
|
|
|
// Set satellite information for redundancy purposes
|
|
|
|
if (gnav_almanac[i_alm_satellite_slot_number - 1].d_H_n_A > 24)
|
|
|
|
{
|
|
|
|
gnav_almanac[i_alm_satellite_slot_number - 1].i_satellite_freq_channel = gnav_almanac[i_alm_satellite_slot_number - 1].d_H_n_A - 32.0;
|
|
|
|
}
|
|
|
|
gnav_almanac[i_alm_satellite_slot_number - 1].i_satellite_slot_number = gnav_almanac[i_alm_satellite_slot_number - 1].d_n_A;
|
2021-02-20 23:01:56 +00:00
|
|
|
gnav_almanac[i_alm_satellite_slot_number - 1].PRN = gnav_almanac[i_alm_satellite_slot_number - 1].d_n_A;
|
2018-03-03 01:03:39 +00:00
|
|
|
|
|
|
|
if (i_alm_satellite_slot_number == gnav_ephemeris.i_satellite_slot_number)
|
|
|
|
{
|
|
|
|
gnav_ephemeris.i_satellite_freq_channel = gnav_almanac[i_alm_satellite_slot_number - 1].i_satellite_freq_channel;
|
|
|
|
}
|
|
|
|
flag_almanac_str_7 = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 8:
|
|
|
|
// --- It is string 8 ----------------------------------------------
|
2019-02-22 09:47:24 +00:00
|
|
|
i_alm_satellite_slot_number = static_cast<uint32_t>(read_navigation_unsigned(string_bits, N_A));
|
2018-03-03 01:03:39 +00:00
|
|
|
d_frame_ID = get_frame_number(i_alm_satellite_slot_number);
|
|
|
|
// Make sure a valid frame_ID or satellite slot number is returned
|
|
|
|
if (d_frame_ID == 0)
|
2019-02-11 20:13:02 +00:00
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
2018-03-03 01:03:39 +00:00
|
|
|
|
2023-11-14 12:42:44 +00:00
|
|
|
gnav_almanac[i_alm_satellite_slot_number - 1].d_C_n = read_navigation_bool(string_bits, C_N);
|
2018-03-03 01:03:39 +00:00
|
|
|
gnav_almanac[i_alm_satellite_slot_number - 1].d_M_n_A = static_cast<double>(read_navigation_unsigned(string_bits, M_N_A));
|
2019-02-22 09:47:24 +00:00
|
|
|
gnav_almanac[i_alm_satellite_slot_number - 1].d_n_A = static_cast<double>(read_navigation_unsigned(string_bits, N_A));
|
2018-03-03 01:03:39 +00:00
|
|
|
gnav_almanac[i_alm_satellite_slot_number - 1].d_tau_n_A = static_cast<double>(read_navigation_unsigned(string_bits, TAU_N_A)) * TWO_N18;
|
2020-07-05 18:20:02 +00:00
|
|
|
gnav_almanac[i_alm_satellite_slot_number - 1].d_lambda_n_A = static_cast<double>(read_navigation_signed(string_bits, LAMBDA_N_A)) * TWO_N20 * GNSS_PI;
|
|
|
|
gnav_almanac[i_alm_satellite_slot_number - 1].d_Delta_i_n_A = static_cast<double>(read_navigation_signed(string_bits, DELTA_I_N_A)) * TWO_N20 * GNSS_PI;
|
2018-03-03 01:03:39 +00:00
|
|
|
gnav_almanac[i_alm_satellite_slot_number - 1].d_epsilon_n_A = static_cast<double>(read_navigation_unsigned(string_bits, EPSILON_N_A)) * TWO_N20;
|
|
|
|
|
|
|
|
flag_almanac_str_8 = true;
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 9:
|
|
|
|
// --- It is string 9 ----------------------------------------------
|
|
|
|
if (flag_almanac_str_8 == true)
|
|
|
|
{
|
2020-07-05 18:20:02 +00:00
|
|
|
gnav_almanac[i_alm_satellite_slot_number - 1].d_omega_n_A = static_cast<double>(read_navigation_signed(string_bits, OMEGA_N_A)) * TWO_N15 * GNSS_PI;
|
2018-03-03 01:03:39 +00:00
|
|
|
gnav_almanac[i_alm_satellite_slot_number - 1].d_t_lambda_n_A = static_cast<double>(read_navigation_unsigned(string_bits, T_LAMBDA_N_A)) * TWO_N5;
|
|
|
|
gnav_almanac[i_alm_satellite_slot_number - 1].d_Delta_T_n_A = static_cast<double>(read_navigation_signed(string_bits, DELTA_T_N_A)) * TWO_N9;
|
|
|
|
gnav_almanac[i_alm_satellite_slot_number - 1].d_Delta_T_n_A_dot = static_cast<double>(read_navigation_signed(string_bits, DELTA_T_DOT_N_A)) * TWO_N14;
|
|
|
|
gnav_almanac[i_alm_satellite_slot_number - 1].d_H_n_A = static_cast<double>(read_navigation_unsigned(string_bits, H_N_A));
|
2023-11-14 12:42:44 +00:00
|
|
|
gnav_almanac[i_alm_satellite_slot_number - 1].d_l_n = read_navigation_bool(string_bits, ALM_L_N);
|
2018-03-03 01:03:39 +00:00
|
|
|
|
|
|
|
// Set satellite information for redundancy purposes
|
|
|
|
if (gnav_almanac[i_alm_satellite_slot_number - 1].d_H_n_A > 24)
|
|
|
|
{
|
|
|
|
gnav_almanac[i_alm_satellite_slot_number - 1].i_satellite_freq_channel = gnav_almanac[i_alm_satellite_slot_number - 1].d_H_n_A - 32.0;
|
|
|
|
}
|
|
|
|
gnav_almanac[i_alm_satellite_slot_number - 1].i_satellite_slot_number = gnav_almanac[i_alm_satellite_slot_number - 1].d_n_A;
|
2021-02-20 23:01:56 +00:00
|
|
|
gnav_almanac[i_alm_satellite_slot_number - 1].PRN = gnav_almanac[i_alm_satellite_slot_number - 1].d_n_A;
|
2018-03-03 01:03:39 +00:00
|
|
|
|
|
|
|
flag_almanac_str_9 = true;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 10:
|
|
|
|
// --- It is string 10 ---------------------------------------------
|
2019-02-22 09:47:24 +00:00
|
|
|
i_alm_satellite_slot_number = static_cast<uint32_t>(read_navigation_unsigned(string_bits, N_A));
|
2018-03-03 01:03:39 +00:00
|
|
|
d_frame_ID = get_frame_number(i_alm_satellite_slot_number);
|
|
|
|
// Make sure a valid frame_ID or satellite slot number is returned
|
|
|
|
if (d_frame_ID == 0)
|
2019-02-11 20:13:02 +00:00
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
2018-03-03 01:03:39 +00:00
|
|
|
|
2023-11-14 12:42:44 +00:00
|
|
|
gnav_almanac[i_alm_satellite_slot_number - 1].d_C_n = read_navigation_bool(string_bits, C_N);
|
2018-03-03 01:03:39 +00:00
|
|
|
gnav_almanac[i_alm_satellite_slot_number - 1].d_M_n_A = static_cast<double>(read_navigation_unsigned(string_bits, M_N_A));
|
2019-02-22 09:47:24 +00:00
|
|
|
gnav_almanac[i_alm_satellite_slot_number - 1].d_n_A = static_cast<double>(read_navigation_unsigned(string_bits, N_A));
|
2018-03-03 01:03:39 +00:00
|
|
|
gnav_almanac[i_alm_satellite_slot_number - 1].d_tau_n_A = static_cast<double>(read_navigation_unsigned(string_bits, TAU_N_A)) * TWO_N18;
|
2020-07-05 18:20:02 +00:00
|
|
|
gnav_almanac[i_alm_satellite_slot_number - 1].d_lambda_n_A = static_cast<double>(read_navigation_signed(string_bits, LAMBDA_N_A)) * TWO_N20 * GNSS_PI;
|
|
|
|
gnav_almanac[i_alm_satellite_slot_number - 1].d_Delta_i_n_A = static_cast<double>(read_navigation_signed(string_bits, DELTA_I_N_A)) * TWO_N20 * GNSS_PI;
|
2018-03-03 01:03:39 +00:00
|
|
|
gnav_almanac[i_alm_satellite_slot_number - 1].d_epsilon_n_A = static_cast<double>(read_navigation_unsigned(string_bits, EPSILON_N_A)) * TWO_N20;
|
|
|
|
|
|
|
|
flag_almanac_str_10 = true;
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 11:
|
|
|
|
// --- It is string 11 ---------------------------------------------
|
|
|
|
if (flag_almanac_str_10 == true)
|
|
|
|
{
|
2020-07-05 18:20:02 +00:00
|
|
|
gnav_almanac[i_alm_satellite_slot_number - 1].d_omega_n_A = static_cast<double>(read_navigation_signed(string_bits, OMEGA_N_A)) * TWO_N15 * GNSS_PI;
|
2018-03-03 01:03:39 +00:00
|
|
|
gnav_almanac[i_alm_satellite_slot_number - 1].d_t_lambda_n_A = static_cast<double>(read_navigation_unsigned(string_bits, T_LAMBDA_N_A)) * TWO_N5;
|
|
|
|
gnav_almanac[i_alm_satellite_slot_number - 1].d_Delta_T_n_A = static_cast<double>(read_navigation_signed(string_bits, DELTA_T_N_A)) * TWO_N9;
|
|
|
|
gnav_almanac[i_alm_satellite_slot_number - 1].d_Delta_T_n_A_dot = static_cast<double>(read_navigation_signed(string_bits, DELTA_T_DOT_N_A)) * TWO_N14;
|
|
|
|
gnav_almanac[i_alm_satellite_slot_number - 1].d_H_n_A = static_cast<double>(read_navigation_unsigned(string_bits, H_N_A));
|
2023-11-14 12:42:44 +00:00
|
|
|
gnav_almanac[i_alm_satellite_slot_number - 1].d_l_n = read_navigation_bool(string_bits, ALM_L_N);
|
2018-03-03 01:03:39 +00:00
|
|
|
|
|
|
|
// Set satellite information for redundancy purposes
|
|
|
|
if (gnav_almanac[i_alm_satellite_slot_number - 1].d_H_n_A > 24)
|
|
|
|
{
|
|
|
|
gnav_almanac[i_alm_satellite_slot_number - 1].i_satellite_freq_channel = gnav_almanac[i_alm_satellite_slot_number - 1].d_H_n_A - 32.0;
|
|
|
|
}
|
|
|
|
gnav_almanac[i_alm_satellite_slot_number - 1].i_satellite_slot_number = gnav_almanac[i_alm_satellite_slot_number - 1].d_n_A;
|
2021-02-20 23:01:56 +00:00
|
|
|
gnav_almanac[i_alm_satellite_slot_number - 1].PRN = gnav_almanac[i_alm_satellite_slot_number - 1].d_n_A;
|
2018-03-03 01:03:39 +00:00
|
|
|
|
|
|
|
flag_almanac_str_11 = true;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 12:
|
|
|
|
// --- It is string 12 ---------------------------------------------
|
2019-02-22 09:47:24 +00:00
|
|
|
i_alm_satellite_slot_number = static_cast<uint32_t>(read_navigation_unsigned(string_bits, N_A));
|
2018-03-03 01:03:39 +00:00
|
|
|
d_frame_ID = get_frame_number(i_alm_satellite_slot_number);
|
|
|
|
// Make sure a valid frame_ID or satellite slot number is returned
|
|
|
|
if (d_frame_ID == 0)
|
2019-02-11 20:13:02 +00:00
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
2023-11-14 12:42:44 +00:00
|
|
|
gnav_almanac[i_alm_satellite_slot_number - 1].d_C_n = read_navigation_bool(string_bits, C_N);
|
2018-03-03 01:03:39 +00:00
|
|
|
gnav_almanac[i_alm_satellite_slot_number - 1].d_M_n_A = static_cast<double>(read_navigation_unsigned(string_bits, M_N_A));
|
2019-02-22 09:47:24 +00:00
|
|
|
gnav_almanac[i_alm_satellite_slot_number - 1].d_n_A = static_cast<double>(read_navigation_unsigned(string_bits, N_A));
|
2018-03-03 01:03:39 +00:00
|
|
|
gnav_almanac[i_alm_satellite_slot_number - 1].d_tau_n_A = static_cast<double>(read_navigation_unsigned(string_bits, TAU_N_A)) * TWO_N18;
|
2020-07-05 18:20:02 +00:00
|
|
|
gnav_almanac[i_alm_satellite_slot_number - 1].d_lambda_n_A = static_cast<double>(read_navigation_signed(string_bits, LAMBDA_N_A)) * TWO_N20 * GNSS_PI;
|
|
|
|
gnav_almanac[i_alm_satellite_slot_number - 1].d_Delta_i_n_A = static_cast<double>(read_navigation_signed(string_bits, DELTA_I_N_A)) * TWO_N20 * GNSS_PI;
|
2018-03-03 01:03:39 +00:00
|
|
|
gnav_almanac[i_alm_satellite_slot_number - 1].d_epsilon_n_A = static_cast<double>(read_navigation_unsigned(string_bits, EPSILON_N_A)) * TWO_N20;
|
|
|
|
|
|
|
|
flag_almanac_str_12 = true;
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 13:
|
|
|
|
// --- It is string 13 ---------------------------------------------
|
|
|
|
if (flag_almanac_str_12 == true)
|
|
|
|
{
|
2020-07-05 18:20:02 +00:00
|
|
|
gnav_almanac[i_alm_satellite_slot_number - 1].d_omega_n_A = static_cast<double>(read_navigation_signed(string_bits, OMEGA_N_A)) * TWO_N15 * GNSS_PI;
|
2018-03-03 01:03:39 +00:00
|
|
|
gnav_almanac[i_alm_satellite_slot_number - 1].d_t_lambda_n_A = static_cast<double>(read_navigation_unsigned(string_bits, T_LAMBDA_N_A)) * TWO_N5;
|
|
|
|
gnav_almanac[i_alm_satellite_slot_number - 1].d_Delta_T_n_A = static_cast<double>(read_navigation_signed(string_bits, DELTA_T_N_A)) * TWO_N9;
|
|
|
|
gnav_almanac[i_alm_satellite_slot_number - 1].d_Delta_T_n_A_dot = static_cast<double>(read_navigation_signed(string_bits, DELTA_T_DOT_N_A)) * TWO_N14;
|
|
|
|
gnav_almanac[i_alm_satellite_slot_number - 1].d_H_n_A = static_cast<double>(read_navigation_unsigned(string_bits, H_N_A));
|
2023-11-14 12:42:44 +00:00
|
|
|
gnav_almanac[i_alm_satellite_slot_number - 1].d_l_n = read_navigation_bool(string_bits, ALM_L_N);
|
2018-03-03 01:03:39 +00:00
|
|
|
|
|
|
|
// Set satellite information for redundancy purposes
|
|
|
|
if (gnav_almanac[i_alm_satellite_slot_number - 1].d_H_n_A > 24)
|
|
|
|
{
|
|
|
|
gnav_almanac[i_alm_satellite_slot_number - 1].i_satellite_freq_channel = gnav_almanac[i_alm_satellite_slot_number - 1].d_H_n_A - 32.0;
|
|
|
|
}
|
|
|
|
gnav_almanac[i_alm_satellite_slot_number - 1].i_satellite_slot_number = gnav_almanac[i_alm_satellite_slot_number - 1].d_n_A;
|
2021-02-20 23:01:56 +00:00
|
|
|
gnav_almanac[i_alm_satellite_slot_number - 1].PRN = gnav_almanac[i_alm_satellite_slot_number - 1].d_n_A;
|
2018-03-03 01:03:39 +00:00
|
|
|
|
|
|
|
flag_almanac_str_13 = true;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 14:
|
|
|
|
// --- It is string 14 ---------------------------------------------
|
|
|
|
if (d_frame_ID == 5)
|
|
|
|
{
|
|
|
|
gnav_utc_model.d_B1 = static_cast<double>(read_navigation_unsigned(string_bits, B1));
|
|
|
|
gnav_utc_model.d_B2 = static_cast<double>(read_navigation_unsigned(string_bits, B2));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2019-02-22 09:47:24 +00:00
|
|
|
i_alm_satellite_slot_number = static_cast<uint32_t>(read_navigation_unsigned(string_bits, N_A));
|
2018-03-03 01:03:39 +00:00
|
|
|
d_frame_ID = get_frame_number(i_alm_satellite_slot_number);
|
|
|
|
// Make sure a valid frame_ID or satellite slot number is returned
|
|
|
|
if (d_frame_ID == 0)
|
2019-02-11 20:13:02 +00:00
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
2023-11-14 12:42:44 +00:00
|
|
|
gnav_almanac[i_alm_satellite_slot_number - 1].d_C_n = read_navigation_bool(string_bits, C_N);
|
2018-03-03 01:03:39 +00:00
|
|
|
gnav_almanac[i_alm_satellite_slot_number - 1].d_M_n_A = static_cast<double>(read_navigation_unsigned(string_bits, M_N_A));
|
2019-02-22 09:47:24 +00:00
|
|
|
gnav_almanac[i_alm_satellite_slot_number - 1].d_n_A = static_cast<double>(read_navigation_unsigned(string_bits, N_A));
|
2018-03-03 01:03:39 +00:00
|
|
|
gnav_almanac[i_alm_satellite_slot_number - 1].d_tau_n_A = static_cast<double>(read_navigation_unsigned(string_bits, TAU_N_A)) * TWO_N18;
|
2020-07-05 18:20:02 +00:00
|
|
|
gnav_almanac[i_alm_satellite_slot_number - 1].d_lambda_n_A = static_cast<double>(read_navigation_signed(string_bits, LAMBDA_N_A)) * TWO_N20 * GNSS_PI;
|
|
|
|
gnav_almanac[i_alm_satellite_slot_number - 1].d_Delta_i_n_A = static_cast<double>(read_navigation_signed(string_bits, DELTA_I_N_A)) * TWO_N20 * GNSS_PI;
|
2018-03-03 01:03:39 +00:00
|
|
|
gnav_almanac[i_alm_satellite_slot_number - 1].d_epsilon_n_A = static_cast<double>(read_navigation_unsigned(string_bits, EPSILON_N_A)) * TWO_N20;
|
|
|
|
|
|
|
|
flag_almanac_str_14 = true;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 15:
|
|
|
|
// --- It is string 15 ----------------------------------------------
|
|
|
|
if (d_frame_ID != 5 and flag_almanac_str_14 == true)
|
|
|
|
{
|
2020-07-05 18:20:02 +00:00
|
|
|
gnav_almanac[i_alm_satellite_slot_number - 1].d_omega_n_A = static_cast<double>(read_navigation_signed(string_bits, OMEGA_N_A)) * TWO_N15 * GNSS_PI;
|
2018-03-03 01:03:39 +00:00
|
|
|
gnav_almanac[i_alm_satellite_slot_number - 1].d_t_lambda_n_A = static_cast<double>(read_navigation_unsigned(string_bits, T_LAMBDA_N_A)) * TWO_N5;
|
|
|
|
gnav_almanac[i_alm_satellite_slot_number - 1].d_Delta_T_n_A = static_cast<double>(read_navigation_signed(string_bits, DELTA_T_N_A)) * TWO_N9;
|
|
|
|
gnav_almanac[i_alm_satellite_slot_number - 1].d_Delta_T_n_A_dot = static_cast<double>(read_navigation_signed(string_bits, DELTA_T_DOT_N_A)) * TWO_N14;
|
|
|
|
gnav_almanac[i_alm_satellite_slot_number - 1].d_H_n_A = static_cast<double>(read_navigation_unsigned(string_bits, H_N_A));
|
2023-11-14 12:42:44 +00:00
|
|
|
gnav_almanac[i_alm_satellite_slot_number - 1].d_l_n = read_navigation_bool(string_bits, ALM_L_N);
|
2018-03-03 01:03:39 +00:00
|
|
|
|
|
|
|
// Set satellite information for redundancy purposes
|
|
|
|
if (gnav_almanac[i_alm_satellite_slot_number - 1].d_H_n_A > 24)
|
|
|
|
{
|
|
|
|
gnav_almanac[i_alm_satellite_slot_number - 1].i_satellite_freq_channel = gnav_almanac[i_alm_satellite_slot_number - 1].d_H_n_A - 32.0;
|
|
|
|
}
|
|
|
|
gnav_almanac[i_alm_satellite_slot_number - 1].i_satellite_slot_number = gnav_almanac[i_alm_satellite_slot_number - 1].d_n_A;
|
2021-02-20 23:01:56 +00:00
|
|
|
gnav_almanac[i_alm_satellite_slot_number - 1].PRN = gnav_almanac[i_alm_satellite_slot_number - 1].d_n_A;
|
2018-03-03 01:03:39 +00:00
|
|
|
|
|
|
|
flag_almanac_str_15 = true;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
LOG(INFO) << "GLONASS GNAV: Invalid String ID of received. Received " << d_string_ID
|
|
|
|
<< ", but acceptable range is from 1-15";
|
|
|
|
|
|
|
|
break;
|
|
|
|
} // switch string ID
|
2017-09-16 04:25:37 +00:00
|
|
|
|
2017-08-31 22:51:50 +00:00
|
|
|
return d_string_ID;
|
2017-06-21 04:44:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2020-06-23 07:47:58 +00:00
|
|
|
Glonass_Gnav_Almanac Glonass_Gnav_Navigation_Message::get_almanac(uint32_t satellite_slot_number) const
|
2017-07-10 06:00:49 +00:00
|
|
|
{
|
2017-07-12 20:11:53 +00:00
|
|
|
return gnav_almanac[satellite_slot_number - 1];
|
2017-06-21 04:44:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-08-18 20:16:13 +00:00
|
|
|
bool Glonass_Gnav_Navigation_Message::have_new_ephemeris() // Check if we have a new ephemeris stored in the galileo navigation class
|
2017-06-21 04:44:44 +00:00
|
|
|
{
|
2017-09-22 18:16:26 +00:00
|
|
|
bool new_eph = false;
|
2017-09-20 14:42:01 +00:00
|
|
|
// We need to make sure we have received the ephemeris info plus the time info
|
|
|
|
if ((flag_ephemeris_str_1 == true) and (flag_ephemeris_str_2 == true) and
|
2018-03-03 01:03:39 +00:00
|
|
|
(flag_ephemeris_str_3 == true) and (flag_ephemeris_str_4 == true) and
|
|
|
|
(flag_utc_model_str_5 == true))
|
2017-07-10 06:00:49 +00:00
|
|
|
{
|
2018-03-03 01:03:39 +00:00
|
|
|
if (d_previous_tb != gnav_ephemeris.d_t_b)
|
2017-09-22 18:16:26 +00:00
|
|
|
{
|
2018-03-03 01:03:39 +00:00
|
|
|
flag_ephemeris_str_1 = false; // clear the flag
|
|
|
|
flag_ephemeris_str_2 = false; // clear the flag
|
|
|
|
flag_ephemeris_str_3 = false; // clear the flag
|
|
|
|
flag_ephemeris_str_4 = false; // clear the flag
|
2017-09-22 18:16:26 +00:00
|
|
|
flag_all_ephemeris = true;
|
|
|
|
// Update the time of ephemeris information
|
|
|
|
d_previous_tb = gnav_ephemeris.d_t_b;
|
2020-07-07 16:53:50 +00:00
|
|
|
DLOG(INFO) << "GLONASS GNAV Ephemeris (1, 2, 3, 4) have been received and belong to the same batch";
|
2017-09-22 18:16:26 +00:00
|
|
|
new_eph = true;
|
|
|
|
}
|
2017-07-10 06:00:49 +00:00
|
|
|
}
|
2017-09-22 18:16:26 +00:00
|
|
|
|
|
|
|
return new_eph;
|
2017-07-10 06:00:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-03-03 01:03:39 +00:00
|
|
|
bool Glonass_Gnav_Navigation_Message::have_new_utc_model() // Check if we have a new utc data set stored in the galileo navigation class
|
2017-07-10 06:00:49 +00:00
|
|
|
{
|
2017-11-02 03:05:40 +00:00
|
|
|
if (flag_utc_model_str_5 == true)
|
2017-07-10 06:00:49 +00:00
|
|
|
{
|
2018-03-03 01:03:39 +00:00
|
|
|
flag_utc_model_str_5 = false; // clear the flag
|
2017-07-10 06:00:49 +00:00
|
|
|
return true;
|
|
|
|
}
|
2018-12-03 21:08:19 +00:00
|
|
|
|
|
|
|
return false;
|
2017-07-10 06:00:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-08-13 23:13:07 +00:00
|
|
|
bool Glonass_Gnav_Navigation_Message::have_new_almanac() // Check if we have a new almanac data set stored in the galileo navigation class
|
2017-07-10 06:00:49 +00:00
|
|
|
{
|
2017-09-16 19:07:34 +00:00
|
|
|
bool new_alm = false;
|
|
|
|
if ((flag_almanac_str_6 == true) and (flag_almanac_str_7 == true))
|
2017-07-10 06:00:49 +00:00
|
|
|
{
|
2017-09-22 18:16:26 +00:00
|
|
|
if (d_previous_Na[i_alm_satellite_slot_number] != gnav_utc_model.d_N_A)
|
|
|
|
{
|
2020-07-28 08:51:45 +00:00
|
|
|
// All Almanac data have been received for this satellite
|
2017-09-22 18:16:26 +00:00
|
|
|
flag_almanac_str_6 = false;
|
|
|
|
flag_almanac_str_7 = false;
|
|
|
|
new_alm = true;
|
|
|
|
}
|
2017-09-16 19:07:34 +00:00
|
|
|
}
|
|
|
|
if ((flag_almanac_str_8 == true) and (flag_almanac_str_9 == true))
|
|
|
|
{
|
2017-09-22 18:16:26 +00:00
|
|
|
if (d_previous_Na[i_alm_satellite_slot_number] != gnav_utc_model.d_N_A)
|
|
|
|
{
|
|
|
|
flag_almanac_str_8 = false;
|
|
|
|
flag_almanac_str_9 = false;
|
|
|
|
new_alm = true;
|
|
|
|
}
|
2017-09-16 19:07:34 +00:00
|
|
|
}
|
2018-03-03 01:03:39 +00:00
|
|
|
if ((flag_almanac_str_10 == true) and (flag_almanac_str_11 == true))
|
2017-09-16 19:07:34 +00:00
|
|
|
{
|
2017-09-22 18:16:26 +00:00
|
|
|
if (d_previous_Na[i_alm_satellite_slot_number] != gnav_utc_model.d_N_A)
|
|
|
|
{
|
|
|
|
flag_almanac_str_10 = false;
|
|
|
|
flag_almanac_str_11 = false;
|
|
|
|
new_alm = true;
|
|
|
|
}
|
2017-09-16 19:07:34 +00:00
|
|
|
}
|
2018-03-03 01:03:39 +00:00
|
|
|
if ((flag_almanac_str_12 == true) and (flag_almanac_str_13 == true))
|
2017-09-16 19:07:34 +00:00
|
|
|
{
|
2017-09-22 18:16:26 +00:00
|
|
|
if (d_previous_Na[i_alm_satellite_slot_number] != gnav_utc_model.d_N_A)
|
|
|
|
{
|
|
|
|
flag_almanac_str_12 = false;
|
|
|
|
flag_almanac_str_13 = false;
|
|
|
|
new_alm = true;
|
|
|
|
}
|
2017-09-16 19:07:34 +00:00
|
|
|
}
|
2018-03-03 01:03:39 +00:00
|
|
|
if ((flag_almanac_str_14 == true) and (flag_almanac_str_15 == true))
|
2017-09-16 19:07:34 +00:00
|
|
|
{
|
2017-09-22 18:16:26 +00:00
|
|
|
if (d_previous_Na[i_alm_satellite_slot_number] != gnav_utc_model.d_N_A)
|
|
|
|
{
|
|
|
|
flag_almanac_str_14 = false;
|
|
|
|
flag_almanac_str_15 = false;
|
|
|
|
new_alm = true;
|
|
|
|
}
|
2017-07-10 06:00:49 +00:00
|
|
|
}
|
2017-09-16 19:07:34 +00:00
|
|
|
|
|
|
|
return new_alm;
|
2017-06-21 04:44:44 +00:00
|
|
|
}
|