Program Listing for File space_comms.cc¶
↰ Return to documentation for file (devices/space_comms.cc)
#include "lupnt/devices/space_comms.h"
#include "lupnt/core/asset_factory.h"
#include "lupnt/core/error.h"
#include "lupnt/core/file.h"
#include "lupnt/core/string_utils.h"
namespace lupnt {
bool StringInCandidates(std::vector<std::string>& candidates, std::string str) {
for (size_t i = 0; i < candidates.size(); i++)
if (str.find(candidates[i]) != std::string::npos) return true;
return false;
}
const std::map<GnssFreq, Real> GNSS_FREQ_MAP
= {{GnssFreq::L1, 1575.42e6}, {GnssFreq::L2, 1227.60e6}, {GnssFreq::L5, 1176.45e6},
{GnssFreq::E1, 1575.42e6}, {GnssFreq::E6, 1278.75e6}, {GnssFreq::E5, 1191.795e6},
{GnssFreq::E5a, 1176.45e6}, {GnssFreq::E5b, 1207.14e6}};
const std::map<GnssFreq, Real> GNSS_RC_MAP
= {{GnssFreq::L1, 1.023e6}, {GnssFreq::L2, 0.5115e6}, {GnssFreq::L5, 10.23e6},
{GnssFreq::E1, 1.023e6}, {GnssFreq::E6, 0.5115e6}, {GnssFreq::E5, 10.23e6},
{GnssFreq::E5a, 10.23e6}, {GnssFreq::E5b, 10.23e6}};
namespace {
Real GpsBlockTransmitPowerDbw(const std::string& block_name, GnssFreq freq) {
Real freq_offset = 0.0;
if (freq == GnssFreq::L5) {
if (block_name == "IIF" || block_name == "III") {
freq_offset = 3.0;
} else if (block_name == "IIR" || block_name == "IIR_M") {
freq_offset = -100.0;
}
}
if (block_name == "IIR") return 17.3 + freq_offset;
if (block_name == "IIR_M") return 18.8 + freq_offset;
if (block_name == "IIF") return 16.2 + freq_offset;
if (block_name == "III") return 18.8 + freq_offset;
return 14.0 + freq_offset;
}
} // namespace
// GnssTransmitter **************************************************************
// Constructor
GnssTransmitter::GnssTransmitter(GnssConst gnss_const, int prn)
: Transmitter(), gnss_const_(gnss_const), prn_(prn) {
switch (gnss_const_) {
case GnssConst::GPS: InitGps(); break;
case GnssConst::GLONASS: InitGlonass(); break;
case GnssConst::GALILEO: InitGalileo(); break;
case GnssConst::BEIDOU: InitBeidou(); break;
case GnssConst::QZSS: InitQzss(); break;
default: LUPNT_CHECK(false, "Invalid GNSS type", "GnssTransmitter");
}
}
// Constructor from YAML
GnssTransmitter::GnssTransmitter(Config& config) : Transmitter(config) {
gnss_const_ = enum_cast<GnssConst>(config["gnss_const"].as<std::string>()).value();
prn_ = config["prn"].as<int>();
switch (gnss_const_) {
case GnssConst::GPS: InitGps(); break;
case GnssConst::GLONASS: InitGlonass(); break;
case GnssConst::GALILEO: InitGalileo(); break;
case GnssConst::BEIDOU: InitBeidou(); break;
case GnssConst::QZSS: InitQzss(); break;
default: LUPNT_CHECK(false, "Invalid GNSS type", "GnssTransmitter");
}
}
// GPS
void GnssTransmitter::InitGps() {
// Todo: Autonomously generate the prn to svn mapping
std::filesystem::path csvpath = GetFilePath("gps_table.csv");
std::vector<std::vector<std::string>> gps_table = ReadCsv(csvpath);
for (size_t i = 0; i < gps_table.size(); i++) {
if (std::stoi(gps_table[i][0]) != prn_) continue;
// set transmittion power and antenna pattern, depending on the gps type
auto gps_type = gps_table[i][2];
std::string ant_name;
if (gps_type == "IIA") {
ant_name = gps_table[i][4]; // ACE Pattern
freq_list_ = {GnssFreq::L1, GnssFreq::L2};
} else if (gps_type == "IIR" || gps_type == "IIR_M") {
ant_name = gps_table[i][3]; // LM Pattern
freq_list_ = {GnssFreq::L1, GnssFreq::L5};
} else if (gps_type == "IIF") {
ant_name = gps_table[i][4]; // ACE Pattern
freq_list_ = {GnssFreq::L1, GnssFreq::L5};
} else if (gps_type == "III") {
ant_name = gps_table[i][3]; // LM Pattern
freq_list_ = {GnssFreq::L1, GnssFreq::L5};
}
for (auto freq : freq_list_) P_tx_[freq] = GpsBlockTransmitPowerDbw(gps_type, freq);
if (gps_type == "III") {
// For Block III, the antenna pattern is different for each frequency
for (auto freq : freq_list_)
antennas_[freq] = Antenna(ant_name + "_" + std::string(enum_name(freq)) + ".txt");
} else {
// For other GPS types, we assume the antenna pattern is the same for all frequencies
for (auto freq : freq_list_) antennas_[freq] = Antenna(ant_name);
}
return;
}
LUPNT_CHECK(false, "PRN not found in GPS table", "GnssTransmitter");
}
// GLONASS
void GnssTransmitter::InitGlonass() {
LUPNT_CHECK(false, "GLONASS not implemented yet", "GnssTransmitter");
}
// Galileo
void GnssTransmitter::InitGalileo() {
freq_list_ = {GnssFreq::E1, GnssFreq::E5a, GnssFreq::E5b, GnssFreq::E6};
for (auto freq : freq_list_) {
antennas_[freq] = Antenna("Galileo_" + std::string(enum_name(freq)) + ".txt");
}
for (auto freq : freq_list_) {
P_tx_[freq] = 14.0; // [dB-W]
}
}
// Beidou
void GnssTransmitter::InitBeidou() {
LUPNT_CHECK(false, "BEIDOU not implemented yet", "GnssTransmitter");
}
// QZSS
void GnssTransmitter::InitQzss() {
std::vector<std::string> names = {"1R", "02", "03", "04", "05", "06", "07"};
if (prn_ <= 4) {
freq_list_ = {GnssFreq::L1, GnssFreq::L2, GnssFreq::L5};
} else {
freq_list_ = {GnssFreq::L1, GnssFreq::L5};
}
for (auto freq : freq_list_) {
antennas_[freq]
= Antenna("QZSS_" + names[prn_ - 1] + "_" + std::string(enum_name(freq)) + ".txt");
}
// Reference: Enhancing Navigation Accuracy in a Geostationary Orbit by Utilizing a Regional
// Navigation Satellite System
for (auto freq : freq_list_) {
P_tx_[freq] = 14.1; // [dB-W]
}
}
REGISTER_FACTORY_CLASS(Device, GnssTransmitter)
// GnssReceiver **************************************************************
// Constructor
GnssReceiver::GnssReceiver(Config& config) : Receiver(config) {}
REGISTER_FACTORY_CLASS(Device, GnssReceiver)
} // namespace lupnt