output-model.cpp
Go to the documentation of this file.
1 // License: Apache 2.0. See LICENSE file in root directory.
2 // Copyright(c) 2020 Intel Corporation. All Rights Reserved.
3 
4 #include <glad/glad.h>
5 #include "output-model.h"
6 
7 #include "model-views.h"
8 #include "os.h"
9 
10 #include <imgui_internal.h>
12 
13 using namespace rs2;
14 
16 {
17  while (!to_stop)
18  {
19  std::vector<rs2::device> dev_copy;
20  {
21  std::lock_guard<std::mutex> lock(devices_mutex);
22  dev_copy = devices;
23  }
25  for (auto&& dev : dev_copy)
26  {
27  try
28  {
29  if (auto fwlogger = dev.as<rs2::firmware_logger>())
30  {
31  bool has_parser = false;
33  std::ifstream f(hwlogger_xml.c_str());
34  if (f.good())
35  {
36  try
37  {
38  std::string str((std::istreambuf_iterator<char>(f)),
39  std::istreambuf_iterator<char>());
40  fwlogger.init_parser(str);
41  has_parser = true;
42  }
43  catch (const std::exception& ex)
44  {
45  add_log(RS2_LOG_SEVERITY_WARN, __FILE__, __LINE__,
46  to_string() << "Invalid Hardware Logger XML at '" << hwlogger_xml << "': " << ex.what() << "\nEither configure valid XML or remove it");
47  }
48  }
49 
50  auto message = fwlogger.create_message();
51  while (fwlogger.get_firmware_log(message))
52  {
53  auto parsed = fwlogger.create_parsed_message();
54  auto parsed_ok = false;
55 
56  if (has_parser)
57  {
58  if (fwlogger.parse_log(message, parsed))
59  {
60  parsed_ok = true;
61 
62  add_log(message.get_severity(),
63  parsed.file_name(), parsed.line(), to_string()
64  << "FW-LOG [" << parsed.thread_name() << "] " << parsed.message());
65  }
66  }
67 
68  if (!parsed_ok)
69  {
70  std::stringstream ss;
71  for (auto& elem : message.data())
72  ss << std::setfill('0') << std::setw(2) << std::hex << static_cast<int>(elem) << " ";
73  add_log(message.get_severity(), __FILE__, 0, ss.str());
74  }
75  }
76  }
77  }
78  catch(const std::exception& ex)
79  {
80  add_log(RS2_LOG_SEVERITY_WARN, __FILE__, __LINE__,
81  to_string() << "Failed to fetch firmware logs: " << ex.what());
82  }
83  }
84  // FW define the logs polling intervals to be no less than 100msec to cope with limited resources.
85  // At the same time 100 msec should guarantee no log drops
86  std::this_thread::sleep_for(std::chrono::milliseconds(100));
87  }
88 }
89 
91 {
92  to_stop = 1;
93  fw_logger.join();
94 }
95 
97 {
102  if (search_line != "") search_open = true;
103 
104  available_dashboards["Frame Drops per Second"] = [&](std::string name){
105  return std::make_shared<frame_drops_dashboard>(name, &number_of_drops, &total_frames);
106  };
107 
108  auto front = available_dashboards.begin();
109  dashboards.push_back(front->second(front->first));
110 }
111 
113  int count, ImVec4 color, std::string tooltip, bool& highlighted, std::string suffix)
114 {
115  std::stringstream ss;
116  ss << icon;
117  if (count > 0) ss << " " << count << suffix;
118  auto size = ImGui::CalcTextSize(ss.str().c_str());
119 
120  if (count == 0 || (!is_output_open && !highlighted)) {
121  color = dark_sensor_bg;
124  }
125  else
126  {
127  if (!highlighted)
128  {
129  color = saturate(color, 0.3f);
131  }
132  else
135  }
136 
139  { pos.x + size.x + 15, pos.y + 27 }, ImColor(color), 12, 15);
140 
141  auto res = ImGui::Button(ss.str().c_str(), ImVec2(size.x + 15, 28));
142  if (count > 0 && ImGui::IsItemHovered())
143  {
144  highlighted = true;
145  win.link_hovered();
146  ImGui::SetTooltip("%s", tooltip.c_str());
147  }
148  else highlighted = false;
149 
151 
152  return res;
153 }
154 
156 {
157  is_output_open = true;
159  default_log_h = (int)((win.height() - 100) / 2);
160  new_log = true;
161 }
162 
163 void output_model::draw(ux_window& win, rect view_rect, device_models_list & device_models)
164 {
166 
167  auto x = view_rect.x;
168  auto y = view_rect.y;
169  auto w = view_rect.w;
170  auto h = view_rect.h;
171 
174 
181 
182  ImGui::PushFont(win.get_font());
186 
187  ImGui::Begin("Output", nullptr, flags);
188 
189  ImGui::SetCursorPosX(w - 31);
190  if (!is_output_open)
191  {
192  if (ImGui::Button(u8"\uF139", ImVec2(28, 28)))
193  {
194  open(win);
195  }
196  if (ImGui::IsItemHovered())
197  {
198  win.link_hovered();
199  ImGui::SetTooltip("%s", "Open Debug Console Window");
200  }
201 
202  if (default_log_h.value() != 36)
203  default_log_h = 36;
204  }
205  else
206  {
207  if (ImGui::Button(u8"\uF13A", ImVec2(28, 28)))
208  {
209  is_output_open = false;
211  default_log_h = 36;
212  search_open = false;
213  }
214  if (ImGui::IsItemHovered())
215  {
216  win.link_hovered();
217  ImGui::SetTooltip("%s", "Collapse Debug Console Window");
218  }
219 
220  int h_val = (int)((win.height() - 100) / 2);
221  if (default_log_h.value() != h_val)
222  default_log_h = h_val;
223  }
224 
225  ImGui::SameLine();
227 
229  if (round_indicator(win, u8"\uF057", number_of_errors, redish, "Instances of logged errors", errors_highlighted))
230  {
232  open(win);
233  }
234  ImGui::SameLine();
235 
237  if (round_indicator(win, u8"\uF071", number_of_warnings, orange, "Instances of logged warnings", warnings_highlighted))
238  {
240  open(win);
241  }
242  ImGui::SameLine();
243 
244  if (info_selected) info_highlighted = true;
245  if (round_indicator(win, u8"\uF05A", number_of_info, greenish, "Instances of logged info messages", info_highlighted))
246  {
248  open(win);
249  }
250  ImGui::SameLine();
251 
252  if (!is_output_open || search_open)
253  {
255  }
256  else
257  {
259  }
260  bool focus_search = false;
261  if (ImGui::Button(u8"\uF002", ImVec2(28, 28)))
262  {
263  focus_search = true;
264  search_open = true;
265  open(win);
266  }
267  if (ImGui::IsItemHovered())
268  {
269  win.link_hovered();
270  ImGui::SetTooltip("%s", "Search through logs");
271  }
273  ImGui::SameLine();
274 
275  auto curr_x = ImGui::GetCursorPosX();
276  ImGui::SetCursorPosX(curr_x - 5);
277 
278 
279  int percent = total_frames ? (int)(100 * ((double)number_of_drops / (total_frames))) : 0;
280 
281  std::stringstream ss;
282  ss << u8"\uF043";
283  if (percent) ss << " " << percent << "%";
284  auto size = ImGui::CalcTextSize(ss.str().c_str());
285 
286  char buff[1024];
287  memcpy(buff, search_line.c_str(), search_line.size());
288  buff[search_line.size()] = 0;
289 
290  auto actual_search_width = w - size.x - 100 - curr_x;
291  if (focus_search) search_width = (int)(actual_search_width);
292 
293  if (search_open && search_width.value() != actual_search_width)
294  search_width = (int)(actual_search_width);
295 
296  // if (is_output_open && search_width < 1)
297  // {
298  // search_open = true;
299  // }
300 
301  if (search_open)
302  {
305  ImGui::PushItemWidth(static_cast<float>(search_width));
307  if (ImGui::InputText("##SearchInLogs",buff, 1023))
308  {
309  search_line = buff;
311  }
312  if (focus_search) ImGui::SetKeyboardFocusHere();
314  ImGui::SameLine();
317  ImGui::PopFont();
318  }
319 
320  ImGui::SetCursorPosX(w - size.x - 3 * 30);
321 
323  {
326  }
327  else
328  {
329  if (is_output_open)
331  else
334  }
335 
336  if (ImGui::Button(u8"\uF2DB", ImVec2(28, 28)))
337  {
339  }
341  if (ImGui::IsItemHovered())
342  {
343  win.link_hovered();
344  if (enable_firmware_logs) ImGui::SetTooltip("%s", "Disable Firmware Logs");
345  else ImGui::SetTooltip("%s", "Enable Firmware Logs");
346  }
347  ImGui::SameLine();
348 
349 
350  if (round_indicator(win, u8"\uF043", percent, regular_blue, "Frame drops", drops_highlighted, "%"))
351  {
352  open(win);
353  }
354 
355  if (is_output_open)
356  {
357  ImGui::SetCursorPos(ImVec2(3, 35));
358 
359 
362 
363  ImGui::BeginChild("##LogArea",
364  ImVec2(0.7f * w - 4, h - 38 - ImGui::GetTextLineHeightWithSpacing() - 1), true,
366 
367  const auto log_area_width = 0.7f * w - 4;
368 
369  bool copy_all = false;
370  bool save_all = false;
371  std::vector<std::string> output_strings;
372 
373  auto time_now = glfwGetTime();
374 
375  int i = 0;
376  foreach_log([&](log_entry& log)
377  {
378  auto line = log.line;
379  if (log.line_number)
380  {
381  line = log.filename.substr(log.filename.find_last_of("/\\") + 1) + ":";
382  line += std::string(to_string() << log.line_number) + " - ";
383  line += log.line;
384  }
385 
386  bool ok = false;
388  {
389  if (info_selected && log.severity <= RS2_LOG_SEVERITY_INFO) ok = true;
390  if (warnings_selected && log.severity == RS2_LOG_SEVERITY_WARN) ok = true;
391  if (errors_selected && log.severity >= RS2_LOG_SEVERITY_ERROR) ok = true;
392  }
393  else ok = true;
394 
395  if (search_line != "" && to_lower(line).find(to_lower(search_line)) == std::string::npos) ok = false;
396 
397  if (!ok) return;
398 
399  std::stringstream ss; ss << log.timestamp << " [" << rs2_log_severity_to_string(log.severity) << "] ";
400  if (log.line_number) ss << log.filename << ":" << log.line_number;
401  ss << " - " << log.line;
402  std::string full = ss.str();
403 
408 
409  ImVec4 color = redish;
410  if (log.severity >= RS2_LOG_SEVERITY_ERROR)
411  {
412  color = redish;
413  }
414  else if (log.severity >= RS2_LOG_SEVERITY_WARN)
415  {
416  color = orange;
417  }
418  else
419  {
420  color = greenish;
421  }
422 
424  auto size = ImGui::CalcTextSize(line.c_str());
425 
426  auto t = single_wave(static_cast<float>(time_now - log.time_added + 0.3f)) * 0.2f;
427  if (log.selected) t = 0.2f;
428 
431  { pos.x + log_area_width, pos.y + size.y + 2 * margin },
432  ImColor(alpha(saturate(color, 0.3f + t), 0.7f + t)));
433  ImGui::GetWindowDrawList()->AddLine({ pos.x, pos.y + size.y + 2 * margin },
434  { pos.x + log_area_width, pos.y + size.y + 2 * margin }, ImColor(alpha(color, 0.5f)));
435 
438  ImGui::Text("%s", log.timestamp.c_str()); ImGui::SameLine();
441 
442  std::string label = to_string() << "##log_entry" << i++;
443  ImGui::InputTextEx(label.c_str(),
444  (char*)line.data(),
445  static_cast<int>(line.size() + 1),
446  ImVec2(-1, size.y + margin),
448 
454  label = to_string() << "##log_entry" << i << "_context_menu";
455  if (ImGui::BeginPopupContextItem(label.c_str()))
456  {
457  log.selected = true;
458  ImGui::PushFont(win.get_font());
459  if (ImGui::Selectable("Copy Line")) {
460  glfwSetClipboardString(win, full.c_str());
461  }
462  if (ImGui::Selectable("Copy All")) {
463  copy_all = true;
464  }
465  if (ImGui::Selectable("Save As...")) {
466  save_all = true;
467  }
468  ImGui::PopFont();
469  ImGui::EndPopup();
470  }
471  else log.selected = false;
474 
476  ImGui::PopFont();
477 
479 
480  output_strings.push_back(full);
481  });
482 
483  std::stringstream ss;
484  for (auto&& s : output_strings) ss << s << "\n";
485  if (copy_all)
486  glfwSetClipboardString(win, ss.str().c_str());
487 
488  if (save_all)
489  {
490  if (auto fn = file_dialog_open(file_dialog_mode::save_file, "Log File\0*.log\0", nullptr, nullptr))
491  {
492  std::ofstream out(fn);
493  if (out.good())
494  {
495  out << ss.str();
496  }
497  out.close();
498  }
499  }
500 
501  ImGui::EndChild();
503 
504 
506  ImGui::Text("%s", u8"\uF120"); ImGui::SameLine();
508 
509 
512  ImGui::PushItemWidth(0.7f * w - 32);
513 
514  bool force_refresh = false;
515 
517  {
518  if (commands_histroy.size())
519  {
523 
524  force_refresh = true;
525  }
526  }
527 
529  {
531  {
533  std::ifstream f(commands_xml.c_str());
534  if (f.good())
535  {
536  std::string str((std::istreambuf_iterator<char>(f)),
537  std::istreambuf_iterator<char>());
538 
539  autocomplete.clear();
540  std::regex exp("Command Name=\"(\\w+)\"");
541  std::smatch res;
542  std::string::const_iterator searchStart(str.cbegin());
543  while (regex_search(searchStart, str.cend(), res, exp))
544  {
545  if (starts_with(to_lower(res[1]), to_lower(command_line)))
546  autocomplete.push_back(res[1]);
547  searchStart = res.suffix().first;
548  }
549  }
550  }
551  if (autocomplete.size())
552  {
553  auto temp = autocomplete.front();
554  autocomplete.pop_front();
555  autocomplete.push_back(temp);
556 
557  if (starts_with(to_lower(temp), command_line))
559  else
560  command_line = autocomplete.front();
561  force_refresh = true;
562  }
563  }
564 
565  memcpy(buff, command_line.c_str(), command_line.size());
566  buff[command_line.size()] = 0;
567 
569  if (force_refresh)
570  {
572  }
573 
575  if (ImGui::InputText("##TerminalCommand", buff, 1023, flags))
576  {
577 
578  }
579  if (!command_focus && !new_log) command_line = buff;
582  ImGui::PopFont();
584 
586  {
587  if (commands_histroy.size() > 100) commands_histroy.pop_back();
588  commands_histroy.push_front(command_line);
589  run_command(command_line, device_models);
590  command_line = "";
591  command_focus = true;
592  }
593  else command_focus = false;
594 
596  {
597  command_line = "";
598  }
599 
600  ImGui::SetCursorPos(ImVec2(0.7f * w - 2, 35));
601  ImGui::BeginChild("##StatsArea",ImVec2(0.3f * w - 2, h - 38), true);
602 
603  auto top = 0;
604  for(auto&& dash : dashboards)
605  {
606  auto h = dash->get_height();
607  auto r = rect { 0.f, (float)top, 0.3f * w - 2, (float)h };
608  dash->draw(win, r);
609  top += h;
610  }
611 
612  dashboards.erase(std::remove_if(dashboards.begin(), dashboards.end(),
613  [](std::shared_ptr<stream_dashboard> p){
614  return p->closing();
615  }), dashboards.end());
616 
617  bool can_add = false;
618  for (auto&& kvp : available_dashboards)
619  {
620  auto name = kvp.first;
621  auto it = std::find_if(dashboards.begin(), dashboards.end(),
622  [name](std::shared_ptr<stream_dashboard> p){
623  return p->get_name() == name;
624  });
625  if (it == dashboards.end()) can_add = true;
626  }
627 
628  if (can_add)
629  {
631  const auto new_dashboard_name = "new_dashaborad";
632  if (ImGui::Button(u8"\uF0D0 Add Dashboard", ImVec2(-1, 25)))
633  {
634  ImGui::OpenPopup(new_dashboard_name);
635  }
636 
637  if (ImGui::IsItemHovered())
638  {
639  ImGui::SetTooltip("Add one of the available stream dashboards to view");
640  win.link_hovered();
641  }
642 
648  if (ImGui::BeginPopup(new_dashboard_name))
649  {
650  for (auto&& kvp : available_dashboards)
651  {
652  auto name = kvp.first;
653  auto it = std::find_if(dashboards.begin(), dashboards.end(),
654  [name](std::shared_ptr<stream_dashboard> p){
655  return p->get_name() == name;
656  });
657  if (it == dashboards.end())
658  {
659  name = name + "##New";
660  bool selected = false;
661  if (ImGui::Selectable(name.c_str(), &selected))
662  {
663  dashboards.push_back(kvp.second(kvp.first));
664  }
665  }
666  }
667 
668  ImGui::EndPopup();
669  }
670 
673  }
674 
675 
676  ImGui::EndChild();
677 
678 
680  }
681  else foreach_log([&](log_entry& log) {});
682 
683 
684  ImGui::End();
687  ImGui::PopFont();
688 
689  {
690  std::lock_guard<std::mutex> lock(devices_mutex);
691  this->devices.clear();
692  for (auto && dev_model : device_models)
693  this->devices.push_back(dev_model->dev);
694  }
695 }
696 
697 void output_model::foreach_log(std::function<void(log_entry& line)> action)
698 {
699  std::lock_guard<std::recursive_mutex> lock(m);
700 
701  // Process only the messages that are available upon invocation
702  log_entry le;
703  for (size_t len = 0; len < incoming_log_queue.size(); len++)
704  {
705  if (incoming_log_queue.try_dequeue(&le))
706  {
709  else number_of_info++;
710 
711  notification_logs.push_back(le);
712  }
713  }
714 
715  // Limit the notification window
716  while (notification_logs.size() > 1000)
717  {
718  auto&& le = notification_logs.front();
721  else number_of_info--;
722  notification_logs.pop_front();
723  }
724 
725  for (auto&& l : notification_logs)
726  action(l);
727 
728  if (new_log)
729  {
731  new_log = false;
732  }
733 }
734 
735 // Callback function must not include mutex
737 {
738  if (!line.size()) return;
739 
740  time_t rawtime;
741  struct tm * timeinfo;
742  char buffer[80];
743  time (&rawtime);
744  timeinfo = localtime(&rawtime);
745  strftime(buffer,sizeof(buffer),"%H:%M:%S",timeinfo);
746 
747  log_entry e;
748  e.line = line;
749  e.line_number = line_number;
750  e.filename = filename;
751  e.severity = severity;
752  e.timestamp = buffer;
753  e.time_added = glfwGetTime();
754 
755  incoming_log_queue.enqueue(std::move(e));
756  new_log = true;
757 }
758 
760 {
761  try
762  {
763  if (to_lower(command) == "clear")
764  {
765  while (notification_logs.size() > 0)
766  {
767  auto&& le = notification_logs.front();
768  if (le.severity >= RS2_LOG_SEVERITY_ERROR) number_of_errors--;
769  else if (le.severity >= RS2_LOG_SEVERITY_WARN) number_of_warnings--;
770  else number_of_info--;
771  notification_logs.pop_front();
772  for (auto& d : dashboards)
773  d->clear(true);
774  }
775 
776  return;
777  }
778 
779  if( user_defined_command( command, device_models ) )
780  return;
781 
782  std::regex e( "([0-9A-Fa-f]{2}\\s)+" );
783 
784  if (std::regex_match(command, e))
785  {
786  add_log(RS2_LOG_SEVERITY_INFO, __FILE__, 0, to_string() << "Trying to send " << command << "...");
787 
788  std::vector<uint8_t> raw_data;
789  std::stringstream ss(command);
790  std::string word;
791  while (ss >> word)
792  {
793  std::stringstream converter;
794  int temp;
795  converter << std::hex << word;
796  converter >> temp;
797  raw_data.push_back(temp);
798  }
799  if (raw_data.empty())
800  throw std::runtime_error("Invalid input!");
801 
802  bool found = false;
803  for (auto&& dev : devices)
804  {
805  if (auto dbg = dev.as<rs2::debug_protocol>())
806  {
807  found = true;
808  auto res = dbg.send_and_receive_raw_data(raw_data);
809 
810  std::stringstream ss;
811  int i = 0;
812  for (auto& elem : res)
813  {
814  ss << std::setfill('0') << std::setw(2) << std::hex << static_cast<int>(elem) << " ";
815  i++;
816  if (i > 80)
817  {
818  ss << "\n";
819  i = 0;
820  }
821  }
822  add_log(RS2_LOG_SEVERITY_INFO, __FILE__, 0, ss.str());
823 
824  return;
825  }
826  }
827 
828  if (!found)
829  {
830  add_log(RS2_LOG_SEVERITY_WARN, __FILE__, __LINE__, "No device is available to receive the command");
831  return;
832  }
833  }
834 
836  std::ifstream f(commands_xml.c_str());
837  if (f.good())
838  {
839  std::string str((std::istreambuf_iterator<char>(f)),
840  std::istreambuf_iterator<char>());
842 
843  auto buffer = terminal_parser.parse_command(to_lower(command));
844 
845  std::stringstream ss; ss << command << " = ";
846  for (auto& elem : buffer)
847  ss << std::setfill('0') << std::setw(2) << std::hex << static_cast<int>(elem) << " ";
848 
849  add_log(RS2_LOG_SEVERITY_INFO, __FILE__, 0, ss.str());
850 
851  bool found = false;
852  for (auto&& dev : devices)
853  {
854  if (auto dbg = dev.as<rs2::debug_protocol>())
855  {
856  found = true;
857  auto res = dbg.send_and_receive_raw_data(buffer);
858 
859  std::string response = to_string() << "\n" << terminal_parser.parse_response(to_lower(command), res);
860  add_log(RS2_LOG_SEVERITY_INFO, __FILE__, 0, response);
861  }
862  }
863 
864  if (!found)
865  add_log(RS2_LOG_SEVERITY_WARN, __FILE__, __LINE__, "No device is available to receive the command");
866 
867  return;
868  }
869 
870  add_log(RS2_LOG_SEVERITY_WARN, __FILE__, __LINE__, to_string() << "Unrecognized command '" << command << "'");
871  }
872  catch(const std::exception& ex)
873  {
874  add_log( RS2_LOG_SEVERITY_ERROR, __FILE__, __LINE__, ex.what() );
875  }
876 }
877 
879 {
880  bool user_defined_command_detected = false;
881  bool user_defined_command_activated = false;
882 
883  // If a known command is detected , it will treated as a user_defined_command and will not be
884  // passed to the FW commands check logic.
885  // Note: For now we find the first device that supports the command and activate the command only on it.
886 
887  if( to_lower( command ) == "trigger-camera-accuracy-health" )
888  {
889  user_defined_command_detected = true;
890 
891  for( auto && dev_model : device_models )
892  {
893  if( dev_model->is_cah_model_enabled() && !user_defined_command_activated)
894  {
895  dev_model->show_trigger_camera_accuracy_health_popup = true;
896  user_defined_command_activated = true;
897  }
898  }
899  }
900  else if( to_lower( command ) == "reset-camera-accuracy-health" )
901  {
902  user_defined_command_detected = true;
903 
904  for( auto && dev_model : device_models )
905  {
906  if( dev_model->is_cah_model_enabled() && !user_defined_command_activated)
907  {
908  dev_model->show_reset_camera_accuracy_health_popup = true;
909  user_defined_command_activated = true;
910  }
911  }
912  }
913  else if( to_lower( command ) == "get-nest" )
914  {
915  user_defined_command_detected = true;
916 
917  for( auto && dev : devices )
918  {
919  if( auto dbg = dev.as< rs2::debug_protocol >() )
920  {
921  // Verify minimal version for handling this command
922  std::vector< uint8_t > special_command
923  = { 'G', 'E', 'T', '-', 'N', 'E', 'S', 'T' };
924  auto res = dbg.send_and_receive_raw_data( special_command );
925  user_defined_command_activated = true;
926  }
927  }
928  }
929 
930  // Log a warning if a known command was not activated
931  if( user_defined_command_detected && ! user_defined_command_activated )
932  {
934  __FILE__,
935  __LINE__,
936  to_string() << "None of the connected devices supports '" << command << "'" );
937  }
938 
939  return user_defined_command_detected;
940 }
941 
942 
944 {
945  for (auto&& d : dashboards)
946  d->add_frame(f);
947 }
948 
950 {
951  auto min_x = 0.f;
952  auto max_x = 1.f;
953  auto min_y = 0.f;
954  auto max_y = 1.f;
955 
956  if (xy.size())
957  {
958  min_x = xy[0].first;
959  max_x = xy[0].first;
960  min_y = xy[0].second;
961  max_y = xy[0].second;
962  for (auto&& p : xy)
963  {
964  min_x = std::min(min_x, p.first);
965  min_y = std::min(min_y, p.second);
966  max_x = std::max(max_x, p.first);
967  max_y = std::max(max_y, p.second);
968  }
969  }
970 
971  auto gap_y = max_y - min_y;
972  auto gap_x = max_x - min_x;
973  auto height_y = r.h - 2 * ImGui::GetTextLineHeight() - 10;
974  auto ticks_y = ceil(height_y / ImGui::GetTextLineHeight());
975 
976  auto max_y_label_width = 0.f;
977  for (int i = 0; i <= ticks_y; i++)
978  {
979  auto y = max_y - i * (gap_y / ticks_y);
980  std::string y_label = to_string() << std::fixed << std::setprecision(2) << y;
981  auto size = ImGui::CalcTextSize(y_label.c_str());
982  max_y_label_width = std::max(max_y_label_width,
983  size.x);
984  }
985 
987 
989 
991  { pos.x + r.w - 1, pos.y + get_height() - 1 }, ImColor(header_color));
993  { pos.x + r.w, pos.y + get_height() }, ImColor(dark_sensor_bg));
994 
995  auto size = ImGui::CalcTextSize(name.c_str());
996  ImGui::SetCursorPos(ImVec2( r.w / 2 - size.x / 2, 5 ));
997  ImGui::Text("%s", name.c_str());
998  ImGui::SameLine();
999 
1001  ImGui::SetCursorPosX(r.w - 25);
1003  std::string id = to_string() << u8"\uF00D##Close_" << name;
1004  if (ImGui::Button(id.c_str(),ImVec2(22,22)))
1005  {
1006  close();
1007  }
1008  if (ImGui::IsItemHovered())
1009  {
1010  ImGui::SetTooltip("Remove Dashboard from View");
1011  win.link_hovered();
1012  }
1014 
1015  ImGui::GetWindowDrawList()->AddRectFilled({ pos.x + max_y_label_width + 15, pos.y + ImGui::GetTextLineHeight() + 5 },
1016  { pos.x + r.w - 10, pos.y + r.h - ImGui::GetTextLineHeight() - 5 }, ImColor(almost_white_bg));
1017 
1018  //ImGui::PushFont(win.get_monofont());
1019  for (int i = 0; i <= ticks_y; i++)
1020  {
1021  auto y = max_y - i * (gap_y / ticks_y);
1022  std::string y_label = to_string() << std::fixed << std::setprecision(2) << y;
1023  auto y_pixel = ImGui::GetTextLineHeight() + i * (height_y / ticks_y);
1024  ImGui::SetCursorPos(ImVec2( 10, y_pixel ));
1025  ImGui::Text("%s", y_label.c_str());
1026 
1027  ImGui::GetWindowDrawList()->AddLine({ pos.x + max_y_label_width + 15, pos.y + y_pixel + 5 },
1028  { pos.x + r.w - 10, pos.y + y_pixel + 5 }, ImColor(light_grey));
1029  }
1030 
1031  auto graph_width = r.w - max_y_label_width - 25;
1032 
1033  int ticks_x = 2;
1034  bool has_room = true;
1035  while (has_room)
1036  {
1037  auto total = 0;
1038  for (int i = 0; i <= ticks_x; i++)
1039  {
1040  auto x = min_x + i * (gap_x / ticks_x);
1041  std::string x_label = to_string() << std::fixed << std::setprecision(2) << x;
1042  auto size = ImGui::CalcTextSize(x_label.c_str());
1043  total += size.x;
1044  }
1045  if (total < graph_width) ticks_x++;
1046  else has_room = false;
1047  }
1048  ticks_x -= 3;
1049 
1050  for (int i = 0; i < ticks_x; i++)
1051  {
1052  auto x = min_x + i * (gap_x / ticks_x);
1053  std::string x_label = to_string() << std::fixed << std::setprecision(2) << x;
1054  ImGui::SetCursorPos(ImVec2( 15 + max_y_label_width+ i * (graph_width / ticks_x), r.h - ImGui::GetTextLineHeight() ));
1055  ImGui::Text("%s", x_label.c_str());
1056 
1057  ImGui::GetWindowDrawList()->AddLine({ pos.x + 15 + max_y_label_width + i * (graph_width / ticks_x), pos.y + ImGui::GetTextLineHeight() + 5 },
1058  { pos.x + max_y_label_width + 15 + i * (graph_width / ticks_x), pos.y + ImGui::GetTextLineHeight() + 5 + height_y }, ImColor(light_grey));
1059  }
1060 
1061  std::sort(xy.begin(), xy.end(), [](const std::pair<float, float>& a, const std::pair<float, float>& b) { return a.first < b.first; });
1062 
1063  for (int i = 0; i + 1 < xy.size(); i++)
1064  {
1065  auto x0 = xy[i].first;
1066  auto y0 = xy[i].second;
1067 
1068  auto x1 = xy[i+1].first;
1069  auto y1 = xy[i+1].second;
1070 
1071  x0 = (x0 - min_x) / (max_x - min_x);
1072  x1 = (x1 - min_x) / (max_x - min_x);
1073 
1074  y0 = (y0 - min_y) / (max_y - min_y);
1075  y1 = (y1 - min_y) / (max_y - min_y);
1076 
1077  ImGui::GetWindowDrawList()->AddLine({ pos.x + 15 + max_y_label_width + x0 * graph_width, pos.y + ImGui::GetTextLineHeight() + 5 + height_y * (1.f - y0) },
1078  { pos.x + 15 + max_y_label_width + x1 * graph_width, pos.y + ImGui::GetTextLineHeight() + 5 + height_y * (1.f - y1) }, ImColor(black));
1079  }
1080 
1081  //ImGui::PopFont();
1083 
1084  xy.clear();
1085 }
1086 
1088 {
1089  write_shared_data([&](){
1090  double ts = glfwGetTime();
1091  if (method == 1) ts = f.get_timestamp() / 1000.f;
1092  auto it = stream_to_time.find(f.get_profile().unique_id());
1093  if (it != stream_to_time.end())
1094  {
1095  auto last = stream_to_time[f.get_profile().unique_id()];
1096 
1097  auto fps = f.get_profile().fps();
1098 
1101 
1102  if (1000.f * (ts - last) > 1.5f * (1000.f / fps)) {
1103  drops++;
1104  }
1105  }
1106 
1107  counter++;
1108 
1109  if (ts - last_time > 1.f)
1110  {
1111  if (drops_history.size() > 100) drops_history.pop_front();
1112  drops_history.push_back(drops);
1113  *total = counter;
1114  *frame_drop_count = drops;
1115  drops = 0;
1116  last_time = ts;
1117  counter = 0;
1118  }
1119 
1120  stream_to_time[f.get_profile().unique_id()] = ts;
1121  });
1122 }
1123 
1125 {
1126  auto hist = read_shared_data<std::deque<int>>([&](){ return drops_history; });
1127  for (int i = 0; i < hist.size(); i++)
1128  {
1129  add_point(i, hist[i]);
1130  }
1132  draw_dashboard(win, r);
1133 
1136  ImGui::Text("%s", "Measurement Metric:"); ImGui::SameLine();
1138 
1139  ImGui::SetCursorPosX(200);
1140 
1141  std::vector<const char*> methods;
1142  methods.push_back("Viewer Processing Rate");
1143  methods.push_back("Camera Timestamp Rate");
1144 
1145  ImGui::PushItemWidth(r.w - 207);
1146  if (ImGui::Combo("##fps_method", &method, methods.data(), (int)(methods.size())))
1147  {
1148  clear(false);
1149  }
1151 }
1152 
1154 {
1155  return (int)(160 + ImGui::GetTextLineHeightWithSpacing());
1156 }
1157 
1159 {
1160  write_shared_data([&](){
1161  stream_to_time.clear();
1162  last_time = 0;
1163  *total = 0;
1164  *frame_drop_count = 0;
1165  if (full)
1166  {
1167  drops_history.clear();
1168  for (int i = 0; i < 100; i++)
1169  drops_history.push_back(0);
1170  }
1171  });
1172 }
float y
Definition: rendering.h:499
static const textual_icon lock
Definition: model-views.h:218
IMGUI_API void PushStyleVar(ImGuiStyleVar idx, float val)
Definition: imgui.cpp:4650
static const ImVec4 transparent
Definition: model-views.h:44
GLenum GLuint GLenum GLsizei const GLchar * message
animated< int > default_log_h
Definition: output-model.h:149
static const ImVec4 white
Definition: model-views.h:45
IMGUI_API float GetCursorPosX()
Definition: imgui.cpp:5082
IMGUI_API void AddRectFilled(const ImVec2 &a, const ImVec2 &b, ImU32 col, float rounding=0.0f, int rounding_corners=0x0F)
Definition: imgui_draw.cpp:814
IMGUI_API bool IsKeyPressed(int key_index, bool repeat=true)
Definition: imgui.cpp:3068
GLboolean GLboolean GLboolean b
GLint y
Definition: output-model.h:110
GLenum GLuint GLenum severity
IMGUI_API bool BeginPopupContextItem(const char *str_id, int mouse_button=1)
Definition: imgui.cpp:3507
IMGUI_API void SetTooltip(const char *fmt,...) IM_PRINTFARGS(1)
Definition: imgui.cpp:3288
std::string to_lower(std::string x)
Definition: parser.hpp:217
GLuint const GLchar * name
static const ImVec4 almost_white_bg
Definition: model-views.h:42
ImVec4 saturate(const ImVec4 &a, float f)
std::mutex devices_mutex
Definition: output-model.h:174
GLdouble GLdouble GLdouble top
GLdouble s
static const ImVec4 greenish
Definition: model-views.h:65
IMGUI_API void SetCursorPos(const ImVec2 &local_pos)
Definition: imgui.cpp:5094
GLfloat GLfloat p
Definition: glext.h:12687
const GLfloat * m
Definition: glext.h:6814
Definition: lz4.c:398
std::vector< uint8_t > parse_command(const std::string &command)
void clear(bool full) override
static const ImVec4 light_grey
Definition: model-views.h:40
Definition: imgui.h:88
rs2_metadata_type get_frame_metadata(rs2_frame_metadata_value frame_metadata) const
Definition: rs_frame.hpp:497
std::atomic< int > to_stop
Definition: output-model.h:186
#define GLFW_KEY_UP
Definition: glfw3.h:421
static config_file & instance()
Definition: rs-config.cpp:80
static const char * commands_xml
Definition: model-views.h:169
static const ImVec4 light_blue
Definition: model-views.h:38
stream_profile get_profile() const
Definition: rs_frame.hpp:557
ImFont * get_monofont() const
Definition: ux-window.h:63
IMGUI_API void SetNextWindowPos(const ImVec2 &pos, ImGuiSetCond cond=0)
Definition: imgui.cpp:4923
void foreach_log(std::function< void(log_entry &line)> action)
UINT8_TYPE u8
Definition: sqlite3.c:11450
std::string parse_response(const std::string &command, const std::vector< uint8_t > &response)
void log(rs2_log_severity severity, const char *message)
Definition: rs.hpp:149
void update_dashboards(rs2::frame f)
IMGUI_API bool BeginChild(const char *str_id, const ImVec2 &size=ImVec2(0, 0), bool border=false, ImGuiWindowFlags extra_flags=0)
Definition: imgui.cpp:3531
bool supports_frame_metadata(rs2_frame_metadata_value frame_metadata) const
Definition: rs_frame.hpp:509
Definition: cah-model.h:10
GLdouble GLdouble GLdouble w
GLsizei const GLchar *const * string
d
Definition: rmse.py:171
int line_number
Definition: output-model.h:115
std::string search_line
Definition: output-model.h:177
GLfloat GLfloat GLfloat GLfloat h
Definition: glext.h:1960
e
Definition: rmse.py:177
static const char * hwlogger_xml
Definition: model-views.h:170
GLenum GLfloat * buffer
static const ImVec4 grey
Definition: model-views.h:48
IMGUI_API void AddLine(const ImVec2 &a, const ImVec2 &b, ImU32 col, float thickness=1.0f)
Definition: imgui_draw.cpp:796
void sort(sort_type m_sort_type, const std::string &in, const std::string &out)
IMGUI_API bool InputText(const char *label, char *buf, size_t buf_size, ImGuiInputTextFlags flags=0, ImGuiTextEditCallback callback=NULL, void *user_data=NULL)
Definition: imgui.cpp:8216
GLdouble t
GLboolean GLboolean GLboolean GLboolean a
ImFont * get_font() const
Definition: ux-window.h:64
GLenum GLsizei len
Definition: glext.h:3285
T get_or_default(const char *key, T def) const
Definition: rs-config.h:65
Definition: parser.hpp:154
float x
Definition: rendering.h:499
std::map< std::string, std::function< std::shared_ptr< stream_dashboard >std::string)> > available_dashboards
Definition: output-model.h:184
IMGUI_API bool BeginPopup(const char *str_id)
Definition: imgui.cpp:3455
IMGUI_API void SameLine(float pos_x=0.0f, float spacing_w=-1.0f)
Definition: imgui.cpp:9246
GLdouble f
bool user_defined_command(std::string command, std::vector< std::unique_ptr< device_model >> &device_models)
IMGUI_API ImDrawList * GetWindowDrawList()
Definition: imgui.cpp:5045
IMGUI_API bool Begin(const char *name, bool *p_open=NULL, ImGuiWindowFlags flags=0)
Definition: imgui.cpp:3772
void add_log(rs2_log_severity severity, std::string filename, int line_number, std::string line)
IMGUI_API void PopStyleVar(int count=1)
Definition: imgui.cpp:4675
static void SetScrollPosHere()
Definition: imgui.h:526
GLsizeiptr size
IMGUI_API ImVec2 CalcTextSize(const char *text, const char *text_end=NULL, bool hide_text_after_double_hash=false, float wrap_width=-1.0f)
Definition: test-wrap.cpp:15
float h
Definition: rendering.h:500
static const ImVec4 orange
Definition: model-views.h:66
static const ImVec4 regular_blue
Definition: model-views.h:39
GLuint counter
Definition: glext.h:5684
GLdouble GLdouble r
GLdouble x
double get_timestamp() const
Definition: rs_frame.hpp:474
std::string get(const char *key, const char *def) const
Definition: rs-config.cpp:32
static const ImVec4 scrollbar_bg
Definition: model-views.h:46
std::deque< std::string > commands_histroy
Definition: output-model.h:179
bool selected
Definition: output-model.h:118
#define GLFW_KEY_ESCAPE
Definition: glfw3.h:412
float single_wave(float x)
Definition: rendering.h:1643
void open(ux_window &win)
IMGUI_API void SetNextWindowSize(const ImVec2 &size, ImGuiSetCond cond=0)
Definition: imgui.cpp:4937
#define GLFW_KEY_TAB
Definition: glfw3.h:414
std::vector< std::shared_ptr< stream_dashboard > > dashboards
Definition: output-model.h:183
static const ImVec4 sensor_bg
Definition: model-views.h:51
GLbitfield flags
void process_frame(rs2::frame f) override
def find(dir, mask)
Definition: file.py:25
static const char * output_open
Definition: model-views.h:157
IMGUI_API void SetCursorPosX(float x)
Definition: imgui.cpp:5101
rs2_log_severity severity
Definition: output-model.h:114
GLuint GLfloat x0
Definition: glext.h:9721
IMGUI_API void PushItemWidth(float item_width)
Definition: imgui.cpp:4486
IMGUI_API void Text(const char *fmt,...) IM_PRINTFARGS(1)
Definition: imgui.cpp:5223
IMGUI_API bool Button(const char *label, const ImVec2 &size=ImVec2(0, 0))
Definition: imgui.cpp:5573
const char * file_dialog_open(file_dialog_mode flags, const char *filters, const char *default_path, const char *default_name)
Definition: os.cpp:169
IMGUI_API void End()
Definition: imgui.cpp:4330
#define GLFW_KEY_ENTER
Definition: glfw3.h:413
Definition: imgui.h:98
std::deque< log_entry > notification_logs
Definition: output-model.h:147
std::string line
Definition: output-model.h:112
IMGUI_API void EndPopup()
Definition: imgui.cpp:3489
action
Definition: enums.py:62
static const ImVec4 header_color
Definition: model-views.h:57
float w
Definition: rendering.h:500
std::deque< std::string > autocomplete
Definition: output-model.h:172
ImVec4 alpha(const ImVec4 &v, float a)
IMGUI_API void PushStyleColor(ImGuiCol idx, const ImVec4 &col)
Definition: imgui.cpp:4599
static const ImVec4 black
Definition: model-views.h:43
IMGUI_API bool Combo(const char *label, int *current_item, const char **items, int items_count, int height_in_items=-1, bool show_arrow_down=true)
Definition: imgui.cpp:8418
GLFWAPI void glfwSetClipboardString(GLFWwindow *window, const char *string)
Sets the clipboard to the specified string.
Definition: input.c:1261
IMGUI_API void PushFont(ImFont *font)
Definition: imgui.cpp:4539
IMGUI_API void EndChild()
Definition: imgui.cpp:3573
IMGUI_API float GetTextLineHeightWithSpacing()
Definition: imgui.cpp:5033
GLuint GLfloat GLfloat GLfloat x1
Definition: glext.h:9721
bool round_indicator(ux_window &win, std::string icon, int count, ImVec4 color, std::string tooltip, bool &highlighted, std::string suffix="")
IMGUI_API ImVec2 GetCursorScreenPos()
Definition: imgui.cpp:5121
#define GLFW_KEY_DOWN
Definition: glfw3.h:420
GLFWAPI double glfwGetTime(void)
Returns the value of the GLFW timer.
Definition: input.c:1275
void set(const char *key, const char *value)
Definition: rs-config.cpp:15
IMGUI_API void PopItemWidth()
Definition: imgui.cpp:4507
#define GLFW_KEY_KP_ENTER
Definition: glfw3.h:471
static const char * search_term
Definition: model-views.h:158
double time_added
Definition: output-model.h:116
void draw_dashboard(ux_window &win, rect &r)
static auto it
int min(int a, int b)
Definition: lz4s.c:73
GLuint GLsizei const GLchar * label
IMGUI_API float GetTextLineHeight()
Definition: imgui.cpp:5027
std::string timestamp
Definition: output-model.h:117
std::string filename
Definition: output-model.h:113
GLint GLsizei count
IMGUI_API bool Selectable(const char *label, bool selected=false, ImGuiSelectableFlags flags=0, const ImVec2 &size=ImVec2(0, 0))
Definition: imgui.cpp:8550
GLuint GLfloat GLfloat y0
Definition: glext.h:9721
typename::boost::move_detail::remove_reference< T >::type && move(T &&t) BOOST_NOEXCEPT
std::vector< std::unique_ptr< device_model > > device_models_list
Definition: model-views.h:96
float rs2_vector::* pos
std::string command_line
Definition: output-model.h:178
bool starts_with(const std::string &s, const std::string &prefix)
Definition: os.cpp:343
static const ImVec4 redish
Definition: model-views.h:52
std::vector< rs2::device > devices
Definition: output-model.h:175
IMGUI_API bool InputTextEx(const char *label, char *buf, int buf_size, const ImVec2 &size_arg, ImGuiInputTextFlags flags, ImGuiTextEditCallback callback=NULL, void *user_data=NULL)
Definition: imgui.cpp:7653
int i
GLuint res
Definition: glext.h:8856
std::array< float, 3 > color
Definition: model-views.h:449
void run_command(std::string command, std::vector< std::unique_ptr< device_model >> &device_models)
single_consumer_queue< log_entry > incoming_log_queue
Definition: output-model.h:146
int unique_id() const
Definition: rs_frame.hpp:54
const char * rs2_log_severity_to_string(rs2_log_severity info)
Definition: rs.cpp:1271
IMGUI_API void OpenPopup(const char *str_id)
Definition: imgui.cpp:3343
IMGUI_API void AddRect(const ImVec2 &a, const ImVec2 &b, ImU32 col, float rounding=0.0f, int rounding_corners=0x0F, float thickness=1.0f)
Definition: imgui_draw.cpp:806
IMGUI_API void SetCursorPosY(float y)
Definition: imgui.cpp:5108
rs2_log_severity
Severity of the librealsense logger.
Definition: rs_types.h:153
animated< int > search_width
Definition: output-model.h:169
void link_hovered()
Definition: ux-window.cpp:166
T value() const
Definition: rendering.h:1568
void draw(ux_window &win, rect view_rect, std::vector< std::unique_ptr< device_model >> &device_models)
static const ImVec4 dark_sensor_bg
Definition: model-views.h:63
IMGUI_API float GetCursorPosY()
Definition: imgui.cpp:5088
IMGUI_API bool IsItemHovered()
Definition: imgui.cpp:3200
int fps() const
Definition: rs_frame.hpp:49
GLdouble y1
IMGUI_API void SetKeyboardFocusHere(int offset=0)
Definition: imgui.cpp:5188
void draw(ux_window &win, rect r) override
IMGUI_API void PopFont()
Definition: imgui.cpp:4549
float x
Definition: imgui.h:90
IMGUI_API void PopStyleColor(int count=1)
Definition: imgui.cpp:4609
float height() const
Definition: ux-window.h:42
std::string to_string(T value)
int get_height() const override


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