diff --git a/armarx_memory/ltm/ReadMe.md b/armarx_memory/ltm/ReadMe.md new file mode 100644 index 0000000000000000000000000000000000000000..9e88491931dfbeca87094d7068b3b22897058550 --- /dev/null +++ b/armarx_memory/ltm/ReadMe.md @@ -0,0 +1,104 @@ +# LTM Functionalities in Python + +This sub-repository contains the functionalities to read and write from the Long-Term Memory (LTM) using python. + +## Usage + +### Loading existing LTM data from FileSystem + +One can load EntityInstances (or any other memory subset consisting of at least one EntityInstance) from the FileSystem by specifying a path at which the LTM should be loaded from and an export name for the memory folder. +Using those one can create a `MemoryServer` and continue to first load the references to the EntityInstances (paths and ids) and then the actual data (including metadata). + +A minimal example could look like this: +```python +from armarx_memory.ltm.memory_server import MemoryServer + +base_path = "path/to/export_directory" +export_name = "LTM" +server = MemoryServer(base_path, export_name) +server.loadReferences() + +mid_vision = MemoryID("Vision", "ImageRGB", "Armar3WideImageProvider", "images") # this defines the entity from which you want to load data +entity = server.get_entity(mid_vision) + +# snapshots can be accessed over the snapshot id (timestamp): +snapshot_id = list(entity.snapshots.keys())[0] +snapshot: EntitySnapshot = entity.snapshots[snapshot_id] +# an instance can be accessed by the instance id (integer counting upwards from 0) +instance: EntityInstance = snapshot.instances[0] +# up until this point only references were loaded, so one needs to load the data (and metadata) of the instance: +instance.load() + +data = instance.data +metadata = instance.metadata +``` + +Be aware that this returns your data as aron types. If you want to convert your data to primitive datatypes use the `to_primitive()` functions, i.e. : + +```python +from armarx_memory.aron.data.variant import AronDict + +data : AronDict = instance.data +primitive_data = data.to_primitive() +``` + +On the highest level data of an entity instance is always an `AronDict`, so importing this aron type class should be sufficient. + +### Storing data from the Memory into the FileSystem + +You can also store EntityInstances (and all other types of memory items as long as they contain at least one EntityInstance) to the FileSystem. + +A small example (including creating a full memory and filling it with data) could look like the following: +```python +from armarx_memory.core.MemoryID import MemoryID +from armarx_memory.ltm.base.memory import Memory +from armarx_memory.ltm.base.core_segment import CoreSegment +from armarx_memory.ltm.base.provider_segment import ProviderSegment +from armarx_memory.ltm.base.entity import Entity +from armarx_memory.ltm.base.entity_snapshot import EntitySnapshot +from armarx_memory.ltm.base.entity_instance import EntityInstance + +from armarx_memory.aron.data.dto.common.metadata import Metadata + +from armarx_memory.aron.data.variant import AronDict, AronInt + +# First create the Memory including one Core- and Provider-Segment, one Entity, one Snapshot and one Instance: +base_path = "path/to/export_directory" +export_name = "LTM" + +memory_id = MemoryID("TestWritingMemory") +memory = Memory(id=memory_id, basepath=base_path, exportName=export_name) + +core_segment_id = MemoryID("TestWritingMemory", "TestCoreSegment") +core_segment = CoreSegment(id=core_segment_id, basepath=memory.rootdir) + +provider_segment_id = MemoryID("TestWritingMemory", "TestCoreSegment", "TestProviderSegment") +provider_segment = ProviderSegment(id=provider_segment_id, basepath=core_segment.rootdir) + +entity_id = MemoryID("TestWritingMemory", "TestCoreSegment", "TestProviderSegment", "TestEntity") +entity = Entity(id=entity_id, basepath=provider_segment.rootdir) + +entity_snapshot_id = MemoryID("TestWritingMemory", "TestCoreSegment", "TestProviderSegment", "TestEntity", 100) +entity_snappshot = EntitySnapshot(id=entity_snapshot_id, basepath=entity.rootdir) + +entity_instance_id = MemoryID("TestWritingMemory", "TestCoreSegment", "TestProviderSegment", "TestEntity", 100, 0) +entity_instance = EntityInstance(id=entity_instance_id, basepath=entity_snappshot.rootdir) +entity_instance.data = AronDict(elements={"testData": AronInt(["TestInteger"], 42)}, path=["t"]) +entity_instance.metadata = Metadata(100, 101, 102, 103) + +# then actually link them together: +memory.addCoreSegment(coreSegment=core_segment) +core_segment.addProviderSegment(providerSegment=provider_segment) +entity_snappshot.addEntityInstance(entityInstance=entity_instance) +entity.addEntitySnapshot(entitySnapshot=entity_snappshot) +provider_segment.addEntity(entity=entity) + +# storing itself is simple: +entity_instance.store() +``` + +If you already have the entity instance itself (i.e. from querying the working memory), you can simply use the last line of code from above. + +## Tests + +Pytest Unittests can be found in `python3-armarx/tests/armarx/armarx_memory/ltm`.