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