global_time_sync_slave.hpp
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2014 Pavel Kirienko <pavel.kirienko@gmail.com>
3  */
4 
5 #ifndef UAVCAN_PROTOCOL_GLOBAL_TIME_SYNC_SLAVE_HPP_INCLUDED
6 #define UAVCAN_PROTOCOL_GLOBAL_TIME_SYNC_SLAVE_HPP_INCLUDED
7 
10 #include <uavcan/protocol/GlobalTimeSync.hpp>
11 #include <uavcan/debug.hpp>
12 #include <cassert>
13 
14 namespace uavcan
15 {
29 {
31  void (GlobalTimeSyncSlave::*)(const ReceivedDataStructure<protocol::GlobalTimeSync>&)>
33 
35 
39  enum State { Update, Adjust } state_;
44 
45  ISystemClock& getSystemClock() const { return sub_.getNode().getSystemClock(); }
46 
48  {
49  UAVCAN_ASSERT(msg.previous_transmission_timestamp_usec > 0);
50  const UtcDuration adjustment = UtcTime::fromUSec(msg.previous_transmission_timestamp_usec) - prev_ts_utc_;
51 
52  UAVCAN_TRACE("GlobalTimeSyncSlave", "Adjustment: usec=%lli snid=%i iface=%i suppress=%i",
53  static_cast<long long>(adjustment.toUSec()),
54  int(msg.getSrcNodeID().get()), int(msg.getIfaceIndex()), int(suppressed_));
55 
56  if (!suppressed_)
57  {
58  getSystemClock().adjustUtc(adjustment);
59  }
60  last_adjustment_ts_ = msg.getMonotonicTimestamp();
61  state_ = Update;
62  }
63 
65  {
66  UAVCAN_TRACE("GlobalTimeSyncSlave", "Update: snid=%i iface=%i",
67  int(msg.getSrcNodeID().get()), int(msg.getIfaceIndex()));
68 
69  prev_ts_utc_ = msg.getUtcTimestamp();
70  prev_ts_mono_ = msg.getMonotonicTimestamp();
71  master_nid_ = msg.getSrcNodeID();
72  prev_iface_index_ = msg.getIfaceIndex();
73  prev_tid_ = msg.getTransferID();
74  state_ = Adjust;
75  }
76 
78  {
79  const MonotonicDuration since_prev_msg = msg.getMonotonicTimestamp() - prev_ts_mono_;
80  UAVCAN_ASSERT(!since_prev_msg.isNegative());
81 
82  const bool needs_init = !master_nid_.isValid() || prev_ts_mono_.isZero();
83  const bool switch_master = msg.getSrcNodeID() < master_nid_;
84  // TODO: Make configurable
85  const bool pub_timeout = since_prev_msg.toMSec() > protocol::GlobalTimeSync::RECOMMENDED_BROADCASTER_TIMEOUT_MS;
86 
87  if (switch_master || pub_timeout || needs_init)
88  {
89  UAVCAN_TRACE("GlobalTimeSyncSlave", "Force update: needs_init=%i switch_master=%i pub_timeout=%i",
90  int(needs_init), int(switch_master), int(pub_timeout));
91  updateFromMsg(msg);
92  }
93  else if (msg.getIfaceIndex() == prev_iface_index_ && msg.getSrcNodeID() == master_nid_)
94  {
95  if (state_ == Adjust)
96  {
97  const bool msg_invalid = msg.previous_transmission_timestamp_usec == 0;
98  const bool wrong_tid = prev_tid_.computeForwardDistance(msg.getTransferID()) != 1;
99  const bool wrong_timing = since_prev_msg.toMSec() > protocol::GlobalTimeSync::MAX_BROADCASTING_PERIOD_MS;
100  if (msg_invalid || wrong_tid || wrong_timing)
101  {
102  UAVCAN_TRACE("GlobalTimeSyncSlave",
103  "Adjustment skipped: msg_invalid=%i wrong_tid=%i wrong_timing=%i",
104  int(msg_invalid), int(wrong_tid), int(wrong_timing));
105  state_ = Update;
106  }
107  }
108  if (state_ == Adjust)
109  {
110  adjustFromMsg(msg);
111  }
112  else
113  {
114  updateFromMsg(msg);
115  }
116  }
117  else
118  {
119  UAVCAN_TRACE("GlobalTimeSyncSlave", "Ignored: snid=%i iface=%i",
120  int(msg.getSrcNodeID().get()), int(msg.getIfaceIndex()));
121  }
122  }
123 
125  {
127  {
128  processMsg(msg);
129  }
130  else
131  {
132  UAVCAN_TRACE("GlobalTimeSyncSlave", "Invalid transfer type %i", int(msg.getTransferType()));
133  }
134  }
135 
136 public:
138  : sub_(node)
139  , state_(Update)
140  , prev_iface_index_(0xFF)
141  , suppressed_(false)
142  { }
143 
149  int start()
150  {
152  }
153 
168  void suppress(bool suppressed) { suppressed_ = suppressed; }
169  bool isSuppressed() const { return suppressed_; }
170 
177  bool isActive() const
178  {
179  const MonotonicDuration since_prev_adj = getSystemClock().getMonotonic() - last_adjustment_ts_;
180  return !last_adjustment_ts_.isZero() &&
181  (since_prev_adj.toMSec() <= protocol::GlobalTimeSync::RECOMMENDED_BROADCASTER_TIMEOUT_MS);
182  }
183 
188  NodeID getMasterNodeID() const { return isActive() ? master_nid_ : NodeID(); }
189 
193  MonotonicTime getLastAdjustmentTime() const { return last_adjustment_ts_; }
194 };
195 
196 }
197 
198 #endif // UAVCAN_PROTOCOL_GLOBAL_TIME_SYNC_SLAVE_HPP_INCLUDED
std::uint8_t uint8_t
Definition: std.hpp:24
virtual MonotonicTime getMonotonic() const =0
bool isZero() const
Definition: time.hpp:123
bool isNegative() const
Definition: time.hpp:49
void updateFromMsg(const ReceivedDataStructure< protocol::GlobalTimeSync > &msg)
MonotonicTime getLastAdjustmentTime() const
static UtcTime fromUSec(uint64_t us)
Definition: time.hpp:112
uavcan::ISystemClock & getSystemClock()
int64_t toUSec() const
Definition: time.hpp:43
Implicitly convertible to/from uavcan.Timestamp.
Definition: time.hpp:191
void adjustFromMsg(const ReceivedDataStructure< protocol::GlobalTimeSync > &msg)
ISystemClock & getSystemClock() const
void handleGlobalTimeSync(const ReceivedDataStructure< protocol::GlobalTimeSync > &msg)
int64_t toMSec() const
Definition: time.hpp:44
int computeForwardDistance(TransferID rhs) const
Definition: uc_transfer.cpp:44
bool isValid() const
Definition: transfer.hpp:134
MonotonicTime getMonotonicTimestamp() const
int start(const Callback &callback)
Definition: subscriber.hpp:83
Subscriber< protocol::GlobalTimeSync, GlobalTimeSyncCallback > sub_
void processMsg(const ReceivedDataStructure< protocol::GlobalTimeSync > &msg)
virtual void adjustUtc(UtcDuration adjustment)=0
TransferType getTransferType() const


uavcan_communicator
Author(s):
autogenerated on Wed Jan 11 2023 03:59:39