MemorySubscriber.cpp
Go to the documentation of this file.
1 #include <algorithm>
2 #include <mutex>
3 #include <type_traits>
4 
8 
14 
17 #include <armarx/navigation/core/aron/Events.aron.generated.h>
19 
20 
22 {
23 
24  MemorySubscriber::MemorySubscriber(const std::string& callerId,
26  callerId(callerId), memoryNameSystem(mns), lastMemoryPoll(armem::Time::Now())
27  {
28  const std::string memoryName = "Navigation";
29 
31  memoryReader = memoryNameSystem.getReader(armem::MemoryID().withMemoryName(memoryName));
32 
33  ARMARX_INFO << "MemorySubscriber: will handle all events newer than " << lastMemoryPoll
34  << ".";
35 
36  // subscription api
37  subscriptionID.memoryName = memoryName;
38  subscriptionID.coreSegmentName = "Events";
39  subscriptionID.providerSegmentName = callerId;
40 
42  memoryNameSystem.subscribe(subscriptionID, this, &MemorySubscriber::onEntityUpdate);
43  }
44 
45  void
46  MemorySubscriber::onEntityUpdate(const std::vector<armem::MemoryID>& snapshotIDs)
47  {
48  ARMARX_VERBOSE << "Received " << snapshotIDs.size() << " events from memory";
49  const armem::client::QueryResult qResult = memoryReader.queryMemoryIDs(snapshotIDs);
50 
51  if (not qResult.success) /* c++20 [[unlikely]] */
52  {
53  ARMARX_WARNING << deactivateSpam(0.1F) << "Memory lookup failed.";
54  return;
55  }
56 
58  handleEvents(qResult.memory);
59  }
60 
61  template <typename AronEventT, typename EventT>
62  auto
63  fromAron(const armem::wm::EntityInstance& entity, EventT& bo)
64  {
65  static_assert(std::is_base_of<armarx::aron::codegenerator::cpp::AronGeneratedClass,
66  AronEventT>::value);
67 
68  // see events::Writer::storeImpl
69  const auto dataDict = aron::data::Dict::DynamicCastAndCheck(entity.data()->getElement("data"));
70  ARMARX_CHECK_NOT_NULL(dataDict);
71  const auto dto = AronEventT::FromAron(dataDict);
72 
73  core::fromAron(dto, bo);
74  return bo;
75  }
76 
77  void
79  {
81 
82  // only one event will be handled at a time
83  std::lock_guard g{eventHandlingMtx};
84 
85  ARMARX_CHECK(memoryEntity.id().hasEntityName());
86  const auto& eventName = memoryEntity.id().entityName;
87 
88  ARMARX_INFO << "Handling event `" << eventName << "`";
89 
90  // factory
92  {
94  fromAron<core::arondto::GlobalPlanningFailedEvent>(memoryEntity, evt);
95 
97  }
98  else if (eventName == core::event_names::MovementStarted)
99  {
101  fromAron<core::arondto::MovementStartedEvent>(memoryEntity, evt);
102 
103  movementStarted(evt);
104  }
105  else if (eventName == core::event_names::GoalReached)
106  {
108  fromAron<core::arondto::GoalReachedEvent>(memoryEntity, evt);
109 
110  goalReached(evt);
111  }
112  else if (eventName == core::event_names::WaypointReached)
113  {
115  fromAron<core::arondto::WaypointReachedEvent>(memoryEntity, evt);
116 
117  waypointReached(evt);
118  }
119  else if (eventName == core::event_names::SafetyThrottlingTriggered)
120  {
122  fromAron<core::arondto::SafetyThrottlingTriggeredEvent>(memoryEntity, evt);
123 
125  }
126  else if (eventName == core::event_names::SafetyStopTriggered)
127  {
129  fromAron<core::arondto::SafetyStopTriggeredEvent>(memoryEntity, evt);
130 
131  safetyStopTriggered(evt);
132  }
133  else if (eventName == core::event_names::UserAbortTriggered)
134  {
136  fromAron<core::arondto::UserAbortTriggeredEvent>(memoryEntity, evt);
137 
138  userAbortTriggered(evt);
139  }
140  else if (eventName == core::event_names::InternalError)
141  {
143  fromAron<core::arondto::InternalErrorEvent>(memoryEntity, evt);
144 
145  internalError(evt);
146  }
147  else
148  {
149  ARMARX_WARNING << "Unknown event `" << eventName << "`";
150  }
151  }
152 
154  {
155  // ARMARX_INFO << "Removing event subscription";
156 
157  ARMARX_TRACE;
158  // memoryNameSystem.unsubscribe(subscriptionID, this, &MemorySubscriber::onEntityUpdate);
159 
160  ARMARX_INFO << "done.";
161  }
162 
163 
164  void
166  {
167  ARMARX_TRACE;
168 
169  // clang-format off
170  const armem::wm::CoreSegment& coreSegment = memory
171  .getCoreSegment("Events");
172  // clang-format on
173 
174  std::vector<armem::wm::EntityInstance> events;
175 
176  coreSegment.forEachInstance([&](const armem::wm::EntityInstance& instance)
177  { events.push_back(instance); });
178 
179  const auto sortByTimestampAsc = [](const armem::wm::EntityInstance& a,
180  const armem::wm::EntityInstance& b) -> bool
181  {
182  ARMARX_CHECK(a.id().hasTimestamp());
183  ARMARX_CHECK(b.id().hasTimestamp());
184 
185  return a.id().timestamp < b.id().timestamp;
186  };
187 
188  std::sort(events.begin(), events.end(), sortByTimestampAsc);
189 
190  std::for_each(events.begin(), events.end(), [&](const auto& event) { handleEvent(event); });
191  }
192 
193 
194 } // namespace armarx::navigation::client
armarx::armem::detail::SuccessHeader::success
bool success
Definition: SuccessHeader.h:20
ARMARX_VERBOSE
#define ARMARX_VERBOSE
Definition: Logging.h:180
armarx::navigation::client::MemorySubscriber::~MemorySubscriber
~MemorySubscriber() override
Definition: MemorySubscriber.cpp:153
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::navigation::core::event_names::MovementStarted
const std::string MovementStarted
Definition: events.h:17
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::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
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::client::MemorySubscriber::handleEvent
void handleEvent(const armem::wm::EntityInstance &memoryEntity)
Definition: MemorySubscriber.cpp:78
armarx::navigation::core::InternalErrorEvent
Event describing the occurance of an internal unhandled error.
Definition: events.h:101
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
armarx::navigation::client::SimpleEventHandler::globalPlanningFailed
void globalPlanningFailed(const core::GlobalPlanningFailedEvent &event) override
Definition: SimpleEventHandler.cpp:165
PeriodicTask.h
armarx::navigation::client::MemorySubscriber::MemorySubscriber
MemorySubscriber(const std::string &callerId, armem::client::MemoryNameSystem &mns)
Definition: MemorySubscriber.cpp:24
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::core::event_names::WaypointReached
const std::string WaypointReached
Definition: events.h:19
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
MemorySubscriber.h
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::MemorySubscriber::onEntityUpdate
void onEntityUpdate(const std::vector< armem::MemoryID > &snapshotIDs)
Definition: MemorySubscriber.cpp:46
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::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::armem::client::util::MemoryListener::subscribe
SubscriptionHandle subscribe(const MemoryID &subscriptionID, Callback Callback)
Definition: MemoryListener.cpp:116
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_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::navigation::core::WaypointReachedEvent
Event describing that a user-defined waypoint was successfully reached.
Definition: events.h:57
MemoryNameSystem.h
Logging.h
armarx::navigation::client::MemorySubscriber::handleEvents
void handleEvents(const armem::wm::Memory &memory)
Definition: MemorySubscriber.cpp:165
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::aron::bo
const std::optional< BoT > & bo
Definition: aron_conversions.h:168
armarx::navigation::core::MovementStartedEvent
Definition: events.h:41