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;
54  id.coreSegmentName = objects::constants::CoreClassSegmentName;
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  {
103  ARMARX_TRACE;
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  {
128  ARMARX_TRACE;
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  {
145  ARMARX_TRACE;
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  {
167  ARMARX_TRACE;
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
192  .providerSegments().all()
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 
209  ARMARX_TRACE;
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  {
219  ARMARX_TRACE;
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)
233  .snapshots().beforeOrAtTime(timestamp);
234  // clang-format on
235  }
236  else // query all providers
237  {
238  // clang-format off
239  qb
241  .providerSegments().all()
242  .entities().withName(name)
243  .snapshots().beforeOrAtTime(timestamp);
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  {
266  ARMARX_TRACE;
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  {
313  ARMARX_TRACE;
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  {
341  ARMARX_TRACE;
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  {
363  ARMARX_TRACE;
364 
365  // clang-format off
366  const armem::wm::CoreSegment& coreSegment = memory.getCoreSegment(objects::constants::CoreClassSegmentName);
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  {
384  ARMARX_TRACE;
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
armarx::armem::articulated_object::Reader::getRobotDescription
std::optional< robot_state::description::RobotDescription > getRobotDescription(const armarx::armem::wm::Memory &memory) const
Definition: Reader.cpp:361
armarx::armem::client::query::EntitySelector::all
EntitySelector & all() override
Definition: selectors.cpp:104
armarx::armem::objects::constants::CoreInstanceSegmentName
const std::string CoreInstanceSegmentName
Definition: constants.h:27
constants.h
armarx::armem::articulated_object::Reader::get
std::optional< ArticulatedObject > get(const std::string &name, const armem::Time &timestamp, const std::optional< std::string > &providerName) const override
Definition: Reader.cpp:99
armarx::armem::articulated_object::Reader::queryState
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
ARMARX_VERBOSE
#define ARMARX_VERBOSE
Definition: Logging.h:187
armarx::armem::client::query::SnapshotSelector::latest
SnapshotSelector & latest()
Definition: selectors.cpp:30
armarx::armem::client::query::ProviderSegmentSelector::entities
EntitySelector & entities()
Start specifying entities.
Definition: selectors.cpp:135
armarx::armem::robot_state::description::RobotDescription
Definition: types.h:44
ARMARX_IMPORTANT
#define ARMARX_IMPORTANT
Definition: Logging.h:190
armarx::armem::base::detail::GetLatestInstanceMixin::getLatestInstance
auto & getLatestInstance(int instanceIndex=0)
Retrieve the latest entity instance.
Definition: lookup_mixins.h:163
armarx::armem::robot_state::Robot
Definition: types.h:126
armarx::armem::articulated_object::Reader::queryDescriptions
std::vector< robot_state::description::RobotDescription > queryDescriptions(const armem::Time &timestamp, const std::optional< std::string > &providerName) const
Definition: Reader.cpp:164
armarx::armem::wm::EntityInstance
Client-side working entity instance.
Definition: memory_definitions.h:32
armarx::armem::client::query::Builder::buildQueryInput
QueryInput buildQueryInput() const
Definition: Builder.cpp:12
armarx::armem::client::query::EntitySelector::snapshots
SnapshotSelector & snapshots()
Start specifying entity snapshots.
Definition: selectors.cpp:92
armarx::armem::robot_state::RobotState
Definition: types.h:113
objpose.h
armarx::armem::objects::constants::MemoryName
const std::string MemoryName
Definition: constants.h:26
ARMARX_CHECK_NOT_EMPTY
#define ARMARX_CHECK_NOT_EMPTY(c)
Definition: ExpressionException.h:224
armarx::armem::client::QueryResult
Result of a QueryInput.
Definition: Query.h:50
armarx::armem::robot_state::RobotState::timestamp
DateTime timestamp
Definition: types.h:118
armarx::armem::articulated_object::Reader::synchronize
bool synchronize(ArticulatedObject &obj, const armem::Time &timestamp, const std::optional< std::string > &providerName) const override
Definition: Reader.cpp:141
armarx::memory
Brief description of class memory.
Definition: memory.h:38
ARMARX_CHECK
#define ARMARX_CHECK(expression)
Shortcut for ARMARX_CHECK_EXPRESSION.
Definition: ExpressionException.h:82
armarx::armem::articulated_object::convertRobotDescription
std::optional< robot_state::description::RobotDescription > convertRobotDescription(const armem::wm::EntityInstance &instance)
Definition: utils.cpp:11
ARMARX_TRACE
#define ARMARX_TRACE
Definition: trace.h:77
armarx::armem::MemoryID
A memory ID.
Definition: MemoryID.h:47
armarx::armem::robot_state::Robot::name
std::string name() const
Definition: types.cpp:20
armarx::armem::robot_state::Robot::config
RobotState config
Definition: types.h:131
armarx::armem::client::query::Builder::coreSegments
CoreSegmentSelector & coreSegments()
Start specifying core segments.
Definition: Builder.cpp:42
ARMARX_DEBUG
#define ARMARX_DEBUG
Definition: Logging.h:184
armarx::armem::wm::CoreSegment
Client-side working memory core segment.
Definition: memory_definitions.h:119
armarx::armem::client::query::CoreSegmentSelector::withName
CoreSegmentSelector & withName(const std::string &name) override
Definition: selectors.cpp:198
error.h
armarx::armem::wm::Memory
Client-side working memory.
Definition: memory_definitions.h:133
armarx::armem::client::MemoryNameSystem::useReader
Reader useReader(const MemoryID &memoryID)
Use a memory server and get a reader for it.
Definition: MemoryNameSystem.cpp:198
armarx::armem::articulated_object::Reader::getArticulatedObjectState
std::optional< robot_state::RobotState > getArticulatedObjectState(const armarx::armem::wm::Memory &memory) const
Definition: Reader.cpp:339
aron_conversions.h
ObjectPose.h
ObjectInfo.h
ARMARX_ERROR
#define ARMARX_ERROR
Definition: Logging.h:196
armarx::armem::robot_state::Robot::instance
std::string instance
Definition: types.h:129
utils.h
memory_definitions.h
ExpressionException.h
armarx::core::time::DateTime
Represents a point in time.
Definition: DateTime.h:24
armarx::objpose::fromAron
void fromAron(const arondto::ObjectAttachmentInfo &dto, ObjectAttachmentInfo &bo)
Definition: objpose.cpp:13
armarx::armem::client::query::EntitySelector::withName
EntitySelector & withName(const std::string &name) override
Definition: selectors.cpp:112
armarx::armem::client::query::ProviderSegmentSelector::withName
ProviderSegmentSelector & withName(const std::string &name) override
Definition: selectors.cpp:155
armarx::armem::objects::constants::CoreClassSegmentName
const std::string CoreClassSegmentName
Definition: constants.h:29
armarx::objpose::ObjectPose::objectPoseGlobal
Eigen::Matrix4f objectPoseGlobal
The object pose in the global frame.
Definition: ObjectPose.h:71
ARMARX_INFO
#define ARMARX_INFO
Definition: Logging.h:181
armarx::armem::client::query::SnapshotSelector::beforeOrAtTime
SnapshotSelector & beforeOrAtTime(Time timestamp)
Definition: selectors.cpp:73
armarx::armem::articulated_object::Reader::getRobotDescriptions
std::vector< robot_state::description::RobotDescription > getRobotDescriptions(const armarx::armem::wm::Memory &memory) const
Definition: Reader.cpp:382
armarx::armem::articulated_object
Definition: ArticulatedObjectReader.cpp:26
armarx::armem::base::detail::ForEachEntityInstanceMixin::forEachInstance
bool forEachInstance(InstanceFunctionT &&func)
Definition: iteration_mixins.h:147
Time.h
Builder.h
armarx::armem::articulated_object::convertToRobotState
std::optional< robot_state::RobotState > convertToRobotState(const armem::wm::EntityInstance &instance)
Definition: Reader.cpp:311
armarx::armem::client::MemoryNameSystem
The memory name system (MNS) client.
Definition: MemoryNameSystem.h:68
armarx::armem::error::CouldNotResolveMemoryServer
Indicates that a query to the Memory Name System failed.
Definition: mns.h:24
armarx::armem::client::query::Builder
The query::Builder class provides a fluent-style specification of hierarchical queries.
Definition: Builder.h:21
armarx::armem::client::query::CoreSegmentSelector::providerSegments
ProviderSegmentSelector & providerSegments()
Start specifying provider segments.
Definition: selectors.cpp:178
armarx::armem::articulated_object::Reader::queryDescription
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
Logging.h
robot_conversions.h
ARMARX_CHECK_EQUAL
#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...
Definition: ExpressionException.h:130
ARMARX_WARNING
#define ARMARX_WARNING
Definition: Logging.h:193
aron_conversions.h
armarx::armem::base::EntityInstanceBase::data
const DataT & data() const
Definition: EntityInstanceBase.h:129
armarx::armem::articulated_object::Reader::connect
void connect(armem::client::MemoryNameSystem &memoryNameSystem)
Definition: Reader.cpp:33
armarx::objpose::ObjectPose::objectJointValues
std::map< std::string, float > objectJointValues
The object's joint values if it is articulated.
Definition: ObjectPose.h:83
armarx::armem::client::query::ProviderSegmentSelector::all
ProviderSegmentSelector & all() override
Definition: selectors.cpp:147
armarx::objpose::ObjectPose
An object pose as stored by the ObjectPoseStorage.
Definition: ObjectPose.h:33
Reader.h
armarx::armem::client::Reader::query
QueryResult query(const QueryInput &input) const
Perform a query.
Definition: Reader.cpp:32
armarx::armem::robot_state::Robot::description
description::RobotDescription description
Definition: types.h:128
armarx::objpose::ObjectPose::timestamp
DateTime timestamp
Source timestamp.
Definition: ObjectPose.h:98
armarx::split
std::vector< std::string > split(const std::string &source, const std::string &splitBy, bool trimElements=false, bool removeEmptyElements=false)
Definition: StringHelpers.cpp:38
PackagePath.h
armarx::human::MemoryID
const armem::MemoryID MemoryID
Definition: memory_ids.cpp:28