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
47namespace armarx
48{
49
54 statechartListenerProviderSegment(iceAdapter()),
55 executableSkillCoreSegment(iceAdapter()),
56 composedSkillCoreSegment(iceAdapter()),
57 profileCoreSegment(iceAdapter()),
58 skillEventCoreSegment(iceAdapter()),
59 skillExecutionRequestCoreSegment(iceAdapter())
60 {
61 }
62
65 {
68
69 const std::string prefix = "mem.";
70 statechartListenerProviderSegment.defineProperties(defs, prefix + "statechartlistener.");
71 executableSkillCoreSegment.defineProperties(defs, prefix + "executableskill.");
72 composedSkillCoreSegment.defineProperties(defs, prefix + "composedskill.");
73 profileCoreSegment.defineProperties(defs, prefix + "profile.");
74 skillExecutionRequestCoreSegment.defineProperties(defs, prefix + "executionrequest.");
75 skillEventCoreSegment.defineProperties(defs, prefix + "event.");
76
77 setMemoryName(MemoryName);
78
79 //Debug Observer:
80 defs->topic(debugObserver);
81 defs->optional(
82 p.useDebugObserver, "useDebugObserver", "Enable debug observer timing measurements");
83
84 return defs;
85 }
86
87 std::string
89 {
90 return "SkillMemory";
91 }
92
93 void
95 {
96 statechartListenerProviderSegment.init();
97 executableSkillCoreSegment.init();
98 composedSkillCoreSegment.init();
99 profileCoreSegment.init();
100 skillExecutionRequestCoreSegment.init();
101 skillEventCoreSegment.init();
102
103 ARMARX_INFO << "Using debug observer: " << p.useDebugObserver;
104 }
105
106 void
108 {
109 // Pass the debug observer to the long-term memory for timing measurements
110 if (p.useDebugObserver && debugObserver)
111 {
112 longtermMemory().setDebugObserver(debugObserver);
113 ARMARX_INFO << "Debug observer set for LTM timing measurements";
114 }
115
116 // create RemoteGUI tab and processing thread for GUI updates
117 createRemoteGuiTab();
119 }
120
121 void
125
126 void
130
131 armem::data::CommitResult
132 SkillsMemory::commit(const armem::data::Commit& commit, const Ice::Current& current)
133 {
134 // This function is overloaded to check for skill executions
135 // First pass arg to parent func to ensure that data is written into memory and that clients are notified
136 IceUtil::Time startTime = IceUtil::Time::now();
137
138 armem::data::CommitResult result = ReadWritePluginUser::commit(commit);
139
140 skills::callback::dti::SkillProviderCallbackInterfacePrx myPrx;
141 getProxy(myPrx, -1);
142
143 for (const auto& up : commit.updates)
144 {
145 if (up.entityID.coreSegmentName ==
147 {
148 for (const auto& instance : up.instancesData)
149 {
150 ARMARX_CHECK_NOT_NULL(instance);
151
152 // Safety net: convertCommit() and downstream conversions
153 // can throw on corrupted data, type mismatches, or unknown
154 // enum values. Without this catch, any such exception
155 // propagates out of the Ice servant call and crashes the
156 // entire SkillMemory component.
157 try
158 {
160 skillExecutionRequestCoreSegment.convertCommit(instance);
162 current);
163 }
164 catch (const std::exception& e)
165 {
166 ARMARX_WARNING << "Failed to process skill execution commit: "
167 << e.what()
168 << ". The local memory commit still proceeds.";
169 }
170 }
171 }
172 }
173
174 if (p.useDebugObserver and debugObserver)
175 {
176 debugObserver->setDebugChannel(
177 "SkillMemory",
178 {
179 {"Memory | t commit [ms]",
180 new Variant((IceUtil::Time::now() - startTime).toMilliSecondsDouble())},
181 });
182 }
183
184 return result;
185 }
186
187 void
188 SkillsMemory::addProvider(const skills::manager::dto::ProviderInfo& info,
189 const Ice::Current& current)
190 {
191 ARMARX_INFO << "Adding provider to skill memory: " << info.providerId.providerName;
193
194 // log skills to memory
195 auto p = skills::ProviderInfo::FromIce(info);
196 executableSkillCoreSegment.addSkillProvider(p);
197 }
198
199 void
200 SkillsMemory::removeProvider(const skills::manager::dto::ProviderID& provider,
201 const Ice::Current& current)
202 {
203 executableSkillCoreSegment.removeSkillProvider(provider.providerName);
204
205 // remove skills from memory
207 }
208
209 skills::manager::dto::SkillStatusUpdate
210 SkillsMemory::executeSkill(const skills::manager::dto::SkillExecutionRequest& info,
211 const Ice::Current& current)
212 {
213 IceUtil::Time startTime = IceUtil::Time::now();
214
216 skillExecutionRequestCoreSegment.addSkillExecutionRequest(e);
217
218 skills::manager::dto::SkillStatusUpdate result =
220
221 if (p.useDebugObserver and debugObserver)
222 {
223 debugObserver->setDebugChannel(
224 "SkillMemory",
225 {
226 {"Memory | t executeSkill [ms]",
227 new Variant((IceUtil::Time::now() - startTime).toMilliSecondsDouble())},
228 });
229 }
230
231 return result;
232 }
233
234 skills::manager::dto::SkillExecutionID
235 SkillsMemory::executeSkillAsync(const skills::manager::dto::SkillExecutionRequest& info,
236 const Ice::Current& current)
237 {
238 IceUtil::Time startTime = IceUtil::Time::now();
239
241 skillExecutionRequestCoreSegment.addSkillExecutionRequest(e);
242
243 skills::manager::dto::SkillExecutionID result =
245
246 if (p.useDebugObserver and debugObserver)
247 {
248 debugObserver->setDebugChannel(
249 "SkillMemory",
250 {
251 {"Memory | t executeSkillAsync [ms]",
252 new Variant((IceUtil::Time::now() - startTime).toMilliSecondsDouble())},
253 });
254 }
255
256 return result;
257 }
258
259 void
260 SkillsMemory::updateStatusForSkill(const skills::provider::dto::SkillStatusUpdate& update,
261 const skills::callback::dto::ProviderID& providerId,
262 const Ice::Current& current)
263 {
264 IceUtil::Time startTime = IceUtil::Time::now();
265
266 {
267 auto p = skills::ProviderID::FromIce(providerId);
268 auto u = skills::SkillStatusUpdate::FromIce(update, p);
269 skillEventCoreSegment.addSkillUpdateEvent(u);
270 }
271
272 if (p.useDebugObserver and debugObserver)
273 {
274 debugObserver->setDebugChannel(
275 "SkillMemory",
276 {
277 {"Memory | t updateStatusForSkill [ms]",
278 new Variant((IceUtil::Time::now() - startTime).toMilliSecondsDouble())},
279 });
280 }
281 }
282
283 IceUtil::Optional<skills::manager::dto::SkillStatusUpdate>
284 SkillsMemory::getSkillExecutionStatus(const skills::manager::dto::SkillExecutionID& executionId,
285 const Ice::Current& current)
286 {
287 IceUtil::Time startTime = IceUtil::Time::now();
288
289 auto eid = skills::SkillExecutionID::FromIce(executionId);
290 auto op = this->skillEventCoreSegment.getSkillStatusUpdate(eid);
291
292 if (p.useDebugObserver and debugObserver)
293 {
294 debugObserver->setDebugChannel(
295 "SkillMemory",
296 {
297 {"Memory | t getSkillStatusUpdate(eid) [ms]",
298 new Variant((IceUtil::Time::now() - startTime).toMilliSecondsDouble())},
299 });
300 }
301
302 if (op.has_value())
303 {
304 return op->toManagerIce();
305 }
306 return {};
307 }
308
309 skills::manager::dto::SkillStatusUpdateMap
310 SkillsMemory::getSkillExecutionStatuses(const Ice::Current& current)
311 {
312 IceUtil::Time startTime = IceUtil::Time::now();
313
314 skills::manager::dto::SkillStatusUpdateMap ret;
315 auto updates = this->skillEventCoreSegment.getSkillStatusUpdates();
316
317 if (p.useDebugObserver and debugObserver)
318 {
319 debugObserver->setDebugChannel(
320 "SkillMemory",
321 {
322 {"Memory | t getSkillStatusUpdates [ms]",
323 new Variant((IceUtil::Time::now() - startTime).toMilliSecondsDouble())},
324 });
325
326 startTime = IceUtil::Time::now();
327 }
328
329 for (const auto& [k, v] : updates)
330 {
331 ret.insert({k.toManagerIce(), v.toManagerIce()});
332 }
333
334 if (p.useDebugObserver and debugObserver)
335 {
336 debugObserver->setDebugChannel(
337 "SkillMemory",
338 {
339 {"Memory | t getSkillStatusUpdates.toManagerIce [ms]",
340 new Variant((IceUtil::Time::now() - startTime).toMilliSecondsDouble())},
341 });
342 }
343
344 return ret;
345 }
346
347 /*
348 * Statechart stuff
349 */
350 void
352 const ProfilerStatechartTransitionWithParameters& x,
353 const Ice::Current&)
354 {
355 statechartListenerProviderSegment.reportStatechartTransitionWithParameters(x);
356 }
357
358 void
360 const ProfilerStatechartTransitionWithParametersList& x,
361 const Ice::Current&)
362 {
363 statechartListenerProviderSegment.reportStatechartTransitionWithParametersList(x);
364 }
365
366 // RemoteGUI
367 void
368 SkillsMemory::createRemoteGuiTab()
369 {
370 using namespace armarx::RemoteGui::Client;
371
372 VBoxLayout root;
373
374 tab.clearSkillEventsButton.setLabel("Clear Skill Events WM");
375 root.addChild(tab.clearSkillEventsButton);
376
377 tab.clearSkillExecutionRequestsButton.setLabel("Clear Skill Execution Requests WM");
378 root.addChild(tab.clearSkillExecutionRequestsButton);
379
380 RemoteGui_createTab(getName(), root, &tab);
381 }
382
383 void
384 SkillsMemory::RemoteGui_update()
385 {
386 if (tab.clearSkillEventsButton.wasClicked())
387 {
388 clearSkillEventsWorkingMemory();
389 }
390 if (tab.clearSkillExecutionRequestsButton.wasClicked())
391 {
392 clearSkillExecutionRequestsWorkingMemory();
393 }
394 }
395
396 void
397 SkillsMemory::clearSkillEventsWorkingMemory()
398 {
399 bool consolidated = false;
400 const std::size_t snapshotCount = skillEventCoreSegment.clearAndConsolidate(
401 longtermMemory(), iceAdapter().workingMemory->name(), consolidated);
402
403 ARMARX_IMPORTANT << "Cleared SkillEvent working memory: removed " << snapshotCount
404 << " snapshot(s). Consolidated to LTM: "
405 << (consolidated ? "yes" : "no (recording disabled)") << ".";
406 }
407
408 void
409 SkillsMemory::clearSkillExecutionRequestsWorkingMemory()
410 {
411 bool consolidated = false;
412 const std::size_t snapshotCount = skillExecutionRequestCoreSegment.clearAndConsolidate(
413 longtermMemory(), iceAdapter().workingMemory->name(), consolidated);
414
415 ARMARX_IMPORTANT << "Cleared SkillExecutionRequest working memory: removed "
416 << snapshotCount << " snapshot(s). Consolidated to LTM: "
417 << (consolidated ? "yes" : "no (recording disabled)") << ".";
418 }
419
420 //****************************//
421 //** Fluxio related methods **//
422 //****************************//
423
424 void
425 SkillsMemory::saveSkill(const skills::manager::arondto::FluxioSkill& skill)
426 {
427 composedSkillCoreSegment.addSkill(skill);
428 }
429
430 std::optional<std::vector<skills::manager::arondto::FluxioSkill>>
432 {
433 return composedSkillCoreSegment.getSkills();
434 }
435
436 std::optional<std::vector<skills::manager::arondto::FluxioSkill>>
437 SkillsMemory::loadCompositeSkillsOfProvider(const std::string& providerId)
438 {
439 return composedSkillCoreSegment.getSkillsOfProvider(providerId);
440 }
441
442 void
443 SkillsMemory::addProfile(const skills::manager::arondto::FluxioProfile& profile)
444 {
445 profileCoreSegment.addProfile(profile);
446 }
447
448 std::optional<std::vector<skills::manager::arondto::FluxioProfile>>
450 {
451 return profileCoreSegment.getProfiles();
452 }
453} // namespace armarx
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
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:513
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)