TimestampSynchronizer.cpp
Go to the documentation of this file.
1 #include <cmath>
2 
4 
5 
6 TimestampSynchronizer::TimestampSynchronizer(Options defaultOptions) : np_("~timestamp_synchronizer") {
7 
8  // TimestampSynchronizer gets its own private namespace inside of the node private namespace
9 
10  // advertise the debug topic, which publishes the values passed to the sync() method
11  debugPublisher_ = np_.advertise<timesync::TimesyncDebug>("debug_info", 10);
12 
13  // load options from ROS params if available, if not, from default options passed by caller
14  options_.useMedianFilter = np_.param("useMedianFilter", defaultOptions.useMedianFilter);
15  options_.medianFilterWindow = np_.param("medianFilterWindow", defaultOptions.medianFilterWindow);
16  options_.useHoltWinters = np_.param("useHoltWinters", defaultOptions.useHoltWinters);
17  options_.alfa_HoltWinters = np_.param("alfa_HoltWinters", defaultOptions.alfa_HoltWinters);
18  options_.beta_HoltWinters = np_.param("beta_HoltWinters", defaultOptions.beta_HoltWinters);
19  options_.alfa_HoltWinters_early = np_.param("alfa_HoltWinters_early", defaultOptions.alfa_HoltWinters_early);
20  options_.beta_HoltWinters_early = np_.param("beta_HoltWinters_early", defaultOptions.beta_HoltWinters_early);
21  options_.earlyClamp = np_.param("earlyClamp", defaultOptions.earlyClamp);
22  options_.earlyClampWindow = np_.param("earlyClampWindow", defaultOptions.earlyClampWindow);
23  options_.timeOffset = np_.param("timeOffset", defaultOptions.timeOffset);
24  options_.initialB_HoltWinters = np_.param("initialB_HoltWinters", defaultOptions.initialB_HoltWinters);
25 
26  ROS_DEBUG("--------------------------");
27  ROS_DEBUG("TimestampSynchronizer init");
28  ROS_DEBUG("useMedianFilter: %d", options_.useMedianFilter);
29  ROS_DEBUG("medianFilterWindow: %d", options_.medianFilterWindow);
30  ROS_DEBUG("useHoltWinters: %d", options_.useHoltWinters);
31  ROS_DEBUG("alfa_HoltWinters: %lf", options_.alfa_HoltWinters);
32  ROS_DEBUG("beta_HoltWinters: %lf", options_.beta_HoltWinters);
33  ROS_DEBUG("alfa_HoltWinters_early: %lf", options_.alfa_HoltWinters_early);
34  ROS_DEBUG("beta_HoltWinters_early: %lf", options_.beta_HoltWinters_early);
35  ROS_DEBUG("earlyClamp: %d", options_.earlyClamp);
36  ROS_DEBUG("earlyClampWindow: %d", options_.earlyClampWindow);
37  ROS_DEBUG("timeOffset: %lf", options_.timeOffset);
38  ROS_DEBUG("initialB_HoltWinters: %.10lf", options_.initialB_HoltWinters);
39  ROS_DEBUG("--------------------------");
40 
41  init();
42 }
43 
44 double TimestampSynchronizer::sync(double currentSensorTime, double currentRosTime, unsigned int seqNumber_external){
45 
46  if(!firstFrameSet_) {
47  seqCounter_ = 0;
48  firstFrameSet_ = true;
49 
50  startSensorTime_ = currentSensorTime;
51  startRosTimeBig_ = currentRosTime;
52  }
53 
54  double currentRosTimeBig = currentRosTime;
55  double currentSensorTimeBig = currentSensorTime;
56 
57  // subtract starting values because we need to work with small numbers,
58  // or else we will lose precision
59  currentRosTime = currentRosTime - startRosTimeBig_;
60  currentSensorTime = currentSensorTime - startSensorTime_;
61 
62  // the basic idea of the timestamp correction algorithm: by estimating t0 (system clock - sensor clock)
63  // we eliminate the effects of both the system clock jitter and system-sensor clock drift
64  double currentHypothesis_t0 = currentRosTime - currentSensorTime;
65 
66  double meanEstimatedHypothesis_t0 = currentHypothesis_t0;
67 
69  pmediator_->insert(meanEstimatedHypothesis_t0);
70  meanEstimatedHypothesis_t0 = pmediator_->getMedian();
71  }
72 
74  // at the early stage of the algorithm, use larger alfa and beta to initialize the filter faster
76  // smooth interpolation between early and regular alfa/beta
77  double progress = ((double) seqCounter_) / options_.earlyClampWindow;
78  // progress interpolated with a logistic curve, derivation 0 at finish
79  double p = 1-std::exp(0.5*(1-1/(1-progress)));
80 
83  }
84  else {
87  }
88  holtWinters_.insert(meanEstimatedHypothesis_t0);
89  meanEstimatedHypothesis_t0 = holtWinters_.getFiltered();
90  }
91 
92  double currentOut = meanEstimatedHypothesis_t0 + currentSensorTime;
93 
94  // add back the subtracted start time, plus an user-configurable offset
95  double finalOut = currentOut + options_.timeOffset + startRosTimeBig_;
96 
97  double currentError = currentOut - currentRosTime;
98 
99  timesync::TimesyncDebug debugMessage;
100  debugMessage.seq = seqNumber_external;
101  debugMessage.sensor_time = currentSensorTimeBig;
102  debugMessage.ros_time = currentRosTimeBig;
103  debugMessage.corrected_timestamp = finalOut;
104  debugPublisher_.publish(debugMessage);
105 
106  ROS_DEBUG("delta_sensor: %.10lf delta_ros: %.10lf delta_out: %.10lf frame_count: %d", currentSensorTime - previousSensorTime_, currentRosTime - previousRosTime_, currentOut - previousOut_, seqNumber_external);
107  ROS_DEBUG("SENSOR_TIMESTAMP: %.10lf CUR_HYP: %.10lf", currentSensorTime, currentHypothesis_t0);
108  ROS_DEBUG("ROS_TIME: %.10lf STAMP: %.10lf ERR: %+.10lf RUN_HYP: %.10lf", currentRosTime, currentOut, currentError, meanEstimatedHypothesis_t0);
109 
110  // update previous values, used for calculating deltas
111  previousOut_ = currentOut;
112  previousSensorTime_ = currentSensorTime;
113  previousRosTime_ = currentRosTime;
114 
115  seqCounter_++;
116 
117  return finalOut;
118 
119 }
120 
121 void TimestampSynchronizer::setTimeOffset(double timeOffset) {
123 }
124 
125 void TimestampSynchronizer::setMedianFilter(bool useMedianFilter, int medianFilterWindow) {
128  initMediator();
129 }
130 
131 void TimestampSynchronizer::setUseHoltWinters(bool useHoltWinters) {
133 }
134 
135 void TimestampSynchronizer::setAlfa_HoltWinters(double alfa_HoltWinters) {
137 }
138 
139 void TimestampSynchronizer::setBeta_HoltWinters(double beta_HoltWinters) {
141 }
142 
143 void TimestampSynchronizer::setAlfa_HoltWinters_early(double alfa_HoltWinters_early) {
145 }
146 
147 void TimestampSynchronizer::setBeta_HoltWinters_early(double beta_HoltWinters_early) {
149 }
150 
152  init();
153 }
154 
155 // allocate a Mediator object
157  pmediator_ = std::unique_ptr<Mediator<double> >(new Mediator<double>(options_.medianFilterWindow));
158 }
159 
161  firstFrameSet_ = false;
162  initMediator();
164 }
165 
166 void TimestampSynchronizer::setEarlyClamp(bool earlyClamp, int earlyClampWindow) {
169 }
void insert(const double &v)
Definition: HoltWinters.cpp:9
TimestampSynchronizer(const Options defaultOptions=Options())
void setTimeOffset(double timeOffset)
void publish(const boost::shared_ptr< M > &message) const
void setUseHoltWinters(bool useHoltWinters)
void setEarlyClamp(bool earlyClamp, int earlyClampWindow=0)
void setAlfa_HoltWinters(double alfa_HoltWinters)
double sync(double currentSensorTime, double currentRosTime, unsigned int seqNumber_external)
bool param(const std::string &param_name, T &param_val, const T &default_val) const
HoltWintersSmoothFilter holtWinters_
void setAlfa_HoltWinters_early(double alfa_HoltWinters_early)
void setBeta_HoltWinters(double beta_HoltWinters)
Publisher advertise(const std::string &topic, uint32_t queue_size, bool latch=false)
TimestampSynchronizer.
void reset(double initialB=defaultInitialB_)
Definition: HoltWinters.cpp:29
void setMedianFilter(bool useMedianFilter, int medianFilterWindow=0)
std::unique_ptr< Mediator< double > > pmediator_
void setBeta_HoltWinters_early(double beta_HoltWinters_early)
void setBeta(double beta)
Definition: HoltWinters.cpp:38
void setAlfa(double alfa)
Definition: HoltWinters.cpp:34
#define ROS_DEBUG(...)


timesync_ros
Author(s): Juraj Oršulić
autogenerated on Mon Jun 10 2019 15:28:33