MRTKLIB 0.7.14
Modernized GNSS Positioning Library
Loading...
Searching...
No Matches
mrtk_eph.c
Go to the documentation of this file.
1/*------------------------------------------------------------------------------
2 * mrtk_eph.c : satellite ephemeris and clock functions
3 *
4 * Copyright (C) 2026 H.SHIONO (MRTKLIB Project)
5 * Copyright (C) 2023-2025 Cabinet Office, Japan
6 * Copyright (C) 2024-2025 Lighthouse Technology & Consulting Co. Ltd.
7 * Copyright (C) 2023-2025 Japan Aerospace Exploration Agency
8 * Copyright (C) 2023-2025 TOSHIBA ELECTRONIC TECHNOLOGIES CORPORATION
9 * Copyright (C) 2015- Mitsubishi Electric Corp.
10 * Copyright (C) 2014 Geospatial Information Authority of Japan
11 * Copyright (C) 2014 T.SUZUKI
12 * Copyright (C) 2007-2023 T.TAKASU
13 *
14 * SPDX-License-Identifier: BSD-2-Clause
15 *----------------------------------------------------------------------------*/
16/**
17 * @file mrtk_eph.c
18 * @brief MRTKLIB Broadcast Ephemeris Module — Kepler/GLONASS/SBAS orbit and
19 * clock computation functions.
20 *
21 * This file contains all broadcast ephemeris orbit/clock computation functions
22 * extracted from ephemeris.c with zero algorithmic changes (pure cut-and-paste).
23 */
24#include "mrtklib/mrtk_eph.h"
25
26#include <math.h>
27
28#include "mrtklib/mrtk_mat.h"
29#include "mrtklib/mrtk_nav.h"
30#include "mrtklib/mrtk_trace.h"
31
32/*============================================================================
33 * Constants (duplicated from rtklib.h / ephemeris.c to avoid header dependency)
34 *===========================================================================*/
35
36#define PI 3.1415926535897932 /* pi */
37#define CLIGHT 299792458.0 /* speed of light (m/s) */
38#define OMGE 7.2921151467E-5 /* earth angular velocity (IS-GPS) (rad/s) */
39
40#define SQR(x) ((x) * (x))
41
42#define RE_GLO 6378136.0 /* radius of earth (m) ref [2] */
43#define MU_GPS 3.9860050E14 /* gravitational constant ref [1] */
44#define MU_GLO 3.9860044E14 /* gravitational constant ref [2] */
45#define MU_GAL 3.986004418E14 /* earth gravitational constant ref [7] */
46#define MU_CMP 3.986004418E14 /* earth gravitational constant ref [9] */
47#define J2_GLO 1.0826257E-3 /* 2nd zonal harmonic of geopot ref [2] */
48
49#define OMGE_GLO 7.292115E-5 /* earth angular velocity (rad/s) ref [2] */
50#define OMGE_GAL 7.2921151467E-5 /* earth angular velocity (rad/s) ref [7] */
51#define OMGE_CMP 7.292115E-5 /* earth angular velocity (rad/s) ref [9] */
52
53#define SIN_5 -0.0871557427476582 /* sin(-5.0 deg) */
54#define COS_5 0.9961946980917456 /* cos(-5.0 deg) */
55
56#define ERREPH_GLO 5.0 /* error of glonass ephemeris (m) */
57#define TSTEP 60.0 /* integration step glonass ephemeris (s) */
58#define RTOL_KEPLER 1E-13 /* relative tolerance for Kepler equation */
59#define MAX_ITER_KEPLER 30 /* max number of iteration of Kelpler */
60
61#define STD_GAL_NAPA 500.0 /* error of galileo ephemeris for NAPA (m) */
62
63/* navigation system identifiers */
64#define SYS_NONE 0x00
65#define SYS_GPS 0x01
66#define SYS_SBS 0x02
67#define SYS_GLO 0x04
68#define SYS_GAL 0x08
69#define SYS_QZS 0x10
70#define SYS_CMP 0x20
71#define SYS_IRN 0x40
72
73/* max time differences to ephemeris Toe */
74#define MAXDTOE 7200.0 /* max time diff to GPS Toe (s) */
75#define MAXDTOE_QZS 7200.0 /* max time diff to QZSS Toe (s) */
76#define MAXDTOE_GAL 14400.0 /* max time diff to Galileo Toe (s) */
77#define MAXDTOE_CMP 21600.0 /* max time diff to BeiDou Toe (s) */
78#define MAXDTOE_GLO 1800.0 /* max time diff to GLONASS Toe (s) */
79#define MAXDTOE_IRN 7200.0 /* max time diff to IRNSS Toe (s) */
80#define MAXDTOE_SBS 360.0 /* max time diff to SBAS Toe (s) */
81
82/* ephemeris option constants */
83#define EPHOPT_BRDC 0 /* broadcast ephemeris */
84#define EPHOPT_PREC 1 /* precise ephemeris */
85#define EPHOPT_SBAS 2 /* broadcast + SBAS */
86#define EPHOPT_SSRAPC 3 /* broadcast + SSR_APC */
87#define EPHOPT_SSRCOM 4 /* broadcast + SSR_COM */
88
89/* SSR correction constants */
90#define DEFURASSR 0.15 /* default accuracy of ssr corr (m) */
91#define MAXECORSSR 10.0 /* max orbit correction of ssr (m) */
92#define MAXCCORSSR (1E-6 * CLIGHT) /* max clock correction of ssr (m) */
93#define MAXAGESSR 60.0 /* max age of ssr orbit and clock (s) */
94#define MAXAGESSR_HRCLK 10.0 /* max age of ssr high-rate clock (s) */
95#define STD_BRDCCLK 30.0 /* error of broadcast clock (m) */
96
97/*============================================================================
98 * Forward declarations for legacy functions (resolved at link time)
99 *===========================================================================*/
100
101extern int satsys(int sat, int* prn);
102extern int sbssatcorr(gtime_t time, int sat, const nav_t* nav, double* rs, double* dts, double* var);
103
104/*============================================================================
105 * Static Helpers
106 *===========================================================================*/
107
108/* variance by ura ephemeris -------------------------------------------------*/
109static double var_uraeph(int sys, int ura) {
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};
112 if (sys == SYS_GAL) { /* galileo sisa (ref [7] 5.1.11) */
113 if (ura <= 49) {
114 return SQR(ura * 0.01);
115 }
116 if (ura <= 74) {
117 return SQR(0.5 + (ura - 50) * 0.02);
118 }
119 if (ura <= 99) {
120 return SQR(1.0 + (ura - 75) * 0.04);
121 }
122 if (ura <= 125) {
123 return SQR(2.0 + (ura - 100) * 0.16);
124 }
125 return SQR(STD_GAL_NAPA);
126 } else { /* gps ura (ref [1] 20.3.3.3.1.1) */
127 return ura < 0 || 14 < ura ? SQR(6144.0) : SQR(ura_value[ura]);
128 }
129}
130/* glonass orbit differential equations --------------------------------------*/
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);
133
134 if (r2 <= 0.0) {
135 xdot[0] = xdot[1] = xdot[2] = xdot[3] = xdot[4] = xdot[5] = 0.0;
136 return;
137 }
138 /* ref [2] A.3.1.2 with bug fix for xdot[4],xdot[5] */
139 a = 1.5 * J2_GLO * MU_GLO * SQR(RE_GLO) / r2 / r3; /* 3/2*J2*mu*Ae^2/r^5 */
140 b = 5.0 * x[2] * x[2] / r2; /* 5*z^2/r^2 */
141 c = -MU_GLO / r3 - a * (1.0 - b); /* -mu/r^3-a(1-b) */
142 xdot[0] = x[3];
143 xdot[1] = x[4];
144 xdot[2] = x[5];
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];
148}
149/* glonass position and velocity by numerical integration --------------------*/
150static void glorbit(double t, double* x, const double* acc) {
151 double k1[6], k2[6], k3[6], k4[6], w[6];
152 int i;
153
154 deq(x, k1, acc);
155 for (i = 0; i < 6; i++) {
156 w[i] = x[i] + k1[i] * t / 2.0;
157 }
158 deq(w, k2, acc);
159 for (i = 0; i < 6; i++) {
160 w[i] = x[i] + k2[i] * t / 2.0;
161 }
162 deq(w, k3, acc);
163 for (i = 0; i < 6; i++) {
164 w[i] = x[i] + k3[i] * t;
165 }
166 deq(w, k4, acc);
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;
169 }
170}
171
172/*============================================================================
173 * Public Functions
174 *===========================================================================*/
175
176/* almanac to satellite position and clock bias --------------------------------
177 * compute satellite position and clock bias with almanac (gps, galileo, qzss)
178 * args : gtime_t time I time (gpst)
179 * alm_t *alm I almanac
180 * double *rs O satellite position (ecef) {x,y,z} (m)
181 * double *dts O satellite clock bias (s)
182 * return : none
183 * notes : see ref [1],[7],[8]
184 *-----------------------------------------------------------------------------*/
185extern void alm2pos(gtime_t time, const alm_t* alm, double* rs, double* dts) {
186 double tk, M, E, Ek, sinE, cosE, u, r, i, O, x, y, sinO, cosO, cosi, mu;
187 int n;
188
189 trace(NULL, 4, "alm2pos : time=%s sat=%2d\n", time_str(time, 3), alm->sat);
190
191 tk = timediff(time, alm->toa);
192
193 if (alm->A <= 0.0) {
194 rs[0] = rs[1] = rs[2] = *dts = 0.0;
195 return;
196 }
197 mu = satsys(alm->sat, NULL) == SYS_GAL ? MU_GAL : MU_GPS;
198
199 M = alm->M0 + sqrt(mu / (alm->A * alm->A * alm->A)) * tk;
200 for (n = 0, E = M, Ek = 0.0; fabs(E - Ek) > RTOL_KEPLER && n < MAX_ITER_KEPLER; n++) {
201 Ek = E;
202 E -= (E - alm->e * sin(E) - M) / (1.0 - alm->e * cos(E));
203 }
204 if (n >= MAX_ITER_KEPLER) {
205 trace(NULL, 2, "alm2pos: kepler iteration overflow sat=%2d\n", alm->sat);
206 return;
207 }
208 sinE = sin(E);
209 cosE = cos(E);
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);
212 i = alm->i0;
213 O = alm->OMG0 + (alm->OMGd - OMGE) * tk - OMGE * alm->toas;
214 x = r * cos(u);
215 y = r * sin(u);
216 sinO = sin(O);
217 cosO = cos(O);
218 cosi = cos(i);
219 rs[0] = x * cosO - y * cosi * sinO;
220 rs[1] = x * sinO + y * cosi * cosO;
221 rs[2] = y * sin(i);
222 *dts = alm->f0 + alm->f1 * tk;
223}
224/* broadcast ephemeris to satellite clock bias ---------------------------------
225 * compute satellite clock bias with broadcast ephemeris (gps, galileo, qzss)
226 * args : gtime_t time I time by satellite clock (gpst)
227 * eph_t *eph I broadcast ephemeris
228 * return : satellite clock bias (s) without relativeity correction
229 * notes : see ref [1],[7],[8]
230 * satellite clock does not include relativity correction and tdg
231 *-----------------------------------------------------------------------------*/
232extern double eph2clk(gtime_t time, const eph_t* eph) {
233 double t, ts;
234 int i;
235
236 trace(NULL, 4, "eph2clk : time=%s sat=%2d\n", time_str(time, 3), eph->sat);
237
238 t = ts = timediff(time, eph->toc);
239
240 for (i = 0; i < 2; i++) {
241 t = ts - (eph->f0 + eph->f1 * t + eph->f2 * t * t);
242 }
243 return eph->f0 + eph->f1 * t + eph->f2 * t * t;
244}
245/* broadcast ephemeris to satellite position and clock bias --------------------
246 * compute satellite position and clock bias with broadcast ephemeris (gps,
247 * galileo, qzss)
248 * args : gtime_t time I time (gpst)
249 * eph_t *eph I broadcast ephemeris
250 * double *rs O satellite position (ecef) {x,y,z} (m)
251 * double *dts O satellite clock bias (s)
252 * double *var O satellite position and clock variance (m^2)
253 * return : none
254 * notes : see ref [1],[7],[8]
255 * satellite clock includes relativity correction without code bias
256 * (tgd or bgd)
257 *-----------------------------------------------------------------------------*/
258extern void eph2pos(gtime_t time, const eph_t* eph, double* rs, double* dts, double* var) {
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;
261 int n, sys, prn;
262
263 trace(NULL, 4, "eph2pos : time=%s sat=%2d\n", time_str(time, 3), eph->sat);
264
265 if (eph->A <= 0.0) {
266 rs[0] = rs[1] = rs[2] = *dts = *var = 0.0;
267 return;
268 }
269 tk = timediff(time, eph->toe);
270
271 switch ((sys = satsys(eph->sat, &prn))) {
272 case SYS_GAL:
273 mu = MU_GAL;
274 omge = OMGE_GAL;
275 break;
276 case SYS_CMP:
277 mu = MU_CMP;
278 omge = OMGE_CMP;
279 break;
280 default:
281 mu = MU_GPS;
282 omge = OMGE;
283 break;
284 }
285 M = eph->M0 + (sqrt(mu / (eph->A * eph->A * eph->A)) + eph->deln) * tk;
286
287 for (n = 0, E = M, Ek = 0.0; fabs(E - Ek) > RTOL_KEPLER && n < MAX_ITER_KEPLER; n++) {
288 Ek = E;
289 E -= (E - eph->e * sin(E) - M) / (1.0 - eph->e * cos(E));
290 }
291 if (n >= MAX_ITER_KEPLER) {
292 trace(NULL, 2, "eph2pos: kepler iteration overflow sat=%2d\n", eph->sat);
293 return;
294 }
295 sinE = sin(E);
296 cosE = cos(E);
297
298 trace(NULL, 4, "kepler: sat=%2d e=%8.5f n=%2d del=%10.3e\n", eph->sat, eph->e, n, E - Ek);
299
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;
308 x = r * cos(u);
309 y = r * sin(u);
310 cosi = cos(i);
311
312 /* beidou geo satellite */
313 if (sys == SYS_CMP && (prn <= 5 || prn >= 59)) { /* ref [9] table 4-1 */
314 O = eph->OMG0 + eph->OMGd * tk - omge * eph->toes;
315 sinO = sin(O);
316 cosO = cos(O);
317 xg = x * cosO - y * cosi * sinO;
318 yg = x * sinO + y * cosi * cosO;
319 zg = y * sin(i);
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;
324 rs[2] = -yg * SIN_5 + zg * COS_5;
325 } else {
326 O = eph->OMG0 + (eph->OMGd - omge) * tk - omge * eph->toes;
327 sinO = sin(O);
328 cosO = cos(O);
329 rs[0] = x * cosO - y * cosi * sinO;
330 rs[1] = x * sinO + y * cosi * cosO;
331 rs[2] = y * sin(i);
332 }
333 tk = timediff(time, eph->toc);
334 *dts = eph->f0 + eph->f1 * tk + eph->f2 * tk * tk;
335
336 /* relativity correction */
337 *dts -= 2.0 * sqrt(mu * eph->A) * eph->e * sinE / SQR(CLIGHT);
338
339 /* position and clock error variance */
340 *var = var_uraeph(sys, eph->sva);
341}
342/* glonass ephemeris to satellite clock bias -----------------------------------
343 * compute satellite clock bias with glonass ephemeris
344 * args : gtime_t time I time by satellite clock (gpst)
345 * geph_t *geph I glonass ephemeris
346 * return : satellite clock bias (s)
347 * notes : see ref [2]
348 *-----------------------------------------------------------------------------*/
349extern double geph2clk(gtime_t time, const geph_t* geph) {
350 double t, ts;
351 int i;
352
353 trace(NULL, 4, "geph2clk: time=%s sat=%2d\n", time_str(time, 3), geph->sat);
354
355 t = ts = timediff(time, geph->toe);
356
357 for (i = 0; i < 2; i++) {
358 t = ts - (-geph->taun + geph->gamn * t);
359 }
360 return -geph->taun + geph->gamn * t;
361}
362/* glonass ephemeris to satellite position and clock bias ----------------------
363 * compute satellite position and clock bias with glonass ephemeris
364 * args : gtime_t time I time (gpst)
365 * geph_t *geph I glonass ephemeris
366 * double *rs O satellite position {x,y,z} (ecef) (m)
367 * double *dts O satellite clock bias (s)
368 * double *var O satellite position and clock variance (m^2)
369 * return : none
370 * notes : see ref [2]
371 *-----------------------------------------------------------------------------*/
372extern void geph2pos(gtime_t time, const geph_t* geph, double* rs, double* dts, double* var) {
373 double t, tt, x[6];
374 int i;
375
376 trace(NULL, 4, "geph2pos: time=%s sat=%2d\n", time_str(time, 3), geph->sat);
377
378 t = timediff(time, geph->toe);
379
380 *dts = -geph->taun + geph->gamn * t;
381
382 for (i = 0; i < 3; i++) {
383 x[i] = geph->pos[i];
384 x[i + 3] = geph->vel[i];
385 }
386 for (tt = t < 0.0 ? -TSTEP : TSTEP; fabs(t) > 1E-9; t -= tt) {
387 if (fabs(t) < TSTEP) {
388 tt = t;
389 }
390 glorbit(tt, x, geph->acc);
391 }
392 for (i = 0; i < 3; i++) {
393 rs[i] = x[i];
394 }
395
396 *var = SQR(ERREPH_GLO);
397}
398/* sbas ephemeris to satellite clock bias --------------------------------------
399 * compute satellite clock bias with sbas ephemeris
400 * args : gtime_t time I time by satellite clock (gpst)
401 * seph_t *seph I sbas ephemeris
402 * return : satellite clock bias (s)
403 * notes : see ref [3]
404 *-----------------------------------------------------------------------------*/
405extern double seph2clk(gtime_t time, const seph_t* seph) {
406 double t, ts;
407 int i;
408
409 trace(NULL, 4, "seph2clk: time=%s sat=%2d\n", time_str(time, 3), seph->sat);
410
411 t = ts = timediff(time, seph->t0);
412
413 for (i = 0; i < 2; i++) {
414 t = ts - (seph->af0 + seph->af1 * t); /* parentheses required: iterate clock bias */
415 }
416 return seph->af0 + seph->af1 * t;
417}
418/* sbas ephemeris to satellite position and clock bias -------------------------
419 * compute satellite position and clock bias with sbas ephemeris
420 * args : gtime_t time I time (gpst)
421 * seph_t *seph I sbas ephemeris
422 * double *rs O satellite position {x,y,z} (ecef) (m)
423 * double *dts O satellite clock bias (s)
424 * double *var O satellite position and clock variance (m^2)
425 * return : none
426 * notes : see ref [3]
427 *-----------------------------------------------------------------------------*/
428extern void seph2pos(gtime_t time, const seph_t* seph, double* rs, double* dts, double* var) {
429 double t;
430 int i;
431
432 trace(NULL, 4, "seph2pos: time=%s sat=%2d\n", time_str(time, 3), seph->sat);
433
434 t = timediff(time, seph->t0);
435
436 for (i = 0; i < 3; i++) {
437 rs[i] = seph->pos[i] + seph->vel[i] * t + seph->acc[i] * t * t / 2.0;
438 }
439 *dts = seph->af0 + seph->af1 * t;
440
441 *var = var_uraeph(SYS_SBS, seph->sva);
442}
443
444/*============================================================================
445 * Ephemeris Selection and Satellite Position Functions
446 * (absorbed from ephemeris.c — pure cut-and-paste)
447 *===========================================================================*/
448
449/* ephemeris selections ------------------------------------------------------*/
450static int eph_sel[] = {/* GPS,GLO,GAL,QZS,BDS,IRN,SBS */
451 0, 0, 0, 0, 0, 0, 0};
452/* variance by ura ssr (ref [10] table 3.3-1 DF389) --------------------------*/
453static double var_urassr(int ura) {
454 double std;
455 if (ura <= 0) {
456 return SQR(DEFURASSR);
457 }
458 if (ura >= 63) {
459 return SQR(5.4665);
460 }
461 std = (pow(3.0, (ura >> 3) & 7) * (1.0 + (ura & 7) / 4.0) - 1.0) * 1E-3;
462 return SQR(std);
463}
464/* select ephemeris ----------------------------------------------------------*/
465eph_t* seleph(gtime_t time, int sat, int iode, const nav_t* nav) {
466 double t, tmax, tmin;
467 int i, j = -1, sys, sel;
468
469 trace(NULL, 4, "seleph : time=%s sat=%2d iode=%d\n", time_str(time, 3), sat, iode);
470
471 sys = satsys(sat, NULL);
472 switch (sys) {
473 case SYS_GPS:
474 tmax = MAXDTOE + 1.0;
475 sel = eph_sel[0];
476 break;
477 case SYS_GAL:
478 tmax = MAXDTOE_GAL;
479 sel = eph_sel[2];
480 break;
481 case SYS_QZS:
482 tmax = MAXDTOE_QZS + 1.0;
483 sel = eph_sel[3];
484 break;
485 case SYS_CMP:
486 tmax = MAXDTOE_CMP + 1.0;
487 sel = eph_sel[4];
488 break;
489 case SYS_IRN:
490 tmax = MAXDTOE_IRN + 1.0;
491 sel = eph_sel[5];
492 break;
493 default:
494 tmax = MAXDTOE + 1.0;
495 break;
496 }
497 tmin = tmax + 1.0;
498
499 for (i = 0; i < nav->n; i++) {
500 if (nav->eph[i].sat != sat) {
501 continue;
502 }
503 if (sys == SYS_CMP) {
504 if (iode >= 0 && ((int)nav->eph[i].toes % 2048) != (iode * 8) % 2048) {
505 continue;
506 }
507 } else {
508 if (iode >= 0 && nav->eph[i].iode != iode) {
509 continue;
510 }
511 }
512 if (sys == SYS_GAL) {
513 sel = getseleph(SYS_GAL);
514 if (sel == 0 && !(nav->eph[i].code & (1 << 9))) {
515 continue; /* I/NAV */
516 }
517 if (sel == 1 && !(nav->eph[i].code & (1 << 8))) {
518 continue; /* F/NAV */
519 }
520 if (timediff(nav->eph[i].toe, time) >= 0.0) {
521 continue; /* AOD<=0 */
522 }
523 }
524 if ((t = fabs(timediff(nav->eph[i].toe, time))) > tmax) {
525 continue;
526 }
527 if (iode >= 0) {
528 return nav->eph + i;
529 }
530 if (t <= tmin) {
531 j = i;
532 tmin = t;
533 } /* toe closest to time */
534 }
535 if (iode >= 0 && nav->eph_prev) {
536 /* IODE-specific lookup failed in nav->eph[]. Fall back to eph_prev[],
537 * which keeps the previous-IODE eph for each satellite slot. This
538 * matters when broadcast eph receives the new IODE (overwriting
539 * eph[]) before the CSSR SSR transitions to that IODE; without this
540 * fallback, seleph() returns NULL for ~55 s on every Galileo IODnav
541 * update, causing periodic DGPS dips. See lessons.md L-041. */
542 int slot_count = (sys == SYS_GAL) ? 2 : 1; /* GAL has I/NAV + F/NAV */
543 int k;
544 for (k = 0; k < slot_count; k++) {
545 int slot = (sat - 1) + MAXSAT * k;
546 const eph_t* e = &nav->eph_prev[slot];
547 if (e->sat != sat) {
548 continue;
549 }
550 if (sys == SYS_CMP) {
551 if (((int)e->toes % 2048) != (iode * 8) % 2048) {
552 continue;
553 }
554 } else if (e->iode != iode) {
555 continue;
556 }
557 if (sys == SYS_GAL) {
558 int gsel = getseleph(SYS_GAL);
559 if (gsel == 0 && !(e->code & (1 << 9))) {
560 continue; /* I/NAV */
561 }
562 if (gsel == 1 && !(e->code & (1 << 8))) {
563 continue; /* F/NAV */
564 }
565 if (timediff(e->toe, time) >= 0.0) {
566 continue;
567 }
568 }
569 if (fabs(timediff(e->toe, time)) > tmax) {
570 continue;
571 }
572 return (eph_t*)e;
573 }
574 }
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);
577 return NULL;
578 }
579 return nav->eph + j;
580}
581/* select glonass ephememeris ------------------------------------------------*/
582static geph_t* selgeph(gtime_t time, int sat, int iode, const nav_t* nav) {
583 double t, tmax = MAXDTOE_GLO, tmin = tmax + 1.0;
584 int i, j = -1;
585
586 trace(NULL, 4, "selgeph : time=%s sat=%2d iode=%2d\n", time_str(time, 3), sat, iode);
587
588 for (i = 0; i < nav->ng; i++) {
589 if (nav->geph[i].sat != sat) {
590 continue;
591 }
592 if (iode >= 0 && nav->geph[i].iode != iode) {
593 continue;
594 }
595 if ((t = fabs(timediff(nav->geph[i].toe, time))) > tmax) {
596 continue;
597 }
598 if (iode >= 0) {
599 return nav->geph + i;
600 }
601 if (t <= tmin) {
602 j = i;
603 tmin = t;
604 } /* toe closest to time */
605 }
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);
608 return NULL;
609 }
610 return nav->geph + j;
611}
612/* select sbas ephememeris ---------------------------------------------------*/
613static seph_t* selseph(gtime_t time, int sat, const nav_t* nav) {
614 double t, tmax = MAXDTOE_SBS, tmin = tmax + 1.0;
615 int i, j = -1;
616
617 trace(NULL, 4, "selseph : time=%s sat=%2d\n", time_str(time, 3), sat);
618
619 for (i = 0; i < nav->ns; i++) {
620 if (nav->seph[i].sat != sat) {
621 continue;
622 }
623 if ((t = fabs(timediff(nav->seph[i].t0, time))) > tmax) {
624 continue;
625 }
626 if (t <= tmin) {
627 j = i;
628 tmin = t;
629 } /* toe closest to time */
630 }
631 if (j < 0) {
632 trace(NULL, 3, "no sbas ephemeris : %s sat=%2d\n", time_str(time, 0), sat);
633 return NULL;
634 }
635 return nav->seph + j;
636}
637/* satellite clock with broadcast ephemeris ----------------------------------*/
638static int ephclk(gtime_t time, gtime_t teph, int sat, const nav_t* nav, double* dts) {
639 eph_t* eph;
640 geph_t* geph;
641 seph_t* seph;
642 int sys;
643
644 trace(NULL, 4, "ephclk : time=%s sat=%2d\n", time_str(time, 3), sat);
645
646 sys = satsys(sat, NULL);
647
648 if (sys == SYS_GPS || sys == SYS_GAL || sys == SYS_QZS || sys == SYS_CMP || sys == SYS_IRN) {
649 if (!(eph = seleph(teph, sat, -1, nav))) {
650 return 0;
651 }
652 *dts = eph2clk(time, eph);
653 } else if (sys == SYS_GLO) {
654 if (!(geph = selgeph(teph, sat, -1, nav))) {
655 return 0;
656 }
657 if (fabs(geph->taun) > 1.0) {
658 return 0; /* reject corrupted GLO clock data */
659 }
660 *dts = geph2clk(time, geph);
661 } else if (sys == SYS_SBS) {
662 if (!(seph = selseph(teph, sat, nav))) {
663 return 0;
664 }
665 *dts = seph2clk(time, seph);
666 } else {
667 return 0;
668 }
669
670 return 1;
671}
672/* satellite position and clock by broadcast ephemeris -----------------------*/
673int ephpos(gtime_t time, gtime_t teph, int sat, const nav_t* nav, int iode, double* rs, double* dts, double* var,
674 int* svh) {
675 eph_t* eph;
676 geph_t* geph;
677 seph_t* seph;
678 double rst[3], dtst[1], tt = 1E-3;
679 int i, sys;
680
681 trace(NULL, 4, "ephpos : time=%s sat=%2d iode=%d\n", time_str(time, 3), sat, iode);
682
683 sys = satsys(sat, NULL);
684
685 *svh = -1;
686
687 if (sys == SYS_GPS || sys == SYS_GAL || sys == SYS_QZS || sys == SYS_CMP || sys == SYS_IRN) {
688 if (!(eph = seleph(teph, sat, iode, nav))) {
689 return 0;
690 }
691 eph2pos(time, eph, rs, dts, var);
692 time = timeadd(time, tt);
693 eph2pos(time, eph, rst, dtst, var);
694 *svh = eph->svh;
695 } else if (sys == SYS_GLO) {
696 if (!(geph = selgeph(teph, sat, iode, nav))) {
697 return 0;
698 }
699 if (fabs(geph->taun) > 1.0) {
700 return 0; /* reject corrupted GLO clock data (consistent with ephclk) */
701 }
702 geph2pos(time, geph, rs, dts, var);
703 time = timeadd(time, tt);
704 geph2pos(time, geph, rst, dtst, var);
705 *svh = geph->svh;
706 } else if (sys == SYS_SBS) {
707 if (!(seph = selseph(teph, sat, nav))) {
708 return 0;
709 }
710 seph2pos(time, seph, rs, dts, var);
711 time = timeadd(time, tt);
712 seph2pos(time, seph, rst, dtst, var);
713 *svh = seph->svh;
714 } else {
715 return 0;
716 }
717
718 /* satellite velocity and clock drift by differential approx */
719 for (i = 0; i < 3; i++) {
720 rs[i + 3] = (rst[i] - rs[i]) / tt;
721 }
722 dts[1] = (dtst[0] - dts[0]) / tt;
723
724 return 1;
725}
726/* satellite position and clock with sbas correction -------------------------*/
727static int satpos_sbas(gtime_t time, gtime_t teph, int sat, const nav_t* nav, double* rs, double* dts, double* var,
728 int* svh) {
729 const sbssatp_t* sbs;
730 int i;
731
732 trace(NULL, 4, "satpos_sbas: time=%s sat=%2d\n", time_str(time, 3), sat);
733
734 /* search sbas satellite correciton */
735 for (i = 0; i < nav->sbssat.nsat; i++) {
736 sbs = nav->sbssat.sat + i;
737 if (sbs->sat == sat) {
738 break;
739 }
740 }
741 if (i >= nav->sbssat.nsat) {
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);
744 *svh = -1;
745 return 0;
746 }
747 /* satellite position and clock by broadcast ephemeris */
748 if (!ephpos(time, teph, sat, nav, sbs->lcorr.iode, rs, dts, var, svh)) {
749 return 0;
750 }
751
752 /* sbas satellite correction (long term and fast) */
753 if (sbssatcorr(time, sat, nav, rs, dts, var)) {
754 return 1;
755 }
756 *svh = -1;
757 return 0;
758}
759/* SSR channel index for satpos_ssr (multi-L6E) -----------------------------*/
760static int _ssr_ch_idx = 0;
761extern void set_ssr_ch_idx(int ch) {
762 if (ch >= 0 && ch < SSR_CH_NUM) {
763 _ssr_ch_idx = ch;
764 }
765}
766extern int get_ssr_ch_idx(void) { return _ssr_ch_idx; }
767
768/* satellite position and clock with ssr correction --------------------------*/
769static int satpos_ssr(gtime_t time, gtime_t teph, int sat, const nav_t* nav, int opt, double* rs, double* dts,
770 double* var, int* svh) {
771 const ssr_t* ssr;
772 eph_t* eph;
773 double t1, t2, t3, er[3], ea[3], ec[3], rc[3], deph[3], dclk, dant[3] = {0}, tk;
774 int i, sys;
775
776 trace(NULL, 4, "satpos_ssr: time=%s sat=%2d\n", time_str(time, 3), sat);
777
778 ssr = nav->ssr_ch[_ssr_ch_idx] + sat - 1;
779
780 if (!ssr->t0[0].time) {
781 trace(NULL, 2, "no ssr orbit correction: %s sat=%2d\n", time_str(time, 0), sat);
782 return 0;
783 }
784 if (!ssr->t0[1].time) {
785 trace(NULL, 2, "no ssr clock correction: %s sat=%2d\n", time_str(time, 0), sat);
786 return 0;
787 }
788 /* inconsistency between orbit and clock correction */
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],
791 ssr->iod[1]);
792 *svh = -1;
793 return 0;
794 }
795 t1 = timediff(time, ssr->t0[0]);
796 t2 = timediff(time, ssr->t0[1]);
797 t3 = timediff(time, ssr->t0[2]);
798
799 /* ssr orbit and clock correction (ref [4]) */
800 if (fabs(t1) > MAXAGESSR || fabs(t2) > MAXAGESSR) {
801 trace(NULL, 2, "age of ssr error: %s sat=%2d t=%.0f %.0f\n", time_str(time, 0), sat, t1, t2);
802 *svh = -1;
803 return 0;
804 }
805 if (ssr->udi[0] >= 1.0) {
806 t1 -= ssr->udi[0] / 2.0;
807 }
808 if (ssr->udi[1] >= 1.0) {
809 t2 -= ssr->udi[1] / 2.0;
810 }
811
812 for (i = 0; i < 3; i++) {
813 deph[i] = ssr->deph[i] + ssr->ddeph[i] * t1;
814 }
815 dclk = ssr->dclk[0] + ssr->dclk[1] * t2 + ssr->dclk[2] * t2 * t2;
816
817 /* ssr highrate clock correction (ref [4]) */
818 if (ssr->iod[0] == ssr->iod[2] && ssr->t0[2].time && fabs(t3) < MAXAGESSR_HRCLK) {
819 dclk += ssr->hrclk;
820 }
821 if (norm(deph, 3) > MAXECORSSR || fabs(dclk) > MAXCCORSSR) {
822 trace(NULL, 3, "invalid ssr correction: %s deph=%.1f dclk=%.1f\n", time_str(time, 0), norm(deph, 3), dclk);
823 *svh = -1;
824 return 0;
825 }
826 /* satellite position and clock by broadcast ephemeris */
827 if (!ephpos(time, teph, sat, nav, ssr->iode, rs, dts, var, svh)) {
828 return 0;
829 }
830
831 /* satellite clock for gps, galileo and qzss */
832 sys = satsys(sat, NULL);
833 if (sys == SYS_GPS || sys == SYS_GAL || sys == SYS_QZS || sys == SYS_CMP) {
834 if (!(eph = seleph(teph, sat, ssr->iode, nav))) {
835 return 0;
836 }
837
838 /* satellite clock by clock parameters */
839 tk = timediff(time, eph->toc);
840 dts[0] = eph->f0 + eph->f1 * tk + eph->f2 * tk * tk;
841 dts[1] = eph->f1 + 2.0 * eph->f2 * tk;
842
843 /* relativity correction */
844 dts[0] -= 2.0 * dot(rs, rs + 3, 3) / CLIGHT / CLIGHT;
845 }
846 /* radial-along-cross directions in ecef */
847 if (!normv3(rs + 3, ea)) {
848 return 0;
849 }
850 cross3(rs, rs + 3, rc);
851 if (!normv3(rc, ec)) {
852 *svh = -1;
853 return 0;
854 }
855 cross3(ea, ec, er);
856
857 /* satellite antenna offset correction */
858 if (opt) {
859 satantoff(time, rs, sat, nav, dant);
860 }
861 for (i = 0; i < 3; i++) {
862 rs[i] += -(er[i] * deph[0] + ea[i] * deph[1] + ec[i] * deph[2]) + dant[i];
863 }
864 /* t_corr = t_sv - (dts(brdc) + dclk(ssr) / CLIGHT) (ref [10] eq.3.12-7) */
865 dts[0] += dclk / CLIGHT;
866
867 /* variance by ssr ura */
868 *var = var_urassr(ssr->ura);
869
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);
872
873 return 1;
874}
875/* satellite position and clock ------------------------------------------------
876 * compute satellite position, velocity and clock
877 * args : gtime_t time I time (gpst)
878 * gtime_t teph I time to select ephemeris (gpst)
879 * int sat I satellite number
880 * nav_t *nav I navigation data
881 * int ephopt I ephemeris option (EPHOPT_???)
882 * double *rs O sat position and velocity (ecef)
883 * {x,y,z,vx,vy,vz} (m|m/s)
884 * double *dts O sat clock {bias,drift} (s|s/s)
885 * double *var O sat position and clock error variance (m^2)
886 * int *svh O sat health flag (-1:correction not available)
887 * return : status (1:ok,0:error)
888 * notes : satellite position is referenced to antenna phase center
889 * satellite clock does not include code bias correction (tgd or bgd)
890 *-----------------------------------------------------------------------------*/
891extern int satpos(gtime_t time, gtime_t teph, int sat, int ephopt, const nav_t* nav, double* rs, double* dts,
892 double* var, int* svh) {
893 trace(NULL, 4, "satpos : time=%s sat=%2d ephopt=%d\n", time_str(time, 3), sat, ephopt);
894
895 *svh = 0;
896
897 switch (ephopt) {
898 case EPHOPT_BRDC:
899 return ephpos(time, teph, sat, nav, -1, rs, dts, var, svh);
900 case EPHOPT_SBAS:
901 return satpos_sbas(time, teph, sat, nav, rs, dts, var, svh);
902 case EPHOPT_SSRAPC:
903 return satpos_ssr(time, teph, sat, nav, 0, rs, dts, var, svh);
904 case EPHOPT_SSRCOM:
905 return satpos_ssr(time, teph, sat, nav, 1, rs, dts, var, svh);
906 case EPHOPT_PREC:
907 if (!peph2pos(time, sat, nav, 1, rs, dts, var)) {
908 break;
909 } else {
910 return 1;
911 }
912 }
913 *svh = -1;
914 return 0;
915}
916/* satellite positions and clocks ----------------------------------------------
917 * compute satellite positions, velocities and clocks
918 * args : gtime_t teph I time to select ephemeris (gpst)
919 * obsd_t *obs I observation data
920 * int n I number of observation data
921 * nav_t *nav I navigation data
922 * int ephopt I ephemeris option (EPHOPT_???)
923 * double *rs O satellite positions and velocities (ecef)
924 * double *dts O satellite clocks
925 * double *var O sat position and clock error variances (m^2)
926 * int *svh O sat health flag (-1:correction not available)
927 * return : none
928 * notes : rs [(0:2)+i*6]= obs[i] sat position {x,y,z} (m)
929 * rs [(3:5)+i*6]= obs[i] sat velocity {vx,vy,vz} (m/s)
930 * dts[(0:1)+i*2]= obs[i] sat clock {bias,drift} (s|s/s)
931 * var[i] = obs[i] sat position and clock error variance (m^2)
932 * svh[i] = obs[i] sat health flag
933 * if no navigation data, set 0 to rs[], dts[], var[] and svh[]
934 * satellite position and clock are values at signal transmission time
935 * satellite position is referenced to antenna phase center
936 * satellite clock does not include code bias correction (tgd or bgd)
937 * any pseudorange and broadcast ephemeris are always needed to get
938 * signal transmission time
939 *-----------------------------------------------------------------------------*/
940extern void satposs(gtime_t teph, const obsd_t* obs, int n, const nav_t* nav, int ephopt, double* rs, double* dts,
941 double* var, int* svh) {
942 gtime_t time[2 * MAXOBS] = {{0}};
943 double dt, pr;
944 int i, j;
945
946 trace(NULL, 3, "satposs : teph=%s n=%d ephopt=%d\n", time_str(teph, 3), n, ephopt);
947
948 for (i = 0; i < n && i < 2 * MAXOBS; i++) {
949 for (j = 0; j < 6; j++) {
950 rs[j + i * 6] = 0.0;
951 }
952 for (j = 0; j < 2; j++) {
953 dts[j + i * 2] = 0.0;
954 }
955 var[i] = 0.0;
956 svh[i] = 0;
957
958 /* search any pseudorange */
959 for (j = 0, pr = 0.0; j < NFREQ; j++) {
960 if ((pr = obs[i].P[j]) != 0.0) {
961 break;
962 }
963 }
964
965 if (j >= NFREQ) {
966 trace(NULL, 3, "no pseudorange %s sat=%2d\n", time_str(obs[i].time, 3), obs[i].sat);
967 continue;
968 }
969 /* transmission time by satellite clock */
970 time[i] = timeadd(obs[i].time, -pr / CLIGHT);
971
972 /* satellite clock bias by broadcast ephemeris */
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);
975 continue;
976 }
977 time[i] = timeadd(time[i], -dt);
978
979 /* satellite position and clock at transmission time */
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);
982 continue;
983 }
984 /* if no precise clock available, use broadcast clock instead */
985 if (dts[i * 2] == 0.0) {
986 if (!ephclk(time[i], teph, obs[i].sat, nav, dts + i * 2)) {
987 continue;
988 }
989 dts[1 + i * 2] = 0.0;
990 *var = SQR(STD_BRDCCLK);
991 }
992 }
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]);
996 }
997}
998/* set selected satellite ephemeris --------------------------------------------
999 * Set selected satellite ephemeris for multiple ones like LNAV - CNAV, I/NAV -
1000 * F/NAV. Call it before calling satpos(),satposs() to use unselected one.
1001 * args : int sys I satellite system (SYS_???)
1002 * int sel I selection of ephemeris
1003 * GPS,QZS : 0:LNAV ,1:CNAV (default: LNAV)
1004 * GAL : 0:I/NAV,1:F/NAV (default: I/NAV)
1005 * others : undefined
1006 * return : none
1007 * notes : default ephemeris selection for galileo is any.
1008 *-----------------------------------------------------------------------------*/
1009extern void setseleph(int sys, int sel) {
1010 switch (sys) {
1011 case SYS_GPS:
1012 eph_sel[0] = sel;
1013 break;
1014 case SYS_GLO:
1015 eph_sel[1] = sel;
1016 break;
1017 case SYS_GAL:
1018 eph_sel[2] = sel;
1019 break;
1020 case SYS_QZS:
1021 eph_sel[3] = sel;
1022 break;
1023 case SYS_CMP:
1024 eph_sel[4] = sel;
1025 break;
1026 case SYS_IRN:
1027 eph_sel[5] = sel;
1028 break;
1029 case SYS_SBS:
1030 eph_sel[6] = sel;
1031 break;
1032 }
1033}
1034/* get selected satellite ephemeris -------------------------------------------
1035 * Get the selected satellite ephemeris.
1036 * args : int sys I satellite system (SYS_???)
1037 * return : selected ephemeris
1038 * refer setseleph()
1039 *-----------------------------------------------------------------------------*/
1040extern int getseleph(int sys) {
1041 switch (sys) {
1042 case SYS_GPS:
1043 return eph_sel[0];
1044 case SYS_GLO:
1045 return eph_sel[1];
1046 case SYS_GAL:
1047 return eph_sel[2];
1048 case SYS_QZS:
1049 return eph_sel[3];
1050 case SYS_CMP:
1051 return eph_sel[4];
1052 case SYS_IRN:
1053 return eph_sel[5];
1054 case SYS_SBS:
1055 return eph_sel[6];
1056 }
1057 return 0;
1058}
#define CLIGHT
Definition mrtk_coords.c:41
#define MAXSAT
Definition mrtk_coords.c:45
#define OMGE
Definition mrtk_coords.c:40
int satsys(int sat, int *prn)
Definition mrtk_nav.c:117
#define EPHOPT_PREC
Definition mrtk_eph.c:84
void geph2pos(gtime_t time, const geph_t *geph, double *rs, double *dts, double *var)
Compute satellite position and clock with GLONASS ephemeris.
Definition mrtk_eph.c:372
int getseleph(int sys)
Get selected satellite ephemeris.
Definition mrtk_eph.c:1040
static int eph_sel[]
Definition mrtk_eph.c:450
#define TSTEP
Definition mrtk_eph.c:57
void set_ssr_ch_idx(int ch)
Set SSR channel index for satpos_ssr() (multi-L6E).
Definition mrtk_eph.c:761
#define OMGE_GAL
Definition mrtk_eph.c:50
static int ephclk(gtime_t time, gtime_t teph, int sat, const nav_t *nav, double *dts)
Definition mrtk_eph.c:638
#define MAXAGESSR_HRCLK
Definition mrtk_eph.c:94
double geph2clk(gtime_t time, const geph_t *geph)
Compute satellite clock bias with GLONASS ephemeris.
Definition mrtk_eph.c:349
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).
Definition mrtk_eph.c:258
static geph_t * selgeph(gtime_t time, int sat, int iode, const nav_t *nav)
Definition mrtk_eph.c:582
#define SYS_GPS
Definition mrtk_eph.c:65
#define J2_GLO
Definition mrtk_eph.c:47
#define SIN_5
Definition mrtk_eph.c:53
#define RTOL_KEPLER
Definition mrtk_eph.c:58
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.
Definition mrtk_eph.c:673
#define MAXDTOE
Definition mrtk_eph.c:74
#define OMGE_GLO
Definition mrtk_eph.c:49
static double var_uraeph(int sys, int ura)
Definition mrtk_eph.c:109
#define MU_CMP
Definition mrtk_eph.c:46
#define SYS_SBS
Definition mrtk_eph.c:66
#define EPHOPT_SSRAPC
Definition mrtk_eph.c:86
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.
Definition mrtk_eph.c:891
#define DEFURASSR
Definition mrtk_eph.c:90
double seph2clk(gtime_t time, const seph_t *seph)
Compute satellite clock bias with SBAS ephemeris.
Definition mrtk_eph.c:405
void setseleph(int sys, int sel)
Set selected satellite ephemeris for multiple ones.
Definition mrtk_eph.c:1009
#define MAXCCORSSR
Definition mrtk_eph.c:92
#define SYS_QZS
Definition mrtk_eph.c:69
#define STD_GAL_NAPA
Definition mrtk_eph.c:61
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)
Definition mrtk_eph.c:769
#define RE_GLO
Definition mrtk_eph.c:42
#define MAXECORSSR
Definition mrtk_eph.c:91
void alm2pos(gtime_t time, const alm_t *alm, double *rs, double *dts)
Compute satellite position and clock bias with almanac.
Definition mrtk_eph.c:185
#define MU_GAL
Definition mrtk_eph.c:45
#define MAXDTOE_IRN
Definition mrtk_eph.c:79
#define OMGE_CMP
Definition mrtk_eph.c:51
#define MAXAGESSR
Definition mrtk_eph.c:93
int get_ssr_ch_idx(void)
Get current SSR channel index.
Definition mrtk_eph.c:766
static void deq(const double *x, double *xdot, const double *acc)
Definition mrtk_eph.c:131
#define SQR(x)
Definition mrtk_eph.c:40
#define STD_BRDCCLK
Definition mrtk_eph.c:95
#define MAXDTOE_SBS
Definition mrtk_eph.c:80
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.
Definition mrtk_eph.c:940
#define MAX_ITER_KEPLER
Definition mrtk_eph.c:59
#define MAXDTOE_QZS
Definition mrtk_eph.c:75
#define MU_GPS
Definition mrtk_eph.c:43
#define SYS_IRN
Definition mrtk_eph.c:71
#define MAXDTOE_CMP
Definition mrtk_eph.c:77
static double var_urassr(int ura)
Definition mrtk_eph.c:453
void seph2pos(gtime_t time, const seph_t *seph, double *rs, double *dts, double *var)
Compute satellite position and clock with SBAS ephemeris.
Definition mrtk_eph.c:428
static seph_t * selseph(gtime_t time, int sat, const nav_t *nav)
Definition mrtk_eph.c:613
#define SYS_CMP
Definition mrtk_eph.c:70
static int satpos_sbas(gtime_t time, gtime_t teph, int sat, const nav_t *nav, double *rs, double *dts, double *var, int *svh)
Definition mrtk_eph.c:727
#define SYS_GAL
Definition mrtk_eph.c:68
static int _ssr_ch_idx
Definition mrtk_eph.c:760
#define EPHOPT_BRDC
Definition mrtk_eph.c:83
#define SYS_GLO
Definition mrtk_eph.c:67
#define EPHOPT_SBAS
Definition mrtk_eph.c:85
double eph2clk(gtime_t time, const eph_t *eph)
Compute satellite clock bias with broadcast ephemeris (GPS/GAL/QZS).
Definition mrtk_eph.c:232
int sbssatcorr(gtime_t time, int sat, const nav_t *nav, double *rs, double *dts, double *var)
Definition mrtk_sbas.c:1047
static void glorbit(double t, double *x, const double *acc)
Definition mrtk_eph.c:150
#define COS_5
Definition mrtk_eph.c:54
#define ERREPH_GLO
Definition mrtk_eph.c:56
#define MU_GLO
Definition mrtk_eph.c:44
#define MAXDTOE_GLO
Definition mrtk_eph.c:78
#define EPHOPT_SSRCOM
Definition mrtk_eph.c:87
#define MAXDTOE_GAL
Definition mrtk_eph.c:76
eph_t * seleph(gtime_t time, int sat, int iode, const nav_t *nav)
Select broadcast ephemeris by satellite and IODE.
Definition mrtk_eph.c:465
MRTKLIB Broadcast Ephemeris Module — Satellite orbit/clock types and Kepler/GLONASS/SBAS orbit comput...
struct nav_s nav_t
Definition mrtk_eph.h:40
#define MAXOBS
#define SSR_CH_NUM
void cross3(const double *a, const double *b, double *c)
Cross product of 3D vectors.
Definition mrtk_mat.c:172
double norm(const double *a, int n)
Euclidean norm of vector.
Definition mrtk_mat.c:165
int normv3(const double *a, double *b)
Normalize 3D vector.
Definition mrtk_mat.c:183
double dot(const double *a, const double *b, int n)
Inner product of vectors.
Definition mrtk_mat.c:151
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.
Definition mrtk_peph.c:864
void satantoff(gtime_t time, const double *rs, int sat, const nav_t *nav, double *dant)
Compute satellite antenna phase center offset in ecef.
Definition mrtk_peph.c:785
double timediff(gtime_t t1, gtime_t t2)
Compute time difference (t1 - t2).
Definition mrtk_time.c:279
gtime_t timeadd(gtime_t t, double sec)
Add seconds to gtime_t.
Definition mrtk_time.c:265
char * time_str(gtime_t t, int n)
Get time string (not reentrant).
Definition mrtk_time.c:530
void trace(mrtk_ctx_t *ctx, int level, const char *format,...)
Output trace message.
Definition mrtk_trace.c:78
MRTKLIB Trace Module — debug trace and logging functions.
GPS/GAL/QZS/BDS/IRN almanac type.
Definition mrtk_eph.h:49
gtime_t toa
Definition mrtk_eph.h:54
double e
Definition mrtk_eph.h:55
double i0
Definition mrtk_eph.h:55
double M0
Definition mrtk_eph.h:55
double toas
Definition mrtk_eph.h:56
double A
Definition mrtk_eph.h:55
int sat
Definition mrtk_eph.h:50
double OMGd
Definition mrtk_eph.h:55
double f0
Definition mrtk_eph.h:57
double OMG0
Definition mrtk_eph.h:55
double f1
Definition mrtk_eph.h:57
double omg
Definition mrtk_eph.h:55
GPS/GAL/QZS/BDS/IRN broadcast ephemeris type.
Definition mrtk_eph.h:77
double OMG0
Definition mrtk_eph.h:90
double omg
Definition mrtk_eph.h:90
int sat
Definition mrtk_eph.h:78
double OMGd
Definition mrtk_eph.h:90
double f1
Definition mrtk_eph.h:94
double f0
Definition mrtk_eph.h:94
int svh
Definition mrtk_eph.h:81
double e
Definition mrtk_eph.h:90
double idot
Definition mrtk_eph.h:90
double M0
Definition mrtk_eph.h:90
double A
Definition mrtk_eph.h:90
double cis
Definition mrtk_eph.h:91
gtime_t toe
Definition mrtk_eph.h:88
gtime_t toc
Definition mrtk_eph.h:88
double cic
Definition mrtk_eph.h:91
double cus
Definition mrtk_eph.h:91
double cuc
Definition mrtk_eph.h:91
double toes
Definition mrtk_eph.h:92
int code
Definition mrtk_eph.h:83
double crs
Definition mrtk_eph.h:91
double i0
Definition mrtk_eph.h:90
int iode
Definition mrtk_eph.h:79
int sva
Definition mrtk_eph.h:80
double deln
Definition mrtk_eph.h:90
double crc
Definition mrtk_eph.h:91
double f2
Definition mrtk_eph.h:94
GLONASS broadcast ephemeris type.
Definition mrtk_eph.h:111
double vel[3]
Definition mrtk_eph.h:121
gtime_t toe
Definition mrtk_eph.h:118
double pos[3]
Definition mrtk_eph.h:120
int iode
Definition mrtk_eph.h:113
double gamn
Definition mrtk_eph.h:123
double acc[3]
Definition mrtk_eph.h:122
int svh
Definition mrtk_eph.h:115
double taun
Definition mrtk_eph.h:123
int sat
Definition mrtk_eph.h:112
GNSS time representation.
Definition mrtk_time.h:49
time_t time
Definition mrtk_time.h:50
eph_t * eph_prev
Definition mrtk_nav.h:401
int ng
Definition mrtk_nav.h:394
sbssat_t sbssat
Definition mrtk_nav.h:431
seph_t * seph
Definition mrtk_nav.h:408
geph_t * geph
Definition mrtk_nav.h:407
ssr_t ssr_ch[SSR_CH_NUM][MAXSAT]
Definition mrtk_nav.h:434
eph_t * eph
Definition mrtk_nav.h:400
int ns
Definition mrtk_nav.h:395
int n
Definition mrtk_nav.h:393
Observation data record.
Definition mrtk_obs.h:44
sbssatp_t sat[MAXSAT]
Definition mrtk_nav.h:140
int nsat
Definition mrtk_nav.h:138
sbslcorr_t lcorr
Definition mrtk_nav.h:133
SBAS ephemeris type.
Definition mrtk_eph.h:130
int sva
Definition mrtk_eph.h:134
double pos[3]
Definition mrtk_eph.h:136
double vel[3]
Definition mrtk_eph.h:137
double acc[3]
Definition mrtk_eph.h:138
double af0
Definition mrtk_eph.h:139
double af1
Definition mrtk_eph.h:139
int sat
Definition mrtk_eph.h:131
gtime_t t0
Definition mrtk_eph.h:132
int svh
Definition mrtk_eph.h:135
double dclk[3]
Definition mrtk_nav.h:185
double ddeph[3]
Definition mrtk_nav.h:184
double hrclk
Definition mrtk_nav.h:186
gtime_t t0[6]
Definition mrtk_nav.h:176
int iod[6]
Definition mrtk_nav.h:178
int iode
Definition mrtk_nav.h:179
double deph[3]
Definition mrtk_nav.h:183
double udi[6]
Definition mrtk_nav.h:177
int ura
Definition mrtk_nav.h:181