1
0
mirror of https://github.com/gnss-sdr/gnss-sdr synced 2025-07-03 10:32:55 +00:00

[TAS-206] [Feature] NavData for ADKD=4 for osnma_test_vector.

This commit is contained in:
cesaaargm 2024-06-04 17:35:00 +02:00
parent 434fff9cbf
commit 6508e985a1
5 changed files with 70 additions and 35 deletions

View File

@ -1082,12 +1082,24 @@ std::vector<uint8_t> osnma_msg_receiver::build_message(const Tag& tag)
two_bits_nmas = two_bits_nmas << 6; two_bits_nmas = two_bits_nmas << 6;
m.push_back(two_bits_nmas); m.push_back(two_bits_nmas);
// Add applicable NavData bits to message
std::string applicable_nav_data;
std::vector<uint8_t> applicable_nav_data_bytes;
if (tag.ADKD == 0 || tag.ADKD == 12)
{
applicable_nav_data = d_satellite_nav_data[tag.PRN_d][tag.TOW - 30].ephemeris_iono_vector_2;
}
else if (tag.ADKD == 4)
{
applicable_nav_data = d_satellite_nav_data[tag.PRN_d][tag.TOW - 30].utc_vector_2;
}
else
std::cerr<<"Galileo OSNMA :: Tag verification :: unknown ADKD" <<"\n";
// convert std::string to vector<uint8_t> // convert std::string to vector<uint8_t>
std::string ephemeris_iono_vector_2 = d_satellite_nav_data[tag.PRN_d][tag.TOW - 30].ephemeris_iono_vector_2; applicable_nav_data_bytes = d_helper->bytes(applicable_nav_data);
std::vector<uint8_t> ephemeris_iono_vector_2_bytes = d_helper->bytes(ephemeris_iono_vector_2);
// Convert and add ephemeris_iono_vector_2 into the vector // Convert and add NavData bytes into the message, taking care of that NMAS has only 2 bits
for (uint8_t byte : ephemeris_iono_vector_2_bytes) { for (uint8_t byte : applicable_nav_data_bytes) {
m.back() |= (byte >> 2); // First take the 6 MSB bits of byte and add to m m.back() |= (byte >> 2); // First take the 6 MSB bits of byte and add to m
m.push_back(byte << 6); // Then take the last 2 bits of byte, shift them to MSB position and insert the new element into m m.push_back(byte << 6); // Then take the last 2 bits of byte, shift them to MSB position and insert the new element into m
} }

View File

@ -54,6 +54,7 @@ public:
std::vector<uint8_t> EphemerisClockAndStatusData {}; // TODO _2 rename and substitute this std::vector<uint8_t> EphemerisClockAndStatusData {}; // TODO _2 rename and substitute this
std::string EphemerisClockAndStatusData_2{}; std::string EphemerisClockAndStatusData_2{};
std::vector<uint8_t> TimingData {}; std::vector<uint8_t> TimingData {};
std::string TimingData_2{};
Galileo_Ephemeris EphemerisData {}; Galileo_Ephemeris EphemerisData {};
Galileo_Iono IonoData {}; Galileo_Iono IonoData {};
Galileo_Utc_Model UtcModelData {}; Galileo_Utc_Model UtcModelData {};

View File

