ViewSelection.cpp
Go to the documentation of this file.
1#include "ViewSelection.h"
2
3#include <memory>
4#include <optional>
5#include <string>
6#include <vector>
7
12
20
25#include <armarx/view_selection/gaze_targets/aron/GazeTarget.aron.generated.h>
26#include <armarx/view_selection/gaze_targets/aron/GazeTargetStatus.aron.generated.h>
29
31{
32
34 std::string providerSegmentName) :
35 memoryNameSystem(mns),
36 providerSegmentName(providerSegmentName),
37 coreSegmentID(memory::constants::ViewMemoryName,
38 memory::constants::GazeTargetCoreSegmentName),
39 statusCoreSegmentID(memory::constants::ViewMemoryName,
40 memory::constants::GazeTargetStatusCoreSegmentName)
41 {
42 ;
43 }
44
46
47 void
49 {
50 ARMARX_IMPORTANT << "ViewSelection: Waiting for memory '" << coreSegmentID << "' ...";
51 try
52 {
53 memoryWriter = memoryNameSystem.useWriter(coreSegmentID);
54 memoryReader = memoryNameSystem.useReader(coreSegmentID);
55 ARMARX_IMPORTANT << "ViewSelection: Connected to memory '" << coreSegmentID << "'";
56 }
58 {
59 ARMARX_ERROR << e.what();
60 return;
61 }
62
63 statusHandler = [&]() -> std::unique_ptr<MemoryStatusHandlerBase>
64 {
65 switch (statusDelivery)
66 {
68 return std::make_unique<MemorySubscriber>(providerSegmentName,
69 memoryNameSystem);
71 return std::make_unique<MemoryPolling>(providerSegmentName, memoryNameSystem);
72 }
73
74 return nullptr;
75 }();
76
77 waiter.emplace(*statusHandler);
78 }
79
80 std::optional<gaze_targets::GazeTarget>
81 ViewSelection::readGazeTarget(const std::string& name)
82 {
84 armem::MemoryID entityId =
85 coreSegmentID.withProviderSegmentName(providerSegmentName).withEntityName(name);
86 qb.latestEntitySnapshot(entityId);
87 auto queryResult = memoryReader.query(qb.buildQueryInput());
88
89 const auto* entityInstance = queryResult.memory.findLatestInstance(entityId);
90
91 if (entityInstance != nullptr)
92 {
94 gaze_targets::arondto::GazeTarget::FromAron(entityInstance->data()));
95
96 return gazeTarget;
97 }
98
99 ARMARX_VERBOSE << "No memory found with id:" << entityId;
100 return std::nullopt;
101 }
102
105 {
106 if (not memoryWriter)
107 {
108 ARMARX_WARNING << "Memory writer is null. Did you forget to call "
109 "ViewSelection::connect() in onConnectComponent()?";
110 return armem::MemoryID();
111 }
112 if (target.name == "")
113 {
114 ARMARX_WARNING << "The target name is empty. Did you forget to initialize it?";
115 return armem::MemoryID();
116 }
117
118 gaze_targets::arondto::GazeTarget dto;
119 toAron(dto, target);
120
121 armem::EntityUpdate update;
122 update.entityID =
123 coreSegmentID.withProviderSegmentName(providerSegmentName).withEntityName(dto.name);
124 update.referencedTime = armarx::Clock::Now();
125 update.instancesData = {dto.toAron()};
126
127 const armem::EntityUpdateResult result = memoryWriter.commit(update);
128
129 if (not result.success)
130 {
131 ARMARX_WARNING << "Failed to commit gaze target " << QUOTED(target.name) << ": "
132 << result.errorMessage;
133 return armem::MemoryID();
134 }
135
136 return result.snapshotID;
137 }
138
139 std::optional<gaze_targets::GazeTargetStatus>
140 ViewSelection::readGazeTargetStatus(const std::string& name)
141 {
143 const armem::MemoryID entityId =
144 statusCoreSegmentID.withProviderSegmentName(providerSegmentName).withEntityName(name);
145 qb.latestEntitySnapshot(entityId);
146
147 const auto queryResult = memoryReader.query(qb.buildQueryInput());
148 const auto* entityInstance = queryResult.memory.findLatestInstance(entityId);
149
150 if (entityInstance == nullptr)
151 {
152 ARMARX_VERBOSE << "No gaze target status found with id:" << entityId;
153 return std::nullopt;
154 }
155
157 fromAron(gaze_targets::arondto::GazeTargetStatus::FromAron(entityInstance->data()), status);
158
159 return status;
160 }
161
164 const armarx::Duration& timeout,
165 const std::function<bool()>& shouldAbort)
166 {
167 if (not waiter.has_value())
168 {
169 ARMARX_WARNING << "Cannot wait for gaze target " << QUOTED(target.name)
170 << ": ViewSelection::connect() was not called.";
171 return GazeTargetWaiter::Result{.status = {}, .message = "not connected"};
172 }
173
174 // Armed before the commit: the scheduler can publish the first update before commit()
175 // has even returned.
176 waiter->expect(target.name);
177
178 const armem::MemoryID gazeTargetID = commitGazeTarget(target);
179
180 if (not gazeTargetID.hasEntityName())
181 {
182 waiter->forget(target.name);
183 return GazeTargetWaiter::Result{.status = {}, .message = "commit failed"};
184 }
185
186 // Narrow from the name to this exact request, now that its ID is known.
187 waiter->bind(target.name, gazeTargetID);
188
189 return waiter->wait(target.name, timeout, shouldAbort);
190 }
191
192 void
194 {
195 gaze_targets::GazeTarget released = target;
196 released.priority =
199 released.keepInQueue = false;
200
201 commitGazeTarget(released);
202 }
203
204 void
205 ViewSelection::commitGazeTargets(const std::vector<gaze_targets::GazeTarget>& targets)
206 {
207 for (const auto& target : targets)
208 {
209 commitGazeTarget(target);
210 }
211 }
212
213} // namespace armarx::view_selection::client
#define QUOTED(x)
static DateTime Now()
Current time on the virtual clock.
Definition Clock.cpp:93
static Duration Seconds(std::int64_t seconds)
Constructs a duration in seconds.
Definition Duration.cpp:72
MemoryID withProviderSegmentName(const std::string &name) const
Definition MemoryID.cpp:417
bool hasEntityName() const
Definition MemoryID.h:121
MemoryID withEntityName(const std::string &name) const
Definition MemoryID.cpp:425
The memory name system (MNS) client.
The query::Builder class provides a fluent-style specification of hierarchical queries.
Definition Builder.h:22
void latestEntitySnapshot(const MemoryID &entityID)
Definition Builder.cpp:131
Indicates that a query to the Memory Name System failed.
Definition mns.h:25
Represents a duration.
Definition Duration.h:17
armarx::armem::MemoryID commitGazeTarget(const gaze_targets::GazeTarget &target)
std::optional< gaze_targets::GazeTargetStatus > readGazeTargetStatus(const std::string &name)
The lifecycle of the named target, as far as the scheduler has published it.
void commitGazeTargets(const std::vector< gaze_targets::GazeTarget > &targets)
void releaseGazeTarget(const gaze_targets::GazeTarget &target)
Give up a target: lowest priority, no duration, not kept in the queue.
std::optional< gaze_targets::GazeTarget > readGazeTarget(const std::string &name)
ViewSelection(armarx::armem::client::MemoryNameSystem &mns, std::string providerSegmentName)
void connect(StatusDelivery statusDelivery=StatusDelivery::Subscription)
GazeTargetWaiter::Result commitGazeTargetAndWait(const gaze_targets::GazeTarget &target, const armarx::Duration &timeout, const std::function< bool()> &shouldAbort={})
Commit a gaze target and block until the robot's gaze is fixed on it.
Business Object (BO) class of GazeTargetStatus: the lifecycle of one gaze target request,...
Business Object (BO) class of GazeTarget.
Definition GazeTarget.h:22
#define ARMARX_IMPORTANT
The logging level for always important information, but expected behaviour (in contrast to ARMARX_WAR...
Definition Logging.h:188
#define ARMARX_ERROR
The logging level for unexpected behaviour, that must be fixed.
Definition Logging.h:194
#define ARMARX_WARNING
The logging level for unexpected behaviour, but not a serious problem.
Definition Logging.h:191
#define ARMARX_VERBOSE
The logging level for verbose information.
Definition Logging.h:185
void fromAron(const T &dto, T &bo)
StatusDelivery
How gaze target status updates reach this client.
@ Polling
Queried every 100 ms. Works anywhere, at the cost of up to one poll period of latency.
@ TaskDriven
Task-Driven attention has highest priority.
This file is part of ArmarX.
Definition Human.cpp:33
void toAron(arondto::PackagePath &dto, const PackageFileLocation &bo)
void fromAron(const arondto::PackagePath &dto, PackageFileLocation &bo)
Result of an EntityUpdate.
Definition Commit.h:75
An update of an entity for a specific point in time.
Definition Commit.h:26