From 2723ee7f1f97640f4a143d0b1c3c4f4401d15103 Mon Sep 17 00:00:00 2001 From: Giacomo Caironi <giacomo.caironi@skywarder.eu> Date: Thu, 22 Sep 2022 23:02:06 +0200 Subject: [PATCH] [OrientationVisualizer] Added new module to visualize the rocket orientation --- .vscode/c_cpp_properties.json | 1 + .vscode/settings.json | 5 +- CMakeLists.txt | 14 +- SkywardHub.pro | 2 +- sbs | 2 +- .../OrientationVisualizer.cpp | 184 ++++++++++++++++++ .../OrientationVisualizer.h | 26 +++ .../valuesconverterviewermodule.h | 1 - src/shared/Modules/moduleinfo.h | 1 + src/shared/Modules/moduleslist.cpp | 18 +- 10 files changed, 243 insertions(+), 11 deletions(-) create mode 100644 src/shared/Modules/OrientationVisualizer/OrientationVisualizer.cpp create mode 100644 src/shared/Modules/OrientationVisualizer/OrientationVisualizer.h diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json index 7c8dbf1e..5180384a 100644 --- a/.vscode/c_cpp_properties.json +++ b/.vscode/c_cpp_properties.json @@ -4,6 +4,7 @@ "name": "Linux", "includePath": [ "${workspaceFolder}/src/shared", + "${workspaceFolder}/libs/mavlink-skyward-lib", "~/Qt/5.15.2/**" ], "defines": [], diff --git a/.vscode/settings.json b/.vscode/settings.json index 614e1741..5be4d54f 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,5 +1,6 @@ { "files.associations": { + ".clang-format": "bibtex", "ratio": "cpp", "sstream": "cpp", "filesystem": "cpp", @@ -111,7 +112,9 @@ "qthread": "cpp", "qtopengl": "cpp", "forward_list": "cpp", - "cfenv": "cpp" + "cfenv": "cpp", + "qaspectengine": "cpp", + "qorbitcameracontroller": "cpp" }, "editor.defaultFormatter": "ms-vscode.cpptools", "[xml]": { diff --git a/CMakeLists.txt b/CMakeLists.txt index cb0d44cc..078a34d5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -31,9 +31,12 @@ set(CMAKE_AUTOMOC ON) set(CMAKE_AUTORCC ON) set(CMAKE_AUTOUIC ON) -find_package(Qt5 COMPONENTS Widgets REQUIRED) -find_package(Qt5 COMPONENTS SerialPort REQUIRED) -find_package(Qt5 COMPONENTS PrintSupport REQUIRED) +find_package(Qt5 REQUIRED COMPONENTS + Widgets + SerialPort + PrintSupport + 3DCore 3DExtras 3DRender 3DInput +) add_executable(groundstation src/shared/Components/ContextMenuSeparator/contextmenuseparator.cpp @@ -81,6 +84,7 @@ add_executable(groundstation src/shared/Modules/SkywardHub/prefabviewelement.cpp src/shared/Modules/SkywardHub/skywardhubmodule.cpp src/shared/Modules/Splitter/Splitter.cpp + src/shared/Modules/OrientationVisualizer/OrientationVisualizer.cpp src/shared/Modules/StateViewer/StateViewer.cpp src/shared/Modules/Tabs/tabsmodule.cpp src/shared/Modules/Test/testmodule.cpp @@ -98,6 +102,10 @@ target_link_libraries(groundstation PUBLIC Qt5::Widgets Qt5::SerialPort Qt5::PrintSupport + Qt5::3DCore + Qt5::3DExtras + Qt5::3DRender + Qt5::3DInput Mavlink::Mavlink ) if(APPLE) diff --git a/SkywardHub.pro b/SkywardHub.pro index 44076ea2..55b1d3ef 100644 --- a/SkywardHub.pro +++ b/SkywardHub.pro @@ -1,4 +1,4 @@ -QT += core gui +QT += core gui 3dcore 3drender 3dinput 3dlogic 3dextras 3danimation greaterThan(QT_MAJOR_VERSION, 4): QT += widgets printsupport serialport diff --git a/sbs b/sbs index 28adeff9..9dd12b16 100755 --- a/sbs +++ b/sbs @@ -322,7 +322,7 @@ EOF } CMAKE_FILENAME="CMakeCache.txt" -CMAKE_PREFIX_PATH="/Users/alberton/Qt/5.15.2/clang_64/lib/cmake/" +CMAKE_PREFIX_PATH="~/Qt/5.15.2/gcc_64/lib/cmake/" DEBUG_FILENAME=".sbsdebug" VERBOSE_FILENAME=".sbsverbose" BUILD_DIRNAME="build" diff --git a/src/shared/Modules/OrientationVisualizer/OrientationVisualizer.cpp b/src/shared/Modules/OrientationVisualizer/OrientationVisualizer.cpp new file mode 100644 index 00000000..956209a4 --- /dev/null +++ b/src/shared/Modules/OrientationVisualizer/OrientationVisualizer.cpp @@ -0,0 +1,184 @@ +#include "OrientationVisualizer.h" + +#include <Qt3DRender/qpointlight.h> + +#include <QSizePolicy> +#include <Qt3DCore/QAspectEngine> +#include <Qt3DCore/QEntity> +#include <Qt3DExtras/QConeMesh> +#include <Qt3DExtras/QFirstPersonCameraController> +#include <Qt3DExtras/QForwardRenderer> +#include <Qt3DExtras/QOrbitCameraController> +#include <Qt3DExtras/QPhongMaterial> +#include <Qt3DExtras/QSphereMesh> +#include <Qt3DExtras/QTorusMesh> +#include <Qt3DExtras/Qt3DWindow> +#include <Qt3DInput/QInputAspect> +#include <Qt3DRender/QCamera> +#include <Qt3DRender/QCameraLens> +#include <Qt3DRender/QGeometryRenderer> +#include <Qt3DRender/QRenderAspect> + +OrientationVisualizer::OrientationVisualizer(QWidget *parent) + : DefaultModule(parent) +{ + + setupUi(); + defaultContextMenuSetup(); + + updateOrientation(0, 0, 0, 1); + + getCore()->getModuleMessagesBroker()->subscribe( + {"Mav/PAYLOAD_FLIGHT_TM"}, this, + [this](const ModuleMessage &msg) + { + updateOrientation(msg.getField("nas_qx").getDouble(0.0), + msg.getField("nas_qy").getDouble(0.0), + msg.getField("nas_qz").getDouble(0.0), + msg.getField("nas_qw").getDouble(0.0)); + }); +} + +QWidget *OrientationVisualizer::toWidget() { return this; } + +XmlObject OrientationVisualizer::toXmlObject() +{ + XmlObject obj(getName(ModuleId::ORIENTATION_VISUALIZER)); + return obj; +} + +void OrientationVisualizer::fromXmlObject(const XmlObject &xmlObject) {} + +void OrientationVisualizer::setupUi() +{ + Qt3DExtras::Qt3DWindow *view = new Qt3DExtras::Qt3DWindow; + QWidget *windowContainer = QWidget::createWindowContainer(view); + + Qt3DCore::QEntity *rootEntity = new Qt3DCore::QEntity; + Qt3DCore::QEntity *rocketEntity = new Qt3DCore::QEntity(rootEntity); + + Qt3DExtras::QConeMesh *rocketMesh = new Qt3DExtras::QConeMesh(); + rocketMesh->setBottomRadius(10); + rocketMesh->setBottomRadius(3); + rocketMesh->setLength(20); + rocketMesh->setRings(100); + rocketMesh->setSlices(20); + + Qt3DExtras::QPhongMaterial *rocketMaterial = + new Qt3DExtras::QPhongMaterial(); + rocketMaterial->setDiffuse(QColor(QRgb(0x15628c))); + + rocketTransform = new Qt3DCore::QTransform(); + + rocketEntity->addComponent(rocketMesh); + rocketEntity->addComponent(rocketMaterial); + rocketEntity->addComponent(rocketTransform); + + // Spheres + + Qt3DExtras::QSphereMesh *sphereMesh = new Qt3DExtras::QSphereMesh; + sphereMesh->setRadius(3); + sphereMesh->setGenerateTangents(true); + + // Qt3DCore::QEntity *sphereEntity1 = new Qt3DCore::QEntity(rootEntity); + // Qt3DCore::QTransform *sphereTransform1 = new Qt3DCore::QTransform; + // sphereTransform1->setTranslation(QVector3D(0.0f, 0.0f, 5.0f)); + // Qt3DExtras::QPhongMaterial *sphereMaterial1 = new + // Qt3DExtras::QPhongMaterial(); + // sphereMaterial1->setDiffuse(QColor(QRgb(0xff0000))); + // sphereEntity1->addComponent(sphereMesh); + // sphereEntity1->addComponent(sphereTransform1); + // sphereEntity1->addComponent(sphereMaterial1); + + // Qt3DCore::QEntity *sphereEntity2 = new Qt3DCore::QEntity(rootEntity); + // Qt3DCore::QTransform *sphereTransform2 = new Qt3DCore::QTransform; + // sphereTransform2->setTranslation(QVector3D(0.0f, 5.0f, 0.0f)); + // Qt3DExtras::QPhongMaterial *sphereMaterial2 = new + // Qt3DExtras::QPhongMaterial(); + // sphereMaterial2->setDiffuse(QColor(QRgb(0x00ff00))); + // sphereEntity2->addComponent(sphereMesh); + // sphereEntity2->addComponent(sphereTransform2); + // sphereEntity2->addComponent(sphereMaterial2); + + // Qt3DCore::QEntity *sphereEntity3 = new Qt3DCore::QEntity(rootEntity); + // Qt3DCore::QTransform *sphereTransform3 = new Qt3DCore::QTransform; + // sphereTransform3->setTranslation(QVector3D(5.0f, 0.0f, 0.0f)); + // Qt3DExtras::QPhongMaterial *sphereMaterial3 = new + // Qt3DExtras::QPhongMaterial(); + // sphereMaterial3->setDiffuse(QColor(QRgb(0x0000ff))); + // sphereEntity3->addComponent(sphereMesh); + // sphereEntity3->addComponent(sphereTransform3); + // sphereEntity3->addComponent(sphereMaterial3); + + // Camera + Qt3DRender::QCamera *camera = view->camera(); + camera->lens()->setPerspectiveProjection(45.0f, 16.0f / 9.0f, 0.1f, + 1000.0f); + camera->setPosition(QVector3D(30.0f, 30.0f, 30.0f)); + camera->setViewCenter(QVector3D(0, 0, 0)); + camera->setUpVector(QVector3D(-1, -1, 1)); + + // Light + Qt3DCore::QEntity *lightEntity = new Qt3DCore::QEntity(rootEntity); + Qt3DRender::QPointLight *light = new Qt3DRender::QPointLight(lightEntity); + light->setColor("white"); + light->setIntensity(1); + lightEntity->addComponent(light); + Qt3DCore::QTransform *lightTransform = + new Qt3DCore::QTransform(lightEntity); + lightTransform->setTranslation(camera->position()); + lightEntity->addComponent(lightTransform); + + // For camera controls + // Qt3DExtras::QFirstPersonCameraController *camController = new + // Qt3DExtras::QFirstPersonCameraController(rootEntity); + // camController->setLinearSpeed( 50.0f ); + // camController->setLookSpeed( 180.0f ); + // camController->setCamera(camera); + + view->setRootEntity(rootEntity); + + // Visualizer of roll/pitch/yaw + QHBoxLayout *lower = new QHBoxLayout(); + + yawLabel = new QLabel(this); + yawLabel->setText("Y: 0.00"); + yawLabel->setAlignment(Qt::AlignCenter); + pitchLabel = new QLabel(this); + pitchLabel->setText("P: 0.00"); + pitchLabel->setAlignment(Qt::AlignCenter); + rollLabel = new QLabel(this); + rollLabel->setText("R: 0.00"); + rollLabel->setAlignment(Qt::AlignCenter); + this->setStyleSheet("QLabel {font-weight: bold;}"); + + lower->addWidget(yawLabel); + lower->addWidget(pitchLabel); + lower->addWidget(rollLabel); + + QVBoxLayout *container = new QVBoxLayout(this); + container->addWidget(windowContainer); + container->addLayout(lower); + + container->setStretch(0, 1); + container->setStretch(1, 0); +} + +void OrientationVisualizer::updateOrientation(double qx, double qy, double qz, + double qw) +{ + float yaw, pitch, roll; + + QQuaternion quaternion(QVector4D(qx, qy, qz, qw)); + quaternion.getEulerAngles(&pitch, &yaw, &roll); + + yawLabel->setText(QString::asprintf("Y: %.2lf", yaw)); + pitchLabel->setText(QString::asprintf("P: %.2lf", pitch)); + rollLabel->setText(QString::asprintf("R: %.2lf", roll)); + + QQuaternion displayQuaternion = QQuaternion::fromRotationMatrix( + quaternion.toRotationMatrix() * + QQuaternion::fromEulerAngles(90, 0, 0).toRotationMatrix()); + + rocketTransform->setRotation(displayQuaternion); +} diff --git a/src/shared/Modules/OrientationVisualizer/OrientationVisualizer.h b/src/shared/Modules/OrientationVisualizer/OrientationVisualizer.h new file mode 100644 index 00000000..a14d7657 --- /dev/null +++ b/src/shared/Modules/OrientationVisualizer/OrientationVisualizer.h @@ -0,0 +1,26 @@ +#pragma once + +#include <Modules/DefaultModule/defaultmodule.h> + +#include <Qt3DCore/QTransform> + +class OrientationVisualizer : public DefaultModule +{ + Q_OBJECT + +public: + explicit OrientationVisualizer(QWidget* parent = nullptr); + + QWidget* toWidget() override; + + XmlObject toXmlObject() override; + void fromXmlObject(const XmlObject& xmlObject) override; + +private: + QLabel *rollLabel, *pitchLabel, *yawLabel; + + Qt3DCore::QTransform* rocketTransform; + + void updateOrientation(double qx, double qy, double qz, double qw); + void setupUi(); +}; diff --git a/src/shared/Modules/ValuesConverterViewer/valuesconverterviewermodule.h b/src/shared/Modules/ValuesConverterViewer/valuesconverterviewermodule.h index 873b9d6a..53a8543e 100644 --- a/src/shared/Modules/ValuesConverterViewer/valuesconverterviewermodule.h +++ b/src/shared/Modules/ValuesConverterViewer/valuesconverterviewermodule.h @@ -17,7 +17,6 @@ class ValuesConverterViewerModule; class ValuesConverterViewerModule : public DefaultModule { - Q_OBJECT public: diff --git a/src/shared/Modules/moduleinfo.h b/src/shared/Modules/moduleinfo.h index 4ebac8d7..76b29257 100644 --- a/src/shared/Modules/moduleinfo.h +++ b/src/shared/Modules/moduleinfo.h @@ -18,6 +18,7 @@ enum ModuleId INCOMINGMESSAGESVIEWER, MAVLINK, FILESTREAM, + ORIENTATION_VISUALIZER, STATEVIEWER, VALUESCONVERTERVIEWER, MAVLINK_RCK_TESTING, diff --git a/src/shared/Modules/moduleslist.cpp b/src/shared/Modules/moduleslist.cpp index 44d46182..6076b53a 100644 --- a/src/shared/Modules/moduleslist.cpp +++ b/src/shared/Modules/moduleslist.cpp @@ -9,6 +9,7 @@ #include <Modules/IncomingMessagesViewer/incomingmessagesviewermodule.h> #include <Modules/Mavlink/mavlinkmodule.h> #include <Modules/Mavlink/mavlinkrocketmsgtestingmodule.h> +#include <Modules/OrientationVisualizer/OrientationVisualizer.h> #include <Modules/OutgoingMessagesViewer/outgoingmessagesviewermodule.h> #include <Modules/SkywardHub/skywardhubmodule.h> #include <Modules/Splitter/Splitter.h> @@ -113,14 +114,23 @@ void ModulesList::createModuleList() stateViewer.addModuleSourceFiles("Modules/StateViewer/"); addModuleInfo(stateViewer); - ModuleInfo valuesconverterviewer(ModuleId::VALUESCONVERTERVIEWER, + ModuleInfo valuesConverterViewer(ModuleId::VALUESCONVERTERVIEWER, "ValuesConverterViewer", ModuleCategory::UTILITY); - valuesconverterviewer.setFactory( + valuesConverterViewer.setFactory( []() { return new ValuesConverterViewerModule(); }); - valuesconverterviewer.addModuleSourceFiles( + valuesConverterViewer.addModuleSourceFiles( "Modules/ValuesConverterViewer/"); - addModuleInfo(valuesconverterviewer); + addModuleInfo(valuesConverterViewer); + + ModuleInfo orientationVisualizer(ModuleId::ORIENTATION_VISUALIZER, + "OrientationVisualizer", + ModuleCategory::UTILITY); + orientationVisualizer.setFactory([]() + { return new OrientationVisualizer(); }); + orientationVisualizer.addModuleSourceFiles( + "Modules/OrientationVisualizer/"); + addModuleInfo(orientationVisualizer); ModuleInfo timerController(ModuleId::TIMER_CONTROLLER, "TimerController", ModuleCategory::UTILITY); -- GitLab