SkillsMemory.cpp
Go to the documentation of this file.
1/*
2 * This file is part of ArmarX.
3 *
4 * ArmarX is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 *
8 * ArmarX is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * @package RobotAPI::ArmarXObjects::SkillsMemory
17 * @author Rainer Kartmann ( rainer dot kartmann at kit dot edu )
18 * @date 2020
19 * @copyright http://www.gnu.org/licenses/gpl-2.0.txt
20 * GNU General Public License
21 */
22
23#include "SkillsMemory.h"
24
25#include <vector>
26
27#include <SimoxUtility/algorithm/string.h>
28
36
39#include <RobotAPI/interface/skills/SkillManagerInterface.h>
45#include <RobotAPI/libraries/skills/core/aron/FluxioSkill.aron.generated.h>
46
48
50
51namespace armarx
52{
53
58 statechartListenerProviderSegment(iceAdapter()),
59 executableSkillCoreSegment(iceAdapter()),
60 composedSkillCoreSegment(iceAdapter()),
61 profileCoreSegment(iceAdapter()),
62 skillEventCoreSegment(iceAdapter()),
63 skillExecutionRequestCoreSegment(iceAdapter())
64 {
65 }
66
69 {
72
73 const std::string prefix = "mem.";
74 statechartListenerProviderSegment.defineProperties(defs, prefix + "statechartlistener.");
75 executableSkillCoreSegment.defineProperties(defs, prefix + "executableskill.");
76 composedSkillCoreSegment.defineProperties(defs, prefix + "composedskill.");
77 profileCoreSegment.defineProperties(defs, prefix + "profile.");
78 skillExecutionRequestCoreSegment.defineProperties(defs, prefix + "executionrequest.");
79 skillEventCoreSegment.defineProperties(defs, prefix + "event.");
80
81 setMemoryName(MemoryName);
82
83 //Debug Observer:
84 defs->topic(debugObserver);
85 defs->optional(
86 p.useDebugObserver, "useDebugObserver", "Enable debug observer timing measurements");
87
88 return defs;
89 }
90
91 std::string
93 {
94 return "SkillMemory";
95 }
96
97 void
99 {
100 statechartListenerProviderSegment.init();
101 executableSkillCoreSegment.init();
102 composedSkillCoreSegment.init();
103 profileCoreSegment.init();
104 skillExecutionRequestCoreSegment.init();
105 skillEventCoreSegment.init();
106
107 ARMARX_INFO << "Using debug observer: " << p.useDebugObserver;
108 }
109
110 void
112 {
113 // Pass the debug observer to the long-term memory for timing measurements
114 if (p.useDebugObserver && debugObserver)
115 {
116 longtermMemory().setDebugObserver(debugObserver);
117 ARMARX_INFO << "Debug observer set for LTM timing measurements";
118 }
119
120 // create RemoteGUI tab and processing thread for GUI updates
121 createRemoteGuiTab();
123 }
124
125 void
129
130 void
134
135 armem::data::CommitResult
136 SkillsMemory::commit(const armem::data::Commit& commit, const Ice::Current& current)
137 {
138 // This function is overloaded to check for skill executions
139 // First pass arg to parent func to ensure that data is written into memory and that clients are notified
140 IceUtil::Time startTime = IceUtil::Time::now();
141
142 armem::data::CommitResult result = ReadWritePluginUser::commit(commit);
143
144 skills::callback::dti::SkillProviderCallbackInterfacePrx myPrx;
145 getProxy(myPrx, -1);
146
147 for (const auto& up : commit.updates)
148 {
149 if (up.entityID.coreSegmentName ==
151 {
152 for (const auto& instance : up.instancesData)
153 {
154 ARMARX_CHECK_NOT_NULL(instance);
155
156 // Safety net: convertCommit() and downstream conversions
157 // can throw on corrupted data, type mismatches, or unknown
158 // enum values. Without this catch, any such exception
159 // propagates out of the Ice servant call and crashes the
160 // entire SkillMemory component.
161 try
162 {
164 skillExecutionRequestCoreSegment.convertCommit(instance);
166 current);
167 }
168 catch (const std::exception& e)
169 {
170 ARMARX_WARNING << "Failed to process skill execution commit: "
171 << e.what()
172 << ". The local memory commit still proceeds.";
173 }
174 }
175 }
176 }
177
178 if (p.useDebugObserver and debugObserver)
179 {
180 debugObserver->setDebugChannel(
181 "SkillMemory",
182 {
183 {"Memory | t commit [ms]",
184 new Variant((IceUtil::Time::now() - startTime).toMilliSecondsDouble())},
185 });
186 }
187
188 return result;
189 }
190
191 void
192 SkillsMemory::addProvider(const skills::manager::dto::ProviderInfo& info,
193 const Ice::Current& current)
194 {
195 ARMARX_INFO << "Adding provider to skill memory: " << info.providerId.providerName;
197
198 // log skills to memory
199 auto p = skills::ProviderInfo::FromIce(info);
200 executableSkillCoreSegment.addSkillProvider(p);
201 }
202
203 void
204 SkillsMemory::removeProvider(const skills::manager::dto::ProviderID& provider,
205 const Ice::Current& current)
206 {
207 executableSkillCoreSegment.removeSkillProvider(provider.providerName);
208
209 // remove skills from memory
211 }
212
213 skills::manager::dto::SkillStatusUpdate
214 SkillsMemory::executeSkill(const skills::manager::dto::SkillExecutionRequest& info,
215 const Ice::Current& current)
216 {
217 IceUtil::Time startTime = IceUtil::Time::now();
218
220 skillExecutionRequestCoreSegment.addSkillExecutionRequest(e);
221
222 skills::manager::dto::SkillStatusUpdate result =
224
225 if (p.useDebugObserver and debugObserver)
226 {
227 debugObserver->setDebugChannel(
228 "SkillMemory",
229 {
230 {"Memory | t executeSkill [ms]",
231 new Variant((IceUtil::Time::now() - startTime).toMilliSecondsDouble())},
232 });
233 }
234
235 return result;
236 }
237
238 skills::manager::dto::SkillExecutionID
239 SkillsMemory::executeSkillAsync(const skills::manager::dto::SkillExecutionRequest& info,
240 const Ice::Current& current)
241 {
242 IceUtil::Time startTime = IceUtil::Time::now();
243
245 skillExecutionRequestCoreSegment.addSkillExecutionRequest(e);
246
247 skills::manager::dto::SkillExecutionID result =
249
250 if (p.useDebugObserver and debugObserver)
251 {
252 debugObserver->setDebugChannel(
253 "SkillMemory",
254 {
255 {"Memory | t executeSkillAsync [ms]",
256 new Variant((IceUtil::Time::now() - startTime).toMilliSecondsDouble())},
257 });
258 }
259
260 return result;
261 }
262
263 void
264 SkillsMemory::updateStatusForSkill(const skills::provider::dto::SkillStatusUpdate& update,
265 const skills::callback::dto::ProviderID& providerId,
266 const Ice::Current& current)
267 {
268 IceUtil::Time startTime = IceUtil::Time::now();
269
270 {
271 auto p = skills::ProviderID::FromIce(providerId);
272 auto u = skills::SkillStatusUpdate::FromIce(update, p);
273 skillEventCoreSegment.addSkillUpdateEvent(u);
274 }
275
276 if (p.useDebugObserver and debugObserver)
277 {
278 debugObserver->setDebugChannel(
279 "SkillMemory",
280 {
281 {"Memory | t updateStatusForSkill [ms]",
282 new Variant((IceUtil::Time::now() - startTime).toMilliSecondsDouble())},
283 });
284 }
285 }
286
287 IceUtil::Optional<skills::manager::dto::SkillStatusUpdate>
288 SkillsMemory::getSkillExecutionStatus(const skills::manager::dto::SkillExecutionID& executionId,
289 const Ice::Current& current)
290 {
291 IceUtil::Time startTime = IceUtil::Time::now();
292
293 auto eid = skills::SkillExecutionID::FromIce(executionId);
294 auto op = this->skillEventCoreSegment.getSkillStatusUpdate(eid);
295
296 if (p.useDebugObserver and debugObserver)
297 {
298 debugObserver->setDebugChannel(
299 "SkillMemory",
300 {
301 {"Memory | t getSkillStatusUpdate(eid) [ms]",
302 new Variant((IceUtil::Time::now() - startTime).toMilliSecondsDouble())},
303 });
304 }
305
306 if (op.has_value())
307 {
308 return op->toManagerIce();
309 }
310 return {};
311 }
312
313 skills::manager::dto::SkillStatusUpdateMap
314 SkillsMemory::getSkillExecutionStatuses(const Ice::Current& current)
315 {
316 IceUtil::Time startTime = IceUtil::Time::now();
317
318 skills::manager::dto::SkillStatusUpdateMap ret;
319 auto updates = this->skillEventCoreSegment.getSkillStatusUpdates();
320
321 if (p.useDebugObserver and debugObserver)
322 {
323 debugObserver->setDebugChannel(
324 "SkillMemory",
325 {
326 {"Memory | t getSkillStatusUpdates [ms]",
327 new Variant((IceUtil::Time::now() - startTime).toMilliSecondsDouble())},
328 });
329
330 startTime = IceUtil::Time::now();
331 }
332
333 for (const auto& [k, v] : updates)
334 {
335 ret.insert({k.toManagerIce(), v.toManagerIce()});
336 }
337
338 if (p.useDebugObserver and debugObserver)
339 {
340 debugObserver->setDebugChannel(
341 "SkillMemory",
342 {
343 {"Memory | t getSkillStatusUpdates.toManagerIce [ms]",
344 new Variant((IceUtil::Time::now() - startTime).toMilliSecondsDouble())},
345 });
346 }
347
348 return ret;
349 }
350
351 /*
352 * Statechart stuff
353 */
354 void
356 const ProfilerStatechartTransitionWithParameters& x,
357 const Ice::Current&)
358 {
359 statechartListenerProviderSegment.reportStatechartTransitionWithParameters(x);
360 }
361
362 void
364 const ProfilerStatechartTransitionWithParametersList& x,
365 const Ice::Current&)
366 {
367 statechartListenerProviderSegment.reportStatechartTransitionWithParametersList(x);
368 }
369
370 // RemoteGUI
371 void
372 SkillsMemory::createRemoteGuiTab()
373 {
374 using namespace armarx::RemoteGui::Client;
375
376 VBoxLayout root;
377
378 tab.clearSkillEventsButton.setLabel("Clear Skill Events WM");
379 root.addChild(tab.clearSkillEventsButton);
380
381 tab.clearSkillExecutionRequestsButton.setLabel("Clear Skill Execution Requests WM");
382 root.addChild(tab.clearSkillExecutionRequestsButton);
383
384 RemoteGui_createTab(getName(), root, &tab);
385 }
386
387 void
388 SkillsMemory::RemoteGui_update()
389 {
390 if (tab.clearSkillEventsButton.wasClicked())
391 {
392 clearSkillEventsWorkingMemory();
393 }
394 if (tab.clearSkillExecutionRequestsButton.wasClicked())
395 {
396 clearSkillExecutionRequestsWorkingMemory();
397 }
398 }
399
400 void
401 SkillsMemory::clearSkillEventsWorkingMemory()
402 {
403 bool consolidated = false;
404 const std::size_t snapshotCount = skillEventCoreSegment.clearAndConsolidate(
405 longtermMemory(), iceAdapter().workingMemory->name(), consolidated);
406
407 ARMARX_IMPORTANT << "Cleared SkillEvent working memory: removed " << snapshotCount
408 << " snapshot(s). Consolidated to LTM: "
409 << (consolidated ? "yes" : "no (recording disabled)") << ".";
410 }
411
412 void
413 SkillsMemory::clearSkillExecutionRequestsWorkingMemory()
414 {
415 bool consolidated = false;
416 const std::size_t snapshotCount = skillExecutionRequestCoreSegment.clearAndConsolidate(
417 longtermMemory(), iceAdapter().workingMemory->name(), consolidated);
418
419 ARMARX_IMPORTANT << "Cleared SkillExecutionRequest working memory: removed "
420 << snapshotCount << " snapshot(s). Consolidated to LTM: "
421 << (consolidated ? "yes" : "no (recording disabled)") << ".";
422 }
423
424 //****************************//
425 //** Fluxio related methods **//
426 //****************************//
427
428 void
429 SkillsMemory::saveSkill(const skills::manager::arondto::FluxioSkill& skill)
430 {
431 composedSkillCoreSegment.addSkill(skill);
432 }
433
434 std::optional<std::vector<skills::manager::arondto::FluxioSkill>>
436 {
437 return composedSkillCoreSegment.getSkills();
438 }
439
440 std::optional<std::vector<skills::manager::arondto::FluxioSkill>>
441 SkillsMemory::loadCompositeSkillsOfProvider(const std::string& providerId)
442 {
443 return composedSkillCoreSegment.getSkillsOfProvider(providerId);
444 }
445
446 void
447 SkillsMemory::addProfile(const skills::manager::arondto::FluxioProfile& profile)
448 {
449 profileCoreSegment.addProfile(profile);
450 }
451
452 std::optional<std::vector<skills::manager::arondto::FluxioProfile>>
454 {
455 return profileCoreSegment.getProfiles();
456 }
457} // namespace armarx
#define ARMARX_REGISTER_COMPONENT_EXECUTABLE(ComponentT, applicationName)
Definition Decoupled.h:29
Default component property definition container.
Definition Component.h:70
std::string getConfigIdentifier()
Retrieve config identifier for this component as set in constructor.
Definition Component.cpp:90
std::string getName() const
Retrieve name of object.
Ice::ObjectPrx getProxy(long timeoutMs=0, bool waitForScheduler=true) const
Returns the proxy of this object (optionally it waits for the proxy)
void removeProvider(const skills::manager::dto::ProviderID &provider, const Ice::Current &current) override
void addProvider(const skills::manager::dto::ProviderInfo &providerInfo, const Ice::Current &current) override
skills::manager::dto::SkillExecutionID executeSkillAsync(const skills::manager::dto::SkillExecutionRequest &skillExecutionRequest, const Ice::Current &current) override
skills::manager::dto::SkillStatusUpdate executeSkill(const skills::manager::dto::SkillExecutionRequest &info, const Ice::Current &current) override
Brief description of class SkillsMemory.
void onInitComponent() override
void addProvider(const skills::manager::dto::ProviderInfo &info, const Ice::Current &current) override
void removeProvider(const skills::manager::dto::ProviderID &provider, const Ice::Current &current) override
armem::data::CommitResult commit(const armem::data::Commit &commit, const Ice::Current &) override
skills::manager::dto::SkillStatusUpdateMap getSkillExecutionStatuses(const Ice::Current &current) override
std::optional< std::vector< skills::manager::arondto::FluxioProfile > > loadProfiles() override
std::optional< std::vector< skills::manager::arondto::FluxioSkill > > loadCompositeSkillsOfProvider(const std::string &providerId) override
void onDisconnectComponent() override
armarx::PropertyDefinitionsPtr createPropertyDefinitions() override
void updateStatusForSkill(const skills::provider::dto::SkillStatusUpdate &update, const skills::callback::dto::ProviderID &id, const Ice::Current &current) override
void reportStatechartTransitionWithParameters(const ProfilerStatechartTransitionWithParameters &, const Ice::Current &) override
void addProfile(const skills::manager::arondto::FluxioProfile &profile) override
skills::manager::dto::SkillStatusUpdate executeSkill(const skills::manager::dto::SkillExecutionRequest &info, const Ice::Current &current) override
void onConnectComponent() override
IceUtil::Optional< skills::manager::dto::SkillStatusUpdate > getSkillExecutionStatus(const skills::manager::dto::SkillExecutionID &executionId, const Ice::Current &current) override
void reportStatechartTransitionWithParametersList(const ProfilerStatechartTransitionWithParametersList &, const Ice::Current &) override
void onExitComponent() override
skills::manager::dto::SkillExecutionID executeSkillAsync(const skills::manager::dto::SkillExecutionRequest &info, const Ice::Current &current) override
std::optional< std::vector< skills::manager::arondto::FluxioSkill > > loadCompositeSkills() override
void saveSkill(const skills::manager::arondto::FluxioSkill &skillt) override
std::string getDefaultName() const override
The Variant class is described here: Variants.
Definition Variant.h:224
void setDebugObserver(DebugObserverInterfacePrx observer)
Set an optional debug observer for timing measurements.
Definition MemoryBase.h:517
static ProviderID FromIce(const manager::dto::ProviderID &)
static ProviderInfo FromIce(const manager::dto::ProviderInfo &)
manager::dto::SkillExecutionRequest toManagerIce() const
static SkillExecutionRequest FromIce(const manager::dto::SkillExecutionRequest &)
#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_INFO
The normal logging level.
Definition Logging.h:181
#define ARMARX_IMPORTANT
The logging level for always important information, but expected behaviour (in contrast to ARMARX_WAR...
Definition Logging.h:190
#define ARMARX_WARNING
The logging level for unexpected behaviour, but not a serious problem.
Definition Logging.h:193
This file offers overloads of toIce() and fromIce() functions for STL container types.
IceUtil::Handle< class PropertyDefinitionContainer > PropertyDefinitionsPtr
PropertyDefinitions smart pointer type.
void RemoteGui_createTab(std::string const &name, RemoteGui::Client::Widget const &rootWidget, RemoteGui::Client::Tab *tab)
void setLabel(std::string const &label)
Definition Widgets.cpp:123
void addChild(Widget const &child)
Definition Widgets.cpp:95
static SkillExecutionID FromIce(const skills::manager::dto::SkillExecutionID &)
static SkillStatusUpdate FromIce(const provider::dto::SkillStatusUpdate &update, const std::optional< skills::ProviderID > &providerId=std::nullopt)