{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"pygments_lexer":"ipython3","nbconvert_exporter":"python","version":"3.6.4","file_extension":".py","codemirror_mode":{"name":"ipython","version":3},"name":"python","mimetype":"text/x-python"}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"<style>\nimg {\n  display: block;\n  margin-left: auto;\n  margin-right: auto;\n}\n</style>\n\n## Accumulated Delta Range (ADR) \nThis is another range measurement from GNSS satellites besides pseudorange (illustrated as the figure below). ADR measures the change in phase of the carrier wave (ADR's alias is carrier phase). Hence ADR is theoretically ~1000x more precise than the pseudorange. While pseudorange is measured by CDMA code (each chip/resolution is 300m for GPS L1), ADR measures a fraction of a carrier cycle, which is 19-centimeter long for GPS L1!\n\n<img src=\"https://storage.googleapis.com/kagglesdsdata/datasets/1477671/2441865/pseudorange_adr_illustration.png?X-Goog-Algorithm=GOOG4-RSA-SHA256&X-Goog-Credential=databundle-worker-v2%40kaggle-161607.iam.gserviceaccount.com%2F20210719%2Fauto%2Fstorage%2Fgoog4_request&X-Goog-Date=20210719T154301Z&X-Goog-Expires=345599&X-Goog-SignedHeaders=host&X-Goog-Signature=6f2185adce7d5195ad59f4dad0dbd99d0973a71f7bae7383f7f9d9ab257495be90fb57ce300cdd2e7a9bf653920805ea0b1fd44a30dba158f4afcc7c84b82f0346f472571e72e7ebd99d6e85758145ad8d5bd1b47fae6cccfa42eff9723f6658be8b821ab897e8f1745fe26854bb5ed8b3d94a797a8f337a2daf3a74887fa35ea0192f99ed178923cc4db309c6ebfcd34af04b8308fc8d40db541ae439684272797f08d67538131adab6d4d679646c84bad41024987b105c7538a3473a18c46663b5a656ce61bd9681038b85917b84b98ce47aea9c1e54affc5268d76ec9786a452af7b51f65ace0937780bf11c086fb697bea01c1b28cb30ef426e39543e17e\" alt=\"Pr vs ADR illustration\" style=\"width:80%;\"/>\n<span style=\"font-size:0.7em;\">(Image credit: \"GPS, Signals, Measurements, and Performance\", P.Misra, P.Enge, 2001.)</span>\n\n\n\nThis sounds great, but why isn't our GPS in the phone giving us centimeter-level positioning accuracy? That's because ADR is not a full range, instead, it is a delta range. ADR measures the change in range from the carrier phase, but remains unknown the rest of the full range (i.e. the total number of carrier cycles from the satellite antenna to the receiver antenna). At every subsequent epoch, ADR reports this delta range, until a cycle slip happens in the GPS receiver circuit. The ADRs before and after the cycle slip cannot be combined directly, because they don't have the same starting point.\n\nDue to the nature of delta range and cycle slips, ADR can be used to improve the location accuracy via special techniques:\n\n\n### Smoothing\n\nThe change of ADR (i.e. ADR(t) - ADR(t-1)) can be used as a precise measure of the change of the pseudorange. Based on this principle, the smoother can correct the pseudorange to reduce its noise. This [webpage](https://gssc.esa.int/navipedia/index.php/Carrier-smoothing_of_code_pseudoranges) details the smoothing algorithm.\n\n\n### Compute delta position\n\nSince the ADR is not a full range, using it alone will not result in  estimating an absolute position either. Instead, we can use its change (i.e. delta\\_ADR = ADR(t) - ADR(t-1)) to estimate a delta position from t-1 to t. Specifically, delta\\_pos (i.e. xyz(t) - xyz(t-1)) is a function of delta\\_ADR, which can be derived by the scripts below. Notice that the result is the position change and it needs to be offset to some absolute starting coordinate to become an absolute position. The following pictures show our previous trace using a Pixel 4.\n\n<left><img src=\"https://storage.googleapis.com/kagglesdsdata/datasets/1477671/2441930/Google_logo_real.jpeg?X-Goog-Algorithm=GOOG4-RSA-SHA256&X-Goog-Credential=databundle-worker-v2%40kaggle-161607.iam.gserviceaccount.com%2F20210719%2Fauto%2Fstorage%2Fgoog4_request&X-Goog-Date=20210719T160109Z&X-Goog-Expires=345599&X-Goog-SignedHeaders=host&X-Goog-Signature=048da2eeaf14e05702b46d9ca88b11bb546618cd1f83cde2ec4ed57e150217ae3f0068b99051c5d029a3aa130de3422de98dff8065cbb2f3c0fc1ca5659e2525ae388e73b96a4f17c0c05b058c48b1bb765737a92db0f629ea606c36f9577547aba27b3d31ba172f09fd151b41627190e80ef65c705a76c476cdd62e7b94b6b8c65066f872ac3ddfb43c9682f77612fff54e6014809b74c14d2909519d700f235d0eed024d3900e851af3eb6142c4941bf1a4754cee99620302cd900f6bfcb9125180def991d06cb0e80090b2bee988596a35c562da8847c5e4afc20e38cf09754620529331e813a36685fe0ba176a979f0e1fac8cfc85167ba1094f63f8a6d0\" alt=\"Google logo real\" style=\"width:50%;\"/></left> \n<right><img src=\"https://storage.googleapis.com/kagglesdsdata/datasets/1477671/2441930/Google_logo_result.png?X-Goog-Algorithm=GOOG4-RSA-SHA256&X-Goog-Credential=databundle-worker-v2%40kaggle-161607.iam.gserviceaccount.com%2F20210719%2Fauto%2Fstorage%2Fgoog4_request&X-Goog-Date=20210719T160212Z&X-Goog-Expires=345599&X-Goog-SignedHeaders=host&X-Goog-Signature=4f00135daf2f7fe6d7488b247262478730f57fe26921bed727c791d90b57e0edd7594a29ef632838a635e2e7e729a4f50ebbd744f456dc421982895d0855f5bc2cbbce424ab559ae3a7f32683917b747f0076511977ab5659aae7360ed24f6e69c2066e8d3c0cf6cc3309bb4b01ace737a8c9807f551cfe7883c378b8627dbcf5f4124ddfdb6d311a5ac2b5fd1219de1786062793e4b25914fff6732c9eb37ebf828819e867aa4f4c7484fd0a7f7b53299be3504da042da59d87dc513f7e69853caa1cee4ad3d206714694d615906f6e9f24de1b66cf0020c1cf3315220d6d2fc3eefc3bda4cf947d2be18c4f933901ac82c816e0a73cf154d3bd24e86483eb1\" alt=\"Google logo result\" style=\"width:50%;\"/></right> \n","metadata":{}},{"cell_type":"code","source":"adrm_col_idx = col_to_idx('AccumulatedDeltaRangeMeters')\nadrm_unc_col_idx = col_to_idx('AccumulatedDeltaRangeUncertaintyMeters')\ncorrected_delta_adr_mps[rows_with_adr_support] = (\n   df_cur_epoch.iloc[rows_with_adr_support, adrm_col_idx].to_numpy() -\n   df_prev_epoch.iloc[rows_with_adr_support, adrm_col_idx].to_numpy())/delta_t_sec\ncorrected_delta_adr_unc_mps[rows_with_adr_support] = df_cur_epoch.iloc[\n       rows_with_adr_support, adrm_unc_col_idx] / delta_t_sec\n\n# Add final corrections to corrected_delta_adr_mps\ndelta_atmos_delay_mps = (\n     (df_cur_epoch['IonoDelayM'] + df_cur_epoch['TropoDelayM']).to_numpy() -\n     (df_prev_epoch['IonoDelayM'] +\n      df_prev_epoch['TropoDelayM']).to_numpy()) / delta_t_sec\n\n# TODO: if using ADR, compute delta's between epochs. If just doppler, use point estimates for velocities.\nclock_drift_mps = (df_cur_epoch['SatClkBiasM'].to_numpy() -\n                    df_prev_epoch['SatClkBiasM'].to_numpy()) / delta_t_sec\n\ncorrected_delta_adr_mps = corrected_delta_adr_mps + clock_drift_mps - delta_atmos_delay_mps","metadata":{"_kg_hide-output":true},"execution_count":null,"outputs":[]}]}