From 2578439e5ff01f3ed483cc6ce6ce14aa5ea7bad8 Mon Sep 17 00:00:00 2001 From: 168492376 <168492376@qq.com> Date: Sun, 10 Nov 2024 14:55:21 +0800 Subject: [PATCH] first commit --- CMakeLists.txt | 16 + src/comtyp.h | 173 ++++++++ src/const.c | 208 +++++++++ src/const.h | 504 +++++++++++++++++++++ src/decodenav.c | 455 +++++++++++++++++++ src/decodenav.h | 20 + src/decodeobs.c | 490 ++++++++++++++++++++ src/decodeobs.h | 18 + src/init_val.c | 14 + src/init_val.h | 7 + src/main.c | 29 ++ src/obscode.c | 151 +++++++ src/obscode.h | 7 + src/option.h | 78 ++++ src/readobsnav.c | 1079 +++++++++++++++++++++++++++++++++++++++++++++ src/readobsnav.h | 70 +++ src/satellite.c | 158 +++++++ src/satellite.h | 28 ++ src/str.c | 76 ++++ src/str.h | 34 ++ src/timeconvert.c | 132 ++++++ src/timeconvert.h | 84 ++++ 22 files changed, 3831 insertions(+) create mode 100644 CMakeLists.txt create mode 100644 src/comtyp.h create mode 100644 src/const.c create mode 100644 src/const.h create mode 100644 src/decodenav.c create mode 100644 src/decodenav.h create mode 100644 src/decodeobs.c create mode 100644 src/decodeobs.h create mode 100644 src/init_val.c create mode 100644 src/init_val.h create mode 100644 src/main.c create mode 100644 src/obscode.c create mode 100644 src/obscode.h create mode 100644 src/option.h create mode 100644 src/readobsnav.c create mode 100644 src/readobsnav.h create mode 100644 src/satellite.c create mode 100644 src/satellite.h create mode 100644 src/str.c create mode 100644 src/str.h create mode 100644 src/timeconvert.c create mode 100644 src/timeconvert.h diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..52e3e04 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,16 @@ +cmake_minimum_required(VERSION 2.8) + +add_library(libspp +src/readobsnav.c +src/const.c +src/init_val.c +src/decodeobs.c +src/str.c +src/obscode.c +src/decodenav.c +src/timeconvert.c +src/satellite.c +) + +add_executable(main src/main.c) +target_link_libraries(main libspp m) diff --git a/src/comtyp.h b/src/comtyp.h new file mode 100644 index 0000000..862d61a --- /dev/null +++ b/src/comtyp.h @@ -0,0 +1,173 @@ +#ifndef COMTYP_H +#define COMTYP_H +#include "const.h" + +typedef struct +{ + long long time; // time (s) expressed by standard time_t + double sec; // fraction of second under 1 s +}gtime_t; + +typedef struct +{ + int sys; // navigation system + int vs; // valid satellite flag single + double azel[2]; // azimuth/elevation angles {az,el} (rad) + double resp[NFREQ]; // residuals of pseudorange (m) + double resc[NFREQ]; // residuals of carrier-phase (m) + double icbias[NFREQ]; // glonass IC bias (cycles) + int vsat[NFREQ]; // valid satellite flag + int snr[NFREQ]; // signal strength (0.25 dBHz) + int lock[NFREQ]; // lock counter of phase +}ssat_t; + +typedef struct +{ + gtime_t time; // receiver sampling time (GPST) + int sat,rcv; // satellite/receiver number + int SNR[NFREQ+NEXOBS]; // signal strength (0.25 dBHz) + int LLI[NFREQ+NEXOBS]; // loss of lock indicator + int code[NFREQ+NEXOBS]; // code indicator (CODE_???) + int qualL[NFREQ+NEXOBS]; // quality of carrier phase measurement + int qualP[NFREQ+NEXOBS]; // quality of pseudorange measurement + double L[NFREQ+NEXOBS]; // observation data carrier-phase (cycle) + double P[NFREQ+NEXOBS]; // observation data pseudorange (m) + double D[NFREQ+NEXOBS]; // observation data doppler frequency (Hz) +}obsd_t; + +typedef struct +{ + int n,nmax; // number of obervation data/allocated + double tint; // time interval + obsd_t* data; // observation data records +}obs_t; + +typedef struct +{ + int sat; // satellite number + int iode,iodc; // IODE,IODC + int sva; // SV accuracy (URA index) + int svh; // SV health (0:ok) + int week; // GPS/QZS: gps week, GAL: galileo week + int code; // GPS/QZS: code on L2, GAL/CMP: data sources + int flag; // GPS/QZS: L2 P data flag, CMP: nav type + gtime_t toe,toc,ttr; // Toe,Toc,T_trans + // SV orbit parameters + double A,e,i0,OMG0,omg,M0,deln,OMGd,idot; + double crc,crs,cuc,cus,cic,cis; + double toes; // Toe (s) in week + double fit; // fit interval (h) + double f0,f1,f2; // SV clock parameters (af0,af1,af2) + double tgd[4]; // group delay parameters + // GPS/QZS:tgd(0)=TGD + // GAL :tgd(0)=BGD E5a/E1,tgd(1)=BGD E5b/E1 + // CMP :tgd(0)=BGD1,tgd(1)=BGD2 + double Adot,ndot; // Adot,ndot for CNAV +}eph_t; + +typedef struct +{ + int sat; // satellite number + int iode; // IODE (0-6 bit of tb field) + int frq; // satellite frequency number + int svh,sva,age; // satellite health, accuracy, age of operation + gtime_t toe; // epoch of epherides (gpst) + gtime_t tof; // message frame time (gpst) + double pos[3]; // satellite position (ecef) (m) + double vel[3]; // satellite velocity (ecef) (m/s) + double acc[3]; // satellite acceleration (ecef) (m/s^2) + double taun,gamn; // SV clock bias (s)/relative freq bias + double dtaun; // delay between L1 and L2 (s) +}geph_t; + +typedef struct +{ /* SBAS ephemeris type */ + int sat; /* satellite number */ + gtime_t t0; /* reference epoch time (GPST) */ + gtime_t tof; /* time of message frame (GPST) */ + int sva; /* SV accuracy (URA index) */ + int svh; /* SV health (0:ok) */ + double pos[3]; /* satellite position (m) (ecef) */ + double vel[3]; /* satellite velocity (m/s) (ecef) */ + double acc[3]; /* satellite acceleration (m/s^2) (ecef) */ + double af0, af1; /* satellite clock-offset/drift (s,s/s) */ +}seph_t; + +typedef struct +{ + int sat; // satellite number + int svh; // sv health (0:ok) + int svconf; // as and sv config + int week; // GPS/QZS: gps week, GAL: galileo week + gtime_t toa; // Toa + // SV orbit parameters + double A,e,i0,OMG0,omg,M0,OMGd; + double toas; // Toa (s) in week + double f0,f1; // SV clock parameters (af0,af1) +}alm_t; + +typedef struct +{ + int n,nmax; // number of broadcast ephemeris + int ng,ngmax; // number of glonass ephemeris + int ns,nsmax; // number of sbas ephemeris + int ne,nemax; // number of precise ephemeris + int nc,ncmax; // number of precise clock + int na,namax; // number of almanac data + int nt,ntmax; // number of tec grid data + int nf,nfmax; // number of satellite fcb data + eph_t* eph; // GPS/QZS/GAL ephemeris + geph_t* geph; // GLONASS ephemeris + seph_t *seph; /* SBAS ephemeris */ + alm_t* alm; // almanac data + double utc_gps[4]; // GPS delta-UTC parameters {A0,A1,T,W} + double utc_glo[4]; // GLONASS UTC GPS time parameters + double utc_gal[4]; // Galileo UTC GPS time parameters + double utc_qzs[4]; // QZS UTC GPS time parameters + double utc_cmp[4]; // BeiDou UTC parameters + double utc_irn[4]; // IRNSS UTC parameters + double utc_sbs[4]; // SBAS UTC parameters + double ion_gps[8]; // GPS iono model parameters {a0,a1,a2,a3,b0,b1,b2,b3} + double ion_gal[4]; // Galileo iono model parameters {ai0,ai1,ai2,0} + double ion_qzs[8]; // QZSS iono model parameters {a0,a1,a2,a3,b0,b1,b2,b3} + double ion_cmp[8]; // BeiDou iono model parameters {a0,a1,a2,a3,b0,b1,b2,b3} + double ion_irn[8]; // IRNSS iono model parameters {a0,a1,a2,a3,b0,b1,b2,b3} + int leaps; // leap seconds (s) + double lam[MAXSAT][NFREQ];// carrier wave lengths (m) + double cbias[MAXSAT][3]; // satellite dcb (0:p1-p2,1:p1-c1,2:p2-c2) (m) + double rbias[MAXRCV][2][3];// receiver dcb (0:p1-p2,1:p1-c1,2:p2-c2) (m) + double wlbias[MAXSAT]; // wide-lane bias (cycle) + double glo_cpbias[4]; // glonass code-phase bias {1C,1P,2C,2P} (m) + char glo_fcn[MAXPRNGLO+1];// glonass frequency channel number + 8 +}nav_t; + +typedef struct +{ + char name[MAXANT]; // marker name + char marker[MAXANT]; // marker number + char antdes[MAXANT]; // antenna descriptor + char antsno[MAXANT]; // antenna serial number + char rectype[MAXANT]; // receiver type descriptor + char recver[MAXANT]; // receiver firmware version + char recsno[MAXANT]; // receiver serial number + int antsetup; // antenna setup id + int itrf; // ITRF realization year + int deltype; // antenna delta type (0:enu,1:xyz) + double pos[3]; // station position (ecef) (m) + double del[3]; // antenna position delta (e/n/u or x/y/z) (m) + double hgt; // antenna height (m) +}sta_t; + +typedef struct +{ + int n; //number of index + int frqIdx[MAXOBSTYPE]; //signal frequency (1:L1,2:L2,...) + int pos[MAXOBSTYPE]; //signal index in obs data (-1:no) + int pri[MAXOBSTYPE]; //signal priority (15-0) + int type[MAXOBSTYPE]; //type (0:C,1:L,2:D,3:S) + int code[MAXOBSTYPE]; //obs code (CODE_L??) + double shift[MAXOBSTYPE];//phase shift (cycle) +}sigind_t; + + +#endif \ No newline at end of file diff --git a/src/const.c b/src/const.c new file mode 100644 index 0000000..c1eab38 --- /dev/null +++ b/src/const.c @@ -0,0 +1,208 @@ +#include "const.h" + +// Definition of constant ---------------------------------------------------- +const double PI = 3.1415926535897932e0; //! pi +const double D2R = (PI/180.e0); //! deg to rad +const double R2D = (180.e0/PI); //! rad to deg +const double CLIGHT = 299792458.e0; //! speed of light (m/s) +const double SC2RAD = 3.1415926535898e0; //! semi-circle to radian (IS-GPS) +const double AU = 149597870691.e0; //! 1 AU (m) +const double AS2R = (D2R/3600.e0); //! arc sec to radian + +const double OMGE = 7.2921151467e-5; //! earth angular velocity (IS-GPS) (rad/s) +const double RE_WGS84 = 6378137.e0; //! earth semimajor axis (WGS84) (m) +const double FE_WGS84 = (1.e0/298.257223563e0); //! earth flattening (WGS84) + +const double HION = 350000.e0; //! ionosphere height (m) + + +const double FREQL1 = 1.57542e9; //! L1/E1 frequency (Hz) +const double FREQL2 = 1.22760e9; //! L2 frequency (Hz) +const double FREQL5 = 1.17645e9; //! L5/E5a frequency (Hz) +const double FREQL6 = 1.27875e9; //! E6/LEX frequency (Hz) +const double FREQE5b = 1.20714e9; //! E5b frequency (Hz) +const double FREQE5ab = 1.191795e9; //! E5a+b frequency (Hz) +const double FREQs = 2.492028e9; //! S frequency (Hz) +const double FREQ1_GLO = 1.60200e9; //! GLONASS G1 base frequency (Hz) +const double DFRQ1_GLO = 0.56250e6; //! GLONASS G1 bias frequency (Hz/n) +const double FREQ2_GLO = 1.24600e9; //! GLONASS G2 base frequency (Hz) +const double DFRQ2_GLO = 0.43750e6; //! GLONASS G2 bias frequency (Hz/n) +const double FREQ1a_GLO = 1.600995E9; // GLONASS G1a frequency (Hz) +const double FREQ2a_GLO = 1.248060E9; // GLONASS G2a frequency (Hz) +const double FREQ3_GLO = 1.202025e9; //! GLONASS G3 frequency (Hz) +const double FREQ1_CMP = 1.561098e9; //! BeiDou B1 frequency (Hz) +const double FREQ2_CMP = 1.20714e9; //! BeiDou B2 frequency (Hz) +const double FREQ3_CMP = 1.26852e9; //! BeiDou B3 frequency (Hz) + +const double EFACT_GPS = 1.e0; //! error factor: GPS +const double EFACT_GLO = 1.5e0; //! error factor: GLONASS +const double EFACT_GAL = 1.e0; //! error factor: Galileo +const double EFACT_QZS = 1.e0; //! error factor: QZSS +const double EFACT_CMP = 1.e0; //! error factor: BeiDou +const double EFACT_IRN = 1.5e0; //! error factor: IRNSS +const double EFACT_SBS = 3.e0; //! error factor: SBAS + + + +const double DTTOL = 0.015e0; //! tolerance of time difference (s) +const double MAXDTOE = 7200.e0; //! max time difference to GPS Toe (s) +const double MAXDTOE_QZS = 7200.e0; //! max time difference to QZSS Toe (s) +const double MAXDTOE_GAL = 14400.e0; //! max time difference to Galileo Toe (s) +const double MAXDTOE_CMP = 21600.e0; //! max time difference to BeiDou Toe (s) +const double MAXDTOE_GLO = 1800.e0; //! max time difference to GLONASS Toe (s) +const double MAXDTOE_SBS = 360.e0; //! max time difference to SBAS Toe (s) +const double MAXDTOE_S = 86400.e0; //! max time difference to ephem toe (s) for other +const double MAXGDOP = 300.e0; //! max GDOP + +const double INT_SWAP_TRAC = 86400.e0; //! swap interval of trace file (s) +const double INT_SWAP_STAT = 86400.e0; //! swap interval of solution status file (s) + + +const double MAXSBSAGEF = 30.e0; //! max age of SBAS fast correction (s) +const double MAXSBSAGEL = 1800.e0; //! max age of SBAS long term corr (s) + +const double RNX2VER = 2.10e0; //! RINEX ver.2 default output version +const double RNX3VER = 3.00e0; //! RINEX ver.3 default output version + + +const char COMMENTH[2] = "%"; //! comment line indicator for solution +const char MSG_DISCONN[13] = "$_DISCONNECT"; //! disconnect message + +const double P2_5 = 0.03125e0; //! 2^-5 +const double P2_6 = 0.015625e0; //! 2^-6 +const double P2_11 = 4.882812500000000e-04; //! 2^-11 +const double P2_15 = 3.051757812500000e-05; //! 2^-15 +const double P2_17 = 7.629394531250000e-06; //! 2^-17 +const double P2_19 = 1.907348632812500e-06; //! 2^-19 +const double P2_20 = 9.536743164062500e-07; //! 2^-20 +const double P2_21 = 4.768371582031250e-07; //! 2^-21 +const double P2_23 = 1.192092895507810e-07; //! 2^-23 +const double P2_24 = 5.960464477539063e-08; //! 2^-24 +const double P2_27 = 7.450580596923828e-09; //! 2^-27 +const double P2_29 = 1.862645149230957e-09; //! 2^-29 +const double P2_30 = 9.313225746154785e-10; //! 2^-30 +const double P2_31 = 4.656612873077393e-10; //! 2^-31 +const double P2_32 = 2.328306436538696e-10; //! 2^-32 +const double P2_33 = 1.164153218269348e-10; //! 2^-33 +const double P2_35 = 2.910383045673370e-11; //! 2^-35 +const double P2_38 = 3.637978807091710e-12; //! 2^-38 +const double P2_39 = 1.818989403545856e-12; //! 2^-39 +const double P2_40 = 9.094947017729280e-13; //! 2^-40 +const double P2_43 = 1.136868377216160e-13; //! 2^-43 +const double P2_48 = 3.552713678800501e-15; //! 2^-48 +const double P2_50 = 8.881784197001252e-16; //! 2^-50 +const double P2_55 = 2.775557561562891e-17; //! 2^-55 + +//! rtkcmn.f90 ---------------------------------------------------------------- +const double MAX_VAR_EPH = 9e4; //! max variance eph to reject satellite (m^2) +const double gpst0[6]={1980,1, 6,0,0,0}; //! gps time reference +const double gst0[6] ={1999,8,22,0,0,0}; //! galileo system time reference +const double bdt0[6] ={2006,1, 1,0,0,0}; //! beidou time reference + +const double lam_carr[MAXFREQ]={ //! carrier wave length (m) + CLIGHT/FREQL1,CLIGHT/FREQL2,CLIGHT/FREQL5,CLIGHT/FREQL6,CLIGHT/FREQE5b, + CLIGHT/FREQE5ab,CLIGHT/FREQs}; + +//! leap seconds (y,m,d,h,m,s,utc-gpst) +const double leaps[19][7]={ + {2017,1,1,0,0,0,-18}, + {2015,7,1,0,0,0,-17}, + {2012,7,1,0,0,0,-16}, + {2009,1,1,0,0,0,-15}, + {2006,1,1,0,0,0,-14}, + {1999,1,1,0,0,0,-13}, + {1997,7,1,0,0,0,-12}, + {1996,1,1,0,0,0,-11}, + {1994,7,1,0,0,0,-10}, + {1993,7,1,0,0,0, -9}, + {1992,7,1,0,0,0, -8}, + {1991,1,1,0,0,0, -7}, + {1990,1,1,0,0,0, -6}, + {1988,1,1,0,0,0, -5}, + {1985,7,1,0,0,0, -4}, + {1983,7,1,0,0,0, -3}, + {1982,7,1,0,0,0, -2}, + {1981,7,1,0,0,0, -1}, + {0 ,0,0,0,0,0, 0} + }; + +//! observation code strings +const char obscodes[60][3]={ + {" "},{"1C"},{"1P"},{"1W"},{"1Y"}, {"1M"},{"1N"},{"1S"},{"1L"},{"1E"}, //! 0- 9 + {"1A"},{"1B"},{"1X"},{"1Z"},{"2C"}, {"2D"},{"2S"},{"2L"},{"2X"},{"2P"}, //! 10-19 + {"2W"},{"2Y"},{"2M"},{"2N"},{"5I"}, {"5Q"},{"5X"},{"7I"},{"7Q"},{"7X"}, //! 20-29 + {"6A"},{"6B"},{"6C"},{"6X"},{"6Z"}, {"6S"},{"6L"},{"8L"},{"8Q"},{"8X"}, //! 30-39 + {"2I"},{"2Q"},{"6I"},{"6Q"},{"3I"}, {"3Q"},{"3X"},{"1I"},{"1Q"},{"5A"}, //! 40-49 + {"5B"},{"5C"},{"9A"},{"9B"},{"9C"}, {"9X"},{" "},{" "},{" "},{" "} //! 50-59 +}; + +//! 1:L1/E1, 2:L2/B1, 3:L5/E5a/L3, 4:L6/LEX/B3, 5:E5b/B2, 6:E5(a+b), 7:S +const int obsfreqs[60]={ + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, //! 0- 9 + 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, //! 10-19 + 2, 2, 2, 2, 3, 3, 3, 5, 5, 5, //! 20-29 + 4, 4, 4, 4, 4, 4, 4, 6, 6, 6, //! 30-39 + 2, 2, 4, 4, 3, 3, 3, 1, 1, 3, //! 40-49 + 3, 3, 7, 7, 7, 7, 0, 0, 0, 0 //! 50-59 +}; + +//! code priority table +//! L1/E1; L2/B1; L5/E5a/L3; L6/LEX/B3; E5b/B2; E5(a+b); S +const char codepris[7][MAXFREQ][17]={ + {"CPYWMNSL ","PYWCMNDSLX","IQX "," "," "," "," "}, //! GPS + {"PC ","PC ","IQX "," "," "," "," "}, //! GLO + {"CABXZ "," ","IQX ","ABCXZ ","IQX ","IQX "," "}, //! GAL + {"CSLXZ ","SLX ","IQX ","SLX "," "," "," "}, //! QZS + {"C "," ","IQX "," "," "," "," "}, //! SBS + {"IQX ","IQX ","IQX ","IQX ","IQX "," "," "}, //! BDS + {" "," ","ABCX "," "," "," ","ABCX "} //! IRN +}; + +//! ephemeris.f90 ------------------------------------------------------------- +const double RE_GLO = 6378136.e0; //! radius of earth (m) ref (2) +const double MU_GPS = 3.9860050e14; //! gravitational constant ref (1) +const double MU_GLO = 3.9860044e14; //! gravitational constant ref (2) +const double MU_GAL = 3.986004418e14; //! earth gravitational constant ref (7) +const double MU_CMP = 3.986004418e14; //! earth gravitational constant ref (9) +const double J2_GLO = 1.0826257e-3; //! 2nd zonal harmonic of geopot ref (2) + +const double OMGE_GLO = 7.292115e-5; //! earth angular velocity (rad/s) ref (2) +const double OMGE_GAL = 7.2921151467e-5; //! earth angular velocity (rad/s) ref (7) +const double OMGE_CMP = 7.292115e-5; //! earth angular velocity (rad/s) ref (9) +const double SIN_5 = -0.0871557427476582e0; //! dsin(-5.e0 deg) +const double COS_5 = 0.9961946980917456e0; //! dcos(-5.e0 deg) + +const double ERREPH_GLO = 5.e0; //! error of glonass ephemeris (m) +const double TSTEP = 60.e0; //! integration step glonass ephemeris (s) +const double RTOL_KEPLER = 1e-13; //! relative tolerance for Kepler equation + +const double DEFURASSR = 0.15e0; //! default accurary of ssr corr (m) +const double MAXECORSSR = 10.e0; //! max orbit correction of ssr (m) +const double MAXCCORSSR = (1e-6*CLIGHT); //! max clock correction of ssr (m) +const double MAXAGESSR = 90.e0; //! max age of ssr orbit and clock (s) +const double MAXAGESSR_HRCLK = 10.e0; //! max age of ssr high-rate clock (s) +const double STD_BRDCCLK = 30.e0; //! error of broadcast clock (m) +const double STD_GAL_NAPA = 500.e0; //! error of galileo ephemeris for NAPA (m) + + +const int eph_sel[6]={0,0,1,0,0,0}; //! GPS,GLO,GAL,QZS,BDS,SBS (ephemeris selections) + +//! pntpos.f90 ---------------------------------------------------------------- +const double ERR_ION = 5.e0 ; //! ionospheric delay std (m) +const double ERR_TROP = 3.e0; //! tropspheric delay std (m) +const double ERR_SAAS = 0.3e0; //! saastamoinen model error std (m) +const double ERR_BRDCI = 0.5e0; //! broadcast iono model error factor +const double ERR_CBIAS = 0.3e0; //! code bias error std (m) +const double REL_HUMI = 0.7e0; //! relative humidity for saastamoinen model + +//! rinex.f90 ----------------------------------------------------------------- +const char systyps[8] = "GREJSCI"; //! satellite system codes +const char obstyps[5] = "CLDS"; //! obs type codes +const char frqtyps[8] = "1256789"; //! frequency codes +const double ura_eph[16] = { //! ura values (ref [3] 20.3.3.3.1.1) + 2.4,3.4,4.85,6.85,9.65,13.65,24.0,48.0,96.0, + 192.0,384.0,768.0,1536.0,3072.0,6144.0,0.00}; +const double ura_nominal[16] = { //! ura nominal values + 2.0,2.8,4.0,5.7,8.0,11.3,16.0,32.0,64.0, + 128.0,256.0,512.0,1024.0,2048.0,4096.0,8192.0}; + diff --git a/src/const.h b/src/const.h new file mode 100644 index 0000000..3aa6bb9 --- /dev/null +++ b/src/const.h @@ -0,0 +1,504 @@ +#ifndef CONST_H +#define CONST_H + +#define SNR_UNIT 0.25 /* SNR unit (dBHz) */ + +#define MAXFREQ 7 //! max NFREQ +#define SYS_NONE 0 //!0x00 //! navigation system: none +#define SYS_GPS 1 //!0x01 //! navigation system: GPS +#define SYS_SBS 2 //!0x02 //! navigation system: SBAS +#define SYS_GLO 4 //!0x04 //! navigation system: GLONASS +#define SYS_GAL 8 //!0x08 //! navigation system: Galileo +#define SYS_QZS 16 //!0x10 //! navigation system: QZSS +#define SYS_CMP 32 //!0x20 //! navigation system: BeiDou +#define SYS_IRN 64 //!0x40 //! navigation system: IRNS +#define SYS_LEO 128 //!0x80 //! navigation system: LEO +#define SYS_ALL 255 //!0xFF //! navigation system: all + +#define TSYS_GPS 0 //! time system: GPS time +#define TSYS_UTC 1 //! time system: UTC +#define TSYS_GLO 2 //! time system: GLONASS time +#define TSYS_GAL 3 //! time system: Galileo time +#define TSYS_QZS 4 //! time system: QZSS time +#define TSYS_CMP 5 //! time system: BeiDou time +#define TSYS_IRN 6 //! time system: IRNSS time + +#define NFREQ 3 //! number of carrier frequencies +#define NFREQGLO 2 //! number of carrier frequencies of GLONASS +#define NEXOBS 3 //! number of extended obs codes + +#define MINPRNGPS 1 //! min satellite PRN number of GPS +#define MAXPRNGPS 32 //! max satellite PRN number of GPS +#define NSATGPS (MAXPRNGPS-MINPRNGPS+1) //! number of GPS satellites +#define NSYSGPS 1 + +#define MINPRNGLO 1 //! min satellite slot number of GLONASS +#define MAXPRNGLO 27 //! max satellite slot number of GLONASS +#define NSATGLO (MAXPRNGLO-MINPRNGLO+1) //! number of GLONASS satellites +#define NSYSGLO 1 + +#define MINPRNGAL 1 //! min satellite PRN number of Galileo +#define MAXPRNGAL 36 //! max satellite PRN number of Galileo +#define NSATGAL (MAXPRNGAL-MINPRNGAL+1) //! number of Galileo satellites +#define NSYSGAL 1 + +#define MINPRNQZS 193 //! min satellite PRN number of QZSS +#define MAXPRNQZS 202 //! max satellite PRN number of QZSS +#define MINPRNQZS_S 183 //! min satellite PRN number of QZSS SAIF +#define MAXPRNQZS_S 191 //! max satellite PRN number of QZSS SAIF +#define NSATQZS (MAXPRNQZS-MINPRNQZS+1) //! number of QZSS satellites +#define NSYSQZS 1 + +#define MINPRNCMP 1 //! min satellite sat number of BeiDou +#define MAXPRNCMP 37 //! max satellite sat number of BeiDou +#define NSATCMP (MAXPRNCMP-MINPRNCMP+1) //! number of BeiDou satellites +#define NSYSCMP 1 + +#define MINPRNIRN 1 //! min satellite sat number of IRNSS +#define MAXPRNIRN 7 //! max satellite sat number of IRNSS +#define NSATIRN (MAXPRNIRN-MINPRNIRN+1) //! number of IRNSS satellites +#define NSYSIRN 1 + +#define MINPRNLEO 1 //! min satellite sat number of LEO +#define MAXPRNLEO 10 //! max satellite sat number of LEO +#define NSATLEO (MAXPRNLEO-MINPRNLEO+1) //! number of LEO satellites +#define NSYSLEO 1 + +#define NSYS (NSYSGPS+NSYSGLO+NSYSGAL+NSYSQZS+NSYSCMP+NSYSIRN+NSYSLEO) //! number of systems + +#define MINPRNSBS 120 //! min satellite PRN number of SBAS +#define MAXPRNSBS 142 //! max satellite PRN number of SBAS +#define NSATSBS (MAXPRNSBS-MINPRNSBS+1) //! number of SBAS satellites +#define MAXSAT (NSATGPS+NSATGLO+NSATGAL+NSATQZS+NSATCMP+NSATIRN+NSATSBS+NSATLEO) + //! max satellite number (1 to MAXSAT) +#define MAXSTA 255 + +#define MAXOBS 128 //! max number of obs in an epoch +#define MAXRCV 64 //! max receiver number (1 to MAXRCV) +#define MAXOBSTYPE 64 //! max number of obs type in RINEX + +#define MAXEXFILE 1024 //! max number of expanded files + +#define MAXSBSURA 8 //! max URA of SBAS satellite +#define MAXBAND 10 //! max SBAS band of IGP +#define MAXNIGP 201 //! max number of IGP in SBAS band +#define MAXNGEO 4 //! max number of GEO satellites +#define MAXCOMMENT 10 //! max number of RINEX comments +#define MAXSTRPATH 1024 //! max length of stream path +#define MAXSTRMSG 1024 //! max length of stream message +#define MAXSTRRTK 8 //! max number of stream in RTK server +#define MAXSBSMSG 32 //! max number of SBAS msg in RTK server +#define MAXSOLMSG 8191 //! max length of solution message +#define MAXRAWLEN 4096 //! max length of receiver raw message +#define MAXERRMSG 4096 //! max length of error/warning message +#define MAXANT 64 //! max length of station name/antenna type +#define MAXSOLBUF 256 //! max number of solution buffer +#define MAXSOLNUM 86400 //! max number of solution in program +#define MAXOBSBUF 128 //! max number of observation data buffer +#define MAXNRPOS 16 //! max number of reference positions +#define MAXLEAPS 64 //! max number of leap seconds table +#define MAXGISLAYER 32 //! max number of GIS data layers +#define MAXRCVCMD 4096 //! max length of receiver commands + +#define OBSTYPE_PR 1 //!#01 //! observation type: pseudorange +#define OBSTYPE_CP 2 //!#02 //! observation type: carrier-phase +#define OBSTYPE_DOP 4 //!#04 //! observation type: doppler-freq +#define OBSTYPE_SNR 8 //!#08 //! observation type: SNR +#define OBSTYPE_ALL 255 //!#FF //! observation type: all + +#define FREQTYPE_L1 1 //!0x01 //! frequency type: L1/E1 +#define FREQTYPE_L2 2 //!0x02 //! frequency type: L2/B1 +#define FREQTYPE_L5 4 //!0x04 //! frequency type: L5/E5a/L3 +#define FREQTYPE_L6 8 //!0x08 //! frequency type: E6/LEX/B3 +#define FREQTYPE_L7 16 //!0x10 //! frequency type: E5b/B2 +#define FREQTYPE_L8 32 //!0x20 //! frequency type: E5(a+b) +#define FREQTYPE_L9 64 //!0x40 //! frequency type: S +#define FREQTYPE_ALL 255 //!0xFF //! frequency type: all + +#define CODE_NONE 0 //! obs code: none or unknown +#define CODE_L1C 1 //! obs code: L1C/A,G1C/A,E1C (GPS,GLO,GAL,QZS,SBS) +#define CODE_L1P 2 //! obs code: L1P,G1P (GPS,GLO) +#define CODE_L1W 3 //! obs code: L1 Z-track (GPS) +#define CODE_L1Y 4 //! obs code: L1Y (GPS) +#define CODE_L1M 5 //! obs code: L1M (GPS) +#define CODE_L1N 6 //! obs code: L1codeless (GPS) +#define CODE_L1S 7 //! obs code: L1C(D) (GPS,QZS) +#define CODE_L1L 8 //! obs code: L1C(P) (GPS,QZS) +#define CODE_L1E 9 //! (not used) +#define CODE_L1A 10 //! obs code: E1A (GAL) +#define CODE_L1B 11 //! obs code: E1B (GAL) +#define CODE_L1X 12 //! obs code: E1B+C,L1C(D+P) (GAL,QZS) +#define CODE_L1Z 13 //! obs code: E1A+B+C,L1SAIF (GAL,QZS) +#define CODE_L2C 14 //! obs code: L2C/A,G1C/A (GPS,GLO) +#define CODE_L2D 15 //! obs code: L2 L1C/A-(P2-P1) (GPS) +#define CODE_L2S 16 //! obs code: L2C(M) (GPS,QZS) +#define CODE_L2L 17 //! obs code: L2C(L) (GPS,QZS) +#define CODE_L2X 18 //! obs code: L2C(M+L),B1I+Q (GPS,QZS,CMP) +#define CODE_L2P 19 //! obs code: L2P,G2P (GPS,GLO) +#define CODE_L2W 20 //! obs code: L2 Z-track (GPS) +#define CODE_L2Y 21 //! obs code: L2Y (GPS) +#define CODE_L2M 22 //! obs code: L2M (GPS) +#define CODE_L2N 23 //! obs code: L2codeless (GPS) +#define CODE_L5I 24 //! obs code: L5/E5aI (GPS,GAL,QZS,SBS) +#define CODE_L5Q 25 //! obs code: L5/E5aQ (GPS,GAL,QZS,SBS) +#define CODE_L5X 26 //! obs code: L5/E5aI+Q/L5B+C (GPS,GAL,QZS,IRN,SBS) +#define CODE_L7I 27 //! obs code: E5bI,B2I (GAL,CMP) +#define CODE_L7Q 28 //! obs code: E5bQ,B2Q (GAL,CMP) +#define CODE_L7X 29 //! obs code: E5bI+Q,B2I+Q (GAL,CMP) +#define CODE_L6A 30 //! obs code: E6A (GAL) +#define CODE_L6B 31 //! obs code: E6B (GAL) +#define CODE_L6C 32 //! obs code: E6C (GAL) +#define CODE_L6X 33 //! obs code: E6B+C,LEXS+L,B3I+Q (GAL,QZS,CMP) +#define CODE_L6Z 34 //! obs code: E6A+B+C (GAL) +#define CODE_L6S 35 //! obs code: LEXS (QZS) +#define CODE_L6L 36 //! obs code: LEXL (QZS) +#define CODE_L8I 37 //! obs code: E5(a+b)I (GAL) +#define CODE_L8Q 38 //! obs code: E5(a+b)Q (GAL) +#define CODE_L8X 39 //! obs code: E5(a+b)I+Q (GAL) +#define CODE_L2I 40 //! obs code: B1I (BDS) +#define CODE_L2Q 41 //! obs code: B1Q (BDS) +#define CODE_L6I 42 //! obs code: B3I (BDS) +#define CODE_L6Q 43 //! obs code: B3Q (BDS) +#define CODE_L3I 44 //! obs code: G3I (GLO) +#define CODE_L3Q 45 //! obs code: G3Q (GLO) +#define CODE_L3X 46 //! obs code: G3I+Q (GLO) +#define CODE_L1I 47 //! obs code: B1I (BDS) +#define CODE_L1Q 48 //! obs code: B1Q (BDS) +#define CODE_L5A 49 //! obs code: L5A SPS (IRN) +#define CODE_L5B 50 //! obs code: L5B RS(D) (IRN) +#define CODE_L5C 51 //! obs code: L5C RS(P) (IRN) +#define CODE_L9A 52 //! obs code: SA SPS (IRN) +#define CODE_L9B 53 //! obs code: SB RS(D) (IRN) +#define CODE_L9C 54 //! obs code: SC RS(P) (IRN) +#define CODE_L9X 55 //! obs code: SB+C (IRN) +#define MAXCODE 55 //! max number of obs code + +#define PMODE_SINGLE 0 //! positioning mode: single +#define PMODE_DGPS 1 //! positioning mode: DGPS/DGNSS +#define PMODE_KINEMA 2 //! positioning mode: kinematic +#define PMODE_STATIC 3 //! positioning mode: static +#define PMODE_MOVEB 4 //! positioning mode: moving-base +#define PMODE_FIXED 5 //! positioning mode: fixed +#define PMODE_PPP_KINEMA 6 //! positioning mode: PPP-kinemaric +#define PMODE_PPP_STATIC 7 //! positioning mode: PPP-static +#define PMODE_PPP_FIXED 8 //! positioning mode: PPP-fixed + +#define SOLF_LLH 0 //! solution format: lat/lon/height +#define SOLF_XYZ 1 //! solution format: x/y/z-ecef +#define SOLF_ENU 2 //! solution format: e/n/u-baseline +#define SOLF_NMEA 3 //! solution format: NMEA-183 +#define SOLF_STAT 4 //! solution format: solution status +#define SOLF_GSIF 5 //! solution format: GSI F1/F2 + +#define SOLQ_NONE 0 //! solution status: no solution +#define SOLQ_FIX 1 //! solution status: fix +#define SOLQ_FLOAT 2 //! solution status: float +#define SOLQ_SBAS 3 //! solution status: SBAS +#define SOLQ_DGPS 4 //! solution status: DGPS/DGNSS +#define SOLQ_SINGLE 5 //! solution status: single +#define SOLQ_PPP 6 //! solution status: PPP +#define SOLQ_DR 7 //! solution status: dead reconing +#define MAXSOLQ 7 //! max number of solution status + +#define TIMES_GPST 0 //! time system: gps time +#define TIMES_UTC 1 //! time system: utc +#define TIMES_JST 2 //! time system: jst + +#define IONOOPT_OFF 0 //! ionosphere option: correction off +#define IONOOPT_BRDC 1 //! ionosphere option: broadcast model +#define IONOOPT_SBAS 2 //! ionosphere option: SBAS model +#define IONOOPT_IFLC 3 //! ionosphere option: L1/L2 or L1/L5 iono-free LC +#define IONOOPT_EST 4 //! ionosphere option: estimation +#define IONOOPT_TEC 5 //! ionosphere option: IONEX TEC model +#define IONOOPT_QZS 6 //! ionosphere option: QZSS broadcast model +#define IONOOPT_LEX 7 //! ionosphere option: QZSS LEX ionospehre +#define IONOOPT_STEC 8 //! ionosphere option: SLANT TEC model + +#define TROPOPT_OFF 0 //! troposphere option: correction off +#define TROPOPT_SAAS 1 //! troposphere option: Saastamoinen model +#define TROPOPT_SBAS 2 //! troposphere option: SBAS model +#define TROPOPT_EST 3 //! troposphere option: ZTD estimation +#define TROPOPT_ESTG 4 //! troposphere option: ZTD+grad estimation +#define TROPOPT_ZTD 5 //! troposphere option: ZTD correction + +#define EPHOPT_BRDC 0 //! ephemeris option: broadcast ephemeris +#define EPHOPT_PREC 1 //! ephemeris option: precise ephemeris +#define EPHOPT_SBAS 2 //! ephemeris option: broadcast + SBAS +#define EPHOPT_SSRAPC 3 //! ephemeris option: broadcast + SSR_APC +#define EPHOPT_SSRCOM 4 //! ephemeris option: broadcast + SSR_COM +#define EPHOPT_LEX 5 //! ephemeris option: QZSS LEX ephemeris + +#define ARMODE_OFF 0 //! AR mode: off +#define ARMODE_CONT 1 //! AR mode: continuous +#define ARMODE_INST 2 //! AR mode: instantaneous +#define ARMODE_FIXHOLD 3 //! AR mode: fix and hold +#define ARMODE_WLNL 4 //! AR mode: wide lane/narrow lane +#define ARMODE_TCAR 5 //! AR mode: triple carrier ar + +#define SBSOPT_LCORR 1 //! SBAS option: long term correction +#define SBSOPT_FCORR 2 //! SBAS option: fast correction +#define SBSOPT_ICORR 4 //! SBAS option: ionosphere correction +#define SBSOPT_RANGE 8 //! SBAS option: ranging + +#define POSOPT_POS 0 //! pos option: LLH/XYZ +#define POSOPT_SINGLE 1 //! pos option: average of single pos +#define POSOPT_FILE 2 //! pos option: read from pos file +#define POSOPT_RINEX 3 //! pos option: rinex header pos +#define POSOPT_RTCM 4 //! pos option: rtcm station pos +#define POSOPT_RAW 5 //! pos option: raw station pos + +#define STR_NONE 0 //! stream type: none +#define STR_SERIAL 1 //! stream type: serial +#define STR_FILE 2 //! stream type: file +#define STR_TCPSVR 3 //! stream type: TCP server +#define STR_TCPCLI 4 //! stream type: TCP client +#define STR_NTRIPSVR 6 //! stream type: NTRIP server +#define STR_NTRIPCLI 7 //! stream type: NTRIP client +#define STR_FTP 8 //! stream type: ftp +#define STR_HTTP 9 //! stream type: http +#define STR_NTRIPC_S 10 //! stream type: NTRIP caster server +#define STR_NTRIPC_C 11 //! stream type: NTRIP caster client +#define STR_UDPSVR 12 //! stream type: UDP server +#define STR_UDPCLI 13 //! stream type: UDP server +#define STR_MEMBUF 14 //! stream type: memory buffer + +#define STRFMT_RTCM2 0 //! stream format: RTCM 2 +#define STRFMT_RTCM3 1 //! stream format: RTCM 3 +#define STRFMT_OEM4 2 //! stream format: NovAtel OEMV/4 +#define STRFMT_OEM3 3 //! stream format: NovAtel OEM3 +#define STRFMT_UBX 4 //! stream format: u-blox LEA-*T +#define STRFMT_SS2 5 //! stream format: NovAtel Superstar II +#define STRFMT_CRES 6 //! stream format: Hemisphere +#define STRFMT_STQ 7 //! stream format: SkyTraq S1315F +#define STRFMT_GW10 8 //! stream format: Furuno GW10 +#define STRFMT_JAVAD 9 //! stream format: JAVAD GRIL/GREIS +#define STRFMT_NVS 10 //! stream format: NVS NVC08C +#define STRFMT_BINEX 11 //! stream format: BINEX +#define STRFMT_RT17 12 //! stream format: Trimble RT17 +#define STRFMT_SEPT 13 //! stream format: Septentrio +#define STRFMT_CMR 14 //! stream format: CMR/CMR+ +#define STRFMT_TERSUS 15 //! stream format: TERSUS +#define STRFMT_LEXR 16 //! stream format: Furuno LPY-10000 +#define STRFMT_RINEX 17 //! stream format: RINEX +#define STRFMT_SP3 18 //! stream format: SP3 +#define STRFMT_RNXCLK 19 //! stream format: RINEX CLK +#define STRFMT_SBAS 20 //! stream format: SBAS messages +#define STRFMT_NMEA 21 //! stream format: NMEA 0183 +#define MAXRCVFMT 15 //! max number of receiver format + +#define STR_MODE_R 1 //! stream mode: read +#define STR_MODE_W 2 //! stream mode: write +#define STR_MODE_RW 3 //! stream mode: read/write + +#define GEOID_EMBEDDED 0 //! geoid model: embedded geoid +#define GEOID_EGM96_M150 1 //! geoid model: EGM96 15x15" +#define GEOID_EGM2008_M25 2 //! geoid model: EGM2008 2.5x2.5" +#define GEOID_EGM2008_M10 3 //! geoid model: EGM2008 1.e0x1.e0" +#define GEOID_GSI2000_M15 4 //! geoid model: GSI geoid 2000 1.e0x1.5" +#define GEOID_RAF09 5 //! geoid model: IGN RAF09 for France 1.5"x2" + +#define DLOPT_FORCE 1 //! download option: force download existing +#define DLOPT_KEEPCMP 2 //! download option: keep compressed file +#define DLOPT_HOLDERR 4 //! download option: hold on error file +#define DLOPT_HOLDLST 8 //! download option: hold on listing file + +#define LLI_SLIP 1 //! LLI: cycle-slip +#define LLI_HALFC 2 //! LLI: half-cycle not resovled +#define LLI_BOCTRK 4 //! LLI: boc tracking of mboc signal +#define LLI_HALFA 64 //! LLI: half-cycle added +#define LLI_HALFS 128 //! LLI: half-cycle subtracted +#define IMUFMT_KVH 1 //! imu data format KVH + +#define FPOUT 10 //! solution files (except for 1/2/5/6) +#define FPREAD 11 //! obs/nav files +#define FPOPT 12 //! option files +#define FPADD 13 //! additional files +#define FPCLK 14 //! additional files (sat clock bias) +#define FPPOS 15 //! additional files (sat pos) + +#define MAX_ITER_KEPLER 30 //! max number of iteration of Kelpler + +#define NX (4+3) //! # of estimated parameters +#define MAXITR 10 //! max number of iteration for point pos + +//! rinex.f90 ----------------------------------------------------------------- +#define NUMSYS 7 //! number of systems +#define MAXRNXLEN (16*MAXOBSTYPE+4) //! max rinex record length +#define MAXPOSHEAD 1024 //! max head line position +#define MINFREQ_GLO -7 //! min frequency number glonass +#define MAXFREQ_GLO 13 //! max frequency number glonass +#define NINCOBS 262144/2 //! inclimental number of obs data + +//! postpos.f90 --------------------------------------------------------------- +#define MAXINFILE 1000 //! max number of input files + +//! rnx2rtkp.f90 -------------------------------------------------------------- +#define MAXFILE 16 //! max number of input files +#define FLNUMLIM 200 //! max number of rnxlist + +extern const double PI; //! pi +extern const double D2R; //! deg to rad +extern const double R2D; //! rad to deg +extern const double CLIGHT; //! speed of light (m/s) +extern const double SC2RAD; //! semi-circle to radian (IS-GPS) +extern const double AU; //! 1 AU (m) +extern const double AS2R; //! arc sec to radian + +extern const double OMGE; //! earth angular velocity (IS-GPS) (rad/s) +extern const double RE_WGS84; //! earth semimajor axis (WGS84) (m) +extern const double FE_WGS84; //! earth flattening (WGS84) + +extern const double HION; //! ionosphere height (m) + + +extern const double FREQL1; //! L1/E1 frequency (Hz) +extern const double FREQL2; //! L2 frequency (Hz) +extern const double FREQL5; //! L5/E5a frequency (Hz) +extern const double FREQL6; //! E6/LEX frequency (Hz) +extern const double FREQE5b; //! E5b frequency (Hz) +extern const double FREQE5ab; //! E5a+b frequency (Hz) +extern const double FREQs; //! S frequency (Hz) +extern const double FREQ1_GLO; //! GLONASS G1 base frequency (Hz) +extern const double DFRQ1_GLO; //! GLONASS G1 bias frequency (Hz/n) +extern const double FREQ2_GLO; //! GLONASS G2 base frequency (Hz) +extern const double DFRQ2_GLO; //! GLONASS G2 bias frequency (Hz/n) +extern const double FREQ1a_GLO; // GLONASS G1a frequency (Hz) +extern const double FREQ2a_GLO; // GLONASS G2a frequency (Hz) +extern const double FREQ3_GLO; //! GLONASS G3 frequency (Hz) +extern const double FREQ1_CMP; //! BeiDou B1 frequency (Hz) +extern const double FREQ2_CMP; //! BeiDou B2 frequency (Hz) +extern const double FREQ3_CMP; //! BeiDou B3 frequency (Hz) + +extern const double EFACT_GPS; //! error factor: GPS +extern const double EFACT_GLO; //! error factor: GLONASS +extern const double EFACT_GAL; //! error factor: Galileo +extern const double EFACT_QZS; //! error factor: QZSS +extern const double EFACT_CMP; //! error factor: BeiDou +extern const double EFACT_IRN; //! error factor: IRNSS +extern const double EFACT_SBS; //! error factor: SBAS + + + +extern const double DTTOL; //! tolerance of time difference (s) +extern const double MAXDTOE; //! max time difference to GPS Toe (s) +extern const double MAXDTOE_QZS; //! max time difference to QZSS Toe (s) +extern const double MAXDTOE_GAL; //! max time difference to Galileo Toe (s) +extern const double MAXDTOE_CMP; //! max time difference to BeiDou Toe (s) +extern const double MAXDTOE_GLO; //! max time difference to GLONASS Toe (s) +extern const double MAXDTOE_SBS; //! max time difference to SBAS Toe (s) +extern const double MAXDTOE_S; //! max time difference to ephem toe (s) for other +extern const double MAXGDOP; //! max GDOP + +extern const double INT_SWAP_TRAC; //! swap interval of trace file (s) +extern const double INT_SWAP_STAT; //! swap interval of solution status file (s) + + +extern const double MAXSBSAGEF; //! max age of SBAS fast correction (s) +extern const double MAXSBSAGEL; //! max age of SBAS long term corr (s) + + +extern const double RNX2VER; //! RINEX ver.2 default output version +extern const double RNX3VER; //! RINEX ver.3 default output version + + + +extern const char COMMENTH[2]; //! comment line indicator for solution +extern const char MSG_DISCONN[13]; //! disconnect message + + + +extern const double P2_5; //! 2^-5 +extern const double P2_6; //! 2^-6 +extern const double P2_11; //! 2^-11 +extern const double P2_15; //! 2^-15 +extern const double P2_17; //! 2^-17 +extern const double P2_19; //! 2^-19 +extern const double P2_20; //! 2^-20 +extern const double P2_21; //! 2^-21 +extern const double P2_23; //! 2^-23 +extern const double P2_24; //! 2^-24 +extern const double P2_27; //! 2^-27 +extern const double P2_29; //! 2^-29 +extern const double P2_30; //! 2^-30 +extern const double P2_31; //! 2^-31 +extern const double P2_32; //! 2^-32 +extern const double P2_33; //! 2^-33 +extern const double P2_35; //! 2^-35 +extern const double P2_38; //! 2^-38 +extern const double P2_39; //! 2^-39 +extern const double P2_40; //! 2^-40 +extern const double P2_43; //! 2^-43 +extern const double P2_48; //! 2^-48 +extern const double P2_50; //! 2^-50 +extern const double P2_55; //! 2^-55 + + + +//! rtkcmn.f90 ---------------------------------------------------------------- +extern const double MAX_VAR_EPH; //! max variance eph to reject satellite (m^2) +extern const double gpst0[6]; //! gps time reference +extern const double gst0[6]; //! galileo system time reference +extern const double bdt0[6]; //! beidou time reference + +extern const double lam_carr[MAXFREQ]; + +//! leap seconds (y,m,d,h,m,s,utc-gpst) +extern const double leaps[19][7]; + +//! observation code strings +extern const char obscodes[60][3]; + +//! 1:L1/E1, 2:L2/B1, 3:L5/E5a/L3, 4:L6/LEX/B3, 5:E5b/B2, 6:E5(a+b), 7:S +extern const int obsfreqs[60]; + +//! code priority table +//! L1/E1; L2/B1; L5/E5a/L3; L6/LEX/B3; E5b/B2; E5(a+b); S +extern const char codepris[7][MAXFREQ][17]; + +//! ephemeris.f90 ------------------------------------------------------------- +extern const double RE_GLO; //! radius of earth (m) ref (2) +extern const double MU_GPS; //! gravitational externant ref (1) +extern const double MU_GLO; //! gravitational externant ref (2) +extern const double MU_GAL; //! earth gravitational externant ref (7) +extern const double MU_CMP; //! earth gravitational externant ref (9) +extern const double J2_GLO; //! 2nd zonal harmonic of geopot ref (2) + +extern const double OMGE_GLO; //! earth angular velocity (rad/s) ref (2) +extern const double OMGE_GAL; //! earth angular velocity (rad/s) ref (7) +extern const double OMGE_CMP; //! earth angular velocity (rad/s) ref (9) +extern const double SIN_5; //! dsin(-5.e0 deg) +extern const double COS_5; //! dcos(-5.e0 deg) + +extern const double ERREPH_GLO; //! error of glonass ephemeris (m) +extern const double TSTEP; //! integration step glonass ephemeris (s) +extern const double RTOL_KEPLER; //! relative tolerance for Kepler equation + +extern const double DEFURASSR; //! default accurary of ssr corr (m) +extern const double MAXECORSSR; //! max orbit correction of ssr (m) +extern const double MAXCCORSSR; //! max clock correction of ssr (m) +extern const double MAXAGESSR; //! max age of ssr orbit and clock (s) +extern const double MAXAGESSR_HRCLK; //! max age of ssr high-rate clock (s) +extern const double STD_BRDCCLK; //! error of broadcast clock (m) +extern const double STD_GAL_NAPA; //! error of galileo ephemeris for NAPA (m) + +extern const int eph_sel[6]; //! GPS,GLO,GAL,QZS,BDS,SBS (ephemeris selections) + +//! pntpos.f90 ---------------------------------------------------------------- +extern const double ERR_ION; //! ionospheric delay std (m) +extern const double ERR_TROP; //! tropspheric delay std (m) +extern const double ERR_SAAS; //! saastamoinen model error std (m) +extern const double ERR_BRDCI; //! broadcast iono model error factor +extern const double ERR_CBIAS; //! code bias error std (m) +extern const double REL_HUMI; //! relative humidity for saastamoinen model + + +extern const char systyps[8]; //! satellite system codes +extern const char obstyps[5]; //! obs type codes +extern const char frqtyps[8]; //! frequency codes +extern const double ura_eph[16]; //! ura values (ref [3] 20.3.3.3.1.1) + +extern const double ura_nominal[16]; //! ura nominal values + + + +#endif \ No newline at end of file diff --git a/src/decodenav.c b/src/decodenav.c new file mode 100644 index 0000000..e7b7cb6 --- /dev/null +++ b/src/decodenav.c @@ -0,0 +1,455 @@ +#include +#include "decodenav.h" +#include "str.h" +#include "timeconvert.h" + +/* URA value (m) to URA index ------------------------------------------------*/ +static int uraindex(double value) +{ + int i; + for (i = 0; i < 15; i++){ + if (ura_eph[i] >= value) break; + } + return i; +} + +/* Galileo SISA value (m) to SISA index --------------------------------------*/ +static int sisa_index(double value) +{ + /* + * kudos to https://core.ac.uk/download/pdf/328854682.pdf for this ... + * Signal-in-Space Accuracy : SISA flag is a prediction at 1-sigma standard deviation of the quality of + * the transmitted signal.The flag can take values from 0 to 255. The transmitted standard index is 107 that + * corresponds to a SISA value of 3.12m.If the prediction is not available, the transmitted index is 255 and + * corresponds to No Accurate Prediction Available(NAPA).NAPA is an indicator of a potential anomalous + * signal-in-space[6].Please notice that SISA flag refers to the dual-frequency signal combinations. + */ + if (value < 0.0 || value > 6.0) + return 255; /* unknown or NAPA */ + else if (value <= 0.5) + return (int)(value / 0.01); + else if (value <= 1.0) + return (int)((value - 0.5) / 0.02) + 50; + else if (value <= 2.0) + return (int)((value - 1.0) / 0.04) + 75; + return (int)((value - 2.0) / 0.16) + 100; +} + +void decode_navh(char *buff, nav_t *nav) +{ + int i,j; + char* label = buff + 60; + if (strstr(label, "ION ALPHA")) + { /* opt ver.2 */ + if (nav) + { + for (i = 0, j = 2; i < 4; i++, j += 12) + { + nav->ion_gps[i] = str2num(buff, j, 12); + } + } + } + else if (strstr(label, "ION BETA")) + { /* opt ver.2 */ + if (nav) + { + for (i = 0, j = 2; i < 4; i++, j += 12) + { + nav->ion_gps[i + 4] = str2num(buff, j, 12); + } + } + } + else if (strstr(label, "DELTA-UTC: A0,A1,T,W")) + { /* opt ver.2 */ + if (nav) + { + for (i = 0, j = 3; i < 2; i++, j += 19) + { + nav->utc_gps[i] = str2num(buff, j, 19); + } + for (; i < 4; i++, j += 9) + { + nav->utc_gps[i] = str2num(buff, j, 9); + } + } + } + else if (strstr(label, "IONOSPHERIC CORR")) + { /* opt ver.3 */ + if (nav) + { + if (!strncmp(buff, "GPSA", 4)) + { + for (i = 0, j = 5; i < 4; i++, j += 12) + { + nav->ion_gps[i] = str2num(buff, j, 12); + } + } + else if (!strncmp(buff, "GPSB", 4)) + { + for (i = 0, j = 5; i < 4; i++, j += 12) + { + nav->ion_gps[i + 4] = str2num(buff, j, 12); + } + } + else if (!strncmp(buff, "GAL", 3)) + { + for (i = 0, j = 5; i < 4; i++, j += 12) + { + nav->ion_gal[i] = str2num(buff, j, 12); + } + } + else if (!strncmp(buff, "QZSA", 4)) + { /* v.3.02 */ + for (i = 0, j = 5; i < 4; i++, j += 12) + { + nav->ion_qzs[i] = str2num(buff, j, 12); + } + } + else if (!strncmp(buff, "QZSB", 4)) + { /* v.3.02 */ + for (i = 0, j = 5; i < 4; i++, j += 12) + { + nav->ion_qzs[i + 4] = str2num(buff, j, 12); + } + } + else if (!strncmp(buff, "BDSA", 4)) + { /* v.3.02 */ + for (i = 0, j = 5; i < 4; i++, j += 12) + { + nav->ion_cmp[i] = str2num(buff, j, 12); + } + } + else if (!strncmp(buff, "BDSB", 4)) + { /* v.3.02 */ + for (i = 0, j = 5; i < 4; i++, j += 12) + { + nav->ion_cmp[i + 4] = str2num(buff, j, 12); + } + } + else if (!strncmp(buff, "IRNA", 4)) + { /* v.3.03 */ + for (i = 0, j = 5; i < 4; i++, j += 12) + { + nav->ion_irn[i] = str2num(buff, j, 12); + } + } + else if (!strncmp(buff, "IRNB", 4)) + { /* v.3.03 */ + for (i = 0, j = 5; i < 4; i++, j += 12) + { + nav->ion_irn[i + 4] = str2num(buff, j, 12); + } + } + } + } + else if (strstr(label, "TIME SYSTEM CORR")) + { /* opt ver.3 */ + if (nav) + { + if (!strncmp(buff, "GPUT", 4)) + { + nav->utc_gps[0] = str2num(buff, 5, 17); + nav->utc_gps[1] = str2num(buff, 22, 16); + nav->utc_gps[2] = str2num(buff, 38, 7); + nav->utc_gps[3] = str2num(buff, 45, 5); + } + else if (!strncmp(buff, "GLUT", 4)) + { + nav->utc_glo[0] = -str2num(buff, 5, 17); /* tau_C */ + } + else if (!strncmp(buff, "GLGP", 4)) + { + nav->utc_glo[1] = str2num(buff, 5, 17); /* tau_GPS */ + } + else if (!strncmp(buff, "GAUT", 4)) + { /* v.3.02 */ + nav->utc_gal[0] = str2num(buff, 5, 17); + nav->utc_gal[1] = str2num(buff, 22, 16); + nav->utc_gal[2] = str2num(buff, 38, 7); + nav->utc_gal[3] = str2num(buff, 45, 5); + } + else if (!strncmp(buff, "QZUT", 4)) + { /* v.3.02 */ + nav->utc_qzs[0] = str2num(buff, 5, 17); + nav->utc_qzs[1] = str2num(buff, 22, 16); + nav->utc_qzs[2] = str2num(buff, 38, 7); + nav->utc_qzs[3] = str2num(buff, 45, 5); + } + else if (!strncmp(buff, "BDUT", 4)) + { /* v.3.02 */ + nav->utc_cmp[0] = str2num(buff, 5, 17); + nav->utc_cmp[1] = str2num(buff, 22, 16); + nav->utc_cmp[2] = str2num(buff, 38, 7); + nav->utc_cmp[3] = str2num(buff, 45, 5); + } + else if (!strncmp(buff, "SBUT", 4)) + { /* v.3.02 */ + nav->utc_sbs[0] = str2num(buff, 5, 17); + nav->utc_sbs[1] = str2num(buff, 22, 16); + nav->utc_sbs[2] = str2num(buff, 38, 7); + nav->utc_sbs[3] = str2num(buff, 45, 5); + } + else if (!strncmp(buff, "IRUT", 4)) + { /* v.3.03 */ + nav->utc_irn[0] = str2num(buff, 5, 17); + nav->utc_irn[1] = str2num(buff, 22, 16); + nav->utc_irn[2] = str2num(buff, 38, 7); + nav->utc_irn[3] = str2num(buff, 45, 5); + } + } + } + else if (strstr(label, "LEAP SECONDS")) + { /* opt */ + if (nav) + { + nav->leaps = (int)str2num(buff, 0, 6); + } + } + return; +} + +void decode_gnavh(char *buff, nav_t *nav) +{ + char *label = buff + 60; + + if (strstr(label, "CORR TO SYSTEM TIME")); + else if (strstr(label, "LEAP SECONDS")) + { + if (nav) + { + nav->leaps = (int)str2num(buff, 0, 6); + } + } +} + +int decode_geph(double ver, int sat, gtime_t toc, double *data, geph_t *geph) +{ + geph_t geph0 = {0}; + gtime_t tof; + double tow, tod; + int week, dow; + + printf("decode_geph: ver=%.2f sat=%2d\n", ver, sat); + + if (satsys(sat, NULL) != SYS_GLO) + { + printf("glonass ephemeris error: invalid satellite sat=%2d\n", sat); + return 0; + } + *geph = geph0; + + geph->sat = sat; + + /* Toc rounded by 15 min in utc */ + tow = time2gpst(toc, &week); + toc = gpst2time(week, floor((tow + 450.0) / 900.0) * 900); + dow = (int)floor(tow / 86400.0); + + /* time of frame in UTC */ + tod = ver <= 2.99 ? data[2] : fmod(data[2], 86400.0); /* Tod (v.2), Tow (v.3) in UTC */ + tof = gpst2time(week, tod + dow * 86400.0); + tof = adjday(tof, toc); + + geph->toe = utc2gpst(toc); /* Toc (GPST) */ + geph->tof = utc2gpst(tof); /* Tof (GPST) */ + + /* IODE = Tb (7bit), Tb =index of UTC+3H within current day */ + geph->iode = (int)(fmod(tow + 10800.0, 86400.0) / 900.0 + 0.5); + + geph->taun = -data[0]; /* -taun */ + geph->gamn = data[1]; /* +gamman */ + + geph->pos[0] = data[3] * 1E3; + geph->pos[1] = data[7] * 1E3; + geph->pos[2] = data[11] * 1E3; + geph->vel[0] = data[4] * 1E3; + geph->vel[1] = data[8] * 1E3; + geph->vel[2] = data[12] * 1E3; + geph->acc[0] = data[5] * 1E3; + geph->acc[1] = data[9] * 1E3; + geph->acc[2] = data[13] * 1E3; + + geph->svh = (int)data[6]; + geph->frq = (int)data[10]; + + geph->age = (int)data[14]; + + /* some receiver output >128 for minus frequency number */ + if (geph->frq > 128) + geph->frq -= 256; + + if (geph->frq < MINFREQ_GLO || MAXFREQ_GLO < geph->frq) + { + printf("rinex gnav invalid freq: sat=%2d fn=%d\n", sat, geph->frq); + } + return 1; +} + +int decode_seph(double ver, int sat, gtime_t toc, double *data,seph_t *seph) +{ + seph_t seph0 = {0}; + int week; + + printf("decode_seph: ver=%.2f sat=%2d\n", ver, sat); + + if (satsys(sat, NULL) != SYS_SBS) + { + printf("geo ephemeris error: invalid satellite sat=%2d\n", sat); + return 0; + } + *seph = seph0; + + seph->sat = sat; + seph->t0 = toc; + + time2gpst(toc, &week); + seph->tof = adjweek(gpst2time(week, data[2]), toc); + + seph->af0 = data[0]; + seph->af1 = data[1]; + + seph->pos[0] = data[3] * 1E3; + seph->pos[1] = data[7] * 1E3; + seph->pos[2] = data[11] * 1E3; + seph->vel[0] = data[4] * 1E3; + seph->vel[1] = data[8] * 1E3; + seph->vel[2] = data[12] * 1E3; + seph->acc[0] = data[5] * 1E3; + seph->acc[1] = data[9] * 1E3; + seph->acc[2] = data[13] * 1E3; + + seph->svh = (int)data[6]; + seph->sva = uraindex(data[10]); + + return 1; +} + +int decode_eph(double ver, int sat, gtime_t toc, const double *data, + eph_t *eph) +{ + eph_t eph0 = {0}; + int sys; + + printf("decode_eph: ver=%.2f sat=%2d\n", ver, sat); + + sys = satsys(sat, NULL); + + if (!(sys & (SYS_GPS | SYS_GAL | SYS_QZS | SYS_CMP | SYS_IRN))) + { + printf("ephemeris error: invalid satellite sat=%2d\n", sat); + return 0; + } + *eph = eph0; + + eph->sat = sat; + eph->toc = toc; + + eph->f0 = data[0]; + eph->f1 = data[1]; + eph->f2 = data[2]; + + eph->A = data[10]*data[10]; + eph->e = data[8]; + eph->i0 = data[15]; + eph->OMG0 = data[13]; + eph->omg = data[17]; + eph->M0 = data[6]; + eph->deln = data[5]; + eph->OMGd = data[18]; + eph->idot = data[19]; + eph->crc = data[16]; + eph->crs = data[4]; + eph->cuc = data[7]; + eph->cus = data[9]; + eph->cic = data[12]; + eph->cis = data[14]; + + if (sys == SYS_GPS || sys == SYS_QZS) + { + eph->iode = (int)data[3]; /* IODE */ + eph->iodc = (int)data[26]; /* IODC */ + eph->toes = data[11]; /* Toe (s) in GPS week */ + eph->week = (int)data[21]; /* GPS week */ + eph->toe = adjweek(gpst2time(eph->week, data[11]), toc); + eph->ttr = adjweek(gpst2time(eph->week, data[27]), toc); + + eph->code = (int)data[20]; /* GPS: codes on L2 ch */ + eph->svh = (int)data[24]; /* SV health */ + eph->sva = uraindex(data[23]); /* URA index (m->index) */ + eph->flag = (int)data[22]; /* GPS: L2 P data flag */ + + eph->tgd[0] = data[25]; /* TGD */ + if (sys == SYS_GPS) + { + eph->fit = data[28]; /* fit interval (h) */ + } + else + { + eph->fit = data[28] == 0.0 ? 1.0 : 2.0; /* fit interval (0:1h,1:>2h) */ + } + } + else if (sys == SYS_GAL) + { /* GAL ver.3 */ + eph->iode = (int)data[3]; /* IODnav */ + eph->toes = data[11]; /* Toe (s) in Galileo week */ + eph->week = (int)data[21]; /* Galileo week = GPS week */ + eph->toe = adjweek(gpst2time(eph->week, data[11]), toc); + eph->ttr = adjweek(gpst2time(eph->week, data[27]), toc); + + eph->code = (int)data[20]; /* data sources */ + /* bit 0 set: I/NAV E1-B */ + /* bit 1 set: F/NAV E5a-I */ + /* bit 2 set: F/NAV E5b-I */ + /* bit 8 set: af0-af2 toc are for E5a.E1 */ + /* bit 9 set: af0-af2 toc are for E5b.E1 */ + eph->svh = (int)data[24]; /* sv health */ + /* bit 0: E1B DVS */ + /* bit 1-2: E1B HS */ + /* bit 3: E5a DVS */ + /* bit 4-5: E5a HS */ + /* bit 6: E5b DVS */ + /* bit 7-8: E5b HS */ + eph->sva = sisa_index(data[23]); /* sisa (m->index) */ + + eph->tgd[0] = data[25]; /* BGD E5a/E1 */ + eph->tgd[1] = data[26]; /* BGD E5b/E1 */ + } + else if (sys == SYS_CMP) + { /* BeiDou v.3.02 */ + eph->toc = bdt2gpst(eph->toc); /* bdt -> gpst */ + eph->iode = (int)data[3]; /* AODE */ + eph->iodc = (int)data[28]; /* AODC */ + eph->toes = data[11]; /* Toe (s) in BDT week */ + eph->week = (int)data[21]; /* bdt week */ + eph->toe = bdt2gpst(bdt2time(eph->week, data[11])); /* BDT -> GPST */ + eph->ttr = bdt2gpst(bdt2time(eph->week, data[27])); /* BDT -> GPST */ + eph->toe = adjweek(eph->toe, toc); + eph->ttr = adjweek(eph->ttr, toc); + + eph->svh = (int)data[24]; /* satH1 */ + eph->sva = uraindex(data[23]); /* URA index (m->index) */ + + eph->tgd[0] = data[25]; /* TGD1 B1/B3 */ + eph->tgd[1] = data[26]; /* TGD2 B2/B3 */ + } + else if (sys == SYS_IRN) + { /* IRNSS v.3.03 */ + eph->iode = (int)data[3]; /* IODEC */ + eph->toes = data[11]; /* Toe (s) in IRNSS week */ + eph->week = (int)data[21]; /* IRNSS week */ + eph->toe = adjweek(gpst2time(eph->week, data[11]), toc); + eph->ttr = adjweek(gpst2time(eph->week, data[27]), toc); + eph->svh = (int)data[24]; /* SV health */ + eph->sva = uraindex(data[23]); /* URA index (m->index) */ + eph->tgd[0] = data[25]; /* TGD */ + } + if (eph->iode < 0 || 1023 < eph->iode) + { + printf("rinex nav invalid: sat=%2d iode=%d\n", sat, eph->iode); + } + if (eph->iodc < 0 || 1023 < eph->iodc) + { + printf("rinex nav invalid: sat=%2d iodc=%d\n", sat, eph->iodc); + } + return 1; +} \ No newline at end of file diff --git a/src/decodenav.h b/src/decodenav.h new file mode 100644 index 0000000..09fef92 --- /dev/null +++ b/src/decodenav.h @@ -0,0 +1,20 @@ +#ifndef DECODENAV_H +#define DECODENAV_H + +#include "comtyp.h" + +/* decode RINEX NAV header ---------------------------------------------------*/ +void decode_navh(char *buff, nav_t *nav); + +/* decode GNAV header --------------------------------------------------------*/ +void decode_gnavh(char *buff, nav_t *nav); + +/* decode GLONASS ephemeris --------------------------------------------------*/ +int decode_geph(double ver, int sat, gtime_t toc, double *data,geph_t *geph); + +/* decode GEO ephemeris ------------------------------------------------------*/ +int decode_seph(double ver, int sat, gtime_t toc, double *data,seph_t *seph); + +/* decode ephemeris ----------------------------------------------------------*/ +int decode_eph(double ver, int sat, gtime_t toc, const double *data,eph_t *eph); +#endif \ No newline at end of file diff --git a/src/decodeobs.c b/src/decodeobs.c new file mode 100644 index 0000000..c5ff96e --- /dev/null +++ b/src/decodeobs.c @@ -0,0 +1,490 @@ +#include "decodeobs.h" +#include "str.h" +#include "obscode.h" + +decode_obsh(FILE *fp, char *buff, double ver, int *tsys, + char tobs[][MAXOBSTYPE][4],obs_t* obs, nav_t *nav, sta_t *sta) +{ + // default codes for unknown code + char defcodes[7][8]={ + "CWX ", // GPS: L125____ + "CC ", // GLO: L12_____ + "X XXXX ", // GAL: L1_5678_ + "CXXX ", // QZS: L1256___ + "C X ", // SBS: L1_5____ + "XIXIIX ", // BDS: L125678_ + " A A"}; // IRN: L__5___9 + double del[3]; + int i,j,k,n,nt,prn,fcn; + char* p; + char* label = buff + 60; + char str[4]; + if (strstr(label, "MARKER NUMBER")) + { + if(sta) setstr(sta->name, buff, 60); + } + else if (strstr(label, "MARKER NUMBER")) + { + if(sta) setstr(sta->marker, buff, 20); + } + else if (strstr(label, "MARKER TYPE")); + else if (strstr(label, "OBSERVER / AGENCY")); + else if (strstr(label, "REC # / TYPE / VERS")) + { + if(sta) + { + setstr(sta->recsno, buff, 20); + setstr(sta->rectype, buff + 20, 20); + setstr(sta->recver, buff + 40, 20); + } + } + else if (strstr(label, "ANT # / TYPE")) + { + if (sta) + { + setstr(sta->antsno, buff, 20); + setstr(sta->antdes, buff + 20, 20); + } + } + else if (strstr(label, "APPROX POSITION XYZ")) + { + if (sta) + { + for (i = 0, j = 0; i < 3; i++, j += 14) + { + sta->pos[i] = str2num(buff, j, 14); + } + + } + } + else if (strstr(label, "ANTENNA: DELTA H/E/N")) + { + if (sta) + { + for (i = 0, j = 0; i < 3; i++, j += 14) + { + del[i] = str2num(buff, j, 14); + } + sta->del[2] = del[0]; /* h */ + sta->del[0] = del[1]; /* e */ + sta->del[1] = del[2]; /* n */ + } + } + else if(strstr(label,"ANTENNA: DELTA X/Y/Z")); // opt ver.3 + else if(strstr(label,"ANTENNA: PHASECENTER")); // opt ver.3 + else if(strstr(label,"ANTENNA: B.SIGHT XYZ")); // opt ver.3 + else if(strstr(label,"ANTENNA: ZERODIR AZI")); // opt ver.3 + else if(strstr(label,"ANTENNA: ZERODIR XYZ")); // opt ver.3 + else if(strstr(label,"CENTER OF MASS: XYZ" )); // opt ver.3 + else if(strstr(label,"SYS / # / OBS TYPES" )) // ver.3 + { + if (!(p = strchr(systyps, buff[0]))) + { + printf("invalid system code: sys=%c\n", buff[0]); + return; + } + i = (int)(p - systyps); + n = (int)str2num(buff, 3, 3); + for (j = nt = 0, k = 7; j < n; j++, k += 4) + { + if (k > 58) + { + if (!fgets(buff, MAXRNXLEN, fp)) + break; + k = 7; + } + if (nt < MAXOBSTYPE - 1) + setstr(tobs[i][nt++], buff + k, 3); + } + *tobs[i][nt] = '\0'; + + /* change BDS B1 code: 3.02 */ + if (i == 5 && fabs(ver - 3.02) < 1e-3) + { + for (j = 0; j < nt; j++) + if (tobs[i][j][1] == '1') + tobs[i][j][1] = '2'; + } + + for (j=0;j 58) + { + if (!fgets(buff, MAXRNXLEN, fp)) + break; + j = 10; + } + if (nt >= MAXOBSTYPE - 1) + continue; + if (ver <= 2.99) + { + setstr(str, buff + j, 2); + convcode(ver, SYS_GPS, str, tobs[0][nt]); + convcode(ver, SYS_GLO, str, tobs[1][nt]); + convcode(ver, SYS_GAL, str, tobs[2][nt]); + convcode(ver, SYS_QZS, str, tobs[3][nt]); + convcode(ver, SYS_SBS, str, tobs[4][nt]); + convcode(ver, SYS_CMP, str, tobs[5][nt]); + } + nt++; + } + *tobs[0][nt] = '\0'; + } + else if (strstr(label, "SIGNAL STRENGTH UNIT")); /* opt ver.3 */ + else if (strstr(label, "INTERVAL")) + { + obs->tint = str2num(buff,0,11); + } + else if (strstr(label, "TIME OF FIRST OBS")) + { + if (!strncmp(buff + 48, "GPS", 3)) + *tsys = TSYS_GPS; + else if (!strncmp(buff + 48, "GLO", 3)) + *tsys = TSYS_UTC; + else if (!strncmp(buff + 48, "GAL", 3)) + *tsys = TSYS_GAL; + else if (!strncmp(buff + 48, "QZS", 3)) + *tsys = TSYS_QZS; /* ver.3.02 */ + else if (!strncmp(buff + 48, "BDT", 3)) + *tsys = TSYS_CMP; /* ver.3.02 */ + else if (!strncmp(buff + 48, "IRN", 3)) + *tsys = TSYS_IRN; /* ver.3.03 */ + } + else if (strstr(label, "TIME OF LAST OBS")); + else if (strstr(label, "RCV CLOCK OFFS APPL")); + else if (strstr(label, "SYS / DCBS APPLIED")); + else if (strstr(label, "SYS / PCVS APPLIED")); + else if (strstr(label, "SYS / SCALE FACTOR")); + else if (strstr(label, "SYS / PHASE SHIFTS")); /* ver.3.01 */ + else if (strstr(label, "GLONASS SLOT / FRQ #")) + { /* ver.3.02 */ + for (i = 0; i < 8; i++) + { + if (buff[4 + i * 7] != 'R') + continue; + prn = (int)str2num(buff, 5 + i * 7, 2); + fcn = (int)str2num(buff, 8 + i * 7, 2); + if (prn < 1 || prn > MAXPRNGLO || fcn < -7 || fcn > 6) + continue; + if (nav) + nav->glo_fcn[prn - 1] = fcn + 8; + } + } + else if (strstr(label, "GLONASS COD/PHS/BIS")) + { /* ver.3.02 */ + if (nav) + { + nav->glo_cpbias[0] = str2num(buff, 5, 8); + nav->glo_cpbias[1] = str2num(buff, 18, 8); + nav->glo_cpbias[2] = str2num(buff, 31, 8); + nav->glo_cpbias[3] = str2num(buff, 44, 8); + } + } + else if (strstr(label, "LEAP SECONDS")) + { /* opt */ + if (nav) + { + /*nav->utc_gps[4] = str2num(buff, 0, 6); + nav->utc_gps[7] = str2num(buff, 6, 6); + nav->utc_gps[5] = str2num(buff, 12, 6); + nav->utc_gps[6] = str2num(buff, 18, 6);*/ + nav->leaps = (int)str2num(buff,0,6); + } + } + else if (strstr(label, "# OF SATELLITES")); + else if (strstr(label, "PRN / # OF OBS")); + return; +} + +int decode_obsepoch(FILE *fp, char *buff, double ver, gtime_t *time, + int *flag, int *sats) +{ + int i, j, n; + char satid[8] = {'\0'}; + + printf("decode_obsepoch: ver=%.2f\n", ver); + + if (ver <= 2.99) + { /* ver.2 */ + /* epoch flag: 3:new site,4:header info,5:external event */ + *flag = (int)str2num(buff, 28, 1); + + /* handle external event */ + if (*flag == 5) + { + str2time(buff, 0, 26, time); + } + + if ((n = (int)str2num(buff, 29, 3)) <= 0) + return 0; + + if (3 <= *flag && *flag <= 5) + return n; + + if (str2time(buff, 0, 26, time)) + { + printf("rinex obs invalid epoch: epoch=%26.26s\n", buff); + return 0; + } + for (i = 0, j = 32; i < n; i++, j += 3) + { + if (j >= 68) + { + if (!fgets(buff, MAXRNXLEN, fp)) + break; + j = 32; + } + if (i < MAXOBS) + { + strncpy(satid, buff + j, 3); + sats[i] = satid2no(satid); + } + } + } + else + { /* ver.3 */ + *flag = (int)str2num(buff, 31, 1); + + /* handle external event */ + if (*flag == 5) + { + str2time(buff, 1, 28, time); + } + + if ((n = (int)str2num(buff, 32, 3)) <= 0) + return 0; + + if (3 <= *flag && *flag <= 5) + return n; + + if (buff[0] != '>' || str2time(buff, 1, 28, time)) + { + printf("rinex obs invalid epoch: epoch=%29.29s\n", buff); + return 0; + } + } + char time_str[64]; + time2str(*time, time_str, 3); + + printf("decode_obsepoch: time=%s flag=%d\n", time_str, *flag); + return n; +} + +int decode_obsdata(FILE *fp, char *buff, double ver, int mask, + sigind_t *index, obsd_t *obs) +{ + sigind_t *ind; + double val[MAXOBSTYPE] = {0}; + unsigned char lli[MAXOBSTYPE] = {0}; + unsigned char std[MAXOBSTYPE] = {0}; + char satid[8] = ""; + int i, j, n, m, q, status = 1, p[MAXOBSTYPE], k[16], l[16], r[16]; + + if (ver > 2.99) + { /* ver.3 */ + sprintf(satid, "%.3s", buff); + obs->sat = (unsigned char)satid2no(satid); + } + if (!obs->sat) + { + printf("decode_obsdata: unsupported sat sat=%s\n", satid); + status = 0; + } + else if (!(satsys(obs->sat, NULL) & mask)) + { + status = 0; + } + /* read observation data fields */ + switch (satsys(obs->sat, NULL)) + { + case SYS_GLO: + ind = index + 1; + break; + case SYS_GAL: + ind = index + 2; + break; + case SYS_QZS: + ind = index + 3; + break; + case SYS_SBS: + ind = index + 4; + break; + case SYS_CMP: + ind = index + 5; + break; + case SYS_IRN: + ind = index + 6; + break; + default: + ind = index; + break; + } + for (i = 0, j = ver <= 2.99 ? 0 : 3; i < ind->n; i++, j += 16) + { + + if (ver <= 2.99 && j >= 80) + { /* ver.2 */ + if (!fgets(buff, MAXRNXLEN, fp)) + break; + j = 0; + } + if (status) + { + val[i] = str2num(buff, j, 14) + ind->shift[i]; + lli[i] = (unsigned char)str2num(buff, j + 14, 1) & 3; + /* measurement std from receiver */ + std[i] = (unsigned char)str2num(buff, j + 15, 1); + } + } + if (!status) + return 0; + + for (i = 0; i < NFREQ + NEXOBS; i++) + { + obs->P[i] = obs->L[i] = 0.0; + obs->D[i] = 0.0f; + obs->SNR[i] = obs->LLI[i] = obs->qualL[i] = obs->qualP[i] = obs->code[i] = 0; + } + /* assign position in observation data */ + for (i = n = m = q = 0; i < ind->n; i++) + { + + p[i] = ind->frqIdx[i]; + + if (ind->type[i] == 0 && p[i] == 0) + k[n++] = i; /* C1? index */ + if (ind->type[i] == 0 && p[i] == 1) + l[m++] = i; /* C2? index */ + if (ind->type[i] == 0 && p[i] == 2) + r[q++] = i; /* C3? index */ + } + + /* if multiple codes (C1/P1,C2/P2), select higher priority */ + if (n >= 2) + { + if (val[k[0]] == 0.0 && val[k[1]] == 0.0) + { + p[k[0]] = -1; + p[k[1]] = -1; + } + else if (val[k[0]] != 0.0 && val[k[1]] == 0.0) + { + p[k[0]] = 0; + p[k[1]] = -1; + } + else if (val[k[0]] == 0.0 && val[k[1]] != 0.0) + { + p[k[0]] = -1; + p[k[1]] = 0; + } + else if (ind->pri[k[1]] > ind->pri[k[0]]) + { + p[k[1]] = 0; + p[k[0]] = NEXOBS < 1 ? -1 : NFREQ; + } + else + { + p[k[0]] = 0; + p[k[1]] = NEXOBS < 1 ? -1 : NFREQ; + } + } + if (m >= 2) + { + if (val[l[0]] == 0.0 && val[l[1]] == 0.0) + { + p[l[0]] = -1; + p[l[1]] = -1; + } + else if (val[l[0]] != 0.0 && val[l[1]] == 0.0) + { + p[l[0]] = 1; + p[l[1]] = -1; + } + else if (val[l[0]] == 0.0 && val[l[1]] != 0.0) + { + p[l[0]] = -1; + p[l[1]] = 1; + } + else if (ind->pri[l[1]] > ind->pri[l[0]]) + { + p[l[1]] = 1; + p[l[0]] = NEXOBS < 2 ? -1 : NFREQ + 1; + } + else + { + p[l[0]] = 1; + p[l[1]] = NEXOBS < 2 ? -1 : NFREQ + 1; + } + } + if (q >= 2) + { + if (val[r[0]] == 0.0 && val[r[1]] == 0.0) + { + p[r[0]] = -1; + p[r[1]] = -1; + } + else if (val[r[0]] != 0.0 && val[r[1]] == 0.0) + { + p[r[0]] = 2; + p[r[1]] = -1; + } + else if (val[r[0]] == 0.0 && val[r[1]] != 0.0) + { + p[r[0]] = -1; + p[r[1]] = 2; + } + else if (ind->pri[r[1]] > ind->pri[r[0]]) + { + p[r[1]] = 2; + p[r[0]] = NEXOBS < 3 ? -1 : NFREQ + 2; + } + else + { + p[r[0]] = 2; + p[r[1]] = NEXOBS < 3 ? -1 : NFREQ + 2; + } + } + /* save observation data */ + for (i = 0; i < ind->n; i++) + { + if (p[i] < 0 || (val[i] == 0.0 && lli[i] == 0)) + continue; + switch (ind->type[i]) + { + case 0: + obs->P[p[i]] = val[i]; + obs->code[p[i]] = ind->code[i]; + obs->qualP[p[i]] = std[i] > 0 ? std[i] : 1; + break; + case 1: + obs->L[p[i]] = val[i]; + obs->LLI[p[i]] = lli[i]; + obs->qualL[p[i]] = std[i] > 0 ? std[i] : 1; + break; + case 2: + obs->D[p[i]] = (float)val[i]; + break; + case 3: + obs->SNR[p[i]] = (unsigned char)(val[i] / SNR_UNIT + 0.5); + break; + } + printf("obs: i=%d f=%d P=%10.3f L=%10.3f LLI=%d code=%d\n", i, p[i], obs->P[p[i]], + obs->L[p[i]], obs->LLI[p[i]], obs->code[p[i]]); + } + char time_str[64]; + time2str(obs->time, time_str, 0); + printf("decode_obsdata: time=%s sat=%2d\n", time_str, obs->sat); + return 1; +} \ No newline at end of file diff --git a/src/decodeobs.h b/src/decodeobs.h new file mode 100644 index 0000000..a294077 --- /dev/null +++ b/src/decodeobs.h @@ -0,0 +1,18 @@ +#ifndef DECODEOBS_H +#define DECODEOBS_H +#include "comtyp.h" +#include + +/* decode RINEX observation data file header ---------------------------------*/ +void decode_obsh(FILE *fp, char *buff, double ver, int *tsys, + char tobs[][MAXOBSTYPE][4],obs_t* obs, nav_t *nav, sta_t *sta); + +/* decode observation epoch --------------------------------------------------*/ +int decode_obsepoch(FILE *fp, char *buff, double ver, gtime_t *time, + int *flag, int *sats); + +/* decode observation data ---------------------------------------------------*/ +int decode_obsdata(FILE *fp, char *buff, double ver, int mask, + sigind_t *index, obsd_t *obs); + +#endif \ No newline at end of file diff --git a/src/init_val.c b/src/init_val.c new file mode 100644 index 0000000..1eceb22 --- /dev/null +++ b/src/init_val.c @@ -0,0 +1,14 @@ +#include "init_val.h" +void init_sta(sta_t *sta) +{ + memset(sta,0,sizeof(sta_t)); + /*int i; + for (i = 0; i < 3; i++){ + sta->pos[i] = 0.0; + } + for (i = 0; i < 3; i++){ + sta->del[i] = 0.0; + } + sta->hgt = 0.0;*/ + return; +} \ No newline at end of file diff --git a/src/init_val.h b/src/init_val.h new file mode 100644 index 0000000..e471aee --- /dev/null +++ b/src/init_val.h @@ -0,0 +1,7 @@ +#ifndef INIT_VAL_H +#define INIT_VAL_H +#include "comtyp.h" + +void init_sta(sta_t *sta); + +#endif \ No newline at end of file diff --git a/src/main.c b/src/main.c new file mode 100644 index 0000000..2c94567 --- /dev/null +++ b/src/main.c @@ -0,0 +1,29 @@ +#include +#include +#include "readobsnav.h" +#include "comtyp.h" +#include "option.h" +#include "init_val.h" + +int main() +{ + gtime_t ts = {0},te = {0}; + double ti = 0; + char* infile[256]; + char file0[] = "/home/ununtu/Downloads/PRIDE-PPPAR/data/TWTF00TWN_R_20233310000_01D_30S_MO/TWTF00TWN_R_20233310000_01D_30S_MO.rnx"; + char file1[] = "/home/ununtu/Downloads/PRIDE-PPPAR/data/TWTF00TWN_R_20233310000_01D_30S_MO/brdm3310.23p"; + infile[0] = &file0; + infile[1] = &file1; + int index=0; + int n = 2; + prcopt_t prcopt; + obs_t obs = {0}; + nav_t nav = {0}; + sta_t sta = {0}; + + readobsnav(ts, te, ti,infile,&index,n,&prcopt,&obs,&nav,&sta); + + freeobsnav(&obs,&nav); + + return 0; +} \ No newline at end of file diff --git a/src/obscode.c b/src/obscode.c new file mode 100644 index 0000000..fa8ad9f --- /dev/null +++ b/src/obscode.c @@ -0,0 +1,151 @@ +#include "obscode.h" +#include "const.h" + +void convcode(double ver, int sys, const char *str, char *type) +{ + strcpy(type, " "); + + if (!strcmp(str, "P1")) + { /* ver.2.11 GPS L1PY,GLO L2P */ + if (sys == SYS_GPS) + sprintf(type, "%c1W", 'C'); + else if (sys == SYS_GLO) + sprintf(type, "%c1P", 'C'); + } + else if (!strcmp(str, "P2")) + { /* ver.2.11 GPS L2PY,GLO L2P */ + if (sys == SYS_GPS) + sprintf(type, "%c2W", 'C'); + else if (sys == SYS_GLO) + sprintf(type, "%c2P", 'C'); + } + else if (!strcmp(str, "C1")) + { /* ver.2.11 GPS L1C,GLO L1C/A */ + if (ver >= 2.12) + ; /* reject C1 for 2.12 */ + else if (sys == SYS_GPS) + sprintf(type, "%c1C", 'C'); + else if (sys == SYS_GLO) + sprintf(type, "%c1C", 'C'); + else if (sys == SYS_GAL) + sprintf(type, "%c1X", 'C'); /* ver.2.12 */ + else if (sys == SYS_QZS) + sprintf(type, "%c1C", 'C'); + else if (sys == SYS_SBS) + sprintf(type, "%c1C", 'C'); + } + else if (!strcmp(str, "C2")) + { + if (sys == SYS_GPS) + { + if (ver >= 2.12) + sprintf(type, "%c2W", 'C'); /* L2P(Y) */ + else + sprintf(type, "%c2X", 'C'); /* L2C */ + } + else if (sys == SYS_GLO) + sprintf(type, "%c2C", 'C'); + else if (sys == SYS_QZS) + sprintf(type, "%c2X", 'C'); + else if (sys == SYS_CMP) + sprintf(type, "%c2X", 'C'); /* ver.2.12 B1_2 */ + } + else if (ver >= 2.12 && str[1] == 'A') + { /* ver.2.12 L1C/A */ + if (sys == SYS_GPS) + sprintf(type, "%c1C", str[0]); + else if (sys == SYS_GLO) + sprintf(type, "%c1C", str[0]); + else if (sys == SYS_QZS) + sprintf(type, "%c1C", str[0]); + else if (sys == SYS_SBS) + sprintf(type, "%c1C", str[0]); + } + else if (ver >= 2.12 && str[1] == 'B') + { /* ver.2.12 GPS L1C */ + if (sys == SYS_GPS) + sprintf(type, "%c1X", str[0]); + else if (sys == SYS_QZS) + sprintf(type, "%c1X", str[0]); + } + else if (ver >= 2.12 && str[1] == 'C') + { /* ver.2.12 GPS L2C */ + if (sys == SYS_GPS) + sprintf(type, "%c2X", str[0]); + else if (sys == SYS_QZS) + sprintf(type, "%c2X", str[0]); + } + else if (ver >= 2.12 && str[1] == 'D') + { /* ver.2.12 GLO L2C/A */ + if (sys == SYS_GLO) + sprintf(type, "%c2C", str[0]); + } + else if (ver >= 2.12 && str[1] == '1') + { /* ver.2.12 GPS L1PY,GLO L1P */ + if (sys == SYS_GPS) + sprintf(type, "%c1W", str[0]); + else if (sys == SYS_GLO) + sprintf(type, "%c1P", str[0]); + else if (sys == SYS_GAL) + sprintf(type, "%c1X", str[0]); /* tentative */ + else if (sys == SYS_CMP) + sprintf(type, "%c2X", str[0]); /* extension */ + } + else if (ver < 2.12 && str[1] == '1') + { + if (sys == SYS_GPS) + sprintf(type, "%c1C", str[0]); + else if (sys == SYS_GLO) + sprintf(type, "%c1C", str[0]); + else if (sys == SYS_GAL) + sprintf(type, "%c1X", str[0]); /* tentative */ + else if (sys == SYS_QZS) + sprintf(type, "%c1C", str[0]); + else if (sys == SYS_SBS) + sprintf(type, "%c1C", str[0]); + } + else if (str[1] == '2') + { + if (sys == SYS_GPS) + sprintf(type, "%c2W", str[0]); + else if (sys == SYS_GLO) + sprintf(type, "%c2P", str[0]); + else if (sys == SYS_QZS) + sprintf(type, "%c2X", str[0]); + else if (sys == SYS_CMP) + sprintf(type, "%c2X", str[0]); /* ver.2.12 B1_2 */ + } + else if (str[1] == '5') + { + if (sys == SYS_GPS) + sprintf(type, "%c5X", str[0]); + else if (sys == SYS_GAL) + sprintf(type, "%c5X", str[0]); + else if (sys == SYS_QZS) + sprintf(type, "%c5X", str[0]); + else if (sys == SYS_SBS) + sprintf(type, "%c5X", str[0]); + } + else if (str[1] == '6') + { + if (sys == SYS_GAL) + sprintf(type, "%c6X", str[0]); + else if (sys == SYS_QZS) + sprintf(type, "%c6X", str[0]); + else if (sys == SYS_CMP) + sprintf(type, "%c6X", str[0]); /* ver.2.12 B3 */ + } + else if (str[1] == '7') + { + if (sys == SYS_GAL) + sprintf(type, "%c7X", str[0]); + else if (sys == SYS_CMP) + sprintf(type, "%c7X", str[0]); /* ver.2.12 B2b */ + } + else if (str[1] == '8') + { + if (sys == SYS_GAL) + sprintf(type, "%c8X", str[0]); + } + printf("convcode: ver=%.2f sys=%2d type= %s -> %s\n", ver, sys, str, type); +} \ No newline at end of file diff --git a/src/obscode.h b/src/obscode.h new file mode 100644 index 0000000..ad9333d --- /dev/null +++ b/src/obscode.h @@ -0,0 +1,7 @@ +#ifndef OBSCODE_H +#define OBSCODE_H + +/* convert RINEX obs-type ver.2 -> ver.3 -------------------------------------*/ +void convcode(double ver, int sys, const char *str, char *type); + +#endif \ No newline at end of file diff --git a/src/option.h b/src/option.h new file mode 100644 index 0000000..e6bab13 --- /dev/null +++ b/src/option.h @@ -0,0 +1,78 @@ +#ifndef OPTION_H +#define OPTION_H +#include "const.h" +#include "comtyp.h" +#include + +typedef struct +{ + int mode; // positioning mode (PMODE_???) + int soltype; // solution type (0:forward,1:backward,2:combined) + int nf; // number of frequencies (1:L1,2:L1+L2,3:L1+L2+L5) + int navsys; // navigation system + double elmin; // elevation mask angle (rad) + int sateph; // satellite ephemeris/clock (EPHOPT_???) + int ionoopt; // ionosphere option (IONOOPT_???) + int tropopt; // troposphere option (TROPOPT_???) + int niter; // number of filter iteration + double maxinno; // reject threshold of innovation (m) + double maxgdop; // reject threshold of gdop + int exsats[MAXSAT]; // excluded satellites (1:excluded,2:included) + char rnxopt[2][256]; // rinex options {rover,base} + int posopt[6]; // positioning options + bool lsa; // SA data (before 2000/123) +}prcopt_t; + +typedef struct +{ + int posf; // solution format (SOLF_???) + int times; // time system (TIMES_???) + int timef; // time format (0:sssss.s,1:yyyy/mm/dd hh:mm:ss.s) + int timeu; // time digits under decimal point + int degf; // latitude/longitude format (0:ddd.ddd,1:ddd mm ss) + int outhead; // output header (0:no,1:yes) + int outopt; // output processing options (0:no,1:yes) + int outvel; // output velocity options (0:no,1:yes) + int datum; // datum (0:WGS84,1:Tokyo) + int height; // height (0:ellipsoidal,1:geodetic) + int geoid; // geoid model (0:EGM96,1:JGD2000) + int solstatic; // solution of static mode (0:all,1:single) + int sstat; // solution statistics level (0:off,1:states,2:residuals) + int trace; // debug trace level (0:off,1-5:debug) + int issingle; // single solution (0:no,1:yes) + double nmeaintv[2]; // nmea output interval (s) ( .lt. 0:no,0:all) + // nmeaintv(0):gprmc,gpgga,nmeaintv(1):gpgsv + char sep[64]; // field separator + char prog[64]; // program name + double maxsolstd; // max std-dev for solution output (m) (0:all) +}solopt_t; + +typedef struct +{ + gtime_t ts,te; // time start/end + double tint; // time interval (s) + double ttol; // time tolerance (s) + double tunit; // time unit for multiple-session (s) + double rnxver; // RINEX version + int navsys; // navigation system + int obstype; // observation type + int freqtype; // frequency type + char mask[7][64]; // code mask {GPS,GLO,GAL,QZS,SBS,CMP,IRN} + char staid[32]; // station id for rinex file name + char prog[32]; // program + char runby[32]; // run-by + char marker[32]; // marker name + char markerno[32]; // marker number + char markertype[32]; // marker type (ver.3) + char name[2][32]; // observer/agency + char rec[3][32]; // receiver #/type/vers + char ant[3][32]; // antenna #/type + int exsats[MAXSAT]; // excluded satellites + gtime_t tstart; // first obs time + gtime_t tend; // last obs time + char tobs[7][MAXOBSTYPE][4]; // obs types {GPS,GLO,GAL,QZS,SBS,CMP,IRN} + int nobs[7]; // number of obs types {GPS,GLO,GAL,QZS,SBS,CMP,IRN} +}rnxopt_t; + + +#endif \ No newline at end of file diff --git a/src/readobsnav.c b/src/readobsnav.c new file mode 100644 index 0000000..4b999da --- /dev/null +++ b/src/readobsnav.c @@ -0,0 +1,1079 @@ +#include +#include +#include +#include +#include "readobsnav.h" +#include "init_val.h" +#include "decodeobs.h" +#include "decodenav.h" +#include "str.h" +#include "timeconvert.h" + +/* add ephemeris to navigation data ------------------------------------------*/ +static int add_eph(nav_t *nav, const eph_t *eph) +{ + eph_t *nav_eph; + + if (nav->nmax <= nav->n) + { + nav->nmax += 1024; + if (!(nav_eph = (eph_t *)realloc(nav->eph, sizeof(eph_t) * nav->nmax))) + { + printf("decode_eph malloc error: n=%d\n", nav->nmax); + free(nav->eph); + nav->eph = NULL; + nav->n = nav->nmax = 0; + return 0; + } + nav->eph = nav_eph; + } + nav->eph[nav->n++] = *eph; + return 1; +} + +/* compare observation data -------------------------------------------------*/ +static int cmpobs(const void *p1, const void *p2) +{ + obsd_t *q1 = (obsd_t *)p1, *q2 = (obsd_t *)p2; + double tt = timediff(q1->time, q2->time); + if (fabs(tt) > DTTOL) + return tt < 0 ? -1 : 1; + if (q1->rcv != q2->rcv) + return (int)q1->rcv - (int)q2->rcv; + return (int)q1->sat - (int)q2->sat; +} + +/* sort and unique observation data -------------------------------------------- + * sort and unique observation data by time, rcv, sat + * args : obs_t *obs IO observation data + * return : number of epochs + *-----------------------------------------------------------------------------*/ +int sortobs(obs_t *obs) +{ + int i, j, n; + + printf("sortobs: nobs=%d\n", obs->n); + + if (obs->n <= 0) + return 0; + + qsort(obs->data, obs->n, sizeof(obsd_t), cmpobs); + + /* delete duplicated data */ + for (i = j = 0; i < obs->n; i++) + { + if (obs->data[i].sat != obs->data[j].sat || + obs->data[i].rcv != obs->data[j].rcv || + timediff(obs->data[i].time, obs->data[j].time) != 0.0) + { + obs->data[++j] = obs->data[i]; + } + } + obs->n = j + 1; + + for (i = n = 0; i < obs->n; i = j, n++) + { + for (j = i + 1; j < obs->n; j++) + { + if (timediff(obs->data[j].time, obs->data[i].time) > DTTOL) + break; + } + } + return n; +} + +/* compare ephemeris ---------------------------------------------------------*/ +static int cmpeph(const void *p1, const void *p2) +{ + eph_t *q1 = (eph_t *)p1, *q2 = (eph_t *)p2; + return q1->ttr.time != q2->ttr.time ? (int)(q1->ttr.time - q2->ttr.time) : (q1->toe.time != q2->toe.time ? (int)(q1->toe.time - q2->toe.time) : q1->sat - q2->sat); +} +/* sort and unique ephemeris -------------------------------------------------*/ +static void uniqeph(nav_t *nav) +{ + eph_t *nav_eph; + int i, j; + + printf("uniqeph: n=%d\n", nav->n); + + if (nav->n <= 0) + return; + + qsort(nav->eph, nav->n, sizeof(eph_t), cmpeph); + + for (i = 1, j = 0; i < nav->n; i++) + { + if (nav->eph[i].sat != nav->eph[j].sat || + nav->eph[i].iode != nav->eph[j].iode) + { + nav->eph[++j] = nav->eph[i]; + } + } + nav->n = j + 1; + + if (!(nav_eph = (eph_t *)realloc(nav->eph, sizeof(eph_t) * nav->n))) + { + printf("uniqeph malloc error n=%d\n", nav->n); + free(nav->eph); + nav->eph = NULL; + nav->n = nav->nmax = 0; + return; + } + nav->eph = nav_eph; + nav->nmax = nav->n; + + printf("uniqeph: n=%d\n", nav->n); +} +/* compare glonass ephemeris -------------------------------------------------*/ +static int cmpgeph(const void *p1, const void *p2) +{ + geph_t *q1 = (geph_t *)p1, *q2 = (geph_t *)p2; + return q1->tof.time != q2->tof.time ? (int)(q1->tof.time - q2->tof.time) : (q1->toe.time != q2->toe.time ? (int)(q1->toe.time - q2->toe.time) : q1->sat - q2->sat); +} +/* sort and unique glonass ephemeris -----------------------------------------*/ +static void uniqgeph(nav_t *nav) +{ + geph_t *nav_geph; + int i, j; + + printf("uniqgeph: ng=%d\n", nav->ng); + + if (nav->ng <= 0) + return; + + qsort(nav->geph, nav->ng, sizeof(geph_t), cmpgeph); + + for (i = j = 0; i < nav->ng; i++) + { + if (nav->geph[i].sat != nav->geph[j].sat || + nav->geph[i].toe.time != nav->geph[j].toe.time || + nav->geph[i].svh != nav->geph[j].svh) + { + nav->geph[++j] = nav->geph[i]; + } + } + nav->ng = j + 1; + + if (!(nav_geph = (geph_t *)realloc(nav->geph, sizeof(geph_t) * nav->ng))) + { + printf("uniqgeph malloc error ng=%d\n", nav->ng); + free(nav->geph); + nav->geph = NULL; + nav->ng = nav->ngmax = 0; + return; + } + nav->geph = nav_geph; + nav->ngmax = nav->ng; + + printf("uniqgeph: ng=%d\n", nav->ng); +} +/* compare sbas ephemeris ----------------------------------------------------*/ +static int cmpseph(const void *p1, const void *p2) +{ + seph_t *q1 = (seph_t *)p1, *q2 = (seph_t *)p2; + return q1->tof.time != q2->tof.time ? (int)(q1->tof.time - q2->tof.time) : (q1->t0.time != q2->t0.time ? (int)(q1->t0.time - q2->t0.time) : q1->sat - q2->sat); +} +/* sort and unique sbas ephemeris --------------------------------------------*/ +static void uniqseph(nav_t *nav) +{ + seph_t *nav_seph; + int i, j; + + printf("uniqseph: ns=%d\n", nav->ns); + + if (nav->ns <= 0) + return; + + qsort(nav->seph, nav->ns, sizeof(seph_t), cmpseph); + + for (i = j = 0; i < nav->ns; i++) + { + if (nav->seph[i].sat != nav->seph[j].sat || + nav->seph[i].t0.time != nav->seph[j].t0.time) + { + nav->seph[++j] = nav->seph[i]; + } + } + nav->ns = j + 1; + + if (!(nav_seph = (seph_t *)realloc(nav->seph, sizeof(seph_t) * nav->ns))) + { + printf("uniqseph malloc error ns=%d\n", nav->ns); + free(nav->seph); + nav->seph = NULL; + nav->ns = nav->nsmax = 0; + return; + } + nav->seph = nav_seph; + nav->nsmax = nav->ns; + + printf("uniqseph: ns=%d\n", nav->ns); +} + +/* unique ephemerides ---------------------------------------------------------- + * unique ephemerides in navigation data and update carrier wave length + * args : nav_t *nav IO navigation data + * return : number of epochs + *-----------------------------------------------------------------------------*/ +void uniqnav(nav_t *nav) +{ + printf("uniqnav: neph=%d ngeph=%d nseph=%d\n", nav->n, nav->ng, nav->ns); + + /* unique ephemeris */ + uniqeph(nav); + uniqgeph(nav); + uniqseph(nav); +} + +static int add_geph(nav_t *nav, const geph_t *geph) +{ + geph_t *nav_geph; + + if (nav->ngmax <= nav->ng) + { + nav->ngmax += 1024; + if (!(nav_geph = (geph_t *)realloc(nav->geph, sizeof(geph_t) * nav->ngmax))) + { + printf("decode_geph malloc error: n=%d\n", nav->ngmax); + free(nav->geph); + nav->geph = NULL; + nav->ng = nav->ngmax = 0; + return 0; + } + nav->geph = nav_geph; + } + nav->geph[nav->ng++] = *geph; + return 1; +} +static int add_seph(nav_t *nav, const seph_t *seph) +{ + seph_t *nav_seph; + + if (nav->nsmax <= nav->ns) + { + nav->nsmax += 1024; + if (!(nav_seph = (seph_t *)realloc(nav->seph, sizeof(seph_t) * nav->nsmax))) + { + printf("decode_seph malloc error: n=%d\n", nav->nsmax); + free(nav->seph); + nav->seph = NULL; + nav->ns = nav->nsmax = 0; + return 0; + } + nav->seph = nav_seph; + } + nav->seph[nav->ns++] = *seph; + return 1; +} + +/* set system mask -----------------------------------------------------------*/ +static int set_sysmask(const char *opt) +{ + const char *p; + int mask = SYS_NONE; + + if (!(p = strstr(opt, "-SYS="))) + return SYS_ALL; + + for (p += 5; *p && *p != ' '; p++) + { + switch (*p) + { + case 'G': + mask |= SYS_GPS; + break; + case 'R': + mask |= SYS_GLO; + break; + case 'E': + mask |= SYS_GAL; + break; + case 'J': + mask |= SYS_QZS; + break; + case 'C': + mask |= SYS_CMP; + break; + case 'I': + mask |= SYS_IRN; + break; + case 'S': + mask |= SYS_SBS; + break; + } + } + return mask; +} + +/* obs type string to obs code ------------------------------------------------- +* convert obs code type string to obs code +* args : char *str I obs code string ("1C","1P","1Y",...) +* return : obs code (CODE_???) +* notes : obs codes are based on RINEX 3.04 +*-----------------------------------------------------------------------------*/ +unsigned char obs2code(const char *obs) +{ + unsigned char i; + + for (i=1;*obscodes[i];i++) { + if (strcmp(obscodes[i],obs)) continue; + return i; + } + return CODE_NONE; +} +char *code2obs(const char code) +{ + if (code<=CODE_NONE||MAXCODE6) return -1; + + switch (obs[0]) { + case '1': *freq=FREQ1_GLO+DFRQ1_GLO*fcn; return 0; /* G1 */ + case '2': *freq=FREQ2_GLO+DFRQ2_GLO*fcn; return 1; /* G2 */ + case '3': *freq=FREQ3_GLO; return 2; /* G3 */ + case '4': *freq=FREQ1a_GLO; return 0; /* G1a */ + case '6': *freq=FREQ2a_GLO; return 1; /* G2a */ + } + return -1; +} +/* Galileo obs code to frequency ---------------------------------------------*/ +static int code2freq_GAL(unsigned char code, double *freq) +{ + char *obs=code2obs(code); + + switch (obs[0]) { + case '1': *freq=FREQL1; return 0; /* E1 */ + case '7': *freq=FREQE5b; return 1; /* E5b */ + case '5': *freq=FREQL5; return 2; /* E5a */ + case '6': *freq=FREQL6; return 3; /* E6 */ + case '8': *freq=FREQE5ab; return 4; /* E5ab */ + } + return -1; +} +/* QZSS obs code to frequency ------------------------------------------------*/ +static int code2freq_QZS(unsigned char code, double *freq) +{ + char *obs=code2obs(code); + + switch (obs[0]) { + case '1': *freq=FREQL1; return 0; /* L1 */ + case '2': *freq=FREQL2; return 1; /* L2 */ + case '5': *freq=FREQL5; return 2; /* L5 */ + case '6': *freq=FREQL6; return 3; /* L6 */ + } + return -1; +} +/* SBAS obs code to frequency ------------------------------------------------*/ +static int code2freq_SBS(unsigned char code, double *freq) +{ + char *obs=code2obs(code); + + switch (obs[0]) { + case '1': *freq=FREQL1; return 0; /* L1 */ + case '5': *freq=FREQL5; return 1; /* L5 */ + } + return -1; +} +/* BDS obs code to frequency -------------------------------------------------*/ +static int code2freq_BDS(unsigned char code, double *freq) +{ + char *obs=code2obs(code); + + switch (obs[0]) { + case '1': *freq=FREQL1; return 0; /* B1C */ + case '2': *freq=FREQ1_CMP; return 0; /* B1I */ + case '7': *freq=FREQ2_CMP; return 1; /* B2b */ + case '5': *freq=FREQL5; return 2; /* B2a */ + case '6': *freq=FREQ3_CMP; return 3; /* B3 */ + case '8': *freq=FREQE5ab; return 4; /* B2ab */ + } + return -1; +} +/* NavIC obs code to frequency -----------------------------------------------*/ +static int code2freq_IRN(unsigned char code, double *freq) +{ + char *obs=code2obs(code); + + switch (obs[0]) { + case '5': *freq=FREQL5; return 0; /* L5 */ + case '9': *freq=FREQs; return 1; /* S */ + } + return -1; +} +/* system and obs code to frequency index -------------------------------------- +* convert system and obs code to frequency index +* args : int sys I satellite system (SYS_???) +* unsigned char code I obs code (CODE_???) +* return : frequency index (-1: error) +* 0 1 2 3 4 +* -------------------------------------- +* GPS L1 L2 L5 - - +* GLONASS G1 G2 G3 - - (G1=G1,G1a,G2=G2,G2a) +* Galileo E1 E5b E5a E6 E5ab +* QZSS L1 L2 L5 L6 - +* SBAS L1 - L5 - - +* BDS B1 B2b B2a B3 B2ab +* NavIC L5 S - - - +*-----------------------------------------------------------------------------*/ +int code2idx(int sys, unsigned char code) +{ + double freq; + + switch (sys) { + case SYS_GPS: return code2freq_GPS(code,&freq); + case SYS_GLO: return code2freq_GLO(code,0,&freq); + case SYS_GAL: return code2freq_GAL(code,&freq); + case SYS_QZS: return code2freq_QZS(code,&freq); + case SYS_SBS: return code2freq_SBS(code,&freq); + case SYS_CMP: return code2freq_BDS(code,&freq); + case SYS_IRN: return code2freq_IRN(code,&freq); + } + return -1; +} +/* get code priority ----------------------------------------------------------- +* get code priority for multiple codes in a frequency +* args : int sys I system (SYS_???) +* uint8_t code I obs code (CODE_???) +* char *opt I code options (NULL:no option) +* return : priority (15:highest-1:lowest,0:error) +*-----------------------------------------------------------------------------*/ +int getcodepri(int sys, unsigned char code, const char *opt) +{ + const char *p,*optstr; + char *obs,str[8]=""; + int i,j; + + switch (sys) { + case SYS_GPS: i=0; optstr="-GL%2s"; break; + case SYS_GLO: i=1; optstr="-RL%2s"; break; + case SYS_GAL: i=2; optstr="-EL%2s"; break; + case SYS_QZS: i=3; optstr="-JL%2s"; break; + case SYS_SBS: i=4; optstr="-SL%2s"; break; + case SYS_CMP: i=5; optstr="-CL%2s"; break; + case SYS_IRN: i=6; optstr="-IL%2s"; break; + default: return 0; + } + if ((j=code2idx(sys,code))<0) return 0; + obs=code2obs(code); + + /* parse code options */ + for (p=opt;p&&(p=strchr(p,'-'));p++) { + if (sscanf(p,optstr,str)<1||str[0]!=obs[0]) continue; + return str[1]==obs[1]?15:0; + } + /* search code priority */ + return (p=strchr(codepris[i][j],obs[1]))?14-(int)(p-codepris[i][j]):0; +} +/* set signal index ----------------------------------------------------------*/ +static void set_index(double ver, int sys, const char *opt, + char tobs[MAXOBSTYPE][4], sigind_t *ind) +{ + const char *p; + char str[8],*optstr=""; + double shift; + int i,j,k,n; + + for (i=n=0;*tobs[i];i++,n++) { + ind->code[i]=obs2code(tobs[i]+1); + ind->type[i]=(p=strchr(obstyps,tobs[i][0]))?(int)(p-obstyps):0; + ind->frqIdx[i]=code2idx(sys,ind->code[i]); + ind->pri[i]=getcodepri(sys,ind->code[i],opt); + ind->pos[i]=-1; + } + /* parse phase shift options */ + switch (sys) { + case SYS_GPS: optstr="-GL%2s=%lf"; break; + case SYS_GLO: optstr="-RL%2s=%lf"; break; + case SYS_GAL: optstr="-EL%2s=%lf"; break; + case SYS_QZS: optstr="-JL%2s=%lf"; break; + case SYS_SBS: optstr="-SL%2s=%lf"; break; + case SYS_CMP: optstr="-CL%2s=%lf"; break; + case SYS_IRN: optstr="-IL%2s=%lf"; break; + } + for (p=opt;p&&(p=strchr(p,'-'));p++) { + if (sscanf(p,optstr,str,&shift)<2) continue; + for (i=0;icode[i]),str)) continue; + ind->shift[i]=shift; + printf("phase shift: sys=%2d tobs=%s shift=%.3f\n",sys, + tobs[i],shift); + } + } + /* assign index for highest priority code */ + for (i=0;ifrqIdx[j]==i&&ind->pri[j]&&(k<0||ind->pri[j]>ind->pri[k])) { + k=j; + } + } + if (k<0) continue; + + for (j=0;jcode[j]==ind->code[k]) ind->pos[j]=i; + } + } + /* assign index of extended observation data */ + for (i=0;icode[j]&&ind->pri[j]&&ind->pos[j]<0) break; + } + if (j>=n) break; + + for (k=0;kcode[k]==ind->code[j]) ind->pos[k]=NFREQ+i; + } + } + /* list rejected observation types */ + for (i=0;icode[i]||!ind->pri[i]||ind->pos[i]>=0) continue; + printf("reject obs type: sys=%2d, obs=%s\n",sys,tobs[i]); + } + ind->n=n; + +} + +bool readobsnav(gtime_t ts, gtime_t te, double ti,const char** infile,const int* index,int n, + const prcopt_t* prcopt,obs_t* obs,nav_t* nav,sta_t* sta) +{ + int i,j,ind=0,nobs=0,rcv=0,info; + sta_t statmp; + obs->data = NULL,obs->n = 0,obs->nmax = 0; + nav->eph = NULL , nav->n = 0, nav->nmax = 0; + nav->geph = NULL, nav->ng = 0, nav->ngmax = 0; + for(i=0;in > nobs) rcv=rcv+1; + ind=index[i]; + nobs=obs->n; + } + // read rinex obs and nav file + if(rcv<=2){ + info = readrnxt(infile[i],rcv,ts,te,ti,prcopt->rnxopt[rcv<=1?1:2],obs,nav,&sta[rcv]); + if(info<=0){ + printf("File reading error : %s\n",infile[i]); + } + }else{ + info = readrnxt(infile[i],rcv,ts,te,ti,prcopt->rnxopt[rcv<=1?1:2],obs,nav,&statmp); + if(info<=0){ + printf("File reading error : %s\n",infile[i]); + } + } + if (info<0){ + return false; + } + } + if(obs->n<=0) + { + printf("Error : no observation data!\n"); + return false; + } + if(nav->n <= 0 && nav->ng <= 0 && nav->ns <= 0) + { + printf("Error : no navigation data!\n"); + return false; + } + + sortobs(obs); + uniqnav(nav); + return true; +} + +int readrnxt(const char *filepath,int rcv,gtime_t ts,gtime_t te,double ti,const char *opt, + obs_t* obs,nav_t* nav,sta_t* sta) +{ + int status = 0; + char type = ' '; + status = readrnxfile(filepath,ts,te,ti,opt,0,rcv,&type,obs,nav,sta); // -1,0: error, 1-normal + + return status; +} + +int readrnxfile(const char *filepath,gtime_t ts,gtime_t te,double ti,const char* opt, + int flag,int index,char* type,obs_t* obs,nav_t* nav,sta_t* sta) +{ + int status, info; + init_sta(sta); + FILE *fp; + if(!(fp = fopen(filepath, "r"))){ + printf("File opening error : %s\n",filepath); + status = -1; + return status; + } + status = readrnxfp(fp,ts,te,ti,opt,flag,index,type,obs,nav,sta); + close(fp); + return status; +} + +int readrnxfp(FILE* fp,gtime_t ts,gtime_t te,double ti,const char* opt, + int flag,int index,char* type,obs_t* obs,nav_t* nav,sta_t* sta) +{ + double ver; + int sys,tsys,status; + char tobs[NUMSYS][MAXOBSTYPE][4] = {{""}}; + status = readrnxh(fp,&ver,type,&sys,&tsys,tobs,obs,nav,sta); + if(status == 0) + { + printf("Error reading rinex header\n"); + return status; + } + switch (*type) + { + case 'O': + status = readrnxobs(fp,ts,te,ti,opt,index,ver,&tsys,tobs,obs,sta); + break; + case 'N': + status = readrnxnav(fp, opt, ver, sys, nav); + break; + case 'G': + status = readrnxnav(fp, opt, ver, SYS_GLO, nav); + break; + case 'H': + status = readrnxnav(fp, opt, ver, SYS_SBS, nav); + break; + case 'J': + status = readrnxnav(fp, opt, ver, SYS_QZS, nav); /* extension */ + break; + case 'L': + status = readrnxnav(fp, opt, ver, SYS_GAL, nav); /* extension */ + break; + default: + break; + } + return status; +} + +int readrnxh(FILE *fp, double *ver, char *type, int *sys, int *tsys, + char tobs[][MAXOBSTYPE][4],obs_t* obs,nav_t *nav, sta_t *sta) +{ + double bias; + char buff[MAXRNXLEN]; + char *label; + int i=0, block=0, sat=0, status=0; + + label = buff + 60; + *ver = 2.10, *type = ' ', *sys=SYS_GPS, *tsys=TSYS_GPS; + + while (fgets(buff, MAXRNXLEN, fp)) + { + if (strlen(buff) <= 60) + { + continue; + } + else if (strstr(label, "RINEX VERSION / TYPE")) + { + *ver = str2num(buff, 0, 9); + + *type = *(buff + 20); + /* satellite system */ + switch (*(buff + 40)) + { + case ' ': + case 'G': + *sys = SYS_GPS,*tsys = TSYS_GPS; + break; + case 'R': + *sys = SYS_GLO,*tsys = TSYS_UTC; + break; + case 'E': + *sys = SYS_GAL,*tsys = TSYS_GAL; + break; /* v.2.12 */ + case 'S': + *sys = SYS_SBS, *tsys = TSYS_GPS; + break; + case 'J': + *sys = SYS_QZS,*tsys = TSYS_QZS; + break; /* v.3.02 */ + case 'C': + *sys = SYS_CMP,*tsys = TSYS_CMP; + break; /* v.2.12 */ + case 'I': + *sys = SYS_IRN,*tsys = TSYS_IRN; + break; /* v.3.03 */ + case 'M': + *sys = SYS_NONE,*tsys = TSYS_GPS; + break; /* mixed */ + default: + printf("not supported satellite system: %c\n", *(buff + 40)); + break; + } + continue; + } + else if (strstr(label, "PGM / RUN BY / DATE")) + { + continue; + } + else if (strstr(label, "COMMENT")) + { + continue; + } + switch (*type) + { + case 'O': + decode_obsh(fp,buff,*ver,tsys,tobs,obs,nav,sta); + break; + case 'N': + decode_navh(buff,nav); + break; + case 'G': + decode_gnavh(buff,nav); + break; + default: + break; + } + if (strstr(label, "END OF HEADER")){ + status = 1; + return status; + } + i = i+1; + + if (i >= MAXPOSHEAD && *type == ' '){ + printf("no RINEX file\n"); + break; /* no RINEX file */ + } + + } + + return status; +} + +int readrnxobs(FILE *fp, gtime_t ts, gtime_t te, double ti, + const char *opt, int rcv, double ver, int *tsys, + char tobs[][MAXOBSTYPE][4], obs_t *obs, sta_t *sta) +{ + obsd_t* data; + int i,n,flag=0,status=0,slips[MAXSAT][NFREQ]={0}; + + if(rcv>MAXRCV) + { + return status; + } + + if (!(data = (obsd_t *)malloc(sizeof(obsd_t) * MAXOBS))) + { + printf("malloc error\n"); + return status; + } + + while (true) + { + n = readrnxobsb(fp,opt,ver,tsys,tobs,&flag,data,sta); + if(!(n>=0 && status>=0)) break; + for (i = 0; i < n; i++) + { + /* UTC -> GPST */ + if (*tsys == TSYS_UTC) + { + data[i].time = utc2gpst(data[i].time); + } + /* save cycle slip */ + saveslips(slips, data + i); + } + /* screen data by time */ + if (n > 0 && !screent(data[0].time, ts, te, ti)){ + continue; + } + + for (i = 0; i < n; i++) + { + /* restore cycle slip */ + restoreslips(slips, data + i); + data[i].rcv = (unsigned char)rcv; + /* save obs data */ + if ((status = addobsdata(obs, data + i)) < 0) break; + } + } + + free(data); + return status; +} + +int readrnxobsb(FILE *fp, const char *opt, double ver, int *tsys, + char tobs[][MAXOBSTYPE][4], int *flag, obsd_t *data, + sta_t *sta) +{ + gtime_t time = {0}; + sigind_t index[NUMSYS] = {{0}}; + obs_t obstmp; + nav_t navtmp; + char buff[MAXRNXLEN]; + int i=0,n=0,nsat=0,sats[MAXOBS]={0},mask,status=-1; + mask = set_sysmask(opt); + set_index(ver,SYS_GPS,opt,tobs[0],&index[0]); + set_index(ver,SYS_GLO,opt,tobs[1],&index[1]); + set_index(ver,SYS_GAL,opt,tobs[2],&index[2]); + set_index(ver,SYS_QZS,opt,tobs[3],&index[3]); + set_index(ver,SYS_SBS,opt,tobs[4],&index[4]); + set_index(ver,SYS_CMP,opt,tobs[5],&index[5]); + set_index(ver,SYS_IRN,opt,tobs[6],&index[6]); + /* read record */ + while (fgets(buff,MAXRNXLEN,fp)) { + + /* decode observation epoch */ + if (i==0) { + if ((nsat=decode_obsepoch(fp,buff,ver,&time,flag,sats))<=0 && (*flag != 5)) { + continue; + } + // if (*flag == 5) { + // data[0].eventime = time; + // return 0; + // } + } + else if ((*flag<=2||*flag==6)&&nnsat) return n; + } + + return status; +} + +void saveslips(unsigned char slips[][NFREQ + NEXOBS], obsd_t *data) +{ + int i; + for (i = 0; i < NFREQ + NEXOBS; i++) + { + if (data->LLI[i] & 1) + slips[data->sat - 1][i] |= LLI_SLIP; + } +} + +int screent(gtime_t time, gtime_t ts, gtime_t te, double tint) +{ + return (tint <= 0.0 || fmod(time2gpst(time, NULL) + DTTOL, tint) <= DTTOL * 2.0) && + (ts.time == 0 || timediff(time, ts) >= -DTTOL) && + (te.time == 0 || timediff(time, te) < DTTOL); +} + +void restoreslips(unsigned char slips[][NFREQ + NEXOBS], obsd_t *data) +{ + int i; + for (i = 0; i < NFREQ + NEXOBS; i++) + { + if (slips[data->sat - 1][i] & 1) + { + data->LLI[i] |= LLI_SLIP; + } + slips[data->sat - 1][i] = 0; + } +} + +int addobsdata(obs_t *obs, const obsd_t *data) +{ + obsd_t *obs_data; + + if (obs->nmax <= obs->n) + { + if (obs->nmax <= 0) + obs->nmax = NINCOBS; + else + obs->nmax *= 2; + if (!(obs_data = (obsd_t *)realloc(obs->data, sizeof(obsd_t) * obs->nmax))) + { + printf("addobsdata: malloc error n=%dx%d\n", sizeof(obsd_t), obs->nmax); + free(obs->data); + obs->data = NULL; + obs->n = obs->nmax = 0; + return -1; + } + obs->data = obs_data; + } + obs->data[obs->n++] = *data; + return 1; +} + +/* read RINEX navigation data ------------------------------------------------*/ +int readrnxnav(FILE *fp, const char *opt, double ver, int sys,nav_t *nav) +{ + eph_t eph; + geph_t geph; + seph_t seph; + int status, type; + + printf("readrnxnav: ver=%.2f sys=%d\n", ver, sys); + + if (!nav) return 0; + + /* read RINEX navigation data body */ + while ((status = readrnxnavb(fp, opt, ver, sys, &type, &eph, &geph, &seph)) >= 0) + { + /* add ephemeris to navigation data */ + if (status) + { + switch (type) + { + case 1: + status = add_geph(nav, &geph); + break; + case 2: + status = add_seph(nav, &seph); + break; + default: + status = add_eph(nav, &eph); + break; + } + if (!status) return 0; + } + } + return nav->n > 0 || nav->ng > 0 || nav->ns > 0; +} + +int readrnxnavb(FILE *fp, const char *opt, double ver, int sys, + int *type, eph_t *eph, geph_t *geph, seph_t *seph) +{ + gtime_t toc; + double data[64]; + int i = 0, j, prn, sat = 0, sp = 3, mask; + char buff[MAXRNXLEN], id[8] = "", *p; + + printf("readrnxnavb: ver=%.2f sys=%d\n", ver, sys); + + /* set system mask */ + mask = set_sysmask(opt); + + while (fgets(buff, MAXRNXLEN, fp)) + { + if (i == 0) + { + /* decode satellite field */ + if (ver >= 3.0 || sys == SYS_GAL || sys == SYS_QZS) + { /* ver.3 or GAL/QZS */ + sprintf(id, "%.3s", buff); + sat = satid2no(id); + sp = 4; + if (ver >= 3.0) + { + sys = satsys(sat, NULL); + if (!sys) + { + sys = (id[0] == 'S') ? SYS_SBS : ((id[0] == 'R') ? SYS_GLO : SYS_GPS); + } + } + } + else + { + prn = (int)str2num(buff, 0, 2); + + if (sys == SYS_SBS) + { + sat = satno(SYS_SBS, prn + 100); + } + else if (sys == SYS_GLO) + { + sat = satno(SYS_GLO, prn); + } + else if (93 <= prn && prn <= 97) + { /* extension */ + sat = satno(SYS_QZS, prn + 100); + } + else + sat = satno(SYS_GPS, prn); + } + /* decode Toc field */ + if (str2time(buff + sp, 0, 19, &toc)) + { + printf("rinex nav toc error: %23.23s\n", buff); + return 0; + } + /* decode data fields */ + for (j = 0, p = buff + sp + 19; j < 3; j++, p += 19) + { + data[i++] = str2num(p, 0, 19); + } + } + else + { + /* decode data fields */ + for (j = 0, p = buff + sp; j < 4; j++, p += 19) + { + data[i++] = str2num(p, 0, 19); + } + /* decode ephemeris */ + if (sys == SYS_GLO && i >= 15) + { + if (!(mask & sys)) + return 0; + *type = 1; + return decode_geph(ver, sat, toc, data, geph); + } + else if (sys == SYS_SBS && i >= 15) + { + if (!(mask & sys)) + return 0; + *type = 2; + return decode_seph(ver, sat, toc, data, seph); + } + else if (i >= 31) + { + if (!(mask & sys)) + return 0; + *type = 0; + return decode_eph(ver, sat, toc, data, eph); + } + } + } + return -1; +} + +void freeobsnav(obs_t *obs, nav_t* nav) +{ + if(obs) + { + if(obs->data) + { + free(obs->data); + obs->data = NULL; + } + obs->n = 0, obs->nmax = 0; + } + if(nav) + { + if(nav->eph) + { + free(nav->eph); + nav->eph = NULL; + } + nav->n = 0,nav->nmax = 0; + + if(nav->geph) + { + free(nav->geph); + nav->geph = NULL; + } + nav->ng = 0,nav->ngmax = 0; + + if(nav->seph) + { + free(nav->seph); + nav->seph = NULL; + } + nav->ns = 0,nav->nsmax = 0; + } +} \ No newline at end of file diff --git a/src/readobsnav.h b/src/readobsnav.h new file mode 100644 index 0000000..c30ffe1 --- /dev/null +++ b/src/readobsnav.h @@ -0,0 +1,70 @@ +#ifndef READOBSNAV_H +#define READOBSNAV_H + +#include "comtyp.h" +#include "option.h" +#include "const.h" + +// Read obs and nav data ----------------------------------------------------- +bool readobsnav(gtime_t ts, gtime_t te, double ti,const char** infile,const int* index,int n, + const prcopt_t* prcopt,obs_t* obs,nav_t* nav,sta_t* sta); + +// read rinex obs and nav files ---------------------------------------------- +//return -1,0: error, 1-normal +int readrnxt(const char *filepath,int rcv,gtime_t ts,gtime_t te,double ti,const char* opt, + obs_t* obs,nav_t* nav,sta_t* sta); + +//read rinex file -------------------------------------------- +//return -1,0: error, 1-normal +int readrnxfile(const char *filepath,gtime_t ts,gtime_t te,double ti,const char* opt, + int flag,int index,char* type,obs_t* obs,nav_t* nav,sta_t* sta); + +// read rinex file ----------------------------------------------------------- +// 0-error, 1-normal +int readrnxfp(FILE* fp,gtime_t ts,gtime_t te,double ti,const char* opt, + int flag,int index,char* type,obs_t* obs,nav_t* nav,sta_t* sta); + +/* read RINEX file header ----------------------------------------------------*/ +// 0-error, 1-normal +int readrnxh(FILE *fp, double *ver, char *type, int *sys, int *tsys, + char tobs[][MAXOBSTYPE][4],obs_t* obs, nav_t *nav, sta_t *sta); + +/* read RINEX observation data -----------------------------------------------*/ +int readrnxobs(FILE *fp, gtime_t ts, gtime_t te, double ti, + const char *opt, int rcv, double ver, int *tsys, + char tobs[][MAXOBSTYPE][4], obs_t *obs, sta_t *sta); + +/* read RINEX observation data body ------------------------------------------*/ +int readrnxobsb(FILE *fp, const char *opt, double ver, int *tsys, + char tobs[][MAXOBSTYPE][4], int *flag, obsd_t *data, + sta_t *sta); + +/* save cycle slips ----------------------------------------------------------*/ +void saveslips(unsigned char slips[][NFREQ + NEXOBS], obsd_t *data); + +/* screen by time -------------------------------------------------------------- + * screening by time start, time end, and time interval + * args : gtime_t time I time + * gtime_t ts I time start (ts.time==0:no screening by ts) + * gtime_t te I time end (te.time==0:no screening by te) + * double tint I time interval (s) (0.0:no screen by tint) + * return : 1:on condition, 0:not on condition + *-----------------------------------------------------------------------------*/ +int screent(gtime_t time, gtime_t ts, gtime_t te, double tint); + +/* restore cycle slips -------------------------------------------------------*/ +void restoreslips(unsigned char slips[][NFREQ + NEXOBS], obsd_t *data); + +/* add observation data ------------------------------------------------------*/ +int addobsdata(obs_t *obs, const obsd_t *data); + +/* read RINEX navigation data ------------------------------------------------*/ +int readrnxnav(FILE *fp, const char *opt, double ver, int sys, nav_t *nav); + +/* read RINEX navigation data body -------------------------------------------*/ +int readrnxnavb(FILE *fp, const char *opt, double ver, int sys, + int *type, eph_t *eph, geph_t *geph, seph_t *seph); + +void freeobsnav(obs_t *obs, nav_t* nav); + +#endif \ No newline at end of file diff --git a/src/satellite.c b/src/satellite.c new file mode 100644 index 0000000..8731cb2 --- /dev/null +++ b/src/satellite.c @@ -0,0 +1,158 @@ +#include "satellite.h" +#include "const.h" + +extern int satid2no(const char *id) +{ + int sys, prn; + char code; + + if (sscanf(id, "%d", &prn) == 1) + { + if (MINPRNGPS <= prn && prn <= MAXPRNGPS) + sys = SYS_GPS; + else if (MINPRNSBS <= prn && prn <= MAXPRNSBS) + sys = SYS_SBS; + else if (MINPRNQZS <= prn && prn <= MAXPRNQZS) + sys = SYS_QZS; + else + return 0; + return satno(sys, prn); + } + if (sscanf(id, "%c%d", &code, &prn) < 2) + return 0; + + switch (code) + { + case 'G': + sys = SYS_GPS; + prn += MINPRNGPS - 1; + break; + case 'R': + sys = SYS_GLO; + prn += MINPRNGLO - 1; + break; + case 'E': + sys = SYS_GAL; + prn += MINPRNGAL - 1; + break; + case 'J': + sys = SYS_QZS; + prn += MINPRNQZS - 1; + break; + case 'C': + sys = SYS_CMP; + prn += MINPRNCMP - 1; + break; + case 'I': + sys = SYS_IRN; + prn += MINPRNIRN - 1; + break; + case 'L': + sys = SYS_LEO; + prn += MINPRNLEO - 1; + break; + case 'S': + sys = SYS_SBS; + prn += 100; + break; + default: + return 0; + } + return satno(sys, prn); +} + +int satno(int sys, int prn) +{ + if (prn <= 0) + return 0; + switch (sys) + { + case SYS_GPS: + if (prn < MINPRNGPS || MAXPRNGPS < prn) + return 0; + return prn - MINPRNGPS + 1; + case SYS_GLO: + if (prn < MINPRNGLO || MAXPRNGLO < prn) + return 0; + return NSATGPS + prn - MINPRNGLO + 1; + case SYS_GAL: + if (prn < MINPRNGAL || MAXPRNGAL < prn) + return 0; + return NSATGPS + NSATGLO + prn - MINPRNGAL + 1; + case SYS_QZS: + if (prn < MINPRNQZS || MAXPRNQZS < prn) + return 0; + return NSATGPS + NSATGLO + NSATGAL + prn - MINPRNQZS + 1; + case SYS_CMP: + if (prn < MINPRNCMP || MAXPRNCMP < prn) + return 0; + return NSATGPS + NSATGLO + NSATGAL + NSATQZS + prn - MINPRNCMP + 1; + case SYS_IRN: + if (prn < MINPRNIRN || MAXPRNIRN < prn) + return 0; + return NSATGPS + NSATGLO + NSATGAL + NSATQZS + NSATCMP + prn - MINPRNIRN + 1; + case SYS_LEO: + if (prn < MINPRNLEO || MAXPRNLEO < prn) + return 0; + return NSATGPS + NSATGLO + NSATGAL + NSATQZS + NSATCMP + NSATIRN + + prn - MINPRNLEO + 1; + case SYS_SBS: + if (prn < MINPRNSBS || MAXPRNSBS < prn) + return 0; + return NSATGPS + NSATGLO + NSATGAL + NSATQZS + NSATCMP + NSATIRN + NSATLEO + + prn - MINPRNSBS + 1; + } + return 0; +} + +int satsys(int sat, int *prn) +{ + int sys = SYS_NONE; + if (sat <= 0 || MAXSAT < sat) + sat = 0; + else if (sat <= NSATGPS) + { + sys = SYS_GPS; + sat += MINPRNGPS - 1; + } + else if ((sat -= NSATGPS) <= NSATGLO) + { + sys = SYS_GLO; + sat += MINPRNGLO - 1; + } + else if ((sat -= NSATGLO) <= NSATGAL) + { + sys = SYS_GAL; + sat += MINPRNGAL - 1; + } + else if ((sat -= NSATGAL) <= NSATQZS) + { + sys = SYS_QZS; + sat += MINPRNQZS - 1; + } + else if ((sat -= NSATQZS) <= NSATCMP) + { + sys = SYS_CMP; + sat += MINPRNCMP - 1; + } + else if ((sat -= NSATCMP) <= NSATIRN) + { + sys = SYS_IRN; + sat += MINPRNIRN - 1; + } + else if ((sat -= NSATIRN) <= NSATLEO) + { + sys = SYS_LEO; + sat += MINPRNLEO - 1; + } + else if ((sat -= NSATLEO) <= NSATSBS) + { + sys = SYS_SBS; + sat += MINPRNSBS - 1; + } + else + sat = 0; + if (prn) + *prn = sat; + return sys; +} \ No newline at end of file diff --git a/src/satellite.h b/src/satellite.h new file mode 100644 index 0000000..6b9ffa8 --- /dev/null +++ b/src/satellite.h @@ -0,0 +1,28 @@ +#ifndef SATELLITE_H +#define SATELLITE_H + +/* satellite id to satellite number -------------------------------------------- + * convert satellite id to satellite number + * args : char *id I satellite id (nn,Gnn,Rnn,Enn,Jnn,Cnn,Inn or Snn) + * return : satellite number (0: error) + * notes : 120-142 and 193-199 are also recognized as sbas and qzss + *-----------------------------------------------------------------------------*/ +int satid2no(const char *id); + +/* satellite system+prn/slot number to satellite number ------------------------ + * convert satellite system+prn/slot number to satellite number + * args : int sys I satellite system (SYS_GPS,SYS_GLO,...) + * int prn I satellite prn/slot number + * return : satellite number (0:error) + *-----------------------------------------------------------------------------*/ +int satno(int sys, int prn); + +/* satellite number to satellite system ---------------------------------------- + * convert satellite number to satellite system + * args : int sat I satellite number (1-MAXSAT) + * int *prn IO satellite prn/slot number (NULL: no output) + * return : satellite system (SYS_GPS,SYS_GLO,...) + *-----------------------------------------------------------------------------*/ +int satsys(int sat, int *prn); + +#endif \ No newline at end of file diff --git a/src/str.c b/src/str.c new file mode 100644 index 0000000..6180f71 --- /dev/null +++ b/src/str.c @@ -0,0 +1,76 @@ +#include +#include "str.h" +#include "timeconvert.h" + +void setstr(char *dst, const char *src, int n) +{ + char *p = dst; + const char *q = src; + while (*q && q < src + n) + { + *p++ = *q++; + } + *p-- = '\0'; + while (p >= dst && *p == ' ') + { + *p-- = '\0'; + } + return; +} + + +double str2num(const char *s, int i, int n) +{ + double value; + char str[256], *p = str; + + if (i < 0 || (int)strlen(s) < i || (int)sizeof(str) - 1 < n) + return 0.0; + for (s += i; *s && --n >= 0; s++) + *p++ = *s == 'd' || *s == 'D' ? 'E' : *s; + *p = '\0'; + return sscanf(str, "%lf", &value) == 1 ? value : 0.0; +} + +int str2time(const char *s, int i, int n, gtime_t *t) +{ + double ep[6]; + char str[256], *p = str; + + if (i < 0 || (int)strlen(s) < i || (int)sizeof(str) - 1 < i) + return -1; + for (s += i; *s && --n >= 0;) + *p++ = *s++; + *p = '\0'; + if (sscanf(str, "%lf %lf %lf %lf %lf %lf", ep, ep + 1, ep + 2, ep + 3, ep + 4, ep + 5) < 6) + return -1; + if (ep[0] < 100.0) + ep[0] += ep[0] < 80.0 ? 2000.0 : 1900.0; + *t = epoch2time(ep); + return 0; +} + +/* time to string -------------------------------------------------------------- + * convert gtime_t struct to string + * args : gtime_t t I gtime_t struct + * char *s O string ("yyyy/mm/dd hh:mm:ss.ssss") + * int n I number of decimals + * return : none + *-----------------------------------------------------------------------------*/ +void time2str(gtime_t t, char *s, int n) +{ + double ep[6]; + + if (n < 0) + n = 0; + else if (n > 12) + n = 12; + if (1.0 - t.sec < 0.5 / pow(10.0, n)) + { + t.time++; + t.sec = 0.0; + }; + time2epoch(t, ep); + sprintf(s, "%04.0f/%02.0f/%02.0f %02.0f:%02.0f:%0*.*f", ep[0], ep[1], ep[2], + ep[3], ep[4], n <= 0 ? 2 : n + 3, n <= 0 ? 0 : n, ep[5]); +} \ No newline at end of file diff --git a/src/str.h b/src/str.h new file mode 100644 index 0000000..213385a --- /dev/null +++ b/src/str.h @@ -0,0 +1,34 @@ +#ifndef STR_H +#define STR_H + +#include "comtyp.h" + +//set string without tail space +void setstr(char *dst, const char *src, int n); + +/* string to number ------------------------------------------------------------ + * convert substring in string to number + * args : char *s I string ("... nnn.nnn ...") + * int i,n I substring position and width + * return : converted number (0.0:error) + *-----------------------------------------------------------------------------*/ +double str2num(const char *s, int i, int n); + +/* string to time -------------------------------------------------------------- + * convert substring in string to gtime_t struct + * args : char *s I string ("... yyyy mm dd hh mm ss ...") + * int i,n I substring position and width + * gtime_t *t O gtime_t struct + * return : status (0:ok,0>:error) + *-----------------------------------------------------------------------------*/ +int str2time(const char *s, int i, int n, gtime_t *t); + +/* time to string -------------------------------------------------------------- + * convert gtime_t struct to string + * args : gtime_t t I gtime_t struct + * char *s O string ("yyyy/mm/dd hh:mm:ss.ssss") + * int n I number of decimals + * return : none + *-----------------------------------------------------------------------------*/ +void time2str(gtime_t t, char *s, int n); +#endif \ No newline at end of file diff --git a/src/timeconvert.c b/src/timeconvert.c new file mode 100644 index 0000000..c3b8909 --- /dev/null +++ b/src/timeconvert.c @@ -0,0 +1,132 @@ +#include +#include "timeconvert.h" + +gtime_t epoch2time(const double *ep) +{ + const int doy[] = {1, 32, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335}; + gtime_t time = {0}; + int days, sec, year = (int)ep[0], mon = (int)ep[1], day = (int)ep[2]; + + if (year < 1970 || 2099 < year || mon < 1 || 12 < mon) + return time; + + /* leap year if year%4==0 in 1901-2099 */ + days = (year - 1970) * 365 + (year - 1969) / 4 + doy[mon - 1] + day - 2 + (year % 4 == 0 && mon >= 3 ? 1 : 0); + sec = (int)floor(ep[5]); + time.time = (time_t)days * 86400 + (int)ep[3] * 3600 + (int)ep[4] * 60 + sec; + time.sec = ep[5] - sec; + return time; +} + +void time2epoch(gtime_t t, double *ep) +{ + const int mday[] = {/* # of days in a month */ + 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31, + 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; + int days, sec, mon, day; + + /* leap year if year%4==0 in 1901-2099 */ + days = (int)(t.time / 86400); + sec = (int)(t.time - (time_t)days * 86400); + for (day = days % 1461, mon = 0; mon < 48; mon++) + { + if (day >= mday[mon]) + day -= mday[mon]; + else + break; + } + ep[0] = 1970 + days / 1461 * 4 + mon / 12; + ep[1] = mon % 12 + 1; + ep[2] = day + 1; + ep[3] = sec / 3600; + ep[4] = sec % 3600 / 60; + ep[5] = sec % 60 + t.sec; +} + +gtime_t utc2gpst(gtime_t t) +{ + int i; + + for (i = 0; leaps[i][0] > 0; i++) + { + if (timediff(t, epoch2time(leaps[i])) >= 0.0) + return timeadd(t, -leaps[i][6]); + } + return t; +} + +double timediff(gtime_t t1, gtime_t t2) +{ + return difftime(t1.time, t2.time) + t1.sec - t2.sec; +} + +gtime_t timeadd(gtime_t t, double sec) +{ + double tt; + + t.sec += sec; + tt = floor(t.sec); + t.time += (int)tt; + t.sec -= tt; + return t; +} + +double time2gpst(gtime_t t, int *week) +{ + gtime_t t0 = epoch2time(gpst0); + time_t sec = t.time - t0.time; + int w = (int)(sec / (86400 * 7)); + + if (week) + *week = w; + return (double)(sec - (double)w * 86400 * 7) + t.sec; +} + +gtime_t gpst2time(int week, double sec) +{ + gtime_t t = epoch2time(gpst0); + + if (sec < -1E9 || 1E9 < sec) + sec = 0.0; + t.time += (time_t)86400 * 7 * week + (int)sec; + t.sec = sec - (int)sec; + return t; +} + +/* adjust time considering week handover -------------------------------------*/ +gtime_t adjday(gtime_t t, gtime_t t0) +{ + double tt = timediff(t, t0); + if (tt < -43200.0) + return timeadd(t, 86400.0); + if (tt > 43200.0) + return timeadd(t, -86400.0); + return t; +} + +gtime_t adjweek(gtime_t t, gtime_t t0) +{ + double tt = timediff(t, t0); + if (tt < -302400.0) + return timeadd(t, 604800.0); + if (tt > 302400.0) + return timeadd(t, -604800.0); + return t; +} + +gtime_t bdt2time(int week, double sec) +{ + gtime_t t = epoch2time(bdt0); + + if (sec < -1E9 || 1E9 < sec) + sec = 0.0; + t.time += (time_t)86400 * 7 * week + (int)sec; + t.sec = sec - (int)sec; + return t; +} + +gtime_t bdt2gpst(gtime_t t) +{ + return timeadd(t, 14.0); +} + diff --git a/src/timeconvert.h b/src/timeconvert.h new file mode 100644 index 0000000..9ec9d06 --- /dev/null +++ b/src/timeconvert.h @@ -0,0 +1,84 @@ +#ifndef TIME_H +#define TIME_H + +#include "comtyp.h" + +/* convert calendar day/time to time ------------------------------------------- + * convert calendar day/time to gtime_t struct + * args : double *ep I day/time {year,month,day,hour,min,sec} + * return : gtime_t struct + * notes : proper in 1970-2037 or 1970-2099 (64bit time_t) + *-----------------------------------------------------------------------------*/ +gtime_t epoch2time(const double *ep); + +/* time to calendar day/time --------------------------------------------------- + * convert gtime_t struct to calendar day/time + * args : gtime_t t I gtime_t struct + * double *ep O day/time {year,month,day,hour,min,sec} + * return : none + * notes : proper in 1970-2037 or 1970-2099 (64bit time_t) + *-----------------------------------------------------------------------------*/ +void time2epoch(gtime_t t, double *ep); + + +/* utc to gpstime -------------------------------------------------------------- + * convert utc to gpstime considering leap seconds + * args : gtime_t t I time expressed in utc + * return : time expressed in gpstime + * notes : ignore slight time offset under 100 ns + *-----------------------------------------------------------------------------*/ +gtime_t utc2gpst(gtime_t t); + +/* time difference ------------------------------------------------------------- + * difference between gtime_t structs + * args : gtime_t t1,t2 I gtime_t structs + * return : time difference (t1-t2) (s) + *-----------------------------------------------------------------------------*/ +double timediff(gtime_t t1, gtime_t t2); + +/* add time -------------------------------------------------------------------- + * add time to gtime_t struct + * args : gtime_t t I gtime_t struct + * double sec I time to add (s) + * return : gtime_t struct (t+sec) + *-----------------------------------------------------------------------------*/ +gtime_t timeadd(gtime_t t, double sec); + +/* time to gps time ------------------------------------------------------------ + * convert gtime_t struct to week and tow in gps time + * args : gtime_t t I gtime_t struct + * int *week IO week number in gps time (NULL: no output) + * return : time of week in gps time (s) + *-----------------------------------------------------------------------------*/ +double time2gpst(gtime_t t, int *week); + +/* gps time to time ------------------------------------------------------------ + * convert week and tow in gps time to gtime_t struct + * args : int week I week number in gps time + * double sec I time of week in gps time (s) + * return : gtime_t struct + *-----------------------------------------------------------------------------*/ +gtime_t gpst2time(int week, double sec); + +/* adjust time considering week handover -------------------------------------*/ +gtime_t adjday(gtime_t t, gtime_t t0); + +/* adjust time considering week handover -------------------------------------*/ +gtime_t adjweek(gtime_t t, gtime_t t0); + +/* beidou time (bdt) to time --------------------------------------------------- + * convert week and tow in beidou time (bdt) to gtime_t struct + * args : int week I week number in bdt + * double sec I time of week in bdt (s) + * return : gtime_t struct + *-----------------------------------------------------------------------------*/ +gtime_t bdt2time(int week, double sec); + +/* bdt to gpstime -------------------------------------------------------------- + * convert bdt (beidou navigation satellite system time) to gpstime + * args : gtime_t t I time expressed in bdt + * return : time expressed in gpstime + * notes : see gpst2bdt() + *-----------------------------------------------------------------------------*/ +gtime_t bdt2gpst(gtime_t t); +#endif \ No newline at end of file