Reader.cpp
Go to the documentation of this file.
1#include "Reader.h"
2
3#include <functional>
4#include <map>
5#include <optional>
6#include <ostream>
7#include <sstream>
8#include <string>
9#include <vector>
10
11#include <SimoxUtility/algorithm/get_map_keys_values.h>
12#include <SimoxUtility/algorithm/string/fuzzy_multi_match.hpp>
13
17
25#include <RobotAPI/libraries/armem_locations/aron/Location.aron.generated.h>
28
30#include <armarx/navigation/core/aron/Graph.aron.generated.h>
34
35#include <range/v3/range/conversion.hpp>
36
38{
39 std::string
41 {
42 return "mem.nav.graph.";
43 }
44
47 {
48 return Properties{.memoryName = navigation::location::coreSegmentID.memoryName,
49 .coreSegmentName = navigation::location::coreSegmentID.coreSegmentName};
50 }
51
52 std::vector<core::Location>
54 {
55 std::vector<core::Location> locations;
56
57 const auto locs = queryLocations();
58 for (const auto& [id, location] : locs)
59 {
60 const std::string locationName = id.entityName;
61 ARMARX_DEBUG << "Location: " << locationName;
62
64 armarx::fromAron(location.framedPose, fp);
65
66 core::Location loc{.name = locationName,
67 .provider = id.providerSegmentName,
68 .framedPose = fp
69
70 };
71 locations.push_back(loc);
72 }
73
74 return locations;
75 }
76
77 std::vector<armarx::navigation::core::Graph>
79 {
81
82 std::map<armem::MemoryID, armarx::navigation::core::Graph> graphs;
83
84 const auto graphSegment = allGraphs();
85 graphSegment.forEachEntity(
86 [&](const armem::wm::Entity& entity)
87 {
89 if (const armem::wm::EntityInstance* instance = entity.findLatestInstance())
90 {
91 navigation::core::arondto::Graph aron;
92 aron.fromAron(instance->data());
94 }
95 // else: empty layer
96 });
97
98
99 const auto locSegment = allLocations();
100
101 for (auto& [_, graph] : graphs)
102 {
104 }
105
106 return simox::get_values(graphs);
107 }
108
111 {
113 // Query all entities from provider.
115
116 // clang-format off
117 qb
120 .entities().all()
121 .snapshots().latest();
122 // clang-format on
123
124 const armem::client::QueryResult qResult =
125 memoryReaderLocations.query(qb.buildQueryInput());
126 ARMARX_DEBUG << "Lookup result in reader: " << qResult;
127
128 if (not qResult.success)
129 {
130 ARMARX_WARNING << "Failure ...";
131 return {};
132 }
133
134 const auto& locSegment =
136 return locSegment;
137 }
138
141 {
143
144 // Query all entities from provider.
146
147 // clang-format off
148 qb
151 .entities().all()
152 .snapshots().latest();
153 // clang-format on
154
155 const armem::client::QueryResult qResult = memoryReaderGraphs.query(qb.buildQueryInput());
156 ARMARX_DEBUG << "Lookup result in reader: " << qResult;
157
158 if (not qResult.success)
159 {
160 ARMARX_WARNING << "Failure ...";
161 return {};
162 }
163
164 const auto& graphSegment =
166 return graphSegment;
167 }
168
169 std::map<armem::MemoryID, location::arondto::Location>
171 {
172 // Query all entities from provider.
174
175 // clang-format off
176 qb
179 .entities().all()
180 .snapshots().latest();
181 // clang-format on
182
183 const armem::client::QueryResult qResult =
184 memoryReaderLocations.query(qb.buildQueryInput());
185 ARMARX_DEBUG << "Lookup result in reader: " << qResult;
186
187 if (not qResult.success)
188 {
189 return {};
190 }
191
192 std::map<armem::MemoryID, location::arondto::Location> locations;
193
194 const auto& locSegment =
196 locSegment.forEachEntity(
197 [&](const armem::wm::Entity& entity)
198 {
199 if (const armem::wm::EntityInstance* instance = entity.findLatestInstance())
200 {
201 locations[entity.id()].fromAron(instance->data());
202 }
203 });
204
205 ARMARX_VERBOSE << "Retrieved " << locations.size() << " locations.";
206 return locations;
207 }
208
209 std::vector<core::Location>
210 Reader::resolveLocation(const std::string& locationName,
211 const std::optional<std::string>& provider)
212 {
213 return core::util::findMatchingLocations(locations(), locationName, provider);
214 }
215
217 Reader::resolveLocationName(const std::string& locationName,
218 double minMatchRatio,
219 std::ostream* log)
220 {
221 const std::map<armem::MemoryID, location::arondto::Location> locations = queryLocations();
222 return ResolveLocationName(locations, locationName, minMatchRatio, log);
223 }
224
227 const std::map<armem::MemoryID, location::arondto::Location>& locations,
228 const std::string& locationName,
229 double minMatchRatio,
230 std::ostream* log)
231 {
232 std::map<armarx::armem::MemoryID, std::vector<std::string>> locationIdsToWords;
233 for (const auto& [id, location] : locations)
234 {
235 if (location.names.has_value())
236 {
237 locationIdsToWords[id] = location.names->recognized;
238 }
239 locationIdsToWords[id].push_back(id.entityName); // FIXME: add version with provider
240 // TODO: Split entityName by "/" and add components?
241 }
242
244
245 if (locationIdsToWords.empty())
246 {
247 std::stringstream msg;
248 msg << "Found no locations in core segment "
249 << armarx::navigation::location::coreSegmentID << " the name '" << locationName
250 << "' could be matched against.";
251
252 resolved.errorMessage = msg.str();
253 return resolved;
254 }
255
256 auto match = log ? simox::alg::fuzzy_multi_match(locationName, locationIdsToWords, *log)
257 : simox::alg::fuzzy_multi_match(locationName, locationIdsToWords);
258 ARMARX_CHECK(match.has_value());
259
260 if (match->ratio < minMatchRatio)
261 {
262 std::stringstream msg;
263 msg << "Match ratio " << match->ratio << " of best match '" << *match->word
264 << "' (location ID " << match->option
265 << ") is below the requested minimum match ratio (" << minMatchRatio << ").";
266
267 resolved.errorMessage = msg.str();
268 return resolved;
269 }
270
272 .locationId = *match->option,
273 .locationName = *match->word,
274 .matchRatio = match->ratio,
275 };
276
277 return resolved;
278 }
279
280 void
282 {
283 // for the sake of completion ...
284 // armem::client::util::SimpleReaderBase::connect();
285
286 // Wait for the memory to become available and add it as dependency.
287 ARMARX_INFO << "Reader: Waiting for memory '" << navigation::graph::coreSegmentID.memoryName
288 << "' ...";
289
290 try
291 {
292 ARMARX_INFO << "graphs ...";
293 memoryReaderGraphs = mns.useReader(
294 armem::MemoryID().withMemoryName(navigation::graph::coreSegmentID.memoryName));
295
296 ARMARX_INFO << "locations ...";
297 memoryReaderLocations = mns.useReader(
298 armem::MemoryID().withMemoryName(navigation::location::coreSegmentID.memoryName));
299
300 ARMARX_INFO << "Reader: Connected to memory '"
301 << navigation::graph::coreSegmentID.memoryName << "'";
302 }
304 {
305 ARMARX_ERROR << e.what();
306 return;
307 }
308 }
309
310} // namespace armarx::navigation::memory::client::graph
The FramedPose class.
Definition FramedPose.h:281
auto * findLatestInstance(int instanceIndex=0)
Definition EntityBase.h:356
CoreSegmentT & getCoreSegment(const std::string &name)
Definition MemoryBase.h:134
The memory name system (MNS) client.
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
EntitySelector & entities()
Start specifying entities.
ProviderSegmentSelector & all() override
Indicates that a query to the Memory Name System failed.
Definition mns.h:25
Client-side working memory core segment.
Client-side working entity instance.
Client-side working memory entity.
std::vector< armarx::navigation::core::Graph > graphs()
Definition Reader.cpp:78
std::vector< core::Location > locations()
Definition Reader.cpp:53
std::map< armem::MemoryID, location::arondto::Location > queryLocations()
Definition Reader.cpp:170
std::string propertyPrefix() const override
Definition Reader.cpp:40
Properties defaultProperties() const override
Definition Reader.cpp:46
static ResolveLocationNameResult ResolveLocationName(const std::map< armem::MemoryID, location::arondto::Location > &locations, const std::string &locationName, double minMatchRatio, std::ostream *log=nullptr)
Resolve a location by human-readable name.
Definition Reader.cpp:226
void connect(armarx::armem::client::MemoryNameSystem &mns) override
Definition Reader.cpp:281
std::vector< core::Location > resolveLocation(const std::string &locationName, const std::optional< std::string > &provider)
Definition Reader.cpp:210
ResolveLocationNameResult resolveLocationName(const std::string &locationName, double minMatchRatio, std::ostream *log=nullptr)
Resolve a location by human-readable name.
Definition Reader.cpp:217
#define ARMARX_CHECK(expression)
Shortcut for ARMARX_CHECK_EXPRESSION.
#define ARMARX_INFO
The normal logging level.
Definition Logging.h:181
#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< core::Location > findMatchingLocations(const std::vector< core::Location > &locations, const std::string &locationName, const std::optional< std::string > &provider)
Definition location.cpp:46
void resolveLocations(Graph &graph, const MemoryContainerT &locationContainer)
Definition Graph.h:145
const armem::MemoryID coreSegmentID
Definition constants.h:30
This file is part of ArmarX.
Definition constants.cpp:4
const armem::MemoryID coreSegmentID
Definition constants.h:30
This file is part of ArmarX.
Definition Reader.cpp:38
void fromAron(const arondto::Circle &dto, Circle &bo)
void fromAron(const arondto::PackagePath &dto, PackageFileLocation &bo)
Result of a QueryInput.
Definition Query.h:51
wm::Memory memory
The slice of the memory that matched the query.
Definition Query.h:58
#define ARMARX_TRACE
Definition trace.h:77