diff --git a/.gitlab/CODEOWNERS b/.gitlab/CODEOWNERS index 88113c1408093d1bd0bd42f4d703bfb7f67ae663..a50d21fe1c21109729acf45e579328b68e740f75 100644 --- a/.gitlab/CODEOWNERS +++ b/.gitlab/CODEOWNERS @@ -1,9 +1,10 @@ # ArMem -/source/RobotAPI/components/armem/ @RainerKartmann @dreher +/source/RobotAPI/components/armem/ @fratty @RainerKartmann @dreher -/source/RobotAPI/libraries/armem/ @RainerKartmann @dreher +/source/RobotAPI/libraries/armem/ @fratty @RainerKartmann @dreher /source/RobotAPI/libraries/armem_robot_localization/ @FabianReister /source/RobotAPI/libraries/armem_robot_mapping/ @FabianReister -/source/RobotAPI/interface/armem.ice @RainerKartmann @dreher +/source/RobotAPI/interface/armem/ @fratty @RainerKartmann @dreher +/source/RobotAPI/interface/armem.ice @fratty @RainerKartmann @dreher diff --git a/source/RobotAPI/components/ArViz/CMakeLists.txt b/source/RobotAPI/components/ArViz/CMakeLists.txt index 5a21a1cd4e02935799bdd4788aa7e2cac5ca12c8..d79d9a4ba4e3ee75d0860328997112e864c008d3 100644 --- a/source/RobotAPI/components/ArViz/CMakeLists.txt +++ b/source/RobotAPI/components/ArViz/CMakeLists.txt @@ -15,6 +15,7 @@ set(SOURCES Client/elements/Mesh.cpp Client/elements/Robot.cpp Client/elements/RobotHand.cpp + Client/drawer/ArVizDrawerBase.cpp Coin/ElementVisualizer.cpp @@ -75,6 +76,8 @@ set(HEADERS Client/elements/Robot.h Client/elements/RobotHand.h + Client/drawer/ArVizDrawerBase.h + Client/elements/point_cloud_type_traits.hpp Introspection/ElementJsonSerializers.h diff --git a/source/RobotAPI/components/ArViz/Client/drawer/ArVizDrawerBase.cpp b/source/RobotAPI/components/ArViz/Client/drawer/ArVizDrawerBase.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a19032cd088ccdf49e16af5ea394d73a92b30878 --- /dev/null +++ b/source/RobotAPI/components/ArViz/Client/drawer/ArVizDrawerBase.cpp @@ -0,0 +1,29 @@ +#include "ArVizDrawerBase.h" + +#include "RobotAPI/components/ArViz/Client/Client.h" +#include "RobotAPI/components/ArViz/Client/Layer.h" + +namespace armarx +{ + + ArVizDrawerBase::ArVizDrawerBase(armarx::viz::Client &arviz) : arvizClient(arviz) {} + + ArVizDrawerBase::~ArVizDrawerBase() = default; + + viz::Client &ArVizDrawerBase::arviz() { return arvizClient; } + + const viz::Client &ArVizDrawerBase::arviz() const { return arvizClient; } + + void ArVizDrawerBase::commit(const viz::Layer &layer) + { + std::lock_guard guard{layerMtx}; + arvizClient.commit(layer); + } + + void ArVizDrawerBase::commit(const std::vector<viz::Layer> &layers) + { + std::lock_guard guard{layerMtx}; + arvizClient.commit(layers); + } + +} // namespace armarx diff --git a/source/RobotAPI/components/ArViz/Client/drawer/ArVizDrawerBase.h b/source/RobotAPI/components/ArViz/Client/drawer/ArVizDrawerBase.h new file mode 100644 index 0000000000000000000000000000000000000000..f7c813be72283ec4899f402a1133c41ab5a381e2 --- /dev/null +++ b/source/RobotAPI/components/ArViz/Client/drawer/ArVizDrawerBase.h @@ -0,0 +1,62 @@ +/* + * This file is part of ArmarX. + * + * ArmarX is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * ArmarX is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + * @author Fabian Reister ( fabian dot reister at kit dot edu ) + * @date 2021 + * @copyright http://www.gnu.org/licenses/gpl-2.0.txt + * GNU General Public License + */ + +#pragma once + +#include <mutex> +#include <vector> + +namespace armarx +{ + // forward declaration + namespace viz + { + class Client; + struct Layer; + } // namespace viz + + /** + * @brief The ArVizDrawerBase class. Use this class to draw arbitrary objects. + * + * Instead of implementing arviz drawing in the component itself, this class helps to + * decouple drawing from "component / processing logic". + * + */ + class ArVizDrawerBase + { + public: + ArVizDrawerBase(armarx::viz::Client &arviz); + virtual ~ArVizDrawerBase(); + + protected: + viz::Client &arviz(); + const viz::Client &arviz() const; + + void commit(const viz::Layer &layer); + void commit(const std::vector<viz::Layer> &layers); + + private: + viz::Client &arvizClient; + + std::mutex layerMtx; + }; + +} // namespace armarx diff --git a/source/RobotAPI/components/ArViz/Coin/Visualizer.cpp b/source/RobotAPI/components/ArViz/Coin/Visualizer.cpp index 89c8340b7fd524b9d3df06bb4332e7e591701011..96ad7fed33e9be2813679f6ab20405f85300fc57 100644 --- a/source/RobotAPI/components/ArViz/Coin/Visualizer.cpp +++ b/source/RobotAPI/components/ArViz/Coin/Visualizer.cpp @@ -144,24 +144,25 @@ namespace armarx::viz CoinVisualizer_ApplyTiming timing; timing.layerName = update.name; - auto layerID = std::make_pair(update.component, update.name); - auto layerIt = layers.find(layerID); + CoinLayerID layerID(update.component, update.name); + auto layerIt = layers.lowerBound(layerID); - if (layerIt == layers.end()) + if (layerIt == layers.data.end() || layerIt->id != layerID) { // Create a new layer SoSeparator* coinNode = new SoSeparator; coinNode->ref(); root->addChild(coinNode); - layerIt = layers.emplace(layerID, CoinLayer(coinNode)).first; + layerIt = layers.data.insert(layerIt, CoinLayer(layerID, coinNode)); } IceUtil::Time time_addLayer = IceUtil::Time::now(); timing.addLayer = time_addLayer - time_start; // Add or update the elements in the update - CoinLayer& layer = layerIt->second; + CoinLayer& layer = *layerIt; + layer.elements.reserve(update.elements.size()); for (auto& updatedElementPtr : update.elements) { if (!updatedElementPtr) @@ -191,24 +192,27 @@ namespace armarx::viz } coin::ElementVisualizer* visualizer = elementVisualizers[visuIndex].get(); - auto oldElementIter = layer.elements.find(updatedElement.id); - if (oldElementIter != layer.elements.end()) + auto oldElementIter = layer.lowerBound(updatedElement.id); + CoinLayerElement* oldElement = nullptr; + if (oldElementIter != layer.elements.end() && oldElementIter->data->id == updatedElement.id) { // Element already exists - coin::ElementVisualization& oldElement = *oldElementIter->second.visu; - oldElement.wasUpdated = true; + CoinLayerElement* oldElement = &*oldElementIter; + coin::ElementVisualization& oldElementVisu = *oldElement->visu; - bool updated = visualizer->update(updatedElement, &oldElement); + oldElementVisu.wasUpdated = true; + + bool updated = visualizer->update(updatedElement, &oldElementVisu); if (updated) { - layer.elements[updatedElement.id].data = updatedElementPtr; + oldElement->data = updatedElementPtr; continue; } else { // Types are different, so we delete the old element and create a new one - layer.node->removeChild(oldElement.separator); + layer.node->removeChild(oldElementVisu.separator); } } @@ -216,7 +220,16 @@ namespace armarx::viz if (elementVisu->separator) { layer.node->addChild(elementVisu->separator); - layer.elements[updatedElement.id] = CoinLayerElement{updatedElementPtr, std::move(elementVisu)}; + if (oldElement) + { + oldElement->data = updatedElementPtr; + oldElement->visu = std::move(elementVisu); + } + else + { + // Need to add a new element + layer.elements.insert(oldElementIter, CoinLayerElement{updatedElementPtr, std::move(elementVisu)}); + } } else { @@ -233,7 +246,7 @@ namespace armarx::viz // Remove the elements which were not contained in the update for (auto iter = layer.elements.begin(); iter != layer.elements.end();) { - auto& elementVisu = *iter->second.visu; + coin::ElementVisualization& elementVisu = *iter->visu; if (elementVisu.wasUpdated) { elementVisu.wasUpdated = false; @@ -266,7 +279,7 @@ namespace armarx::viz std::unique_lock<std::mutex> lock(stateMutex); storage = stateStorage; root->removeAllChildren(); - layers.clear(); + layers.data.clear(); pulledUpdates.revision = 0; pulledUpdates.updates.clear(); updateResult = CoinVisualizerUpdateResult::SUCCESS; @@ -364,20 +377,19 @@ namespace armarx::viz void CoinVisualizer::showLayer(CoinLayerID const& id, bool visible) { - auto iter = layers.find(id); - if (iter == layers.end()) + CoinLayer* layer = layers.findLayer(id); + if (layer == nullptr) { return; } - viz::CoinLayer& layer = iter->second; - int childIndex = root->findChild(layer.node); + int childIndex = root->findChild(layer->node); if (childIndex < 0) { // Layer is currently not visible if (visible) { - root->addChild(layer.node); + root->addChild(layer->node); } } else @@ -399,10 +411,10 @@ namespace armarx::viz std::vector<CoinLayerID> CoinVisualizer::getLayerIDs() { std::vector<CoinLayerID> result; - result.reserve(layers.size()); - for (auto& entry : layers) + result.reserve(layers.data.size()); + for (CoinLayer& layer : layers.data) { - result.push_back(entry.first); + result.push_back(layer.id); } return result; } diff --git a/source/RobotAPI/components/ArViz/Coin/Visualizer.h b/source/RobotAPI/components/ArViz/Coin/Visualizer.h index 01d7072ca3a59dc6b69fb6b5c0adf3e6f25b4ead..5cb71b0fecc568e06b42ae49d8f8e9525104feea 100644 --- a/source/RobotAPI/components/ArViz/Coin/Visualizer.h +++ b/source/RobotAPI/components/ArViz/Coin/Visualizer.h @@ -5,14 +5,13 @@ #include <RobotAPI/interface/ArViz/Component.h> #include <Inventor/nodes/SoSeparator.h> +#include <IceUtil/Shared.h> -#include <map> -#include <unordered_map> +#include <functional> +#include <typeindex> #include <memory> +#include <string> #include <mutex> -#include <typeindex> - -#include <IceUtil/Shared.h> namespace armarx::viz { @@ -25,19 +24,31 @@ namespace armarx::viz std::unique_ptr<coin::ElementVisualization> visu; }; + inline bool isElementIdLess(CoinLayerElement const& left, CoinLayerElement const& right) + { + return left.data->id < right.data->id; + } + struct CoinLayer { - CoinLayer(SoSeparator* node) - : node(node) + CoinLayer() = default; + + CoinLayer(CoinLayerID const& id, SoSeparator* node) + : id(id) + , node(node) { // Increase ref-count, so we can add/remove this node without it being deleted // This is needed for showing/hiding layers node->ref(); + pivot.data = new data::Element; } CoinLayer(CoinLayer&& other) - : node(other.node), elements(std::move(other.elements)) + : id(std::move(other.id)) + , node(other.node) + , elements(std::move(other.elements)) + , pivot(std::move(other.pivot)) { other.node = nullptr; } @@ -55,13 +66,69 @@ namespace armarx::viz void operator= (CoinLayer&& other) { + id = std::move(other.id); node = other.node; other.node = nullptr; elements = std::move(other.elements); } + auto lowerBound(std::string const& id) + { + pivot.data->id = id; + return std::lower_bound(elements.begin(), elements.end(), pivot, &isElementIdLess); + } + + CoinLayerElement* findElement(std::string const& id) + { + auto iter = lowerBound(id); + if (iter != elements.end() && iter->data->id == id) + { + return &*iter; + } + return nullptr; + } + + CoinLayerElement const* findElement(std::string const& id) const + { + return const_cast<CoinLayer*>(this)->findElement(id); + } + + CoinLayerID id; SoSeparator* node = nullptr; - std::map<std::string, CoinLayerElement> elements; + std::vector<CoinLayerElement> elements; + CoinLayerElement pivot; + }; + + inline bool isCoinLayerIdLess(CoinLayer const& left, CoinLayer const& right) + { + return left.id < right.id; + } + + struct CoinLayerMap + { + auto lowerBound(CoinLayerID const& id) + { + pivot.id = id; + return std::lower_bound(data.begin(), data.end(), pivot, &isCoinLayerIdLess); + } + + CoinLayer* findLayer(CoinLayerID const& id) + { + auto iter = lowerBound(id); + if (iter != data.end() && iter->id == id) + { + return &*iter; + } + return nullptr; + } + + CoinLayer const* findLayer(CoinLayerID const& id) const + { + return const_cast<CoinLayerMap*>(this)->findLayer(id); + } + + std::vector<CoinLayer> data; + CoinLayer pivot; }; enum class CoinVisualizerState @@ -158,7 +225,7 @@ namespace armarx::viz viz::StorageInterfacePrx storage; SoTimerSensor* timerSensor = nullptr; - std::map<CoinLayerID, CoinLayer> layers; + CoinLayerMap layers; std::vector<std::type_index> elementVisualizersTypes; std::vector<std::unique_ptr<coin::ElementVisualizer>> elementVisualizers; diff --git a/source/RobotAPI/components/armem/client/ExampleMemoryClient/ExampleMemoryClient.cpp b/source/RobotAPI/components/armem/client/ExampleMemoryClient/ExampleMemoryClient.cpp index 5ed005e7a82c5c5eb24b056d0f5d71e10ebcf380..c1ebb7ba455032cf3d48fa32b40081a6a2fcdb3d 100644 --- a/source/RobotAPI/components/armem/client/ExampleMemoryClient/ExampleMemoryClient.cpp +++ b/source/RobotAPI/components/armem/client/ExampleMemoryClient/ExampleMemoryClient.cpp @@ -22,6 +22,8 @@ #include "ExampleMemoryClient.h" +#include <random> + #include <SimoxUtility/color/cmaps.h> #include <ArmarXCore/core/exceptions/local/ExpressionException.h> @@ -112,6 +114,8 @@ namespace armarx void ExampleMemoryClient::run() { ARMARX_IMPORTANT << "Running example."; + run_started = IceUtil::Time::now(); + std::srand(std::time(nullptr)); armem::MemoryID snapshotID = commitSingleSnapshot(entityID); if (true) @@ -132,11 +136,15 @@ namespace armarx queryExampleData(); } - CycleUtil c(1000); + CycleUtil c(100); int i = 0; - while (!task->isStopped() && i++ < 100) + while (!task->isStopped()) { - commitSingleSnapshot(entityID); + commitExampleData(); + if (i++ < 10000) + { + commitSingleSnapshot(entityID); + } c.waitForCycleDuration(); } } @@ -161,10 +169,30 @@ namespace armarx armem::EntityUpdate update; update.entityID = entityID; update.timeCreated = armem::Time::now(); + + double diff = (update.timeCreated - run_started).toMilliSecondsDouble() / 1000; + + auto dict1 = std::make_shared<aron::datanavigator::DictNavigator>(); + auto dict2 = std::make_shared<aron::datanavigator::DictNavigator>(); + + auto sin = std::make_shared<aron::datanavigator::FloatNavigator>(std::sin(diff)); + auto cos = std::make_shared<aron::datanavigator::FloatNavigator>(std::cos(diff)); + + auto sqrt = std::make_shared<aron::datanavigator::DoubleNavigator>(std::sqrt(diff)); + auto lin = std::make_shared<aron::datanavigator::LongNavigator>((long)(diff * 1000)); + auto rand = std::make_shared<aron::datanavigator::IntNavigator>(std::rand()); + + dict1->addElement("sin", sin); + dict1->addElement("cos", cos); + + dict2->addElement("sqrt", sqrt); + dict2->addElement("lin", lin); + dict2->addElement("rand", rand); + update.instancesData = { - std::make_shared<aron::datanavigator::DictNavigator>(), - std::make_shared<aron::datanavigator::DictNavigator>() + dict1, + dict2 }; ARMARX_IMPORTANT << "Committing " << update; @@ -311,6 +339,7 @@ namespace armarx armem::Time time = armem::Time::now(); armem::Commit commit; + //default { armem::EntityUpdate& update = commit.updates.emplace_back(); update.entityID = providerID.withEntityName("default"); @@ -319,6 +348,7 @@ namespace armarx armem::example::ExampleData primitive; update.instancesData = { primitive.toAron() }; } + //the answer { armem::EntityUpdate& update = commit.updates.emplace_back(); update.entityID = providerID.withEntityName("the answer"); @@ -326,7 +356,7 @@ namespace armarx armem::example::ExampleData data; data.the_bool = true; - data.the_double = 2 * 42.42; + data.the_double = std::sin(time.toSecondsDouble()); data.the_float = 21.5; data.the_int = 42; data.the_long = 424242; diff --git a/source/RobotAPI/components/armem/client/ExampleMemoryClient/ExampleMemoryClient.h b/source/RobotAPI/components/armem/client/ExampleMemoryClient/ExampleMemoryClient.h index e2e975c4a5450fa614cf0020b1e21a09fabbdb4f..774a4cbb84bc06496471e214d1cdb7935af1418f 100644 --- a/source/RobotAPI/components/armem/client/ExampleMemoryClient/ExampleMemoryClient.h +++ b/source/RobotAPI/components/armem/client/ExampleMemoryClient/ExampleMemoryClient.h @@ -114,6 +114,8 @@ namespace armarx private: + IceUtil::Time run_started; + armarx::RunningTask<ExampleMemoryClient>::pointer_type task; armarx::DebugObserverInterfacePrx debugObserver; diff --git a/source/RobotAPI/gui-plugins/ArViz/ArVizWidgetController.cpp b/source/RobotAPI/gui-plugins/ArViz/ArVizWidgetController.cpp index cf42b9ff2bb4d42f04a6067f08803ea6ac69f873..44d9c0aa5a71bee4a4095077a3aca2525cb0437a 100644 --- a/source/RobotAPI/gui-plugins/ArViz/ArVizWidgetController.cpp +++ b/source/RobotAPI/gui-plugins/ArViz/ArVizWidgetController.cpp @@ -171,7 +171,7 @@ namespace armarx emit connectGui(); } - void armarx::ArVizWidgetController::onDisconnectComponent() + void ArVizWidgetController::onDisconnectComponent() { visualizer.stop(); @@ -336,17 +336,18 @@ namespace armarx } // A layer was selected. - const viz::CoinLayerID id = std::make_pair(current->parent()->text(0).toStdString(), current->text(0).toStdString()); + viz::CoinLayerID id(current->parent()->text(0).toStdString(), current->text(0).toStdString()); - try + viz::CoinLayer* layer = visualizer.layers.findLayer(id); + if (layer == nullptr) { - viz::CoinLayer& layer = visualizer.layers.at(id); - layerInfoTree.setSelectedLayer(id, &layer); + ARMARX_WARNING << "Could not find layer (" << id.first << " / " << id.second << ") in Visualizer."; } - catch (const std::out_of_range&) + else { - ARMARX_WARNING << "Could not find layer (" << id.first << " / " << id.second << ") in Visualizer."; + layerInfoTree.setSelectedLayer(id, &visualizer.layers); } + #endif } @@ -446,10 +447,22 @@ namespace armarx { if (debugObserver) { - timingMap["0.pull"] = new Variant(timing.pull.toMilliSecondsDouble()); - timingMap["1.apply"] = new Variant(timing.applyTotal.total.toMilliSecondsDouble()); - timingMap["2.layers"] = new Variant(timing.layersChanged.toMilliSecondsDouble()); - timingMap["total"] = new Variant(timing.total.toMilliSecondsDouble()); + timingMap["0. pull (ms)"] = new Variant(timing.pull.toMilliSecondsDouble()); + timingMap["1. apply (ms)"] = new Variant(timing.applyTotal.total.toMilliSecondsDouble()); + timingMap["1.1 apply, addLayer (ms)"] = new Variant(timing.applyTotal.addLayer.toMilliSecondsDouble()); + timingMap["1.2 apply, updateElements (ms)"] = new Variant(timing.applyTotal.updateElements.toMilliSecondsDouble()); + timingMap["1.3 apply, removeElements (ms)"] = new Variant(timing.applyTotal.removeElements.toMilliSecondsDouble()); + timingMap["2. layers (ms)"] = new Variant(timing.layersChanged.toMilliSecondsDouble()); + timingMap["total (ms)"] = new Variant(timing.total.toMilliSecondsDouble()); + + timings.push_back(timing.total.toMilliSecondsDouble()); + int numTimings = 20; + if ((int)timings.size() > numTimings) + { + timings.erase(timings.begin()); + } + double averageTime = std::accumulate(timings.begin(), timings.end(), 0.0) / numTimings; + timingMap["total avg (ms)"] = new Variant(averageTime); debugObserver->begin_setDebugChannel("ArViz_Timing", timingMap); } @@ -920,7 +933,7 @@ namespace armarx } - auto& entry = iter->second; + TimestampedRecordingBatch& entry = iter->second; entry.lastUsed = now; return entry.data; } @@ -939,7 +952,7 @@ namespace armarx for (auto iter = recordingBatchCache.begin(); iter != recordingBatchCache.end(); ++iter) { - auto& entry = iter->second; + TimestampedRecordingBatch& entry = iter->second; if (entry.lastUsed < oldestIter->second.lastUsed) { oldestIter = iter; @@ -957,8 +970,8 @@ namespace armarx return visualizer.root; } - const static std::string CONFIG_KEY_STORAGE = "Storage"; - const static std::string CONFIG_KEY_DEBUG_OBSERVER = "DebugObserver"; + static const std::string CONFIG_KEY_STORAGE = "Storage"; + static const std::string CONFIG_KEY_DEBUG_OBSERVER = "DebugObserver"; void ArVizWidgetController::loadSettings(QSettings* settings) { @@ -976,7 +989,7 @@ namespace armarx QString::fromStdString(debugObserverName)); } - QPointer<QDialog> armarx::ArVizWidgetController::getConfigDialog(QWidget* parent) + QPointer<QDialog> ArVizWidgetController::getConfigDialog(QWidget* parent) { if (!configDialog) { @@ -987,7 +1000,7 @@ namespace armarx return qobject_cast<QDialog*>(configDialog); } - void armarx::ArVizWidgetController::configured() + void ArVizWidgetController::configured() { if (configDialog) { diff --git a/source/RobotAPI/gui-plugins/ArViz/ArVizWidgetController.h b/source/RobotAPI/gui-plugins/ArViz/ArVizWidgetController.h index e59b685797f5e8ee4b56220c9c5070109e50a140..7a3a0bfa34330ecf32509b24d2e1d420e4016d0f 100644 --- a/source/RobotAPI/gui-plugins/ArViz/ArVizWidgetController.h +++ b/source/RobotAPI/gui-plugins/ArViz/ArVizWidgetController.h @@ -215,6 +215,9 @@ namespace armarx IceUtil::Handle<ArVizWidgetBatchCallback> callbackData; armarx::viz::Callback_StorageInterface_getRecordingBatchPtr callback; Ice::AsyncResultPtr callbackResult; + + std::vector<double> timings; + public: static QIcon GetWidgetIcon() { diff --git a/source/RobotAPI/gui-plugins/ArViz/LayerInfoTree.cpp b/source/RobotAPI/gui-plugins/ArViz/LayerInfoTree.cpp index 9d78b9888742040908574c587a8061bc50c2b61a..2d20d7974a53aae2ebfa73d053b9d7a1a86b4439 100644 --- a/source/RobotAPI/gui-plugins/ArViz/LayerInfoTree.cpp +++ b/source/RobotAPI/gui-plugins/ArViz/LayerInfoTree.cpp @@ -40,9 +40,20 @@ namespace armarx // Update layer element properties when expanded. widgetConnections.append(connect(widget, &QTreeWidget::itemExpanded, [this](QTreeWidgetItem * item) { - if (!item->parent()) + if (item->parent() || this->layers == nullptr) { - this->updateLayerElementProperties(item, this->layer->elements.at(item->text(0).toStdString()).data); + return; + } + + std::string id = item->text(0).toStdString(); + auto* layer = this->layers->findLayer(this->layerID); + if (layer != nullptr) + { + viz::CoinLayerElement const* element = layer->findElement(id); + if (element != nullptr) + { + this->updateLayerElementProperties(item, element->data); + } } })); @@ -58,10 +69,6 @@ namespace armarx { if (layerID == this->layerID) { - // If the layer object identified by layerID changed, we should use the new one. - // This can happen when the gui plugin reconnects. - this->layer = &layer; - this->update(); } }); @@ -88,29 +95,29 @@ namespace armarx } } - void LayerInfoTree::setSelectedLayer(viz::CoinLayerID id, viz::CoinLayer* layer) + void LayerInfoTree::setSelectedLayer(viz::CoinLayerID id, viz::CoinLayerMap* layers) { this->layerID = id; - this->layer = layer; + this->layers = layers; showMoreItem = nullptr; maxElementCount = maxElementCountDefault; widget->clear(); - if (!layer) - { - return; - } update(); } void LayerInfoTree::update() { - if (enabled && layer) + if (enabled && layers) { - updateLayerElements(layer->elements); + auto* layer = layers->findLayer(layerID); + if (layer != nullptr) + { + updateLayerElements(layer->elements); + } } } @@ -125,7 +132,7 @@ namespace armarx } - void LayerInfoTree::updateLayerElements(const std::map<std::string, viz::CoinLayerElement>& elements) + void LayerInfoTree::updateLayerElements(const std::vector<viz::CoinLayerElement>& elements) { if (showMoreItem) { @@ -139,9 +146,9 @@ namespace armarx ARMARX_CHECK_IS_NULL(showMoreItem); int currentIndex = 0; - for (auto it = elements.begin(); it != elements.end(); ++it) + for (viz::CoinLayerElement const& element : elements) { - const auto& [name, element] = *it; + std::string const& name = element.data->id; if (maxElementCount >= 0 && currentIndex >= maxElementCount) { @@ -546,6 +553,14 @@ namespace armarx { ARMARX_CHECK_NULL(showMoreItem) << "There should not be a showMoreItem when this function is called."; + auto* layer = this->layers->findLayer(this->layerID); + if (layer == nullptr) + { + ARMARX_WARNING << "No layer with ID '" << this->layerID.first + << "/" << this->layerID.second << "' found"; + return; + } + std::stringstream ss; ss << "Showing " << widget->topLevelItemCount() << " of " << layer->elements.size() << " elements."; @@ -556,7 +571,7 @@ namespace armarx QPushButton* button = new QPushButton("Show more"); widget->setItemWidget(item, 0, button); - connect(button, &QPushButton::pressed, [this]() + connect(button, &QPushButton::pressed, [this, layer]() { maxElementCount += maxElementCountDefault; this->updateLayerElements(layer->elements); diff --git a/source/RobotAPI/gui-plugins/ArViz/LayerInfoTree.h b/source/RobotAPI/gui-plugins/ArViz/LayerInfoTree.h index a5289ac8b10aa7a7d184c3e4922c26fed5dabcc4..bccbff58de0ad18bfbd289f0d08ac21d69419bfb 100644 --- a/source/RobotAPI/gui-plugins/ArViz/LayerInfoTree.h +++ b/source/RobotAPI/gui-plugins/ArViz/LayerInfoTree.h @@ -35,7 +35,7 @@ namespace armarx void setEnabled(bool enabled); /// Set the selected layer. - void setSelectedLayer(viz::CoinLayerID id, viz::CoinLayer* layer); + void setSelectedLayer(viz::CoinLayerID id, viz::CoinLayerMap* layers); /// Update the currently expanded layer elements. void update(); @@ -57,7 +57,7 @@ namespace armarx * * Items are inserted, removed and updated accordingly. */ - void updateLayerElements(const std::map<std::string, viz::CoinLayerElement>& elements); + void updateLayerElements(const std::vector<viz::CoinLayerElement>& elements); /// Insert a (top-level) layer element at `ìndex`. QTreeWidgetItem* insertLayerElementItem(int index, const std::string& name, const viz::data::ElementPtr& element); @@ -122,7 +122,7 @@ namespace armarx int maxElementCount = maxElementCountDefault; viz::CoinLayerID layerID = {"", ""}; - const viz::CoinLayer* layer = nullptr; + const viz::CoinLayerMap* layers = nullptr; diff --git a/source/RobotAPI/interface/units/RobotUnit/NJointTaskSpaceDMPController.ice b/source/RobotAPI/interface/units/RobotUnit/NJointTaskSpaceDMPController.ice index 2f039d60c1343421a5a22bc576eec0ea7b3fc456..38cdb96be1a6e47b98e7adc0c939cc816cfd55c6 100644 --- a/source/RobotAPI/interface/units/RobotUnit/NJointTaskSpaceDMPController.ice +++ b/source/RobotAPI/interface/units/RobotUnit/NJointTaskSpaceDMPController.ice @@ -340,6 +340,7 @@ module armarx void resetDMP(); void stopDMP(); void resumeDMP(); + void removeAllViaPoints(); void setMPWeights(DoubleSeqSeq weights); DoubleSeqSeq getMPWeights(); diff --git a/source/RobotAPI/libraries/RobotAPINJointControllers/DMPController/NJointTaskSpaceImpedanceDMPController.cpp b/source/RobotAPI/libraries/RobotAPINJointControllers/DMPController/NJointTaskSpaceImpedanceDMPController.cpp index 0ed7f2136377c71399c71fec0310fbec12baba85..70fae3d0b1c6576d26d71ee652cd79ef4ae3c75d 100644 --- a/source/RobotAPI/libraries/RobotAPINJointControllers/DMPController/NJointTaskSpaceImpedanceDMPController.cpp +++ b/source/RobotAPI/libraries/RobotAPINJointControllers/DMPController/NJointTaskSpaceImpedanceDMPController.cpp @@ -575,6 +575,12 @@ namespace armarx return resvec; } + void NJointTaskSpaceImpedanceDMPController::removeAllViaPoints(const Ice::Current&) + { + LockGuardType guard {controllerMutex}; + ARMARX_INFO << "setting via points "; + dmpCtrl->removeAllViaPoints(); + } } diff --git a/source/RobotAPI/libraries/RobotAPINJointControllers/DMPController/NJointTaskSpaceImpedanceDMPController.h b/source/RobotAPI/libraries/RobotAPINJointControllers/DMPController/NJointTaskSpaceImpedanceDMPController.h index 412a46f20b5ce93eddfed0d68854d4a3c03bc30a..34bd9785cbac94d173e45c6e345cf1531e0a158c 100644 --- a/source/RobotAPI/libraries/RobotAPINJointControllers/DMPController/NJointTaskSpaceImpedanceDMPController.h +++ b/source/RobotAPI/libraries/RobotAPINJointControllers/DMPController/NJointTaskSpaceImpedanceDMPController.h @@ -74,6 +74,8 @@ namespace armarx void setMPWeights(const DoubleSeqSeq& weights, const Ice::Current&); DoubleSeqSeq getMPWeights(const Ice::Current&); + void removeAllViaPoints(const Ice::Current&) override; + protected: virtual void onPublish(const SensorAndControl&, const DebugDrawerInterfacePrx&, const DebugObserverInterfacePrx&);