Reader.cpp
Go to the documentation of this file.
1#include "Reader.h"
2
3#include <cstring>
4#include <optional>
5#include <set>
6#include <string>
7#include <vector>
8
13
18#include <RobotAPI/interface/units/LaserScannerUnit.h>
25#include <RobotAPI/libraries/armem_laser_scans/aron/LaserScan.aron.generated.h>
29
31{
32
34 {
35 }
36
37 Reader::~Reader() = default;
38
39 void
41 {
42 ARMARX_DEBUG << "TransformReader: registerPropertyDefinitions";
43
44 const std::string prefix = propertyPrefix;
45 }
46
47 void
49 {
50 // Wait for the memory to become available and add it as dependency.
51 ARMARX_IMPORTANT << "MappingDataReader: Waiting for memory '" << constants::memoryName
52 << "' ...";
53 try
54 {
55 memoryReader =
56 memoryNameSystem.useReader(MemoryID().withMemoryName(constants::memoryName));
57 ARMARX_IMPORTANT << "MappingDataReader: Connected to memory '" << constants::memoryName
58 << "'";
59 }
61 {
62 ARMARX_ERROR << e.what();
63 return;
64 }
65 }
66
69 {
71
72 ARMARX_VERBOSE << "Query for agent: " << query.agent
73 << " memory name: " << constants::memoryName;
74
75 if (query.sensorList.empty()) // all sensors
76 {
77 // clang-format off
78 auto& snapshots = qb
81 .entities().all()
82 .snapshots();
83 // clang-format on
84 if (query.timeRange.has_value())
85 {
86 snapshots.timeRange(query.timeRange->min, query.timeRange->max);
87 }
88 else
89 {
90 snapshots.latest();
91 }
92 }
93 else
94 {
95 // clang-format off
96 auto& snapshots = qb
99 .entities().withNames(query.sensorList)
100 .snapshots();
101 // clang-format on
102 if (query.timeRange.has_value())
103 {
104 snapshots.timeRange(query.timeRange->min, query.timeRange->max);
105 }
106 else
107 {
108 snapshots.latest();
109 }
110 }
111
112 return qb;
113 }
114
115 std::vector<LaserScanStamped>
116 asLaserScans(const wm::ProviderSegment& providerSegment)
117 {
118 std::vector<LaserScanStamped> outV;
119
120 if (providerSegment.empty())
121 {
122 ARMARX_WARNING << "No entities!";
123 }
124
125 const auto convert = [](const auto& aronLaserScanStamped,
127 {
128 LaserScanStamped laserScanStamped;
129 fromAron(aronLaserScanStamped, laserScanStamped);
130
131 const auto ndArrayNavigator =
132 aron::data::NDArray::DynamicCast(ei.data()->getElement("scan"));
133
134 ARMARX_CHECK_NOT_NULL(ndArrayNavigator);
135
136 laserScanStamped.data = fromAron<LaserScanStep>(ndArrayNavigator);
137
138 return laserScanStamped;
139 };
140
141 // loop over all entities and their snapshots
142 providerSegment.forEachEntity(
143 [&outV, &convert](const wm::Entity& entity)
144 {
145 // If we don't need this warning, we could directly iterate over the snapshots.
146 if (entity.empty())
147 {
148 ARMARX_WARNING << "Empty history for " << entity.id();
149 }
150 ARMARX_DEBUG << "History size: " << entity.size();
151
152 entity.forEachInstance(
153 [&outV, &convert](const wm::EntityInstance& entityInstance)
154 {
155 if (const auto o = tryCast<arondto::LaserScanStamped>(entityInstance))
156 {
157 outV.push_back(convert(*o, entityInstance));
158 }
159 return true;
160 });
161 return true;
162 });
163
164 return outV;
165 }
166
167 Reader::Result
169 {
170 const auto qb = buildQuery(query);
171
172 ARMARX_DEBUG << "[MappingDataReader] query ... ";
173
174 const armem::client::QueryResult qResult = memoryReader.query(qb.buildQueryInput());
175
176 ARMARX_DEBUG << "[MappingDataReader] result: " << qResult;
177
178 if (not qResult.success)
179 {
180 ARMARX_WARNING << "Failed to query data from memory: " << qResult.errorMessage;
181 return {.laserScans = {},
182 .sensors = {},
183 .status = Result::Status::Error,
184 .errorMessage = qResult.errorMessage};
185 }
186
188 {
189 ARMARX_VERBOSE << "No core segment `" << constants::memoryName << "` found in memory!";
190 return {.laserScans = {},
191 .sensors = {},
192 .status = Result::Status::Error,
193 .errorMessage =
194 "No core segment `" + constants::memoryName + "`found in memory!"};
195 }
196
198 .hasProviderSegment(query.agent))
199 {
200 ARMARX_VERBOSE << "No provider segment `" << query.agent << "` found in memory!";
201 return {.laserScans = {},
202 .sensors = {},
203 .status = Result::Status::Error,
204 .errorMessage = "No provider segment `" + query.agent + "`found in memory!"};
205 }
206
207
208 // now create result from memory
209 const wm::ProviderSegment& providerSegment =
210 qResult.memory.getCoreSegment(constants::memoryName).getProviderSegment(query.agent);
211
212 const auto laserScans = asLaserScans(providerSegment);
213 std::set<std::string> sensors;
214 providerSegment.forEachEntity(
215 [&sensors](const wm::Entity& entity)
216 {
217 sensors.insert(entity.name());
218 return true;
219 });
220
221 return {.laserScans = laserScans,
222 .sensors = sensors,
223 .status = Result::Status::Success,
224 .errorMessage = ""};
225 }
226
227} // namespace armarx::armem::laser_scans::client
bool hasCoreSegment(const std::string &name) const
Definition MemoryBase.h:107
CoreSegmentT & getCoreSegment(const std::string &name)
Definition MemoryBase.h:134
The memory name system (MNS) client.
Reader useReader(const MemoryID &memoryID)
Use a memory server and get a reader for it.
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.
virtual DerivedT & withNames(const std::vector< std::string > &names)
Indicates that a query to the Memory Name System failed.
Definition mns.h:25
void connect(armem::client::MemoryNameSystem &memoryNameSystem)
Definition Reader.cpp:48
armarx::armem::client::query::Builder buildQuery(const Query &query) const
Definition Reader.cpp:68
Result queryData(const Query &query) const
Definition Reader.cpp:168
void registerPropertyDefinitions(armarx::PropertyDefinitionsPtr &def)
Definition Reader.cpp:40
#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_IMPORTANT
The logging level for always important information, but expected behaviour (in contrast to ARMARX_WAR...
Definition Logging.h:190
#define ARMARX_ERROR
The logging level for unexpected behaviour, that must be fixed.
Definition Logging.h:196
#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
#define ARMARX_VERBOSE
The logging level for verbose information.
Definition Logging.h:187
std::vector< LaserScanStamped > asLaserScans(const wm::ProviderSegment &providerSegment)
Definition Reader.cpp:116
SensorHeader fromAron(const arondto::SensorHeader &aronSensorHeader)
armem::wm::EntityInstance EntityInstance
std::optional< AronClass > tryCast(const wm::EntityInstance &item)
Tries to cast a armem::EntityInstance to AronClass.
Definition util.h:45
armem::articulated_object::ArticulatedObject convert(const VirtualRobot::Robot &obj, const armem::Time &timestamp)
IceUtil::Handle< class PropertyDefinitionContainer > PropertyDefinitionsPtr
PropertyDefinitions smart pointer type.
Result of a QueryInput.
Definition Query.h:51
wm::Memory memory
The slice of the memory that matched the query.
Definition Query.h:58