|
|
**Table of contents**
|
|
|
|
|
|
This is an intro section to give an overview of each topic presented in this Wiki document..
|
|
|
|
|
|
* [Introduction](#introduction)
|
|
|
* [Project setup](#project-setup)
|
|
|
* [Installing Qt](#installing-qt)
|
|
|
* [Cloning the repository](#cloning-the-repository)
|
|
|
* [Add a new Module](#add-a-new-module)
|
|
|
* [1. Create the module folder](#1-create-the-module-folder)
|
|
|
* [2. Create the module class](#2-create-the-module-class)
|
|
|
* [3. Insert the ModuleId](#3-insert-the-moduleid)
|
|
|
* [4. Add the module to the module factory](#4-add-the-module-to-the-module-factory)
|
|
|
* [5. Overrides the module abstract methods](#5-overrides-the-module-abstract-methods)
|
|
|
* [Using the default context menu](#using-the-default-context-menu)
|
|
|
|
|
|
# Introduction
|
|
|
|
|
|
The **SkywardHub** is an HMI (_Human-Machine Interface_) suite. The software is made of _Modules_ that can be arranged in different _configurations_ each of which is design for a specific purpose.
|
|
|
|
|
|
The **GroundStation** is one of the possible configurations of the modules, it is used for pre-flight operations, testing, and integration procedures.The main purpose of the GS is to enable the members of the team to monitor the state of the rocket and its subsystems. During all the phases of the mission, the GS configuration is made of modules that decode the data coming from the rocket through radio signals and display them in custom views designed to organize the data in a way that facilitates user analysis and real-time checks. Besides receiving telemetry data, remote commands can also be sent to the rocket, in order to perform the required integrity checks before the launch and, eventually, to manually control the actuators in case of necessity during flight. All the data received by the GS are logged for post-mission analysis.
|
|
|
|
|
|
Besides the GroundStation, the modules of the SkywardHub can be configured to offer a versatile tool for the development and testing process. The purpose of the SkywardHub is to offer a standard development framework for quick deployment and testing of new functionalities, ensuring a coherent design among all the HMI applications developed in Skyward. The modular and configurable design aims to guarantee a flexible UI and maintainable software for long-term compatibility with future mission requirements.
|
|
|
|
|
|
The modules are independent logical units implementing some specific functionalities. They communicate with each other through a _publisher-subscriber paradigm_. Inside a module, there may be more than one _panel_, all of them sharing some logic.
|
|
|
|
|
|
The MVC (Model-View-Controller) is implemented module level, while for the entire system there is a **Core** unit that acts as manager of the modules. The Core handles the communication between modules, defines some common logic such as the serialization and deserialization in xml of the entire application, and defines the messages that the modules exchange.
|
|
|
|
|
|
# Project setup
|
|
|
|
|
|
The project is developed using the Qt framework. To setup the project the following steps are required
|
|
|
|
|
|
1. Install the Qt libraries, a compatible compiler and an IDE
|
|
|
2. Clone the SkywardHub repository to access the project's source code
|
|
|
|
|
|
#### Installing Qt
|
|
|
|
|
|
Qt is a powerful library for HMI applications. The installer of the Qt framework can be found on the official Qt website, together with all the necessary information for the installation process.
|
|
|
|
|
|
It is worth mentioning two important aspect. With the installer you can configure which pakets to install. It is highly racomanted to use the tool provided by the Qt installer, therefore pay attention to select the following components
|
|
|
|
|
|
* The compiler
|
|
|
* The Qt library
|
|
|
* The IDE (Qt Creator)
|
|
|
|
|
|
### Cloning the repository
|
|
|
|
|
|
This is a standard operation that can be perform using a Git console or GUI.
|
|
|
|
|
|
**Prerequisite**
|
|
|
|
|
|
To be able to clone a repository with the ssh key, you must associate to your account an _autentication key_. This is a simple operation that can be done in the section [SSH Key](https://git.skywarder.eu/-/profile/keys) of your account settings.
|
|
|
|
|
|
**Clone**
|
|
|
|
|
|
1. From the GitLab repository, click on the _clone_ button and copy the SSH link to the SkywardHub repository.
|
|
|
2. On your pc, choose a working directory and open a Git terminal in that folder.
|
|
|
3. On the Git terminal, execute the command `git clone <repository link>`
|
|
|
4. In the same terminal, execute the command `git submodule update --init --recursive` to download the submodules such as mavlink_skyward_lib.
|
|
|
|
|
|
At this point you should have all the necessary components to start working on the project. The last step is to configure the Qt project to correctly link your working directory. Open Qt Creator and load the .pro file of the project. At this point, go in the _Projects_ tab of Qt Creator and set a _build directory_. If required, specify also the directory of the compiler you just installed.
|
|
|
|
|
|
# Add a new Module
|
|
|
|
|
|
To add a module the following steps are required
|
|
|
|
|
|
##### 1. Create the module folder
|
|
|
|
|
|
Create a folder inside the Module directory. The name of the folder is arbitrary but it is a good practice to name it with the module name.
|
|
|
|
|
|
##### 2. Create the module class
|
|
|
|
|
|
Create a class that will inherit from the abstract Module class and creates a UI class that will inherit from the QWidget class. These two classes can coincide, in this case, you can directly inherit from the DefaultModule class.
|
|
|
|
|
|
##### 3. Insert the ModuleId
|
|
|
|
|
|
Go to the ModuleInfo class and add a unique ID inside the ModuleId enum.
|
|
|
|
|
|
##### 4. Add the module to the module factory
|
|
|
|
|
|
Go to the ModulesList class and in the createModuleList() method append the following code
|
|
|
|
|
|
```plaintext
|
|
|
1. #ifdef <YOURMODULE_H>
|
|
|
2. ModuleInfo yourmodule(ModuleId::<module id>, "<modulename>", ModuleCategory::<chosen category>);
|
|
|
3. yourmodule.setFactory([](){return new MyModuleConstructure();});
|
|
|
4. yourmodule.addModuleSourceFiles("Modules/<your module folder>/");
|
|
|
5. addModuleInfo(yourmodule);
|
|
|
6. #endif
|
|
|
```
|
|
|
|
|
|
You can check the <YOURMODULE_H> variable in the top part of the .h file of your module.
|
|
|
|
|
|
With the line 2. you are creating a ModuleInfo variable that associate the module id with its name. The name will be the same displayed in the PickModulePanel and saved inside the XML configuration file. The Category will determine in which area of the module picker panel will be the button to instantiate the module.
|
|
|
|
|
|
With line 3. you are specifying the factory method to instantiate your module class. It can be a lambda that calls the class constructor.
|
|
|
|
|
|
With line 4. the module folder created at the first step is specified. This information will be used from the SkywardHub compiler for the auto-deployment feature.
|
|
|
|
|
|
##### 5. Overrides the module abstract methods
|
|
|
|
|
|
In order to implement the module class, you have to override the following three public abstract methods:
|
|
|
|
|
|
```plaintext
|
|
|
QWidget *toWidget() override;
|
|
|
XmlObject toXmlObject() override;
|
|
|
void fromXmlObject(const XmlObject &xmlObject) override;
|
|
|
```
|
|
|
|
|
|
The method toWidget() allows you to specify which View will be displayed as a panel inside the MainWindow. It is a good practice to create a view class and a model class that implements the logic. However, if the view and the model coincide, you can simply return this.
|
|
|
|
|
|
The toXmlObject and fromXmlObject specify methods to serialize the current model into an XML file to save and restore the configuration. If you do not have any data to save in the xml file, in the toXmlObject() method you can simply return the name of the current model.
|
|
|
|
|
|
Take as example the following code. Please remind that you should use the ModuleId you created in the previous step.
|
|
|
|
|
|
```plaintext
|
|
|
XmlObject<your module class>::toXmlObject(){
|
|
|
return XmlObject(getName(ModuleId::<your module id>));
|
|
|
}
|
|
|
```
|
|
|
|
|
|
While the fromXmlObject() can be left empty if you do not need to store any data in the xml.
|
|
|
|
|
|
##### Using the default context menu
|
|
|
|
|
|
At this point the module is created and insert inside the SkywardHub.
|
|
|
|
|
|
If you inherited from DefaultModule and you want to use the default options for the context menu add in the constructor the following line of code: defaultContextMenuSetup(); as in the following example.
|
|
|
|
|
|
```plaintext
|
|
|
EmptyModule::EmptyModule() : DefaultModule(), ui(new Ui::EmptyModule)
|
|
|
{
|
|
|
ui->setupUi(this);
|
|
|
defaultContextMenuSetup();
|
|
|
}
|
|
|
```
|
|
|
|
|
|
After this, to add QActions at the context menu override the method void addCustomActionsToMenu() override; as in the following example
|
|
|
|
|
|
```plaintext
|
|
|
void TableModule::addCustomActionsToMenu()
|
|
|
{
|
|
|
QAction* action= new QAction("<Action Name>");
|
|
|
connect(action, &QAction::triggered, this, &TableModule::onActionClicked);
|
|
|
|
|
|
addActionToMenu(action);
|
|
|
}
|
|
|
``` |
|
|
\ No newline at end of file |