New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
GPS position precision #386
Comments
Honestly, with the base code, I was having similar issues as you. I've made a TON of modifications to my code to work better (but also rewritten it in c++, made it full realtime and added a full gRPC interface/web interface). Because of my mods, it's not really possible to do a pull request. The issue was unrelated to clock source for me. Even my $800 DS Instruments external TCXO wouldn't keep a steady lock on satellites. In UBLOX U-Center, I would watch the residual error drop and drop until it resets. (NOTE - I'm talking specifically about an external clock. The one that comes with the HackRF is NOT good enough, and no amount of software changes will help that one. I'm saying even after getting a good clock, I've modified the software a bit). With my changes, I'm able to run a stable fix at even 3MHz sample rate with a HackRF. Residual errors all remain ~= 0.5, and my PDOP ~= 1.7 and HDOP ~=1.0. And when I say I've done "a TON of work", most of that work as learning how GPS works. This code base is still amazing. After months of digging, I've narrowed it down to a few things that could be added for better long-term tracking.
Notice how instead of computing a rate using position, I'm instead using the computed one from the range_t (which includes the clock errors).
My theory (which is likely very wrong) is that there are 2 parts to clocks - their stability and their aging rate. Stability is the most important part in making sure that all samples get transmitted at a stable rate. They will state that their clocks will be within 0.1 ppm over all temperature ranges which is great. However, we have to account for the clock age rate in the sim. For example - this clock I was using states it has a daily aging rate of +/- 1 PPB, and a yearly rate of +/- 50 PPB. Note - the aging isn't a linear line....it tends to be the highest in the first few years of the clock. Thus, my correction of -13.95 ns (or about -14PPB) doesn't seem that far fetched for me. The only reason I don't fully buy into my own logic is that this same offset works well for ALL of my clocks I have. As for how this can help you now, I'd try changing your ephemeris clock errors to all be 0.0 and adding an offset similar to how it was done in issue 192. I think I'd make this offset be a command line input since I think this value depends on hardware. (i.e. Ivan subtracted 0.84 m/s where I had to subtract nearly 4 m/s. The easiest way for me to know what my offset should be was to watch the residual errors in Ublox (UBX - NAV - SAT) until they stopped drifting. I think this single change alone would help you the most....but you'll have to play around to see what the actual value should be. There is a small bug in the ionosphere calculation lines 1198 and 1206 (https://github.com/osqzss/gps-sdr-sim/blob/master/gpssim.c#L1198), its mixing radians and semicircles in calculations. Line 1198 should divide azel[0] by pi and 1206 should also divide by pi (then not divide phi_i by pi). Basically, either make them ALL semicircles, or convert the values to all Radians (i.e. the constants of 0.0137/(E + 0.11) - 0.022 could instead be in radians). But honestly, because the current code only applies ionosphere to the pseudorange, fixing this won't change a whole lot in terms of drifting. |
FWIW, I did a fair bit of work exhaustively comparing the group/phase pseudorange observables to the same observables computed using the open source GNSS toolkit GPStk. The GPStk calculation are in agreement with truth rinex data reported by commercial simulators at the mm-level. What I discovered in this analysis is that the calculation of light time by gps-sdr-sim is a simplification which is understandable if you're trying to compute quantities in real-time or perform the calculations quickly. For stationary receivers grounded to the Earth, the direct form of the light time calculation implemented by gps-sdr-sim is a reasonable approximation. But if you're simulating a receiver in an accelerated frame of reference (drone or worst case LEO satellite) the range rate accuracy is going to deteriorate. I suspect this is at least part of the range rate issue you talked about above. Generally, light time has to be computed in a higher order fashion (e.g. iteratively) rather than the direct manner applied by gps-sdr-sim. |
@KingofTown Thank you for the comprehensive response. Do you have your rewritten code available somewhere, or is it strictly proprietary now? :) I just soldered rf shield and I'm getting repeating patterns on the same data executed multiple times, so it points to the simulator code... Strange is that I'm getting the right position with a random android phone in non-conductive mode... But maybe u-blox gps receivers are too wily and do some too smart things that ... Were you playing with u-blox device as well? |
I've tested with a Gen 8 ublox, a Gen 9 ublox and various other receivers I could get my hands on. UBlox was nice in that it was easy to see Residual errors. I would just add a value into this line in the code: https://github.com/osqzss/gps-sdr-sim/blob/master/gpssim.c#L1324 Then re-run to see if it's more stable. Maybe try starting by adding 4.5 to that value and see how it affects the output. I don't think I can upload my code as there is a lot of other stuff that wouldn't be allowed, but I can show my functions. My current calibration settings are:
Then I've modified the computeRange function to instead calculate the range-rate and store it in range_t so that the first order clock errors get included. In addition, I add my own clock errors to the range-rate here as well.
Then in computeCodePhase() - you just use use the computed range-rate instead of doing the math
I added a few more fields to range_t to store the tropo and iono delay, but I don't think those have a huge effect outside of accuracy. The biggest one is not incorporating clk[1] into the range-rate, and also not correcting for the sim clock drift in range-rate as these affect the perceived speed of light causing receivers to drift away. All of my other changes make it so the computed position on receivers matches to at least 5 decimal places in lat/lon or higher. Now, the biggest source of error is due to WGS-84 model (sim and receiver are both estimating the earth shape which compounds the errors). At the equator, my output is much more stable compared to near the poles. |
TLDR: gps-sdr-sim -> HackRF -> ublox GPS: drifts for dozens of meters in static and also dynamic mode, sometimes looses fix
Setup
I tried multiple configurations. But always similar scenario:
Schematic
HackRF one rev. 9:
TX gains - I tried multiple so that I see satellites with SNR around 30 to 55 dB. And tried to skip one 30 dB attenuator.
I have TXC0 installed and HackRF should know about that and hopefully use it.
I also tried multiple sample rates e.g.
I also tried to play with ppm correction, but when I try more than +-1 ppm, I'm not getting fix at all or loosing more often.
And now, I'm quite out of ideas what else to try.
Expected behavior
Get fix in a few minutes and simulate precise location (+- a few meters at maximum).
Issues
In any configuration I tried, I'm able to get 3D fix. However, the position is always drifting quite a lot (see pic). Usually after cold start, I get right position, which holds for a few minutes. But then it starts to walk around expected position in both static and dynamic modes. Sometimes, I also lose fix. Altitude is almost always wrong. When I repeat the same simulation, the drift is always different.
Here, scale is missing, but the square in the middle is 100m × 100m.
Questions
Thank you
The text was updated successfully, but these errors were encountered: