#include #include #include #include #include "fmt/format.h" #include "fmt/printf.h" #include "CLI/CLI.hpp" #include #include #include #include #include #include #include #include "ubx.hh" #include "bits.hh" #include "minivec.hh" #include "navmon.pb.h" #include "ephemeris.hh" #include "gps.hh" #include "glonass.hh" #include "beidou.hh" #include "galileo.hh" #include "navmon.hh" #include "tle.hh" #include "sp3.hh" #include using namespace std; Point g_ourpos; vector g_sp3s; bool sp3Order(const SP3Entry& a, const SP3Entry& b) { return tie(a.gnss, a.sv, a.t) < tie(b.gnss, b.sv, b.t); } void readSP3s(string_view fname) { SP3Reader sp3(fname); SP3Entry e; while(sp3.get(e)) { g_sp3s.push_back(e); } sort(g_sp3s.begin(), g_sp3s.end(), sp3Order); } string beidouHealth(int in) { string ret; if(in == 256) { return "NO CLOCK"; } if(in==511) { return "NO SAT"; } if(in & (1<<7)) ret += "B1I abnormal "; if(in & (1<<6)) ret += "B2I abnormal "; if(in & (1<<5)) ret += "B3I abnormal "; if(in & (1<<1)) ret += "navigation abnormal "; if(ret.empty()) return "OK"; return ret; } double utcFromGPS(int wn, double tow) { return (315964800 + wn * 7*86400 + tow - 18); } static double utcFromGST(int wn, double tow) { return (935280000.0 + wn * 7*86400 + tow - 18); } // GALILEO ONLY!! template void doOrbitDump(int gnss, int sv, int wn, const T& oldEph, const T& newEph, int time_start, int time_end) { ofstream orbitcsv("orbit."+to_string(gnss)+"."+to_string(sv)+"."+to_string(oldEph.iodnav)+"-"+to_string(newEph.iodnav)+".csv"); orbitcsv << "timestamp x y z oldx oldy oldz\n"; orbitcsv << fixed; for(int t = time_start; t < time_end; t += 30) { Point p, oldp; getCoordinates(t, newEph, &p); getCoordinates(t, oldEph, &oldp); time_t posix = utcFromGST(wn, t); orbitcsv << posix <<" " < d_filter; }; int main(int argc, char** argv) try { GOOGLE_PROTOBUF_VERIFY_VERSION; CLI::App app("navdump"); TLERepo tles; // tles.parseFile("active.txt"); tles.parseFile("galileo.txt"); tles.parseFile("glo-ops.txt"); tles.parseFile("gps-ops.txt"); tles.parseFile("beidou.txt"); /* readSP3s("all.sp3"); if(!g_sp3s.empty()) { // sort(g_sp3s.begin(), g_sp3s.end(), [](const auto& a, const auto&b) { return a.t < b.t; }); cout<<"Have "<t) <<" to "<< humanTime(g_sp3s.rbegin()->t)< svpairs; bool doReceptionData{false}; bool doRFData{true}; bool doObserverPosition{false}; app.add_option("--svs", svpairs, "Listen to specified svs. '0' = gps, '2' = Galileo, '2,1' is E01"); app.add_option("--positions,-p", doObserverPosition, "Print out observer positions (or not)"); app.add_option("--rfdata,-r", doRFData, "Print out RF data (or not)"); try { app.parse(argc, argv); } catch(const CLI::Error &e) { return app.exit(e); } SVFilter svfilter; for(const auto& svp : svpairs) { svfilter.addFilter(svp); } ofstream almanac("almanac.txt"); ofstream iodstream("iodstream.csv"); iodstream << "timestamp gnssid sv iodnav t0e age" << endl; ofstream csv("delta.csv"); csv <<"timestamp gnssid sv tow tle_distance alma_distance utc_dist x y z vx vy vz rad inclination e iod"< inav((uint8_t*)nmm.gi().contents().c_str(), nmm.gi().contents().size()); static map gms; static map, GalileoMessage> gmwtypes; static map oldgm4s; int sv = nmm.gi().gnsssv(); if(!svfilter.check(2, sv, nmm.gi().sigid())) continue; etstamp(); int64_t imptow = (((uint32_t)round(nmm.localutcseconds() + nmm.localutcnanoseconds()/1000000000.0) - 935280000 + 18) % (7*86400)) - 2; if(nmm.gi().sigid() != 5) { if(!(imptow % 2)) imptow--; } else if((imptow % 2)) imptow--; if(imptow != nmm.gi().gnsstow()) cout<< " !!"<< (imptow - nmm.gi().gnsstow()) <<"!! "; GalileoMessage& gm = gms[sv]; int wtype = gm.parse(inav); gm.tow = nmm.gi().gnsstow(); gmwtypes[{nmm.gi().gnsssv(), wtype}] = gm; static map oldEph; cout << "gal inav wtype "<gnss == e.gnss && bestSP3->sv == sv) { static set> haveSeen; if(!haveSeen.count({sv, bestSP3->t})) { haveSeen.insert({sv, bestSP3->t}); Point newPoint; getCoordinates(gm.tow + (bestSP3->t - start), gm, &newPoint); Point sp3Point(bestSP3->x, bestSP3->y, bestSP3->z); Vector dist(newPoint, sp3Point); cout<<"\nsp3 "<<(bestSP3->t - start)<<" E"<t)<<" (" << newPoint.x/1000.0 <<", "<x/1000.0) <<", " << (bestSP3->y/1000.0) <<", " << (bestSP3->z/1000.0) << ") "<clockBias << " " << gm.getAtomicOffset(gm.tow + (bestSP3->t-start)).first<< " " << dist.length()<< " "; cout << (bestSP3->clockBias - gm.getAtomicOffset(gm.tow + (bestSP3->t-start)).first); cout << " " << gm.af0 <<" " << gm.af1; cout << endl; sp3csv <t << " 2 "<< sv <<" " << ephAge(gm.tow+(bestSP3->t - start), gm.getT0e()) <<" "<x<<" " << bestSP3->y<<" " <z <<" " << newPoint.x<<" " <clockBias <<" "; sp3csv << gm.getAtomicOffset(gm.tow + (bestSP3->t-start)).first<<" " << dist.length() <<" "; sp3csv << (bestSP3->clockBias - gm.getAtomicOffset(gm.tow + (bestSP3->t-start)).first) << endl; } } if(!oldEph[sv].sqrtA) oldEph[sv] = gm; else if(oldEph[sv].iodnav != gm.iodnav) { cout<<" disco! "<< oldEph[sv].iodnav << " - > "<=7 && wtype<=10) cout<<" ioda "<((uint8_t*)nmm.gpsi().contents().c_str(), nmm.gpsi().contents().size())); struct GPSState gs; static map eph; static map almas; uint8_t page; static int gpswn; int frame=parseGPSMessage(cond, gs, &page); cout<<"GPS "< oldgs1s; gpswn = gs.wn; cout << "gpshealth = "<<(int)gs.gpshealth<<", wn "<second.t0c != gs.t0c) { auto oldOffset = getGPSAtomicOffset(gs.tow, iter->second); auto newOffset = getGPSAtomicOffset(gs.tow, gs); cout<<" Timejump: "<second) )<<" seconds, old t0c "<second.t0c; } oldgs1s[sv] = gs; } else if(frame == 2) { parseGPSMessage(cond, eph[sv], &page); cout << "t0e = "<second.t0e << " " <second.t0e) << " iod "<= 25 && gs.gpsalma.sv <= 32) || gs.gpsalma.sv==57 ) { // see table 20-V of the GPS ICD cout << " data-id "<((uint8_t*)nmm.bid1().contents().c_str(), nmm.bid1().contents().size())); uint8_t pageno; static map bms; auto& bm = bms[sv]; int fraid = bm.parse(cond, &pageno); cout<<"BeiDou "< msgs; if(msgs[sv].wn>= 0 && msgs[sv].t0c != bm.t0c) { auto oldOffset = msgs[sv].getAtomicOffset(bm.sow); auto newOffset = bm.getAtomicOffset(bm.sow); cout<<" Timejump: "<((uint8_t*)nmm.bid2().contents().c_str(), nmm.bid2().contents().size())); BeidouMessage bm; uint8_t pageno; int fraid = bm.parse(cond, &pageno); cout<<"BeiDou "< gms; auto& gm = gms[nmm.gloi().gnsssv()]; int strno = gm.parse(std::basic_string((uint8_t*)nmm.gloi().contents().c_str(), nmm.gloi().contents().size())); cout<<"Glonass R"< "; cout << "("<