36#define PI 3.1415926535897932
37#define CLIGHT 299792458.0
38#define OMGE 7.2921151467E-5
40#define SQR(x) ((x) * (x))
42#define RE_GLO 6378136.0
43#define MU_GPS 3.9860050E14
44#define MU_GLO 3.9860044E14
45#define MU_GAL 3.986004418E14
46#define MU_CMP 3.986004418E14
47#define J2_GLO 1.0826257E-3
49#define OMGE_GLO 7.292115E-5
50#define OMGE_GAL 7.2921151467E-5
51#define OMGE_CMP 7.292115E-5
53#define SIN_5 -0.0871557427476582
54#define COS_5 0.9961946980917456
58#define RTOL_KEPLER 1E-13
59#define MAX_ITER_KEPLER 30
61#define STD_GAL_NAPA 500.0
75#define MAXDTOE_QZS 7200.0
76#define MAXDTOE_GAL 14400.0
77#define MAXDTOE_CMP 21600.0
78#define MAXDTOE_GLO 1800.0
79#define MAXDTOE_IRN 7200.0
80#define MAXDTOE_SBS 360.0
86#define EPHOPT_SSRAPC 3
87#define EPHOPT_SSRCOM 4
91#define MAXECORSSR 10.0
92#define MAXCCORSSR (1E-6 * CLIGHT)
94#define MAXAGESSR_HRCLK 10.0
95#define STD_BRDCCLK 30.0
101extern int satsys(
int sat,
int* prn);
110 const double ura_value[] = {2.4, 3.4, 4.85, 6.85, 9.65, 13.65, 24.0, 48.0,
111 96.0, 192.0, 384.0, 768.0, 1536.0, 3072.0, 6144.0};
114 return SQR(ura * 0.01);
117 return SQR(0.5 + (ura - 50) * 0.02);
120 return SQR(1.0 + (ura - 75) * 0.04);
123 return SQR(2.0 + (ura - 100) * 0.16);
127 return ura < 0 || 14 < ura ?
SQR(6144.0) :
SQR(ura_value[ura]);
131static void deq(
const double* x,
double* xdot,
const double* acc) {
132 double a, b, c, r2 =
dot(x, x, 3), r3 = r2 * sqrt(r2), omg2 =
SQR(
OMGE_GLO);
135 xdot[0] = xdot[1] = xdot[2] = xdot[3] = xdot[4] = xdot[5] = 0.0;
140 b = 5.0 * x[2] * x[2] / r2;
141 c = -
MU_GLO / r3 - a * (1.0 - b);
145 xdot[3] = (c + omg2) * x[0] + 2.0 *
OMGE_GLO * x[4] + acc[0];
146 xdot[4] = (c + omg2) * x[1] - 2.0 *
OMGE_GLO * x[3] + acc[1];
147 xdot[5] = (c - 2.0 * a) * x[2] + acc[2];
150static void glorbit(
double t,
double* x,
const double* acc) {
151 double k1[6], k2[6], k3[6], k4[6], w[6];
155 for (i = 0; i < 6; i++) {
156 w[i] = x[i] + k1[i] * t / 2.0;
159 for (i = 0; i < 6; i++) {
160 w[i] = x[i] + k2[i] * t / 2.0;
163 for (i = 0; i < 6; i++) {
164 w[i] = x[i] + k3[i] * t;
167 for (i = 0; i < 6; i++) {
168 x[i] += (k1[i] + 2.0 * k2[i] + 2.0 * k3[i] + k4[i]) * t / 6.0;
186 double tk, M, E, Ek, sinE, cosE, u, r, i, O, x, y, sinO, cosO, cosi, mu;
194 rs[0] = rs[1] = rs[2] = *dts = 0.0;
199 M = alm->
M0 + sqrt(mu / (alm->
A * alm->
A * alm->
A)) * tk;
202 E -= (E - alm->
e * sin(E) - M) / (1.0 - alm->
e * cos(E));
205 trace(NULL, 2,
"alm2pos: kepler iteration overflow sat=%2d\n", alm->
sat);
210 u = atan2(sqrt(1.0 - alm->
e * alm->
e) * sinE, cosE - alm->
e) + alm->
omg;
211 r = alm->
A * (1.0 - alm->
e * cosE);
219 rs[0] = x * cosO - y * cosi * sinO;
220 rs[1] = x * sinO + y * cosi * cosO;
222 *dts = alm->
f0 + alm->
f1 * tk;
240 for (i = 0; i < 2; i++) {
241 t = ts - (eph->
f0 + eph->
f1 * t + eph->
f2 * t * t);
243 return eph->
f0 + eph->
f1 * t + eph->
f2 * t * t;
259 double tk, M, E, Ek, sinE, cosE, u, r, i, O, sin2u, cos2u, x, y, sinO, cosO, cosi, mu, omge;
260 double xg, yg, zg, sino, coso;
266 rs[0] = rs[1] = rs[2] = *dts = *var = 0.0;
271 switch ((sys =
satsys(eph->
sat, &prn))) {
285 M = eph->
M0 + (sqrt(mu / (eph->
A * eph->
A * eph->
A)) + eph->
deln) * tk;
289 E -= (E - eph->
e * sin(E) - M) / (1.0 - eph->
e * cos(E));
292 trace(NULL, 2,
"eph2pos: kepler iteration overflow sat=%2d\n", eph->
sat);
298 trace(NULL, 4,
"kepler: sat=%2d e=%8.5f n=%2d del=%10.3e\n", eph->
sat, eph->
e, n, E - Ek);
300 u = atan2(sqrt(1.0 - eph->
e * eph->
e) * sinE, cosE - eph->
e) + eph->
omg;
301 r = eph->
A * (1.0 - eph->
e * cosE);
302 i = eph->
i0 + eph->
idot * tk;
303 sin2u = sin(2.0 * u);
304 cos2u = cos(2.0 * u);
305 u += eph->
cus * sin2u + eph->
cuc * cos2u;
306 r += eph->
crs * sin2u + eph->
crc * cos2u;
307 i += eph->
cis * sin2u + eph->
cic * cos2u;
313 if (sys ==
SYS_CMP && (prn <= 5 || prn >= 59)) {
317 xg = x * cosO - y * cosi * sinO;
318 yg = x * sinO + y * cosi * cosO;
320 sino = sin(omge * tk);
321 coso = cos(omge * tk);
322 rs[0] = xg * coso + yg * sino *
COS_5 + zg * sino *
SIN_5;
323 rs[1] = -xg * sino + yg * coso *
COS_5 + zg * coso *
SIN_5;
326 O = eph->
OMG0 + (eph->
OMGd - omge) * tk - omge * eph->
toes;
329 rs[0] = x * cosO - y * cosi * sinO;
330 rs[1] = x * sinO + y * cosi * cosO;
334 *dts = eph->
f0 + eph->
f1 * tk + eph->
f2 * tk * tk;
337 *dts -= 2.0 * sqrt(mu * eph->
A) * eph->
e * sinE /
SQR(
CLIGHT);
353 trace(NULL, 4,
"geph2clk: time=%s sat=%2d\n",
time_str(time, 3), geph->
sat);
357 for (i = 0; i < 2; i++) {
358 t = ts - (-geph->
taun + geph->
gamn * t);
360 return -geph->
taun + geph->
gamn * t;
376 trace(NULL, 4,
"geph2pos: time=%s sat=%2d\n",
time_str(time, 3), geph->
sat);
380 *dts = -geph->
taun + geph->
gamn * t;
382 for (i = 0; i < 3; i++) {
384 x[i + 3] = geph->
vel[i];
386 for (tt = t < 0.0 ? -
TSTEP :
TSTEP; fabs(t) > 1E-9; t -= tt) {
387 if (fabs(t) <
TSTEP) {
392 for (i = 0; i < 3; i++) {
409 trace(NULL, 4,
"seph2clk: time=%s sat=%2d\n",
time_str(time, 3), seph->
sat);
413 for (i = 0; i < 2; i++) {
414 t = ts - (seph->
af0 + seph->
af1 * t);
416 return seph->
af0 + seph->
af1 * t;
432 trace(NULL, 4,
"seph2pos: time=%s sat=%2d\n",
time_str(time, 3), seph->
sat);
436 for (i = 0; i < 3; i++) {
437 rs[i] = seph->
pos[i] + seph->
vel[i] * t + seph->
acc[i] * t * t / 2.0;
439 *dts = seph->
af0 + seph->
af1 * t;
451 0, 0, 0, 0, 0, 0, 0};
461 std = (pow(3.0, (ura >> 3) & 7) * (1.0 + (ura & 7) / 4.0) - 1.0) * 1E-3;
466 double t, tmax, tmin;
467 int i, j = -1, sys, sel;
469 trace(NULL, 4,
"seleph : time=%s sat=%2d iode=%d\n",
time_str(time, 3), sat, iode);
499 for (i = 0; i < nav->
n; i++) {
500 if (nav->
eph[i].
sat != sat) {
504 if (iode >= 0 && ((
int)nav->
eph[i].
toes % 2048) != (iode * 8) % 2048) {
508 if (iode >= 0 && nav->
eph[i].
iode != iode) {
514 if (sel == 0 && !(nav->
eph[i].
code & (1 << 9))) {
517 if (sel == 1 && !(nav->
eph[i].
code & (1 << 8))) {
542 int slot_count = (sys ==
SYS_GAL) ? 2 : 1;
544 for (k = 0; k < slot_count; k++) {
545 int slot = (sat - 1) +
MAXSAT * k;
551 if (((
int)e->
toes % 2048) != (iode * 8) % 2048) {
554 }
else if (e->
iode != iode) {
559 if (gsel == 0 && !(e->
code & (1 << 9))) {
562 if (gsel == 1 && !(e->
code & (1 << 8))) {
575 if (iode >= 0 || j < 0) {
576 trace(NULL, 3,
"no broadcast ephemeris: %s sat=%2d iode=%3d\n",
time_str(time, 0), sat, iode);
586 trace(NULL, 4,
"selgeph : time=%s sat=%2d iode=%2d\n",
time_str(time, 3), sat, iode);
588 for (i = 0; i < nav->
ng; i++) {
592 if (iode >= 0 && nav->
geph[i].
iode != iode) {
599 return nav->
geph + i;
606 if (iode >= 0 || j < 0) {
607 trace(NULL, 3,
"no glonass ephemeris : %s sat=%2d iode=%2d\n",
time_str(time, 0), sat, iode);
610 return nav->
geph + j;
617 trace(NULL, 4,
"selseph : time=%s sat=%2d\n",
time_str(time, 3), sat);
619 for (i = 0; i < nav->
ns; i++) {
632 trace(NULL, 3,
"no sbas ephemeris : %s sat=%2d\n",
time_str(time, 0), sat);
635 return nav->
seph + j;
644 trace(NULL, 4,
"ephclk : time=%s sat=%2d\n",
time_str(time, 3), sat);
649 if (!(eph =
seleph(teph, sat, -1, nav))) {
654 if (!(geph =
selgeph(teph, sat, -1, nav))) {
657 if (fabs(geph->
taun) > 1.0) {
662 if (!(seph =
selseph(teph, sat, nav))) {
678 double rst[3], dtst[1], tt = 1E-3;
681 trace(NULL, 4,
"ephpos : time=%s sat=%2d iode=%d\n",
time_str(time, 3), sat, iode);
688 if (!(eph =
seleph(teph, sat, iode, nav))) {
691 eph2pos(time, eph, rs, dts, var);
693 eph2pos(time, eph, rst, dtst, var);
696 if (!(geph =
selgeph(teph, sat, iode, nav))) {
699 if (fabs(geph->
taun) > 1.0) {
704 geph2pos(time, geph, rst, dtst, var);
707 if (!(seph =
selseph(teph, sat, nav))) {
712 seph2pos(time, seph, rst, dtst, var);
719 for (i = 0; i < 3; i++) {
720 rs[i + 3] = (rst[i] - rs[i]) / tt;
722 dts[1] = (dtst[0] - dts[0]) / tt;
732 trace(NULL, 4,
"satpos_sbas: time=%s sat=%2d\n",
time_str(time, 3), sat);
737 if (sbs->
sat == sat) {
742 trace(NULL, 2,
"no sbas correction for orbit: %s sat=%2d\n",
time_str(time, 0), sat);
743 ephpos(time, teph, sat, nav, -1, rs, dts, var, svh);
748 if (!
ephpos(time, teph, sat, nav, sbs->
lcorr.
iode, rs, dts, var, svh)) {
753 if (
sbssatcorr(time, sat, nav, rs, dts, var)) {
770 double* var,
int* svh) {
773 double t1, t2, t3, er[3], ea[3], ec[3], rc[3], deph[3], dclk, dant[3] = {0}, tk;
776 trace(NULL, 4,
"satpos_ssr: time=%s sat=%2d\n",
time_str(time, 3), sat);
781 trace(NULL, 2,
"no ssr orbit correction: %s sat=%2d\n",
time_str(time, 0), sat);
785 trace(NULL, 2,
"no ssr clock correction: %s sat=%2d\n",
time_str(time, 0), sat);
789 if (ssr->
iod[0] != ssr->
iod[1]) {
790 trace(NULL, 2,
"inconsist ssr correction: %s sat=%2d iod=%d %d\n",
time_str(time, 0), sat, ssr->
iod[0],
801 trace(NULL, 2,
"age of ssr error: %s sat=%2d t=%.0f %.0f\n",
time_str(time, 0), sat, t1, t2);
805 if (ssr->
udi[0] >= 1.0) {
806 t1 -= ssr->
udi[0] / 2.0;
808 if (ssr->
udi[1] >= 1.0) {
809 t2 -= ssr->
udi[1] / 2.0;
812 for (i = 0; i < 3; i++) {
813 deph[i] = ssr->
deph[i] + ssr->
ddeph[i] * t1;
815 dclk = ssr->
dclk[0] + ssr->
dclk[1] * t2 + ssr->
dclk[2] * t2 * t2;
822 trace(NULL, 3,
"invalid ssr correction: %s deph=%.1f dclk=%.1f\n",
time_str(time, 0),
norm(deph, 3), dclk);
827 if (!
ephpos(time, teph, sat, nav, ssr->
iode, rs, dts, var, svh)) {
834 if (!(eph =
seleph(teph, sat, ssr->
iode, nav))) {
840 dts[0] = eph->
f0 + eph->
f1 * tk + eph->
f2 * tk * tk;
841 dts[1] = eph->
f1 + 2.0 * eph->
f2 * tk;
847 if (!
normv3(rs + 3, ea)) {
861 for (i = 0; i < 3; i++) {
862 rs[i] += -(er[i] * deph[0] + ea[i] * deph[1] + ec[i] * deph[2]) + dant[i];
870 trace(NULL, 5,
"satpos_ssr: %s sat=%2d deph=%6.3f %6.3f %6.3f er=%6.3f %6.3f %6.3f dclk=%6.3f var=%6.3f\n",
871 time_str(time, 2), sat, deph[0], deph[1], deph[2], er[0], er[1], er[2], dclk, *var);
892 double* var,
int* svh) {
893 trace(NULL, 4,
"satpos : time=%s sat=%2d ephopt=%d\n",
time_str(time, 3), sat, ephopt);
899 return ephpos(time, teph, sat, nav, -1, rs, dts, var, svh);
901 return satpos_sbas(time, teph, sat, nav, rs, dts, var, svh);
903 return satpos_ssr(time, teph, sat, nav, 0, rs, dts, var, svh);
905 return satpos_ssr(time, teph, sat, nav, 1, rs, dts, var, svh);
907 if (!
peph2pos(time, sat, nav, 1, rs, dts, var)) {
941 double* var,
int* svh) {
946 trace(NULL, 3,
"satposs : teph=%s n=%d ephopt=%d\n",
time_str(teph, 3), n, ephopt);
948 for (i = 0; i < n && i < 2 *
MAXOBS; i++) {
949 for (j = 0; j < 6; j++) {
952 for (j = 0; j < 2; j++) {
953 dts[j + i * 2] = 0.0;
959 for (j = 0, pr = 0.0; j < NFREQ; j++) {
960 if ((pr = obs[i].P[j]) != 0.0) {
966 trace(NULL, 3,
"no pseudorange %s sat=%2d\n",
time_str(obs[i].time, 3), obs[i].sat);
973 if (!
ephclk(time[i], teph, obs[i].sat, nav, &dt)) {
974 trace(NULL, 3,
"no broadcast clock %s sat=%2d\n",
time_str(time[i], 3), obs[i].sat);
977 time[i] =
timeadd(time[i], -dt);
980 if (!
satpos(time[i], teph, obs[i].sat, ephopt, nav, rs + i * 6, dts + i * 2, var + i, svh + i)) {
981 trace(NULL, 3,
"no ephemeris %s sat=%2d\n",
time_str(time[i], 3), obs[i].sat);
985 if (dts[i * 2] == 0.0) {
986 if (!
ephclk(time[i], teph, obs[i].sat, nav, dts + i * 2)) {
989 dts[1 + i * 2] = 0.0;
993 for (i = 0; i < n && i < 2 *
MAXOBS; i++) {
994 trace(NULL, 4,
"%s sat=%2d rs=%13.3f %13.3f %13.3f dts=%12.3f var=%7.3f svh=%02X\n",
time_str(time[i], 6),
995 obs[i].sat, rs[i * 6], rs[1 + i * 6], rs[2 + i * 6], dts[i * 2] * 1E9, var[i], svh[i]);
int satsys(int sat, int *prn)
void geph2pos(gtime_t time, const geph_t *geph, double *rs, double *dts, double *var)
Compute satellite position and clock with GLONASS ephemeris.
int getseleph(int sys)
Get selected satellite ephemeris.
void set_ssr_ch_idx(int ch)
Set SSR channel index for satpos_ssr() (multi-L6E).
static int ephclk(gtime_t time, gtime_t teph, int sat, const nav_t *nav, double *dts)
double geph2clk(gtime_t time, const geph_t *geph)
Compute satellite clock bias with GLONASS ephemeris.
void eph2pos(gtime_t time, const eph_t *eph, double *rs, double *dts, double *var)
Compute satellite position and clock with broadcast ephemeris (GPS/GAL/QZS/BDS/IRN).
static geph_t * selgeph(gtime_t time, int sat, int iode, const nav_t *nav)
int ephpos(gtime_t time, gtime_t teph, int sat, const nav_t *nav, int iode, double *rs, double *dts, double *var, int *svh)
Satellite position and clock by broadcast ephemeris.
static double var_uraeph(int sys, int ura)
int satpos(gtime_t time, gtime_t teph, int sat, int ephopt, const nav_t *nav, double *rs, double *dts, double *var, int *svh)
Compute satellite position, velocity and clock.
double seph2clk(gtime_t time, const seph_t *seph)
Compute satellite clock bias with SBAS ephemeris.
void setseleph(int sys, int sel)
Set selected satellite ephemeris for multiple ones.
static int satpos_ssr(gtime_t time, gtime_t teph, int sat, const nav_t *nav, int opt, double *rs, double *dts, double *var, int *svh)
void alm2pos(gtime_t time, const alm_t *alm, double *rs, double *dts)
Compute satellite position and clock bias with almanac.
int get_ssr_ch_idx(void)
Get current SSR channel index.
static void deq(const double *x, double *xdot, const double *acc)
void satposs(gtime_t teph, const obsd_t *obs, int n, const nav_t *nav, int ephopt, double *rs, double *dts, double *var, int *svh)
Compute satellite positions, velocities and clocks.
static double var_urassr(int ura)
void seph2pos(gtime_t time, const seph_t *seph, double *rs, double *dts, double *var)
Compute satellite position and clock with SBAS ephemeris.
static seph_t * selseph(gtime_t time, int sat, const nav_t *nav)
static int satpos_sbas(gtime_t time, gtime_t teph, int sat, const nav_t *nav, double *rs, double *dts, double *var, int *svh)
double eph2clk(gtime_t time, const eph_t *eph)
Compute satellite clock bias with broadcast ephemeris (GPS/GAL/QZS).
int sbssatcorr(gtime_t time, int sat, const nav_t *nav, double *rs, double *dts, double *var)
static void glorbit(double t, double *x, const double *acc)
eph_t * seleph(gtime_t time, int sat, int iode, const nav_t *nav)
Select broadcast ephemeris by satellite and IODE.
MRTKLIB Broadcast Ephemeris Module — Satellite orbit/clock types and Kepler/GLONASS/SBAS orbit comput...
void cross3(const double *a, const double *b, double *c)
Cross product of 3D vectors.
double norm(const double *a, int n)
Euclidean norm of vector.
int normv3(const double *a, double *b)
Normalize 3D vector.
double dot(const double *a, const double *b, int n)
Inner product of vectors.
MRTKLIB Matrix Module — Matrix/vector operations and estimation.
MRTKLIB Navigation Module — Navigation data types and satellite/nav utility functions.
int peph2pos(gtime_t time, int sat, const nav_t *nav, int opt, double *rs, double *dts, double *var)
Compute satellite position/clock with precise ephemeris/clock.
void satantoff(gtime_t time, const double *rs, int sat, const nav_t *nav, double *dant)
Compute satellite antenna phase center offset in ecef.
double timediff(gtime_t t1, gtime_t t2)
Compute time difference (t1 - t2).
gtime_t timeadd(gtime_t t, double sec)
Add seconds to gtime_t.
char * time_str(gtime_t t, int n)
Get time string (not reentrant).
void trace(mrtk_ctx_t *ctx, int level, const char *format,...)
Output trace message.
MRTKLIB Trace Module — debug trace and logging functions.
GPS/GAL/QZS/BDS/IRN almanac type.
GPS/GAL/QZS/BDS/IRN broadcast ephemeris type.
GLONASS broadcast ephemeris type.
GNSS time representation.
ssr_t ssr_ch[SSR_CH_NUM][MAXSAT]