depth-quality-model.h
Go to the documentation of this file.
1 /* License: Apache 2.0. See LICENSE file in root directory. */
2 /* Copyright(c) 2019 Intel Corporation. All Rights Reserved. */
3 #pragma once
4 
5 #include <librealsense2/rs.hpp>
6 
7 #include "depth-metrics.h"
8 #include "model-views.h"
9 #include "viewer.h"
10 #include "ux-window.h"
11 #include "os.h"
12 
13 #include <tuple>
14 #include <vector>
15 #include <thread>
16 #include <mutex>
17 
18 namespace rs2
19 {
20  namespace depth_quality
21  {
22  class metrics_model;
23 
24  struct sample
25  {
26  sample(std::vector<single_metric_data> samples, double timestamp, unsigned long long frame_number) :
27  samples(std::move(samples)), timestamp(timestamp), frame_number(frame_number) {}
28 
29  std::vector<single_metric_data> samples;
30 
31  double timestamp;
32  unsigned long long frame_number;
33  };
34 
36  {
39  };
40 
42  {
43  public:
45  _recording(false), _viewer_model(viewer_model)
46  {}
47 
49  {
50  std::lock_guard<std::mutex> lock(_m);
51  _metric_data.push_back(data);
52  }
53 
54  void add_sample(rs2::frameset& frames, std::vector<single_metric_data> sample)
55  {
56  std::lock_guard<std::mutex> lock(_m);
57  if (_recording)
58  {
59  record_frames(frames);
60 
61  if (sample.size())
62  _samples.push_back({ sample, _model_timer.get_elapsed_ms(), frames.get_frame_number() });
63  }
64  }
66  {
67  std::lock_guard<std::mutex> lock(_m);
68  _metrics = metrics;
69  if (auto ret = file_dialog_open(save_file, NULL, NULL, NULL))
70  {
71  _filename_base = ret;
72  _recording = true;
73  }
74  }
75 
77  {
78  std::lock_guard<std::mutex> lock(_m);
79  _recording = false;
80  serialize_to_csv();
81 
82  if (dev)
83  {
84  if (auto adv = dev->dev.as<rs400::advanced_mode>())
85  {
86  std::string filename = _filename_base + "_configuration.json";
87  std::ofstream out(filename);
88  try
89  {
90  out << adv.serialize_json();
91  }
92  catch (...)
93  {
94  _viewer_model.not_model->add_notification(notification_data{ to_string() << "Metrics Recording: JSON Serializaion has failed",
96  }
97  }
98  }
99  _samples.clear();
100  _viewer_model.not_model->add_notification(notification_data{ to_string() << "Finished to record frames and matrics data " ,
102  }
103 
105  {
106  return _recording;
107  }
108 
109  private:
110  void serialize_to_csv() const;
111  void record_frames(const frameset & frame);
113  std::vector<metric_definition> _metric_data;
114  std::vector<sample> _samples;
116  std::mutex _m;
122  };
123 
124  class metric_plot : public std::enable_shared_from_this<metric_plot>
125  {
126  public:
127  enum range
128  {
132  MAX_RANGE
133  };
134 
135  std::shared_ptr<metric_plot> set(range r, float from, float to)
136  {
137  ranges[r].x = from;
138  ranges[r].y = to;
139  return shared_from_this();
140  }
141 
142  range get_range(float val) const
143  {
144  for (int i = 0; i < MAX_RANGE; i++)
145  {
146  if (ranges[i].x < val && val <= ranges[i].y)
147  return (range)i;
148  }
149  return MAX_RANGE;
150  }
151 
152  metric_plot(const std::string& name, float min, float max,
153  const std::string& units, const std::string& description,
154  const bool with_plane_fit)
155  : _idx(0), _first_idx(0),_vals(), _min(min), _max(max), _id("##" + name),
156  _label(name + " = "), _name(name),
157  _units(units), _description(description),
158  _enabled(true),
159  _requires_plane_fit(with_plane_fit),
160  _trending_up(std::chrono::milliseconds(700)),
161  _trending_down(std::chrono::milliseconds(700)),
162  _persistent_visibility(std::chrono::milliseconds(2000)) // The metric's status will be absorbed to make the UI persistent
163  {
164  for (int i = 0; i < MAX_RANGE; i++) ranges[i] = { 0.f, 0.f };
165  }
167 
168  void add_value(float val)
169  {
170  std::lock_guard<std::mutex> lock(_m);
171  _vals[_idx] = val;
172  _timestamps[_idx] = _model_timer.get_elapsed_ms();
173  _idx = (_idx + 1) % SIZE;
174  if (_first_idx== _idx)
175  _first_idx = (_first_idx + 1) % SIZE;
176  }
177 
178  void render(ux_window& win);
179 
180  void visible(bool is_visible)
181  {
182  std::lock_guard<std::mutex> lock(_m);
183  _persistent_visibility.add_value(is_visible);
184  }
185 
186  void enable(bool enable)
187  {
188  std::lock_guard<std::mutex> lock(_m);
189  if (enable != _enabled)
190  {
191  _persistent_visibility.reset();
192  _enabled = enable;
193  }
194  }
195 
196  bool enabled() const { return _enabled; }
197  bool requires_plane_fit() const { return _requires_plane_fit; }
198  std::string get_name() { return _name; }
199 
200  private:
201  bool has_trend(bool positive);
202 
203  std::mutex _m;
204  const static size_t SIZE = 200;
205  size_t _idx, _first_idx;
206  std::array<float, SIZE> _vals;
207  std::array<double, SIZE> _timestamps;
208  float _min, _max;
209  std::string _id, _label, _units, _name, _description;
210  bool _enabled;
212 
216  temporal_event _persistent_visibility; // Control the metric visualization
217 
218  float2 ranges[MAX_RANGE];
219 
220  friend class metrics_model; // For CSV export
221  };
222 
224  {
225  public:
227  ~metrics_model();
228 
229  void render(ux_window& win);
230 
231  std::array<float3, 4> get_plane()
232  {
233  std::lock_guard<std::mutex> lock(_m);
234  return _latest_metrics.plane_corners;
235  }
236 
237  void update_stream_attributes(const rs2_intrinsics &intrinsic, float scale_units, float baseline)
238  {
239  std::lock_guard<std::mutex> lock(_m);
240  _depth_intrinsic = intrinsic;
241  _depth_scale_units = scale_units;
242  _stereo_baseline_mm = baseline;
243  };
244 
245  void update_roi_attributes(const region_of_interest& roi, float roi_percent)
246  {
247  std::lock_guard<std::mutex> lock(_m);
248  _roi = roi;
249  _roi_percentage = roi_percent;
250  }
251 
253  {
254  std::lock_guard<std::mutex> lock(_m);
255  return _roi;
256  }
257 
259  {
260  std::lock_guard<std::mutex> lock(_m);
261  return _latest_metrics;
262  }
263 
264  void begin_process_frame(rs2::frame f) { _frame_queue.enqueue(std::move(f)); }
265 
266  void add_metric(std::shared_ptr<metric_plot> metric) { _plots.push_back(metric); }
267 
269 
270  void set_ground_truth(int gt)
271  {
272  std::lock_guard<std::mutex> lock(_m);
273  _ground_truth_mm = gt;
274  _use_gt = true;
275  }
276 
277  void set_plane_fit(bool found)
278  {
279  std::lock_guard<std::mutex> lock(_m);
280  _plane_fit = found;
281  for (auto&& plot : _plots)
282  {
283  if (plot->enabled())
284  {
285  bool val = plot->requires_plane_fit() ? found : true;
286  plot->visible(val);
287  }
288  }
289  }
290 
292  {
293  std::lock_guard<std::mutex> lock(_m);
294  _use_gt = false;
295  _ground_truth_mm = 0;
296  }
297  std::tuple<int, bool> get_inputs() const
298  {
299  std::lock_guard<std::mutex> lock(_m);
300  return std::make_tuple(_ground_truth_mm, _plane_fit);
301  }
302 
303  void reset()
304  {
305  _plane_fit = false;
306  rs2::frame f;
307  while (_frame_queue.poll_for_frame(&f));
308  }
309 
310  void update_device_data(const std::string& camera_info)
311  {
312  _camera_info = camera_info;
313  }
315  {
316  return _recorder.is_recording();
317  }
319  {
320  _recorder.start_record(this);
321  }
323  {
324  _recorder.stop_record(dev);
325  }
326  private:
328 
330  std::thread _worker_thread;
331 
336  bool _use_gt;
341  bool _active;
342  std::vector<std::shared_ptr<metric_plot>> _plots;
345  mutable std::mutex _m;
346 
347  friend class metrics_recorder;
348  friend class tool_model;
349  };
350 
351  using metric = std::shared_ptr<metric_plot>;
352 
354  {
355  public:
357 
358  bool start(ux_window& win);
359 
360  void render(ux_window& win);
361 
362  void update_configuration();
363 
364  void reset(ux_window& win);
365 
366  bool draw_instructions(ux_window& win, const rect& viewer_rect, bool& distance, bool& orientation);
367 
368  void draw_guides(ux_window& win, const rect& viewer_rect, bool distance_guide, bool orientation_guide);
369 
370  std::shared_ptr<metric_plot> make_metric(
371  const std::string& name, float min, float max, bool plane_fit,
372  const std::string& units,
373  const std::string& description);
374 
375  void on_frame(callback_type callback) { _metrics_model.callback = callback; }
376 
377  float get_depth_scale() const { return _metrics_model._depth_scale_units; }
378  rs2::device get_active_device(void) const;
379 
380  private:
381 
382  std::string capture_description();
383 
386  std::shared_ptr<device_model> _device_model;
390  std::shared_ptr<subdevice_model> _depth_sensor_model;
393  bool _first_frame = true;
395  bool _device_in_use = false;
396 
397  float _roi_percent = 0.4f;
398  int _roi_combo_index = 2;
400 
408  std::map<int, temporal_event> _depth_scale_events;
409 
410  float _min_dist, _max_dist, _max_angle;
411  std::mutex _mutex;
412 
413  bool _use_ground_truth = false;
414  int _ground_truth = 0;
415  };
416  }
417 }
void start_record(metrics_model *metrics)
static const textual_icon lock
Definition: model-views.h:218
GLint y
void on_frame(callback_type callback)
GLuint const GLchar * name
utilities::time::stopwatch _model_timer
void add_metric(const metric_definition &data)
GLsizei GLenum const void GLuint GLsizei GLfloat * metrics
Definition: glext.h:10557
GLboolean reset
void update_roi_attributes(const region_of_interest &roi, float roi_percent)
std::array< float3, 4 > get_plane()
metric_plot(const std::string &name, float min, float max, const std::string &units, const std::string &description, const bool with_plane_fit)
utilities::time::periodic_timer _update_readonly_options_timer
std::array< float, SIZE > _vals
Definition: cah-model.h:10
GLsizei const GLchar *const * string
GLsizei GLsizei GLfloat distance
Definition: glext.h:10563
GLuint GLfloat * val
std::shared_ptr< subdevice_model > _depth_sensor_model
GLdouble f
GLdouble GLdouble r
GLdouble x
metrics_recorder(viewer_model &viewer_model)
def callback(frame)
Definition: t265_stereo.py:91
GLuint start
void update_stream_attributes(const rs2_intrinsics &intrinsic, float scale_units, float baseline)
const char * file_dialog_open(file_dialog_mode flags, const char *filters, const char *default_path, const char *default_name)
Definition: os.cpp:169
unsigned long long frame_number
std::shared_ptr< metric_plot > metric
std::array< double, SIZE > _timestamps
std::function< void(const std::vector< rs2::float3 > &points, const plane p, const rs2::region_of_interest roi, const float baseline_mm, const float focal_length_pixels, const int ground_thruth_mm, const bool plane_fit, const float plane_fit_to_ground_truth_mm, const float distance_mm, bool record, std::vector< single_metric_data > &samples)> callback_type
Definition: depth-metrics.h:55
GLfloat units
std::map< int, temporal_event > _depth_scale_events
std::shared_ptr< device_model > _device_model
GLboolean enable
Definition: glext.h:5688
std::vector< single_metric_data > samples
void add_metric(std::shared_ptr< metric_plot > metric)
int min(int a, int b)
Definition: lz4s.c:73
GLsizei samples
typename::boost::move_detail::remove_reference< T >::type && move(T &&t) BOOST_NOEXCEPT
Video stream intrinsics.
Definition: rs_types.h:58
void add_sample(rs2::frameset &frames, std::vector< single_metric_data > sample)
#define NULL
Definition: tinycthread.c:47
int i
sample(std::vector< single_metric_data > samples, double timestamp, unsigned long long frame_number)
std::vector< metric_definition > _metric_data
std::tuple< int, bool > get_inputs() const
Definition: parser.hpp:150
range get_range(float val) const
void update_device_data(const std::string &camera_info)
T as() const
Definition: rs_device.hpp:129
utilities::time::stopwatch _model_timer
std::vector< std::shared_ptr< metric_plot > > _plots
std::string to_string(T value)


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