cpp-config-ui.cpp
Go to the documentation of this file.
1 #include <librealsense/rs.hpp>
2 #include "example.hpp"
3 
4 #include <cstdarg>
5 #include <thread>
6 #include <iostream>
7 #include <algorithm>
8 #include <iomanip>
9 #include <mutex>
10 #include "concurrency.hpp"
11 #include <atomic>
12 #include <map>
13 
14 
15 #pragma comment(lib, "opengl32.lib")
16 
17 template<typename T> inline T MIN(T x, T y) { return x < y ? x : y; }
18 template<typename T> inline T MAX(T x, T y) { return x > y ? x : y; }
19 
20 struct int2 { int x, y; };
21 struct rect
22 {
23  int x0, y0, x1, y1;
24  bool contains(const int2 & p) const { return x0 <= p.x && y0 <= p.y && p.x < x1 && p.y < y1; }
25  rect shrink(int amt) const { return{ x0 + amt, y0 + amt, x1 - amt, y1 - amt }; }
26 };
27 struct color { float r, g, b; };
28 
30 {
31  for (std::string::size_type i = 0; (i = source.find(find, i)) != std::string::npos;)
32  {
33  source.replace(i, find.length(), replace);
34  i += replace.length();
35  }
36  return source;
37 }
38 
39 struct gui
40 {
41  int2 cursor, clicked_offset, scroll_vec;
42  bool click, mouse_down;
44 
45  gui() : scroll_vec({ 0, 0 }), click(), mouse_down(), clicked_id() {}
46 
47  void label(const int2 & p, const color& c, const char * format, ...)
48  {
49  va_list args;
50  va_start(args, format);
51  char buffer[2048];
52  vsnprintf(buffer, sizeof(buffer), format, args);
53  va_end(args);
54 
55  glColor3f(c.r, c.g, c.b);
56  draw_text(p.x, p.y, buffer);
57  }
58 
59  // extended label method for option lines
60  // the purpose is to provide a little more visual context to the various options,
61  // and make config-ui interface more human friendly
62  void option_label(const int2& p, const color& c, rs::device& dev, rs::option opt, double max_width, bool enabled, double* value = nullptr)
63  {
64  auto name = find_and_replace(rs_option_to_string((rs_option)opt), "_", " "); // replacing _ with ' ' to reduce visual clutter
66 
67  auto size = name.size(); // align the string to max. allowed width
68  while (size > 0 && stb_easy_font_width((char*)s.c_str()) > max_width)
69  {
70  s = name.substr(0, size--) + "...";
71  }
72 
73  // remove option prefixes converting them to visual hints through color:
74  color newC = c;
75 #define STRING_CASE(S, C) std::string S = #S; if (s.compare(0, S.length(), S) == 0) { newC = C; s = find_and_replace(s, S + " ", ""); }
76  color color1 = { 0.6f, 1.0f, 1.0f };
77  color color2 = { 1.0f, 0.6f, 1.0f };
78  color color3 = { 1.0f, 1.0f, 0.6f };
79  color color4 = { 1.0f, 0.6f, 0.6f };
80  color color5 = { 0.6f, 0.6f, 1.0f };
81  color color6 = { 0.6f, 1.0f, 0.6f };
82  STRING_CASE(ZR300, color1)
83  STRING_CASE(F200, color2)
84  STRING_CASE(SR300, color3)
85  STRING_CASE(R200, color4)
86  STRING_CASE(FISHEYE, color5)
87  STRING_CASE(COLOR, color6)
88  if (!enabled) newC = { 0.5f, 0.5f, 0.5f };
89 
90  auto w = stb_easy_font_width((char*)s.c_str());
91  label(p, newC, s.c_str());
92  // if value is required, append it at the end of the string
93  if (value)
94  {
95  std::stringstream sstream;
96  sstream << ": " << *value;
97  int2 newP{ p.x + w, p.y };
98  label(newP, c, sstream.str().c_str());
99  }
100 
101  rect bbox{ p.x - 15, p.y - 10, p.x + w + 10, p.y + 5 };
102  if (bbox.contains(cursor))
103  {
104  std::string hint = dev.get_option_description(opt);
105  auto hint_w = stb_easy_font_width((char*)hint.c_str());
106  fill_rect({ cursor.x - hint_w - 7, cursor.y + 5, cursor.x + 7, cursor.y - 17 }, { 1.0f, 1.0f, 1.0f });
107  fill_rect({ cursor.x - hint_w - 6, cursor.y + 4, cursor.x + 6, cursor.y - 16 }, { 0.0f, 0.0f, 0.0f });
108  label({ cursor.x - hint_w, cursor.y - 2 }, { 1.f, 1.f, 1.f }, hint.c_str());
109  }
110  }
111 
112  void fill_rect(const rect & r, const color & c)
113  {
114  glBegin(GL_QUADS);
115  glColor3f(c.r, c.g, c.b);
116  glVertex2i(r.x0, r.y0);
117  glVertex2i(r.x0, r.y1);
118  glVertex2i(r.x1, r.y1);
119  glVertex2i(r.x1, r.y0);
120  glEnd();
121  }
122 
123  void outline_rect(const rect & r, const color & c)
124  {
125  glPushAttrib(GL_ENABLE_BIT);
126 
127  glLineStipple(1, 0xAAAA);
128  glEnable(GL_LINE_STIPPLE);
129 
130  glBegin(GL_LINE_STRIP);
131  glColor3f(c.r, c.g, c.b);
132  glVertex2i(r.x0, r.y0);
133  glVertex2i(r.x0, r.y1);
134  glVertex2i(r.x1, r.y1);
135  glVertex2i(r.x1, r.y0);
136  glVertex2i(r.x0, r.y0);
137  glEnd();
138 
139  glPopAttrib();
140  }
141 
142  bool button(const rect & r, const std::string & label)
143  {
144  fill_rect(r, { 1, 1, 1 });
145  fill_rect(r.shrink(2), r.contains(cursor) ? (mouse_down ? color{ 0.3f, 0.3f, 0.3f } : color{ 0.4f, 0.4f, 0.4f }) : color{ 0.5f, 0.5f, 0.5f });
146  glColor3f(1, 1, 1);
147  draw_text(r.x0 + 4, r.y1 - 8, label.c_str());
148  return click && r.contains(cursor);
149  }
150 
151  bool checkbox(const rect & r, bool & value)
152  {
153  bool changed = false;
154  if (click && r.contains(cursor))
155  {
156  value = !value;
157  changed = true;
158  }
159  fill_rect(r, { 1, 1, 1 });
160  fill_rect(r.shrink(1), { 0.5, 0.5, 0.5 });
161  if (value) fill_rect(r.shrink(3), { 1, 1, 1 });
162  return changed;
163  }
164 
165  bool slider(int id, const rect & r, double min, double max, double step, double & value, bool disable_dragger = false)
166  {
167  bool changed = false;
168  const int w = r.x1 - r.x0, h = r.y1 - r.y0;
169  double p = (w - h) * (value - min) / (max - min);
170  if (mouse_down && clicked_id == id)
171  {
172  p = std::max(0.0, std::min<double>(cursor.x - clicked_offset.x - r.x0, w - h));
173  double new_value = min + p * (max - min) / (w - h);
174  if (step) new_value = std::round((new_value - min) / step) * step + min;
175  changed = new_value != value;
176  value = new_value;
177  p = (w - h) * (value - min) / (max - min);
178  }
179  const rect dragger = { int(r.x0 + p), int(r.y0), int(r.x0 + p + h), int(r.y1) };
180  if (click && dragger.contains(cursor) && !disable_dragger)
181  {
182  clicked_offset = { cursor.x - dragger.x0, cursor.y - dragger.y0 };
183  clicked_id = id;
184  }
185  fill_rect(r, { 0.5, 0.5, 0.5 });
186 
187  if (!disable_dragger)
188  fill_rect(dragger, { 1, 1, 1 });
189 
190  return changed;
191  }
192 
193  void indicator(const rect & r, double min, double max, double value)
194  {
195  value = MAX(min, MIN(max, value));
196  const int w = r.x1 - r.x0, h = r.y0 - r.y1;
197  double p = (w)* (value - min) / (max - min);
198  int Xdelta = 1;
199  int Ydelta = -1;
200  if (value == max)
201  {
202  Xdelta = 0;
203  Ydelta = -2;
204  }
205  else if (value == min)
206  {
207  Xdelta = 2;
208  Ydelta = 0;
209  }
210 
211  const rect dragger = { int(r.x0 + p + Xdelta), int(r.y0), int(r.x0 + p + Ydelta), int(r.y1) };
212  fill_rect(r, { 0.5, 0.5, 0.5 });
213  fill_rect(dragger, { 1, 1, 1 });
214  glColor3f(1, 1, 1);
215 
216  std::ostringstream oss;
217  oss << std::setprecision(2) << std::fixed << min;
218  auto delta = (min < 0) ? 40 : 22;
219  draw_text(r.x0 - delta, r.y1 + abs(h / 2) + 3, oss.str().c_str());
220 
221  oss.str("");
222  oss << std::setprecision(2) << std::fixed << max;
223  draw_text(r.x1 + 6, r.y1 + abs(h / 2) + 3, oss.str().c_str());
224 
225  oss.str("");
226  oss << std::setprecision(2) << std::fixed << value;
227  draw_text(dragger.x0 - 1, dragger.y0 + 12, oss.str().c_str());
228  }
229 
230  void vscroll(const rect & r, int client_height, int & offset)
231  {
232  if (r.contains(cursor)) offset -= scroll_vec.y * 20;
233  offset = std::min(offset, client_height - (r.y1 - r.y0));
234  offset = std::max(offset, 0);
235  if (client_height <= r.y1 - r.y0) return;
236  auto bar = r; bar.x0 = bar.x1 - 10;
237  auto dragger = bar;
238  dragger.y0 = bar.y0 + offset * (r.y1 - r.y0) / client_height;
239  dragger.y1 = bar.y0 + (offset + r.y1 - r.y0) * (r.y1 - r.y0) / client_height;
240  fill_rect(bar, { 0.5, 0.5, 0.5 });
241  fill_rect(dragger, { 1, 1, 1 });
242  }
243 };
244 
245 
246 std::mutex mm_mutex;
249 
251 {
252  std::lock_guard<std::mutex> lock(mm_mutex);
254  m_acc_data = entry;
256  m_gyro_data = entry;
257 }
258 
260 {
261 }
262 
263 struct user_data
264 {
265  GLFWwindow* curr_window = nullptr;
266  gui* g = nullptr;
267 };
268 
269 void show_message(GLFWwindow* curr_window, const std::string& title, const std::string& message)
270 {
271  glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);
272  glfwWindowHint(GLFW_FLOATING, GL_TRUE);
273 
274  int xpos, ypos;
275  glfwGetWindowPos(curr_window, &xpos, &ypos);
276 
277  int width, height;
278  glfwGetWindowSize(curr_window, &width, &height);
279 
280  int close_win_width = 550;
281  int close_win_height = 150;
282  auto closeWin = glfwCreateWindow(close_win_width, close_win_height, title.c_str(), nullptr, nullptr);
283  glfwMakeContextCurrent(closeWin);
284  glfwSetWindowPos(closeWin, xpos + width / 2 - close_win_width / 2, ypos + height / 2 - close_win_height / 2);
285 
286  gui g;
287 
288  user_data data;
289  data.curr_window = curr_window;
290  data.g = &g;
291 
292  glfwSetWindowUserPointer(closeWin, &data);
293  glfwSetWindowCloseCallback(closeWin, [](GLFWwindow* w) {
295  });
296 
297  glfwSetCursorPosCallback(closeWin, [](GLFWwindow * w, double cx, double cy) { reinterpret_cast<user_data *>(glfwGetWindowUserPointer(w))->g->cursor = { (int)cx, (int)cy }; });
298  glfwSetScrollCallback(closeWin, [](GLFWwindow * w, double x, double y) { reinterpret_cast<user_data *>(glfwGetWindowUserPointer(w))->g->scroll_vec = { (int)x, (int)y }; });
299 
300  glfwSetMouseButtonCallback(closeWin, [](GLFWwindow * w, int button, int action, int mods)
301  {
302  auto data = reinterpret_cast<user_data *>(glfwGetWindowUserPointer(w));
303  if (action == GLFW_PRESS)
304  {
305  data->g->clicked_id = 0;
306  data->g->click = true;
307  }
308  data->g->mouse_down = action != GLFW_RELEASE;
309  });
310 
311 
312  while (!glfwWindowShouldClose(closeWin))
313  {
314  glfwPollEvents();
315  int w, h;
316  glfwGetFramebufferSize(closeWin, &w, &h);
317  glViewport(0, 0, w, h);
318  glClear(GL_COLOR_BUFFER_BIT);
319 
320  glfwGetWindowSize(closeWin, &w, &h);
321  glLoadIdentity();
322  glOrtho(0, w, h, 0, -1, +1);
323 
324 
325  size_t line_lenght = 80;
326  int2 p;
327  p.x = 20;
328  p.y = 30;
329  if (message.size() < line_lenght)
330  {
331  g.label(p, { 1, 1, 1 }, message.c_str());
332  }
333  else
334  {
335  std::vector<std::string> str_vec;
336  std::string temp_message = message;
337  temp_message = find_and_replace(temp_message, "\n", " ");
338  size_t index = 0;
339  size_t string_size = temp_message.size();
340  while (index < string_size)
341  {
342  if (index + line_lenght >= string_size)
343  {
344  str_vec.push_back(temp_message.substr(index));
345  break;
346  }
347 
348  auto curr_index = index + temp_message.substr(index, line_lenght).find_last_of(' ');
349 
350  str_vec.push_back(temp_message.substr(index, curr_index - index));
351  index = curr_index;
352  }
353 
354  for (auto& elem : str_vec)
355  {
356  g.label(p, { 1, 1, 1 }, elem.c_str());
357  p.y += 15;
358  }
359 
360  if (p.y > 100)
361  glfwSetWindowSize(closeWin, close_win_width, p.y + 50);
362  }
363 
364  if (g.button({ w / 2 - 40, h - 40, w / 2 + 40, h - 10 }, " OK"))
365  {
366  glfwDestroyWindow(closeWin);
367  }
368 
369  glfwSwapBuffers(closeWin);
370  g.click = false;
371  if (!g.mouse_down) g.clicked_id = 0;
372  }
373  glfwMakeContextCurrent(curr_window);
374 }
375 
376 struct option { rs::option opt; double min, max, step, value, def; bool supports; };
377 
378 static std::map<rs::option, std::vector<rs::option>> options_dependencies =
379 {
393  } },
398 };
399 
400 void update_related_options(rs::device& dev, rs::option opt, std::vector<option>& options)
401 {
402  auto it = options_dependencies.find(opt);
403  if (it != options_dependencies.end())
404  {
405  for (auto& related : it->second)
406  {
407  auto opt_it = std::find_if(options.begin(), options.end(), [related](option o) { return related == o.opt; });
408  if (opt_it != options.end())
409  {
410  try
411  {
412  if (!dev.supports_option(opt_it->opt)) continue;
413  dev.get_option_range(opt_it->opt, opt_it->min, opt_it->max, opt_it->step, opt_it->def);
414  opt_it->value = dev.get_option(opt_it->opt);
415  }
416  catch (...) {}
417  }
418  }
419  }
420 }
421 
423 {
424  bool sts = false;
425  for (auto i = 0; i < 5; i++)
426  {
427  if (dev->is_stream_enabled((rs::stream)i))
428  {
429  sts = true;
430  break;
431  }
432  }
433 
434  return sts;
435 }
436 
438 void enable_stream(rs::device * dev, int stream, rs::format format, int w, int h, int fps, bool enable, std::stringstream& stream_name)
439 {
440  stream_name.str("");
441  if (stream == RS_CAPABILITIES_MOTION_EVENTS)
442  {
443  stream_name << "MOTION EVENTS";
444 
445  if (dev->is_motion_tracking_active())
446  return;
447 
448  if (enable)
449  {
451  motion_tracking_enable = true;
452  }
453  else
454  {
456  motion_tracking_enable = false;
457  }
458  }
459  else
460  {
461  stream_name << rs_stream_to_string((rs_stream)stream);
462  if (enable)
463  {
464  if (!dev->is_stream_enabled((rs::stream)stream))
465  dev->enable_stream((rs::stream)stream, w, h, format, fps);
466  }
467  else
468  {
469  if (dev->is_stream_enabled((rs::stream)stream))
470  dev->disable_stream((rs::stream)stream);
471  }
472  }
473 }
474 
476 {
477  int x = w / 3 + 10;
478  int y = 2 * h / 3 + 5;
479  auto rect_y0_pos = y + 36;
480  auto rect_y1_pos = y + 28;
481  auto indicator_width = 42;
482 
483  buffers[5].print(x, rect_y0_pos - 10, "Gyro X: ");
484  g.indicator({ x + 100, rect_y0_pos, x + 300, rect_y1_pos }, -10, 10, m_gyro_data.axes[0]);
485  rect_y0_pos += indicator_width;
486  rect_y1_pos += indicator_width;
487 
488  buffers[5].print(x, rect_y0_pos - 10, "Gyro Y: ");
489  g.indicator({ x + 100, rect_y0_pos, x + 300, rect_y1_pos }, -10, 10, m_gyro_data.axes[1]);
490  rect_y0_pos += indicator_width;
491  rect_y1_pos += indicator_width;
492 
493  buffers[5].print(x, rect_y0_pos - 10, "Gyro Z: ");
494  g.indicator({ x + 100, rect_y0_pos, x + 300, rect_y1_pos }, -10, 10, m_gyro_data.axes[2]);
495  rect_y0_pos += indicator_width;
496  rect_y1_pos += indicator_width;
497 
498  buffers[5].print(x, rect_y0_pos - 10, "Acc X: ");
499  g.indicator({ x + 100, rect_y0_pos, x + 300, rect_y1_pos }, -10, 10, m_acc_data.axes[0]);
500  rect_y0_pos += indicator_width;
501  rect_y1_pos += indicator_width;
502 
503  buffers[5].print(x, rect_y0_pos - 10, "Acc Y: ");
504  g.indicator({ x + 100, rect_y0_pos, x + 300, rect_y1_pos }, -10, 10, m_acc_data.axes[1]);
505  rect_y0_pos += indicator_width;
506  rect_y1_pos += indicator_width;
507 
508  buffers[5].print(x, rect_y0_pos - 10, "Acc Z: ");
509  g.indicator({ x + 100, rect_y0_pos, x + 300, rect_y1_pos }, -10, 10, m_acc_data.axes[2]);
510 }
511 
512 double find_option_value(const std::vector<option>& options, rs::option opt)
513 {
514  auto it = find_if(options.begin(), options.end(), [opt](option o) { return o.opt == opt; });
515  if (it == options.end()) return 0.0;
516  return it->value;
517 }
518 
519 void draw_autoexposure_roi_boundary(rs::stream s, const std::vector<option>& options, rs::device* dev, gui& g, int x, int y, double w, double h)
520 {
521  if ((s == rs::stream::depth || s == rs::stream::infrared) &&
523  {
524  auto intrinsics = dev->get_stream_intrinsics(s);
525  auto width = intrinsics.width;
526  auto height = intrinsics.height;
527 
532 
533  left = x + left * w;
534  right = x + right * w;
535  top = y + top * h;
536  bottom = y + bottom * h;
537 
538  g.outline_rect({ (int)left + 1, (int)top + 1, (int)right - 1, (int)bottom - 1 }, { 1.0f, 1.0f, 1.0f });
539  g.label({ (int)left + 4, (int)bottom - 6 }, { 1.0f, 1.0f, 1.0f }, "AE ROI");
540  }
541 }
542 
543 int main(int argc, char * argv[])
544 {
546  GLFWwindow* win = nullptr;
547  const auto streams = (unsigned short)rs::stream::fisheye + 1; // Use camera-supported native streams
548  gui g = {};
549  rs::device * dev = nullptr;
550  std::atomic<bool> running(true);
551  bool has_motion_module = false;
552  single_consumer_queue<rs::frame> frames_queue[streams];
553  std::vector<option> options;
554  texture_buffer buffers[streams];
555  struct resolution
556  {
557  int width;
558  int height;
560  };
561  std::map<rs::stream, resolution> resolutions;
562 
563  std::vector<int> req_fps = { 30, 30, 30, 30, 60, 30 };
564  struct w_h { int width, height; };
566  std::vector<w_h> wh = { { 0,0 }, { 640,480 }, { 0,0 }, { 0,0 }, { 640,480 }, {0,0}};
567 
568  try {
570  //rs::log_to_file(rs::log_severity::debug, "librealsense.log");
571 
572  glfwInit();
573  glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);
574  win = glfwCreateWindow(1550, 960, "CPP Configuration Example", nullptr, nullptr);
575 
577 
578  glfwSetWindowUserPointer(win, &g);
579  glfwSetCursorPosCallback(win, [](GLFWwindow * w, double cx, double cy) { reinterpret_cast<gui *>(glfwGetWindowUserPointer(w))->cursor = { (int)cx, (int)cy }; });
580  glfwSetScrollCallback(win, [](GLFWwindow * w, double x, double y) { reinterpret_cast<gui *>(glfwGetWindowUserPointer(w))->scroll_vec = { (int)x, (int)y }; });
581  glfwSetMouseButtonCallback(win, [](GLFWwindow * w, int button, int action, int mods)
582  {
583  auto g = reinterpret_cast<gui *>(glfwGetWindowUserPointer(w));
584  if (action == GLFW_PRESS)
585  {
586  g->clicked_id = 0;
587  g->click = true;
588  }
589  g->mouse_down = action != GLFW_RELEASE;
590  });
591 
592 
593  if (ctx.get_device_count() < 1) throw std::runtime_error("No device found. Is it plugged in?");
594 
595  dev = ctx.get_device(0);
596 
597  for (int stream = 0; stream < streams; stream++)
598  {
599  if (dev->supports((rs::capabilities)stream))
600  {
601  dev->enable_stream((rs::stream)stream, wh[stream].width, wh[stream].height, formats[stream], req_fps[stream]);
602  resolutions[(rs::stream)stream] = { dev->get_stream_width((rs::stream)stream), dev->get_stream_height((rs::stream)stream), formats[stream] };
603  }
604  }
605 
607 
608  if (has_motion_module)
609  {
611  {
613  }
614 
615  glfwSetWindowSize(win, 1100, 960);
616  }
617 
618  for (int i = 0; i < RS_OPTION_COUNT; ++i)
619  {
620  option o = { (rs::option)i };
621  try {
622  o.supports = dev->supports_option(o.opt);
623  if (o.supports)
624  {
625  dev->get_option_range(o.opt, o.min, o.max, o.step, o.def);
626  o.value = dev->get_option(o.opt);
627  }
628  options.push_back(o);
629  }
630  catch (...) {}
631  }
632  }
633  catch (const rs::error & e)
634  {
635  std::stringstream ss;
636  ss << "RealSense error calling " << e.get_failed_function() << "(" << e.get_failed_args() << "):\n " << e.what() << std::endl;
637  std::cerr << ss.str();
638  show_message(win, "Exception", ss.str());
639  return 1;
640  }
641  catch (const std::exception & e)
642  {
643  std::cerr << e.what() << std::endl;
644  show_message(win, "Exception", e.what());
645  return 1;
646  }
647  catch (...)
648  {
649  std::cerr << "Unresolved error type during camera initialization" << std::endl;
650  show_message(win, "Exception", "Unresolved error type during camera initialization");
651  return 1;
652  }
653 
654  rs::format format[streams] = {};
655  unsigned long long frame_number[streams] = {};
656  double frame_timestamp[streams] = {};
657  int fps[streams] = {};
658  double dc_preset = 0, iv_preset = 0;
659  int offset = 0, panel_height = 1;
660  int gui_click_flag = 0;
661 
662  while (true)
663  {
664  try
665  {
666  while (!glfwWindowShouldClose(win))
667  {
668  glfwPollEvents();
669  rs::frame frame;
670 
671  int w, h;
672  glfwGetFramebufferSize(win, &w, &h);
673  glViewport(0, 0, w, h);
674  glClear(GL_COLOR_BUFFER_BIT);
675 
676  glfwGetWindowSize(win, &w, &h);
677  glLoadIdentity();
678  glOrtho(0, w, h, 0, -1, +1);
679 
680  g.vscroll({ w - 270, 0, w, h }, panel_height, offset);
681  int y = 10 - offset;
682 
683  if (dev->is_streaming() || dev->is_motion_tracking_active())
684  {
685  if (g.button({ w - 260, y, w - 20, y + 24 }, "Stop Capture"))
686  {
687  if (is_any_stream_enable(dev))
688  {
689  running = false;
690  for (auto i = 0; i < 5; i++) frames_queue[i].clear();
691  dev->stop();
692  }
693 
694  if (has_motion_module && motion_tracking_enable)
695  {
696  running = false;
698  }
699  }
700  }
701  else
702  {
703  if (g.button({ w - 260, y, w - 20, y + 24 }, "Start Capture"))
704  {
705  std::vector<rs::stream> supported_streams;
706  for (int i = (int)rs::capabilities::depth; i <= (int)rs::capabilities::fish_eye; i++)
707  if (dev->supports((rs::capabilities)i))
708  supported_streams.push_back((rs::stream)i);
709  for (auto & stream : supported_streams)
710  {
711  if (!dev->is_stream_enabled(stream)) continue;
712  auto intrin = dev->get_stream_intrinsics(stream);
713  std::cout << "Capturing " << stream << " at " << intrin.width << " x " << intrin.height;
714  std::cout << std::setprecision(1) << std::fixed << ", fov = " << intrin.hfov() << " x " << intrin.vfov() << ", distortion = " << intrin.model() << std::endl;
715  }
716 
717  if (has_motion_module && motion_tracking_enable)
718  {
719  running = true;
721  }
722 
723  if (is_any_stream_enable(dev))
724  {
725  running = true;
726  dev->start();
727  }
728  }
729  }
730  y += 34;
731  if (!dev->is_streaming())
732  {
733  for (int i = 0; i <= RS_CAPABILITIES_MOTION_EVENTS; ++i)
734  {
735  auto s = (rs::stream)i;
736  auto cap = (rs::capabilities)i;
737  std::stringstream stream_name;
738 
739  if (dev->supports(cap))
740  {
741  static bool is_callback_set = false;
742  bool enable;
744  enable = motion_tracking_enable;
745  else
746  enable = dev->is_stream_enabled(s);
747 
748  enable_stream(dev, i, formats[i], wh[i].width, wh[i].height, req_fps[i], enable, stream_name);
749 
750  if (!is_callback_set || g.checkbox({ w - 260, y, w - 240, y + 20 }, enable))
751  {
752  enable_stream(dev, i, formats[i], wh[i].width, wh[i].height, req_fps[i], enable, stream_name);
753 
754  if (enable)
755  {
756  static const auto max_queue_size = 2;
757  for (auto i = 0; i < 5; i++)
758  {
759  dev->set_frame_callback((rs::stream)i, [dev, &buffers, &running, &frames_queue, &resolutions, i](rs::frame frame)
760  {
761  if (running && frames_queue[i].size() < max_queue_size)
762  {
763  frames_queue[i].enqueue(std::move(frame));
764  }
765  });
766  }
767  }
768  is_callback_set = true;
769  }
770  g.label({ w - 234, y + 13 }, { 1, 1, 1 }, "Enable %s", stream_name.str().c_str());
771  y += 30;
772  }
773  }
774  }
775 
776  if (dev->is_streaming() || dev->is_motion_tracking_active())
777  {
778  auto new_w = w + (has_motion_module ? 150 : -280);
779 
780  int scale_factor = (has_motion_module ? 3 : 2);
781  int fWidth = new_w / scale_factor;
782  int fHeight = h / scale_factor;
783 
784  static struct position { int rx, ry, rw, rh; } pos_vec[5];
785  pos_vec[0] = position{ fWidth, 0, fWidth, fHeight };
786  pos_vec[1] = position{ 0, 0, fWidth, fHeight };
787  pos_vec[2] = position{ 0, fHeight, fWidth, fHeight };
788  pos_vec[3] = position{ fWidth, fHeight, fWidth, fHeight };
789  pos_vec[4] = position{ 0, 2 * fHeight, fWidth, fHeight };
790  position center_position = position{ 0, 0, fWidth * 2, fHeight * 2 };
791  position prev_pos;
792  bool g_clicked = g.click;
793  static int frame_clicked[5] = {};
794 
795  for (auto i = 0; i < 5; i++)
796  {
797  if (!dev->is_stream_enabled((rs::stream)i))
798  continue;
799 
800  if (frames_queue[i].try_dequeue(&frame))
801  {
802  buffers[i].upload(frame);
803  format[i] = frame.get_format();
804  frame_number[i] = frame.get_frame_number();
805  frame_timestamp[i] = frame.get_timestamp();
806  fps[i] = frame.get_framerate();
807  }
808 
809  if (g_clicked && gui_click_flag &&
810  g.cursor.x >= center_position.rx && g.cursor.x <= (center_position.rw + center_position.rx) &&
811  g.cursor.y >= center_position.ry && g.cursor.y <= (center_position.rh + center_position.ry))
812  {
813  pos_vec[i] = prev_pos;
814  gui_click_flag = !gui_click_flag;
815  for (int j = 0; j < 5; ++j)
816  frame_clicked[j] = false;
817 
818  g_clicked = false;
819  }
820  else if (g_clicked && !gui_click_flag &&
821  g.cursor.x >= pos_vec[i].rx && g.cursor.x <= (pos_vec[i].rw + pos_vec[i].rx) &&
822  g.cursor.y >= pos_vec[i].ry && g.cursor.y <= (pos_vec[i].rh + pos_vec[i].ry))
823  {
824  gui_click_flag = !gui_click_flag;
825  frame_clicked[i] = gui_click_flag;
826  g_clicked = false;
827  }
828 
829  if (frame_clicked[i])
830  {
831  prev_pos = pos_vec[i];
832  pos_vec[i] = center_position;
833  buffers[i].show((rs::stream)i, format[i], fps[i], frame_number[i], frame_timestamp[i], pos_vec[i].rx, pos_vec[i].ry, pos_vec[i].rw, pos_vec[i].rh, resolutions[(rs::stream)i].width, resolutions[(rs::stream)i].height);
834  }
835  else if (!gui_click_flag)
836  buffers[i].show((rs::stream)i, format[i], fps[i], frame_number[i], frame_timestamp[i], pos_vec[i].rx, pos_vec[i].ry, pos_vec[i].rw, pos_vec[i].rh, resolutions[(rs::stream)i].width, resolutions[(rs::stream)i].height);
837 
838  if (frame_clicked[i])
839  draw_autoexposure_roi_boundary((rs::stream)i, options, dev, g, center_position.rx, center_position.ry, center_position.rw, center_position.rh);
840  else if (!gui_click_flag)
841  draw_autoexposure_roi_boundary((rs::stream)i, options, dev, g, pos_vec[i].rx, pos_vec[i].ry, fWidth, fHeight);
842  }
843 
844  if (has_motion_module && motion_tracking_enable)
845  {
846  std::lock_guard<std::mutex> lock(mm_mutex);
847  update_mm_data(buffers, new_w, h, g);
848  }
849  }
850 
851  for (auto & o : options)
852  {
853  if (!dev->supports_option(o.opt))
854  {
855  o.supports = false;
856  continue;
857  }
858  if (!o.supports)
859  {
860  try {
861  dev->get_option_range(o.opt, o.min, o.max, o.step, o.def);
862  o.value = dev->get_option(o.opt);
863  }
864  catch (...) {}
865  o.supports = true;
866  }
867 
868  auto is_checkbox = (o.min == 0) && (o.max == 1) && (o.step == 1);
869  auto is_checked = o.value > 0;
870 
871  if (is_checkbox ?
872  g.checkbox({ w - 260, y + 10, w - 240, y + 30 }, is_checked) :
873  g.slider((int)o.opt + 1, { w - 260, y + 16, w - 20, y + 36 }, o.min, o.max, o.step, o.value))
874  {
875  if (is_checkbox) dev->set_option(o.opt, is_checked ? 1 : 0);
876  else dev->set_option(o.opt, o.value);
877 
878  update_related_options(*dev, o.opt, options);
879 
880  o.value = dev->get_option(o.opt);
881  }
882 
883  if (is_checkbox) g.option_label({ w - 230, y + 24 }, { 1, 1, 1 }, *dev, o.opt, 210, true);
884  else g.option_label({ w - 260, y + 12 }, { 1, 1, 1 }, *dev, o.opt, 240, true, &o.value);
885 
886  y += 38;
887  }
888 
889  g.label({ w - 260, y + 12 }, { 1, 1, 1 }, "Depth control parameters preset: %g", dc_preset);
890  if (g.slider(100, { w - 260, y + 16, w - 20, y + 36 }, 0, 5, 1, dc_preset)) rs_apply_depth_control_preset((rs_device *)dev, static_cast<int>(dc_preset));
891  y += 38;
892  g.label({ w - 260, y + 12 }, { 1, 1, 1 }, "IVCAM options preset: %g", iv_preset);
893  if (g.slider(101, { w - 260, y + 16, w - 20, y + 36 }, 0, 10, 1, iv_preset)) rs_apply_ivcam_preset((rs_device *)dev, static_cast<rs_ivcam_preset>((int)iv_preset));
894  y += 38;
895 
896  panel_height = y + 10 + offset;
897 
898  glfwSwapBuffers(win);
899  g.scroll_vec = { 0, 0 };
900  g.click = false;
901  if (!g.mouse_down) g.clicked_id = 0;
902  }
903 
904  running = false;
905 
906  for (auto i = 0; i < streams; i++) frames_queue[i].clear();
907 
908  if (dev->is_streaming())
909  dev->stop();
910 
911  for (auto i = 0; i < streams; i++)
912  {
913  if (dev->is_stream_enabled((rs::stream)i))
914  dev->disable_stream((rs::stream)i);
915  }
916 
917  glfwTerminate();
918  return 0;
919  }
920  catch (const rs::error & e)
921  {
922  std::stringstream ss;
923  ss << "RealSense error calling " << e.get_failed_function() << "(" << e.get_failed_args() << "):\n " << e.what() << std::endl;
924  std::cerr << ss.str();
925  show_message(win, "Exception", ss.str());
926  }
927  catch (const std::exception & e)
928  {
929  std::cerr << e.what() << std::endl;
930  show_message(win, "Exception", e.what());
931  }
932  }
933 }
void log_to_console(log_severity min_severity)
Definition: rs.hpp:1104
Provides convenience methods relating to devices.
Definition: rs.hpp:567
intrinsics get_stream_intrinsics(stream stream) const
Retrieves intrinsic camera parameters for specific stream.
Definition: rs.hpp:788
GLboolean GLboolean g
Definition: glext.h:1104
static void rs_apply_ivcam_preset(rs_device *device, rs_ivcam_preset preset)
Definition: rsutil.h:89
#define STRING_CASE(S, C)
void indicator(const rect &r, double min, double max, double value)
void enable_stream(stream stream, int width, int height, format format, int framerate, output_buffer_format output_buffer_type=output_buffer_format::continous)
Enables specific stream and requests specific properties.
Definition: rs.hpp:704
rs_timestamp_data timestamp_data
Definition: rs.h:349
void show_message(GLFWwindow *curr_window, const std::string &title, const std::string &message)
const char * rs_stream_to_string(rs_stream stream)
Definition: rs.cpp:754
GLFWAPI void glfwGetWindowSize(GLFWwindow *window, int *width, int *height)
Retrieves the size of the client area of the specified window.
Definition: window.c:456
rs_event_source source_id
Definition: rs.h:342
double def
const std::string & get_failed_args() const
Definition: rs.hpp:315
void on_timestamp_event(rs::timestamp_data entry)
#define GLFW_RESIZABLE
Definition: glfw3.h:594
void update_related_options(rs::device &dev, rs::option opt, std::vector< option > &options)
rs_error * e
T MIN(T x, T y)
int2 scroll_vec
GLint GLint GLsizei GLsizei height
Definition: glext.h:112
GLint GLint GLint GLint GLint GLint y
Definition: glext.h:114
bool slider(int id, const rect &r, double min, double max, double step, double &value, bool disable_dragger=false)
GLFWwindow * curr_window
GLuint GLsizei const GLchar * message
Definition: glext.h:2482
bool click
void get_option_range(option option, double &min, double &max, double &step)
Retrieves available range of values of supported option.
Definition: rs.hpp:909
GLFWAPI void * glfwGetWindowUserPointer(GLFWwindow *window)
Returns the user pointer of the specified window.
Definition: window.c:612
GLsizei const GLchar *const * string
Definition: glext.h:683
int get_stream_width(stream stream) const
Retrieves width, in pixels, of a specific stream, equivalent to the width field from the stream&#39;s int...
Definition: rs.hpp:744
int main(int argc, char *argv[])
const GLuint * buffers
Definition: glext.h:529
Motion data from gyroscope and accelerometer from the microcontroller.
Definition: rs.hpp:295
GLFWAPI GLFWmousebuttonfun glfwSetMouseButtonCallback(GLFWwindow *window, GLFWmousebuttonfun cbfun)
Sets the mouse button callback.
Definition: input.c:482
bool button(const rect &r, const std::string &label)
rs::motion_data m_gyro_data
Exposes librealsense functionality for C++ compilers.
GLenum GLenum GLsizei const GLuint GLboolean enabled
Definition: glext.h:2478
void fill_rect(const rect &r, const color &c)
T MAX(T x, T y)
rs_option
Defines general configuration controls.
Definition: rs.h:128
int2 cursor
GLuint GLuint stream
Definition: glext.h:1774
GLfloat GLfloat GLfloat GLfloat h
Definition: glext.h:1944
option
Defines general configuration controls.
Definition: rs.hpp:87
GLuint buffer
Definition: glext.h:528
rs::option opt
struct GLFWwindow GLFWwindow
Opaque window object.
Definition: glfw3.h:722
double max
rect shrink(int amt) const
bool motion_tracking_enable
GLenum cap
Definition: glext.h:8336
#define GLFW_RELEASE
The key or mouse button was released.
Definition: glfw3.h:225
void stop(rs::source source=rs::source::video)
Ends streaming on all streams for this device.
Definition: rs.hpp:887
float g
bool supports
GLFWAPI int glfwInit(void)
Initializes the GLFW library.
void show(float rx, float ry, float rw, float rh) const
Definition: example.hpp:189
void enqueue(T item)
Definition: concurrency.hpp:20
double step
GLFWAPI void glfwSetWindowUserPointer(GLFWwindow *window, void *pointer)
Sets the user pointer of the specified window.
Definition: window.c:605
static void rs_apply_depth_control_preset(rs_device *device, int preset)
Definition: rsutil.h:63
void option_label(const int2 &p, const color &c, rs::device &dev, rs::option opt, double max_width, bool enabled, double *value=nullptr)
stream
Streams are different types of data provided by RealSense devices.
Definition: rs.hpp:24
GLint GLint bottom
Definition: glext.h:1947
#define GLFW_FLOATING
Definition: glfw3.h:598
int get_stream_height(stream stream) const
Retrieves height, in pixels, of a specific stream, equivalent to the height field from the stream&#39;s i...
Definition: rs.hpp:755
GLuint index
Definition: glext.h:655
const GLubyte * c
Definition: glext.h:11542
bool is_any_stream_enable(rs::device *dev)
bool is_stream_enabled(stream stream) const
Determines if specific stream is enabled.
Definition: rs.hpp:733
std::mutex mm_mutex
Context.
Definition: rs.hpp:319
GLfixed y1
Definition: glext.h:4952
void disable_motion_tracking(void)
Disables events polling.
Definition: rs.hpp:861
format get_format() const
Retrieves frame format.
Definition: rs.hpp:534
format
Formats: defines how each stream can be encoded. rs_format specifies how a frame is represented in me...
Definition: rs.hpp:42
void print(int x, int y, const char *text)
Definition: example.hpp:203
typedef int(WINAPI *PFNWGLRELEASEPBUFFERDCARBPROC)(HPBUFFERARB hPbuffer
void start(rs::source source=rs::source::video)
Begins streaming on all enabled streams for this device.
Definition: rs.hpp:879
void enable_motion_tracking(std::function< void(motion_data)> motion_handler, std::function< void(timestamp_data)> timestamp_handler)
Sets callback for motion module event.
Definition: rs.hpp:841
void draw_autoexposure_roi_boundary(rs::stream s, const std::vector< option > &options, rs::device *dev, gui &g, int x, int y, double w, double h)
GLFWAPI void glfwSwapBuffers(GLFWwindow *window)
Swaps the front and back buffers of the specified window.
Definition: context.c:544
GLFWAPI void glfwMakeContextCurrent(GLFWwindow *window)
Makes the context of the specified window current for the calling thread.
Definition: context.c:531
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const void * data
Definition: glext.h:223
double get_option(option option)
Retrieves current value of single option.
Definition: rs.hpp:954
GLFWAPI void glfwWindowHint(int target, int hint)
Sets the specified window hint to the desired value.
Definition: window.c:267
GLintptr offset
Definition: glext.h:533
GLuint GLsizei const GLchar * label
Definition: glext.h:2484
bool contains(const int2 &p) const
GLuint GLfloat x0
Definition: glext.h:8966
GLFWAPI GLFWcursorposfun glfwSetCursorPosCallback(GLFWwindow *window, GLFWcursorposfun cbfun)
Sets the cursor position callback.
Definition: input.c:491
GLint left
Definition: glext.h:1947
int clicked_id
double value
int is_motion_tracking_active()
Checks if data acquisition is active.
Definition: rs.hpp:869
int get_framerate() const
Returns configured frame rate.
Definition: rs.hpp:505
GLdouble GLdouble right
Definition: glext.h:6472
void update_mm_data(texture_buffer *buffers, int w, int h, gui &g)
auto ctx
GLsizei const GLfloat * value
Definition: glext.h:693
GLFWAPI void glfwSetWindowSize(GLFWwindow *window, int width, int height)
Sets the size of the client area of the specified window.
Definition: window.c:469
GLFWAPI void glfwSetWindowPos(GLFWwindow *window, int xpos, int ypos)
Sets the position of the client area of the specified window.
Definition: window.c:440
int width
Definition: rs.h:302
bool checkbox(const rect &r, bool &value)
GLboolean GLboolean GLboolean b
Definition: glext.h:1104
bool supports_option(option option) const
Determines if device allows specific option to be queried and set.
Definition: rs.hpp:664
GLFWAPI GLFWwindow * glfwCreateWindow(int width, int height, const char *title, GLFWmonitor *monitor, GLFWwindow *share)
Creates a window and its associated context.
Definition: window.c:116
bool mouse_down
void disable_stream(stream stream)
Disables specific stream.
Definition: rs.hpp:723
float axes[3]
Definition: rs.h:351
GLuint GLfloat GLfloat GLfloat x1
Definition: glext.h:8966
Frame.
Definition: rs.hpp:392
float b
GLuint id
Definition: glext.h:523
GLFWAPI void glfwGetWindowPos(GLFWwindow *window, int *xpos, int *ypos)
Retrieves the position of the client area of the specified window.
Definition: window.c:427
static int stb_easy_font_width(char *text)
GLboolean enable
Definition: glext.h:5365
GLdouble s
Definition: glext.h:231
rs_stream
Streams are different types of data provided by RealSense devices.
Definition: rs.h:33
GLint GLint GLsizei width
Definition: glext.h:112
rs::motion_data m_acc_data
static std::map< rs::option, std::vector< rs::option > > options_dependencies
const char * rs_option_to_string(rs_option option)
Definition: rs.cpp:758
GLuint const GLchar * name
Definition: glext.h:655
double get_timestamp() const
Definition: rs.hpp:426
GLsizei GLsizei GLchar * source
Definition: glext.h:672
void label(const int2 &p, const color &c, const char *format,...)
GLFWAPI GLFWscrollfun glfwSetScrollCallback(GLFWwindow *window, GLFWscrollfun cbfun)
Sets the scroll callback.
Definition: input.c:509
rs_device * dev
GLFWAPI void glfwDestroyWindow(GLFWwindow *window)
Destroys the specified window and its context.
Definition: window.c:369
GLFWAPI void glfwGetFramebufferSize(GLFWwindow *window, int *width, int *height)
Retrieves the size of the framebuffer of the specified window.
Definition: window.c:484
GLsizeiptr size
Definition: glext.h:532
unsigned long long get_frame_number() const
Definition: rs.hpp:468
void draw_text(int x, int y, const char *text)
Definition: example.hpp:46
GLFWAPI GLFWwindowclosefun glfwSetWindowCloseCallback(GLFWwindow *window, GLFWwindowclosefun cbfun)
Sets the close callback for the specified window.
Definition: window.c:637
double min
GLFWAPI void glfwTerminate(void)
Terminates the GLFW library.
GLuint GLfloat GLfloat y0
Definition: glext.h:8966
void enable_stream(rs::device *dev, int stream, rs::format format, int w, int h, int fps, bool enable, std::stringstream &stream_name)
void set_frame_callback(rs::stream stream, std::function< void(frame)> frame_handler)
Sets callback for frame arrival event.
Definition: rs.hpp:817
GLFWAPI void glfwPollEvents(void)
Processes all pending events.
Definition: window.c:682
GLint GLint GLsizei GLsizei GLsizei GLint GLenum format
Definition: glext.h:112
const char * get_option_description(option option)
Retrieves device-specific option description.
Definition: rs.hpp:965
bool supports(capabilities capability) const
Determines device capabilities.
Definition: rs.hpp:1005
void vscroll(const rect &r, int client_height, int &offset)
bool is_streaming() const
Determines if device is currently streaming.
Definition: rs.hpp:896
double find_option_value(const std::vector< option > &options, rs::option opt)
device * get_device(int index)
Definition: rs.hpp:354
GLdouble GLdouble GLdouble GLdouble top
Definition: glext.h:6472
void set_option(option option, double value)
Sets current value of single option.
Definition: rs.hpp:976
void outline_rect(const rect &r, const color &c)
void on_motion_event(rs::motion_data entry)
GLfloat GLfloat p
Definition: glext.h:11539
rs_ivcam_preset
For SR300 devices: provides optimized settings (presets) for specific types of usage.
Definition: rs.h:109
const std::string & get_failed_function() const
Definition: rs.hpp:314
Timestamp data from the motion microcontroller.
Definition: rs.hpp:288
capabilities
Specifies various capabilities of a RealSense device.
Definition: rs.hpp:169
#define GLFW_PRESS
The key or mouse button was pressed.
Definition: glfw3.h:232
GLdouble GLdouble GLdouble r
Definition: glext.h:247
GLint GLint GLint GLint GLint x
Definition: glext.h:114
float r
GLubyte GLubyte GLubyte GLubyte w
Definition: glext.h:726
std::string find_and_replace(std::string source, std::string const &find, std::string const &replace)
void upload(const void *data, int width, int height, rs::format format, int stride=0)
Definition: example.hpp:73
int get_device_count() const
Definition: rs.hpp:343
GLFWAPI int glfwWindowShouldClose(GLFWwindow *window)
Checks the close flag of the specified window.
Definition: window.c:406


librealsense
Author(s): Sergey Dorodnicov , Mark Horn , Reagan Lopez
autogenerated on Fri Mar 13 2020 03:16:17