Reader.cpp
Go to the documentation of this file.
1 #include "Reader.h"
2 
3 #include <mutex>
4 #include <optional>
5 
6 #include <Eigen/Geometry>
7 
11 
15 #include <RobotAPI/libraries/ArmarXObjects/aron/ObjectPose.aron.generated.h>
23 #include <RobotAPI/libraries/armem_robot/aron/Robot.aron.generated.h>
26 
27 #include "utils.h"
28 
29 namespace fs = ::std::filesystem;
30 
32 {
33 
34  void
36  {
38 
39  // Wait for the memory to become available and add it as dependency.
40  ARMARX_IMPORTANT << "Reader: Waiting for memory '" << objects::constants::MemoryName
41  << "' ...";
42  try
43  {
44  memoryReader = memoryNameSystem.useReader(objects::constants::MemoryName);
45  ARMARX_IMPORTANT << "Reader: Connected to memory '" << objects::constants::MemoryName
46  << "'";
47  }
49  {
50  ARMARX_ERROR << e.what();
51  return;
52  }
53 
55  id.memoryName = objects::constants::MemoryName;
56  id.coreSegmentName = objects::constants::CoreClassSegmentName;
57  // listen to all provider segments!
58 
59  memoryNameSystem.subscribe(id, this, &Reader::updateKnownObjects);
60  }
61 
62  void
63  Reader::updateKnownObject(const armem::MemoryID& snapshotId)
64  {
65  // const std::string& nameWithDataset = snapshotId.providerSegmentName;
66 
67  // arondto::RobotDescription aronArticulatedObjectDescription;
68  // aronArticulatedObjectDescription.fromAron(snapshotId.);
69 
70  // TODO(fabian.reister): implement
71  }
72 
73  void
74  Reader::updateKnownObjects(const armem::MemoryID& subscriptionID,
75  const std::vector<armem::MemoryID>& snapshotIDs)
76  {
78 
79  ARMARX_INFO << "New objects available!";
80 
81  // // Query all entities from provider.
82  // armem::client::query::Builder qb;
83 
84  // // clang-format off
85  // qb
86  // .coreSegments().withName(properties.coreClassSegmentName)
87  // .providerSegments().all() // TODO(fabian.reister): think about this: which authority is trustworthy?
88  // .entities().withName(name)
89  // .snapshots().atTime(timestamp);
90  // // clang-format on
91 
92  // const armem::client::QueryResult qResult = memoryReader.query(qb.buildQueryInput());
93 
94  // std::for_each(snapshotIDs.begin(), snapshotIDs.end(), [&](const auto & snapshotID)
95  // {
96  // updateKnownObject(snapshotID);
97  // });
98  }
99 
100  std::optional<ArticulatedObject>
101  Reader::get(const std::string& name,
102  const armem::Time& timestamp,
103  const std::optional<std::string>& providerName)
104  {
105  ARMARX_TRACE;
106 
107  const auto splits = simox::alg::split(name, "/");
108  ARMARX_CHECK_EQUAL(splits.size(), 3) << "`name` must be of form `DATASET/NAME/INSTANCE`";
109 
110  const std::string className = splits.at(0) + "/" + splits.at(1); // `DATASET/NAME`
111  const std::string instanceName = splits.at(2);
112 
113  const auto description = queryDescription(className, timestamp, providerName);
114 
115  if (not description)
116  {
117  ARMARX_WARNING << "Unknown object " << className;
118  return std::nullopt;
119  }
120 
121  return get(*description, timestamp, instanceName, providerName);
122  }
123 
126  const armem::Time& timestamp,
127  const std::string& instanceName,
128  const std::optional<std::string>& providerName)
129  {
130  ARMARX_TRACE;
131 
132  ArticulatedObject obj{.description = description,
133  .instance = instanceName,
134  .config = {}, // will be populated by `synchronize()`
135  .timestamp = timestamp};
136 
137  ARMARX_CHECK(synchronize(obj, timestamp, providerName));
138 
139  return obj;
140  }
141 
142  bool
144  const armem::Time& timestamp,
145  const std::optional<std::string>& providerName)
146  {
147  ARMARX_TRACE;
148 
149  ARMARX_CHECK_NOT_EMPTY(obj.instance) << "An instance name must be provided!";
150 
151  auto state = queryState(obj.name(), timestamp, providerName);
152 
153  if (not state) /* c++20 [[unlikely]] */
154  {
155  ARMARX_WARNING << "Could not synchronize object " << obj.name() << " with instance "
156  << obj.instance << ". Provider is `" << providerName.value_or("~unset~")
157  << "`.";
158  return false;
159  }
160 
161  obj.config = std::move(*state);
162  return true;
163  }
164 
165  std::vector<robot::RobotDescription>
167  const std::optional<std::string>& providerName)
168  {
169  ARMARX_TRACE;
170  // Query all entities from provider.
172 
173 
174  if (providerName.has_value()) // query single provider
175  {
176  ARMARX_CHECK_NOT_EMPTY(providerName.value());
177 
178  // clang-format off
179  qb
181  .providerSegments().withName(providerName.value())
182  .entities().all()
183  .snapshots().latest(); // TODO beforeTime(timestamp);
184  // clang-format on
185  }
186  else // query all providers
187  {
188  // clang-format off
189  qb
191  .providerSegments().all()
192  .entities().all()
193  .snapshots().latest(); // TODO beforeTime(timestamp);
194  // clang-format on
195  }
196 
197  const armem::client::QueryResult qResult = memoryReader.query(qb.buildQueryInput());
198 
199  ARMARX_DEBUG << "Lookup result in reader: " << qResult;
200 
201  if (not qResult.success) /* c++20 [[unlikely]] */
202  {
203  return {};
204  }
205 
206  return getRobotDescriptions(qResult.memory);
207  }
208 
209  std::optional<robot::RobotDescription>
210  Reader::queryDescription(const std::string& name,
211  const armem::Time& timestamp,
212  const std::optional<std::string>& providerName)
213  {
214  ARMARX_TRACE;
215 
216  // Query all entities from provider.
218 
219  if (providerName.has_value()) // query single provider
220  {
221  ARMARX_CHECK_NOT_EMPTY(providerName.value());
222 
223  // clang-format off
224  qb
226  .providerSegments().withName(providerName.value())
227  .entities().withName(name)
228  .snapshots().beforeOrAtTime(timestamp);
229  // clang-format on
230  }
231  else // query all providers
232  {
233  // clang-format off
234  qb
236  .providerSegments().all()
237  .entities().withName(name)
238  .snapshots().beforeOrAtTime(timestamp);
239  // clang-format on
240  }
241 
242 
243  const armem::client::QueryResult qResult = memoryReader.query(qb.buildQueryInput());
244 
245  ARMARX_DEBUG << "Lookup result in reader: " << qResult;
246 
247  if (not qResult.success) /* c++20 [[unlikely]] */
248  {
249  ARMARX_WARNING << qResult.errorMessage;
250  return std::nullopt;
251  }
252 
253  return getRobotDescription(qResult.memory);
254  }
255 
256  std::optional<robot::RobotState>
257  Reader::queryState(const std::string& instanceName,
258  const armem::Time& timestamp,
259  const std::optional<std::string>& providerName)
260  {
261  ARMARX_TRACE;
262 
263  // Query all entities from provider.
265 
266  if (not providerName.has_value())
267  {
268  // clang-format off
269  qb
271  .providerSegments().all() // no specific provider
272  .entities().withName(instanceName)
273  // .snapshots().beforeOrAtTime(timestamp);
274  .snapshots().latest();
275  // clang-format on
276  }
277  else
278  {
279  ARMARX_CHECK_NOT_EMPTY(providerName.value());
280  ARMARX_VERBOSE << "Provider is `" << providerName.value() << "`.";
281 
282  // clang-format off
283  qb
285  .providerSegments().withName(providerName.value()) // agent
286  .entities().withName(instanceName)
287  // .snapshots().beforeOrAtTime(timestamp);
288  .snapshots().latest();
289  // clang-format on
290  }
291 
292 
293  const armem::client::QueryResult qResult = memoryReader.query(qb.buildQueryInput());
294 
295  ARMARX_DEBUG << "Lookup result in reader: " << qResult;
296 
297  if (not qResult.success) /* c++20 [[unlikely]] */
298  {
299  return std::nullopt;
300  }
301 
302  return getArticulatedObjectState(qResult.memory);
303  }
304 
305  std::optional<robot::RobotState>
307  {
308  ARMARX_TRACE;
309 
310  armarx::armem::arondto::ObjectInstance aronObjectInstance;
311  try
312  {
313  aronObjectInstance.fromAron(instance.data());
314  }
315  catch (...)
316  {
317  ARMARX_WARNING << "Conversion to ObjectInstance failed!";
318  return std::nullopt;
319  }
320 
321  objpose::ObjectPose objectPose;
322  objpose::fromAron(aronObjectInstance.pose, objectPose);
323 
324  robot::RobotState robotState{.timestamp = objectPose.timestamp,
325  .globalPose = Eigen::Affine3f(objectPose.objectPoseGlobal),
326  .jointMap = objectPose.objectJointValues,
327  .proprioception = std::nullopt};
328 
329  return robotState;
330  }
331 
332  std::optional<robot::RobotState>
334  {
335  ARMARX_TRACE;
336 
337  // clang-format off
338  const armem::wm::CoreSegment& coreSegment = memory
340  // clang-format on
341 
342  try
343  {
344  const wm::EntityInstance& instance = coreSegment.getLatestInstance();
345  return convertToRobotState(instance);
346  }
347  catch (...)
348  {
349  ARMARX_FATAL << "Failed to obtain robot state";
350  return std::nullopt;
351  }
352  }
353 
354  std::optional<robot::RobotDescription>
356  {
357  ARMARX_TRACE;
358 
359  // clang-format off
360  const armem::wm::CoreSegment& coreSegment = memory.getCoreSegment(objects::constants::CoreClassSegmentName);
361  // clang-format on
362 
363  std::optional<wm::EntityInstance> instance;
364  coreSegment.forEachInstance([&instance](const wm::EntityInstance& i) { instance = i; });
365 
366  if (instance.has_value())
367  {
368  return convertRobotDescription(instance.value());
369  }
370 
371  ARMARX_DEBUG << "No robot description";
372  return std::nullopt;
373  }
374 
375  std::vector<robot::RobotDescription>
377  {
378  ARMARX_TRACE;
379 
380  const armem::wm::CoreSegment& coreSegment =
382 
383  std::vector<robot::RobotDescription> descriptions;
384  coreSegment.forEachEntity(
385  [&descriptions](const wm::Entity& entity)
386  {
387  if (not entity.empty())
388  {
389  const auto robotDescription =
390  convertRobotDescription(entity.getFirstSnapshot().getInstance(0));
391  if (robotDescription)
392  {
393  descriptions.push_back(*robotDescription);
394  }
395  }
396  });
397 
398  return descriptions;
399  }
400 
401 } // namespace armarx::armem::articulated_object
armarx::armem::client::query::EntitySelector::all
EntitySelector & all() override
Definition: selectors.cpp:96
armarx::armem::objects::constants::CoreInstanceSegmentName
const std::string CoreInstanceSegmentName
Definition: constants.h:27
constants.h
armarx::armem::base::detail::MemoryContainerBase::empty
bool empty() const
Definition: MemoryContainerBase.h:44
ARMARX_VERBOSE
#define ARMARX_VERBOSE
Definition: Logging.h:180
armarx::armem::articulated_object::Reader::getArticulatedObjectState
std::optional< robot::RobotState > getArticulatedObjectState(const armarx::armem::wm::Memory &memory) const
Definition: Reader.cpp:333
armarx::armem::client::query::SnapshotSelector::latest
SnapshotSelector & latest()
Definition: selectors.cpp:28
armarx::armem::client::query::ProviderSegmentSelector::entities
EntitySelector & entities()
Start specifying entities.
Definition: selectors.cpp:123
armarx::armem::articulated_object::Reader::synchronize
bool synchronize(ArticulatedObject &obj, const armem::Time &timestamp, const std::optional< std::string > &providerName) override
Definition: Reader.cpp:143
ARMARX_IMPORTANT
#define ARMARX_IMPORTANT
Definition: Logging.h:183
armarx::armem::base::detail::GetLatestInstanceMixin::getLatestInstance
auto & getLatestInstance(int instanceIndex=0)
Retrieve the latest entity instance.
Definition: lookup_mixins.h:163
armarx::armem::wm::EntityInstance
Client-side working entity instance.
Definition: memory_definitions.h:32
armarx::armem::robot::Robot
Definition: types.h:68
armarx::armem::client::query::Builder::buildQueryInput
QueryInput buildQueryInput() const
Definition: Builder.cpp:11
armarx::armem::client::query::EntitySelector::snapshots
SnapshotSelector & snapshots()
Start specifying entity snapshots.
Definition: selectors.cpp:86
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::articulated_object::Reader::queryDescriptions
std::vector< robot::RobotDescription > queryDescriptions(const armem::Time &timestamp, const std::optional< std::string > &providerName)
Definition: Reader.cpp:166
armarx::armem::robot::Robot::name
std::string name() const
Definition: types.cpp:16
armarx::armem::articulated_object::Reader::queryState
std::optional< robot::RobotState > queryState(const std::string &instanceName, const armem::Time &timestamp, const std::optional< std::string > &providerName)
Definition: Reader.cpp:257
armarx::armem::server::wm::Entity
Definition: memory_definitions.h:30
armarx::memory
Brief description of class memory.
Definition: memory.h:39
armarx::armem::base::detail::ForEachEntityMixin::forEachEntity
bool forEachEntity(FunctionT &&func)
Definition: iteration_mixins.h:258
armarx::armem::articulated_object::Reader::get
std::optional< ArticulatedObject > get(const std::string &name, const armem::Time &timestamp, const std::optional< std::string > &providerName) override
Definition: Reader.cpp:101
armarx::armem::articulated_object::convertRobotDescription
std::optional< robot::RobotDescription > convertRobotDescription(const armem::wm::EntityInstance &instance)
Definition: utils.cpp:10
ARMARX_CHECK
#define ARMARX_CHECK(expression)
Shortcut for ARMARX_CHECK_EXPRESSION.
Definition: ExpressionException.h:82
ARMARX_FATAL
#define ARMARX_FATAL
Definition: Logging.h:192
armarx::armem::robot::RobotState
Definition: types.h:54
armarx::armem::robot::RobotDescription
Definition: types.h:17
ARMARX_TRACE
#define ARMARX_TRACE
Definition: trace.h:69
armarx::armem::articulated_object::convertToRobotState
std::optional< robot::RobotState > convertToRobotState(const armem::wm::EntityInstance &instance)
Definition: Reader.cpp:306
armarx::armem::MemoryID
A memory ID.
Definition: MemoryID.h:47
armarx::armem::client::query::Builder::coreSegments
CoreSegmentSelector & coreSegments()
Start specifying core segments.
Definition: Builder.cpp:38
armarx::armem::robot::Robot::description
RobotDescription description
Definition: types.h:70
ARMARX_DEBUG
#define ARMARX_DEBUG
Definition: Logging.h:177
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:177
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:184
armarx::armem::robot::Robot::instance
std::string instance
Definition: types.h:71
ObjectPose.h
armarx::armem::client::util::MemoryListener::subscribe
SubscriptionHandle subscribe(const MemoryID &subscriptionID, Callback Callback)
Definition: MemoryListener.cpp:116
ObjectInfo.h
armarx::armem::articulated_object::Reader::getRobotDescriptions
std::vector< robot::RobotDescription > getRobotDescriptions(const armarx::armem::wm::Memory &memory) const
Definition: Reader.cpp:376
ARMARX_ERROR
#define ARMARX_ERROR
Definition: Logging.h:189
aron_conversions.h
utils.h
memory_definitions.h
ExpressionException.h
Commit.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:15
armarx::armem::client::query::EntitySelector::withName
EntitySelector & withName(const std::string &name) override
Definition: selectors.cpp:103
armarx::armem::client::query::ProviderSegmentSelector::withName
ProviderSegmentSelector & withName(const std::string &name) override
Definition: selectors.cpp:140
armarx::armem::objects::constants::CoreClassSegmentName
const std::string CoreClassSegmentName
Definition: constants.h:28
armarx::objpose::ObjectPose::objectPoseGlobal
Eigen::Matrix4f objectPoseGlobal
The object pose in the global frame.
Definition: ObjectPose.h:73
ARMARX_INFO
#define ARMARX_INFO
Definition: Logging.h:174
armarx::armem::articulated_object::Reader::queryDescription
std::optional< robot::RobotDescription > queryDescription(const std::string &name, const armem::Time &timestamp, const std::optional< std::string > &providerName)
Definition: Reader.cpp:210
armarx::armem::client::query::SnapshotSelector::beforeOrAtTime
SnapshotSelector & beforeOrAtTime(Time timestamp)
Definition: selectors.cpp:68
armarx::armem::articulated_object
Definition: ArticulatedObjectReader.cpp:24
armarx::armem::base::detail::ForEachEntityInstanceMixin::forEachInstance
bool forEachInstance(InstanceFunctionT &&func)
Definition: iteration_mixins.h:146
Time.h
Builder.h
armarx::armem::client::MemoryNameSystem
The memory name system (MNS) client.
Definition: MemoryNameSystem.h:69
armarx::armem::error::CouldNotResolveMemoryServer
Indicates that a query to the Memory Name System failed.
Definition: mns.h:26
armarx::armem::client::query::Builder
The query::Builder class provides a fluent-style specification of hierarchical queries.
Definition: Builder.h:22
armarx::armem::client::query::CoreSegmentSelector::providerSegments
ProviderSegmentSelector & providerSegments()
Start specifying provider segments.
Definition: selectors.cpp:160
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:186
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:35
armarx::objpose::ObjectPose::objectJointValues
std::map< std::string, float > objectJointValues
The object's joint values if it is articulated.
Definition: ObjectPose.h:85
armarx::armem::client::query::ProviderSegmentSelector::all
ProviderSegmentSelector & all() override
Definition: selectors.cpp:133
armarx::armem::robot::Robot::config
RobotState config
Definition: types.h:73
armarx::armem::robot::RobotState::timestamp
DateTime timestamp
Definition: types.h:59
armarx::objpose::ObjectPose
An object pose as stored by the ObjectPoseStorage.
Definition: ObjectPose.h:36
armarx::armem::articulated_object::Reader::getRobotDescription
std::optional< robot::RobotDescription > getRobotDescription(const armarx::armem::wm::Memory &memory) const
Definition: Reader.cpp:355
Reader.h
armarx::armem::client::Reader::query
QueryResult query(const QueryInput &input) const
Perform a query.
Definition: Reader.cpp:33
armarx::objpose::ObjectPose::timestamp
DateTime timestamp
Source timestamp.
Definition: ObjectPose.h:100
armarx::split
std::vector< std::string > split(const std::string &source, const std::string &splitBy, bool trimElements=false, bool removeEmptyElements=false)
Definition: StringHelpers.cpp:36
PackagePath.h
armarx::human::MemoryID
const armem::MemoryID MemoryID
Definition: memory_ids.cpp:29