JitterCorrection.cpp 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. /*
  2. This program is free software: you can redistribute it and/or modify
  3. it under the terms of the GNU General Public License as published by
  4. the Free Software Foundation, either version 3 of the License, or
  5. (at your option) any later version.
  6. This program is distributed in the hope that it will be useful,
  7. but WITHOUT ANY WARRANTY; without even the implied warranty of
  8. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  9. GNU General Public License for more details.
  10. You should have received a copy of the GNU General Public License
  11. along with this program. If not, see <http://www.gnu.org/licenses/>.
  12. */
  13. /*
  14. class to correct an offboard timestamp in microseconds into a local
  15. timestamp, removing timing jitter caused by the transport.
  16. It takes the offboard_usec timestamp which is a timestamp provided
  17. in a protocol from a remote device, and the time of arrival of the
  18. message in local microseconds. It returns an improved estimate of
  19. the time that the message was generated on the remote system in the
  20. local time domain
  21. The algorithm assumes two things:
  22. 1) the data did not come from the future in our local time-domain
  23. 2) the data is not older than max_lag_ms in our local time-domain
  24. It works by estimating the transport lag by looking for the incoming
  25. packet that had the least lag, and converging on the offset that is
  26. associated with that lag
  27. */
  28. #include <AP_HAL/AP_HAL.h>
  29. #include "JitterCorrection.h"
  30. // constructor
  31. JitterCorrection::JitterCorrection(uint16_t _max_lag_ms, uint16_t _convergence_loops) :
  32. max_lag_ms(_max_lag_ms),
  33. convergence_loops(_convergence_loops)
  34. {}
  35. /*
  36. correct an offboard timestamp in microseconds into a local
  37. timestamp, removing timing jitter caused by the transport.
  38. Return a value in microseconds since boot in the local time domain
  39. */
  40. uint64_t JitterCorrection::correct_offboard_timestamp_usec(uint64_t offboard_usec, uint64_t local_usec)
  41. {
  42. int64_t diff_us = int64_t(local_usec) - int64_t(offboard_usec);
  43. if (!initialised ||
  44. diff_us < link_offset_usec) {
  45. // this message arrived from the remote system with a
  46. // timestamp that would imply the message was from the
  47. // future. We know that isn't possible, so we adjust down the
  48. // correction value
  49. link_offset_usec = diff_us;
  50. initialised = true;
  51. }
  52. int64_t estimate_us = offboard_usec + link_offset_usec;
  53. if (estimate_us + (max_lag_ms*1000U) < int64_t(local_usec)) {
  54. // this implies the message came from too far in the past. clamp the lag estimate
  55. // to assume the message had maximum lag
  56. estimate_us = local_usec - (max_lag_ms*1000U);
  57. link_offset_usec = estimate_us - offboard_usec;
  58. }
  59. if (min_sample_counter == 0) {
  60. min_sample_us = diff_us;
  61. }
  62. min_sample_counter++;
  63. if (diff_us < min_sample_us) {
  64. min_sample_us = diff_us;
  65. }
  66. if (min_sample_counter == convergence_loops) {
  67. // we have the requested number of samples of the transport
  68. // lag for convergence. To account for long term clock drift
  69. // we set the diff we will use in future to this value
  70. link_offset_usec = min_sample_us;
  71. min_sample_counter = 0;
  72. }
  73. return uint64_t(estimate_us);
  74. }
  75. /*
  76. correct an offboard timestamp in microseconds into a local
  77. timestamp, removing timing jitter caused by the transport.
  78. Return a value in milliseconds since boot in the local time domain
  79. */
  80. uint32_t JitterCorrection::correct_offboard_timestamp_msec(uint32_t offboard_ms, uint32_t local_ms)
  81. {
  82. return correct_offboard_timestamp_usec(offboard_ms*1000ULL, local_ms*1000ULL) / 1000ULL;
  83. }