From b4027acfce38fcfb574801d7fa09b5c67ba20c12 Mon Sep 17 00:00:00 2001 From: Fabian Paus <fabian.paus@kit.edu> Date: Thu, 29 Jul 2021 14:49:31 +0200 Subject: [PATCH] ArViz: Cleanup timer changes from Coin to Qt --- .../components/ArViz/Coin/Visualizer.cpp | 14 +--- .../components/ArViz/Coin/Visualizer.h | 1 - .../ArViz/ArVizWidgetController.cpp | 73 ++++++++++++++----- .../gui-plugins/ArViz/ArVizWidgetController.h | 3 + 4 files changed, 59 insertions(+), 32 deletions(-) diff --git a/source/RobotAPI/components/ArViz/Coin/Visualizer.cpp b/source/RobotAPI/components/ArViz/Coin/Visualizer.cpp index 5f99047a6..778c2db5f 100644 --- a/source/RobotAPI/components/ArViz/Coin/Visualizer.cpp +++ b/source/RobotAPI/components/ArViz/Coin/Visualizer.cpp @@ -5,6 +5,7 @@ #include <Inventor/sensors/SoTimerSensor.h> #include <Inventor/nodes/SoUnits.h> +#include <QCoreApplication> #include <thread> @@ -88,11 +89,6 @@ namespace armarx::viz &CoinVisualizerWrapper::onUpdateSuccess, &CoinVisualizerWrapper::onUpdateFailure); root = new SoSeparator; - - //timerSensor = new SoTimerSensor(updateVisualizationCB, this); - - //float cycleTimeMS = 33.0f; - //timerSensor->setInterval(SbTime(cycleTimeMS / 1000.0f)); } CoinVisualizer::~CoinVisualizer() @@ -114,9 +110,6 @@ namespace armarx::viz } state = CoinVisualizerState::STARTING; stateStorage = storage; - - //SoSensorManager* sensor_mgr = SoDB::getSensorManager(); - //sensor_mgr->insertTimerSensor(timerSensor); } void CoinVisualizer::stop() @@ -126,15 +119,12 @@ namespace armarx::viz return; } - SoSensorManager* sensor_mgr = SoDB::getSensorManager(); state = CoinVisualizerState::STOPPING; while (state != CoinVisualizerState::STOPPED) { - sensor_mgr->processTimerQueue(); + QCoreApplication::processEvents(); usleep(1000); } - sensor_mgr->removeTimerSensor(timerSensor); - } CoinVisualizer_ApplyTiming CoinVisualizer::apply(data::LayerUpdate const& update) diff --git a/source/RobotAPI/components/ArViz/Coin/Visualizer.h b/source/RobotAPI/components/ArViz/Coin/Visualizer.h index 49ad2a51b..1494be07d 100644 --- a/source/RobotAPI/components/ArViz/Coin/Visualizer.h +++ b/source/RobotAPI/components/ArViz/Coin/Visualizer.h @@ -229,7 +229,6 @@ namespace armarx::viz std::mutex storageMutex; viz::StorageInterfacePrx storage; - SoTimerSensor* timerSensor = nullptr; CoinLayerMap layers; std::vector<std::type_index> elementVisualizersTypes; diff --git a/source/RobotAPI/gui-plugins/ArViz/ArVizWidgetController.cpp b/source/RobotAPI/gui-plugins/ArViz/ArVizWidgetController.cpp index 4f7372a5e..e210b778f 100644 --- a/source/RobotAPI/gui-plugins/ArViz/ArVizWidgetController.cpp +++ b/source/RobotAPI/gui-plugins/ArViz/ArVizWidgetController.cpp @@ -810,30 +810,34 @@ namespace armarx void ArVizWidgetController::onReplayTimerTick() { - if (mode != ArVizWidgetMode::ReplayingTimed) + if (mode == ArVizWidgetMode::ReplayingTimed) { - return; - } - double replaySpeed = widget.replaySpeedSpinBox->value(); + double replaySpeed = widget.replaySpeedSpinBox->value(); - replayCurrentTimestamp += 33000 * replaySpeed; + long currentRealTime = IceUtil::Time::now().toMicroSeconds(); + long elapsedRealTime = currentRealTime - lastReplayRealTime; - long revision = getRevisionForTimestamp(replayCurrentTimestamp); - if (revision == -2) - { - if (widget.replayLoopbackCheckBox->checkState() == Qt::Checked) + replayCurrentTimestamp += elapsedRealTime * replaySpeed; + + long revision = getRevisionForTimestamp(replayCurrentTimestamp); + if (revision == -2) { - replayCurrentTimestamp = currentRecording.firstTimestampInMicroSeconds; + if (widget.replayLoopbackCheckBox->checkState() == Qt::Checked) + { + replayCurrentTimestamp = currentRecording.firstTimestampInMicroSeconds; + } + else + { + revision = currentRecording.lastRevision; + } } - else + if (revision >= 0) { - revision = currentRecording.lastRevision; + widget.replayRevisionSlider->setValue(revision); } } - if (revision >= 0) - { - widget.replayRevisionSlider->setValue(revision); - } + + lastReplayRealTime = IceUtil::Time::now().toMicroSeconds(); } void ArVizWidgetController::changeMode(ArVizWidgetMode newMode) @@ -917,10 +921,16 @@ namespace armarx auto& entry = recordingBatchCache[batch.header.index]; entry.data = batch; entry.lastUsed = IceUtil::Time::now(); + + limitRecordingBatchCacheSize(); + + recordingWaitingForBatchIndex = -1; } viz::data::RecordingBatch const& ArVizWidgetController::getRecordingBatch(long index) { + ARMARX_TRACE; + IceUtil::Time now = IceUtil::Time::now(); std::unique_lock<std::mutex> lock(recordingBatchCacheMutex); @@ -930,16 +940,23 @@ namespace armarx { // Start prefetching neighbouring batches bool asyncPrefetchIsRunning = callbackResult && !callbackResult->isCompleted(); - if (!asyncPrefetchIsRunning) + if (!asyncPrefetchIsRunning && recordingWaitingForBatchIndex == -1) { if (index + 1 < long(currentRecording.batchHeaders.size()) && recordingBatchCache.count(index + 1) == 0) { + // ARMARX_WARNING << "after begin_getRecordingBatch: " << (index + 1) + // << " waiting for " << recordingWaitingForBatchIndex; callbackResult = storage->begin_getRecordingBatch(currentRecording.id, index + 1, callback); + recordingWaitingForBatchIndex = index + 1; + ARMARX_INFO << "Now waiting for " << recordingWaitingForBatchIndex; } else if (index > 0 && recordingBatchCache.count(index - 1) == 0) { + // ARMARX_WARNING << "before begin_getRecordingBatch: " << (index - 1) + // << " waiting for " << recordingWaitingForBatchIndex; callbackResult = storage->begin_getRecordingBatch(currentRecording.id, index - 1, callback); + recordingWaitingForBatchIndex = index - 1; } } @@ -949,6 +966,19 @@ namespace armarx return entry.data; } + // Maybe there has already been sent a asynchronous request to get + if (index == recordingWaitingForBatchIndex) + { + lock.unlock(); + ARMARX_INFO << "Waiting to receive async batch: " << index; + // Wait until request completes + while (recordingWaitingForBatchIndex != -1) + { + QCoreApplication::processEvents(); + } + return getRecordingBatch(index); + } + ARMARX_INFO << "Batch #" << index << " is not in the cache. Getting synchronously, blocking GUI..."; // Entry is not in the cache, we have to get it from ArVizStorage @@ -956,6 +986,13 @@ namespace armarx newEntry.lastUsed = now; newEntry.data = storage->getRecordingBatch(currentRecording.id, index); + limitRecordingBatchCacheSize(); + + return newEntry.data; + } + + void ArVizWidgetController::limitRecordingBatchCacheSize() + { if (recordingBatchCache.size() > recordingBatchCacheMaxSize) { // Remove the entry with the oldest last used timestamp @@ -972,8 +1009,6 @@ namespace armarx recordingBatchCache.erase(oldestIter); } - - return newEntry.data; } SoNode* ArVizWidgetController::getScene() diff --git a/source/RobotAPI/gui-plugins/ArViz/ArVizWidgetController.h b/source/RobotAPI/gui-plugins/ArViz/ArVizWidgetController.h index 31383a63e..4a493dbd1 100644 --- a/source/RobotAPI/gui-plugins/ArViz/ArVizWidgetController.h +++ b/source/RobotAPI/gui-plugins/ArViz/ArVizWidgetController.h @@ -182,6 +182,7 @@ namespace armarx QTimer* replayTimer; long replayCurrentTimestamp = 0; + long lastReplayRealTime = 0; std::string storageName; armarx::viz::StorageInterfacePrx storage; @@ -207,9 +208,11 @@ namespace armarx }; viz::data::RecordingBatch const& getRecordingBatch(long index); + void limitRecordingBatchCacheSize(); std::size_t recordingBatchCacheMaxSize = 5; std::mutex recordingBatchCacheMutex; + std::atomic<long> recordingWaitingForBatchIndex = -1; std::map<long, TimestampedRecordingBatch> recordingBatchCache; ArVizWidgetMode mode = ArVizWidgetMode::NotConnected; -- GitLab