Skip to content

Conversation

@plutonheaven
Copy link
Collaborator

@plutonheaven plutonheaven commented May 6, 2025

When comparing satellite position computed by prx and rtklib, some meter-level difference was observed, mainly present in the along-track direction.

This may be due to ignoring satellite clock offset in the query time for satellite position computation.

edit after solving the issue:
The difference is due to 2 factors:

  • ignoring satellite clock offset in the query time for satellite position computation
  • selecting different ephemerides: a duplicate ephemerides cleaning process has been implemented based on the comparison of time of ephemerides and time of transmission in GPS ephemerides datasets.

Only the first issue will be solved in this PR. The other will be dealt with in another one.

@plutonheaven
Copy link
Collaborator Author

Before toe correction:
position_difference_without_toe_correction

After toe correction:
position_difference_with_toe_correction

There is still an along-track bias, but all errors are grouped around the same values.

@jtec
Copy link
Owner

jtec commented May 7, 2025

Another thought: Is there a way to compare ephemeris IODs? Although if that was the issue we'd see probably large errors in cross-track and radial.

per_signal_query = compute_clock_offsets(per_signal_query)

# Apply sat clock correction to the query time for satellite position computation
per_signal_query.query_time_wrt_ephemeris_reference_time_s -= (
Copy link
Owner

@jtec jtec May 7, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We're making the hypothesis here that clock error changes so slowly, that computing it at the time of emission biased by sat clock error introduces negligible error, right? Or do we need a loop here that iteratively computes a corrected time of emission?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added a 2-iteration refinement of the toe, but the results are identical. I'll still keep this, since it's implemented as such in rtklib.

per_signal_query = compute_clock_offsets(per_signal_query)

# Apply sat clock correction to the query time for satellite position computation
per_signal_query.query_time_wrt_ephemeris_reference_time_s -= (
Copy link
Owner

@jtec jtec May 7, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does the difference get larger when doing += here?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried with a += and it was worse. -= should be correct.

@plutonheaven
Copy link
Collaborator Author

After computing the toe iteratively, I have the same error signature.
position_difference_with_toe_correction_iteration

I'm out of ideas.

@plutonheaven
Copy link
Collaborator Author

Another thought: Is there a way to compare ephemeris IODs? Although if that was the issue we'd see probably large errors in cross-track and radial.

Not easily. I am using the same RINEX NAV file, and the OBS data span only 5 minutes. I'd guess that we would choose the same ephemeris set...

@plutonheaven
Copy link
Collaborator Author

I think the impact of the difference is minimal, since we are using the along-track is orthogonal to the line-of-sight vector. But it still bother me to not understand precisely why we have this difference.

I'll let the PR open a few more days to think about it.

@jtec
Copy link
Owner

jtec commented May 8, 2025

I also wonder - assuming that rtklib is wrong, would anyone even notice? How is rtklib testing the orbit computations? Does anyone do PPP using rtklib? And even then, given that the line-of-sight diff is so small, would a PPP user notice?

I guess the only way to really know is to run rtklib in debug mode (or add a few printfs) and look at intermediate values, first probably time of emission.

Can it be time datatype resolution? We use a pandas Timestamp/Timedelta which is backed by a nanosecond-resolution uint64 I believe, and we are looking at an issue of the order of milliseconds here, so probably not.

What about the line where we divide pseudorange by the speed of light to remove time of flight - can that introduce a floating-point resolution issue, given that both numbers are pretty big ones?

@jtec
Copy link
Owner

jtec commented May 9, 2025

Running

(1e7 / 1e8) - (np.nextafter(1e7, np.inf) / np.nextafter(1e8, 0))

1e7 being the order of magnitude of pseudoranges and 1e8 being the order of magnitude of the speed of light

gives me -2.7755575615628914e-17, suggesting that the division here is indeed not the issue.

@jtec
Copy link
Owner

jtec commented May 9, 2025

@plutonheaven It looks like the difference is exactly 0 (or just very small?) for one of the QZSS satellites - can we use that to better understand this by looking at what is different between J03 and J07?

@jtec
Copy link
Owner

jtec commented May 9, 2025

I see unit tests for GLONASS ephemerides here https://github.com/tomojitakasu/RTKLIB/blob/c033e62bcd311e4b3dcb8430a89597cc21be9f0b/test/utest/t_gloeph.c, nothing that compares with an expected broadcast orbit position though. And even then, if time of emission is off, a test of that kind wouldn't catch it.

Still looking for where rtklib computes time-of-emission.

@plutonheaven
Copy link
Collaborator Author

The toe computation in rtklib is here: https://github.com/tomojitakasu/RTKLIB/blob/71db0ffa0d9735697c6adfd06fdf766d0e5ce807/src/ephemeris.c#L739

There is a python version of rtklib, which is quite reliable and the toe is computed there: https://github.com/rtklibexplorer/rtklib-py/blob/5d8968d85902b94e29e5b221e5f7ba35b22ca8a4/src/ephemeris.py#L265

@plutonheaven
Copy link
Collaborator Author

About the order of magnitude of the error on the toe, 1.6 m on the along-track axis of a satellite moving at 4 km/s is 1.6 / 4e6 = 4e-7 seconds (0.4 µs). Converted in meters, this would relate to 4e-7 * 3e8 = 120 meters.
This means that we are off applying an error of 0.4 µs or 120 meters to all satellites when computing the toe.

@plutonheaven
Copy link
Collaborator Author

@jtec I found the error: I was processing 2 different files 🤦 So much time wasted, i'm SO DUMB!!!!!

@plutonheaven
Copy link
Collaborator Author

Still, it's worth applying the sat clk correction for toe computation. It reduces the error by a few meters, so a useful update.

I'll write a nice test to complete the PR.

@plutonheaven
Copy link
Collaborator Author

plutonheaven commented May 9, 2025

There is one GPS satellite having a strange behaviour, I'll investigate later.

Before toe correction:
position_difference_without_toe_correction

After toe correction:
position_difference_with_toe_correction

@jtec
Copy link
Owner

jtec commented May 10, 2025

@plutonheaven That's great news pretty cool that we get the same positions after all! And definitely intriguing that one of the GPS sats still has 70 cm of difference - any idea what might be going on there? A satellite maneuvering and prx ignoring the ephemeris health bit or something?

@plutonheaven
Copy link
Collaborator Author

I bet on different iode

@plutonheaven
Copy link
Collaborator Author

plutonheaven commented May 12, 2025

Ok, I've seen where this difference comes from. The concerned satellite is G15 at epochs around 08:20:00.

G15 2024 06 24 07 59 44 1.736045815051e-04 4.206412995700e-12 0.000000000000e+00
     4.000000000000e+00-9.028125000000e+01 4.785199322759e-09-6.493624923029e-01
    -4.604458808899e-06 1.573454437312e-02 9.842216968536e-06 5.153677450180e+03
     1.151840000000e+05-1.396983861923e-07-2.820946273747e+00 1.899898052216e-07
     9.359883245393e-01 1.812500000000e+02 1.319706711607e+00-8.354633718315e-09
     3.239420649158e-10 1.000000000000e+00 2.320000000000e+03 0.000000000000e+00
     2.000000000000e+00 0.000000000000e+00-1.024454832077e-08 4.000000000000e+00
     1.146660000000e+05 4.000000000000e+00                                      
G15 2024 06 24 08 00 00 1.736055128276e-04 4.206412995700e-12 0.000000000000e+00
     1.120000000000e+02-9.028125000000e+01 4.785556480493e-09-6.470286903135e-01
    -4.604458808899e-06 1.573454204481e-02 9.842216968536e-06 5.153677459717e+03
     1.152000000000e+05-1.396983861923e-07-2.820946398095e+00 1.899898052216e-07
     9.359883245393e-01 1.812500000000e+02 1.319706609203e+00-8.354633718315e-09
     3.239420649158e-10 1.000000000000e+00 2.320000000000e+03 0.000000000000e+00
     2.000000000000e+00 0.000000000000e+00-1.024454832077e-08 1.120000000000e+02
     1.080180000000e+05 4.000000000000e+00

In the RINEX NAV file, there are two ephemerides sets, one valid at 08:00:00 and the other at 07:59:44.
prx choses the one at 08:00:00 and rtklib the one at 07:59:44.

When I force prx to choose the same one as rtklib, the difference is small.

@jtec: Any ideas why there are two so closely-spaced ephemerides in the NAV file ?

@plutonheaven
Copy link
Collaborator Author

I opened an issue on rtklib's repo: tomojitakasu/RTKLIB#765

@plutonheaven plutonheaven linked an issue May 20, 2025 that may be closed by this pull request
@plutonheaven
Copy link
Collaborator Author

Ok, I had some useful information from rtklib developers (Tomoji Takasu and Taro Suzuki!!) on rtklib's repository.

What happened in this file is that an ephemerides set was transmitted a few hours before, and later updated. However, the time of ephemerides t_oe of the new ephemerides was earlier the the one from the older ephemerides, resulting in the selection of the old ephemeris.

A process to remove "duplicate" ephemerides based on the closeness of the t_oe and selecting the most recent one in terms of transmission time TransTime has been added, inspired by what is coded in MatRTKLIB

@plutonheaven plutonheaven marked this pull request as ready for review May 24, 2025 05:44
@plutonheaven plutonheaven requested a review from jtec May 24, 2025 05:45
}
)
query_with_ephemerides = select_ephemerides(ephemerides, query)
# The selected ephemerides should be the second one (ephemeris_hash=2), based on t_oe comparison,
Copy link
Owner

