Skip to content
Snippets Groups Projects
Commit 24955941 authored by Christian Dreher's avatar Christian Dreher
Browse files

Merge branch 'feature/skillMemoryGUI' into 'master'

Urgent Skill Manipulation Features in SkillMemoryGUI

See merge request sw/armarx/robot-api!401
parents fbac38ee 17972d59
No related branches found
No related tags found
No related merge requests found
Showing
with 704 additions and 237 deletions
...@@ -27,6 +27,7 @@ set(SOURCES ...@@ -27,6 +27,7 @@ set(SOURCES
aronTreeWidget/modal/AronTreeWidgetModal.cpp aronTreeWidget/modal/AronTreeWidgetModal.cpp
ColorPalettes.cpp ColorPalettes.cpp
SkillManagerMonitorWidgetController.cpp SkillManagerMonitorWidgetController.cpp
PeriodicUpdateWidget.cpp
) )
set(HEADERS set(HEADERS
...@@ -53,6 +54,7 @@ set(HEADERS ...@@ -53,6 +54,7 @@ set(HEADERS
aronTreeWidget/modal/bool/AronTreeWidgetBoolInputModalController.h aronTreeWidget/modal/bool/AronTreeWidgetBoolInputModalController.h
ColorPalettes.h ColorPalettes.h
SkillManagerMonitorWidgetController.h SkillManagerMonitorWidgetController.h
PeriodicUpdateWidget.h
) )
set(GUI_UIS set(GUI_UIS
......
#include "PeriodicUpdateWidget.h"
#include <cmath>
#include <QCheckBox>
#include <QDoubleSpinBox>
#include <QHBoxLayout>
#include <QPushButton>
#include <QTimer>
namespace armarx
{
PeriodicUpdateWidget::PeriodicUpdateWidget(double frequency, double maxFrequency)
{
setSizePolicy(QSizePolicy::Policy::Minimum, QSizePolicy::Policy::Minimum);
QLayout* vlayout = new QVBoxLayout();
QLayout* hlayout = new QHBoxLayout();
this->setLayout(vlayout);
const int margin = 0;
hlayout->setContentsMargins(margin, margin, margin, margin);
_updateButton = new QPushButton("Update", this);
_autoCheckBox = new QCheckBox("Auto Update", this);
_frequencySpinBox = new QDoubleSpinBox(this);
_frequencySpinBox->setValue(frequency);
_frequencySpinBox->setMinimum(0);
_frequencySpinBox->setMaximum(maxFrequency);
_frequencySpinBox->setSingleStep(0.5);
_frequencySpinBox->setSuffix(" Hz");
hlayout->addWidget(_updateButton);
hlayout->addWidget(_autoCheckBox);
hlayout->addWidget(_frequencySpinBox);
vlayout->addItem(hlayout);
_timer = new QTimer(this);
_updateTimerFrequency();
_frequencySpinBox->setEnabled(_autoCheckBox->isChecked());
// Private connections.
connect(_autoCheckBox, &QCheckBox::toggled, this, &This::_toggleAutoUpdates);
connect(_frequencySpinBox,
&QDoubleSpinBox::editingFinished,
this,
&This::_updateTimerFrequency);
// Public connections.
connect(_updateButton, &QPushButton::pressed, this, &This::updateSingle);
connect(_timer, &QTimer::timeout, this, &This::updatePeriodic);
connect(this, &This::updateSingle, this, &This::update);
connect(this, &This::updatePeriodic, this, &This::update);
// See `startTimerIfEnabled` for the signal reasoning.
// qOverload is required because `QTimer::start()` is overloaded.
connect(this, &This::startTimerSignal, _timer, qOverload<>(&QTimer::start));
connect(this, &This::stopTimerSignal, _timer, &QTimer::stop);
}
QPushButton*
PeriodicUpdateWidget::updateButton()
{
return _updateButton;
}
int
PeriodicUpdateWidget::getUpdateIntervalMs() const
{
return static_cast<int>(std::round(1000 / _frequencySpinBox->value()));
}
void
PeriodicUpdateWidget::startTimerIfEnabled()
{
/* A QTimer can only be started and stopped within its own thread (the thread for which
* it has the greatest affinity). Since this method can be called from any thread, we
* need to take a detour through these signals, which can be emitted from any thread and
* will always be caught in this object's (and thus the timer's) native thread.
*/
if (_autoCheckBox->isChecked())
{
emit startTimerSignal();
}
else
{
emit stopTimerSignal();
}
}
void
PeriodicUpdateWidget::stopTimer()
{
// See `startTimerIfEnabled` for the signal reasoning.
emit stopTimerSignal();
}
void
PeriodicUpdateWidget::_updateTimerFrequency()
{
_timer->setInterval(getUpdateIntervalMs());
}
void
PeriodicUpdateWidget::_toggleAutoUpdates(bool enabled)
{
// This method is already a slot, so it doesn't need to use the timer signals.
_frequencySpinBox->setEnabled(enabled);
if (enabled)
{
_timer->start();
}
else
{
_timer->stop();
}
}
QCheckBox*
PeriodicUpdateWidget::autoCheckBox()
{
return _autoCheckBox;
}
QDoubleSpinBox*
PeriodicUpdateWidget::frequencySpinBox()
{
return _frequencySpinBox;
}
QTimer*
PeriodicUpdateWidget::timer()
{
return _timer;
}
} // namespace armarx
#pragma once
#include <QWidget>
class QCheckBox;
class QDoubleSpinBox;
class QPushButton;
class QTimer;
namespace armarx
{
class PeriodicUpdateWidget : public QWidget
{
Q_OBJECT
using This = PeriodicUpdateWidget;
public:
PeriodicUpdateWidget(double frequency = 2.0, double maxFrequency = 60);
QTimer* timer();
QCheckBox* autoCheckBox();
QDoubleSpinBox* frequencySpinBox();
QPushButton* updateButton();
bool isAutoEnabled() const;
double getUpdateFrequency() const;
int getUpdateIntervalMs() const;
void startTimerIfEnabled();
void stopTimer();
public slots:
signals:
void update();
void updateSingle();
void updatePeriodic();
private slots:
void _updateTimerFrequency();
void _toggleAutoUpdates(bool enabled);
signals:
void startTimerSignal();
void stopTimerSignal();
private:
QPushButton* _updateButton;
QCheckBox* _autoCheckBox;
QDoubleSpinBox* _frequencySpinBox;
QPushButton* _collapseAllButton;
QTimer* _timer;
};
} // namespace armarx
...@@ -6,12 +6,12 @@ ...@@ -6,12 +6,12 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>1060</width> <width>1126</width>
<height>657</height> <height>729</height>
</rect> </rect>
</property> </property>
<property name="sizePolicy"> <property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding"> <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch> <horstretch>0</horstretch>
<verstretch>0</verstretch> <verstretch>0</verstretch>
</sizepolicy> </sizepolicy>
...@@ -19,41 +19,14 @@ ...@@ -19,41 +19,14 @@
<property name="windowTitle"> <property name="windowTitle">
<string>SkillManagerMonitorWidget</string> <string>SkillManagerMonitorWidget</string>
</property> </property>
<layout class="QGridLayout" name="gridLayout_3"> <layout class="QGridLayout" name="gridLayout_3" rowstretch="0,0,0,0">
<item row="3" column="2"> <item row="3" column="0" colspan="2">
<widget class="QDoubleSpinBox" name="doubleSpinBoxUpdateFreq"/>
</item>
<item row="3" column="0">
<widget class="QCheckBox" name="checkBoxAutoUpdate">
<property name="text">
<string>Auto Update</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QLabel" name="label">
<property name="text">
<string>Update Frequency:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="3" column="3">
<widget class="QPushButton" name="pushButtonRefreshNow">
<property name="text">
<string>Refresh Now</string>
</property>
</widget>
</item>
<item row="4" column="0" colspan="4">
<widget class="QSplitter" name="splitter_2"> <widget class="QSplitter" name="splitter_2">
<property name="enabled"> <property name="enabled">
<bool>true</bool> <bool>true</bool>
</property> </property>
<property name="sizePolicy"> <property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred"> <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch> <horstretch>0</horstretch>
<verstretch>0</verstretch> <verstretch>0</verstretch>
</sizepolicy> </sizepolicy>
...@@ -75,11 +48,14 @@ ...@@ -75,11 +48,14 @@
<string>Executions</string> <string>Executions</string>
</property> </property>
<layout class="QGridLayout" name="gridLayout_4"> <layout class="QGridLayout" name="gridLayout_4">
<item row="1" column="0" colspan="3"> <item row="0" column="0" colspan="3">
<widget class="QTreeWidget" name="treeWidgetSkillExecutions"> <widget class="QTreeWidget" name="treeWidgetSkillExecutions">
<property name="contextMenuPolicy">
<enum>Qt::CustomContextMenu</enum>
</property>
<column> <column>
<property name="text"> <property name="text">
<string>ExecutionID</string> <string>Timestamp</string>
</property> </property>
</column> </column>
<column> <column>
...@@ -94,27 +70,7 @@ ...@@ -94,27 +70,7 @@
</column> </column>
<column> <column>
<property name="text"> <property name="text">
<string>IsConstructing</string> <string>Status</string>
</property>
</column>
<column>
<property name="text">
<string>IsInitializing</string>
</property>
</column>
<column>
<property name="text">
<string>IsPreparing</string>
</property>
</column>
<column>
<property name="text">
<string>IsRunning</string>
</property>
</column>
<column>
<property name="text">
<string>Finished</string>
</property> </property>
</column> </column>
</widget> </widget>
...@@ -171,6 +127,9 @@ ...@@ -171,6 +127,9 @@
<item row="4" column="0"> <item row="4" column="0">
<widget class="QLineEdit" name="lineEditSearch"> <widget class="QLineEdit" name="lineEditSearch">
<property name="text"> <property name="text">
<string/>
</property>
<property name="placeholderText">
<string>Search...</string> <string>Search...</string>
</property> </property>
</widget> </widget>
...@@ -209,65 +168,65 @@ ...@@ -209,65 +168,65 @@
<bool>false</bool> <bool>false</bool>
</property> </property>
<widget class="QWidget" name="groupBoxSkillDetailsTop" native="true"> <widget class="QWidget" name="groupBoxSkillDetailsTop" native="true">
<layout class="QVBoxLayout" name="verticalLayout_2"> <layout class="QVBoxLayout" name="verticalLayout_2">
<property name="leftMargin"> <property name="leftMargin">
<number>0</number> <number>0</number>
</property> </property>
<property name="topMargin"> <property name="topMargin">
<number>0</number> <number>0</number>
</property> </property>
<property name="rightMargin"> <property name="rightMargin">
<number>0</number> <number>0</number>
</property> </property>
<property name="bottomMargin"> <property name="bottomMargin">
<number>0</number> <number>0</number>
</property> </property>
<item> <item>
<layout class="QGridLayout" name="gridLayout_5"> <layout class="QGridLayout" name="gridLayout_5">
<item row="0" column="0"> <item row="0" column="0">
<widget class="QPushButton" name="pushButtonPaste"> <widget class="QPushButton" name="pushButtonPaste">
<property name="text">
<string>Set args from clipboard</string>
</property>
</widget>
</item>
<item row="0" column="3">
<widget class="QPushButton" name="pushButtonReset">
<property name="text">
<string>Reset args to profile</string>
</property>
</widget>
</item>
<item row="1" column="0" colspan="4">
<widget class="QComboBox" name="comboBoxProfiles">
<item>
<property name="text"> <property name="text">
<string>&lt;No Profile selected. Using root&gt;</string> <string>Set args from clipboard</string>
</property> </property>
</item> </widget>
</widget> </item>
</item> <item row="0" column="3">
<item row="0" column="1"> <widget class="QPushButton" name="pushButtonReset">
<widget class="QPushButton" name="pushButtonCopy"> <property name="text">
<property name="text"> <string>Reset args to profile</string>
<string>Copy args to clipboard</string> </property>
</property> </widget>
</widget> </item>
</item> <item row="1" column="0" colspan="4">
<item row="0" column="2"> <widget class="QComboBox" name="comboBoxProfiles">
<widget class="QLabel" name="label_2"> <item>
<property name="text"> <property name="text">
<string/> <string>&lt;No Profile selected. Using root&gt;</string>
</property> </property>
</widget> </item>
</item> </widget>
</layout> </item>
</item> <item row="0" column="1">
<item> <widget class="QPushButton" name="pushButtonCopy">
<widget class="QWidget" name="skillDescription" native="true"/> <property name="text">
</item> <string>Copy args to clipboard</string>
</layout> </property>
</widget> </widget>
</item>
<item row="0" column="2">
<widget class="QLabel" name="label_2">
<property name="text">
<string/>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QWidget" name="skillDescription" native="true"/>
</item>
</layout>
</widget>
<widget class="QWidget" name="groupBoxSkillDetailsBottom" native="true"> <widget class="QWidget" name="groupBoxSkillDetailsBottom" native="true">
<layout class="QVBoxLayout" name="verticalLayout_3"> <layout class="QVBoxLayout" name="verticalLayout_3">
<property name="leftMargin"> <property name="leftMargin">
...@@ -328,6 +287,50 @@ ...@@ -328,6 +287,50 @@
</widget> </widget>
</widget> </widget>
</item> </item>
<item row="0" column="0" rowspan="3" colspan="2">
<layout class="QHBoxLayout" name="horizontalLayout">
<property name="sizeConstraint">
<enum>QLayout::SetDefaultConstraint</enum>
</property>
<item>
<layout class="QHBoxLayout" name="updateWidgetLayout">
<item>
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Expanding</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="stopAllLayout">
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
</layout>
</item>
</layout> </layout>
</widget> </widget>
<resources/> <resources/>
......
...@@ -22,11 +22,27 @@ ...@@ -22,11 +22,27 @@
#include "SkillManagerMonitorWidgetController.h" #include "SkillManagerMonitorWidgetController.h"
#include <optional>
#include <regex>
#include <string> #include <string>
#include <SimoxUtility/algorithm/string.h>
#include <RobotAPI/libraries/skills/core/Skill.h>
#include "aronTreeWidget/visitors/AronTreeWidgetConverter.h"
#include "aronTreeWidget/visitors/AronTreeWidgetCreator.h"
#include "aronTreeWidget/visitors/AronTreeWidgetModalCreator.h"
// modals
#include "aronTreeWidget/modal/text/AronTreeWidgetTextInputModalController.h"
// debug
#include <QAction>
#include <QClipboard> #include <QClipboard>
#include <QDoubleSpinBox> #include <QDoubleSpinBox>
#include <QGridLayout> #include <QGridLayout>
#include <QMenu>
#include <QTextBrowser> #include <QTextBrowser>
#include <RobotAPI/libraries/aron/converter/json/NLohmannJSONConverter.h> #include <RobotAPI/libraries/aron/converter/json/NLohmannJSONConverter.h>
...@@ -40,8 +56,12 @@ ...@@ -40,8 +56,12 @@
#include "aronTreeWidget/visitors/AronTreeWidgetModalCreator.h" #include "aronTreeWidget/visitors/AronTreeWidgetModalCreator.h"
#include "aronTreeWidget/widgets/SkillDescriptionWidget.h" #include "aronTreeWidget/widgets/SkillDescriptionWidget.h"
//configSk
namespace armarx namespace armarx
{ {
const skills::SkillID SkillManagerMonitorWidgetController::SelectedSkill::UNK_SKILL_ID =
skills::SkillID{.providerId = ::std::nullopt, .skillName = skills::SkillID::UNKNOWN};
QPointer<QDialog> QPointer<QDialog>
SkillManagerMonitorWidgetController::getConfigDialog(QWidget* parent) SkillManagerMonitorWidgetController::getConfigDialog(QWidget* parent)
{ {
...@@ -76,6 +96,38 @@ namespace armarx ...@@ -76,6 +96,38 @@ namespace armarx
// Others // Others
namespace armarx namespace armarx
{ {
void
SkillManagerMonitorWidgetController::prepareAndRunMenu(const QPoint& pos)
{
QMenu* menu = new QMenu();
// Stop skill
QAction* stopSkillAction = new QAction("Stop execution", this);
skills::SkillStatus currentStatus =
skillStatusUpdates.at(selectedSkill.skillExecutionId).status;
stopSkillAction->setDisabled(currentStatus == skills::SkillStatus::Aborted ||
currentStatus == skills::SkillStatus::Failed ||
currentStatus == skills::SkillStatus::Succeeded);
QAction* rerunSkillAction = new QAction("Re-run with similar params", this);
menu->addAction(stopSkillAction);
menu->addAction(rerunSkillAction);
connect(stopSkillAction,
&QAction::triggered,
this,
&SkillManagerMonitorWidgetController::stopSkill);
connect(rerunSkillAction,
&QAction::triggered,
this,
&SkillManagerMonitorWidgetController::rerunSkillWithSimilarParams);
// Temporarily disable rerun-skill-Action
rerunSkillAction->setDisabled(true);
// open menu
menu->popup(widget.treeWidgetSkillExecutions->viewport()->mapToGlobal(pos));
}
SkillExecutionInfoTreeWidgetItem* SkillExecutionInfoTreeWidgetItem*
SkillExecutionInfoTreeWidgetItem::SearchRecursiveForMatch( SkillExecutionInfoTreeWidgetItem::SearchRecursiveForMatch(
SkillExecutionInfoTreeWidgetItem* haystack, SkillExecutionInfoTreeWidgetItem* haystack,
...@@ -101,13 +153,12 @@ namespace armarx ...@@ -101,13 +153,12 @@ namespace armarx
SkillManagerMonitorWidgetController::SkillManagerMonitorWidgetController() SkillManagerMonitorWidgetController::SkillManagerMonitorWidgetController()
{ {
widget.setupUi(getWidget()); widget.setupUi(getWidget());
this->updateWidget = new PeriodicUpdateWidget(2.0, 60);
widget.updateWidgetLayout->insertWidget(0, updateWidget);
this->stopAllButton = new QPushButton("Stop all executions");
widget.stopAllLayout->addWidget(stopAllButton);
double default_hz = 2;
widget.doubleSpinBoxUpdateFreq->setValue(default_hz);
widget.doubleSpinBoxUpdateFreq->setMinimum(0.5);
widget.doubleSpinBoxUpdateFreq->setMaximum(20);
widget.doubleSpinBoxUpdateFreq->setSingleStep(0.5);
widget.doubleSpinBoxUpdateFreq->setSuffix(" Hz");
skillDescriptionWidget = new SkillDescriptionWidget(); skillDescriptionWidget = new SkillDescriptionWidget();
widget.skillDescription->parentWidget()->layout()->replaceWidget(widget.skillDescription, widget.skillDescription->parentWidget()->layout()->replaceWidget(widget.skillDescription,
...@@ -115,16 +166,17 @@ namespace armarx ...@@ -115,16 +166,17 @@ namespace armarx
widget.skillDescription = skillDescriptionWidget; widget.skillDescription = skillDescriptionWidget;
refreshSkillsResultTimer = new QTimer(this); connect(this->stopAllButton,
updateTimerFrequency(); &QPushButton::clicked,
refreshSkillsResultTimer->start();
connect(widget.doubleSpinBoxUpdateFreq,
&QDoubleSpinBox::editingFinished,
this, this,
&SkillManagerMonitorWidgetController::updateTimerFrequency); &SkillManagerMonitorWidgetController::stopAllExecutions);
connect(refreshSkillsResultTimer, connect(widget.treeWidgetSkillExecutions,
&QTimer::timeout, &QTreeWidget::customContextMenuRequested,
this,
&SkillManagerMonitorWidgetController::prepareAndRunMenu);
connect(updateWidget,
&armarx::PeriodicUpdateWidget::update,
this, this,
&SkillManagerMonitorWidgetController::refreshSkillsAndExecutions); &SkillManagerMonitorWidgetController::refreshSkillsAndExecutions);
...@@ -140,21 +192,31 @@ namespace armarx ...@@ -140,21 +192,31 @@ namespace armarx
connect(widget.pushButtonExecuteSkill, connect(widget.pushButtonExecuteSkill,
&QPushButton::clicked, &QPushButton::clicked,
this, this,
&SkillManagerMonitorWidgetController::executeSkill); &SkillManagerMonitorWidgetController::executeSelectedSkill);
// connect(widget.pushButtonStopSkill,
// &QPushButton::clicked,
// this,
// &SkillManagerMonitorWidgetController::stopSkill);
connect(widget.treeWidgetSkills, connect(widget.treeWidgetSkills,
&QTreeWidget::currentItemChanged, &QTreeWidget::currentItemChanged,
this, this,
&SkillManagerMonitorWidgetController::skillSelectionChanged); &SkillManagerMonitorWidgetController::skillSelectionChanged);
connect(widget.pushButtonRefreshNow, connect(widget.treeWidgetSkillExecutions,
&QTreeWidget::currentItemChanged,
this,
&SkillManagerMonitorWidgetController::skillExecutionSelectionChanged);
/*connect(widget.pushButtonRefreshNow,
&QPushButton::clicked, &QPushButton::clicked,
this, this,
&SkillManagerMonitorWidgetController::refreshSkills); &SkillManagerMonitorWidgetController::refreshSkills);*/
connect(widget.pushButtonSearch,
&QPushButton::clicked,
this,
&SkillManagerMonitorWidgetController::searchSkills);
// alternatively run search when pressing enter
connect(widget.lineEditSearch,
&QLineEdit::returnPressed,
this,
&SkillManagerMonitorWidgetController::searchSkills);
} }
SkillManagerMonitorWidgetController::~SkillManagerMonitorWidgetController() SkillManagerMonitorWidgetController::~SkillManagerMonitorWidgetController()
...@@ -176,6 +238,7 @@ namespace armarx ...@@ -176,6 +238,7 @@ namespace armarx
widget.treeWidgetSkillDetails->setColumnHidden(3, true); widget.treeWidgetSkillDetails->setColumnHidden(3, true);
getProxy(memory, observerName, 1000); getProxy(memory, observerName, 1000);
this->updateWidget->startTimerIfEnabled();
connected = true; connected = true;
} }
...@@ -192,23 +255,51 @@ namespace armarx ...@@ -192,23 +255,51 @@ namespace armarx
skillsArgumentsTreeWidgetItem = nullptr; skillsArgumentsTreeWidgetItem = nullptr;
selectedSkill.skillId.providerId->providerName = ""; selectedSkill.skillId.providerId->providerName = "";
selectedSkill.skillId.skillName = ""; selectedSkill.skillId.skillName = "";
this->updateWidget->stopTimer();
} }
void void
SkillManagerMonitorWidgetController::updateTimerFrequency() SkillManagerMonitorWidgetController::searchSkills()
{ {
int f = static_cast<int>(std::round(1000 / widget.doubleSpinBoxUpdateFreq->value())); this->currentSkillSearch = widget.lineEditSearch->text();
refreshSkillsResultTimer->setInterval(f);
} }
void void
SkillManagerMonitorWidgetController::refreshSkillsAndExecutions() SkillManagerMonitorWidgetController::refreshSkillsAndExecutions()
{ {
if (widget.checkBoxAutoUpdate->isChecked()) refreshSkills();
refreshExecutions();
}
void
SkillManagerMonitorWidgetController::matchSkillUpdateToSearch(
std::map<skills::manager::dto::SkillID, skills::manager::dto::SkillDescription>& update)
{
/*
if (this->currentSkillSearch.isEmpty())
{ {
refreshSkills(); return;
refreshExecutions();
} }
// TODO: whitespace to wildcard
std::string search = this->currentSkillSearch.toLower().toStdString();
std::transform(search.begin(), search.end(), search.begin(),
[](unsigned char c){ return std::tolower(c); });
for (auto it = update.begin(); it != update.end();)
{
if (simox::alg::to_lower(skills::SkillID::FromIce(it->first).skillName)
.find(this->currentSkillSearch.toLower().toStdString()))
{
it = update.erase(it);
}
else
{
++it;
}
}
*/
} }
void void
...@@ -227,6 +318,7 @@ namespace armarx ...@@ -227,6 +318,7 @@ namespace armarx
std::scoped_lock l(updateMutex); std::scoped_lock l(updateMutex);
auto managerSkills = memory->getSkillDescriptions(); auto managerSkills = memory->getSkillDescriptions();
this->matchSkillUpdateToSearch(managerSkills);
// completely recreate internal skills map // completely recreate internal skills map
skills.clear(); skills.clear();
...@@ -341,16 +433,16 @@ namespace armarx ...@@ -341,16 +433,16 @@ namespace armarx
SkillManagerMonitorWidgetController::refreshExecutions() SkillManagerMonitorWidgetController::refreshExecutions()
{ {
static std::map<skills::SkillStatus, std::string> ExecutionStatus2String = { static std::map<skills::SkillStatus, std::string> ExecutionStatus2String = {
// Main states
{skills::SkillStatus::Constructing, "Constructing"},
{skills::SkillStatus::Initializing, "Initializing"},
{skills::SkillStatus::Preparing, "Preparing"},
{skills::SkillStatus::Running, "Running"},
// Terminating // Terminating
{skills::SkillStatus::Aborted, "Aborted"}, {skills::SkillStatus::Aborted, "Aborted"},
{skills::SkillStatus::Failed, "Failed"}, {skills::SkillStatus::Failed, "Failed"},
{skills::SkillStatus::Succeeded, "Succeeded"}, {skills::SkillStatus::Succeeded, "Succeeded"}};
// Others
{skills::SkillStatus::Constructing, "Under construction"},
{skills::SkillStatus::Running, "Running"},
{skills::SkillStatus::Initializing, "Initializing"},
{skills::SkillStatus::Preparing, "Preparing"}};
if (!memory) if (!memory)
{ {
...@@ -362,15 +454,18 @@ namespace armarx ...@@ -362,15 +454,18 @@ namespace armarx
{ {
std::scoped_lock l(updateMutex); std::scoped_lock l(updateMutex);
auto currentManagerStatuses = auto currentManagerStatuses = memory->getSkillExecutionStatuses();
memory
->getSkillExecutionStatuses(); // we assume that there are no more than 100 new skills..
for (const auto& [k, v] : currentManagerStatuses) for (const auto& [k, v] : currentManagerStatuses)
{ {
auto executionId = skills::SkillExecutionID::FromIce(k); auto executionId = skills::SkillExecutionID::FromIce(k);
auto statusUpdate = skills::SkillStatusUpdate::FromIce(v); auto statusUpdate = skills::SkillStatusUpdate::FromIce(v);
// update maps
skillStatusUpdates[executionId] = statusUpdate;
//skillExecutionParams.insert_or_assign(executionId,
// statusUpdate.usedParameterization);
SkillExecutionInfoTreeWidgetItem* found = nullptr; SkillExecutionInfoTreeWidgetItem* found = nullptr;
for (int i = 0; i < widget.treeWidgetSkillExecutions->topLevelItemCount(); ++i) for (int i = 0; i < widget.treeWidgetSkillExecutions->topLevelItemCount(); ++i)
{ {
...@@ -382,22 +477,14 @@ namespace armarx ...@@ -382,22 +477,14 @@ namespace armarx
if (found) if (found)
{ {
// update values for (std::pair<skills::SkillStatus, std::string> i : ExecutionStatus2String)
found->setText(3, {
QString::fromStdString( if (i.first == statusUpdate.status)
statusUpdate.hasBeenConstructed() ? " yes " : " no ")); {
found->setText(4, found->setText(3, QString::fromStdString(i.second));
QString::fromStdString( }
statusUpdate.hasBeenInitialized() ? " yes " : " no ")); }
found->setText(5,
QString::fromStdString(
statusUpdate.hasBeenPrepared() ? " yes " : " no "));
found->setText(6,
QString::fromStdString(
statusUpdate.hasBeenRunning() ? " yes " : " no "));
found->setText(7,
QString::fromStdString(
statusUpdate.hasBeenTerminated() ? " yes " : " no "));
break; break;
} }
} }
...@@ -405,29 +492,22 @@ namespace armarx ...@@ -405,29 +492,22 @@ namespace armarx
if (!found) if (!found)
{ {
// TODO: Sort to executor! // TODO: Sort to executor!
auto item = new SkillExecutionInfoTreeWidgetItem( auto item = new SkillExecutionInfoTreeWidgetItem(executionId);
executionId, widget.treeWidgetSkillExecutions);
item->setText(0, item->setText(0,
QString::fromStdString( QString::fromStdString(
executionId.executionStartedTime.toDateTimeString())); executionId.executionStartedTime.toDateTimeString()));
item->setText(1, QString::fromStdString(executionId.executorName)); item->setText(1, QString::fromStdString(executionId.executorName));
item->setText(2, QString::fromStdString(executionId.skillId.toString())); item->setText(2, QString::fromStdString(executionId.skillId.toString()));
item->setText(3, for (std::pair<skills::SkillStatus, std::string> i : ExecutionStatus2String)
QString::fromStdString( {
statusUpdate.hasBeenConstructed() ? " yes " : " no ")); if (i.first == statusUpdate.status)
item->setText(4, {
QString::fromStdString( item->setText(3, QString::fromStdString(i.second));
statusUpdate.hasBeenInitialized() ? " yes " : " no ")); }
item->setText( }
5,
QString::fromStdString(statusUpdate.hasBeenPrepared() ? " yes " : " no ")); widget.treeWidgetSkillExecutions->insertTopLevelItem(0, item);
item->setText(
6,
QString::fromStdString(statusUpdate.hasBeenRunning() ? " yes " : " no "));
item->setText(7,
QString::fromStdString(
statusUpdate.hasBeenTerminated() ? " yes " : " no "));
} }
} }
} }
...@@ -438,31 +518,48 @@ namespace armarx ...@@ -438,31 +518,48 @@ namespace armarx
} }
void void
SkillManagerMonitorWidgetController::executeSkill() SkillManagerMonitorWidgetController::executeSelectedSkill()
{ {
if (not selectedSkill.skillId.isFullySpecified()) auto data = getConfigAsAron();
{ executeSkillWithParams(selectedSkill.skillId, data);
return; }
}
void
SkillManagerMonitorWidgetController::rerunSkillWithSimilarParams()
{
// TODO: disabled until skillparameterization is replaced
//skills::SkillParameterization selectedExecutionParams =
//skillExecutionParams.at(selectedSkill.skillExecutionId);
//executeSkillWithParams(selectedSkill.skillExecutionId.skillId,
// selectedExecutionParams.parameterization);
executeSelectedSkill();
}
void
SkillManagerMonitorWidgetController::executeSkillWithParams(skills::SkillID skillId,
aron::data::DictPtr params)
{
std::scoped_lock l(updateMutex); std::scoped_lock l(updateMutex);
auto providerId = *selectedSkill.skillId.providerId; auto providerId = skillId.providerId;
const auto& skillDescriptions = skills.at(providerId); if (!providerId.has_value())
if (skillDescriptions.find(selectedSkill.skillId) == skillDescriptions.end()) {
return;
}
const auto& skillDescriptions = skills.at(providerId.value());
if (skillDescriptions.find(skillId) == skillDescriptions.end())
{ {
return; return;
} }
auto data = getConfigAsAron();
char hostname[HOST_NAME_MAX]; char hostname[HOST_NAME_MAX];
gethostname(hostname, HOST_NAME_MAX); gethostname(hostname, HOST_NAME_MAX);
skills::SkillExecutionRequest req{selectedSkill.skillId, skills::SkillExecutionRequest req{
"Skills.Manager GUI (hostname: " + std::string(hostname) + .skillId = selectedSkill.skillId,
")", .executorName = "Skills.Manager GUI (hostname: " + std::string(hostname) + ")",
data}; .parameters = params};
ARMARX_CHECK(selectedSkill.skillId.isFullySpecified()); // sanity check ARMARX_CHECK(selectedSkill.skillId.isFullySpecified()); // sanity check
ARMARX_IMPORTANT << "Executing skill from GUI: " << selectedSkill.skillId << "."; ARMARX_IMPORTANT << "Executing skill from GUI: " << selectedSkill.skillId << ".";
...@@ -470,24 +567,112 @@ namespace armarx ...@@ -470,24 +567,112 @@ namespace armarx
memory->begin_executeSkill(req.toManagerIce()); memory->begin_executeSkill(req.toManagerIce());
} }
void
SkillManagerMonitorWidgetController::stopAllExecutions()
{
QTreeWidget const* tree = widget.treeWidgetSkillExecutions;
int const max_retries = 3;
int left_retries = max_retries;
bool retry = false;
do
{
retry = false;
for (ssize_t i = 0; i < tree->topLevelItemCount(); ++i)
{
SkillExecutionInfoTreeWidgetItem const* item =
dynamic_cast<SkillExecutionInfoTreeWidgetItem*>(
widget.treeWidgetSkillExecutions->topLevelItem(i));
if (not item)
{
// At this point, dynamic-casting failed and we don't know anything about the
// type.
ARMARX_ERROR << "Cannot stop unknown skill.";
retry = true;
continue;
}
try
{
ARMARX_INFO << "Aborting skill '" << item->executionId.skillId.skillName
<< "'...";
memory->abortSkillAsync(item->executionId.toManagerIce());
}
catch (Ice::Exception const& e)
{
retry = true;
ARMARX_ERROR << "Unhandeled Ice exception while aborting skill '"
<< item->executionId.skillId.skillName << "'.";
}
catch (...)
{
retry = true;
ARMARX_ERROR << "Unhandled error while aborting skill '"
<< item->executionId.skillId.skillName << "'.";
}
}
if (retry)
{
left_retries -= 1;
if (left_retries > 0)
{
ARMARX_WARNING << "There where errors aborting skills. Retrying...";
}
else
{
ARMARX_ERROR << "Couldn't abort all skills after " << max_retries
<< " tries. Giving up.";
retry = false;
}
}
} while (retry);
}
void void
SkillManagerMonitorWidgetController::stopSkill() SkillManagerMonitorWidgetController::stopSkill()
{ {
// std::scoped_lock l(updateMutex); std::scoped_lock l(updateMutex);
// if (selectedSkill.skillId.isFullySpecified())
// { /*
// return; if (selectedSkill.skillExecutionId.skillId.fullySpecified())
// } {
ARMARX_INFO << "The user requested to stop a skill, which was not fully specified!";
return;
}
const auto& skillDescriptions = skills.at(*selectedSkill.skillId.providerId);
if (!skillDescriptions.count(selectedSkill.skillId.skillName))
{
return;
}
*/
ARMARX_INFO << "Stopping skill from GUI: " << selectedSkill.skillExecutionId.toString();
memory->abortSkillAsync(selectedSkill.skillExecutionId.toManagerIce());
}
// const auto& skillDescriptions = skills.at(*selectedSkill.skillId.providerId); void
// if (!skillDescriptions.count(selectedSkill.skillId.skillName)) SkillManagerMonitorWidgetController::skillExecutionSelectionChanged(QTreeWidgetItem* current,
// { QTreeWidgetItem*)
// return; {
// } std::scoped_lock l(updateMutex);
widget.groupBoxSkillExecutions->setEnabled(false);
// ARMARX_INFO << "Stopping skill from GUI: " << selectedSkill.skillId; if (!current)
{
// gui has died?
return;
}
// manager->abortSkill(selectedSkill.skillId); auto c = static_cast<SkillExecutionInfoTreeWidgetItem*>(current);
selectedSkill.skillExecutionId = c->executionId;
widget.groupBoxSkillExecutions->setEnabled(true);
} }
void void
...@@ -506,14 +691,14 @@ namespace armarx ...@@ -506,14 +691,14 @@ namespace armarx
if (!current->parent()) if (!current->parent())
{ {
// no parent available. Perhaps provider clicked? Reset selected skill. // no parent available. Perhaps provider clicked? Reset selected skill.
selectedSkill.skillId.providerId->providerName = ""; selectedSkill.skillId = SelectedSkill::UNK_SKILL_ID;
selectedSkill.skillId.skillName = "";
return; return;
} }
auto c = static_cast<SkillInfoTreeWidgetItem*>(current); auto c = static_cast<SkillInfoTreeWidgetItem*>(current);
auto skillDescription = c->skillDescription; auto skillDescription = c->skillDescription;
if (selectedSkill.skillId == skillDescription.skillId) if (selectedSkill.skillId == skillDescription.skillId)
{ {
// no change // no change
...@@ -537,7 +722,28 @@ namespace armarx ...@@ -537,7 +722,28 @@ namespace armarx
ARMARX_CHECK(skills.at(*selectedSkill.skillId.providerId).count(selectedSkill.skillId) > 0); ARMARX_CHECK(skills.at(*selectedSkill.skillId.providerId).count(selectedSkill.skillId) > 0);
auto skillDesc = skills.at(*selectedSkill.skillId.providerId).at(selectedSkill.skillId); auto skillDesc = skills.at(*selectedSkill.skillId.providerId).at(selectedSkill.skillId);
skillDescriptionWidget->setSkillDescription(skillDesc); {
auto it = new QTreeWidgetItem(widget.treeWidgetSkillDetails,
{QString::fromStdString("Name"),
QString::fromStdString(skillDesc.skillId.skillName)});
widget.treeWidgetSkillDetails->addTopLevelItem(it);
}
{
auto it = new QTreeWidgetItem(widget.treeWidgetSkillDetails,
{QString::fromStdString("Description"),
QString::fromStdString(skillDesc.description)});
widget.treeWidgetSkillDetails->addTopLevelItem(it);
}
{
auto it = new QTreeWidgetItem(
widget.treeWidgetSkillDetails,
{QString::fromStdString("Timeout"),
QString::fromStdString(std::to_string(skillDesc.timeout.toMilliSeconds())) +
" ms"});
widget.treeWidgetSkillDetails->addTopLevelItem(it);
}
// select root profile // select root profile
widget.comboBoxProfiles->setCurrentIndex(0); widget.comboBoxProfiles->setCurrentIndex(0);
......
...@@ -33,6 +33,7 @@ ...@@ -33,6 +33,7 @@
#include <ArmarXGui/libraries/ArmarXGuiBase/ArmarXGuiPlugin.h> #include <ArmarXGui/libraries/ArmarXGuiBase/ArmarXGuiPlugin.h>
#include <ArmarXGui/libraries/SimpleConfigDialog/SimpleConfigDialog.h> #include <ArmarXGui/libraries/SimpleConfigDialog/SimpleConfigDialog.h>
#include "RobotAPI/gui-plugins/SkillManagerPlugin/PeriodicUpdateWidget.h"
#include <RobotAPI/gui-plugins/SkillManagerPlugin/ui_SkillManagerMonitorWidget.h> #include <RobotAPI/gui-plugins/SkillManagerPlugin/ui_SkillManagerMonitorWidget.h>
#include <RobotAPI/interface/skills/SkillMemoryInterface.h> #include <RobotAPI/interface/skills/SkillMemoryInterface.h>
#include <RobotAPI/libraries/aron/core/data/variant/All.h> #include <RobotAPI/libraries/aron/core/data/variant/All.h>
...@@ -66,6 +67,7 @@ namespace armarx ...@@ -66,6 +67,7 @@ namespace armarx
class SkillExecutionInfoTreeWidgetItem : public QTreeWidgetItem class SkillExecutionInfoTreeWidgetItem : public QTreeWidgetItem
{ {
//Q_OBJECT
public: public:
SkillExecutionInfoTreeWidgetItem(const skills::SkillExecutionID& id, SkillExecutionInfoTreeWidgetItem(const skills::SkillExecutionID& id,
QTreeWidgetItem* parent) : QTreeWidgetItem* parent) :
...@@ -73,6 +75,12 @@ namespace armarx ...@@ -73,6 +75,12 @@ namespace armarx
{ {
} }
// After constructing an item, it must be manually inserted into the tree!
SkillExecutionInfoTreeWidgetItem(const skills::SkillExecutionID& id) : executionId(id)
{
}
// When using this constructor, the new item will be appended to the bottom of the tree!
SkillExecutionInfoTreeWidgetItem(const skills::SkillExecutionID& id, QTreeWidget* parent) : SkillExecutionInfoTreeWidgetItem(const skills::SkillExecutionID& id, QTreeWidget* parent) :
QTreeWidgetItem(parent), executionId(id) QTreeWidgetItem(parent), executionId(id)
{ {
...@@ -113,15 +121,16 @@ namespace armarx ...@@ -113,15 +121,16 @@ namespace armarx
void onInitComponent() override; void onInitComponent() override;
void onConnectComponent() override; void onConnectComponent() override;
void onDisconnectComponent() override; void onDisconnectComponent();
private slots: private slots:
void skillSelectionChanged(QTreeWidgetItem* current, QTreeWidgetItem* previous); void skillSelectionChanged(QTreeWidgetItem* current, QTreeWidgetItem* previous);
void skillExecutionSelectionChanged(QTreeWidgetItem* current, QTreeWidgetItem* previous);
void stopSkill(); void stopAllExecutions();
void executeSkill(); void stopSkill(); // TODO: rename
void executeSelectedSkill();
void updateTimerFrequency();
void refreshSkills(); void refreshSkills();
void refreshExecutions(); void refreshExecutions();
void refreshSkillsAndExecutions(); void refreshSkillsAndExecutions();
...@@ -130,6 +139,11 @@ namespace armarx ...@@ -130,6 +139,11 @@ namespace armarx
void pasteCurrentConfig(); void pasteCurrentConfig();
void resetCurrentConfig(); void resetCurrentConfig();
void prepareAndRunMenu(const QPoint& pos);
void rerunSkillWithSimilarParams();
void searchSkills();
private: private:
aron::data::DictPtr getConfigAsAron() const; aron::data::DictPtr getConfigAsAron() const;
...@@ -140,6 +154,7 @@ namespace armarx ...@@ -140,6 +154,7 @@ namespace armarx
*/ */
Ui::SkillManagerMonitorWidget widget; Ui::SkillManagerMonitorWidget widget;
QPointer<SimpleConfigDialog> dialog; QPointer<SimpleConfigDialog> dialog;
QString currentSkillSearch;
std::string observerName = "SkillManager"; std::string observerName = "SkillManager";
skills::dti::SkillMemoryInterfacePrx memory = nullptr; skills::dti::SkillMemoryInterfacePrx memory = nullptr;
...@@ -150,24 +165,41 @@ namespace armarx ...@@ -150,24 +165,41 @@ namespace armarx
{}; {};
std::map<skills::SkillExecutionID, skills::SkillStatusUpdate> skillStatusUpdates = {}; std::map<skills::SkillExecutionID, skills::SkillStatusUpdate> skillStatusUpdates = {};
// store copies (!) of skill descriptions
//std::map<skills::SkillExecutionID, skills::SkillParameterization> skillExecutionParams = {};
// User Input // User Input
struct SelectedSkill struct SelectedSkill
{ {
static const skills::SkillID UNK_SKILL_ID;
skills::SkillID skillId; skills::SkillID skillId;
skills::SkillExecutionID skillExecutionId;
// make default constructable // make default constructable
SelectedSkill() : SelectedSkill() :
skillId{.providerId = skills::ProviderID{.providerName = ""}, .skillName = ""} skillId(UNK_SKILL_ID),
skillExecutionId{.skillId = UNK_SKILL_ID,
.executorName = skills::SkillExecutionID::UNKNOWN,
.executionStartedTime = armarx::core::time::DateTime::Invalid()}
{ {
} }
} selectedSkill; }
selectedSkill;
void executeSkillWithParams(skills::SkillID skillId, aron::data::DictPtr params);
void matchSkillUpdateToSearch(std::map<skills::manager::dto::SkillID,
skills::manager::dto::SkillDescription>& update);
PeriodicUpdateWidget* updateWidget =
nullptr; // TODO: this should not be held by the controller!
QPushButton* stopAllButton = nullptr; // also this. Oh well...
// Helper to get the treeWidgetItem easily // Helper to get the treeWidgetItem easily
QTreeWidgetItem* skillsArgumentsTreeWidgetItem = nullptr; QTreeWidgetItem* skillsArgumentsTreeWidgetItem = nullptr;
AronTreeWidgetControllerPtr aronTreeWidgetController = nullptr; AronTreeWidgetControllerPtr aronTreeWidgetController = nullptr;
// others
QTimer* refreshSkillsResultTimer;
SkillDescriptionWidget* skillDescriptionWidget = nullptr; SkillDescriptionWidget* skillDescriptionWidget = nullptr;
// connected flag // connected flag
......
...@@ -4,6 +4,7 @@ namespace armarx ...@@ -4,6 +4,7 @@ namespace armarx
{ {
namespace skills namespace skills
{ {
skills::manager::dto::SkillExecutionID skills::manager::dto::SkillExecutionID
SkillExecutionID::toManagerIce() const SkillExecutionID::toManagerIce() const
{ {
...@@ -29,7 +30,9 @@ namespace armarx ...@@ -29,7 +30,9 @@ namespace armarx
{ {
armarx::core::time::DateTime t; armarx::core::time::DateTime t;
armarx::core::time::fromIce(i.executionStartedTime, t); armarx::core::time::fromIce(i.executionStartedTime, t);
return {skills::SkillID::FromIce(i.skillId), i.executorName, t}; return {.skillId = skills::SkillID::FromIce(i.skillId),
.executorName = i.executorName,
.executionStartedTime = t};
} }
SkillExecutionID SkillExecutionID
...@@ -40,5 +43,13 @@ namespace armarx ...@@ -40,5 +43,13 @@ namespace armarx
armarx::core::time::fromIce(i.executionStartedTime, t); armarx::core::time::fromIce(i.executionStartedTime, t);
return {skills::SkillID::FromIce(i.skillId, providerName), i.executorName, t}; return {skills::SkillID::FromIce(i.skillId, providerName), i.executorName, t};
} }
std::string
SkillExecutionID::toString() const
{
return skillId.toString() + ENTER_SEPARATOR + executorName + SEPARATOR +
executionStartedTime.toDateTimeString() + EXIT_SEPARATOR;
}
} // namespace skills } // namespace skills
} // namespace armarx } // namespace armarx
...@@ -18,6 +18,15 @@ namespace armarx ...@@ -18,6 +18,15 @@ namespace armarx
{ {
struct SkillExecutionID struct SkillExecutionID
{ {
SkillID skillId;
std::string executorName;
armarx::core::time::DateTime executionStartedTime;
static const constexpr char* UNKNOWN = "UNKNOWN";
static const constexpr char* ENTER_SEPARATOR = "[";
static const constexpr char* EXIT_SEPARATOR = "]";
static const constexpr char* SEPARATOR = "@";
bool bool
operator==(const SkillExecutionID& other) const operator==(const SkillExecutionID& other) const
{ {
...@@ -36,13 +45,6 @@ namespace armarx ...@@ -36,13 +45,6 @@ namespace armarx
return this->toString() <= other.toString(); return this->toString() <= other.toString();
} }
std::string
toString() const
{
return skillId.toString() + " requested by " + executorName + " at " +
executionStartedTime.toDateTimeString();
}
skills::manager::dto::SkillExecutionID toManagerIce() const; skills::manager::dto::SkillExecutionID toManagerIce() const;
skills::provider::dto::SkillExecutionID toProviderIce() const; skills::provider::dto::SkillExecutionID toProviderIce() const;
...@@ -52,10 +54,7 @@ namespace armarx ...@@ -52,10 +54,7 @@ namespace armarx
static SkillExecutionID FromIce(const skills::provider::dto::SkillExecutionID&, static SkillExecutionID FromIce(const skills::provider::dto::SkillExecutionID&,
const std::optional<skills::ProviderID>& providerName); const std::optional<skills::ProviderID>& providerName);
std::string toString() const;
SkillID skillId;
std::string executorName;
armarx::core::time::DateTime executionStartedTime;
}; };
} // namespace skills } // namespace skills
......
...@@ -18,6 +18,7 @@ namespace armarx ...@@ -18,6 +18,7 @@ namespace armarx
{ {
public: public:
static const constexpr char* NAME_SEPARATOR = "/"; static const constexpr char* NAME_SEPARATOR = "/";
static const constexpr char* UNKNOWN = "UNKNOWN";
bool operator==(const SkillID& other) const; bool operator==(const SkillID& other) const;
bool operator!=(const SkillID& other) const; bool operator!=(const SkillID& other) const;
......
...@@ -275,12 +275,18 @@ namespace armarx ...@@ -275,12 +275,18 @@ namespace armarx
try try
{ {
mainRet = skill->mainOfSkill(); mainRet = skill->mainOfSkill();
if (mainRet.status != TerminatedSkillStatus::Succeeded) if (mainRet.status == TerminatedSkillStatus::Failed)
{ {
std::string message = "SkillError 501: The main method of skill '" + skillName + std::string message =
"' did not succeed."; "SkillError 501: The main method of skill '" + skillName + "' did fail.";
return exitAndMakeFailedResult(message); return exitAndMakeFailedResult(message);
} }
else if (mainRet.status == TerminatedSkillStatus::Aborted)
{
std::string message =
"SkillError 501: The main method of skill '" + skillName + "' got aborted.";
return exitAndMakeAbortedResult(message);
}
} }
catch (const error::SkillAbortedException& ex) catch (const error::SkillAbortedException& ex)
{ {
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment