diff --git a/source/RobotAPI/libraries/armem_objects/server/instance/Segment.cpp b/source/RobotAPI/libraries/armem_objects/server/instance/Segment.cpp index a55ed916713ec93627c5275d548897a8cc2a6401..4f9ab4cf19073ef86e7ecabe892a3880760943d3 100644 --- a/source/RobotAPI/libraries/armem_objects/server/instance/Segment.cpp +++ b/source/RobotAPI/libraries/armem_objects/server/instance/Segment.cpp @@ -119,10 +119,20 @@ namespace armarx::armem::server::obj::instance "Scene snapshots are expected to be located in Package/data/Package/Scenes/*.json."); defs->optional(p.sceneSnapshotsDirectory, prefix + "scene.11_Directory", "Directory in Package/data/Package/ containing the scene snapshots."); - defs->optional(p.sceneSnapshotToLoad, prefix + "scene.12_SnapshotToLoad", - "Scene to load on startup (e.g. 'Scene_2021-06-24_20-20-03').\n" - "You can also specify paths relative to 'Package/scenes/'. \n" - "You can also specify a ; separated list of scenes."); + + std::vector<std::string> sceneSnapshotToLoadDescription = + { + "Scene(s) to load on startup.", + "Specify multiple scenes in a ; separated list.", + "Each entry must be one of the following:", + "(1) A scene file in 'Package/scenes/' (with or without '.json' extension), " + "e.g. 'MyScene', 'MyScene.json'", + "(2) A path to a scene file relative to 'Package/scenes/' (with or without '.json' extension), " + "e.g. 'path/to/MyScene', 'path/to/MyScene.json'", + "(3) An ArmarX data path to a scene file, e.g. 'Package/scenes/path/to/MyScene.json'", + }; + defs->optional(p.sceneSnapshotsToLoad, prefix + "scene.12_SnapshotToLoad", + simox::alg::join(sceneSnapshotToLoadDescription, " \n")); decay.defineProperties(defs, prefix + "decay."); } @@ -132,10 +142,10 @@ namespace armarx::armem::server::obj::instance { SpecializedCoreSegment::init(); - if (not p.sceneSnapshotToLoad.empty()) + if (not p.sceneSnapshotsToLoad.empty()) { bool trim = true; - const std::vector<std::string> scenes = simox::alg::split(p.sceneSnapshotToLoad, ";", trim); + const std::vector<std::string> scenes = simox::alg::split(p.sceneSnapshotsToLoad, ";", trim); for (const std::string& scene : scenes) { const bool lockMemory = false; @@ -934,7 +944,7 @@ namespace armarx::armem::server::obj::instance void Segment::storeScene(const std::string& filename, const armarx::objects::Scene& scene) { - if (const std::optional<std::filesystem::path> path = resolveSceneFilename(filename)) + if (const std::optional<std::filesystem::path> path = resolveSceneFilepath(filename)) { ARMARX_INFO << "Storing scene snapshot at: \n" << path.value(); @@ -953,7 +963,7 @@ namespace armarx::armem::server::obj::instance std::optional<armarx::objects::Scene> Segment::loadScene(const std::string& filename) { - if (const std::optional<std::filesystem::path> path = resolveSceneFilename(filename)) + if (const std::optional<std::filesystem::path> path = resolveSceneFilepath(filename)) { return loadScene(path.value()); } @@ -983,17 +993,18 @@ namespace armarx::armem::server::obj::instance std::optional<std::filesystem::path> - Segment::resolveSceneFilename(const std::string& _filename) + Segment::resolveSceneFilepath(const std::string& _filename) { - std::string filename = _filename; + std::string filepath = _filename; - filename = simox::alg::replace_all(filename, timestampPlaceholder, + filepath = simox::alg::replace_all(filepath, timestampPlaceholder, Time::Now().toString("%Y-%m-%d_%H-%M-%S")); - if (not simox::alg::ends_with(filename, ".json")) + if (not simox::alg::ends_with(filepath, ".json")) { - filename += ".json"; + filepath += ".json"; } + // Try to interprete it as relative to 'Package/scenes/'. if (!finder) { finder.reset(new CMakePackageFinder(p.sceneSnapshotsPackage)); @@ -1004,14 +1015,26 @@ namespace armarx::armem::server::obj::instance } if (finder->packageFound()) { - std::filesystem::path dataDir = finder->getDataDir(); - std::filesystem::path path = dataDir / p.sceneSnapshotsPackage / p.sceneSnapshotsDirectory / filename; - return path; + std::filesystem::path absDataDir = finder->getDataDir(); + std::filesystem::path absPath = absDataDir / p.sceneSnapshotsPackage + / p.sceneSnapshotsDirectory / filepath; + if (std::filesystem::is_regular_file(absPath)) + { + return absPath; + } } - else + + // Try to interprete it as ArmarXDataPath. { - return std::nullopt; + std::string resolved = ArmarXDataPath::resolvePath(filepath); + if (resolved != filepath) + { + return resolved; + } } + + // Else: Fail + return std::nullopt; } @@ -1114,25 +1137,40 @@ namespace armarx::armem::server::obj::instance void Segment::commitSceneSnapshotFromFilename(const std::string& filename, bool lockMemory) { - ARMARX_INFO << "Loading scene snapshot '" << filename << "' ..."; - if (auto path = resolveSceneFilename(filename)) + std::stringstream ss; + ss << "Loading scene '" << filename << "' ..."; + if (std::optional<std::filesystem::path> path = resolveSceneFilepath(filename)) { + ARMARX_INFO << ss.str() << "\nfrom " << path.value(); + if (const auto snapshot = loadScene(path.value())) { - std::filesystem::path filename = path->filename(); - filename.replace_extension(); // Removes extension + auto makeSceneName = [](const std::filesystem::path& path) + { + std::filesystem::path filename = path.filename(); + filename.replace_extension(); // Removes extension + return filename.string(); + }; + std::string sceneName = makeSceneName(path.value()); // The check seems useless? if (lockMemory) { - commitSceneSnapshot(snapshot.value(), filename.string()); + segmentPtr->doLocked([this,&snapshot, &sceneName]() + { + commitSceneSnapshot(snapshot.value(), sceneName); + }); } else { - commitSceneSnapshot(snapshot.value(), filename.string()); + commitSceneSnapshot(snapshot.value(), sceneName); } } } + else + { + ARMARX_INFO << ss.str() << " failed: Could not resolve scene name or path."; + } } diff --git a/source/RobotAPI/libraries/armem_objects/server/instance/Segment.h b/source/RobotAPI/libraries/armem_objects/server/instance/Segment.h index b9c5a6d374cd1f40fed8013d2581c8996a2e26e2..c5e62d975ca161773c9ae4e8b7d7f5352f0f1922 100644 --- a/source/RobotAPI/libraries/armem_objects/server/instance/Segment.h +++ b/source/RobotAPI/libraries/armem_objects/server/instance/Segment.h @@ -160,7 +160,7 @@ namespace armarx::armem::server::obj::instance void storeScene(const std::string& filename, const armarx::objects::Scene& scene); std::optional<armarx::objects::Scene> loadScene(const std::string& filename); std::optional<armarx::objects::Scene> loadScene(const std::filesystem::path& path); - std::optional<std::filesystem::path> resolveSceneFilename(const std::string& filename); + std::optional<std::filesystem::path> resolveSceneFilepath(const std::string& filename); armarx::objects::Scene getSceneSnapshot() const; void commitSceneSnapshot(const armarx::objects::Scene& scene, const std::string& sceneName); @@ -200,7 +200,7 @@ namespace armarx::armem::server::obj::instance /// Package containing the scene snapshots std::string sceneSnapshotsPackage = armarx::ObjectFinder::DefaultObjectsPackageName; std::string sceneSnapshotsDirectory = "scenes"; - std::string sceneSnapshotToLoad = ""; + std::string sceneSnapshotsToLoad = ""; }; Properties p;