From e5323e13939e11e1a4ded9ec08355071a1c355e4 Mon Sep 17 00:00:00 2001 From: Rainer Kartmann <rainer.kartmann@kit.edu> Date: Thu, 24 Jun 2021 20:32:54 +0200 Subject: [PATCH] Implement scene snapshot loading --- .../libraries/armem_objects/SceneSnapshot.cpp | 10 +- .../libraries/armem_objects/SceneSnapshot.h | 5 +- .../armem_objects/server/instance/Segment.cpp | 162 +++++++++++------- .../armem_objects/server/instance/Segment.h | 10 +- 4 files changed, 118 insertions(+), 69 deletions(-) diff --git a/source/RobotAPI/libraries/armem_objects/SceneSnapshot.cpp b/source/RobotAPI/libraries/armem_objects/SceneSnapshot.cpp index 8c9297558..c410c7e35 100644 --- a/source/RobotAPI/libraries/armem_objects/SceneSnapshot.cpp +++ b/source/RobotAPI/libraries/armem_objects/SceneSnapshot.cpp @@ -2,6 +2,8 @@ #include <SimoxUtility/json.h> +// #include <RobotAPI/libraries/armem/core/json_conversions.h> + namespace armarx::armem::obj { @@ -10,18 +12,20 @@ namespace armarx::armem::obj void armarx::armem::obj::to_json(nlohmann::json& j, const SceneSnapshot::Object& rhs) { + // j["instanceID"] = rhs.instanceID; j["class"] = rhs.classID.str(); j["collection"] = rhs.collection; - j["postion"] = rhs.postion; + j["position"] = rhs.position; j["orientation"] = rhs.orientation; } void armarx::armem::obj::from_json(const nlohmann::json& j, SceneSnapshot::Object& rhs) { + // j.at("instanceID").get_to(rhs.instanceID); rhs.classID = ObjectID(j.at("class").get<std::string>()); - rhs.collection = j.at("collection"); - j.at("postion").get_to(rhs.postion); + j.at("collection").get_to(rhs.collection); + j.at("position").get_to(rhs.position); j.at("orientation").get_to(rhs.orientation); } diff --git a/source/RobotAPI/libraries/armem_objects/SceneSnapshot.h b/source/RobotAPI/libraries/armem_objects/SceneSnapshot.h index 5fe5192a4..b7c9ed5d8 100644 --- a/source/RobotAPI/libraries/armem_objects/SceneSnapshot.h +++ b/source/RobotAPI/libraries/armem_objects/SceneSnapshot.h @@ -26,6 +26,7 @@ #include <Eigen/Geometry> #include <RobotAPI/libraries/ArmarXObjects/ObjectID.h> +// #include <RobotAPI/libraries/armem/core/MemoryID.h> namespace armarx::armem::obj @@ -35,10 +36,12 @@ namespace armarx::armem::obj { struct Object { + // MemoryID instanceID; + ObjectID classID; std::string collection; - Eigen::Vector3f postion = Eigen::Vector3f::Zero(); + Eigen::Vector3f position = Eigen::Vector3f::Zero(); Eigen::Quaternionf orientation = Eigen::Quaternionf::Identity(); }; std::vector<Object> objects; diff --git a/source/RobotAPI/libraries/armem_objects/server/instance/Segment.cpp b/source/RobotAPI/libraries/armem_objects/server/instance/Segment.cpp index 29e3b2d56..8d876520b 100644 --- a/source/RobotAPI/libraries/armem_objects/server/instance/Segment.cpp +++ b/source/RobotAPI/libraries/armem_objects/server/instance/Segment.cpp @@ -11,6 +11,8 @@ #include <RobotAPI/libraries/armem/client/query/query_fns.h> #include <RobotAPI/libraries/armem/util/util.h> +#include <RobotAPI/libraries/aron/common/aron_conversions.h> + #include <RobotAPI/libraries/ArmarXObjects/ObjectFinder.h> #include <RobotAPI/libraries/ArmarXObjects/aron_conversions.h> #include <RobotAPI/libraries/ArmarXObjects/ice_conversions.h> @@ -167,43 +169,41 @@ namespace armarx::armem::server::obj::instance } } - commitObjectPoses(providerName, newObjectPoses); + commitObjectPoses(newObjectPoses, providerName); return stats; } - void Segment::commitObjectPoses(const std::string& providerName, const ObjectPoseSeq& objectPoses) + void Segment::commitObjectPoses(const ObjectPoseSeq& objectPoses, const std::string& providerName) { ARMARX_CHECK_NOT_NULL(coreSegment); + Time now = TimeUtil::GetTime(); - // Update memory. - const MemoryID providerSegmentID = coreSegment->id().withProviderSegmentName(providerName); - if (!coreSegment->hasProviderSegment(providerSegmentID.providerSegmentName)) - { - coreSegment->addProviderSegment(providerSegmentID.providerSegmentName); - } + const MemoryID coreSegmentID = coreSegment->id(); Commit commit; for (const objpose::ObjectPose& pose : objectPoses) { EntityUpdate& update = commit.updates.emplace_back(); + + const MemoryID providerID = coreSegmentID.withProviderSegmentName( + providerName.empty() ? pose.providerName : providerName); + + update.entityID = providerID.withEntityName(pose.objectID.str()); + update.timeArrived = now; + update.timeCreated = pose.timestamp; + update.confidence = pose.confidence; + + arondto::ObjectInstance dto; + toAron(dto, pose); + // Search for object class. + if (auto instance = findClassInstance(pose.objectID)) { - update.entityID = providerSegmentID.withEntityName(pose.objectID.str()); - update.timeArrived = TimeUtil::GetTime(); - update.timeCreated = pose.timestamp; - update.confidence = pose.confidence; - - arondto::ObjectInstance dto; - toAron(dto, pose); - // Search for object class. - if (auto instance = findClassInstance(pose.objectID)) - { - toAron(dto.classID, instance->id()); - } - update.instancesData.push_back(dto.toAron()); + toAron(dto.classID, instance->id()); } - + toAron(dto.sourceID, MemoryID()); + update.instancesData.push_back(dto.toAron()); } iceMemory.commit(commit); } @@ -674,14 +674,17 @@ namespace armarx::armem::server::obj::instance } - std::optional<wm::EntityInstance> Segment::findClassInstance(const ObjectID& objectID) + std::optional<wm::EntityInstance> Segment::findClassInstance(const ObjectID& objectID) const { const ObjectID classID = { objectID.dataset(), objectID.className() }; try { for (const auto& [_, provSeg] : iceMemory.workingMemory->getCoreSegment("Class")) { - return provSeg.getEntity(classID.str()).getLatestSnapshot().getInstance(0); + if (provSeg.hasEntity(classID.str())) + { + return provSeg.getEntity(classID.str()).getLatestSnapshot().getInstance(0); + } } return std::nullopt; } @@ -715,20 +718,7 @@ namespace armarx::armem::server::obj::instance { if (const std::optional<std::filesystem::path> path = resolveSceneFilename(filename)) { - ARMARX_INFO << "Loading scene snapshot from: \n" << path.value(); - nlohmann::json j; - try - { - j = nlohmann::read_json(path.value()); - } - catch (const std::ios_base::failure& e) - { - ARMARX_WARNING << "Loading scene snapshot failed: \n" << e.what(); - return std::nullopt; - } - - armem::obj::SceneSnapshot snapshot = j; - return snapshot; + return loadScene(path.value()); } else { @@ -737,8 +727,27 @@ namespace armarx::armem::server::obj::instance } - static const std::string timestampPlaceholder = "%TIMESTAMP"; - static const std::string targetPackage = "ArmarXObjects"; + std::optional<armem::obj::SceneSnapshot> Segment::loadScene(const std::filesystem::path& path) + { + ARMARX_INFO << "Loading scene snapshot from: \n" << path; + nlohmann::json j; + try + { + j = nlohmann::read_json(path); + } + catch (const std::ios_base::failure& e) + { + ARMARX_WARNING << "Loading scene snapshot failed: \n" << e.what(); + return std::nullopt; + } + + armem::obj::SceneSnapshot snapshot = j; + return snapshot; + } + + + const std::string Segment::timestampPlaceholder = "%TIMESTAMP"; + const std::string Segment::targetPackage = "ArmarXObjects"; std::optional<std::filesystem::path> Segment::resolveSceneFilename(const std::string& _filename) @@ -780,24 +789,24 @@ namespace armarx::armem::server::obj::instance wm::FunctionalVisitor visitor; visitor.entityFn = [&scene](wm::Entity & entity) { - ARMARX_IMPORTANT_S << "Processing entity " << entity.id(); - std::optional<arondto::ObjectInstance> instance; try { const wm::EntityInstance& entityInstance = entity.getLatestSnapshot().getInstance(0); - instance = tryCast<arondto::ObjectInstance>(entityInstance); + std::optional<arondto::ObjectInstance> objectInstance = tryCast<arondto::ObjectInstance>(entityInstance); + if (objectInstance) + { + armem::obj::SceneSnapshot::Object& object = scene.objects.emplace_back(); + // object.instanceID = entityInstance.id(); + object.classID = objectInstance->classID.entityName; + object.collection = ""; + object.position = simox::math::position(objectInstance->pose.objectPoseGlobal); + object.orientation = simox::math::orientation(objectInstance->pose.objectPoseGlobal); + } } catch (const armem::error::ArMemError& e) { ARMARX_WARNING_S << e.what(); } - if (instance) - { - armem::obj::SceneSnapshot::Object& object = scene.objects.emplace_back(); - object.classID = instance->classID.entityName; - object.postion = simox::math::position(instance->pose.objectPoseGlobal); - object.orientation = simox::math::orientation(instance->pose.objectPoseGlobal); - } return false; }; @@ -806,9 +815,35 @@ namespace armarx::armem::server::obj::instance } - void Segment::commitSceneSnapshot(const armem::obj::SceneSnapshot& scene) const + void Segment::commitSceneSnapshot(const armem::obj::SceneSnapshot& scene, const std::string& sceneName) { - ARMARX_WARNING << "ToDo: Implement"; + const Time now = TimeUtil::GetTime(); + std::map<ObjectID, int> idCounters; + + objpose::ObjectPoseSeq objectPoses; + + for (const auto& object : scene.objects) + { + objpose::ObjectPose& pose = objectPoses.emplace_back(); + + pose.providerName = sceneName; + pose.objectType = objpose::ObjectTypeEnum::KnownObject; + pose.objectID = object.classID.withInstanceName(std::to_string(idCounters[object.classID]++)); + + pose.objectPoseGlobal = simox::math::pose(object.position, object.orientation); + pose.objectPoseRobot = pose.objectPoseGlobal; + pose.objectPoseOriginal = pose.objectPoseGlobal; + pose.objectPoseOriginalFrame = armarx::GlobalFrame; + + pose.robotConfig = {}; + pose.robotPose = Eigen::Matrix4f::Identity(); + + pose.confidence = 1.0; + pose.localOOBB = getObjectOOBB(object.classID); + pose.timestamp = now; + } + + commitObjectPoses(objectPoses); } @@ -824,15 +859,16 @@ namespace armarx::armem::server::obj::instance storeLoadLine.setValue("Scene_" + timestampPlaceholder); loadButton.setLabel("Load Scene"); storeButton.setLabel("Store Scene"); - HBoxLayout storeLoadLineLayout; - storeLoadLineLayout.addChildren({Label(targetPackage + "/Scenes/"), storeLoadLine, Label(".json")}); + + HBoxLayout storeLoadLineLayout({Label(targetPackage + "/Scenes/"), storeLoadLine, Label(".json")}); + HBoxLayout storeLoadButtonsLayout({loadButton, storeButton}); GridLayout grid; int row = 0; grid.add(storeLoadLineLayout, {row, 0}, {1, 2}); row++; - grid.add(loadButton, {row, 0}).add(storeButton, {row, 1}); + grid.add(storeLoadButtonsLayout, {row, 0}, {1, 2}); row++; grid.add(Label("Max History Size"), {row, 0}).add(maxHistorySize, {row, 1}); @@ -851,14 +887,16 @@ namespace armarx::armem::server::obj::instance { if (loadButton.wasClicked()) { - ARMARX_IMPORTANT_S << "Store button clicked"; - if (const auto snapshot = data.loadScene(storeLoadLine.getValue())) + if (auto path = data.resolveSceneFilename(storeLoadLine.getValue())) { - ARMARX_IMPORTANT_S << "Snapshot loaded"; - std::scoped_lock lock(data.memoryMutex); - ARMARX_IMPORTANT_S << "Committing"; - data.commitSceneSnapshot(snapshot.value()); - ARMARX_IMPORTANT_S << "Committed"; + if (const auto snapshot = data.loadScene(path.value())) + { + std::filesystem::path filename = path->filename(); + filename.replace_extension(); // Removes extension + + std::scoped_lock lock(data.memoryMutex); + data.commitSceneSnapshot(snapshot.value(), filename.string()); + } } } diff --git a/source/RobotAPI/libraries/armem_objects/server/instance/Segment.h b/source/RobotAPI/libraries/armem_objects/server/instance/Segment.h index 910b816e8..57e918dd0 100644 --- a/source/RobotAPI/libraries/armem_objects/server/instance/Segment.h +++ b/source/RobotAPI/libraries/armem_objects/server/instance/Segment.h @@ -59,7 +59,7 @@ namespace armarx::armem::server::obj::instance const std::string& providerName, const objpose::data::ProvidedObjectPoseSeq& providedPoses, std::optional<Time> discardUpdatesUntil = std::nullopt); - void commitObjectPoses(const std::string& providerName, const ObjectPoseSeq& objectPoses); + void commitObjectPoses(const ObjectPoseSeq& objectPoses, const std::string& providerName = ""); wm::CoreSegment& getCoreSegment(); @@ -135,7 +135,7 @@ namespace armarx::armem::server::obj::instance bool commitAttachedPose); - std::optional<wm::EntityInstance> findClassInstance(const ObjectID& objectID); + std::optional<wm::EntityInstance> findClassInstance(const ObjectID& objectID) const; friend struct DetachVisitor; @@ -145,10 +145,11 @@ namespace armarx::armem::server::obj::instance void storeScene(const std::string& filename, const armem::obj::SceneSnapshot& scene); std::optional<armem::obj::SceneSnapshot> loadScene(const std::string& filename); + std::optional<armem::obj::SceneSnapshot> loadScene(const std::filesystem::path& path); std::optional<std::filesystem::path> resolveSceneFilename(const std::string& filename); armem::obj::SceneSnapshot getSceneSnapshot() const; - void commitSceneSnapshot(const armem::obj::SceneSnapshot& scene) const; + void commitSceneSnapshot(const armem::obj::SceneSnapshot& scene, const std::string& sceneName); public: @@ -190,6 +191,9 @@ namespace armarx::armem::server::obj::instance std::unique_ptr<CMakePackageFinder> finder; + static const std::string timestampPlaceholder; + static const std::string targetPackage; + public: -- GitLab