MemoryPolling.cpp
Go to the documentation of this file.
1 #include <algorithm>
2 #include <mutex>
3 #include <type_traits>
4 
9 
15 
17 #include <armarx/navigation/core/aron/Events.aron.generated.h>
20 
21 
23 {
24 
25  MemoryPolling::MemoryPolling(const std::string& callerId,
27  callerId(callerId), memoryNameSystem(mns), lastMemoryEventReceived(armem::Time::Now())
28  {
29  const std::string memoryName = "Navigation";
30 
32  memoryReader = memoryNameSystem.getReader(armem::MemoryID().withMemoryName(memoryName));
33 
34  ARMARX_INFO << "MemoryPolling: will handle all events newer than "
35  << lastMemoryEventReceived << ".";
36 
37  // subscription api
38  armem::MemoryID subscriptionID;
39  subscriptionID.memoryName = memoryName;
40  subscriptionID.coreSegmentName = "Events";
41  subscriptionID.providerSegmentName = callerId;
42 
44  // memoryNameSystem.subscribe(subscriptionID, this, &MemoryPolling::onEntityUpdate);
46  task->start();
47  }
48 
49  void
50  MemoryPolling::onEntityUpdate(const std::vector<armem::MemoryID>& snapshotIDs)
51  {
52  ARMARX_INFO << "Received " << snapshotIDs.size() << " events from memory";
53  const armem::client::QueryResult qResult = memoryReader.queryMemoryIDs(snapshotIDs);
54 
55  if (not qResult.success) /* c++20 [[unlikely]] */
56  {
57  ARMARX_WARNING << deactivateSpam(0.1F) << "Memory lookup failed.";
58  return;
59  }
60 
62  handleEvents(qResult.memory);
63  }
64 
65  template <typename AronEventT, typename EventT>
66  auto
67  fromAron(const armem::wm::EntityInstance& entity, EventT& bo)
68  {
69  static_assert(std::is_base_of<armarx::aron::codegenerator::cpp::AronGeneratedClass,
70  AronEventT>::value);
71 
72  // see events::Writer::storeImpl
73  const auto dataDict =
74  aron::data::Dict::DynamicCastAndCheck(entity.data()->getElement("data"));
75  ARMARX_CHECK_NOT_NULL(dataDict);
76  const auto dto = AronEventT::FromAron(dataDict);
77 
78  core::fromAron(dto, bo);
79  return bo;
80  }
81 
82  void
84  {
86 
87  // only one event will be handled at a time
88  std::lock_guard g{eventHandlingMtx};
89 
90  ARMARX_CHECK(memoryEntity.id().hasEntityName());
91  const auto& eventName = memoryEntity.id().entityName;
92 
93  ARMARX_IMPORTANT << "Handling event `" << eventName << "`";
94 
95  // factory
97  {
99  fromAron<core::arondto::GlobalPlanningFailedEvent>(memoryEntity, evt);
100 
102  }
103  else if (eventName == core::event_names::MovementStarted)
104  {
106  fromAron<core::arondto::MovementStartedEvent>(memoryEntity, evt);
107 
108  movementStarted(evt);
109  }
110  else if (eventName == core::event_names::GoalReached)
111  {
113  fromAron<core::arondto::GoalReachedEvent>(memoryEntity, evt);
114 
115  goalReached(evt);
116  }
117  else if (eventName == core::event_names::WaypointReached)
118  {
120  fromAron<core::arondto::WaypointReachedEvent>(memoryEntity, evt);
121 
122  waypointReached(evt);
123  }
124  else if (eventName == core::event_names::SafetyThrottlingTriggered)
125  {
127  fromAron<core::arondto::SafetyThrottlingTriggeredEvent>(memoryEntity, evt);
128 
130  }
131  else if (eventName == core::event_names::SafetyStopTriggered)
132  {
134  fromAron<core::arondto::SafetyStopTriggeredEvent>(memoryEntity, evt);
135 
136  safetyStopTriggered(evt);
137  }
138  else if (eventName == core::event_names::UserAbortTriggered)
139  {
141  fromAron<core::arondto::UserAbortTriggeredEvent>(memoryEntity, evt);
142 
143  userAbortTriggered(evt);
144  }
145  else if (eventName == core::event_names::InternalError)
146  {
148  fromAron<core::arondto::InternalErrorEvent>(memoryEntity, evt);
149 
150  internalError(evt);
151  }
152  else
153  {
154  ARMARX_WARNING << "Unknown event `" << eventName << "`";
155  }
156  }
157 
159  {
160  ARMARX_INFO << "Stopping event polling";
161  task->stop();
162  ARMARX_INFO << "done.";
163  }
164 
165 
166  void
168  {
169  ARMARX_TRACE;
170 
171  const armem::Time now = armem::Time::Now();
172 
174  // clang-format off
175  qb
176  .coreSegments().withName("Events")
177  .providerSegments().withName(callerId)
178  .entities().all()
179  .snapshots().timeRange(lastMemoryEventReceived, now);
180  // clang-format on
181 
182  // ARMARX_DEBUG << "Polling memory events in interval "
183  // << "[" << lastMemoryPoll << ", " << now << "]";
184 
185  const armem::client::QueryResult qResult = memoryReader.query(qb.buildQueryInput());
186 
187  // ARMARX_DEBUG << "Lookup result in reader: " << qResult;
188 
189  if (not qResult.success) /* c++20 [[unlikely]] */
190  {
191  ARMARX_WARNING << deactivateSpam(0.1F) << "Memory lookup failed.";
192  return;
193  }
194 
195  handleEvents(qResult.memory);
196  }
197 
198  void
200  {
201  ARMARX_TRACE;
202 
203  // clang-format off
204  const armem::wm::CoreSegment& coreSegment = memory
205  .getCoreSegment("Events");
206  // clang-format on
207 
208  std::vector<armem::wm::EntityInstance> events;
209 
210  coreSegment.forEachInstance([&](const armem::wm::EntityInstance& instance)
211  { events.push_back(instance); });
212 
213  const auto sortByTimestampAsc = [](const armem::wm::EntityInstance& a,
214  const armem::wm::EntityInstance& b) -> bool
215  {
216  ARMARX_CHECK(a.id().hasTimestamp());
217  ARMARX_CHECK(b.id().hasTimestamp());
218 
219  return a.id().timestamp < b.id().timestamp;
220  };
221 
222  std::sort(events.begin(), events.end(), sortByTimestampAsc);
223 
224  if (not events.empty())
225  {
226  ARMARX_INFO << "Updating memory timestamp to " << events.back().id().timestamp;
227  // we add 1 µs to ensure that the events are only handled once
228  lastMemoryEventReceived = events.back().id().timestamp + armarx::Duration::MicroSeconds(1);
229  }
230 
231  std::for_each(events.begin(), events.end(), [&](const auto& event) { handleEvent(event); });
232  }
233 
234 
235 } // namespace armarx::navigation::client
armarx::armem::detail::SuccessHeader::success
bool success
Definition: SuccessHeader.h:20
armarx::armem::client::query::EntitySelector::all
EntitySelector & all() override
Definition: selectors.cpp:96
armarx::navigation::client::MemoryPolling::handleEvent
void handleEvent(const armem::wm::EntityInstance &memoryEntity)
Definition: MemoryPolling.cpp:83
armarx::armem::client::query::ProviderSegmentSelector::entities
EntitySelector & entities()
Start specifying entities.
Definition: selectors.cpp:123
armarx::armem::client::QueryResult::memory
wm::Memory memory
The slice of the memory that matched the query.
Definition: Query.h:58
armarx::navigation::client::SimpleEventHandler::safetyStopTriggered
void safetyStopTriggered(const core::SafetyStopTriggeredEvent &event) override
Will be called whenever a safety stop is triggered.
Definition: SimpleEventHandler.cpp:104
armarx::armem::client::query::SnapshotSelector::timeRange
SnapshotSelector & timeRange(Time min, Time max)
Definition: selectors.cpp:42
armarx::navigation::core::event_names::MovementStarted
const std::string MovementStarted
Definition: events.h:17
ARMARX_IMPORTANT
#define ARMARX_IMPORTANT
Definition: Logging.h:183
armarx::armem::MemoryID::providerSegmentName
std::string providerSegmentName
Definition: MemoryID.h:52
armarx::navigation::client::SimpleEventHandler::movementStarted
void movementStarted(const core::MovementStartedEvent &event) override
Definition: SimpleEventHandler.cpp:183
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::navigation::client::SimpleEventHandler::safetyThrottlingTriggered
void safetyThrottlingTriggered(const core::SafetyThrottlingTriggeredEvent &event) override
Will be called whenever safety throttling is triggered to a certain degree (configurable).
Definition: SimpleEventHandler.cpp:93
armarx::navigation::core::fromAron
void fromAron(const arondto::GlobalTrajectoryPoint &dto, GlobalTrajectoryPoint &bo)
Definition: aron_conversions.cpp:25
armarx::core::time::DateTime::Now
static DateTime Now()
Definition: DateTime.cpp:55
armarx::armem::client::query::EntitySelector::snapshots
SnapshotSelector & snapshots()
Start specifying entity snapshots.
Definition: selectors.cpp:86
MemoryID.h
ARMARX_CHECK_NOT_NULL
#define ARMARX_CHECK_NOT_NULL(ptr)
This macro evaluates whether ptr is not null and if it turns out to be false it will throw an Express...
Definition: ExpressionException.h:206
armarx::navigation::core::InternalErrorEvent
Event describing the occurance of an internal unhandled error.
Definition: events.h:101
armarx::navigation::client::MemoryPolling::MemoryPolling
MemoryPolling(const std::string &callerId, armem::client::MemoryNameSystem &mns)
Definition: MemoryPolling.cpp:25
armarx::navigation::core::SafetyThrottlingTriggeredEvent
Event desciribing that a significant safety throttling factor was reached.
Definition: events.h:68
armarx::armem
Definition: LegacyRobotStateMemoryAdapter.cpp:31
armarx::navigation::core::event_names::UserAbortTriggered
const std::string UserAbortTriggered
Definition: events.h:22
Duration.h
armarx::navigation::client::SimpleEventHandler::globalPlanningFailed
void globalPlanningFailed(const core::GlobalPlanningFailedEvent &event) override
Definition: SimpleEventHandler.cpp:165
PeriodicTask.h
armarx::navigation::client::SimpleEventHandler::internalError
void internalError(const core::InternalErrorEvent &event) override
Will be called whenever an internal error occurs.
Definition: SimpleEventHandler.cpp:126
armarx::navigation::client::MemoryPolling::handleEvents
void handleEvents(const armem::wm::Memory &memory)
Definition: MemoryPolling.cpp:199
armarx::navigation::core::event_names::WaypointReached
const std::string WaypointReached
Definition: events.h:19
MemoryPolling.h
armarx::navigation::client
This file is part of ArmarX.
Definition: ComponentPlugin.cpp:20
armarx::armem::client::QueryResult
Result of a QueryInput.
Definition: Query.h:50
armarx::aron::data::detail::SpecializedVariantBase< data::dto::Dict, Dict >::DynamicCastAndCheck
static PointerType DynamicCastAndCheck(const VariantPtr &n)
Definition: SpecializedVariant.h:135
armarx::memory
Brief description of class memory.
Definition: memory.h:39
armarx::armem::MemoryID::coreSegmentName
std::string coreSegmentName
Definition: MemoryID.h:51
armarx::navigation::client::fromAron
auto fromAron(const armem::wm::EntityInstance &entity, EventT &bo)
Definition: MemoryPolling.cpp:67
ARMARX_CHECK
#define ARMARX_CHECK(expression)
Shortcut for ARMARX_CHECK_EXPRESSION.
Definition: ExpressionException.h:82
events.h
armarx::navigation::core::event_names::SafetyStopTriggered
const std::string SafetyStopTriggered
Definition: events.h:21
armarx::armem::client::Reader::queryMemoryIDs
QueryResult queryMemoryIDs(const std::vector< MemoryID > &ids, armem::query::DataMode dataMode=armem::query::DataMode::WithData) const
Query a specific set of memory IDs.
Definition: Reader.cpp:290
deactivateSpam
SpamFilterDataPtr deactivateSpam(SpamFilterDataPtr const &spamFilter, float deactivationDurationSec, const std::string &identifier, bool deactivate)
Definition: Logging.cpp:72
ARMARX_TRACE
#define ARMARX_TRACE
Definition: trace.h:69
armarx::navigation::core::event_names::SafetyThrottlingTriggered
const std::string SafetyThrottlingTriggered
Definition: events.h:20
armarx::ctrlutil::a
double a(double t, double a0, double j)
Definition: CtrlUtil.h:45
cxxopts::value
std::shared_ptr< Value > value()
Definition: cxxopts.hpp:926
armarx::navigation::core::event_names::GlobalPlanningFailed
const std::string GlobalPlanningFailed
Definition: events.h:15
armarx::armem::MemoryID
A memory ID.
Definition: MemoryID.h:47
armarx::navigation::client::SimpleEventHandler::userAbortTriggered
void userAbortTriggered(const core::UserAbortTriggeredEvent &event) override
Will be called whenever the user aborts the current navigation.
Definition: SimpleEventHandler.cpp:115
armarx::navigation::client::MemoryPolling::~MemoryPolling
~MemoryPolling() override
Definition: MemoryPolling.cpp:158
armarx::armem::client::query::Builder::coreSegments
CoreSegmentSelector & coreSegments()
Start specifying core segments.
Definition: Builder.cpp:38
armarx::navigation::core::SafetyStopTriggeredEvent
Event describing that for security reasons, the robot was stopped completely.
Definition: events.h:84
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
armarx::armem::wm::Memory
Client-side working memory.
Definition: memory_definitions.h:133
armarx::aron::cpp::AronGeneratedClass
Definition: AronGeneratedClass.h:46
armarx::navigation::core::UserAbortTriggeredEvent
Event describing that the user aborted the current execution.
Definition: events.h:93
armarx::navigation::client::MemoryPolling::runPollMemoryEvents
void runPollMemoryEvents()
Definition: MemoryPolling.cpp:167
armarx::navigation::client::MemoryPolling::onEntityUpdate
void onEntityUpdate(const std::vector< armem::MemoryID > &snapshotIDs)
Definition: MemoryPolling.cpp:50
armarx::armem::base::detail::MemoryItem::id
MemoryID & id()
Definition: MemoryItem.h:27
armarx::armem::Time
armarx::core::time::DateTime Time
Definition: forward_declarations.h:13
armarx::navigation::core::GlobalPlanningFailedEvent
Definition: events.h:31
armarx::armem::MemoryID::entityName
std::string entityName
Definition: MemoryID.h:53
armarx::navigation::core::GoalReachedEvent
Event describing that the targeted goal was successfully reached.
Definition: events.h:49
armarx::navigation::core::event_names::GoalReached
const std::string GoalReached
Definition: events.h:18
armarx::navigation::core::event_names::InternalError
const std::string InternalError
Definition: events.h:23
memory_definitions.h
armarx::armem::MemoryID::hasEntityName
bool hasEntityName() const
Definition: MemoryID.h:121
armarx::armem::MemoryID::memoryName
std::string memoryName
Definition: MemoryID.h:50
ExpressionException.h
armarx::core::time::DateTime
Represents a point in time.
Definition: DateTime.h:24
armarx::armem::client::query::ProviderSegmentSelector::withName
ProviderSegmentSelector & withName(const std::string &name) override
Definition: selectors.cpp:140
ARMARX_INFO
#define ARMARX_INFO
Definition: Logging.h:174
aron_conversions.h
armarx::navigation::client::SimpleEventHandler::goalReached
void goalReached(const core::GoalReachedEvent &event) override
Will be called whenever the navigator reached the goal.
Definition: SimpleEventHandler.cpp:72
armarx::armem::laser_scans::constants::memoryName
const std::string memoryName
Definition: constants.h:28
armarx::armem::base::detail::ForEachEntityInstanceMixin::forEachInstance
bool forEachInstance(InstanceFunctionT &&func)
Definition: iteration_mixins.h:146
F
Definition: ExportDialogControllerTest.cpp:16
Time.h
Builder.h
armarx::navigation::client::SimpleEventHandler::waypointReached
void waypointReached(const core::WaypointReachedEvent &event) override
Will be called whenever the navigator reached a user-defined waypoint.
Definition: SimpleEventHandler.cpp:82
armarx::armem::client::MemoryNameSystem
The memory name system (MNS) client.
Definition: MemoryNameSystem.h:69
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::navigation::core::WaypointReachedEvent
Event describing that a user-defined waypoint was successfully reached.
Definition: events.h:57
MemoryNameSystem.h
armarx::PeriodicTask
Definition: ArmarXManager.h:70
Logging.h
ARMARX_WARNING
#define ARMARX_WARNING
Definition: Logging.h:186
armarx::armem::client::MemoryNameSystem::getReader
Reader getReader(const MemoryID &memoryID)
Get a reader to the given memory name.
Definition: MemoryNameSystem.cpp:177
armarx::armem::base::EntityInstanceBase::data
const DataT & data() const
Definition: EntityInstanceBase.h:129
armarx::core::time::Duration::MicroSeconds
static Duration MicroSeconds(std::int64_t microSeconds)
Constructs a duration in microseconds.
Definition: Duration.cpp:27
armarx::aron::bo
const std::optional< BoT > & bo
Definition: aron_conversions.h:166
armarx::armem::client::Reader::query
QueryResult query(const QueryInput &input) const
Perform a query.
Definition: Reader.cpp:33
armarx::navigation::core::MovementStartedEvent
Definition: events.h:41