{
  "id": 340693,
  "title": "26th Place solution",
  "url": "/competitions/smartphone-decimeter-2022/writeups/solverworld-26th-place-solution",
  "author_name": "",
  "post_date": "2022-07-30T16:46:54.843Z",
  "votes": 15,
  "comment_count": 5,
  "views": 0,
  "content": "<p>Thank you to all the competition organizers and the participants who shared their knowledge with the rest of us learning about GNSS.  Who knew GPS positioning was so complicated?</p>\n<p><strong>My solution was based on these 3 public notebooks and ideas:</strong></p>\n<ol>\n<li><p>\"WLS\" A solution based on \"Carrier-Smoothing-WLS-Kalman Filtering\" from<br>\n<a href=\"https://www.kaggle.com/saurabhbagchi\" target=\"_blank\">@saurabhbagchi</a> - <a href=\"https://www.kaggle.com/code/saurabhbagchi/carrier-smoothing-robust-wls-kalman-smootherv2\" target=\"_blank\">https://www.kaggle.com/code/saurabhbagchi/carrier-smoothing-robust-wls-kalman-smootherv2</a><br>\nwhich was based on<br>\n<a href=\"https://www.kaggle.com/taroz1461\" target=\"_blank\">@taroz1461</a> - <a href=\"https://www.kaggle.com/code/taroz1461/carrier-smoothing-robust-wls-kalman-smoother\" target=\"_blank\">https://www.kaggle.com/code/taroz1461/carrier-smoothing-robust-wls-kalman-smoother</a></p></li>\n<li><p>\"RTKLIB\" An RTKLIB  solution <a href=\"https://www.kaggle.com/timeverett\" target=\"_blank\">@timeverett</a> - <a href=\"https://www.kaggle.com/code/timeverett/getting-started-with-rtklib\" target=\"_blank\">https://www.kaggle.com/code/timeverett/getting-started-with-rtklib</a>.  I would especially like to commend RTKLIBExplorer for all his explanations and patience in answering many people's questions on RTKLIB.</p></li>\n<li><p>\"OFFSET\" An offset correction based on <a href=\"https://www.kaggle.com/saitodevelo01\" target=\"_blank\">@saitodevelo01</a> - <a href=\"https://www.kaggle.com/code/saitodevel01/gsdc-bias-correction\" target=\"_blank\">https://www.kaggle.com/code/saitodevel01/gsdc-bias-correction</a></p></li>\n</ol>\n<p><strong>I used the above algorithms as follows:</strong></p>\n<ol>\n<li><p>Starting with the WLS solution, which uses an L1 optimization at each point to determine the receiver clock bias and thus the best X,Y,Z ECEF coordinates, I replaced the Kalman smoother with a more complicated model as follows:<br>\nThere were 9 states: (3) x,y,z, (3) the velocities in x,y,z, (3) the accelerations in x,y,z.<br>\nThe measurements were position and velocity from the WLS algorithm (vel comes from doppler shift).<br>\nThe measurement noise was as determined from WLS, which comes from the device_gnss uncertainty in Pseudorange and Pseudorange velocity, using the Jacobian of the L1 solution.  I implemented Kalman Smoothing, which effectively runs the Kalman filter forward and backward, combining the results properly.  The authority for this is \"Applied Optimal Estimation\" by Art Gelb.  I tuned the process noise (Q) and thresholds (Mahalanobis) for throwing out measurements by simple trial and error.  I added the OFFSET solution above to this, but it seemed like the offset got smaller as my solutions got better, so in the end perhaps this did not make much difference.</p></li>\n<li><p>I generated the RTKLIB solution, and initially replaced the Q!=2 bad points it found with my solution from #1.  Since my #1 was better than the other publicly available solutions, this solution put me ahead of all the other people trying out RTKLIB for the first time  (Public LB 2.593)</p></li>\n<li><p>I wanted to be able to use the base positions from RTKLIB to improve point positioning so that I could run my Kalman smoother on it, but was never able to get that to work.</p></li>\n<li><p>I tried using the Ionosphere and Troposphere correction functions from RTKLIB instead of the ones from the device_gnss file, but did not see an improvement from that.</p></li>\n<li><p>I realized that some of the device_gnss entries has blanks for baseline prediction and pseudoranges, yet RTKLIB was able to make predictions.  Looking a little more closely, it seemed like you could generate pseudorange estimates from the timing numbers directly.  So I generated 2 new solutions using the RTKLIB observation data, but running it through the  WLS/Kalman Smoother algorithm.</p></li>\n<li><p>I then developed a merge algorithm that took multiple solutions with weights W and computed the weighted mean, where the weights for each point were W divided by the variance estimate at each point. The tricky part here was dealing with NaNs properly.  This method allowed me to remove the \"bad\" measurements from the RTKLIB solution, and other points I deemed to be outliers.  I found small improvements by tweaking the variance estimates.</p></li>\n<li><p>Running out of time, I did a simple search for the best weights to use, combining 4 solutions:<br>\n(a) RTKLIB, (b) My WLS/Smoother soln, (c) WLS from RTKLIB's observation data, and (d) Kalman Smoothed WLS<br>\nfrom RTKLIB.</p></li>\n<li><p>Then, really out of time and ideas, I did a quick computation to see if there was any lat/lon offset in my solution vs. the ground truth.  I found a very small offset and added that in as a correction, which resulted in about a .04 improvement.</p></li>\n</ol>\n<p><strong>Other notes:</strong><br>\nI never did any fitting to the Leaderboard.  All my calculations and improvements were done on the train set.  Every time (almost) I submitted a solution, it improved, roughly equaling the improvement on the train set.  I never picked parameters or methods based on feedback from the Leaderboard, I wanted to be \"clean\" from an overfitting perspective.</p>",
  "messages": [
    {
      "id": "1877311",
      "postDate": "07/30/2022 14:17:40",
      "content": "<p>Thank you to all the competition organizers and the participants who shared their knowledge with the rest of us learning about GNSS.  Who knew GPS positioning was so complicated?</p>\n<p><strong>My solution was based on these 3 public notebooks and ideas:</strong></p>\n<ol>\n<li><p>\"WLS\" A solution based on \"Carrier-Smoothing-WLS-Kalman Filtering\" from<br>\n<a href=\"https://www.kaggle.com/saurabhbagchi\" target=\"_blank\">@saurabhbagchi</a> - <a href=\"https://www.kaggle.com/code/saurabhbagchi/carrier-smoothing-robust-wls-kalman-smootherv2\" target=\"_blank\">https://www.kaggle.com/code/saurabhbagchi/carrier-smoothing-robust-wls-kalman-smootherv2</a><br>\nwhich was based on<br>\n<a href=\"https://www.kaggle.com/taroz1461\" target=\"_blank\">@taroz1461</a> - <a href=\"https://www.kaggle.com/code/taroz1461/carrier-smoothing-robust-wls-kalman-smoother\" target=\"_blank\">https://www.kaggle.com/code/taroz1461/carrier-smoothing-robust-wls-kalman-smoother</a></p></li>\n<li><p>\"RTKLIB\" An RTKLIB  solution <a href=\"https://www.kaggle.com/timeverett\" target=\"_blank\">@timeverett</a> - <a href=\"https://www.kaggle.com/code/timeverett/getting-started-with-rtklib\" target=\"_blank\">https://www.kaggle.com/code/timeverett/getting-started-with-rtklib</a>.  I would especially like to commend RTKLIBExplorer for all his explanations and patience in answering many people's questions on RTKLIB.</p></li>\n<li><p>\"OFFSET\" An offset correction based on <a href=\"https://www.kaggle.com/saitodevelo01\" target=\"_blank\">@saitodevelo01</a> - <a href=\"https://www.kaggle.com/code/saitodevel01/gsdc-bias-correction\" target=\"_blank\">https://www.kaggle.com/code/saitodevel01/gsdc-bias-correction</a></p></li>\n</ol>\n<p><strong>I used the above algorithms as follows:</strong></p>\n<ol>\n<li><p>Starting with the WLS solution, which uses an L1 optimization at each point to determine the receiver clock bias and thus the best X,Y,Z ECEF coordinates, I replaced the Kalman smoother with a more complicated model as follows:<br>\nThere were 9 states: (3) x,y,z, (3) the velocities in x,y,z, (3) the accelerations in x,y,z.<br>\nThe measurements were position and velocity from the WLS algorithm (vel comes from doppler shift).<br>\nThe measurement noise was as determined from WLS, which comes from the device_gnss uncertainty in Pseudorange and Pseudorange velocity, using the Jacobian of the L1 solution.  I implemented Kalman Smoothing, which effectively runs the Kalman filter forward and backward, combining the results properly.  The authority for this is \"Applied Optimal Estimation\" by Art Gelb.  I tuned the process noise (Q) and thresholds (Mahalanobis) for throwing out measurements by simple trial and error.  I added the OFFSET solution above to this, but it seemed like the offset got smaller as my solutions got better, so in the end perhaps this did not make much difference.</p></li>\n<li><p>I generated the RTKLIB solution, and initially replaced the Q!=2 bad points it found with my solution from #1.  Since my #1 was better than the other publicly available solutions, this solution put me ahead of all the other people trying out RTKLIB for the first time  (Public LB 2.593)</p></li>\n<li><p>I wanted to be able to use the base positions from RTKLIB to improve point positioning so that I could run my Kalman smoother on it, but was never able to get that to work.</p></li>\n<li><p>I tried using the Ionosphere and Troposphere correction functions from RTKLIB instead of the ones from the device_gnss file, but did not see an improvement from that.</p></li>\n<li><p>I realized that some of the device_gnss entries has blanks for baseline prediction and pseudoranges, yet RTKLIB was able to make predictions.  Looking a little more closely, it seemed like you could generate pseudorange estimates from the timing numbers directly.  So I generated 2 new solutions using the RTKLIB observation data, but running it through the  WLS/Kalman Smoother algorithm.</p></li>\n<li><p>I then developed a merge algorithm that took multiple solutions with weights W and computed the weighted mean, where the weights for each point were W divided by the variance estimate at each point. The tricky part here was dealing with NaNs properly.  This method allowed me to remove the \"bad\" measurements from the RTKLIB solution, and other points I deemed to be outliers.  I found small improvements by tweaking the variance estimates.</p></li>\n<li><p>Running out of time, I did a simple search for the best weights to use, combining 4 solutions:<br>\n(a) RTKLIB, (b) My WLS/Smoother soln, (c) WLS from RTKLIB's observation data, and (d) Kalman Smoothed WLS<br>\nfrom RTKLIB.</p></li>\n<li><p>Then, really out of time and ideas, I did a quick computation to see if there was any lat/lon offset in my solution vs. the ground truth.  I found a very small offset and added that in as a correction, which resulted in about a .04 improvement.</p></li>\n</ol>\n<p><strong>Other notes:</strong><br>\nI never did any fitting to the Leaderboard.  All my calculations and improvements were done on the train set.  Every time (almost) I submitted a solution, it improved, roughly equaling the improvement on the train set.  I never picked parameters or methods based on feedback from the Leaderboard, I wanted to be \"clean\" from an overfitting perspective.</p>",
      "rawMarkdown": "Thank you to all the competition organizers and the participants who shared their knowledge with the rest of us learning about GNSS.  Who knew GPS positioning was so complicated?\n\n**My solution was based on these 3 public notebooks and ideas:**\n\n1. \"WLS\" A solution based on \"Carrier-Smoothing-WLS-Kalman Filtering\" from\n@saurabhbagchi - https://www.kaggle.com/code/saurabhbagchi/carrier-smoothing-robust-wls-kalman-smootherv2\nwhich was based on\n@taroz1461 - https://www.kaggle.com/code/taroz1461/carrier-smoothing-robust-wls-kalman-smoother\n\n2. \"RTKLIB\" An RTKLIB  solution @timeverett - https://www.kaggle.com/code/timeverett/getting-started-with-rtklib.  I would especially like to commend RTKLIBExplorer for all his explanations and patience in answering many people's questions on RTKLIB.\n\n3. \"OFFSET\" An offset correction based on @saitodevelo01 - https://www.kaggle.com/code/saitodevel01/gsdc-bias-correction\n\n**I used the above algorithms as follows:**\n\n1. Starting with the WLS solution, which uses an L1 optimization at each point to determine the receiver clock bias and thus the best X,Y,Z ECEF coordinates, I replaced the Kalman smoother with a more complicated model as follows:\n   There were 9 states: (3) x,y,z, (3) the velocities in x,y,z, (3) the accelerations in x,y,z.\n   The measurements were position and velocity from the WLS algorithm (vel comes from doppler shift).\n   The measurement noise was as determined from WLS, which comes from the device_gnss uncertainty in Pseudorange and Pseudorange velocity, using the Jacobian of the L1 solution.  I implemented Kalman Smoothing, which effectively runs the Kalman filter forward and backward, combining the results properly.  The authority for this is \"Applied Optimal Estimation\" by Art Gelb.  I tuned the process noise (Q) and thresholds (Mahalanobis) for throwing out measurements by simple trial and error.  I added the OFFSET solution above to this, but it seemed like the offset got smaller as my solutions got better, so in the end perhaps this did not make much difference.\n\n2. I generated the RTKLIB solution, and initially replaced the Q!=2 bad points it found with my solution from #1.  Since my #1 was better than the other publicly available solutions, this solution put me ahead of all the other people trying out RTKLIB for the first time  (Public LB 2.593)\n\n3. I wanted to be able to use the base positions from RTKLIB to improve point positioning so that I could run my Kalman smoother on it, but was never able to get that to work.\n\n4. I tried using the Ionosphere and Troposphere correction functions from RTKLIB instead of the ones from the device_gnss file, but did not see an improvement from that.\n\n5. I realized that some of the device_gnss entries has blanks for baseline prediction and pseudoranges, yet RTKLIB was able to make predictions.  Looking a little more closely, it seemed like you could generate pseudorange estimates from the timing numbers directly.  So I generated 2 new solutions using the RTKLIB observation data, but running it through the  WLS/Kalman Smoother algorithm.\n\n6. I then developed a merge algorithm that took multiple solutions with weights W and computed the weighted mean, where the weights for each point were W divided by the variance estimate at each point. The tricky part here was dealing with NaNs properly.  This method allowed me to remove the \"bad\" measurements from the RTKLIB solution, and other points I deemed to be outliers.  I found small improvements by tweaking the variance estimates.\n\n7. Running out of time, I did a simple search for the best weights to use, combining 4 solutions:\n   (a) RTKLIB, (b) My WLS/Smoother soln, (c) WLS from RTKLIB's observation data, and (d) Kalman Smoothed WLS\n   from RTKLIB.\n\n8. Then, really out of time and ideas, I did a quick computation to see if there was any lat/lon offset in my solution vs. the ground truth.  I found a very small offset and added that in as a correction, which resulted in about a .04 improvement.\n\n**Other notes:**\nI never did any fitting to the Leaderboard.  All my calculations and improvements were done on the train set.  Every time (almost) I submitted a solution, it improved, roughly equaling the improvement on the train set.  I never picked parameters or methods based on feedback from the Leaderboard, I wanted to be \"clean\" from an overfitting perspective.",
      "votes": null
    },
    {
      "id": "1877887",
      "postDate": "07/31/2022 04:12:39",
      "content": "<p>Thanks for sharing your approach! <br>\nFor your weighted averaging, did you just try different weights until you found a good combination, or is there some method to optimizing the weights?</p>\n<p>The Devastator.</p>",
      "rawMarkdown": "Thanks for sharing your approach! \nFor your weighted averaging, did you just try different weights until you found a good combination, or is there some method to optimizing the weights?\n\nThe Devastator.",
      "votes": null
    },
    {
      "id": "1878011",
      "postDate": "07/31/2022 06:01:20",
      "content": "<p>Great solution and thanks for the mention <a href=\"https://www.kaggle.com/solverworld\" target=\"_blank\">@solverworld</a> !</p>",
      "rawMarkdown": "Great solution and thanks for the mention @solverworld !",
      "votes": null
    },
    {
      "id": "1878605",
      "postDate": "07/31/2022 13:43:38",
      "content": "<p>I tried different weights, no magic there.  If the variance estimates were accurate, then theoretically, the weights should all be equal.  But since it seemed like there was some scale factor between variance estimates of RTKLIB and my Kalman smoother, the weights were needed.  First I found a good pair of weights for the 2 best solutions, and added little bits of the 2 worst solutions.  If I had more time, I could have done a more automated global search, but time ran out…</p>",
      "rawMarkdown": "I tried different weights, no magic there.  If the variance estimates were accurate, then theoretically, the weights should all be equal.  But since it seemed like there was some scale factor between variance estimates of RTKLIB and my Kalman smoother, the weights were needed.  First I found a good pair of weights for the 2 best solutions, and added little bits of the 2 worst solutions.  If I had more time, I could have done a more automated global search, but time ran out...",
      "votes": null
    },
    {
      "id": "1879533",
      "postDate": "08/01/2022 05:45:35",
      "content": "<p>Thank you for sharing 🙏</p>",
      "rawMarkdown": "Thank you for sharing 🙏",
      "votes": null
    },
    {
      "id": "1989485",
      "postDate": "10/16/2022 02:53:10",
      "content": "<p>Great work!</p>",
      "rawMarkdown": "Great work!",
      "votes": null
    }
  ],
  "comments": [
    {
      "id": 1877887,
      "author_name": "thedevastator",
      "author_url": "",
      "post_date": "07/31/2022 04:12:39",
      "content": "<p>Thanks for sharing your approach! <br>\nFor your weighted averaging, did you just try different weights until you found a good combination, or is there some method to optimizing the weights?</p>\n<p>The Devastator.</p>",
      "votes": null,
      "replies": [
        {
          "id": 1878605,
          "author_name": "solverworld",
          "author_url": "",
          "post_date": "07/31/2022 13:43:38",
          "content": "<p>I tried different weights, no magic there.  If the variance estimates were accurate, then theoretically, the weights should all be equal.  But since it seemed like there was some scale factor between variance estimates of RTKLIB and my Kalman smoother, the weights were needed.  First I found a good pair of weights for the 2 best solutions, and added little bits of the 2 worst solutions.  If I had more time, I could have done a more automated global search, but time ran out…</p>",
          "votes": null,
          "replies": []
        }
      ]
    },
    {
      "id": 1878011,
      "author_name": "saurabhbagchi",
      "author_url": "",
      "post_date": "07/31/2022 06:01:20",
      "content": "<p>Great solution and thanks for the mention <a href=\"https://www.kaggle.com/solverworld\" target=\"_blank\">@solverworld</a> !</p>",
      "votes": null,
      "replies": []
    },
    {
      "id": 1879533,
      "author_name": "willcramptonn",
      "author_url": "",
      "post_date": "08/01/2022 05:45:35",
      "content": "<p>Thank you for sharing 🙏</p>",
      "votes": null,
      "replies": []
    },
    {
      "id": 1989485,
      "author_name": "snickin",
      "author_url": "",
      "post_date": "10/16/2022 02:53:10",
      "content": "<p>Great work!</p>",
      "votes": null,
      "replies": []
    }
  ],
  "raw_markdown_by_id": {
    "1877311": "Thank you to all the competition organizers and the participants who shared their knowledge with the rest of us learning about GNSS.  Who knew GPS positioning was so complicated?\n\n**My solution was based on these 3 public notebooks and ideas:**\n\n1. \"WLS\" A solution based on \"Carrier-Smoothing-WLS-Kalman Filtering\" from\n@saurabhbagchi - https://www.kaggle.com/code/saurabhbagchi/carrier-smoothing-robust-wls-kalman-smootherv2\nwhich was based on\n@taroz1461 - https://www.kaggle.com/code/taroz1461/carrier-smoothing-robust-wls-kalman-smoother\n\n2. \"RTKLIB\" An RTKLIB  solution @timeverett - https://www.kaggle.com/code/timeverett/getting-started-with-rtklib.  I would especially like to commend RTKLIBExplorer for all his explanations and patience in answering many people's questions on RTKLIB.\n\n3. \"OFFSET\" An offset correction based on @saitodevelo01 - https://www.kaggle.com/code/saitodevel01/gsdc-bias-correction\n\n**I used the above algorithms as follows:**\n\n1. Starting with the WLS solution, which uses an L1 optimization at each point to determine the receiver clock bias and thus the best X,Y,Z ECEF coordinates, I replaced the Kalman smoother with a more complicated model as follows:\n   There were 9 states: (3) x,y,z, (3) the velocities in x,y,z, (3) the accelerations in x,y,z.\n   The measurements were position and velocity from the WLS algorithm (vel comes from doppler shift).\n   The measurement noise was as determined from WLS, which comes from the device_gnss uncertainty in Pseudorange and Pseudorange velocity, using the Jacobian of the L1 solution.  I implemented Kalman Smoothing, which effectively runs the Kalman filter forward and backward, combining the results properly.  The authority for this is \"Applied Optimal Estimation\" by Art Gelb.  I tuned the process noise (Q) and thresholds (Mahalanobis) for throwing out measurements by simple trial and error.  I added the OFFSET solution above to this, but it seemed like the offset got smaller as my solutions got better, so in the end perhaps this did not make much difference.\n\n2. I generated the RTKLIB solution, and initially replaced the Q!=2 bad points it found with my solution from #1.  Since my #1 was better than the other publicly available solutions, this solution put me ahead of all the other people trying out RTKLIB for the first time  (Public LB 2.593)\n\n3. I wanted to be able to use the base positions from RTKLIB to improve point positioning so that I could run my Kalman smoother on it, but was never able to get that to work.\n\n4. I tried using the Ionosphere and Troposphere correction functions from RTKLIB instead of the ones from the device_gnss file, but did not see an improvement from that.\n\n5. I realized that some of the device_gnss entries has blanks for baseline prediction and pseudoranges, yet RTKLIB was able to make predictions.  Looking a little more closely, it seemed like you could generate pseudorange estimates from the timing numbers directly.  So I generated 2 new solutions using the RTKLIB observation data, but running it through the  WLS/Kalman Smoother algorithm.\n\n6. I then developed a merge algorithm that took multiple solutions with weights W and computed the weighted mean, where the weights for each point were W divided by the variance estimate at each point. The tricky part here was dealing with NaNs properly.  This method allowed me to remove the \"bad\" measurements from the RTKLIB solution, and other points I deemed to be outliers.  I found small improvements by tweaking the variance estimates.\n\n7. Running out of time, I did a simple search for the best weights to use, combining 4 solutions:\n   (a) RTKLIB, (b) My WLS/Smoother soln, (c) WLS from RTKLIB's observation data, and (d) Kalman Smoothed WLS\n   from RTKLIB.\n\n8. Then, really out of time and ideas, I did a quick computation to see if there was any lat/lon offset in my solution vs. the ground truth.  I found a very small offset and added that in as a correction, which resulted in about a .04 improvement.\n\n**Other notes:**\nI never did any fitting to the Leaderboard.  All my calculations and improvements were done on the train set.  Every time (almost) I submitted a solution, it improved, roughly equaling the improvement on the train set.  I never picked parameters or methods based on feedback from the Leaderboard, I wanted to be \"clean\" from an overfitting perspective.",
    "1877887": "Thanks for sharing your approach! \nFor your weighted averaging, did you just try different weights until you found a good combination, or is there some method to optimizing the weights?\n\nThe Devastator.",
    "1878011": "Great solution and thanks for the mention @solverworld !",
    "1878605": "I tried different weights, no magic there.  If the variance estimates were accurate, then theoretically, the weights should all be equal.  But since it seemed like there was some scale factor between variance estimates of RTKLIB and my Kalman smoother, the weights were needed.  First I found a good pair of weights for the 2 best solutions, and added little bits of the 2 worst solutions.  If I had more time, I could have done a more automated global search, but time ran out...",
    "1879533": "Thank you for sharing 🙏",
    "1989485": "Great work!"
  },
  "source": "meta"
}