gnss-sdr/src/core/libs/gnss_sdr_supl_client.cc

381 lines
16 KiB
C++

/*!
* \file gnss_sdr_supl_client.c
* \brief class that implements a C++ interface to external Secure User Location Protocol (SUPL) client library.
* \author Javier Arribas, 2013. jarribas(at)cttc.es
*
* TODO: put here supl.c author info
* class that implements a C++ interface to external Secure User Location Protocol (SUPL) client library.
*
* -------------------------------------------------------------------------
*
* Copyright (C) 2010-2014 (see AUTHORS file for a list of contributors)
*
* GNSS-SDR is a software defined Global Navigation
* Satellite Systems receiver
*
* This file is part of GNSS-SDR.
*
* GNSS-SDR is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* at your option) any later version.
*
* GNSS-SDR is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNSS-SDR. If not, see <http://www.gnu.org/licenses/>.
*
* -------------------------------------------------------------------------
*/
#include "gnss_sdr_supl_client.h"
#include <utility>
gnss_sdr_supl_client::gnss_sdr_supl_client()
{}
gnss_sdr_supl_client::~gnss_sdr_supl_client()
{}
void gnss_sdr_supl_client::print_assistance()
{
if (assist.set & SUPL_RRLP_ASSIST_REFTIME)
{
fprintf(stdout, "T %ld %ld %ld %ld\n", assist.time.gps_week, assist.time.gps_tow,
assist.time.stamp.tv_sec, assist.time.stamp.tv_usec);
}
if (assist.set & SUPL_RRLP_ASSIST_UTC)
{
fprintf(stdout, "U %d %d %d %d %d %d %d %d\n",
assist.utc.a0, assist.utc.a1, assist.utc.delta_tls,
assist.utc.tot, assist.utc.wnt, assist.utc.wnlsf,
assist.utc.dn, assist.utc.delta_tlsf);
}
if (assist.set & SUPL_RRLP_ASSIST_REFLOC)
{
fprintf(stdout, "L %f %f %d\n", assist.pos.lat, assist.pos.lon, assist.pos.uncertainty);
}
if (assist.set & SUPL_RRLP_ASSIST_IONO)
{
fprintf(stdout, "I %d %d %d %d %d %d %d %d\n",
assist.iono.a0, assist.iono.a1, assist.iono.a2, assist.iono.a3,
assist.iono.b0, assist.iono.b1, assist.iono.b2, assist.iono.b3);
}
if (assist.cnt_eph)
{
int i;
fprintf(stdout, "E %d\n", assist.cnt_eph);
for (i = 0; i < assist.cnt_eph; i++)
{
struct supl_ephemeris_s *e = &assist.eph[i];
fprintf(stdout, "e %d %d %d %d %d %d %d %d %d %d",
e->prn, e->delta_n, e->M0, e->A_sqrt, e->OMEGA_0, e->i0, e->w, e->OMEGA_dot, e->i_dot, e->e);
fprintf(stdout, " %d %d %d %d %d %d",
e->Cuc, e->Cus, e->Crc, e->Crs, e->Cic, e->Cis);
fprintf(stdout, " %d %d %d %d %d %d",
e->toe, e->IODC, e->toc, e->AF0, e->AF1, e->AF2);
fprintf(stdout, " %d %d %d %d %d\n",
e->bits, e->ura, e->health, e->tgd, e->AODA);
}
}
if (assist.cnt_alm)
{
int i;
fprintf(stdout, "A %d\n", assist.cnt_alm);
for (i = 0; i < assist.cnt_alm; i++)
{
struct supl_almanac_s *a = &assist.alm[i];
fprintf(stdout, "a %d %d %d %d %d ",
a->prn, a->e, a->toa, a->Ksii, a->OMEGA_dot);
fprintf(stdout, "%d %d %d %d %d %d\n",
a->A_sqrt, a->OMEGA_0, a->w, a->M0, a->AF0, a->AF1);
}
}
if (assist.cnt_acq)
{
int i;
fprintf(stdout, "Q %d %d\n", assist.cnt_acq, assist.acq_time);
for (i = 0; i < assist.cnt_acq; i++)
{
struct supl_acquis_s *q = &assist.acq[i];
fprintf(stdout, "q %d %d %d ",
q->prn, q->parts, q->doppler0);
if (q->parts & SUPL_ACQUIS_DOPPLER)
{
fprintf(stdout, "%d %d ", q->doppler1, q->d_win);
}
else
{
fprintf(stdout, "0 0 ");
}
fprintf(stdout, "%d %d %d %d ",
q->code_ph, q->code_ph_int, q->bit_num, q->code_ph_win);
if (q->parts & SUPL_ACQUIS_ANGLE)
{
fprintf(stdout, "%d %d\n", q->az, q->el);
}
else
{
fprintf(stdout, "0 0\n");
}
}
}
}
int gnss_sdr_supl_client::get_assistance(int i_mcc, int i_mns, int i_lac, int i_ci)
{
// SET SUPL CLIENT INFORMATION
// GSM CELL PARAMETERS
mcc = i_mcc;
mns = i_mns;
lac = i_lac;
ci = i_ci;
supl_set_gsm_cell(&ctx, mcc, mns, lac, ci);
// PERFORM SUPL COMMUNICATION
char *cstr = new char[server_name.length() + 1];
strcpy(cstr, server_name.c_str());
int err;
ctx.p.request = request; // select assistance info request from a pre-defined set
//std::cout<<"mcc="<<mcc<<"mns="<<mns<<"lac="<<lac<<"ci="<<ci<<std::endl;
err = supl_get_assist(&ctx, cstr, &assist);
if (err == 0)
{
read_supl_data();
}
delete [] cstr;
return err;
}
void gnss_sdr_supl_client::read_supl_data()
{
// READ REFERENCE LOCATION
if (assist.set & SUPL_RRLP_ASSIST_REFLOC)
{
gps_ref_loc.lat = assist.pos.lat;
gps_ref_loc.lon = assist.pos.lon;
gps_ref_loc.uncertainty = assist.pos.uncertainty;
gps_ref_loc.valid = true;
}
// READ REFERENCE TIME
if (assist.set & SUPL_RRLP_ASSIST_REFTIME)
{
/* TS 44.031: GPSTOW, range 0-604799.92, resolution 0.08 sec, 23-bit presentation */
gps_time.d_TOW = ((double)assist.time.gps_tow)*0.08;
gps_time.d_Week = (double)assist.time.gps_week;
gps_time.d_tv_sec = (double)assist.time.stamp.tv_sec;
gps_time.d_tv_usec = (double)assist.time.stamp.tv_usec;
gps_time.valid = true;
}
// READ UTC MODEL
if (assist.set & SUPL_RRLP_ASSIST_UTC)
{
gps_utc.d_A0 = ((double)assist.utc.a0)*pow(2.0, -30);
gps_utc.d_A1 = ((double)assist.utc.a1)*pow(2.0, -50);
gps_utc.d_DeltaT_LS = ((double)assist.utc.delta_tls);
gps_utc.d_DeltaT_LSF = ((double)assist.utc.delta_tlsf);
gps_utc.d_t_OT = ((double)assist.utc.tot)*pow(2.0,12);
gps_utc.i_DN = ((double)assist.utc.dn);
gps_utc.i_WN_T = ((double)assist.utc.wnt);
gps_utc.i_WN_LSF = ((double)assist.utc.wnlsf);
gps_utc.valid = true;
}
// READ IONOSPHERIC MODEL
if (assist.set & SUPL_RRLP_ASSIST_IONO)
{
gps_iono.d_alpha0 = (double)assist.iono.a0 * ALPHA_0_LSB;
gps_iono.d_alpha1 = (double)assist.iono.a1 * ALPHA_1_LSB;
gps_iono.d_alpha2 = (double)assist.iono.a2 * ALPHA_2_LSB;
gps_iono.d_alpha3 = (double)assist.iono.a3 * ALPHA_3_LSB;
gps_iono.d_beta0 = (double)assist.iono.b0 * BETA_0_LSB;
gps_iono.d_beta1 = (double)assist.iono.b1 * BETA_1_LSB;
gps_iono.d_beta2 = (double)assist.iono.b2 * BETA_2_LSB;
gps_iono.d_beta3 = (double)assist.iono.b3 * BETA_3_LSB;
gps_iono.valid = true;
}
// READ SV ALMANAC
if (assist.cnt_alm)
{
std::map<int,Gps_Almanac>::iterator gps_almanac_iterator;
for (int i = 0; i < assist.cnt_alm; i++)
{
struct supl_almanac_s *a = &assist.alm[i];
// Check if the SV is present in the map
gps_almanac_iterator = this->gps_almanac_map.find(a->prn);
// the SV is not present in the almanac data -> insert new SV register
if (gps_almanac_iterator==gps_almanac_map.end())
{
Gps_Almanac gps_almanac_entry;
gps_almanac_map.insert(std::pair<int, Gps_Almanac>(a->prn, gps_almanac_entry));
gps_almanac_iterator = this->gps_almanac_map.find(a->prn);
}
gps_almanac_iterator->second.i_satellite_PRN = a->prn;
gps_almanac_iterator->second.d_A_f0 = ((double)a->AF0)*pow(2.0, -20);
gps_almanac_iterator->second.d_A_f1 = ((double)a->AF1)*pow(2.0, -38);
gps_almanac_iterator->second.d_Delta_i = ((double)a->Ksii)*pow(2.0, -19);
gps_almanac_iterator->second.d_OMEGA = ((double)a->w)*pow(2.0, -23);
gps_almanac_iterator->second.d_OMEGA0 = ((double)a->OMEGA_0)*pow(2.0, -23);
gps_almanac_iterator->second.d_sqrt_A = ((double)a->A_sqrt)*pow(2.0, -11);
gps_almanac_iterator->second.d_OMEGA_DOT = ((double)a->OMEGA_dot)*pow(2.0, -38);
gps_almanac_iterator->second.d_Toa = ((double)a->toa)*pow(2.0, 12);
gps_almanac_iterator->second.d_e_eccentricity = ((double)a->toa)*pow(2.0, -21);
gps_almanac_iterator->second.d_M_0 = ((double)a->M0)*pow(2.0, -23);
}
}
// READ SV EPHEMERIS
if (assist.cnt_eph)
{
std::map<int,Gps_Ephemeris>::iterator gps_eph_iterator;
for (int i = 0; i < assist.cnt_eph; i++)
{
struct supl_ephemeris_s *e = &assist.eph[i];
// Check if the SV is present in the map
gps_eph_iterator = this->gps_ephemeris_map.find(e->prn);
// the SV is not present in the assistance data -> insert new SV register
if (gps_eph_iterator == gps_ephemeris_map.end())
{
Gps_Ephemeris gps_eph;
gps_ephemeris_map.insert(std::pair<int,Gps_Ephemeris>(e->prn, gps_eph));
gps_eph_iterator = this->gps_ephemeris_map.find(e->prn);
}
if (gps_time.valid)
{
gps_eph_iterator->second.i_GPS_week = assist.time.gps_week;
/* TS 44.031: GPSTOW, range 0-604799.92, resolution 0.08 sec, 23-bit presentation */
gps_eph_iterator->second.d_TOW = ((double)assist.time.gps_tow)*0.08;
}
else
{
gps_eph_iterator->second.i_GPS_week = 0;
gps_eph_iterator->second.d_TOW = 0;
}
gps_eph_iterator->second.i_satellite_PRN = e->prn;
// SV navigation model
gps_eph_iterator->second.i_code_on_L2 = e->bits;
gps_eph_iterator->second.i_SV_accuracy = e->ura; //User Range Accuracy (URA)
gps_eph_iterator->second.i_SV_health = e->health;
gps_eph_iterator->second.d_IODC = (double)e->IODC;
//miss P flag (1 bit)
//miss SF1 Reserved (87 bits)
gps_eph_iterator->second.d_TGD = ((double)e->tgd)*T_GD_LSB;
gps_eph_iterator->second.d_Toc = ((double)e->toc)*T_OC_LSB;
gps_eph_iterator->second.d_A_f0 = ((double)e->AF0)*A_F0_LSB;
gps_eph_iterator->second.d_A_f1 = ((double)e->AF1)*A_F1_LSB;
gps_eph_iterator->second.d_A_f2 = ((double)e->AF2)*A_F2_LSB;
gps_eph_iterator->second.d_Crc = ((double)e->Crc)*C_RC_LSB;
gps_eph_iterator->second.d_Delta_n = ((double)e->delta_n)*DELTA_N_LSB;
gps_eph_iterator->second.d_M_0 = ((double)e->M0)*M_0_LSB;
gps_eph_iterator->second.d_Cuc = ((double)e->Cuc)*C_UC_LSB;
gps_eph_iterator->second.d_e_eccentricity = ((double)e->e)*E_LSB;
gps_eph_iterator->second.d_Cus = ((double)e->Cus)*C_US_LSB;
gps_eph_iterator->second.d_sqrt_A = ((double)e->A_sqrt)*SQRT_A_LSB;
gps_eph_iterator->second.d_Toe = ((double)e->toe)*T_OE_LSB;
//miss fit interval flag (1 bit)
gps_eph_iterator->second.i_AODO = e->AODA * AODO_LSB;
gps_eph_iterator->second.d_Cic = ((double)e->Cic)*C_IC_LSB;
gps_eph_iterator->second.d_OMEGA0 = ((double)e->OMEGA_0)*OMEGA_0_LSB;
gps_eph_iterator->second.d_Cis = ((double)e->Cis)*C_IS_LSB;
gps_eph_iterator->second.d_i_0 = ((double)e->i0)*I_0_LSB;
gps_eph_iterator->second.d_Crs = ((double)e->Crs)*C_RS_LSB;
gps_eph_iterator->second.d_OMEGA = ((double)e->w)*OMEGA_LSB;
gps_eph_iterator->second.d_OMEGA_DOT = (double)e->OMEGA_dot*OMEGA_DOT_LSB;
gps_eph_iterator->second.d_IDOT = ((double)e->i_dot)*I_DOT_LSB;
}
}
// READ SV ACQUISITION ASSISTANCE
if (assist.cnt_acq)
{
std::map<int,Gps_Acq_Assist>::iterator gps_acq_iterator;
for (int i = 0; i < assist.cnt_acq; i++)
{
struct supl_acquis_s *e = &assist.acq[i];
// Check if the SV is present in the map
gps_acq_iterator=this->gps_acq_map.find(e->prn);
// the SV is not present in the assistance data -> insert new SV register
if (gps_acq_iterator == gps_acq_map.end())
{
Gps_Acq_Assist gps_acq_assist;
gps_acq_map.insert(std::pair<int,Gps_Acq_Assist>(e->prn, gps_acq_assist));
gps_acq_iterator = this->gps_acq_map.find(e->prn);
}
// fill the acquisition assistance structure
gps_acq_iterator->second.i_satellite_PRN = e->prn;
gps_acq_iterator->second.d_TOW = (double)assist.acq_time;
gps_acq_iterator->second.d_Doppler0 = (double)e->doppler0;
gps_acq_iterator->second.d_Doppler1 = (double)e->doppler1;
gps_acq_iterator->second.dopplerUncertainty = (double)e->d_win;
gps_acq_iterator->second.Code_Phase = (double)e->code_ph;
gps_acq_iterator->second.Code_Phase_int = (double)e->code_ph_int;
gps_acq_iterator->second.Code_Phase_window = (double)e->code_ph_win;
gps_acq_iterator->second.Azimuth = (double)e->az;
gps_acq_iterator->second.Elevation = (double)e->el;
gps_acq_iterator->second.GPS_Bit_Number = (double)e->bit_num;
}
}
}
bool gnss_sdr_supl_client::load_ephemeris_xml(const std::string file_name)
{
try
{
std::ifstream ifs(file_name.c_str(), std::ifstream::binary | std::ifstream::in);
boost::archive::xml_iarchive xml(ifs);
gps_ephemeris_map.clear();
xml >> boost::serialization::make_nvp("GNSS-SDR_ephemeris_map", gps_ephemeris_map);
ifs.close();
}
catch (std::exception& e)
{
LOG_AT_LEVEL(ERROR) << e.what() << "File: " << file_name;
return false;
}
return true;
}
bool gnss_sdr_supl_client::save_ephemeris_xml(const std::string file_name)
{
try
{
std::ofstream ofs(file_name.c_str(), std::ofstream::trunc | std::ofstream::out);
boost::archive::xml_oarchive xml(ofs);
xml << boost::serialization::make_nvp("GNSS-SDR_ephemeris_map", gps_ephemeris_map);
ofs.close();
}
catch (std::exception& e)
{
LOG_AT_LEVEL(ERROR) << e.what();
return false;
}
return true;
}