Reader.cpp
Go to the documentation of this file.
1#include "Reader.h"
2
3// STD / STL
4#include <algorithm>
5#include <cstring>
6#include <map>
7#include <optional>
8#include <ostream>
9#include <type_traits>
10#include <utility>
11#include <vector>
12
13// ICE
14#include <IceUtil/Handle.h>
15#include <IceUtil/Time.h>
16
17// Simox
18#include <SimoxUtility/algorithm/get_map_keys_values.h>
19
20// ArmarXCore
25
26// RobotAPI Interfaces
27#include <RobotAPI/interface/armem/mns/MemoryNameSystemInterface.h>
28#include <RobotAPI/interface/armem/server/ReadingMemoryInterface.h>
29#include <RobotAPI/interface/units/LaserScannerUnit.h>
31
32// RobotAPI Aron
33#include <RobotAPI/libraries/armem_vision/aron/OccupancyGrid.aron.generated.h>
36
37// RobotAPI Armem
46
48{
49 Reader::~Reader() = default;
50
53 {
55
56 // clang-format off
57 qb
58 .coreSegments().withName(properties().coreSegmentName)
59 .providerSegments().withName(query.providerName)
60 .entities().all()
61 .snapshots().beforeOrAtTime(query.timestamp);
62 // clang-format on
63
64 return qb;
65 }
66
67 std::string
69 {
70 return "mem.vision.occupancy_grid.";
71 }
72
75 {
76 return {.memoryName = "Vision", .coreSegmentName = "OccupancyGrid"};
77 }
78
80 asOccupancyGrid(const wm::ProviderSegment& providerSegment)
81 {
82 ARMARX_CHECK(not providerSegment.empty()) << "No entities";
83 ARMARX_CHECK(providerSegment.size() == 1) << "There should be only one entity!";
84
85 const wm::EntityInstance* entityInstance = nullptr;
86 providerSegment.forEachEntity(
87 [&entityInstance](const wm::Entity& entity)
88 {
89 const auto& entitySnapshot = entity.getLatestSnapshot();
90 ARMARX_CHECK(not entitySnapshot.empty()) << "No entity snapshot instances";
91
92 entityInstance = &entitySnapshot.getInstance(0);
93 return false;
94 });
95 ARMARX_CHECK_NOT_NULL(entityInstance);
96
97 const auto aronDto = tryCast<arondto::OccupancyGrid>(*entityInstance);
98 ARMARX_CHECK(aronDto) << "Failed casting to OccupancyGrid";
99
100 OccupancyGrid occupancyGrid;
101 fromAron(*aronDto, occupancyGrid);
102
103 // direct access to grid data
104 const auto ndArrayNavigator =
105 aron::data::NDArray::DynamicCast(entityInstance->data()->getElement("grid"));
106 ARMARX_CHECK_NOT_NULL(ndArrayNavigator);
107
108 occupancyGrid.grid =
110
111 return occupancyGrid;
112 }
113
114 Reader::Result
116 {
117 const auto qb = buildQuery(query);
118
119 ARMARX_DEBUG << "[MappingDataReader] query ... ";
120
121 const armem::client::QueryResult qResult = memoryReader().query(qb.buildQueryInput());
122
123 ARMARX_DEBUG << "[MappingDataReader] result: " << qResult;
124
125 if (not qResult.success)
126 {
127 ARMARX_WARNING << "Failed to query data from memory: " << qResult.errorMessage;
128 return {.occupancyGrid = std::nullopt,
129 .status = Result::Status::Error,
130 .errorMessage = qResult.errorMessage};
131 }
132
133 const auto coreSegment = qResult.memory.getCoreSegment(properties().coreSegmentName);
134
135 if (not coreSegment.hasProviderSegment(query.providerName))
136 {
137 ARMARX_WARNING << "Provider segment `" << query.providerName
138 << "` does not exist (yet).";
139 return {.occupancyGrid = std::nullopt, .status = Result::Status::NoData};
140 }
141
142 const wm::ProviderSegment& providerSegment =
143 coreSegment.getProviderSegment(query.providerName);
144
145 if (providerSegment.empty())
146 {
147 ARMARX_WARNING << "No entities.";
148 return {.occupancyGrid = std::nullopt,
149 .status = Result::Status::NoData,
150 .errorMessage = "No entities"};
151 }
152
153 try
154 {
155 const auto occupancyGrid = asOccupancyGrid(providerSegment);
156 return Result{.occupancyGrid = occupancyGrid, .status = Result::Status::Success};
157 }
158 catch (...)
159 {
160 return Result{.status = Result::Status::Error,
161 .errorMessage = GetHandledExceptionString()};
162 }
163 }
164
165} // namespace armarx::armem::vision::occupancy_grid::client
CoreSegmentT & getCoreSegment(const std::string &name)
Definition MemoryBase.h:134
QueryResult query(const QueryInput &input) const
Perform a query on the WM.
Definition Reader.cpp:119
The query::Builder class provides a fluent-style specification of hierarchical queries.
Definition Builder.h:22
CoreSegmentSelector & coreSegments()
Start specifying core segments.
Definition Builder.cpp:42
CoreSegmentSelector & withName(const std::string &name) override
ProviderSegmentSelector & providerSegments()
Start specifying provider segments.
SnapshotSelector & snapshots()
Start specifying entity snapshots.
Definition selectors.cpp:92
ProviderSegmentSelector & withName(const std::string &name) override
EntitySelector & entities()
Start specifying entities.
SnapshotSelector & beforeOrAtTime(Time timestamp)
Definition selectors.cpp:73
const armem::client::Reader & memoryReader() const
::armarx::armem::client::query::Builder buildQuery(const Query &query) const
Definition Reader.cpp:52
static Eigen::Array< T, Rows, Cols > ConvertToArray(const data::NDArray &nav)
#define ARMARX_CHECK(expression)
Shortcut for ARMARX_CHECK_EXPRESSION.
#define ARMARX_CHECK_NOT_NULL(ptr)
This macro evaluates whether ptr is not null and if it turns out to be false it will throw an Express...
#define ARMARX_DEBUG
The logging level for output that is only interesting while debugging.
Definition Logging.h:184
#define ARMARX_WARNING
The logging level for unexpected behaviour, but not a serious problem.
Definition Logging.h:193
armem::wm::EntityInstance EntityInstance
OccupancyGrid asOccupancyGrid(const wm::ProviderSegment &providerSegment)
Definition Reader.cpp:80
void fromAron(const arondto::OccupancyGrid &dto, OccupancyGrid &bo)
std::optional< AronClass > tryCast(const wm::EntityInstance &item)
Tries to cast a armem::EntityInstance to AronClass.
Definition util.h:45
std::string GetHandledExceptionString()
auto & getLatestSnapshot(int snapshotIndex=0)
Retrieve the latest entity snapshot.
Result of a QueryInput.
Definition Query.h:51
wm::Memory memory
The slice of the memory that matched the query.
Definition Query.h:58