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_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_CHECK_NOT_EMPTY(providerName.value());
175 
176  // clang-format off
177  qb
179  .providerSegments().withName(providerName.value())
180  .entities().all()
181  .snapshots().latest(); // TODO beforeTime(timestamp);
182  // clang-format on
183  }
184  else // query all providers
185  {
186  // clang-format off
187  qb
189  .providerSegments().all()
190  .entities().all()
191  .snapshots().latest(); // TODO beforeTime(timestamp);
192  // clang-format on
193  }
194 
195  const armem::client::QueryResult qResult = memoryReader.query(qb.buildQueryInput());
196 
197  ARMARX_DEBUG << "Lookup result in reader: " << qResult;
198 
199  if (not qResult.success) /* c++20 [[unlikely]] */
200  {
201  return {};
202  }
203 
204  return getRobotDescriptions(qResult.memory);
205  }
206 
207  std::optional<robot_state::description::RobotDescription>
208  Reader::queryDescription(const std::string& name,
209  const armem::Time& timestamp,
210  const std::optional<std::string>& providerName) const
211  {
212  ARMARX_TRACE;
213 
214  // Query all entities from provider.
216 
217  if (providerName.has_value()) // query single provider
218  {
219  ARMARX_CHECK_NOT_EMPTY(providerName.value());
220 
221  // clang-format off
222  qb
224  .providerSegments().withName(providerName.value())
225  .entities().withName(name)
226  .snapshots().beforeOrAtTime(timestamp);
227  // clang-format on
228  }
229  else // query all providers
230  {
231  // clang-format off
232  qb
234  .providerSegments().all()
235  .entities().withName(name)
236  .snapshots().beforeOrAtTime(timestamp);
237  // clang-format on
238  }
239 
240 
241  const armem::client::QueryResult qResult = memoryReader.query(qb.buildQueryInput());
242 
243  ARMARX_DEBUG << "Lookup result in reader: " << qResult;
244 
245  if (not qResult.success) /* c++20 [[unlikely]] */
246  {
247  ARMARX_WARNING << qResult.errorMessage;
248  return std::nullopt;
249  }
250 
251  return getRobotDescription(qResult.memory);
252  }
253 
254  std::optional<robot_state::RobotState>
255  Reader::queryState(const std::string& instanceName,
256  const armem::Time& timestamp,
257  const std::optional<std::string>& providerName) const
258  {
259  ARMARX_TRACE;
260 
261  // Query all entities from provider.
263 
264  if (not providerName.has_value())
265  {
266  // clang-format off
267  qb
269  .providerSegments().all() // no specific provider
270  .entities().withName(instanceName)
271  // .snapshots().beforeOrAtTime(timestamp);
272  .snapshots().latest();
273  // clang-format on
274  }
275  else
276  {
277  ARMARX_CHECK_NOT_EMPTY(providerName.value());
278  ARMARX_VERBOSE << "Provider is `" << providerName.value() << "`.";
279 
280  // clang-format off
281  qb
283  .providerSegments().withName(providerName.value()) // agent
284  .entities().withName(instanceName)
285  // .snapshots().beforeOrAtTime(timestamp);
286  .snapshots().latest();
287  // clang-format on
288  }
289 
290 
291  const armem::client::QueryResult qResult = memoryReader.query(qb.buildQueryInput());
292 
293  ARMARX_DEBUG << "Lookup result in reader: " << qResult;
294 
295  if (not qResult.success) /* c++20 [[unlikely]] */
296  {
297  return std::nullopt;
298  }
299 
300  return getArticulatedObjectState(qResult.memory);
301  }
302 
303  std::optional<robot_state::RobotState>
305  {
306  ARMARX_TRACE;
307 
308  armarx::armem::arondto::ObjectInstance aronObjectInstance;
309  try
310  {
311  aronObjectInstance.fromAron(instance.data());
312  }
313  catch (...)
314  {
315  ARMARX_WARNING << "Conversion to ObjectInstance failed!";
316  return std::nullopt;
317  }
318 
319  objpose::ObjectPose objectPose;
320  objpose::fromAron(aronObjectInstance.pose, objectPose);
321 
322  robot_state::RobotState robotState{.timestamp = objectPose.timestamp,
323  .globalPose =
324  Eigen::Isometry3f(objectPose.objectPoseGlobal),
325  .jointMap = objectPose.objectJointValues,
326  .proprioception = std::nullopt};
327 
328  return robotState;
329  }
330 
331  std::optional<robot_state::RobotState>
333  {
334  ARMARX_TRACE;
335 
336  // clang-format off
337  const armem::wm::CoreSegment& coreSegment = memory
339  // clang-format on
340 
341  try
342  {
343  const wm::EntityInstance& instance = coreSegment.getLatestInstance();
344  return convertToRobotState(instance);
345  }
346  catch (...)
347  {
348  ARMARX_FATAL << "Failed to obtain robot state";
349  return std::nullopt;
350  }
351  }
352 
353  std::optional<robot_state::description::RobotDescription>
355  {
356  ARMARX_TRACE;
357 
358  // clang-format off
359  const armem::wm::CoreSegment& coreSegment = memory.getCoreSegment(objects::constants::CoreClassSegmentName);
360  // clang-format on
361 
362  std::optional<wm::EntityInstance> instance;
363  coreSegment.forEachInstance([&instance](const wm::EntityInstance& i) { instance = i; });
364 
365  if (instance.has_value())
366  {
367  return convertRobotDescription(instance.value());
368  }
369 
370  ARMARX_DEBUG << "No robot description";
371  return std::nullopt;
372  }
373 
374  std::vector<robot_state::description::RobotDescription>
376  {
377  ARMARX_TRACE;
378 
379  const armem::wm::CoreSegment& coreSegment =
381 
382  std::vector<robot_state::description::RobotDescription> descriptions;
383  coreSegment.forEachEntity(
384  [&descriptions](const wm::Entity& entity)
385  {
386  if (not entity.empty())
387  {
388  const auto robotDescription =
389  convertRobotDescription(entity.getFirstSnapshot().getInstance(0));
390  if (robotDescription)
391  {
392  descriptions.push_back(*robotDescription);
393  }
394  }
395  });
396 
397  return descriptions;
398  }
399 
400 } // 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:354
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::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:255
armarx::armem::base::detail::MemoryContainerBase::empty
bool empty() const
Definition: MemoryContainerBase.h:44
ARMARX_VERBOSE
#define ARMARX_VERBOSE
Definition: Logging.h:180
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::robot_state::description::RobotDescription
Definition: types.h:44
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::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:11
armarx::armem::client::query::EntitySelector::snapshots
SnapshotSelector & snapshots()
Start specifying entity snapshots.
Definition: selectors.cpp:86
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::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_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::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:69
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:38
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::articulated_object::Reader::getArticulatedObjectState
std::optional< robot_state::RobotState > getArticulatedObjectState(const armarx::armem::wm::Memory &memory) const
Definition: Reader.cpp:332
aron_conversions.h
ObjectPose.h
armarx::armem::client::util::MemoryListener::subscribe
SubscriptionHandle subscribe(const MemoryID &subscriptionID, Callback Callback)
Definition: MemoryListener.cpp:116
ObjectInfo.h
ARMARX_ERROR
#define ARMARX_ERROR
Definition: Logging.h:189
armarx::armem::robot_state::Robot::instance
std::string instance
Definition: types.h:129
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::client::query::SnapshotSelector::beforeOrAtTime
SnapshotSelector & beforeOrAtTime(Time timestamp)
Definition: selectors.cpp:68
armarx::armem::articulated_object::Reader::getRobotDescriptions
std::vector< robot_state::description::RobotDescription > getRobotDescriptions(const armarx::armem::wm::Memory &memory) const
Definition: Reader.cpp:375
armarx::armem::articulated_object
Definition: ArticulatedObjectReader.cpp:25
armarx::armem::base::detail::ForEachEntityInstanceMixin::forEachInstance
bool forEachInstance(InstanceFunctionT &&func)
Definition: iteration_mixins.h:146
Time.h
Builder.h
armarx::armem::articulated_object::convertToRobotState
std::optional< robot_state::RobotState > convertToRobotState(const armem::wm::EntityInstance &instance)
Definition: Reader.cpp:304
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
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:208
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:33
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::objpose::ObjectPose
An object pose as stored by the ObjectPoseStorage.
Definition: ObjectPose.h:36
Reader.h
armarx::armem::client::Reader::query
QueryResult query(const QueryInput &input) const
Perform a query.
Definition: Reader.cpp:33
armarx::armem::robot_state::Robot::description
description::RobotDescription description
Definition: types.h:128
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