ArVizWidgetController.cpp
Go to the documentation of this file.
1 /*
2  * This file is part of ArmarX.
3  *
4  * ArmarX is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License version 2 as
6  * published by the Free Software Foundation.
7  *
8  * ArmarX is distributed in the hope that it will be useful, but
9  * WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  * GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License
14  * along with this program. If not, see <http://www.gnu.org/licenses/>.
15  *
16  * \package RobotAPI::gui-plugins::ArVizWidgetController
17  * \author Fabian Paus ( fabian dot paus at kit dot edu )
18  * \date 2019
19  * \copyright http://www.gnu.org/licenses/gpl-2.0.txt
20  * GNU General Public License
21  */
22 
23 #include "ArVizWidgetController.h"
24 
26 
27 #include <SimoxUtility/algorithm/string/string_tools.h>
28 
29 #include <QLineEdit>
30 #include <QMessageBox>
31 #include <QTimer>
32 #include <QFileDialog>
33 
34 
35 namespace armarx
36 {
37  struct ArVizWidgetBatchCallback : IceUtil::Shared
38  {
40 
41  void onSuccess(viz::data::RecordingBatch const& batch)
42  {
43  this_->onGetBatchAsync(batch);
44  }
45 
46  void onFailure(Ice::Exception const& ex)
47  {
48  ARMARX_WARNING << "Failed to get batch async.\nReason:"
49  << ex;
50  }
51  };
52 
54  {
55  using This = ArVizWidgetController;
56 
57  widget.setupUi(getWidget());
58 
59  updateTimer = new QTimer(this);
60  connect(updateTimer, &QTimer::timeout, this, QOverload<>::of(&This::onUpdate));
61 
62  replayTimer = new QTimer(this);
63  connect(replayTimer, &QTimer::timeout, this, QOverload<>::of(&This::onReplayTimerTick));
64 
65  connect(widget.layerTree, &QTreeWidget::itemChanged, this, &This::layerTreeChanged);
66  connect(widget.expandButton, &QPushButton::clicked, this, &This::onExpandAll);
67  connect(widget.collapseButton, &QPushButton::clicked, this, &This::onCollapseAll);
68  connect(widget.filterEdit, &QLineEdit::textChanged, this, &This::onFilterTextChanged);
69  connect(widget.hideAllButton, &QPushButton::clicked, this, &This::onHideAll);
70  connect(widget.showAllButton, &QPushButton::clicked, this, &This::onShowAll);
71  connect(widget.hideFilteredButton, &QPushButton::clicked, this, &This::onHideFiltered);
72  connect(widget.showFilteredButton, &QPushButton::clicked, this, &This::onShowFiltered);
73 
74  connect(widget.recordingStartButton, &QPushButton::clicked, this, &This::onStartRecording);
75  connect(widget.recordingStopButton, &QPushButton::clicked, this, &This::onStopRecording);
76 
77  connect(widget.refreshRecordingsButton, &QPushButton::clicked, this, &This::onRefreshRecordings);
78  connect(widget.recordingList, &QListWidget::currentItemChanged, this, &This::onRecordingSelectionChanged);
79 
80  connect(widget.replayRevisionSpinBox, QOverload<int>::of(&QSpinBox::valueChanged), this, &This::onReplaySpinChanged);
81  connect(widget.replayRevisionSlider, QOverload<int>::of(&QSlider::valueChanged), this, &This::onReplaySliderChanged);
82 
83  connect(widget.replayStartButton, &QPushButton::clicked, this, &This::onReplayStart);
84  connect(widget.replayStopButton, &QPushButton::clicked, this, &This::onReplayStop);
85  connect(widget.replayTimedButton, &QPushButton::toggled, this, &This::onReplayTimedStart);
86 
87  connect(widget.exportToVRMLButton, &QPushButton::clicked, this, &This::exportToVRML);
88 
89  connect(widget.deselectButton, &QPushButton::clicked, this, &This::onDeselectElement);
90  connect(widget.listInteractiveElements, &QListWidget::itemDoubleClicked, this, &This::onInteractiveElementSelected);
91 
92  connect(this, &This::connectGui, this, &This::onConnectGui, Qt::QueuedConnection);
93  connect(this, &This::disconnectGui, this, &This::onDisconnectGui, Qt::QueuedConnection);
94 
95  // Layer info tree.
96 
97  connect(widget.layerTree, &QTreeWidget::currentItemChanged, this, &This::updateSelectedLayer);
98 
99  connect(widget.layerInfoTreeGroupBox, &QGroupBox::toggled, &layerInfoTree, &LayerInfoTree::setEnabled);
100  connect(widget.defaultShowLimitSpinBox, qOverload<int>(&QSpinBox::valueChanged),
102  layerInfoTree.setMaxElementCountDefault(widget.defaultShowLimitSpinBox->value());
103 
104  layerInfoTree.setWidget(widget.layerInfoTree);
105  layerInfoTree.setEnabled(widget.layerInfoTreeGroupBox->isChecked());
106  layerInfoTree.registerVisualizerCallbacks(visualizer);
107 
108 
109  // We need a callback from the visualizer, when the layers have changed
110  // So we can update the tree accordingly
111  visualizer.layersChangedCallback = [this](std::vector<viz::CoinLayerID> const & layers)
112  {
113  layersChanged(layers);
114  };
115 
116  replayTimer->start(33);
117  }
118 
120  {
121 
122  }
123 
125  {
126  if (storageName.size() > 0)
127  {
128  usingProxy(storageName);
129  }
130  if (debugObserverName.size() > 0)
131  {
132  usingProxy(debugObserverName);
133  }
134 
135  callbackData = new ArVizWidgetBatchCallback();
136  callbackData->this_ = this;
137  callback = viz::newCallback_StorageInterface_getRecordingBatch(
138  callbackData,
141  }
142 
144  {
145  visualizer.clearCache();
146  }
147 
149  {
150  getProxy(storage, storageName);
151  // DebugObserver is optional (check for null on every call)
152  if (!debugObserverName.empty())
153  {
154  getProxy(debugObserver, debugObserverName, false, "", false);
155  }
156 
157  lastTiming = visualizer.getTiming();
158  visualizer.startAsync(storage);
159 
160  // Changes to UI elements are only allowed in the GUI thread
161  emit connectGui();
162  }
163 
165  {
166  // Changes to UI elements are only allowed in the GUI thread
167  emit disconnectGui();
168  }
169 
170  void ArVizWidgetController::onConnectGui()
171  {
172  onRefreshRecordings();
173  currentRecordingSelected = false;
174  changeMode(ArVizWidgetMode::Live);
175 
176  updateTimer->start(33);
177  }
178 
179  void ArVizWidgetController::onDisconnectGui()
180  {
181  visualizer.stop();
182  updateTimer->stop();
183  changeMode(ArVizWidgetMode::NotConnected);
184  }
185 
186  void ArVizWidgetController::layerTreeChanged(QTreeWidgetItem* item, int /*column*/)
187  {
188  // Iterate over all items and activate/deactivate layers accordingly
189  int componentCount = widget.layerTree->topLevelItemCount();
190  for (int compIndex = 0; compIndex < componentCount; ++compIndex)
191  {
192  QTreeWidgetItem* componentItem = widget.layerTree->topLevelItem(compIndex);
193  std::string component = componentItem->text(0).toStdString();
194  Qt::CheckState componentCheck = componentItem->checkState(0);
195  int layerCount = componentItem->childCount();
196 
197  if (componentItem == item)
198  {
199  // The parent was selected or deselected, so all children should be set accordingly
200  ARMARX_VERBOSE << "Setting all children of " << component << " to " << (componentCheck == Qt::Checked);
201  for (int layerIndex = 0; layerIndex < layerCount; ++layerIndex)
202  {
203  QTreeWidgetItem* layerItem = componentItem->child(layerIndex);
204  if (layerItem->checkState(0) != componentCheck)
205  {
206  layerItem->setCheckState(0, componentCheck);
207  }
208  }
209  return;
210  }
211 
212  for (int layerIndex = 0; layerIndex < layerCount; ++layerIndex)
213  {
214  QTreeWidgetItem* layerItem = componentItem->child(layerIndex);
215  std::string layer = layerItem->text(0).toStdString();
216  bool layerVisible = (layerItem->checkState(0) == Qt::Checked);
217  ARMARX_VERBOSE << "Layer: " << layer << ", Visible: " << layerVisible;
218 
219  viz::CoinLayerID layerID(component, layer);
220  visualizer.showLayer(layerID, layerVisible);
221  }
222  }
223  }
224 
225  void ArVizWidgetController::layersChanged(std::vector<viz::CoinLayerID> const& layers)
226  {
227  QTreeWidget* tree = widget.layerTree;
228 
229  std::map<std::string, QTreeWidgetItem*> currentComponents;
230  std::map<viz::CoinLayerID, QTreeWidgetItem*> currentLayers;
231  int componentCount = widget.layerTree->topLevelItemCount();
232  for (int compIndex = 0; compIndex < componentCount; ++compIndex)
233  {
234  QTreeWidgetItem* componentItem = widget.layerTree->topLevelItem(compIndex);
235  std::string component = componentItem->text(0).toStdString();
236  currentComponents.emplace(component, componentItem);
237 
238  int layerCount = componentItem->childCount();
239  for (int layerIndex = 0; layerIndex < layerCount; ++layerIndex)
240  {
241  QTreeWidgetItem* layerItem = componentItem->child(layerIndex);
242  std::string layer = layerItem->text(0).toStdString();
243 
244  viz::CoinLayerID layerID(component, layer);
245  currentLayers.emplace(layerID, layerItem);
246  }
247  }
248 
249  const QList<QTreeWidgetItem*> selectedItems = widget.layerTree->selectedItems();
250 
251  // We need to determine which layers are new and where to append them
252  QTreeWidgetItem* currentItem = nullptr;
253  bool componentWasNew = false;
254  std::string currentComponent;
255  for (auto& entry : layers)
256  {
257  std::string const& component = entry.first;
258  if (component != currentComponent)
259  {
260  auto iter = currentComponents.find(component);
261  if (iter == currentComponents.end())
262  {
263  // Create a new item
264  currentItem = new QTreeWidgetItem(tree);
265  currentItem->setText(0, QString::fromStdString(component));
266  // A new item is visible by default
267  currentItem->setCheckState(0, Qt::Checked);
268 
269  componentWasNew = true;
270  }
271  else
272  {
273  // Item exists already
274  currentItem = iter->second;
275 
276  componentWasNew = false;
277  }
278 
279  currentComponent = component;
280  }
281 
282  auto iter = currentLayers.find(entry);
283  if (iter == currentLayers.end())
284  {
285  // Create a new item
286  std::string const& layer = entry.second;
287  QTreeWidgetItem* layerItem = new QTreeWidgetItem;
288  layerItem->setText(0, QString::fromStdString(layer));
289  // A new item is visible by default
290  layerItem->setCheckState(0, Qt::Checked);
291 
292  if (currentItem)
293  {
294  currentItem->addChild(layerItem);
295 
296  if (componentWasNew)
297  {
298  // Initially expand new items
299  tree->expandItem(currentItem);
300  }
301  }
302  else
303  {
304  ARMARX_WARNING << deactivateSpam(10, entry.first + entry.second)
305  << "Invalid component/layer ID: "
306  << entry.first << " / " << entry.second;
307  }
308  }
309  else
310  {
311  // Item exists already ==> nothing to be done
312  }
313  }
314  }
315 
316  void ArVizWidgetController::updateSelectedLayer(QTreeWidgetItem* current, QTreeWidgetItem* previous)
317  {
318  (void) previous;
319 
320  if (!current->parent())
321  {
322  // A component was selected.
323  return;
324  }
325 
326  // A layer was selected.
327  viz::CoinLayerID id(current->parent()->text(0).toStdString(), current->text(0).toStdString());
328 
329  viz::CoinLayer* layer = visualizer.layers.findLayer(id);
330  if (layer == nullptr)
331  {
332  ARMARX_WARNING << "Could not find layer (" << id.first << " / " << id.second << ") in Visualizer.";
333  }
334  else
335  {
336  layerInfoTree.setSelectedLayer(id, &visualizer.layers);
337  }
338  }
339 
340  void ArVizWidgetController::onCollapseAll(bool)
341  {
342  widget.layerTree->collapseAll();
343  }
344 
345  void ArVizWidgetController::onExpandAll(bool)
346  {
347  widget.layerTree->expandAll();
348  }
349 
350  void ArVizWidgetController::onHideAll(bool)
351  {
352  showAllLayers(false);
353  }
354 
355  void ArVizWidgetController::onShowAll(bool)
356  {
357  showAllLayers(true);
358  }
359 
360  void ArVizWidgetController::onHideFiltered(bool)
361  {
362  showFilteredLayers(false);
363  }
364 
365  void ArVizWidgetController::onShowFiltered(bool)
366  {
367  showFilteredLayers(true);
368  }
369 
370  void ArVizWidgetController::onFilterTextChanged(const QString& filter)
371  {
372  // Now we need to show these matches and hide the other items
373  // Is there a better way? Probably, via QSortFilterProxyModel...
374  QRegExp rx(filter, Qt::CaseInsensitive, QRegExp::Wildcard);
375  for (QTreeWidgetItemIterator iter(widget.layerTree); *iter; ++iter)
376  {
377  QTreeWidgetItem* item = *iter;
378  QString itemText = item->text(0);
379  bool matches = filter.size() == 0 || itemText.contains(rx);
380  item->setHidden(!matches);
381  if (matches && item->parent())
382  {
383  // Make parent visible if a child is visible
384  item->parent()->setHidden(false);
385  }
386  }
387  }
388 
389  void ArVizWidgetController::showAllLayers(bool visible)
390  {
391  widget.layerTree->blockSignals(true);
392 
393  for (QTreeWidgetItemIterator iter(widget.layerTree); *iter; ++iter)
394  {
395  QTreeWidgetItem* item = *iter;
396  item->setCheckState(0, visible ? Qt::Checked : Qt::Unchecked);
397  }
398 
399  widget.layerTree->blockSignals(false);
400 
401  // Update shown/hidden layers
402  layerTreeChanged(nullptr, 0);
403  }
404 
405  void ArVizWidgetController::showFilteredLayers(bool visible)
406  {
407  widget.layerTree->blockSignals(true);
408 
409  QString filter = widget.filterEdit->text();
410  QRegExp rx(filter, Qt::CaseInsensitive, QRegExp::Wildcard);
411 
412  for (QTreeWidgetItemIterator iter(widget.layerTree); *iter; ++iter)
413  {
414  QTreeWidgetItem* item = *iter;
415  QString itemText = item->text(0);
416  bool matches = filter.size() == 0 || itemText.contains(rx);
417  if (matches)
418  {
419  item->setCheckState(0, visible ? Qt::Checked : Qt::Unchecked);
420  }
421  }
422 
423  widget.layerTree->blockSignals(false);
424 
425  // Update shown/hidden layers
426  layerTreeChanged(nullptr, 0);
427  }
428 
429  void ArVizWidgetController::onDeselectElement()
430  {
431  // We just deselect all elements.
432  // Maybe we need to be more specific for strange use cases (?)
433  visualizer.selection->deselectAll();
434  }
435 
436  void ArVizWidgetController::onContextMenuClicked()
437  {
438  viz::ElementInteractionData* selected = visualizer.selectedElement;
439  if (selected == nullptr)
440  {
441  ARMARX_WARNING << "Selected element is null, but a context menu option was clicked!";
442  return;
443  }
444 
445  QPushButton* clickedButton = static_cast<QPushButton*>(sender());
446 
447  QLayout* layout = widget.groupBoxContextMenu->layout();
448  int count = layout->count();
449  for (int i = 0; i < count; ++i)
450  {
451  QPushButton* button = static_cast<QPushButton*>(layout->itemAt(i)->widget());
452  if (button == clickedButton)
453  {
454  viz::data::InteractionFeedback& interaction = visualizer.interactionFeedbackBuffer.emplace_back();
455  interaction.component = selected->layer.first;
456  interaction.layer = selected->layer.second;
457  interaction.element = selected->element;
458  interaction.type = viz::data::InteractionFeedbackType::CONTEXT_MENU_CHOSEN;
459  interaction.chosenContextMenuEntry = i;
460  return;
461  }
462  }
463  }
464 
465  void ArVizWidgetController::onInteractiveElementSelected(QListWidgetItem* item)
466  {
467  int index = widget.listInteractiveElements->row(item);
468  if (index < 0)
469  {
470  return;
471  }
472 
473  visualizer.selectElement(index);
474  }
475 
476  static QString toQString(viz::ElementInteractionData const& inter)
477  {
478  std::string id = inter.layer.first + "/"
479  + inter.layer.second + "/"
480  + inter.element;
481  return QString::fromStdString(id);
482  }
483 
484  void ArVizWidgetController::onUpdate()
485  {
486  visualizer.update();
487 
488  // Show the currently selected element
489  QString selectedElementName("<None>");
490  QLayout* contextMenuLayout = widget.groupBoxContextMenu->layout();
491  if (visualizer.selectedElement)
492  {
493  selectedElementName = toQString(*visualizer.selectedElement);
494 
495  // Show context menu options if enabled
496  int currentCount = contextMenuLayout->count();
497  viz::data::InteractionDescription const& desc = visualizer.selectedElement->interaction;
498  std::vector<std::string> const& options = desc.contextMenuOptions;
499  int newCount = 0;
500  if (desc.enableFlags & viz::data::InteractionEnableFlags::CONTEXT_MENU)
501  {
502  newCount = (int)options.size();
503  }
504  if (newCount != currentCount)
505  {
506  // Remove all items
507  QLayoutItem* item;
508  while ((item = contextMenuLayout->takeAt( 0 )) != nullptr)
509  {
510  delete item->widget();
511  delete item;
512  }
513 
514  for (std::string const& option : options)
515  {
516  QPushButton* button = new QPushButton(
517  QString::fromStdString(option),
518  widget.groupBoxContextMenu);
519  connect(button, &QPushButton::clicked, this, &ArVizWidgetController::onContextMenuClicked);
520  contextMenuLayout->addWidget(button);
521  }
522  }
523  else
524  {
525  for (int i = 0; i < currentCount; ++i)
526  {
527  QLayoutItem* item = contextMenuLayout->itemAt(i);
528  QPushButton* button = static_cast<QPushButton*>(item->widget());
529  button->setText(QString::fromStdString(options[i]));
530  }
531  }
532  }
533  else
534  {
535  QLayoutItem* item;
536  while ((item = contextMenuLayout->takeAt( 0 )) != nullptr)
537  {
538  delete item->widget();
539  delete item;
540  }
541  }
542  widget.labelSelectedElement->setText(selectedElementName);
543 
544  // Show the interactive elements
545  int currentCount = widget.listInteractiveElements->count();
546  int newCount = (int)visualizer.elementInteractions.size();
547  if (newCount != currentCount)
548  {
549  widget.listInteractiveElements->clear();
550  for (auto& interaction : visualizer.elementInteractions)
551  {
552  QString elementID = toQString(*interaction);
553  widget.listInteractiveElements->addItem(elementID);
554  }
555  }
556 
557  onTimingObserverUpdate();
558  }
559 
560  void ArVizWidgetController::onTimingObserverUpdate()
561  {
562  viz::CoinVisualizer_UpdateTiming timing = visualizer.getTiming();
563  //if (timing.counter > lastTiming.counter)
564  {
565  if (debugObserver)
566  {
567  timingMap["0. pull (ms)"] = new Variant(timing.pull.toMilliSecondsDouble());
568  timingMap["1. apply (ms)"] = new Variant(timing.applyTotal.total.toMilliSecondsDouble());
569  timingMap["1.1 apply, addLayer (ms)"] = new Variant(timing.applyTotal.addLayer.toMilliSecondsDouble());
570  timingMap["1.2 apply, updateElements (ms)"] = new Variant(timing.applyTotal.updateElements.toMilliSecondsDouble());
571  timingMap["1.3 apply, removeElements (ms)"] = new Variant(timing.applyTotal.removeElements.toMilliSecondsDouble());
572  timingMap["2. layers (ms)"] = new Variant(timing.layersChanged.toMilliSecondsDouble());
573  timingMap["3. wait duration (ms)"] = new Variant(timing.waitDuration.toMilliSecondsDouble());
574  timingMap["4. update toggle"] = new Variant(timing.updateToggle);
575  timingMap["total (ms)"] = new Variant(timing.total.toMilliSecondsDouble());
576 
577  timings.push_back(timing.total.toMilliSecondsDouble());
578  int numTimings = 20;
579  if ((int)timings.size() > numTimings)
580  {
581  timings.erase(timings.begin());
582  }
583  double averageTime = std::accumulate(timings.begin(), timings.end(), 0.0) / numTimings;
584  timingMap["total avg (ms)"] = new Variant(averageTime);
585 
586  debugObserver->begin_setDebugChannel("ArViz_Timing", timingMap);
587  }
588  }
589  }
590 
591  void ArVizWidgetController::onStartRecording()
592  {
593  std::string recordingID = widget.recordingIdTextBox->text().toStdString();
594 
595  std::string runningID = storage->startRecording(recordingID);
596 
597  changeMode(ArVizWidgetMode::Recording);
598 
599  if (runningID.size() > 0)
600  {
601  std::string message = "There is already a recording running with ID '"
602  + runningID + "'. \n"
603  + "You have to stop the running recording first";
604  QMessageBox::information(widget.tabWidget,
605  "Recording running",
606  QString::fromStdString(message));
607 
608 
609 
610  return;
611  }
612  }
613 
614  void ArVizWidgetController::onStopRecording()
615  {
616  storage->stopRecording();
617 
618  onRefreshRecordings();
619  changeMode(ArVizWidgetMode::Live);
620  }
621 
622  void ArVizWidgetController::onRefreshRecordings()
623  {
624  allRecordings = storage->getAllRecordings().recordings;
625  std::sort(allRecordings.begin(), allRecordings.end(),
626  [](viz::data::Recording const & lhs, viz::data::Recording const & rhs)
627  {
628  return lhs.id < rhs.id;
629  });
630 
631  std::string currentText;
632  QListWidgetItem* currentItem = widget.recordingList->currentItem();
633  if (currentItem)
634  {
635  currentText = currentItem->text().toStdString();
636  }
637 
638  widget.recordingList->clear();
639  int currentTextIndex = -1;
640  int index = 0;
641  for (auto& recording : allRecordings)
642  {
643  if (recording.id == currentText)
644  {
645  currentTextIndex = index;
646  }
647  widget.recordingList->addItem(QString::fromStdString(recording.id));
648  ++index;
649  }
650 
651  if (currentTextIndex > 0)
652  {
653  widget.recordingList->setCurrentRow(currentTextIndex);
654  }
655  }
656 
657  void ArVizWidgetController::onRecordingSelectionChanged(QListWidgetItem* current, QListWidgetItem* previous)
658  {
659  if (!current)
660  {
661  return;
662  }
663 
664  std::string selectedID = current->text().toStdString();
665  for (viz::data::Recording const& recording : allRecordings)
666  {
667  if (recording.id == selectedID)
668  {
669  selectRecording(recording);
670  break;
671  }
672  }
673  }
674 
675  static std::string timestampToString(long timestampInMicroSeconds, bool showMS = false)
676  {
677  IceUtil::Time time = IceUtil::Time::microSeconds(timestampInMicroSeconds);
678  std::string timeString = time.toDateTime();
679  if (!showMS)
680  {
681  timeString = timeString.substr(0, timeString.size() - 4);
682  };
683  return timeString;
684  }
685 
686  void ArVizWidgetController::onReplaySpinChanged(int newValue)
687  {
688  widget.replayRevisionSlider->setValue(newValue);
689  }
690 
691  void ArVizWidgetController::onReplaySliderChanged(int newValue)
692  {
693  if (currentRevision != newValue)
694  {
695  long timestamp = replayToRevision(newValue);
696  if (timestamp > 0)
697  {
698  currentRevision = newValue;
699  currentTimestamp = timestamp;
700  widget.replayRevisionSpinBox->setValue(newValue);
701 
702 
703  widget.replayTimestampLabel->setText(QString::fromStdString(
704  timestampToString(timestamp, true)
705  ));
706  }
707  else
708  {
709  widget.replayRevisionSlider->setValue(currentRevision);
710  }
711  }
712  }
713 
714  void ArVizWidgetController::selectRecording(const viz::data::Recording& recording)
715  {
716  // Update recording description
717  widget.recordingIdLabel->setText(QString::fromStdString(recording.id));
718 
719  widget.recordingRevisionLabel->setText(QString::fromStdString(
720  std::to_string(recording.firstRevision) +
721  " - " +
722  std::to_string(recording.lastRevision)));
723 
724  std::string firstTimeString = timestampToString(recording.firstTimestampInMicroSeconds);
725  std::string lastTimeString = timestampToString(recording.lastTimestampInMicroSeconds);
726 
727  widget.recordingTimestampLabel->setText(QString::fromStdString(
728  firstTimeString +
729  " - " +
730  lastTimeString));
731 
732  IceUtil::Time duration = IceUtil::Time::microSeconds(
733  recording.lastTimestampInMicroSeconds -
734  recording.firstTimestampInMicroSeconds);
735  int durationSeconds = duration.toSeconds();
736  widget.recordingDurationLabel->setText(QString::fromStdString(
737  std::to_string(durationSeconds) + " s"));
738 
739  widget.recordingBatchesLabel->setText(QString::fromStdString(
740  std::to_string(recording.batchHeaders.size())
741  ));
742 
743  // Update replay control
744  currentRecording = recording;
745  currentRecordingSelected = true;
746  enableWidgetAccordingToMode();
747  }
748 
749  void ArVizWidgetController::onReplayStart(bool)
750  {
751  if (!currentRecordingSelected)
752  {
753  ARMARX_WARNING << "No recording selected, so no replay can be started";
754  return;
755  }
756  {
757  std::unique_lock<std::mutex> lock(recordingBatchCacheMutex);
758  recordingBatchCache.clear();
759  }
760 
761  visualizer.stop();
762 
764 
765  widget.replayRevisionSpinBox->blockSignals(true);
766  widget.replayRevisionSpinBox->setMinimum(currentRecording.firstRevision);
767  widget.replayRevisionSpinBox->setMaximum(currentRecording.lastRevision);
768  widget.replayRevisionSpinBox->setValue(currentRecording.firstRevision);
769  widget.replayRevisionSpinBox->blockSignals(false);
770 
771  widget.replayRevisionSlider->blockSignals(true);
772  widget.replayRevisionSlider->setMinimum(currentRecording.firstRevision);
773  widget.replayRevisionSlider->setMaximum(currentRecording.lastRevision);
774  widget.replayRevisionSlider->setValue(currentRecording.firstRevision);
775  widget.replayRevisionSlider->blockSignals(false);
776 
777  currentRevision = -1;
778  onReplaySliderChanged(widget.replayRevisionSlider->value());
779  }
780 
781  void ArVizWidgetController::onReplayStop(bool)
782  {
783  visualizer.startAsync(storage);
784 
785  changeMode(ArVizWidgetMode::Live);
786  }
787 
788  long ArVizWidgetController::replayToRevision(long revision)
789  {
791  {
792  ARMARX_WARNING << "Cannot call replayToRevision, when not in replaying mode.\n"
793  << "Actual mode: " << int(mode);
794  return -1;
795  }
796 
797  viz::data::RecordingBatchHeader* matchingBatchHeader = nullptr;
798  for (auto& batchHeader : currentRecording.batchHeaders)
799  {
800  if (batchHeader.firstRevision <= revision &&
801  revision <= batchHeader.lastRevision)
802  {
803  matchingBatchHeader = &batchHeader;
804  break;
805  }
806  }
807  if (matchingBatchHeader == nullptr)
808  {
809  ARMARX_WARNING << "Could not find batch for revision: " << revision;
810  return -1;
811  }
812 
813  viz::data::RecordingBatch const& batch = getRecordingBatch(matchingBatchHeader->index);
814 
815  ARMARX_VERBOSE << "Replaying to revision : " << revision
816  << "\nGot batch: " << batch.header.firstRevision << " - " << batch.header.lastRevision
817  << "\nUpdates: " << batch.updates.size()
818  << "\nInitial state: " << batch.initialState.size();
819 
820 
821  auto revisionLess = [](viz::data::TimestampedLayerUpdate const & lhs, viz::data::TimestampedLayerUpdate const & rhs)
822  {
823  return lhs.revision < rhs.revision;
824  };
825  viz::data::TimestampedLayerUpdate pivot;
826  pivot.revision = revision;
827  auto updateBegin = std::lower_bound(batch.updates.begin(), batch.updates.end(), pivot, revisionLess);
828  auto updateEnd = std::upper_bound(updateBegin, batch.updates.end(), pivot, revisionLess);
829 
830  // TODO: Optimize: Only start from the last update position
831  std::map<std::string, viz::data::LayerUpdate const*> updates;
832 
833  for (auto& update : batch.initialState)
834  {
835  updates[update.update.name] = &update.update;
836  }
837  for (auto updateIter = batch.updates.begin(); updateIter != updateEnd; ++updateIter)
838  {
839  updates[updateIter->update.name] = &updateIter->update;
840  }
841 
842  auto layerIDsBefore = visualizer.getLayerIDs();
843  for (auto& pair : updates)
844  {
845  visualizer.apply(*pair.second);
846  }
847  auto layerIDsAfter = visualizer.getLayerIDs();
848  if (layerIDsAfter != layerIDsBefore)
849  {
850  visualizer.emitLayersChanged(layerIDsAfter);
851  }
852 
853  return updateBegin->timestampInMicroseconds;
854  }
855 
856  long ArVizWidgetController::getRevisionForTimestamp(long timestamp)
857  {
859  {
860  ARMARX_WARNING << "Cannot call replayToTimestamp, when not in replaying mode.\n"
861  << "Actual mode: " << int(mode);
862  return -1;
863  }
864 
865  if (timestamp < currentRecording.firstTimestampInMicroSeconds)
866  {
867  ARMARX_INFO << "Requested timestamp is earlier than recording: " << timestampToString(timestamp);
868  return -1;
869  }
870 
871  viz::data::RecordingBatchHeader* matchingBatchHeader = nullptr;
872  for (auto& batchHeader : currentRecording.batchHeaders)
873  {
874  matchingBatchHeader = &batchHeader;
875  if (timestamp <= batchHeader.lastTimestampInMicroSeconds)
876  {
877  break;
878  }
879  }
880 
881  viz::data::RecordingBatch const& batch = getRecordingBatch(matchingBatchHeader->index);
882 
883  auto timestampLess = [](viz::data::TimestampedLayerUpdate const & lhs, viz::data::TimestampedLayerUpdate const & rhs)
884  {
885  return lhs.timestampInMicroseconds < rhs.timestampInMicroseconds;
886  };
887  viz::data::TimestampedLayerUpdate pivot;
888  pivot.timestampInMicroseconds = timestamp;
889  auto updateEnd = std::lower_bound(batch.updates.begin(), batch.updates.end(), pivot, timestampLess);
890  if (updateEnd == batch.updates.end())
891  {
892  return -2;
893  }
894  if (updateEnd != batch.updates.begin())
895  {
896  // lower_bound gives the first entry with a later timestamp then the goal
897  // So we should only apply updates before this point
898  updateEnd -= 1;
899  }
900 
901  long revisionBeforeTimestamp = updateEnd->revision;
902  return revisionBeforeTimestamp;
903  }
904 
905  void ArVizWidgetController::onReplayTimedStart(bool checked)
906  {
907  if (checked)
908  {
909 
911  replayCurrentTimestamp = currentTimestamp;
912  }
913  else
914  {
916  }
917  }
918 
919  void ArVizWidgetController::onReplayTimerTick()
920  {
922  {
923  double replaySpeed = widget.replaySpeedSpinBox->value();
924 
925  long currentRealTime = IceUtil::Time::now().toMicroSeconds();
926  long elapsedRealTime = currentRealTime - lastReplayRealTime;
927 
928  replayCurrentTimestamp += elapsedRealTime * replaySpeed;
929 
930  long revision = getRevisionForTimestamp(replayCurrentTimestamp);
931  if (revision == -2)
932  {
933  if (widget.replayLoopbackCheckBox->checkState() == Qt::Checked)
934  {
935  replayCurrentTimestamp = currentRecording.firstTimestampInMicroSeconds;
936  }
937  else
938  {
939  revision = currentRecording.lastRevision;
940  }
941  }
942  if (revision >= 0)
943  {
944  widget.replayRevisionSlider->setValue(revision);
945  }
946  }
947 
948  lastReplayRealTime = IceUtil::Time::now().toMicroSeconds();
949  }
950 
951  void ArVizWidgetController::changeMode(ArVizWidgetMode newMode)
952  {
953  mode = newMode;
954 
955  enableWidgetAccordingToMode();
956  }
957 
958  void ArVizWidgetController::enableWidgetAccordingToMode()
959  {
960  switch (mode)
961  {
963  {
964  widget.recordingStartButton->setDisabled(true);
965  widget.recordingStopButton->setDisabled(true);
966  widget.replayStartButton->setDisabled(true);
967  widget.replayStopButton->setDisabled(true);
968  widget.replayControlGroupBox->setDisabled(true);
969  }
970  break;
972  {
973  widget.recordingStartButton->setDisabled(false);
974  widget.recordingStopButton->setDisabled(true);
975  widget.replayStartButton->setDisabled(false);
976  widget.replayStopButton->setDisabled(true);
977  widget.replayControlGroupBox->setDisabled(true);
978  widget.recordingList->setDisabled(false);
979  }
980  break;
982  {
983  widget.recordingStartButton->setDisabled(true);
984  widget.recordingStopButton->setDisabled(false);
985  widget.replayStartButton->setDisabled(true);
986  widget.replayStopButton->setDisabled(true);
987  widget.replayControlGroupBox->setDisabled(true);
988  }
989  break;
991  {
992  widget.recordingStartButton->setDisabled(true);
993  widget.recordingStopButton->setDisabled(true);
994  widget.replayStartButton->setDisabled(true);
995  widget.replayStopButton->setDisabled(false);
996  widget.replayControlGroupBox->setDisabled(false);
997  widget.replayRevisionSlider->setDisabled(false);
998  widget.replayRevisionSpinBox->setDisabled(false);
999  widget.recordingList->setDisabled(true);
1000  }
1001  break;
1003  {
1004  widget.recordingStartButton->setDisabled(true);
1005  widget.recordingStopButton->setDisabled(true);
1006  widget.replayStartButton->setDisabled(true);
1007  widget.replayStopButton->setDisabled(false);
1008  widget.replayControlGroupBox->setDisabled(false);
1009  widget.replayRevisionSlider->setDisabled(true);
1010  widget.replayRevisionSpinBox->setDisabled(true);
1011  widget.recordingList->setDisabled(true);
1012  }
1013  break;
1014  }
1015 
1016  if (!currentRecordingSelected)
1017  {
1018  widget.replayStartButton->setDisabled(true);
1019  widget.replayStopButton->setDisabled(true);
1020  }
1021  }
1022 
1023  void ArVizWidgetController::onGetBatchAsync(const viz::data::RecordingBatch& batch)
1024  {
1025  // We received a batch asynchronously ==> Update the cache
1026  ARMARX_INFO << "Received async batch: " << batch.header.index;
1027  std::unique_lock<std::mutex> lock(recordingBatchCacheMutex);
1028 
1029  auto& entry = recordingBatchCache[batch.header.index];
1030  entry.data = batch;
1031  entry.lastUsed = IceUtil::Time::now();
1032 
1033  limitRecordingBatchCacheSize();
1034 
1035  recordingWaitingForBatchIndex = -1;
1036  }
1037 
1038  viz::data::RecordingBatch const& ArVizWidgetController::getRecordingBatch(long index)
1039  {
1040  ARMARX_TRACE;
1041 
1042  IceUtil::Time now = IceUtil::Time::now();
1043 
1044  std::unique_lock<std::mutex> lock(recordingBatchCacheMutex);
1045 
1046  auto iter = recordingBatchCache.find(index);
1047  if (iter != recordingBatchCache.end())
1048  {
1049  // Start prefetching neighbouring batches
1050  bool asyncPrefetchIsRunning = callbackResult && !callbackResult->isCompleted();
1051  if (!asyncPrefetchIsRunning && recordingWaitingForBatchIndex == -1)
1052  {
1053  if (index + 1 < long(currentRecording.batchHeaders.size())
1054  && recordingBatchCache.count(index + 1) == 0)
1055  {
1056  // ARMARX_WARNING << "after begin_getRecordingBatch: " << (index + 1)
1057  // << " waiting for " << recordingWaitingForBatchIndex;
1058  callbackResult = storage->begin_getRecordingBatch(currentRecording.id, index + 1, callback);
1059  recordingWaitingForBatchIndex = index + 1;
1060  ARMARX_INFO << "Now waiting for " << recordingWaitingForBatchIndex;
1061  }
1062  else if (index > 0 && recordingBatchCache.count(index - 1) == 0)
1063  {
1064  // ARMARX_WARNING << "before begin_getRecordingBatch: " << (index - 1)
1065  // << " waiting for " << recordingWaitingForBatchIndex;
1066  callbackResult = storage->begin_getRecordingBatch(currentRecording.id, index - 1, callback);
1067  recordingWaitingForBatchIndex = index - 1;
1068  }
1069 
1070  }
1071 
1072  TimestampedRecordingBatch& entry = iter->second;
1073  entry.lastUsed = now;
1074  return entry.data;
1075  }
1076 
1077  // Maybe there has already been sent a asynchronous request to get
1078  if (index == recordingWaitingForBatchIndex)
1079  {
1080  lock.unlock();
1081  ARMARX_INFO << "Waiting to receive async batch: " << index;
1082  // Wait until request completes
1083  while (recordingWaitingForBatchIndex != -1)
1084  {
1085  QCoreApplication::processEvents();
1086  }
1087  return getRecordingBatch(index);
1088  }
1089 
1090  ARMARX_INFO << "Batch #" << index << " is not in the cache. Getting synchronously, blocking GUI...";
1091 
1092  // Entry is not in the cache, we have to get it from ArVizStorage
1093  auto& newEntry = recordingBatchCache[index];
1094  newEntry.lastUsed = now;
1095  newEntry.data = storage->getRecordingBatch(currentRecording.id, index);
1096 
1097  limitRecordingBatchCacheSize();
1098 
1099  return newEntry.data;
1100  }
1101 
1102  void ArVizWidgetController::limitRecordingBatchCacheSize()
1103  {
1104  if (recordingBatchCache.size() > recordingBatchCacheMaxSize)
1105  {
1106  // Remove the entry with the oldest last used timestamp
1107  auto oldestIter = recordingBatchCache.begin();
1108  for (auto iter = recordingBatchCache.begin();
1109  iter != recordingBatchCache.end(); ++iter)
1110  {
1111  TimestampedRecordingBatch& entry = iter->second;
1112  if (entry.lastUsed < oldestIter->second.lastUsed)
1113  {
1114  oldestIter = iter;
1115  }
1116  }
1117 
1118  recordingBatchCache.erase(oldestIter);
1119  }
1120  }
1121 
1123  {
1124  return visualizer.root;
1125  }
1126 
1127  static const std::string CONFIG_KEY_STORAGE = "Storage";
1128  static const std::string CONFIG_KEY_DEBUG_OBSERVER = "DebugObserver";
1129 
1130  void ArVizWidgetController::loadSettings(QSettings* settings)
1131  {
1132  storageName = settings->value(QString::fromStdString(CONFIG_KEY_STORAGE),
1133  "ArVizStorage").toString().toStdString();
1134  debugObserverName = settings->value(QString::fromStdString(CONFIG_KEY_DEBUG_OBSERVER),
1135  "DebugObserver").toString().toStdString();
1136  }
1137 
1138  void ArVizWidgetController::saveSettings(QSettings* settings)
1139  {
1140  settings->setValue(QString::fromStdString(CONFIG_KEY_STORAGE),
1141  QString::fromStdString(storageName));
1142  settings->setValue(QString::fromStdString(CONFIG_KEY_DEBUG_OBSERVER),
1143  QString::fromStdString(debugObserverName));
1144  }
1145 
1146  QPointer<QDialog> ArVizWidgetController::getConfigDialog(QWidget* parent)
1147  {
1148  if (!configDialog)
1149  {
1150  configDialog = new SimpleConfigDialog(parent);
1151  configDialog->addProxyFinder<armarx::viz::StorageInterfacePrx>({CONFIG_KEY_STORAGE, "ArViz Storage", "ArViz*"});
1152  configDialog->addProxyFinder<armarx::DebugObserverInterfacePrx>({CONFIG_KEY_DEBUG_OBSERVER, "Debug observer", "DebugObserver"});
1153  }
1154  return qobject_cast<QDialog*>(configDialog);
1155  }
1156 
1158  {
1159  if (configDialog)
1160  {
1161  storageName = configDialog->getProxyName(CONFIG_KEY_STORAGE);
1162  debugObserverName = configDialog->getProxyName(CONFIG_KEY_DEBUG_OBSERVER);
1163  }
1164  }
1165 
1166 
1168  {
1169 
1170  QString fi = QFileDialog::getSaveFileName(Q_NULLPTR, tr("VRML 2.0 File"), QString(), tr("VRML Files (*.wrl)"));
1171  std::string s = std::string(fi.toLatin1());
1172 
1173  if (s.empty())
1174  {
1175  return;
1176  }
1177  if (!simox::alg::ends_with(s, ".wrl"))
1178  {
1179  s += ".wrl";
1180  }
1181 
1182  visualizer.exportToVRML(s);
1183  }
1184 }
armarx::viz::CoinVisualizer::selectedElement
ElementInteractionData * selectedElement
Definition: Visualizer.h:253
armarx::viz::CoinLayer
Definition: Visualizer.h:36
armarx::viz::CoinVisualizer_ApplyTiming::removeElements
IceUtil::Time removeElements
Definition: Visualizer.h:158
armarx::ArVizWidgetMode::Recording
@ Recording
armarx::ArVizWidgetController::onExitComponent
void onExitComponent() override
Hook for subclass.
Definition: ArVizWidgetController.cpp:143
armarx::viz::coin::exportToVRML
void exportToVRML(SoNode *node, std::string const &exportFilePath)
Definition: ExportVRML.cpp:68
ARMARX_VERBOSE
#define ARMARX_VERBOSE
Definition: Logging.h:180
armarx::LayerInfoTree::registerVisualizerCallbacks
void registerVisualizerCallbacks(viz::CoinVisualizer &visualizer)
Definition: LayerInfoTree.cpp:65
armarx::viz::CoinVisualizer_UpdateTiming::waitDuration
IceUtil::Time waitDuration
Definition: Visualizer.h:181
armarx::viz::CoinLayerMap::findLayer
CoinLayer * findLayer(CoinLayerID const &id)
Definition: Visualizer.h:118
armarx::ArVizWidgetMode
ArVizWidgetMode
Definition: ArVizWidgetController.h:41
armarx::viz::CoinVisualizer::selectElement
void selectElement(int index)
Definition: Visualizer.cpp:583
armarx::ArVizWidgetBatchCallback
Definition: ArVizWidgetController.cpp:37
armarx::viz::CoinVisualizer_UpdateTiming::total
IceUtil::Time total
Definition: Visualizer.h:178
armarx::viz::CoinVisualizer::showLayer
void showLayer(CoinLayerID const &id, bool visible)
Definition: Visualizer.cpp:514
armarx::ArVizWidgetController::configured
void configured() override
This function must be implemented by the user, if he supplies a config dialog.
Definition: ArVizWidgetController.cpp:1157
armarx::viz::interaction
InteractionDescription interaction()
Definition: ElementOps.h:101
index
uint8_t index
Definition: EtherCATFrame.h:59
ArVizWidgetController.h
armarx::ProxyType::component
@ component
armarx::viz::CoinVisualizer::clearCache
void clearCache()
Definition: Visualizer.cpp:142
armarx::viz::CoinVisualizer::startAsync
void startAsync(StorageInterfacePrx const &storage)
Definition: Visualizer.cpp:149
armarx::LayerInfoTree::setWidget
void setWidget(QTreeWidget *treeWidget)
Definition: LayerInfoTree.cpp:26
armarx::viz::CoinVisualizer::selection
SoSelection * selection
Definition: Visualizer.h:268
armarx::ArVizWidgetController::loadSettings
void loadSettings(QSettings *settings) override
Implement to load the settings that are part of the GUI configuration.
Definition: ArVizWidgetController.cpp:1130
armarx::viz::ElementInteractionData::layer
CoinLayerID layer
Definition: Visualizer.h:192
armarx::viz::CoinVisualizer::getLayerIDs
std::vector< CoinLayerID > getLayerIDs()
Definition: Visualizer.cpp:553
armarx::LayerInfoTree::setSelectedLayer
void setSelectedLayer(viz::CoinLayerID id, viz::CoinLayerMap *layers)
Set the selected layer.
Definition: LayerInfoTree.cpp:98
armarx::ArVizWidgetBatchCallback::this_
struct ArVizWidgetController * this_
Definition: ArVizWidgetController.cpp:39
armarx::ArVizWidgetController::connectGui
void connectGui()
message
message(STATUS "Boost-Library-Dir: " "${Boost_LIBRARY_DIRS}") message(STATUS "Boost-LIBRARIES
Definition: CMakeLists.txt:8
armarx::LayerInfoTree::setEnabled
void setEnabled(bool enabled)
Enable or disable the layer info tree.
Definition: LayerInfoTree.cpp:82
armarx::viz::CoinVisualizer_UpdateTiming::pull
IceUtil::Time pull
Definition: Visualizer.h:176
armarx::viz::CoinVisualizer_ApplyTiming::updateElements
IceUtil::Time updateElements
Definition: Visualizer.h:157
armarx::ArVizWidgetController::onGetBatchAsync
void onGetBatchAsync(viz::data::RecordingBatch const &batch)
Definition: ArVizWidgetController.cpp:1023
armarx::ArVizWidgetMode::ReplayingManual
@ ReplayingManual
armarx::viz::CoinVisualizer_UpdateTiming::updateToggle
int updateToggle
Definition: Visualizer.h:183
armarx::viz::CoinVisualizer_UpdateTiming
Definition: Visualizer.h:170
armarx::ArVizWidgetController
ArVizWidgetController brief one line description.
Definition: ArVizWidgetController.h:71
armarx::ArVizWidgetController::saveSettings
void saveSettings(QSettings *settings) override
Implement to save the settings as part of the GUI configuration.
Definition: ArVizWidgetController.cpp:1138
armarx::ArVizWidgetController::getConfigDialog
QPointer< QDialog > getConfigDialog(QWidget *parent) override
getConfigDialog returns a pointer to the a configuration widget of this controller.
Definition: ArVizWidgetController.cpp:1146
ARMARX_TRACE
#define ARMARX_TRACE
Definition: trace.h:69
armarx::viz::ElementInteractionData::interaction
viz::data::InteractionDescription interaction
Definition: Visualizer.h:194
armarx::ArVizWidgetMode::NotConnected
@ NotConnected
armarx::viz::ElementInteractionData
Definition: Visualizer.h:190
armarx::viz::CoinVisualizer_UpdateTiming::layersChanged
IceUtil::Time layersChanged
Definition: Visualizer.h:177
armarx::ArVizWidgetController::disconnectGui
void disconnectGui()
armarx::viz::ElementInteractionData::element
std::string element
Definition: Visualizer.h:193
armarx::ArVizWidgetController::onDisconnectComponent
void onDisconnectComponent() override
Hook for subclass.
Definition: ArVizWidgetController.cpp:164
armarx::viz::CoinVisualizer::emitLayersChanged
void emitLayersChanged(std::vector< CoinLayerID > const &layerIDs)
Definition: Visualizer.cpp:564
armarx::viz::CoinVisualizer_ApplyTiming::total
IceUtil::Time total
Definition: Visualizer.h:159
armarx::viz::CoinVisualizer::layers
CoinLayerMap layers
Definition: Visualizer.h:263
armarx::viz::CoinVisualizer::stop
void stop()
Definition: Visualizer.cpp:163
armarx::ArVizWidgetController::onInitComponent
void onInitComponent() override
Definition: ArVizWidgetController.cpp:124
armarx::viz::CoinVisualizer::exportToVRML
void exportToVRML(std::string const &exportFilePath)
Definition: Visualizer.cpp:942
armarx::viz::CoinVisualizer::update
void update()
Definition: Visualizer.cpp:389
armarx::ArVizWidgetController::ArVizWidgetController
ArVizWidgetController()
Controller Constructor.
Definition: ArVizWidgetController.cpp:53
armarx::viz::CoinVisualizer_UpdateTiming::applyTotal
CoinVisualizer_ApplyTiming applyTotal
Definition: Visualizer.h:174
armarx::ArVizWidgetBatchCallback::onSuccess
void onSuccess(viz::data::RecordingBatch const &batch)
Definition: ArVizWidgetController.cpp:41
armarx::viz::CoinVisualizer::root
SoSeparator * root
Definition: Visualizer.h:269
armarx::armem::Time
armarx::core::time::DateTime Time
Definition: forward_declarations.h:13
armarx::to_string
const std::string & to_string(const std::string &s)
Definition: StringHelpers.h:40
armarx::armem::server::ltm::util::mongodb::detail::update
bool update(mongocxx::collection &coll, const nlohmann::json &query, const nlohmann::json &update)
Definition: mongodb.cpp:67
armarx::ArVizWidgetController::onConnectComponent
void onConnectComponent() override
Pure virtual hook for the subclass.
Definition: ArVizWidgetController.cpp:148
armarx::ArVizWidgetController::~ArVizWidgetController
virtual ~ArVizWidgetController() override
Controller destructor.
Definition: ArVizWidgetController.cpp:119
armarx::viz::CoinVisualizer::getTiming
CoinVisualizer_UpdateTiming getTiming()
Definition: Visualizer.cpp:547
visionx::imrec::Recording
std::shared_ptr< AbstractRecordingStrategy > Recording
Convenience alias for any recording strategy.
Definition: AbstractRecordingStrategy.h:181
armarx::viz::CoinVisualizer::apply
CoinVisualizer_ApplyTiming apply(data::LayerUpdate const &update)
Definition: Visualizer.cpp:173
option
#define option(type, fn)
armarx::ArVizWidgetController::getScene
SoNode * getScene() override
Reimplementing this function and returning a SoNode* will show this SoNode in the 3DViewerWidget,...
Definition: ArVizWidgetController.cpp:1122
ARMARX_INFO
#define ARMARX_INFO
Definition: Logging.h:174
armarx::viz::CoinVisualizer::elementInteractions
std::vector< std::unique_ptr< ElementInteractionData > > elementInteractions
Definition: Visualizer.h:250
armarx::skills::gui::matches
bool matches(std::string skillName, std::vector< std::string > &searches)
Definition: SkillManagerWrapper.cpp:59
armarx::ends_with
bool ends_with(const std::string &haystack, const std::string &needle)
Definition: StringHelpers.cpp:50
IceInternal::ProxyHandle<::IceProxy::armarx::DebugObserverInterface >
armarx::Logging::deactivateSpam
SpamFilterDataPtr deactivateSpam(float deactivationDurationSec=10.0f, const std::string &identifier="", bool deactivate=true) const
disables the logging for the current line for the given amount of seconds.
Definition: Logging.cpp:92
armarx::ArmarXWidgetController::getWidget
virtual QPointer< QWidget > getWidget()
getWidget returns a pointer to the a widget of this controller.
Definition: ArmarXWidgetController.cpp:54
armarx::RemoteGui::toQString
QString toQString(std::string const &string)
Definition: WidgetHandler.cpp:12
armarx::ArVizWidgetMode::Live
@ Live
armarx::viz::CoinVisualizer::layersChangedCallback
std::function< void(std::vector< CoinLayerID > const &)> layersChangedCallback
Definition: Visualizer.h:280
ARMARX_WARNING
#define ARMARX_WARNING
Definition: Logging.h:186
armarx::ArVizWidgetMode::ReplayingTimed
@ ReplayingTimed
armarx::LayerInfoTree::setMaxElementCountDefault
void setMaxElementCountDefault(int max)
Definition: LayerInfoTree.cpp:77
armarx::ManagedIceObject::getProxy
Ice::ObjectPrx getProxy(long timeoutMs=0, bool waitForScheduler=true) const
Returns the proxy of this object (optionally it waits for the proxy)
Definition: ManagedIceObject.cpp:393
Variant.h
armarx::ArVizWidgetBatchCallback::onFailure
void onFailure(Ice::Exception const &ex)
Definition: ArVizWidgetController.cpp:46
armarx::ManagedIceObject::usingProxy
bool usingProxy(const std::string &name, const std::string &endpoints="")
Registers a proxy for retrieval after initialization and adds it to the dependency list.
Definition: ManagedIceObject.cpp:151
armarx::ctrlutil::s
double s(double t, double s0, double v0, double a0, double j)
Definition: CtrlUtil.h:33
armarx::viz::CoinLayerID
std::pair< std::string, std::string > CoinLayerID
Definition: Visualizer.h:21
armarx
This file offers overloads of toIce() and fromIce() functions for STL container types.
Definition: ArmarXTimeserver.cpp:28
armarx::viz::CoinVisualizer_ApplyTiming::addLayer
IceUtil::Time addLayer
Definition: Visualizer.h:156
armarx::viz::CoinVisualizer::interactionFeedbackBuffer
std::vector< viz::data::InteractionFeedback > interactionFeedbackBuffer
Definition: Visualizer.h:251
armarx::SimpleConfigDialog
A config-dialog containing one (or multiple) proxy finders.
Definition: SimpleConfigDialog.h:84