clock.hpp 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  1. /*
  2. * Copyright (C) 2014 <pavel.kirienko@gmail.com>
  3. */
  4. #pragma once
  5. #include <cassert>
  6. #include <time.h>
  7. #include <sys/time.h>
  8. #include <uavcan/driver/system_clock.hpp>
  9. class SystemClockMock : public uavcan::ISystemClock
  10. {
  11. public:
  12. mutable uint64_t monotonic;
  13. mutable uint64_t utc;
  14. uavcan::UtcDuration last_adjustment;
  15. uint64_t monotonic_auto_advance;
  16. bool preserve_utc;
  17. SystemClockMock(uint64_t initial = 0)
  18. : monotonic(initial)
  19. , utc(initial)
  20. , monotonic_auto_advance(0)
  21. , preserve_utc(false)
  22. { }
  23. void advance(uint64_t usec) const
  24. {
  25. monotonic += usec;
  26. if (!preserve_utc)
  27. {
  28. utc += usec;
  29. }
  30. }
  31. virtual uavcan::MonotonicTime getMonotonic() const
  32. {
  33. assert(this);
  34. const uint64_t res = monotonic;
  35. advance(monotonic_auto_advance);
  36. return uavcan::MonotonicTime::fromUSec(res);
  37. }
  38. virtual uavcan::UtcTime getUtc() const
  39. {
  40. assert(this);
  41. return uavcan::UtcTime::fromUSec(utc);
  42. }
  43. virtual void adjustUtc(uavcan::UtcDuration adjustment)
  44. {
  45. assert(this);
  46. const uint64_t prev_utc = utc;
  47. utc = uint64_t(int64_t(utc) + adjustment.toUSec());
  48. last_adjustment = adjustment;
  49. std::cout << "Clock adjustment " << prev_utc << " --> " << utc << std::endl;
  50. }
  51. };
  52. class SystemClockDriver : public uavcan::ISystemClock
  53. {
  54. public:
  55. uavcan::UtcDuration utc_adjustment;
  56. virtual uavcan::MonotonicTime getMonotonic() const
  57. {
  58. struct timespec ts;
  59. const int ret = clock_gettime(CLOCK_MONOTONIC, &ts);
  60. if (ret != 0)
  61. {
  62. assert(0);
  63. return uavcan::MonotonicTime();
  64. }
  65. return uavcan::MonotonicTime::fromUSec(uint64_t(int64_t(ts.tv_sec) * 1000000L + int64_t(ts.tv_nsec / 1000L)));
  66. }
  67. virtual uavcan::UtcTime getUtc() const
  68. {
  69. struct timeval tv;
  70. const int ret = gettimeofday(&tv, UAVCAN_NULLPTR);
  71. if (ret != 0)
  72. {
  73. assert(0);
  74. return uavcan::UtcTime();
  75. }
  76. return uavcan::UtcTime::fromUSec(uint64_t(int64_t(tv.tv_sec) * 1000000L + tv.tv_usec)) + utc_adjustment;
  77. }
  78. virtual void adjustUtc(uavcan::UtcDuration adjustment)
  79. {
  80. utc_adjustment += adjustment;
  81. }
  82. };
  83. inline uavcan::MonotonicTime tsMono(uint64_t usec) { return uavcan::MonotonicTime::fromUSec(usec); }
  84. inline uavcan::UtcTime tsUtc(uint64_t usec) { return uavcan::UtcTime::fromUSec(usec); }
  85. inline uavcan::MonotonicDuration durMono(int64_t usec) { return uavcan::MonotonicDuration::fromUSec(usec); }
  86. template <typename T>
  87. static bool areTimestampsClose(const T& a, const T& b, int64_t precision_usec = 100000)
  88. {
  89. return (a - b).getAbs().toUSec() < precision_usec;
  90. }