From 8b4c82206ab5ce6237b97a7b9454aa04d1950598 Mon Sep 17 00:00:00 2001
From: Peter Albrecht <albrecpe@gmail.com>
Date: Mon, 23 Oct 2023 16:02:38 +0200
Subject: [PATCH] Implemented re-running a Skill with similar parameters

---
 .../SkillManagerMonitorWidgetController.cpp   | 43 +++++++++++++------
 .../SkillManagerMonitorWidgetController.h     |  7 ++-
 2 files changed, 36 insertions(+), 14 deletions(-)

diff --git a/source/RobotAPI/gui-plugins/SkillManagerPlugin/SkillManagerMonitorWidgetController.cpp b/source/RobotAPI/gui-plugins/SkillManagerPlugin/SkillManagerMonitorWidgetController.cpp
index be7b4593e..4b7833160 100644
--- a/source/RobotAPI/gui-plugins/SkillManagerPlugin/SkillManagerMonitorWidgetController.cpp
+++ b/source/RobotAPI/gui-plugins/SkillManagerPlugin/SkillManagerMonitorWidgetController.cpp
@@ -95,12 +95,17 @@ namespace armarx
                                      currentStatus == skills::SkillStatus::Failed ||
                                      currentStatus == skills::SkillStatus::Succeeded);
 
-        // TODO: re-run with similar params; remove skill entry (if finished)
+        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);
         // open menu
         menu->popup(widget.treeWidgetSkillExecutions->viewport()->mapToGlobal(pos));
     }
@@ -168,7 +173,7 @@ namespace armarx
         connect(widget.pushButtonExecuteSkill,
                 &QPushButton::clicked,
                 this,
-                &SkillManagerMonitorWidgetController::executeSkill);
+                &SkillManagerMonitorWidgetController::executeSelectedSkill);
 
         connect(widget.treeWidgetSkills,
                 &QTreeWidget::currentItemChanged,
@@ -396,8 +401,10 @@ namespace armarx
                 auto executionId = skills::SkillExecutionID::FromIce(k);
                 auto statusUpdate = skills::SkillStatusUpdate::FromIce(v);
 
-                // update snapshot
+                // update maps
                 skillStatusUpdates.insert_or_assign(executionId, statusUpdate);
+                skillExecutionParams.insert_or_assign(executionId,
+                                                      statusUpdate.usedParameterization);
 
                 SkillExecutionInfoTreeWidgetItem* found = nullptr;
                 for (int i = 0; i < widget.treeWidgetSkillExecutions->topLevelItemCount(); ++i)
@@ -468,31 +475,41 @@ namespace armarx
     }
 
     void
-    SkillManagerMonitorWidgetController::executeSkill()
+    SkillManagerMonitorWidgetController::executeSelectedSkill()
     {
-        if (not selectedSkill.skillId.fullySpecified())
-        {
-            return;
-        }
+        auto data = getConfigAsAron();
+        executeSkillWithParams(selectedSkill.skillId, data);
+    }
 
+    void
+    SkillManagerMonitorWidgetController::rerunSkillWithSimilarParams()
+    {
+        skills::SkillParameterization selectedExecutionParams =
+            skillExecutionParams.at(selectedSkill.skillExecutionId);
+        executeSkillWithParams(selectedSkill.skillExecutionId.skillId,
+                               selectedExecutionParams.parameterization);
+    }
+
+    void
+    SkillManagerMonitorWidgetController::executeSkillWithParams(skills::SkillID skillId,
+                                                                aron::data::DictPtr params)
+    {
         std::scoped_lock l(updateMutex);
 
-        auto providerId = skills::ProviderID(selectedSkill.skillId);
+        auto providerId = skills::ProviderID(skillId);
         const auto& skillDescriptions = skills.at(providerId);
-        if (skillDescriptions.find(selectedSkill.skillId) == skillDescriptions.end())
+        if (skillDescriptions.find(skillId) == skillDescriptions.end())
         {
             return;
         }
 
-        auto data = getConfigAsAron();
-
         char hostname[HOST_NAME_MAX];
         gethostname(hostname, HOST_NAME_MAX);
 
         skills::SkillExecutionRequest req(selectedSkill.skillId,
                                           "Skills.Manager GUI (hostname: " + std::string(hostname) +
                                               ")",
-                                          data);
+                                          params);
 
         ARMARX_CHECK(selectedSkill.skillId.fullySpecified()); // sanity check
         ARMARX_IMPORTANT << "Executing skill from GUI: " << selectedSkill.skillId << ".";
diff --git a/source/RobotAPI/gui-plugins/SkillManagerPlugin/SkillManagerMonitorWidgetController.h b/source/RobotAPI/gui-plugins/SkillManagerPlugin/SkillManagerMonitorWidgetController.h
index 4a7d0e79e..ce93db4e5 100644
--- a/source/RobotAPI/gui-plugins/SkillManagerPlugin/SkillManagerMonitorWidgetController.h
+++ b/source/RobotAPI/gui-plugins/SkillManagerPlugin/SkillManagerMonitorWidgetController.h
@@ -119,7 +119,7 @@ namespace armarx
         void skillExecutionSelectionChanged(QTreeWidgetItem* current, QTreeWidgetItem* previous);
 
         void stopSkill();
-        void executeSkill();
+        void executeSelectedSkill();
 
         void updateTimerFrequency();
         void refreshSkills();
@@ -131,6 +131,7 @@ namespace armarx
         void resetCurrentConfig();
 
         void prepareAndRunMenu(const QPoint& pos);
+        void rerunSkillWithSimilarParams();
 
 
     private:
@@ -151,6 +152,8 @@ namespace armarx
         std::map<skills::ProviderID, std::map<skills::SkillID, skills::SkillDescription>> skills =
             {};
         std::map<skills::SkillExecutionID, skills::SkillStatusUpdate> skillStatusUpdates = {};
+        // store copies (!) of skill descriptions
+        std::map<skills::SkillExecutionID, skills::SkillParameterization> skillExecutionParams = {};
 
         // User Input
         struct SelectedSkill
@@ -168,6 +171,8 @@ namespace armarx
             }
         } selectedSkill;
 
+        void executeSkillWithParams(skills::SkillID skillId, aron::data::DictPtr params);
+
         // Helper to get the treeWidgetItem easily
         QTreeWidgetItem* skillsArgumentsTreeWidgetItem = nullptr;
         AronTreeWidgetControllerPtr aronTreeWidgetController = nullptr;
-- 
GitLab