@ -38,6 +38,7 @@ void NavData::init(const std::shared_ptr<OSNMA_msg> &osnma_msg)
// new parsing, directly parsing bits // new parsing, directly parsing bits
ephemeris_iono_vector_2 = osnma_msg->EphemerisClockAndStatusData_2; ephemeris_iono_vector_2 = osnma_msg->EphemerisClockAndStatusData_2;
utc_vector_2 = osnma_msg->TimingData_2;
}; };
void NavData::generate_eph_iono_vector() void NavData::generate_eph_iono_vector()
{ {

View File

@ -134,6 +134,7 @@ public:
std::vector<uint8_t> ephemeris_iono_vector{}; std::vector<uint8_t> ephemeris_iono_vector{};
std::string ephemeris_iono_vector_2{}; std::string ephemeris_iono_vector_2{};
std::vector<uint8_t> utc_vector{}; std::vector<uint8_t> utc_vector{};
std::string utc_vector_2{};
uint32_t PRNa{}; uint32_t PRNa{};
uint32_t WN_sf0{}; uint32_t WN_sf0{};
uint32_t TOW_sf0{}; uint32_t TOW_sf0{};

View File

@ -90,6 +90,7 @@ TEST_F(OsnmaMsgReceiverTest, OsnmaTestVectorsSimulation)
{ {
initializeGoogleLog(); initializeGoogleLog();
// Arrange // Arrange
// ----------
std::vector<TestVector> testVectors = readTestVectorsFromFile("/home/cgm/CLionProjects/osnma/data/16_AUG_2023_GST_05_00_01.csv"); std::vector<TestVector> testVectors = readTestVectorsFromFile("/home/cgm/CLionProjects/osnma/data/16_AUG_2023_GST_05_00_01.csv");
if (testVectors.empty()){ if (testVectors.empty()){
ASSERT_TRUE(false); ASSERT_TRUE(false);
@ -98,10 +99,10 @@ TEST_F(OsnmaMsgReceiverTest, OsnmaTestVectorsSimulation)
bool end_of_hex_stream{false}; bool end_of_hex_stream{false};
int offset_byte{0}; int offset_byte{0};
int byte_index{0}; // index containing the last byte position of the hex stream that was retrieved. Takes advantage that all TVs have same size int byte_index{0}; // index containing the last byte position of the hex stream that was retrieved. Takes advantage that all TVs have same size
const int SIZE_PAGE_BYTES{240/8}; const int SIZE_PAGE_BYTES{240/8}; // total bytes of a page
const int SIZE_SUBFRAME_PAGES{15}; const int SIZE_SUBFRAME_PAGES{15}; // number of pages of a subframe
const int SIZE_SUBFRAME_BYTES{SIZE_PAGE_BYTES*SIZE_SUBFRAME_PAGES}; const int SIZE_SUBFRAME_BYTES{SIZE_PAGE_BYTES*SIZE_SUBFRAME_PAGES}; // total bytes of a subframe
const int DURATION_SUBFRAME{30}; const int DURATION_SUBFRAME{30}; // duration of a subframe, in seconds
const int DUMMY_PAGE{63}; const int DUMMY_PAGE{63};
bool flag_dummy_page{false}; bool flag_dummy_page{false};
@ -110,7 +111,11 @@ TEST_F(OsnmaMsgReceiverTest, OsnmaTestVectorsSimulation)
<< ", WN=" << WN << std::endl; << ", WN=" << WN << std::endl;
// Act // Act
// ----------
while (end_of_hex_stream == false){ // loop over all bytes of data. Note all TestVectors have same amount of data. while (end_of_hex_stream == false){ // loop over all bytes of data. Note all TestVectors have same amount of data.
for(const TestVector& tv : testVectors) { // loop over all SVs, extract a subframe for(const TestVector& tv : testVectors) { // loop over all SVs, extract a subframe
std::cout << "OsnmaTestVectorsSimulation: SVID (PRN_a) "<< tv.svId << std::endl; std::cout << "OsnmaTestVectorsSimulation: SVID (PRN_a) "<< tv.svId << std::endl;
@ -118,7 +123,7 @@ TEST_F(OsnmaMsgReceiverTest, OsnmaTestVectorsSimulation)
std::array<uint8_t, 15> hkroot{}; std::array<uint8_t, 15> hkroot{};
std::array<uint32_t, 15> mack{}; std::array<uint32_t, 15> mack{};
byte_index = offset_byte; // reset byte_index to the offset position for the next test vector. Offset is updated at the end of each Subframe (every 30 s or 450 Bytes) byte_index = offset_byte; // reset byte_index to the offset position for the next test vector. Offset is updated at the end of each Subframe (every 30 s or 450 Bytes)
std::map<uint8_t, std::bitset<128>> words; std::map<uint8_t, std::bitset<128>> words; // structure containing <WORD_NUMBER> and <EXTRACTED_BITS>
for (int idx = 0; idx < SIZE_SUBFRAME_PAGES; ++idx) // extract all pages of a subframe for (int idx = 0; idx < SIZE_SUBFRAME_PAGES; ++idx) // extract all pages of a subframe
{ {
@ -179,6 +184,7 @@ TEST_F(OsnmaMsgReceiverTest, OsnmaTestVectorsSimulation)
byte_index += SIZE_PAGE_BYTES; byte_index += SIZE_PAGE_BYTES;
} }
std::cout<< "----------" << std::endl; std::cout<< "----------" << std::endl;
if(end_of_hex_stream) if(end_of_hex_stream)
break; break;
@ -193,17 +199,21 @@ TEST_F(OsnmaMsgReceiverTest, OsnmaTestVectorsSimulation)
osnmaMsg_sptr->WN_sf0 = (d_GST_SIS & 0xFFF00000) >> 20 ; osnmaMsg_sptr->WN_sf0 = (d_GST_SIS & 0xFFF00000) >> 20 ;
osnmaMsg_sptr->PRN = tv.svId; // PRNa osnmaMsg_sptr->PRN = tv.svId; // PRNa
bool allWordsReceived = true; // TODO - refactor this logic, currently it is split
// check if words 1--> 5 words are received
bool ephClockStatusWordsReceived = true;
for (int i = 1; i <= 5; ++i) for (int i = 1; i <= 5; ++i)
{ {
if (words.find(i) == words.end() && flag_dummy_page == false) if (words.find(i) == words.end())
{ {
allWordsReceived = false; ephClockStatusWordsReceived = false;
std::cerr<< "OsnmaTestVectorsSimulation: error parsing words 1->5. " std::cerr<< "OsnmaTestVectorsSimulation: error parsing words 1->5. "
"Word "<< i << " should be received for each subframe but was not." << std::endl; "Word "<< i << " should be received for each subframe but was not." << std::endl;
} }
} }
if(allWordsReceived) // extract bits as needed by osnma block
if(ephClockStatusWordsReceived)
{ {
// Define the starting position and length of bits to extract for each word // Define the starting position and length of bits to extract for each word
@ -222,32 +232,38 @@ TEST_F(OsnmaMsgReceiverTest, OsnmaTestVectorsSimulation)
uint8_t start = param.second.first; uint8_t start = param.second.first;
uint8_t length = param.second.second; uint8_t length = param.second.second;
// Extract the required bits // Extract the required bits and fill osnma block
osnmaMsg_sptr->EphemerisClockAndStatusData_2 += words[wordKey]. osnmaMsg_sptr->EphemerisClockAndStatusData_2 += words[wordKey].
to_string().substr( to_string().substr(
start, length); start, length);
// std::bitset<8> byte;
// int byteIndex = 0;
// for (uint8_t i = start; i < start + length; ++i) {
// byte[byteIndex] = word[i];
// byteIndex++;
//
// // Once we have collected 8 bits, we can add them as an uint8_t to the vector
// if (byteIndex == 8) {
// osnmaMsg_sptr->EphemerisClockAndStatusData.push_back(static_cast<uint8_t>(byte.to_ulong()));
// byte.reset();
// byteIndex = 0;
// }
// }
//
// // Push remaining bits if it didn't reach 8 bits
// if (byteIndex > 0) {
// osnmaMsg_sptr->EphemerisClockAndStatusData.push_back(static_cast<uint8_t>(byte.to_ulong()));
// }
} }
} }
// check w6 && w10 is received
bool timingWordsReceived = words.find(6) != words.end() &&
words.find(10) != words.end();
// extract bits as needed by osnma block
if(timingWordsReceived){
// Define the starting position and length of bits to extract for each word
std::map<uint8_t, std::pair<uint8_t, uint8_t>> extractionParams = {
{6, {6, 99}},
{10, {86, 42}}
};
// Fill NavData bits -- Iterate over the extraction parameters
for (const auto& param : extractionParams)
{
uint8_t wordKey = param.first;
uint8_t start = param.second.first;
uint8_t length = param.second.second;
// Extract the required bits and fill osnma block
osnmaMsg_sptr->TimingData_2 += words[wordKey].to_string().substr(
start, length);
}
}
auto temp_obj = pmt::make_any(osnmaMsg_sptr); auto temp_obj = pmt::make_any(osnmaMsg_sptr);
osnma->msg_handler_osnma(temp_obj); // osnma entry point osnma->msg_handler_osnma(temp_obj); // osnma entry point
@ -266,8 +282,12 @@ TEST_F(OsnmaMsgReceiverTest, OsnmaTestVectorsSimulation)
} }
// Assert // Assert
// TODO // ----------
// TODO - create global vars with failed tags and compare to total tags (Tag Id for example)
} }
std::vector<TestVector> OsnmaMsgReceiverTest::readTestVectorsFromFile(const std::string& filename) std::vector<TestVector> OsnmaMsgReceiverTest::readTestVectorsFromFile(const std::string& filename)
@ -527,7 +547,7 @@ TEST_F(OsnmaMsgReceiverTest, TagVerification) {
osnma->d_osnma_data.d_dsm_kroot_message.ts = 9; // 40 bit osnma->d_osnma_data.d_dsm_kroot_message.ts = 9; // 40 bit
osnma->d_tesla_keys[TOW_Key_Tag3] = {0x69, 0xC0, 0x0A, 0xA7, 0x36, 0x42, 0x37, 0xA6, 0x5E, 0xBF, 0x00, 0x6A, 0xD8, 0xDD, 0xBC, 0x73}; // K4 osnma->d_tesla_keys[TOW_Key_Tag3] = {0x69, 0xC0, 0x0A, 0xA7, 0x36, 0x42, 0x37, 0xA6, 0x5E, 0xBF, 0x00, 0x6A, 0xD8, 0xDD, 0xBC, 0x73}; // K4
osnma->d_osnma_data.d_dsm_kroot_message.mf = 0; osnma->d_osnma_data.d_dsm_kroot_message.mf = 0;
osnma->d_satellite_nav_data[PRNa][TOW_NavData].ephemeris_iono_vector_2 = osnma->d_satellite_nav_data[PRNa][TOW_NavData].utc_vector_2 =
"111111111111111111111111111111110000000000000000000000010001001001001000" "111111111111111111111111111111110000000000000000000000010001001001001000"
"111000001000100111100010010111111111011110111111111001001100000100000000"; "111000001000100111100010010111111111011110111111111001001100000100000000";
osnma->d_osnma_data.d_nma_header.nmas = 0b10; osnma->d_osnma_data.d_nma_header.nmas = 0b10;