diff --git a/source/RobotAPI/components/ArViz/Client/elements/RobotHand.cpp b/source/RobotAPI/components/ArViz/Client/elements/RobotHand.cpp index ea0966ff156625fedc0c1287771a32e29b2cb9e9..b4926f0d369e93bd64897a1b8a33313986a1699d 100644 --- a/source/RobotAPI/components/ArViz/Client/elements/RobotHand.cpp +++ b/source/RobotAPI/components/ArViz/Client/elements/RobotHand.cpp @@ -9,8 +9,8 @@ namespace armarx::viz RobotHand& RobotHand::fileBySide(const std::string& side, RobotInfoNodePtr robotInfo) { ARMARX_CHECK_NOT_NULL(robotInfo); - RobotNameHelper nh(robotInfo, nullptr); - return this->fileBySide(side, nh); + RobotNameHelperPtr nh = RobotNameHelper::Create(robotInfo, nullptr); + return this->fileBySide(side, *nh); } RobotHand& RobotHand::fileBySide(const std::string& side, const RobotNameHelper& nameHelper) diff --git a/source/RobotAPI/components/ArViz/Coin/VisualizationRobot.cpp b/source/RobotAPI/components/ArViz/Coin/VisualizationRobot.cpp index bf0ae91ddc2dd48cd7368254c58cb80258d04d3f..e02312f388610108db2caccf4d81e31a80000a06 100644 --- a/source/RobotAPI/components/ArViz/Coin/VisualizationRobot.cpp +++ b/source/RobotAPI/components/ArViz/Coin/VisualizationRobot.cpp @@ -90,6 +90,7 @@ namespace armarx::viz::coin bool VisualizationRobot::update(ElementType const& element) { IceUtil::Time time_start = IceUtil::Time::now(); + (void) time_start; bool robotChanged = loaded.project != element.project || loaded.filename != element.filename; if (robotChanged) diff --git a/source/RobotAPI/gui-plugins/ArViz/ArVizWidget.ui b/source/RobotAPI/gui-plugins/ArViz/ArVizWidget.ui index 00e1d435e4567cca000291e074d2f566d397d144..b5dc5e5dd125a004758a383ad4c431517bd3f1d2 100644 --- a/source/RobotAPI/gui-plugins/ArViz/ArVizWidget.ui +++ b/source/RobotAPI/gui-plugins/ArViz/ArVizWidget.ui @@ -102,10 +102,16 @@ </layout> </item> <item> - <widget class="QGroupBox" name="groupBox"> + <widget class="QGroupBox" name="layerInfoTreeGroupBox"> <property name="title"> <string>Layer Information</string> </property> + <property name="checkable"> + <bool>true</bool> + </property> + <property name="checked"> + <bool>false</bool> + </property> <layout class="QVBoxLayout" name="verticalLayout_6"> <property name="leftMargin"> <number>3</number> diff --git a/source/RobotAPI/gui-plugins/ArViz/ArVizWidgetController.cpp b/source/RobotAPI/gui-plugins/ArViz/ArVizWidgetController.cpp index c893f73b6927c28cbb6db2641e890155989d6235..006be56ad97d2f3f9fa7b1947df08f002bb52d09 100644 --- a/source/RobotAPI/gui-plugins/ArViz/ArVizWidgetController.cpp +++ b/source/RobotAPI/gui-plugins/ArViz/ArVizWidgetController.cpp @@ -32,7 +32,7 @@ #include <ArmarXCore/observers/variant/Variant.h> -#define ENABLE_INTROSPECTION 0 +#define ENABLE_INTROSPECTION 1 namespace armarx @@ -93,13 +93,17 @@ namespace armarx // Layer info tree. connect(widget.layerTree, &QTreeWidget::currentItemChanged, this, &This::updateSelectedLayer); + #if ENABLE_INTROSPECTION + connect(widget.layerInfoTreeGroupBox, &QGroupBox::toggled, &layerInfoTree, &LayerInfoTree::setEnabled); connect(widget.defaultShowLimitSpinBox, qOverload<int>(&QSpinBox::valueChanged), &layerInfoTree, &LayerInfoTree::setMaxElementCountDefault); layerInfoTree.setMaxElementCountDefault(widget.defaultShowLimitSpinBox->value()); layerInfoTree.setWidget(widget.layerInfoTree); + layerInfoTree.setEnabled(widget.layerInfoTreeGroupBox->isChecked()); layerInfoTree.registerVisualizerCallbacks(visualizer); + #endif diff --git a/source/RobotAPI/gui-plugins/ArViz/LayerInfoTree.cpp b/source/RobotAPI/gui-plugins/ArViz/LayerInfoTree.cpp index aeecddbef7737399b08182c9e067f1ee8e01ebc8..3245ae66c52e75bc663f5dae8128a7d102a0c6af 100644 --- a/source/RobotAPI/gui-plugins/ArViz/LayerInfoTree.cpp +++ b/source/RobotAPI/gui-plugins/ArViz/LayerInfoTree.cpp @@ -72,6 +72,22 @@ namespace armarx this->maxElementCountDefault = max; } + void LayerInfoTree::setEnabled(bool value) + { + if (this->enabled != value) + { + this->enabled = value; + if (value) + { + update(); + } + else + { + clearLayerElements(); + } + } + } + void LayerInfoTree::setSelectedLayer(viz::CoinLayerID id, viz::CoinLayer* layer) { this->layerID = id; @@ -92,7 +108,20 @@ namespace armarx void LayerInfoTree::update() { - updateLayerElements(layer->elements); + if (enabled && layer) + { + updateLayerElements(layer->elements); + } + } + + + void LayerInfoTree::clearLayerElements() + { + if (widget) + { + widget->clear(); + showMoreItem = nullptr; + } } @@ -169,7 +198,8 @@ namespace armarx int index, const std::string& name, const viz::data::ElementPtr& element) { QTreeWidgetItem* item = new QTreeWidgetItem(QStringList { name.c_str(), getTypeName(element).c_str() }); - item->setCheckState(0, Qt::CheckState::Unchecked); + // To be used when we can hide specific elements. + // item->setCheckState(0, Qt::CheckState::Unchecked); widget->insertTopLevelItem(index, item); return item; } @@ -300,7 +330,8 @@ namespace armarx QTreeWidgetItem* LayerInfoTree::addJsonChild(QTreeWidgetItem* parent, const std::string& key) { QTreeWidgetItem* child = new QTreeWidgetItem(QStringList { key.c_str(), "" }); - child->setCheckState(0, Qt::CheckState::Unchecked); + // To be used when we can actually change the values (enabled = use value from GUI). + // child->setCheckState(0, Qt::CheckState::Unchecked); parent->addChild(child); return child; diff --git a/source/RobotAPI/gui-plugins/ArViz/LayerInfoTree.h b/source/RobotAPI/gui-plugins/ArViz/LayerInfoTree.h index eeb169e5c4cf59b12d9e5721cbd9237d28a49a5c..a5289ac8b10aa7a7d184c3e4922c26fed5dabcc4 100644 --- a/source/RobotAPI/gui-plugins/ArViz/LayerInfoTree.h +++ b/source/RobotAPI/gui-plugins/ArViz/LayerInfoTree.h @@ -26,6 +26,13 @@ namespace armarx void registerVisualizerCallbacks(viz::CoinVisualizer& visualizer); void setMaxElementCountDefault(int max); + /** + * @brief Enable or disable the layer info tree. + * + * When enabled, the tree will be filled on the first update. + * When disabled, the tree is cleared and will not be updated. + */ + void setEnabled(bool enabled); /// Set the selected layer. void setSelectedLayer(viz::CoinLayerID id, viz::CoinLayer* layer); @@ -43,6 +50,8 @@ namespace armarx private: + void clearLayerElements(); + /** * @brief Updates the list of layer elements. * @@ -102,10 +111,12 @@ namespace armarx private: - QTreeWidget* widget; + QTreeWidget* widget = nullptr; /// Connections to the current widget. QVector<QMetaObject::Connection> widgetConnections; + bool enabled = true; + QTreeWidgetItem* showMoreItem = nullptr; int maxElementCountDefault = 25; int maxElementCount = maxElementCountDefault; diff --git a/source/RobotAPI/libraries/ArmarXObjects/ObjectFinder.cpp b/source/RobotAPI/libraries/ArmarXObjects/ObjectFinder.cpp index a02b6bd1031836da23ce9617e7e5f55d7075d2d3..089bd030b541b0938f3d4f944fac4c3ce0b83440 100644 --- a/source/RobotAPI/libraries/ArmarXObjects/ObjectFinder.cpp +++ b/source/RobotAPI/libraries/ArmarXObjects/ObjectFinder.cpp @@ -25,7 +25,7 @@ namespace armarx if (packageDataDir.empty()) { ARMARX_WARNING << "Could not find package '" << packageName << "'."; - throw LocalException() << "Could not find package '" << packageName << "'."; + // throw LocalException() << "Could not find package '" << packageName << "'."; } else { @@ -38,6 +38,10 @@ namespace armarx std::optional<ObjectInfo> ObjectFinder::findObject(const std::string& dataset, const std::string& name) const { init(); + if (!_ready()) + { + return std::nullopt; + } if (!dataset.empty()) { return ObjectInfo(packageName, packageDataDir, dataset, name); @@ -88,6 +92,10 @@ namespace armarx std::vector<ObjectFinder::path> ObjectFinder::getDatasetDirectories() const { init(); + if (!_ready()) + { + return {}; + } const bool local = false; std::vector<path> dirs = simox::fs::list_directory(_rootDirAbs(), local); std::vector<path> datasetDirs; @@ -104,6 +112,10 @@ namespace armarx std::vector<ObjectInfo> ObjectFinder::findAllObjects(bool checkPaths) const { init(); + if (!_ready()) + { + return {}; + } const bool local = true; std::vector<ObjectInfo> objects; for (const path& datasetDir : simox::fs::list_directory(_rootDirAbs(), local)) @@ -135,6 +147,10 @@ namespace armarx std::vector<ObjectInfo> ObjectFinder::findAllObjectsOfDataset(const std::string& dataset, bool checkPaths) const { init(); + if (!_ready()) + { + return {}; + } path datasetDir = _rootDirAbs() / dataset; if (!fs::is_directory(datasetDir)) { @@ -169,5 +185,10 @@ namespace armarx return packageName; } + bool ObjectFinder::_ready() const + { + return !packageDataDir.empty(); + } + } diff --git a/source/RobotAPI/libraries/ArmarXObjects/ObjectFinder.h b/source/RobotAPI/libraries/ArmarXObjects/ObjectFinder.h index 3c56afba7a8bba669d95b3afd14438ebeaa00e9f..411edb339943cb7c2334ebfcfb6612009ee0274a 100644 --- a/source/RobotAPI/libraries/ArmarXObjects/ObjectFinder.h +++ b/source/RobotAPI/libraries/ArmarXObjects/ObjectFinder.h @@ -44,13 +44,18 @@ namespace armarx path _rootDirAbs() const; path _rootDirRel() const; + bool _ready() const; + private: /// Name of package containing the object models (ArmarXObjects by default). mutable std::string packageName; - /// Absolute path to data directory (e.g. "/.../repos/ArmarXObjects/data"). + /** + * @brief Absolute path to data directory (e.g. "/.../repos/ArmarXObjects/data"). + * Empty if package could not be found. + */ mutable path packageDataDir; }; diff --git a/source/RobotAPI/libraries/core/CMakeLists.txt b/source/RobotAPI/libraries/core/CMakeLists.txt index 6cb265f6f7e319be9bd6e4043cc10b9ffd0fbf59..5743f098b27b9de73ed56047ee020089a046af22 100644 --- a/source/RobotAPI/libraries/core/CMakeLists.txt +++ b/source/RobotAPI/libraries/core/CMakeLists.txt @@ -108,6 +108,8 @@ set(LIB_HEADERS #diffik/NaturalDiffIK.h #diffik/SimpleDiffIK.h + + json_conversions.h ) add_subdirectory(test) diff --git a/source/RobotAPI/libraries/core/json_conversions.h b/source/RobotAPI/libraries/core/json_conversions.h new file mode 100644 index 0000000000000000000000000000000000000000..bccd85c6884cb75930932cec64a4480742191b20 --- /dev/null +++ b/source/RobotAPI/libraries/core/json_conversions.h @@ -0,0 +1,64 @@ +/* + * 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/>. + * + * @package RobotAPI::Core + * @author Christian R. G. Dreher <c.dreher@kit.edu> + * @date 2020 + * @copyright http://www.gnu.org/licenses/gpl-2.0.txt + * GNU General Public License + */ + + +#pragma once + + +// Simox +#include <SimoxUtility/json.h> + +// RobotAPI +#include <RobotAPI/libraries/core/FramedPose.h> + + +namespace armarx +{ + void to_json(nlohmann::json& j, const FramedPose& fp) + { + j = nlohmann::json + { + {"agent", fp.agent}, + {"frame", fp.frame}, + {"qw", fp.orientation->qw}, + {"qx", fp.orientation->qx}, + {"qy", fp.orientation->qy}, + {"qz", fp.orientation->qz}, + {"x", fp.position->x}, + {"y", fp.position->y}, + {"z", fp.position->z} + }; + } + + void from_json(const nlohmann::json& j, FramedPose& fp) + { + j.at("agent").get_to(fp.agent); + j.at("frame").get_to(fp.frame); + j.at("qw").get_to(fp.orientation->qw); + j.at("qx").get_to(fp.orientation->qx); + j.at("qy").get_to(fp.orientation->qy); + j.at("qz").get_to(fp.orientation->qz); + j.at("x").get_to(fp.position->x); + j.at("y").get_to(fp.position->y); + j.at("z").get_to(fp.position->z); + } +}