Support for Advanced Navigation ANPP format#861
Conversation
020b239 to
b4f5fd4
Compare
|
Hi @rtklibexplorer. This is my first PR to RTKLIB. I'm curious if there is any procedure you have for reviewing/merging, and what standard of testing you expect for incoming PRs. |
|
|
||
| /* map ANPP (sys, freq_code) to rtklib observation code ---------------------*/ | ||
| static uint8_t anpp2code(uint8_t anpp_sys, uint8_t freq_code) | ||
| { |
There was a problem hiding this comment.
Perhaps add all the documented signals. For BDS it appears to be just B1 B2 B3 and might the following not be the most relevant reference. Would they limit Trimble receiver processing to just these signals, and BDS2 has been largely retired now and there is no reference to the B1C / B2A signals. For QZSS there is no definition for L1C/B for J04 and J08. This reference looks a little stale.
https://docs.advancednavigation.com/boreas-d/ANPP/RawSatelliteDataPacket.htm#Raw_Satellite_Data_Packet
There was a problem hiding this comment.
Will add. From the bottom of that page: © 2026 Advanced Navigation. All Rights Reserved. Version:2.5.1 Date: 2026-03-24. I know for a fact that it contains the latest version of the messages for 60 and 61 because the firmware including them was recently updated. That being said, I don't discount the possibility that a more recent source is available, so will look around.
There was a problem hiding this comment.
Also, I have an off-by-one here
There was a problem hiding this comment.
I've cut the Gordian knot here and reached out directly to the source (Advanced Navigation). Hoping this will get resolved soon, since I frankly don't know enough to get these mappings absolutely right.
83d180b to
e6fb96d
Compare
|
@ourairquality I've addressed as much of your feedback as I could for the moment. Waiting for feedback from Advanced Navigation. In the meantime, I've continued testing this with the |
| case ANPP_SYS_GPS: | ||
| switch (freq_code) { | ||
| case 1: return CODE_L1C; /* L1 C/A */ | ||
| case 2: return CODE_L1C; /* L1 C */ |
There was a problem hiding this comment.
L1 C is likely rinex L1L (or L1S or L1X)
| case 1: return CODE_L1C; /* L1 C/A */ | ||
| case 2: return CODE_L1C; /* L1 C */ | ||
| case 3: return CODE_L1P; /* L1 P */ | ||
| case 4: return CODE_L1M; /* L1 M */ |
There was a problem hiding this comment.
While this might really be L1M, for non-mil it is likely rinex L1W.
| case 3: return CODE_L1P; /* L1 P */ | ||
| case 4: return CODE_L1M; /* L1 M */ | ||
| case 5: return CODE_L2C; /* L2 C */ | ||
| case 6: return CODE_L2P; /* L2 P */ |
There was a problem hiding this comment.
Guess rinex L2W, except dup of L2M below?
| case 5: return CODE_L2C; /* L2 C */ | ||
| case 6: return CODE_L2P; /* L2 P */ | ||
| case 7: return CODE_L2M; /* L2 M */ | ||
| case 8: return CODE_L5X; /* L5 */ |
There was a problem hiding this comment.
If their receiver is Trimble based then 5X otherwise guess L5Q.
| case 3: return CODE_L1P; /* G1 P */ | ||
| case 5: return CODE_L2C; /* G2 C/A */ | ||
| case 6: return CODE_L2P; /* G2 P */ | ||
| case 8: return CODE_L3X; /* G3 */ |
There was a problem hiding this comment.
Guess L3X for Trimble otherwise L3Q.
| case 4: return CODE_L1M; /* L1 M */ | ||
| case 5: return CODE_L2C; /* L2 C */ | ||
| case 6: return CODE_L2P; /* L2 P */ | ||
| case 7: return CODE_L2M; /* L2 M */ |
| case 1: return CODE_L1C; /* L1 C/A */ | ||
| case 2: return CODE_L1C; /* L2 C */ | ||
| case 3: return CODE_L1Z; /* L1 SAIF */ | ||
| case 5: return CODE_L2X; /* L2 C */ |
There was a problem hiding this comment.
Trimble L2X otherwise guess L2L (or L2S).
| case 2: return CODE_L1C; /* L2 C */ | ||
| case 3: return CODE_L1Z; /* L1 SAIF */ | ||
| case 5: return CODE_L2X; /* L2 C */ | ||
| case 6: return CODE_L6X; /* LEX */ |
| case 3: return CODE_L1Z; /* L1 SAIF */ | ||
| case 5: return CODE_L2X; /* L2 C */ | ||
| case 6: return CODE_L6X; /* LEX */ | ||
| case 8: return CODE_L5Z; /* L5 ?? */ |
|
Imported the patch into my branch and updated as to personal preference, the raw buffer access with bounds checking, avoiding the pointer arithmetic, the signals mapping guess, also noted a few other integration issues, and reworked a little. Are there anpp files that can be shared for testing? |
I am sure I can find some non-proprietary stuff that I can share next week. |
Format defined here: https://docs.advancednavigation.com/boreas-d/ANPP/Advanced%20Navigation%20Packet.htm
This implementation only handles the raw satellite measurements, not the entire protocol.
Receiver selection is done in the same way as for SBF format: the
optfield is searched for-RCVR{n}, wherenmust be an integer in the range [0-255] since ANPP theoretically supports that many antennae per unit.Testing
Compared raw output from Boreas D-90 parsed with https://github.com/saronic-technologies/liban-rs/ (see saronic-technologies/liban-rs#18) to result of parsing with rust bindings to this library in https://github.com/kpwebb/rtklib-ffi/ (see joe-saronic/rtklib-ffi#1). Verified that obs fragments are handled correctly.
Inspected output of convbin from two receivers in a well-known dataset to ensure correct numbers of observations, constellations, etc. Main dataset can not be provided, but a small edited sample is available in the integration tests of the rust wrapper.