Reader.cpp
Go to the documentation of this file.
1#include "Reader.h"
2
3#include <optional>
4
5#include <Eigen/Geometry>
6
7#include <SimoxUtility/algorithm/string/string_tools.h>
8
12
15#include <RobotAPI/libraries/ArmarXObjects/aron/ObjectPose.aron.generated.h>
23#include <RobotAPI/libraries/armem_robot_state/aron/Robot.aron.generated.h>
26
27#include "utils.h"
28
30{
31
32 void
34 {
36
37 // Wait for the memory to become available and add it as dependency.
38 ARMARX_IMPORTANT << "Reader: Waiting for memory '" << objects::constants::MemoryName
39 << "' ...";
40 try
41 {
42 memoryReader = memoryNameSystem.useReader(objects::constants::MemoryName);
43 ARMARX_IMPORTANT << "Reader: Connected to memory '" << objects::constants::MemoryName
44 << "'";
45 }
47 {
48 ARMARX_ERROR << e.what();
49 return;
50 }
51
53 id.memoryName = objects::constants::MemoryName;
55 // listen to all provider segments!
56
57 // memoryNameSystem.subscribe(id, this, &Reader::updateKnownObjects);
58 }
59
60 void
61 Reader::updateKnownObject(const armem::MemoryID& snapshotId)
62 {
63 // const std::string& nameWithDataset = snapshotId.providerSegmentName;
64
65 // arondto::RobotDescription aronArticulatedObjectDescription;
66 // aronArticulatedObjectDescription.fromAron(snapshotId.);
67
68 // TODO(fabian.reister): implement
69 }
70
71 void
72 Reader::updateKnownObjects(const armem::MemoryID& subscriptionID,
73 const std::vector<armem::MemoryID>& snapshotIDs)
74 {
76
77 ARMARX_INFO << "New objects available!";
78
79 // // Query all entities from provider.
80 // armem::client::query::Builder qb;
81
82 // // clang-format off
83 // qb
84 // .coreSegments().withName(properties.coreClassSegmentName)
85 // .providerSegments().all() // TODO(fabian.reister): think about this: which authority is trustworthy?
86 // .entities().withName(name)
87 // .snapshots().atTime(timestamp);
88 // // clang-format on
89
90 // const armem::client::QueryResult qResult = memoryReader.query(qb.buildQueryInput());
91
92 // std::for_each(snapshotIDs.begin(), snapshotIDs.end(), [&](const auto & snapshotID)
93 // {
94 // updateKnownObject(snapshotID);
95 // });
96 }
97
98 std::optional<ArticulatedObject>
99 Reader::get(const std::string& name,
100 const armem::Time& timestamp,
101 const std::optional<std::string>& providerName) const
102 {
104
105 const auto splits = simox::alg::split(name, "/");
106 ARMARX_CHECK_EQUAL(splits.size(), 3) << "`name` must be of form `DATASET/NAME/INSTANCE`";
107
108 const std::string className = splits.at(0) + "/" + splits.at(1); // `DATASET/NAME`
109 const std::string instanceName = splits.at(2);
110
111 const auto description = queryDescription(className, timestamp, providerName);
112
113 if (not description)
114 {
115 ARMARX_WARNING << "Unknown object " << className;
116 return std::nullopt;
117 }
118
119 return get(*description, timestamp, instanceName, providerName);
120 }
121
124 const armem::Time& timestamp,
125 const std::string& instanceName,
126 const std::optional<std::string>& providerName) const
127 {
129
130 ArticulatedObject obj{.description = description,
131 .instance = instanceName,
132 .config = {}, // will be populated by `synchronize()`
133 .timestamp = timestamp};
134
135 ARMARX_CHECK(synchronize(obj, timestamp, providerName));
136
137 return obj;
138 }
139
140 bool
142 const armem::Time& timestamp,
143 const std::optional<std::string>& providerName) const
144 {
146
147 ARMARX_CHECK_NOT_EMPTY(obj.instance) << "An instance name must be provided!";
148
149 auto state = queryState(obj.name(), timestamp, providerName);
150
151 if (not state) /* c++20 [[unlikely]] */
152 {
153 ARMARX_WARNING << "Could not synchronize object " << obj.name() << " with instance "
154 << obj.instance << ". Provider is `" << providerName.value_or("~unset~")
155 << "`.";
156 return false;
157 }
158
159 obj.config = std::move(*state);
160 return true;
161 }
162
163 std::vector<robot_state::description::RobotDescription>
165 const std::optional<std::string>& providerName) const
166 {
168 // Query all entities from provider.
170
171
172 if (providerName.has_value()) // query single provider
173 {
174 ARMARX_VERBOSE << "Single provider query";
175 ARMARX_CHECK_NOT_EMPTY(providerName.value());
176
177 // clang-format off
178 qb
180 .providerSegments().withName(providerName.value())
181 .entities().all()
182 .snapshots().latest(); // TODO beforeTime(timestamp);
183 // clang-format on
184 }
185 else // query all providers
186 {
187 ARMARX_VERBOSE << "All provider query";
188
189 // clang-format off
190 qb
193 .entities().all()
194 .snapshots().latest(); // TODO beforeTime(timestamp);
195 // clang-format on
196 }
197
198 ARMARX_VERBOSE << "Before query";
199 const armem::client::QueryResult qResult = memoryReader.query(qb.buildQueryInput());
200 ARMARX_VERBOSE << "After query";
201
202 ARMARX_DEBUG << "Lookup result in reader: " << qResult;
203
204 if (not qResult.success) /* c++20 [[unlikely]] */
205 {
206 return {};
207 }
208
210 ARMARX_VERBOSE << "getRobotDescriptions";
211 return getRobotDescriptions(qResult.memory);
212 }
213
214 std::optional<robot_state::description::RobotDescription>
215 Reader::queryDescription(const std::string& name,
216 const armem::Time& timestamp,
217 const std::optional<std::string>& providerName) const
218 {
220
221 // Query all entities from provider.
223
224 if (providerName.has_value()) // query single provider
225 {
226 ARMARX_CHECK_NOT_EMPTY(providerName.value());
227
228 // clang-format off
229 qb
231 .providerSegments().withName(providerName.value())
232 .entities().withName(name)
234 // clang-format on
235 }
236 else // query all providers
237 {
238 // clang-format off
239 qb
242 .entities().withName(name)
244 // clang-format on
245 }
246
247
248 const armem::client::QueryResult qResult = memoryReader.query(qb.buildQueryInput());
249
250 ARMARX_DEBUG << "Lookup result in reader: " << qResult;
251
252 if (not qResult.success) /* c++20 [[unlikely]] */
253 {
254 ARMARX_WARNING << qResult.errorMessage;
255 return std::nullopt;
256 }
257
258 return getRobotDescription(qResult.memory);
259 }
260
261 std::optional<robot_state::RobotState>
262 Reader::queryState(const std::string& instanceName,
263 const armem::Time& timestamp,
264 const std::optional<std::string>& providerName) const
265 {
267
268 // Query all entities from provider.
270
271 if (not providerName.has_value())
272 {
273 // clang-format off
274 qb
276 .providerSegments().all() // no specific provider
277 .entities().withName(instanceName)
278 // .snapshots().beforeOrAtTime(timestamp);
279 .snapshots().latest();
280 // clang-format on
281 }
282 else
283 {
284 ARMARX_CHECK_NOT_EMPTY(providerName.value());
285 ARMARX_VERBOSE << "Provider is `" << providerName.value() << "`.";
286
287 // clang-format off
288 qb
290 .providerSegments().withName(providerName.value()) // agent
291 .entities().withName(instanceName)
292 // .snapshots().beforeOrAtTime(timestamp);
293 .snapshots().latest();
294 // clang-format on
295 }
296
297
298 const armem::client::QueryResult qResult = memoryReader.query(qb.buildQueryInput());
299
300 ARMARX_DEBUG << "Lookup result in reader: " << qResult;
301
302 if (not qResult.success) /* c++20 [[unlikely]] */
303 {
304 return std::nullopt;
305 }
306
307 return getArticulatedObjectState(qResult.memory);
308 }
309
310 std::optional<robot_state::RobotState>
312 {
314
315 armarx::armem::arondto::ObjectInstance aronObjectInstance;
316 try
317 {
318 aronObjectInstance.fromAron(instance.data());
319 }
320 catch (...)
321 {
322 ARMARX_WARNING << "Conversion to ObjectInstance failed!";
323 return std::nullopt;
324 }
325
326 objpose::ObjectPose objectPose;
327 objpose::fromAron(aronObjectInstance.pose, objectPose);
328
329 robot_state::RobotState robotState{.timestamp = objectPose.timestamp,
330 .globalPose =
331 Eigen::Isometry3f(objectPose.objectPoseGlobal),
332 .jointMap = objectPose.objectJointValues,
333 .proprioception = std::nullopt};
334
335 return robotState;
336 }
337
338 std::optional<robot_state::RobotState>
340 {
342
343 // clang-format off
344 const armem::wm::CoreSegment& coreSegment = memory
346 // clang-format on
347
348 try
349 {
350 const wm::EntityInstance& instance = coreSegment.getLatestInstance();
351 return convertToRobotState(instance);
352 }
353 catch (...)
354 {
355 ARMARX_VERBOSE << "Failed to obtain robot state";
356 return std::nullopt;
357 }
358 }
359
360 std::optional<robot_state::description::RobotDescription>
362 {
364
365 // clang-format off
367 // clang-format on
368
369 std::optional<wm::EntityInstance> instance;
370 coreSegment.forEachInstance([&instance](const wm::EntityInstance& i) { instance = i; });
371
372 if (instance.has_value())
373 {
374 return convertRobotDescription(instance.value());
375 }
376
377 ARMARX_DEBUG << "No robot description";
378 return std::nullopt;
379 }
380
381 std::vector<robot_state::description::RobotDescription>
383 {
385
386 const armem::wm::CoreSegment& coreSegment =
388
389 std::vector<robot_state::description::RobotDescription> descriptions;
390 coreSegment.forEachInstance(
391 [&descriptions](const wm::EntityInstance& instance)
392 {
393 ARMARX_VERBOSE << "Converting ...";
394 if (const auto robotDescription = convertRobotDescription(instance))
395 {
396 descriptions.push_back(*robotDescription);
397 }
398 });
399
400 ARMARX_VERBOSE << descriptions.size() << " descriptions";
401
402 return descriptions;
403 }
404
405} // namespace armarx::armem::articulated_object
std::string timestamp()
#define ARMARX_CHECK_NOT_EMPTY(c)
std::optional< robot_state::RobotState > queryState(const std::string &instanceName, const armem::Time &timestamp, const std::optional< std::string > &providerName) const
Definition Reader.cpp:262
void connect(armem::client::MemoryNameSystem &memoryNameSystem)
Definition Reader.cpp:33
std::optional< ArticulatedObject > get(const std::string &name, const armem::Time &timestamp, const std::optional< std::string > &providerName) const override
Definition Reader.cpp:99
bool synchronize(ArticulatedObject &obj, const armem::Time &timestamp, const std::optional< std::string > &providerName) const override
Definition Reader.cpp:141
std::vector< robot_state::description::RobotDescription > queryDescriptions(const armem::Time &timestamp, const std::optional< std::string > &providerName) const
Definition Reader.cpp:164
std::optional< robot_state::description::RobotDescription > queryDescription(const std::string &name, const armem::Time &timestamp, const std::optional< std::string > &providerName) const
Definition Reader.cpp:215
std::optional< robot_state::description::RobotDescription > getRobotDescription(const armarx::armem::wm::Memory &memory) const
Definition Reader.cpp:361
std::optional< robot_state::RobotState > getArticulatedObjectState(const armarx::armem::wm::Memory &memory) const
Definition Reader.cpp:339
std::vector< robot_state::description::RobotDescription > getRobotDescriptions(const armarx::armem::wm::Memory &memory) const
Definition Reader.cpp:382
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.
EntitySelector & withName(const std::string &name) override
SnapshotSelector & snapshots()
Start specifying entity snapshots.
Definition selectors.cpp:92
ProviderSegmentSelector & withName(const std::string &name) override
EntitySelector & entities()
Start specifying entities.
ProviderSegmentSelector & all() override
SnapshotSelector & beforeOrAtTime(Time timestamp)
Definition selectors.cpp:73
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.
Brief description of class memory.
Definition memory.h:39
#define ARMARX_CHECK(expression)
Shortcut for ARMARX_CHECK_EXPRESSION.
#define ARMARX_CHECK_EQUAL(lhs, rhs)
This macro evaluates whether lhs is equal (==) rhs and if it turns out to be false it will throw an E...
#define ARMARX_INFO
The normal logging level.
Definition Logging.h:181
#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::optional< robot_state::RobotState > convertToRobotState(const armem::wm::EntityInstance &instance)
Definition Reader.cpp:311
armarx::armem::robot_state::Robot ArticulatedObject
Definition types.h:140
armarx::armem::robot_state::description::RobotDescription ArticulatedObjectDescription
Definition types.h:138
std::optional< robot_state::description::RobotDescription > convertRobotDescription(const armem::wm::EntityInstance &instance)
Definition utils.cpp:11
const std::string CoreClassSegmentName
Definition constants.h:29
const std::string CoreInstanceSegmentName
Definition constants.h:27
armem::wm::EntityInstance EntityInstance
armarx::core::time::DateTime Time
void fromAron(const arondto::ObjectAttachmentInfo &dto, ObjectAttachmentInfo &bo)
Definition objpose.cpp:13
auto & getLatestInstance(int instanceIndex=0)
Retrieve the latest entity instance.
Result of a QueryInput.
Definition Query.h:51
wm::Memory memory
The slice of the memory that matched the query.
Definition Query.h:58
An object pose as stored by the ObjectPoseStorage.
Definition ObjectPose.h:34
DateTime timestamp
Source timestamp.
Definition ObjectPose.h:98
std::map< std::string, float > objectJointValues
The object's joint values if it is articulated.
Definition ObjectPose.h:83
Eigen::Matrix4f objectPoseGlobal
The object pose in the global frame.
Definition ObjectPose.h:71
#define ARMARX_TRACE
Definition trace.h:77