diff --git a/source/RobotAPI/libraries/armem_gui/MemoryViewer.cpp b/source/RobotAPI/libraries/armem_gui/MemoryViewer.cpp index 5cf0df43721c50a0499860e4c8c32ee44bde0f81..bfa97db1e1afe59d2bd03bc47af21ea60fe3968f 100644 --- a/source/RobotAPI/libraries/armem_gui/MemoryViewer.cpp +++ b/source/RobotAPI/libraries/armem_gui/MemoryViewer.cpp @@ -442,10 +442,11 @@ namespace armarx::armem::gui { std::string name = memory.id().memoryName; - auto commit = armem::toCommit(memory); - if (memoryWriters.count(name) > 0) { + // we need to merge the current memory with the one from the disk. + // Please note that this may ignores coresegments, if not already existent + auto commit = armem::toCommit(memory); memoryWriters.at(name).commit(commit); } else @@ -456,10 +457,9 @@ namespace armarx::armem::gui // Please note: Here we assume that a memory server with the same name does not exist. // I think this assumption is ok, since nobody should use filepaths as memory name. // Nonetheless, we did not restrict the user to do so... - std::string virtualMemoryName = name + " (at " + path.string() + ")"; - wm::Memory virtualMemory(virtualMemoryName); - virtualMemory.update(commit, true, false); - memoryData[virtualMemoryName] = std::move(virtualMemory); + std::string virtualMemoryName = name;// + " (at " + path.string() + ")"; + memory.id().memoryName = virtualMemoryName; + memoryData[virtualMemoryName] = std::move(memory); } } diff --git a/source/RobotAPI/libraries/armem_gui/instance/tree_visitors/TreeTypedJSONConverter.cpp b/source/RobotAPI/libraries/armem_gui/instance/tree_visitors/TreeTypedJSONConverter.cpp index c36d567350b3050ed49e7d362dfcaf2f63f3a643..58e15d056ae74b3d79b48ef917822d20c9de206c 100644 --- a/source/RobotAPI/libraries/armem_gui/instance/tree_visitors/TreeTypedJSONConverter.cpp +++ b/source/RobotAPI/libraries/armem_gui/instance/tree_visitors/TreeTypedJSONConverter.cpp @@ -51,18 +51,29 @@ namespace armarx::armem::gui::instance } else { - return; + // should not happen + throw aron::error::AronException(__PRETTY_FUNCTION__, "Both, data and type are NULL."); } try { key = path.getLastElement(); + if (!elementData) + { + // push NULL + jsonStack.push({key, nullptr}); + } + else + { + // push new object as there is data + jsonStack.push({key, nlohmann::json(nlohmann::json::value_t::object)}); + } } catch (const aron::error::AronException& e) { // This happens when we start at the top-level object. + jsonStack.push({key, nlohmann::json(nlohmann::json::value_t::object)}); } - jsonStack.push({key, nlohmann::json(nlohmann::json::value_t::object)}); } void @@ -111,10 +122,34 @@ namespace armarx::armem::gui::instance } void - TreeTypedJSONConverter::visitListOnEnter(DataInput& elementData, TypeInput& /*elementType*/) + TreeTypedJSONConverter::visitListOnEnter(DataInput& elementData, TypeInput& elementType) { - const std::string key = elementData->getPath().getLastElement(); - jsonStack.push({key, nlohmann::json(nlohmann::json::value_t::array)}); + std::string key = ""; + aron::Path path; + if (elementData) + { + path = elementData->getPath(); + } + else if(elementType) + { + path = elementType->getPath(); + } + else + { + // should not happen + throw aron::error::AronException(__PRETTY_FUNCTION__, "Both, data and type are NULL."); + } + + key = path.getLastElement(); + + if (!elementData) + { + jsonStack.push({key, nlohmann::json(nlohmann::json::value_t::array)}); + } + else + { + jsonStack.push({key, nullptr}); + } } void @@ -128,115 +163,263 @@ namespace armarx::armem::gui::instance void TreeTypedJSONConverter::visitMatrix(DataInput& elementData, TypeInput& elementType) { - const std::string key = elementData->getPath().getLastElement(); - auto nd = *aron::data::NDArray::DynamicCastAndCheck(elementData); - auto t = *aron::type::Matrix::DynamicCastAndCheck(elementType); - nlohmann::json obj; - if (nd.getType() == "float") + if (elementData) { - Eigen::Map<Eigen::Matrix<float, Eigen::Dynamic, Eigen::Dynamic>> m( - reinterpret_cast<float*>(nd.getData()), t.getRows(), t.getCols()); - Eigen::to_json(obj, m); + auto e = aron::data::NDArray::DynamicCast(elementData); + auto t = *aron::type::Matrix::DynamicCastAndCheck(elementType); + + auto& nd = *e; + const std::string key = nd.getPath().getLastElement(); + + nlohmann::json obj; + if (nd.getType() == "float") // TODO: are these types correct? + { + Eigen::Map<Eigen::Matrix<float, Eigen::Dynamic, Eigen::Dynamic>> m( + reinterpret_cast<float*>(nd.getData()), t.getRows(), t.getCols()); + Eigen::to_json(obj, m); + } + else if (nd.getType() == "double") + { + Eigen::Map<Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic>> m( + reinterpret_cast<double*>(nd.getData()), t.getRows(), t.getCols()); + Eigen::to_json(obj, m); + } + else + { + obj = handleGenericNDArray(nd); + } + + insertIntoJSON(key, obj); } - else if (nd.getType() == "double") + else if(elementType) { - Eigen::Map<Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic>> m( - reinterpret_cast<double*>(nd.getData()), t.getRows(), t.getCols()); - Eigen::to_json(obj, m); + std::string key = elementType->getPath().getLastElement(); + insertNULLIntoJSON(key); } else { - obj = handleGenericNDArray(nd); + // should not happen + throw aron::error::AronException(__PRETTY_FUNCTION__, "Both, data and type are NULL."); } - insertIntoJSON(key, obj); } void - TreeTypedJSONConverter::visitNDArray(DataInput& elementData, TypeInput& /*elementType*/) + TreeTypedJSONConverter::visitNDArray(DataInput& elementData, TypeInput& elementType) { - const std::string key = elementData->getPath().getLastElement(); - auto nd = *aron::data::NDArray::DynamicCastAndCheck(elementData); - insertIntoJSON(key, handleGenericNDArray(nd)); + if (elementData) + { + const std::string key = elementData->getPath().getLastElement(); + auto nd = *aron::data::NDArray::DynamicCastAndCheck(elementData); + insertIntoJSON(key, handleGenericNDArray(nd)); + } + else if(elementType) + { + std::string key = elementType->getPath().getLastElement(); + insertNULLIntoJSON(key); + } + else + { + // should not happen + throw aron::error::AronException(__PRETTY_FUNCTION__, "Both, data and type are NULL."); + } } void - TreeTypedJSONConverter::visitQuaternion(DataInput& elementData, TypeInput& /*elementType*/) + TreeTypedJSONConverter::visitQuaternion(DataInput& elementData, TypeInput& elementType) { - const std::string key = elementData->getPath().getLastElement(); - auto nd = *aron::data::NDArray::DynamicCastAndCheck(elementData); - nlohmann::json obj; - Eigen::to_json(obj, aron::data::converter::AronEigenConverter::ConvertToQuaternionf(nd)); - insertIntoJSON(key, obj); + if (elementData) + { + const std::string key = elementData->getPath().getLastElement(); + auto nd = *aron::data::NDArray::DynamicCastAndCheck(elementData); + nlohmann::json obj; + Eigen::to_json(obj, aron::data::converter::AronEigenConverter::ConvertToQuaternionf(nd)); + insertIntoJSON(key, obj); + } + else if (elementType) + { + std::string key = elementType->getPath().getLastElement(); + insertNULLIntoJSON(key); + } + else + { + // should not happen + throw aron::error::AronException(__PRETTY_FUNCTION__, "Both, data and type are NULL."); + } + } void - TreeTypedJSONConverter::visitImage(DataInput& elementData, TypeInput& /*elementType*/) + TreeTypedJSONConverter::visitImage(DataInput& elementData, TypeInput& elementType) { - const std::string key = elementData->getPath().getLastElement(); - auto nd = *aron::data::NDArray::DynamicCastAndCheck(elementData); - insertIntoJSON(key, handleGenericNDArray(nd)); + if (elementData) + { + const std::string key = elementData->getPath().getLastElement(); + auto nd = *aron::data::NDArray::DynamicCastAndCheck(elementData); + insertIntoJSON(key, handleGenericNDArray(nd)); + } + else if (elementType) + { + std::string key = elementType->getPath().getLastElement(); + insertNULLIntoJSON(key); + } + else + { + // should not happen + throw aron::error::AronException(__PRETTY_FUNCTION__, "Both, data and type are NULL."); + } } void - TreeTypedJSONConverter::visitPointCloud(DataInput& elementData, TypeInput& /*elementType*/) + TreeTypedJSONConverter::visitPointCloud(DataInput& elementData, TypeInput& elementType) { - const std::string key = elementData->getPath().getLastElement(); - auto nd = *aron::data::NDArray::DynamicCastAndCheck(elementData); - insertIntoJSON(key, handleGenericNDArray(nd)); + if (elementData) + { + const std::string key = elementData->getPath().getLastElement(); + auto nd = *aron::data::NDArray::DynamicCastAndCheck(elementData); + insertIntoJSON(key, handleGenericNDArray(nd)); + } + else if (elementType) + { + std::string key = elementType->getPath().getLastElement(); + insertNULLIntoJSON(key); + } + else + { + // should not happen + throw aron::error::AronException(__PRETTY_FUNCTION__, "Both, data and type are NULL."); + } } void TreeTypedJSONConverter::visitIntEnum(DataInput& elementData, TypeInput& elementType) { - /* Not handled by the TreeTypedDataVisitor either */ + this->visitInt(elementData, elementType); } void - TreeTypedJSONConverter::visitInt(DataInput& elementData, TypeInput& /*elementType*/) + TreeTypedJSONConverter::visitInt(DataInput& elementData, TypeInput& elementType) { - const std::string key = elementData->getPath().getLastElement(); - int i = *aron::data::Int::DynamicCastAndCheck(elementData); - insertIntoJSON(key, i); + if (elementData) + { + const std::string key = elementData->getPath().getLastElement(); + int i = *aron::data::Int::DynamicCastAndCheck(elementData); + insertIntoJSON(key, i); + } + else if (elementType) + { + std::string key = elementType->getPath().getLastElement(); + insertNULLIntoJSON(key); + } + else + { + // should not happen + throw aron::error::AronException(__PRETTY_FUNCTION__, "Both, data and type are NULL."); + } } void - TreeTypedJSONConverter::visitLong(DataInput& elementData, TypeInput& /*elementType*/) + TreeTypedJSONConverter::visitLong(DataInput& elementData, TypeInput& elementType) { - const std::string key = elementData->getPath().getLastElement(); - int64_t l = *aron::data::Long::DynamicCastAndCheck(elementData); - insertIntoJSON(key, l); + if (elementData) + { + const std::string key = elementData->getPath().getLastElement(); + int64_t l = *aron::data::Long::DynamicCastAndCheck(elementData); + insertIntoJSON(key, l); + } + else if (elementType) + { + std::string key = elementType->getPath().getLastElement(); + insertNULLIntoJSON(key); + } + else + { + // should not happen + throw aron::error::AronException(__PRETTY_FUNCTION__, "Both, data and type are NULL."); + } } void - TreeTypedJSONConverter::visitFloat(DataInput& elementData, TypeInput& /*elementType*/) + TreeTypedJSONConverter::visitFloat(DataInput& elementData, TypeInput& elementType) { - const std::string key = elementData->getPath().getLastElement(); - float f = *aron::data::Float::DynamicCastAndCheck(elementData); - insertIntoJSON(key, f); + if (elementData) + { + const std::string key = elementData->getPath().getLastElement(); + float f = *aron::data::Float::DynamicCastAndCheck(elementData); + insertIntoJSON(key, f); + } + else if (elementType) + { + std::string key = elementType->getPath().getLastElement(); + insertNULLIntoJSON(key); + } + else + { + // should not happen + throw aron::error::AronException(__PRETTY_FUNCTION__, "Both, data and type are NULL."); + } } void - TreeTypedJSONConverter::visitDouble(DataInput& elementData, TypeInput& /*elementType*/) + TreeTypedJSONConverter::visitDouble(DataInput& elementData, TypeInput& elementType) { - const std::string key = elementData->getPath().getLastElement(); - double d = *aron::data::Double::DynamicCastAndCheck(elementData); - insertIntoJSON(key, d); + if (elementData) + { + const std::string key = elementData->getPath().getLastElement(); + double d = *aron::data::Double::DynamicCastAndCheck(elementData); + insertIntoJSON(key, d); + } + else if (elementType) + { + std::string key = elementType->getPath().getLastElement(); + insertNULLIntoJSON(key); + } + else + { + // should not happen + throw aron::error::AronException(__PRETTY_FUNCTION__, "Both, data and type are NULL."); + } } void - TreeTypedJSONConverter::visitBool(DataInput& elementData, TypeInput& /*elementType*/) + TreeTypedJSONConverter::visitBool(DataInput& elementData, TypeInput& elementType) { - const std::string key = elementData->getPath().getLastElement(); - bool b = *aron::data::Bool::DynamicCastAndCheck(elementData); - insertIntoJSON(key, b); + if (elementData) + { + const std::string key = elementData->getPath().getLastElement(); + bool b = *aron::data::Bool::DynamicCastAndCheck(elementData); + insertIntoJSON(key, b); + } + else if (elementType) + { + std::string key = elementType->getPath().getLastElement(); + insertNULLIntoJSON(key); + } + else + { + // should not happen + throw aron::error::AronException(__PRETTY_FUNCTION__, "Both, data and type are NULL."); + } } void - TreeTypedJSONConverter::visitString(DataInput& elementData, TypeInput& /*elementType*/) + TreeTypedJSONConverter::visitString(DataInput& elementData, TypeInput& elementType) { - const std::string key = elementData->getPath().getLastElement(); - std::string s = *aron::data::String::DynamicCastAndCheck(elementData); - insertIntoJSON(key, s); + if (elementData) + { + const std::string key = elementData->getPath().getLastElement(); + std::string s = *aron::data::String::DynamicCastAndCheck(elementData); + insertIntoJSON(key, s); + } + else if (elementType) + { + std::string key = elementType->getPath().getLastElement(); + insertNULLIntoJSON(key); + } + else + { + // should not happen + throw aron::error::AronException(__PRETTY_FUNCTION__, "Both, data and type are NULL."); + } } //void @@ -266,6 +449,19 @@ namespace armarx::armem::gui::instance } } + void + TreeTypedJSONConverter::insertNULLIntoJSON(const std::string& key) + { + if (jsonStack.top().second.is_object()) + { + jsonStack.top().second[key] = nullptr; + } + else + { + jsonStack.top().second.emplace_back(nullptr); + } + } + nlohmann::json TreeTypedJSONConverter::handleGenericNDArray(const aron::data::NDArray& nd) { diff --git a/source/RobotAPI/libraries/armem_gui/instance/tree_visitors/TreeTypedJSONConverter.h b/source/RobotAPI/libraries/armem_gui/instance/tree_visitors/TreeTypedJSONConverter.h index e299f8f64974bc32a5af1883fc0a10e52ebdedec..a83a6a2352f88c0c2aed408e38677e1be3c35ecf 100644 --- a/source/RobotAPI/libraries/armem_gui/instance/tree_visitors/TreeTypedJSONConverter.h +++ b/source/RobotAPI/libraries/armem_gui/instance/tree_visitors/TreeTypedJSONConverter.h @@ -48,6 +48,7 @@ namespace armarx::armem::gui::instance template <typename ElementType> void insertIntoJSON(const std::string& key, const ElementType& data); + void insertNULLIntoJSON(const std::string& key); static nlohmann::json handleGenericNDArray(const aron::data::NDArray& nd); }; diff --git a/source/RobotAPI/libraries/aron/core/data/visitor/variant/VariantVisitor.cpp b/source/RobotAPI/libraries/aron/core/data/visitor/variant/VariantVisitor.cpp index b0799cdbd06bc44004359ebf87a1e1469296f18d..d060c70606a439a9b7abe8ec03f89c565aefaa17 100644 --- a/source/RobotAPI/libraries/aron/core/data/visitor/variant/VariantVisitor.cpp +++ b/source/RobotAPI/libraries/aron/core/data/visitor/variant/VariantVisitor.cpp @@ -508,7 +508,7 @@ namespace armarx::aron::data RecursiveConstTypedVariantVisitor::GetObjectElementsWithNullType(DataInput& o, TypeInput& t) { std::map<std::string, std::pair<aron::data::VariantPtr, aron::type::VariantPtr>> ret; - auto data = aron::data::Dict::DynamicCastAndCheck(o); + auto data = aron::data::Dict::DynamicCast(o); auto type = aron::type::Object::DynamicCastAndCheck(t); if (data)