armem_gui Directory Reference
+ Directory dependency graph for armem_gui:

Directories

 controller
 
 core
 
 model
 
 util
 
 view
 

Files

 MemoryViewer.cpp
 
 MemoryViewer.h
 

Detailed Description

Issue boards: [Bugs]( .../-/issues/?sort=updated_desc&state=opened&label_name[]=bug&first_page_size=20 ) [Migration]( .../-/issues/?sort=updated_desc&state=opened&label_name[]=migration&first_page_size=20 ) [Requests]( .../-/issues/?sort=updated_desc&state=opened&label_name[]=migration&first_page_size=20 ) | Setup: [Installation]( ./Installation.md ) | Maintainer: [Code owners]( ./.gitlab/CODEOWNERS )

[[TOC]]


Foreword

The armem_gui package provides a graphical interface for interacting with the ArmarX Memory system. It is designed to support users in visualizing and managing memory-related data. The GUI consists of the following core interface elements, that form the Memory Viewer:

Terms and Concepts

The armem_guifollows a Model-View-Controller design pattern. In this structure:

Structure of this Package

Folderstrucutre

The folder structure of the armem_gui package follows the MVC architecture used throughout the module. Each of the main directories reflects one of the core MVC responsibilities:

The package additionaly includes several supporting folders:

Codestructure

In this GUI, each major component (except the status label) has its own dedicated controller:

The MemoryViewer starts by creating the DiskIOController and the PeriodicUpdateController. The PeriodicUpdateController then creates the MemoryGroupBoxController, which then creates the InstanceGroupBoxController.

The GUI is composed of the following view components:

The following diagram shows the general relationsship between the GUI components: Class relations

Usage Example

Opening the Memory Viewer

There are multiple ways to open the Memory Viewer after starting ArmarXGUI.

  1. One way is to go to Add Widget on the menu bar, then ArMem and MemoryViewer.
  2. You can also use the button shaped like a brain underneath the menu bar, left to the Widget Search field.

Displaying memories in the Memory Tree

First of all, at least the armar7_l1_1_low_level_components_sim and armar7_l2_1_memory_sim scenarios must be running. If so, the available memories will be listed in the Query Settings tab. The memories can be selected here and after clicking on the Update button, the Memory Tree will display the selected memories. Instead of manually clicking Update all the time, it is possible to activate Auto Update, which may slow down the system.

When selecting an Entity instance in the Memory Tree, the entity-specific data is shown in the Instance View, which is located on the right side of the Memory Viewer.

Using the tab group

Query Settings

This tab allows you to check/uncheck the available memory checkboxes and provides some additional query settings.

Snapshot Selection

This tab allows you to select different snapshot forms, that are used as the query input.

Prediction

Generates predictions unsing a prediction engine. Not maintained at the moment!

Commit

Not maintained at the moment!

LTM

Allows you to independently select available memories for long term memory recording.

Loading and Storing from/to disk

The Store shown Data on Disk button allows to store the data of the selected memories in a folder on the disk, which can later be loaded back in with the Load Query from Disk into WM button.

Scenarios

The Memory Viewer can be opened and explored without any scenarios running in the background. However to actively interact with memories, at least the following scenarios must be running:

Scenario Minimal set of components that need to work
armar7_l2_1_memory_sim RobotAPI
armar7_l1_1_low_level_components_sim ArmarXGui, RobotAPI

How To

How To add a new button

The folowing example shows how to extend an existing view component. In this case the DiskIOView. The same procedure applies to any other view in this package. We will add a new button to the widget to trigger a custom controller action using Qt's signal/slot mechanism.

  1. Add a new button to the view

In DiskIOView.h, declare the button as a private member:

private:
QPushButton* _tutorialButton;

In the constructur of DiskIOView.cpp, create the button and add it to the layout:

...
_tutorialButton = new QPushButton("Tutorial", this);
...
layout->addWidget(_tutorialButton);

After rebuilding, the new button will appear in the GUI. However, at this point it does not trigger any behavior.

  1. Create a signal for the button

In DiskIOView.h, declare a new signal that will be emitted when the button is pressed:

signals:
void tutorialSignal();

Next, connect the button press to the signal in the constructor in DiskIOView.cpp:

connect(_tutorialButton, &QPushButton::pressed, this, &This::tutorialSignal);
  1. Handle the signal in the controller

To react to this signal, add a correspondig slot in DiskIOController.h:

private slots:
void onTutorialSignal();

Then implement the slot in DiskIOController.cpp. In our case it is only a message to the console, but technically you can implement new functionality here:

void DiskIOController::onTutorialSignal()
{
ARMARX_INFO << "Tutorial message!";
}
#define ARMARX_INFO
The normal logging level.
Definition Logging.h:181

Finally, connect the view's signal with the controller's slot in the DiskIOController.cpp constructor:

connect(_diskIOView, &armem::gui::view::DiskIOView::tutorialSignal, this, &This::onTutorialSignal);

After rebuilding and running the application again, pressing the new button will trigger the controller slot and print:

Tutorial message

How To add a new tab to the tab group

If you want to add new funtionality, that does not fit in any of the existing tabs/widgets, it is possible to add a new tab in the existing tab group.

Lets start by creating a new folder tutorial_widget in view/memory_group, where all existing tabs can be found. In tutorial_widget create a new header file TutorialWidget.h with the following content:

#pragma once
#include <QWidget>
{
class TutorialWidget : public QWidget
{
Q_OBJECT
using This = TutorialWidget;
public:
TutorialWidget();
public slots:
private slots:
signals:
private:
};
} // namespace armarx::armem::gui

Now let's create the source file TutorialWidget.cpp with the content:

#include "TutorialWidget.h"
#include <QVBoxLayout>
{
TutorialWidget::TutorialWidget()
{
auto* vlayout = new QVBoxLayout();
setLayout(vlayout);
}
} // namespace armarx::armem::gui

Most widgets use a QVBoxLayout, but any layout can be used here.

Now TutorialWidget.h and TutorialWidget.cpp need to be added to the HEADERS/**SOURCES** in the CMakeLists.txt.

Next the new tab needs to be added to the existing tab group, which is located in MemoryGroupBoxView. In MemoryGroupBoxView.h add the new private member:

TutorialWidget* _tutorialWidget;

and add the include:

#include <RobotAPI/libraries/armem_gui/view/memory_group/tutorial_widget/TutorialWidget.h>

Now in the constructor in MemoryGroupBoxView.cpp add the new Widget to the tab group:

{
_tutorialWidget = new armem::gui::TutorialWidget();
_tutorialWidget->setSizePolicy(QSizePolicy::Policy::Expanding,
QSizePolicy::Policy::Maximum);
_memoryTabWidget->addTab(_tutorialWidget, QString("Tutorial"));
}

After rebuilding and running the application a new empty tab will show up. New functionality can be added here. To learn how to add a button we refer to the previous tutorial.

Troubleshooting

  1. Loading queries from disk may cause crashes: A known issue can occur when loading queries or memories from disk. If the data on disk is incomplete or corrupted, the GUI may crash during the import process.
  2. Long loading and storing times for large datasets: The operations Load from Disk and Store on Disk can take a significant amount of time for large datasets.

Feedback

If you experience any problems with this documentation, or find certain aspects not to be covered, please feel free to create an issue. This helps us to keep the documentation up to date and to improve it. Thank you!