208 tab.maxEntries.setRange(1, 100);
209 tab.maxEntries.setValue(guiMaxEntries);
214 settingsGrid.
add(
Label(
"Max Entries"),
Pos{0, col++});
215 settingsGrid.
add(tab.maxEntries,
Pos{0, col++});
220 settingsGroup.
addChild(settingsGrid);
223 std::vector<armem::task_outcome::TaskOutcome> outcomes;
224 std::vector<armem::MemoryID> outcomeIds;
229 [&outcomes, &outcomeIds](
const auto& providerSegment)
231 providerSegment.forEachEntity(
232 [&outcomes, &outcomeIds](
const auto& entity)
234 entity.forEachSnapshot(
235 [&outcomes, &outcomeIds](
const auto& snapshot)
237 snapshot.forEachInstance(
238 [&outcomes, &outcomeIds](
const auto& instance)
243 armarx::task_outcome::arondto::
244 TaskOutcome::FromAron(
248 outcomes.push_back(bo);
249 outcomeIds.push_back(instance.id());
261 if (
static_cast<int>(outcomes.size()) > guiMaxEntries)
263 const int excess =
static_cast<int>(outcomes.size()) - guiMaxEntries;
264 outcomes.erase(outcomes.begin(), outcomes.begin() + excess);
265 outcomeIds.erase(outcomeIds.begin(), outcomeIds.begin() + excess);
270 std::vector<size_t> idx(outcomes.size());
271 std::iota(idx.begin(), idx.end(), 0);
272 std::sort(idx.begin(),
274 [&outcomes](
size_t a,
size_t b)
275 { return outcomes[a].endTime > outcomes[b].endTime; });
277 std::vector<armem::task_outcome::TaskOutcome> sortedOutcomes(outcomes.size());
278 std::vector<armem::MemoryID> sortedIds(outcomeIds.size());
279 for (
size_t i = 0; i < idx.size(); ++i)
281 sortedOutcomes[i] = std::move(outcomes[idx[i]]);
282 sortedIds[i] = std::move(outcomeIds[idx[i]]);
284 outcomes = std::move(sortedOutcomes);
285 outcomeIds = std::move(sortedIds);
289 if (selectedOutcomeIndex >=
static_cast<int>(outcomes.size()))
291 selectedOutcomeIndex = -1;
294 displayedOutcomeIds = outcomeIds;
297 tab.selectButtons.clear();
307 resultsGrid.
add(
Label(
"Failure Types"),
Pos{row, 3});
314 for (
int i = 0; i < static_cast<int>(outcomes.size()); ++i)
316 const auto& outcome = outcomes[i];
318 auto& btn = tab.selectButtons[i];
319 btn.setLabel(
"select");
320 btn.setValue(i == selectedOutcomeIndex);
322 const std::string failureStr =
323 outcome.failureInfo.has_value()
324 ? failureTypeSummary(outcome.failureInfo->failureType)
327 const std::string recoveredStr =
328 outcome.couldRecover.has_value()
329 ? (outcome.couldRecover.value() ?
"yes" :
"no")
332 resultsGrid.
add(btn,
Pos{row, 0});
333 resultsGrid.
add(
Label(truncateStr(outcome.taskName, 20)),
Pos{row, 1});
335 Label(outcomeTypeToString(outcome.outcomeType)),
Pos{row, 2});
336 resultsGrid.
add(
Label(truncateStr(failureStr, 50)),
Pos{row, 3});
337 resultsGrid.
add(
Label(taskTypeToString(outcome.taskType)),
Pos{row, 4});
338 resultsGrid.
add(
Label(outcome.endTime.toTimeString()),
Pos{row, 5});
341 Label(truncateStr(outcome.errorMessage.value_or(
"-"), 35)),
Pos{row, 7});
346 const std::string resultsLabel =
347 "Task Outcomes (" + std::to_string(outcomes.size()) +
" entries)";
349 resultsGroup.
setLabel(resultsLabel);
355 constexpr size_t detailMaxLen = 80;
358 if (selectedOutcomeIndex >= 0 &&
359 selectedOutcomeIndex <
static_cast<int>(outcomes.size()))
361 const auto& sel = outcomes[selectedOutcomeIndex];
362 detailGroup.
setLabel(
"Selected: " + sel.taskName);
368 detailGrid.
add(
Label(truncateStr(sel.taskName, detailMaxLen)),
Pos{row, 1});
372 detailGrid.
add(
Label(outcomeTypeToString(sel.outcomeType)),
Pos{row, 1});
376 detailGrid.
add(
Label(taskTypeToString(sel.taskType)),
Pos{row, 1});
379 if (sel.specialTaskTypeDescription.has_value())
381 detailGrid.
add(
Label(
"Special Type"),
Pos{row, 0});
382 detailGrid.
add(
Label(truncateStr(sel.specialTaskTypeDescription.value(), detailMaxLen)),
Pos{row, 1});
387 detailGrid.
add(
Label(truncateStr(sel.agent, detailMaxLen)),
Pos{row, 1});
391 detailGrid.
add(
Label(sel.startTime.toTimeString()),
Pos{row, 1});
395 detailGrid.
add(
Label(sel.endTime.toTimeString()),
Pos{row, 1});
399 detailGrid.
add(
Label(truncateStr(sel.errorMessage.value_or(
"-"), detailMaxLen)),
Pos{row, 1});
403 const std::string failureStr = sel.failureInfo.has_value()
404 ? failureTypeSummary(sel.failureInfo->failureType)
407 detailGrid.
add(
Label(
"Failure Types"),
Pos{row, 0});
408 detailGrid.
add(
Label(truncateStr(failureStr, detailMaxLen)),
Pos{row, 1});
412 if (sel.failureInfo.has_value() &&
413 sel.failureInfo->specialFailureDescription.has_value())
415 detailGrid.
add(
Label(
"Failure Desc"),
Pos{row, 0});
417 Label(truncateStr(sel.failureInfo->specialFailureDescription.value(), detailMaxLen)),
422 detailGrid.
add(
Label(
"Could Recover"),
Pos{row, 0});
424 Label(sel.couldRecover.has_value()
425 ? (sel.couldRecover.value() ?
"true" :
"false")
430 if (sel.recoveryInfo.has_value())
432 detailGrid.
add(
Label(
"Recovery Time"),
Pos{row, 0});
434 Label(sel.recoveryInfo->recoveryTime.toTimeString()),
Pos{row, 1});
437 detailGrid.
add(
Label(
"Recovery Measure"),
Pos{row, 0});
439 Label(truncateStr(sel.recoveryInfo->recoveryMeasure, detailMaxLen)),
445 detailGrid.
add(
Label(truncateStr(sel.context.skillName, detailMaxLen)),
Pos{row, 1});
448 if (sel.context.skillExecutionStartedTimestamp.has_value())
450 detailGrid.
add(
Label(
"Skill Exec Started"),
Pos{row, 0});
451 detailGrid.
add(
Label(sel.context.skillExecutionStartedTimestamp->toTimeString()),
Pos{row, 1});
455 if (sel.context.naturalLanguageDescription.has_value())
458 detailGrid.
add(
Label(truncateStr(sel.context.naturalLanguageDescription.value(), detailMaxLen)),
Pos{row, 1});
462 for (
const auto& [key, value] : sel.context.parameters)
464 detailGrid.
add(
Label(
"Param: " + key),
Pos{row, 0});
465 detailGrid.
add(
Label(truncateStr(value, detailMaxLen)),
Pos{row, 1});
469 for (
const auto& [key, value] : sel.context.additional)
471 detailGrid.
add(
Label(
"Extra: " + key),
Pos{row, 0});
472 detailGrid.
add(
Label(truncateStr(value, detailMaxLen)),
Pos{row, 1});
476 for (
const auto& [key, value] : sel.context.taskPreconditions.items())
478 detailGrid.
add(
Label(
"Precond: " + key),
Pos{row, 0});
479 detailGrid.
add(
Label(truncateStr(value.dump(), detailMaxLen)),
Pos{row, 1});
483 for (
const auto& [key, value] : sel.context.taskPostconditions.items())
485 detailGrid.
add(
Label(
"Postcond: " + key),
Pos{row, 0});
486 detailGrid.
add(
Label(truncateStr(value.dump(), detailMaxLen)),
Pos{row, 1});
494 detailGroup.
setLabel(
"Selected: (none)");
495 detailGroup.
addChild(
Label(
"Click \"select\" on a row to select an outcome."));
505 const bool hasSelection = selectedOutcomeIndex >= 0 &&
506 selectedOutcomeIndex < static_cast<int>(outcomes.size());
508 if (selectionJustChanged)
510 editStatusMessage =
"";
513 const auto& sel = outcomes[selectedOutcomeIndex];
514 editErrorText = sel.errorMessage.value_or(
"");
515 editStatus = outcomeTypeToString(sel.outcomeType);
516 editFailureType = sel.failureInfo.has_value()
517 ? sel.failureInfo->failureType
523 editStatus =
"UNKNOWN";
526 selectionJustChanged =
false;
529 tab.statusComboBox.setOptions({
"UNKNOWN",
"SUCCESS",
"FAILURE",
"ABORTED",
"SUSPENDED"});
530 tab.statusComboBox.setValue(editStatus);
533 tab.failureCheckBoxes.planningNoTrajectoryFound.setValue(editFailureType.planning.noTrajectoryFound);
534 tab.failureCheckBoxes.planningNoGraspFound.setValue(editFailureType.planning.noGraspFound);
535 tab.failureCheckBoxes.planningSpecial.setValue(editFailureType.planning.special);
536 tab.failureCheckBoxes.perceptionObjectNotDetected.setValue(editFailureType.knowledge.perception.objectNotDetected);
537 tab.failureCheckBoxes.perceptionCameraNotWorking.setValue(editFailureType.knowledge.perception.cameraNotWorking);
538 tab.failureCheckBoxes.knowledgeRetrievalTechnicalFailure.setValue(editFailureType.knowledge.knowledgeRetrieval.technicalFailure);
539 tab.failureCheckBoxes.knowledgeRetrievalKnowledgeNotInMemory.setValue(editFailureType.knowledge.knowledgeRetrieval.knowledgeNotInMemory);
540 tab.failureCheckBoxes.executionRobotNotMoving.setValue(editFailureType.execution.robotNotMoving);
541 tab.failureCheckBoxes.executionHandNotClosing.setValue(editFailureType.execution.handNotClosing);
542 tab.failureCheckBoxes.executionGraspingFailureDetected.setValue(editFailureType.execution.graspingFailureDetected);
543 tab.failureCheckBoxes.interactionNoHumanForHandover.setValue(editFailureType.interaction.noHumanForHandover);
544 tab.failureCheckBoxes.interactionDesiredObjectNotAtLocation.setValue(editFailureType.interaction.desiredObjectNotAtLocation);
545 tab.failureCheckBoxes.interactionCommunicationFailure.setValue(editFailureType.interaction.communicationFailure);
546 tab.failureCheckBoxes.interruptionUserStopped.setValue(editFailureType.interruption.userStopped);
547 tab.failureCheckBoxes.subskillFailureFailed.setValue(editFailureType.subskillFailure.failed);
548 tab.failureCheckBoxes.subskillFailureName.setValue(editFailureType.subskillFailure.subskillName);
550 tab.errorMessageInput.setValue(editErrorText);
551 tab.saveButton.setLabel(
"Save");
557 editGrid.
add(
Label(
"Select an outcome to edit."),
Pos{editRow, 0});
562 editGrid.
add(tab.statusComboBox,
Pos{editRow, 0});
568 planningGroup.
setLabel(
"Planning Failures");
570 planningGrid.
add(tab.failureCheckBoxes.planningNoTrajectoryFound,
Pos{0, 0});
571 planningGrid.
add(
Label(
"No Trajectory Found"),
Pos{0, 1});
572 planningGrid.
add(tab.failureCheckBoxes.planningNoGraspFound,
Pos{1, 0});
573 planningGrid.
add(
Label(
"No Grasp Found"),
Pos{1, 1});
574 planningGrid.
add(tab.failureCheckBoxes.planningSpecial,
Pos{2, 0});
576 planningGroup.
addChild(planningGrid);
577 editGrid.
add(planningGroup,
Pos{editRow, 0});
584 knowledgeGroup.
setLabel(
"Knowledge Failures");
587 knowledgeGrid.
add(
Label(
"-- Perception --"),
Pos{kRow, 0},
Span{1, 2});
589 knowledgeGrid.
add(tab.failureCheckBoxes.perceptionObjectNotDetected,
Pos{kRow, 0});
590 knowledgeGrid.
add(
Label(
"Object Not Detected"),
Pos{kRow, 1});
592 knowledgeGrid.
add(tab.failureCheckBoxes.perceptionCameraNotWorking,
Pos{kRow, 0});
593 knowledgeGrid.
add(
Label(
"Camera Not Working"),
Pos{kRow, 1});
595 knowledgeGrid.
add(
Label(
"-- Knowledge Retrieval --"),
Pos{kRow, 0},
Span{1, 2});
597 knowledgeGrid.
add(tab.failureCheckBoxes.knowledgeRetrievalTechnicalFailure,
Pos{kRow, 0});
598 knowledgeGrid.
add(
Label(
"Technical Failure"),
Pos{kRow, 1});
600 knowledgeGrid.
add(tab.failureCheckBoxes.knowledgeRetrievalKnowledgeNotInMemory,
Pos{kRow, 0});
601 knowledgeGrid.
add(
Label(
"Knowledge Not In Memory"),
Pos{kRow, 1});
602 knowledgeGroup.
addChild(knowledgeGrid);
603 editGrid.
add(knowledgeGroup,
Pos{editRow, 0});
610 executionGroup.
setLabel(
"Execution Failures");
612 executionGrid.
add(tab.failureCheckBoxes.executionRobotNotMoving,
Pos{0, 0});
613 executionGrid.
add(
Label(
"Robot Not Moving"),
Pos{0, 1});
614 executionGrid.
add(tab.failureCheckBoxes.executionHandNotClosing,
Pos{1, 0});
615 executionGrid.
add(
Label(
"Hand Not Closing"),
Pos{1, 1});
616 executionGrid.
add(tab.failureCheckBoxes.executionGraspingFailureDetected,
Pos{2, 0});
617 executionGrid.
add(
Label(
"Grasping Failure Detected"),
Pos{2, 1});
618 executionGroup.
addChild(executionGrid);
619 editGrid.
add(executionGroup,
Pos{editRow, 0});
626 interactionGroup.
setLabel(
"Interaction Failures");
628 interactionGrid.
add(tab.failureCheckBoxes.interactionNoHumanForHandover,
Pos{0, 0});
629 interactionGrid.
add(
Label(
"No Human For Handover"),
Pos{0, 1});
630 interactionGrid.
add(tab.failureCheckBoxes.interactionDesiredObjectNotAtLocation,
Pos{1, 0});
631 interactionGrid.
add(
Label(
"Desired Object Not At Location"),
Pos{1, 1});
632 interactionGrid.
add(tab.failureCheckBoxes.interactionCommunicationFailure,
Pos{2, 0});
633 interactionGrid.
add(
Label(
"Communication Failure"),
Pos{2, 1});
634 interactionGroup.
addChild(interactionGrid);
635 editGrid.
add(interactionGroup,
Pos{editRow, 0});
642 interruptionGroup.
setLabel(
"Interruption Failures");
644 interruptionGrid.
add(tab.failureCheckBoxes.interruptionUserStopped,
Pos{0, 0});
645 interruptionGrid.
add(
Label(
"User Stopped"),
Pos{0, 1});
646 interruptionGroup.
addChild(interruptionGrid);
647 editGrid.
add(interruptionGroup,
Pos{editRow, 0});
654 subskillGroup.
setLabel(
"Subskill Failure");
656 subskillGrid.
add(tab.failureCheckBoxes.subskillFailureFailed,
Pos{0, 0});
658 subskillGrid.
add(
Label(
"Subskill Name:"),
Pos{1, 0});
659 subskillGrid.
add(tab.failureCheckBoxes.subskillFailureName,
Pos{1, 1});
660 subskillGroup.
addChild(subskillGrid);
661 editGrid.
add(subskillGroup,
Pos{editRow, 0});
665 editGrid.
add(
Label(
"Error Message:"),
Pos{editRow, 0});
667 editGrid.
add(tab.errorMessageInput,
Pos{editRow, 0});
669 editGrid.
add(tab.saveButton,
Pos{editRow, 0});
671 const std::string messageHtml = editStatusMessage.empty()
673 :
"<font color='red'>" + editStatusMessage +
"</font>";
686 bool needsRebuild =
false;
689 editErrorText = tab.errorMessageInput.getValue();
690 editStatus = tab.statusComboBox.getValue();
691 editFailureType.planning.noTrajectoryFound = tab.failureCheckBoxes.planningNoTrajectoryFound.getValue();
692 editFailureType.planning.noGraspFound = tab.failureCheckBoxes.planningNoGraspFound.getValue();
693 editFailureType.planning.special = tab.failureCheckBoxes.planningSpecial.getValue();
694 editFailureType.knowledge.perception.objectNotDetected = tab.failureCheckBoxes.perceptionObjectNotDetected.getValue();
695 editFailureType.knowledge.perception.cameraNotWorking = tab.failureCheckBoxes.perceptionCameraNotWorking.getValue();
696 editFailureType.knowledge.knowledgeRetrieval.technicalFailure = tab.failureCheckBoxes.knowledgeRetrievalTechnicalFailure.getValue();
697 editFailureType.knowledge.knowledgeRetrieval.knowledgeNotInMemory = tab.failureCheckBoxes.knowledgeRetrievalKnowledgeNotInMemory.getValue();
698 editFailureType.execution.robotNotMoving = tab.failureCheckBoxes.executionRobotNotMoving.getValue();
699 editFailureType.execution.handNotClosing = tab.failureCheckBoxes.executionHandNotClosing.getValue();
700 editFailureType.execution.graspingFailureDetected = tab.failureCheckBoxes.executionGraspingFailureDetected.getValue();
701 editFailureType.interaction.noHumanForHandover = tab.failureCheckBoxes.interactionNoHumanForHandover.getValue();
702 editFailureType.interaction.desiredObjectNotAtLocation = tab.failureCheckBoxes.interactionDesiredObjectNotAtLocation.getValue();
703 editFailureType.interaction.communicationFailure = tab.failureCheckBoxes.interactionCommunicationFailure.getValue();
704 editFailureType.interruption.userStopped = tab.failureCheckBoxes.interruptionUserStopped.getValue();
705 editFailureType.subskillFailure.failed = tab.failureCheckBoxes.subskillFailureFailed.getValue();
706 editFailureType.subskillFailure.subskillName = tab.failureCheckBoxes.subskillFailureName.getValue();
708 if (tab.maxEntries.hasValueChanged())
710 guiMaxEntries = tab.maxEntries.getValue();
715 for (
auto& [
index, btn] : tab.selectButtons)
717 if (btn.hasValueChanged() && btn.getValue())
719 selectedOutcomeIndex =
index;
720 selectionJustChanged =
true;
723 else if (btn.hasValueChanged() && !btn.getValue() &&
724 index == selectedOutcomeIndex)
726 selectedOutcomeIndex = -1;
727 selectionJustChanged =
true;
733 if (tab.saveButton.wasClicked() && selectedOutcomeIndex >= 0 &&
734 selectedOutcomeIndex <
static_cast<int>(displayedOutcomeIds.size()))
736 const std::string newError = tab.errorMessageInput.getValue();
737 const std::string newStatus = tab.statusComboBox.getValue();
738 const auto&
id = displayedOutcomeIds[selectedOutcomeIndex];
740 const auto newOutcomeType = stringToOutcomeType(newStatus);
742 editStatusMessage =
"";
748 .getProviderSegment(
id.providerSegmentName)
749 .getEntity(
id.entityName)
751 .getInstance(
id.instanceIndex);
753 auto dto = armarx::task_outcome::arondto::TaskOutcome::FromAron(
757 dto.errorMessage = newError.empty()
758 ? std::optional<std::string>(std::nullopt)
759 : std::optional<std::string>(newError);
765 if (!dto.failureInfo.has_value())
767 armarx::task_outcome::arondto::FailureInfo fi;
770 dto.failureInfo = fi;
774 instance.data() = dto.toAron();
776 ARMARX_INFO <<
"Updated outcome for '" <<
id.entityName
777 <<
"': status=" << newStatus
778 <<
", failures=" << failureTypeSummary(editFailureType)
779 <<
", error='" << newError <<
"'";
781 catch (
const std::exception& e)
790 if (selectedOutcomeIndex < 0 && newDataAvailable.exchange(
false))