global_timestamp_reader.cpp
Go to the documentation of this file.
1 // License: Apache 2.0. See LICENSE file in root directory.
2 // Copyright(c) 2015 Intel Corporation. All Rights Reserved.
4 #include <chrono>
5 
6 using namespace std::chrono;
7 
8 namespace librealsense
9 {
10  CSample& CSample::operator-=(const CSample& other)
11  {
12  _x -= other._x;
13  _y -= other._y;
14  return *this;
15  }
16 
18  {
19  _x += other._x;
20  _y += other._y;
21  return *this;
22  }
23 
24  CLinearCoefficients::CLinearCoefficients(unsigned int buffer_size) :
25  _base_sample(0, 0),
26  _buffer_size(buffer_size),
27  _time_span_ms(1000) // Spread the linear equation modifications over a whole second.
28  {
29  }
30 
32  {
33  _last_values.clear();
34  }
35 
37  {
38  return _last_values.size() >= _buffer_size;
39  }
40 
42  {
43  while (_last_values.size() > _buffer_size)
44  {
45  _last_values.pop_back();
46  }
47  _last_values.push_front(val);
49  }
50 
52  {
53  for (auto &&sample : _last_values)
54  {
55  sample._y += dy;
56  }
57  }
58 
60  {
61  // Calculate linear coefficients, based on calculus described in: https://www.statisticshowto.datasciencecentral.com/probability-and-statistics/regression-analysis/find-a-linear-regression-equation/
62  // Calculate Std
63  double n(static_cast<double>(_last_values.size()));
64  double a(1);
65  double b(0);
66  double dt(1);
67  if (n == 1)
68  {
69  _base_sample = _last_values.back();
70  _dest_a = 1;
71  _dest_b = 0;
72  _prev_a = 0;
73  _prev_b = 0;
74  _last_request_time = _last_values.front()._x;
75  }
76  else
77  {
78  double sum_x(0);
79  double sum_y(0);
80  double sum_xy(0);
81  double sum_x2(0);
82  for (auto sample = _last_values.begin(); sample != _last_values.end(); sample++)
83  {
84  CSample crnt_sample(*sample);
85  crnt_sample -= _base_sample;
86  sum_x += crnt_sample._x;
87  sum_y += crnt_sample._y;
88  sum_xy += (crnt_sample._x * crnt_sample._y);
89  sum_x2 += (crnt_sample._x * crnt_sample._x);
90  }
91  b = (sum_y*sum_x2 - sum_x * sum_xy) / (n*sum_x2 - sum_x * sum_x);
92  a = (n*sum_xy - sum_x * sum_y) / (n*sum_x2 - sum_x * sum_x);
93 
95  {
97  }
98  }
99  _prev_a = _dest_a * dt + _prev_a * (1 - dt);
100  _prev_b = _dest_b * dt + _prev_b * (1 - dt);
101  _dest_a = a;
102  _dest_b = b;
104  }
105 
106  void CLinearCoefficients::get_a_b(double x, double& a, double& b) const
107  {
108  a = _dest_a;
109  b = _dest_b;
110  if (x - _prev_time < _time_span_ms)
111  {
112  double dt((x - _prev_time) / _time_span_ms);
113  a = _dest_a * dt + _prev_a * (1 - dt);
114  b = _dest_b * dt + _prev_b * (1 - dt);
115  }
116  }
117 
118  double CLinearCoefficients::calc_value(double x) const
119  {
120  double a, b;
121  get_a_b(x, a, b);
122  double y(a * (x - _base_sample._x) + b + _base_sample._y);
123  LOG_DEBUG(__FUNCTION__ << ": " << x << " -> " << y << " with coefs:" << a << ", " << b << ", " << _base_sample._x << ", " << _base_sample._y);
124  return y;
125  }
126 
128  {
129  static const double max_device_time(pow(2, 32) * TIMESTAMP_USEC_TO_MSEC);
130  double base_x;
131  if (_last_values.empty())
132  return false;
133  if ((_last_values.front()._x - x) > max_device_time / 2)
134  base_x = max_device_time;
135  else if ((x - _last_values.front()._x) > max_device_time / 2)
136  base_x = -max_device_time;
137  else
138  return false;
139  LOG_DEBUG(__FUNCTION__ << "(" << base_x << ")");
140 
141  double a, b;
142  get_a_b(x+base_x, a, b);
143  for (auto &&sample : _last_values)
144  {
145  sample._x -= base_x;
146  }
147  _prev_time -= base_x;
148  _base_sample._y += a * base_x;
149  return true;
150  }
151 
153  {
155  }
156 
157  time_diff_keeper::time_diff_keeper(global_time_interface* dev, const unsigned int sampling_interval_ms) :
158  _device(dev),
159  _poll_intervals_ms(sampling_interval_ms),
160  _coefs(15),
161  _users_count(0),
162  _is_ready(false),
163  _min_command_delay(1000),
164  _active_object([this](dispatcher::cancellable_timer cancellable_timer)
165  {
166  polling(cancellable_timer);
167  })
168  {
169  //LOG_DEBUG("start new time_diff_keeper ");
170  }
171 
173  {
174  std::lock_guard<std::recursive_mutex> lock(_enable_mtx);
175  _users_count++;
176  LOG_DEBUG("time_diff_keeper::start: _users_count = " << _users_count);
178  }
179 
181  {
182  std::lock_guard<std::recursive_mutex> lock(_enable_mtx);
183  if (_users_count <= 0)
184  LOG_ERROR("time_diff_keeper users_count <= 0.");
185 
186  _users_count--;
187  LOG_DEBUG("time_diff_keeper::stop: _users_count = " << _users_count);
188  if (_users_count == 0)
189  {
190  LOG_DEBUG("time_diff_keeper::stop: stop object.");
192  _coefs.reset();
193  _is_ready = false;
194  }
195  }
196 
198  {
200  }
201 
203  {
204  try
205  {
206  if (!_users_count)
207  throw wrong_api_call_sequence_exception("time_diff_keeper::update_diff_time called before object started.");
208  double system_time_start = duration<double, std::milli>(system_clock::now().time_since_epoch()).count();
209  double sample_hw_time = _device->get_device_time_ms();
210  double system_time_finish = duration<double, std::milli>(system_clock::now().time_since_epoch()).count();
211  double command_delay = (system_time_finish-system_time_start)/2;
212 
213  std::lock_guard<std::recursive_mutex> lock(_read_mtx);
214  if (command_delay < _min_command_delay)
215  {
217  _min_command_delay = command_delay;
218  }
219  double system_time(system_time_finish - _min_command_delay);
220  if (_is_ready)
221  {
222  _coefs.update_samples_base(sample_hw_time);
223  }
224  CSample crnt_sample(sample_hw_time, system_time);
225  _coefs.add_value(crnt_sample);
226  _is_ready = true;
227  return true;
228  }
229  catch (const io_exception& ex)
230  {
231  LOG_DEBUG("Temporary skip during time_diff_keeper polling: " << ex.what());
232  }
233  catch (const wrong_api_call_sequence_exception& ex)
234  {
235  LOG_DEBUG("Temporary skip during time_diff_keeper polling: " << ex.what());
236  }
237  catch (const std::exception& ex)
238  {
239  LOG_ERROR("Error during time_diff_keeper polling: " << ex.what());
240  }
241  catch (...)
242  {
243  LOG_ERROR("Unknown error during time_diff_keeper polling!");
244  }
245  return false;
246  }
247 
249  {
251  unsigned int time_to_sleep = _poll_intervals_ms + _coefs.is_full() * (9 * _poll_intervals_ms);
252  if (!cancellable_timer.try_sleep(time_to_sleep))
253  {
254  LOG_DEBUG("Notification: time_diff_keeper polling loop is being shut-down");
255  }
256  }
257 
258  double time_diff_keeper::get_system_hw_time(double crnt_hw_time, bool& is_ready)
259  {
260  std::lock_guard<std::recursive_mutex> lock(_read_mtx);
261  is_ready = _is_ready;
262  if (_is_ready)
263  {
264  _coefs.update_samples_base(crnt_hw_time);
265  _coefs.update_last_sample_time(crnt_hw_time);
266  return _coefs.calc_value(crnt_hw_time);
267  }
268  else
269  return crnt_hw_time;
270  }
271 
272  global_timestamp_reader::global_timestamp_reader(std::unique_ptr<frame_timestamp_reader> device_timestamp_reader,
273  std::shared_ptr<time_diff_keeper> timediff,
274  std::shared_ptr<global_time_option> enable_option) :
275  _device_timestamp_reader(std::move(device_timestamp_reader)),
276  _time_diff_keeper(timediff),
277  _option_is_enabled(enable_option),
278  _ts_is_ready(false)
279  {
280  }
281 
282  double global_timestamp_reader::get_frame_timestamp(const std::shared_ptr<frame_interface>& frame)
283  {
284  double frame_time = _device_timestamp_reader->get_frame_timestamp(frame);
285  rs2_timestamp_domain ts_domain = _device_timestamp_reader->get_frame_timestamp_domain(frame);
286  if (_option_is_enabled->is_true() && ts_domain == RS2_TIMESTAMP_DOMAIN_HARDWARE_CLOCK)
287  {
288  auto sp = _time_diff_keeper.lock();
289  if (sp)
290  frame_time = sp->get_system_hw_time(frame_time, _ts_is_ready);
291  else
292  LOG_DEBUG("Notification: global_timestamp_reader - time_diff_keeper is being shut-down");
293  }
294  return frame_time;
295  }
296 
297 
298  unsigned long long global_timestamp_reader::get_frame_counter(const std::shared_ptr<frame_interface>& frame) const
299  {
300  return _device_timestamp_reader->get_frame_counter(frame);
301  }
302 
304  {
305  rs2_timestamp_domain ts_domain = _device_timestamp_reader->get_frame_timestamp_domain(frame);
307  }
308 
310  {
311  _device_timestamp_reader->reset();
312  }
313 
315  _tf_keeper(std::make_shared<time_diff_keeper>(this, 100))
316  {}
317 
319  {
320  if (is_enable)
321  _tf_keeper->start();
322  else
323  _tf_keeper->stop();
324  }
325 }
void get_a_b(double x, double &a, double &b) const
static const textual_icon lock
Definition: model-views.h:218
time_diff_keeper(global_time_interface *dev, const unsigned int sampling_interval_ms)
static const double TIMESTAMP_USEC_TO_MSEC
Definition: src/types.h:92
GLboolean GLboolean GLboolean b
GLint y
rs2_timestamp_domain get_frame_timestamp_domain(const std::shared_ptr< frame_interface > &frame) const override
double get_system_hw_time(double crnt_hw_time, bool &is_ready)
double dt
Definition: boing.c:106
std::shared_ptr< global_time_option > _option_is_enabled
GLdouble n
Definition: glext.h:1966
GLboolean GLboolean GLboolean GLboolean a
GLuint GLfloat * val
std::shared_ptr< time_diff_keeper > _tf_keeper
std::unique_ptr< frame_timestamp_reader > _device_timestamp_reader
unsigned long long get_frame_counter(const std::shared_ptr< frame_interface > &frame) const override
GLdouble x
virtual double get_device_time_ms()=0
#define LOG_ERROR(...)
Definition: src/types.h:242
std::weak_ptr< time_diff_keeper > _time_diff_keeper
auto operator+=(std::string &lhs, StringRef const &sr) -> std::string &
auto dispatcher
global_timestamp_reader(std::unique_ptr< frame_timestamp_reader > device_timestamp_reader, std::shared_ptr< time_diff_keeper > timediff, std::shared_ptr< global_time_option >)
const char * what() const noexceptoverride
Definition: src/types.h:284
GLint GLsizei count
typename::boost::move_detail::remove_reference< T >::type && move(T &&t) BOOST_NOEXCEPT
#define LOG_DEBUG(...)
Definition: src/types.h:239
bool try_sleep(std::chrono::milliseconds::rep ms)
Definition: concurrency.h:204
void polling(dispatcher::cancellable_timer cancellable_timer)
rs2_time_t get_frame_timestamp(const std::shared_ptr< frame_interface > &frame) override
rs2_timestamp_domain
Specifies the clock in relation to which the frame timestamp was measured.
Definition: rs_frame.h:19


librealsense2
Author(s): Sergey Dorodnicov , Doron Hirshberg , Mark Horn , Reagan Lopez , Itay Carpis
autogenerated on Mon May 3 2021 02:47:16