SkillProxy.cpp
Go to the documentation of this file.
1#include "SkillProxy.h"
2
3#include <chrono>
4#include <mutex>
5#include <optional>
6#include <sstream>
7#include <string>
8#include <thread>
9#include <IceUtil/Optional.h>
10
18
24#include <RobotAPI/interface/skills/SkillManagerInterface.h>
26
27namespace armarx
28{
29 namespace skills
30 {
32
33 SkillProxy::SkillProxy(const manager::dti::SkillManagerInterfacePrx& manager,
34 const SkillID& skillId) :
36 {
38 IceUtil::Optional<manager::dto::SkillDescription> description =
39 manager->getSkillDescription(skillId.toManagerIce());
40 if (description)
41 {
42 skillDescription = SkillDescription::FromIce(description.value());
43 ARMARX_CHECK(skillDescription.skillId.isFullySpecified());
44 }
45 else
46 {
47 std::stringstream reason;
48 reason << "No skill with ID " << skillId << " found";
49 throw error::SkillNotFoundException(__PRETTY_FUNCTION__, reason.str());
50 }
51
53 [this](const skills::SkillStatusUpdate& statusUpdate)
54 { this->updateSubSkillStatus(statusUpdate); });
55 }
56
57 SkillProxy::SkillProxy(const manager::dti::SkillManagerInterfacePrx& manager,
58 const SkillDescription& skillDesc) :
60 {
63
65 [this](const skills::SkillStatusUpdate& statusUpdate)
66 { this->updateSubSkillStatus(statusUpdate); });
67 }
68
69
77 {
79 }
80
83 {
84 return skillDescription.skillId;
85 }
86
88 SkillProxy::executeSkill(const std::string& executorName,
89 const aron::data::DictPtr& params) const
90 {
92 skills::manager::dto::SkillExecutionRequest req;
93 req.executorName = executorName;
94 req.parameters = aron::data::Dict::ToAronDictDTO(params);
95 req.skillId = skillDescription.skillId.toManagerIce();
96
97 auto terminatingUpdateIce = manager->executeSkill(req);
98 return TerminatedSkillStatusUpdate::FromIce(terminatingUpdateIce);
99 }
100
102 SkillProxy::executeSkillAsync(const std::string& executorName,
103 const aron::data::DictPtr& params) const
104 {
106 skills::manager::dto::SkillExecutionRequest req;
107 req.executorName = executorName;
108 req.parameters = aron::data::Dict::ToAronDictDTO(params);
109 req.skillId = skillDescription.skillId.toManagerIce();
110
111 auto execIdIce = manager->executeSkillAsync(req);
112 return SkillExecutionID::FromIce(execIdIce);
113 }
114
115 std::optional<TerminatedSkillStatusUpdate>
117 const armarx::Duration max_wait_time,
118 const armarx::Frequency check_frequency) const
119 {
121
122 std::optional<TerminatedSkillStatusUpdate> ret = std::nullopt;
123
124 int const max_tries =
125 check_frequency.toHertzDouble() * max_wait_time.toSecondsDouble() + 1e-5;
126 ARMARX_VERBOSE << VAROUT(max_tries);
127 int tries = 0;
128
129 armarx::Metronome m{check_frequency};
130
131 ARMARX_VERBOSE << "Waiting for skill " << QUOTED(executionId.toString())
132 << " to finish...";
133
134 while (true)
135 {
136 SkillStatusUpdate statusUpdate;
137
138 {
139 std::scoped_lock l{lastUpdatesMutex};
140 if (lastUpdates.count(executionId.toString()) > 0)
141 {
142 ARMARX_DEBUG << "Status update received.";
143 statusUpdate = lastUpdates.at(executionId.toString());
144 }
145 else
146 {
147 tries += 1;
148 if (tries > max_tries)
149 {
150 ARMARX_WARNING << "Skill " << QUOTED(executionId.toString())
151 << " does not seem to have been started "
152 "successfully after "
153 << max_wait_time
154 << ". "
155 "Giving up.";
156 break;
157 }
158 }
159 }
160
161 if (statusUpdate.hasBeenTerminated())
162 {
163 // TODO do conversion without ice
165 ARMARX_VERBOSE << "Got skill termination status for "
166 << statusUpdate.executionId.toString();
167 break;
168 }
169
170 m.waitForNextTick();
171 }
172
173 return ret;
174 }
175
176 void
178 {
179 ARMARX_DEBUG << VAROUT(skillDescription.skillId.skillName);
181
182 if (skillDescription.skillId.skillName == statusUpdate.executionId.skillId.skillName)
183 {
184 // TODO only update if new status
185 // if (lastUpdates.count(update.executionId) == 0 or
186 // lastUpdates.at(update.executionId) < update)
187 // {
188 // lastUpdates[update.executionId] = update;
189 // }
190 // else
191 // {
192 // ARMARX_INFO << "Ignoring.";
193 // }
194 {
195 std::scoped_lock l{lastUpdatesMutex};
196 ARMARX_DEBUG << "Updating status for skill "
197 << QUOTED(statusUpdate.executionId.toString());
198 lastUpdates[statusUpdate.executionId.toString()] = statusUpdate;
199 }
200 }
201 else
202 {
203 ARMARX_DEBUG << "Ignoring status update for skill "
204 << QUOTED(statusUpdate.executionId.skillId.skillName);
205 }
206 }
207
208 bool
210 {
212 auto r = manager->abortSkill(id.toManagerIce());
213 return r.success;
214 }
215
216 bool
218 {
220 auto r = manager->abortSkillAsync(id.toManagerIce());
221 return r.success;
222 }
223
226 {
227 return skillDescription.rootProfileDefaults;
228 }
229
230 std::optional<SkillStatusUpdate>
232 {
233 IceUtil::Optional<::armarx::skills::manager::dto::SkillStatusUpdate> statusUpdate =
234 manager->getSkillExecutionStatus(executionId.toManagerIce());
235
236 if (not statusUpdate)
237 {
238 return std::nullopt;
239 }
240
241 auto status = skills::SkillStatusUpdate::FromIce(statusUpdate.value());
242 // status.executionId.skillId.providerId.emplace().providerName = providerName;
243 return status;
244 }
245 } // namespace skills
246} // namespace armarx
#define VAROUT(x)
#define QUOTED(x)
static data::dto::DictPtr ToAronDictDTO(const PointerType &navigator)
Definition Dict.cpp:140
Represents a duration.
Definition Duration.h:17
double toSecondsDouble() const
Returns the amount of seconds.
Definition Duration.cpp:90
Represents a frequency.
Definition Frequency.h:17
Simple rate limiter for use in loops to maintain a certain frequency given a clock.
Definition Metronome.h:57
bool isFullySpecified() const
Definition SkillID.cpp:78
manager::dto::SkillID toManagerIce() const
Definition SkillID.cpp:55
std::string skillName
Definition SkillID.h:41
TerminatedSkillStatusUpdate executeSkill(const std::string &executorName, const aron::data::DictPtr &params=nullptr) const
execute a skill and block until skill terminates
SkillExecutionID executeSkillAsync(const std::string &executorName, const aron::data::DictPtr &params=nullptr) const
execute a skill. Do not block during execution
SkillDescription skillDescription
Definition SkillProxy.h:128
std::optional< TerminatedSkillStatusUpdate > join(const SkillExecutionID &executionId, armarx::Duration max_wait_time=armarx::Duration::Seconds(1), armarx::Frequency check_frequency=armarx::Frequency::Hertz(20)) const
poll execution status and block until its null or terminated
manager::dti::SkillManagerInterfacePrx manager
Definition SkillProxy.h:127
std::unordered_map< std::string, SkillStatusUpdate > lastUpdates
Definition SkillProxy.h:131
std::optional< SkillStatusUpdate > getExecutionStatus(const SkillExecutionID &executionId) const
SkillProxy()=delete
We remove the default constructor as every skill proxy requires a manager.
bool abortSkillAsync(const SkillExecutionID &executionId) const
ask skill to abort ASAP
bool abortSkill(const SkillExecutionID &executionId) const
ask skill to abort ASAP. Blocks until skill stopped
SkillID getSkillId() const
get the skill id from the skill description
aron::data::DictPtr getRootProfileParameters() const
get the default parameters of the skill. TODO: Skill profiles in memory!
void updateSubSkillStatus(const skills::SkillStatusUpdate &statusUpdate)
SkillDescription getSkillDescription() const
get the skill description
SkillUpdateManager::CallbackID callbackId
Definition SkillProxy.h:132
Indicates that a skill was not found, e.g., by the skill manager.
Definition Exception.h:46
#define ARMARX_CHECK(expression)
Shortcut for ARMARX_CHECK_EXPRESSION.
#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...
#define ARMARX_DEBUG
The logging level for output that is only interesting while debugging.
Definition Logging.h:184
#define ARMARX_WARNING
The logging level for unexpected behaviour, but not a serious problem.
Definition Logging.h:193
#define ARMARX_VERBOSE
The logging level for verbose information.
Definition Logging.h:187
std::shared_ptr< Dict > DictPtr
Definition Dict.h:42
This file is part of ArmarX.
SkillUpdateManager GlobalSkillUpdateManager
This file offers overloads of toIce() and fromIce() functions for STL container types.
static SkillDescription FromIce(const provider::dto::SkillDescription &i, const std::optional< ProviderID > &=std::nullopt)
static SkillExecutionID FromIce(const skills::manager::dto::SkillExecutionID &)
skills::manager::dto::SkillExecutionID toManagerIce() const
static SkillStatusUpdate FromIce(const provider::dto::SkillStatusUpdate &update, const std::optional< skills::ProviderID > &providerId=std::nullopt)
provider::dto::SkillStatusUpdate toProviderIce() const
static TerminatedSkillStatusUpdate FromIce(const provider::dto::SkillStatusUpdate &update, const std::optional< skills::ProviderID > &providerId=std::nullopt)