@jtec jtec Jun 2, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we'd want to emulate the behaviour of real-time ephemeris evaluation we'd select the one transmitted later, correct? Would that be a change we can make to achieve the same outcome?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Exactly. In the ephemeris selection, we would have to take into account both t_oe and TransTime. But in select_ephemerides, we implemented a really fast ephemeris selection, assuming that the t_oe is sorted.
So that is why I implemented the duplicate (or rather very close) ephemeris.

@plutonheaven
Copy link
Collaborator Author

@jtec, I found a solution to to mimic the ephemeris selection that a real-time receiver would do. However, I fear it may slow down the execution time. Will do some profiling once merging #178 has been merged.

@plutonheaven
Copy link
Collaborator Author

Hi @jtec, I revert the latest commits to focus only on the correction of the time of emission.
The part dealing with ephemerides selection will be dealt in a separate PR. Let's keep our PR small and focused!

@jtec
Copy link
Owner

jtec commented Jun 25, 2025

Hi @jtec, I revert the latest commits to focus only on the correction of the time of emission. The part dealing with ephemerides selection will be dealt in a separate PR. Let's keep our PR small and focused!

@plutonheaven I have a PR up that implements selecting ephemerides by time of transmission, there are still a few rough edges: https://github.com/jtec/prx/pull/179/files

@plutonheaven plutonheaven merged commit 05cd864 into main Jun 25, 2025
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Time-of-emission not corrected for sat clock offset

3 participants