Merge branch 'master' of ssh://github.com/cthunter01/qtrocket

This commit is contained in:
Travis Hunter 2023-04-22 12:49:03 -06:00
commit ed5ecc766c
57 changed files with 3610 additions and 134 deletions

3
.gitignore vendored
View File

@ -34,6 +34,9 @@
# Build files and executable # Build files and executable
build/ build/
# Doxygen
docs/doxygen/*
# IDE # IDE
.vscode/qtrocket.pro.user .vscode/qtrocket.pro.user
qtrocket.pro.user qtrocket.pro.user

2694
Doxyfile Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1,12 +1,18 @@
#include "QtRocket.h"
#include "gui/MainWindow.h"
/// \cond
// C headers
// C++ headers
#include <thread>
// 3rd party headers
#include <QApplication> #include <QApplication>
#include <QLocale> #include <QLocale>
#include <QTranslator> #include <QTranslator>
/// \endcond
#include <thread> // qtrocket headers
#include "QtRocket.h"
#include "gui/MainWindow.h"
#include "sim/ConstantAtmosphere.h" #include "sim/ConstantAtmosphere.h"
#include "sim/ConstantGravityModel.h" #include "sim/ConstantGravityModel.h"

View File

@ -1,17 +1,22 @@
#ifndef QTROCKET_H #ifndef QTROCKET_H
#define QTROCKET_H #define QTROCKET_H
/// \cond
// C headers
// C++ headers
#include <atomic>
#include <memory> #include <memory>
#include <mutex> #include <mutex>
#include <atomic>
#include "utils/Logger.h" // 3rd party headers
/// \endcond
// qtrocket headers
#include "model/MotorModel.h"
#include "model/Rocket.h" #include "model/Rocket.h"
#include "sim/AtmosphericModel.h" #include "sim/AtmosphericModel.h"
#include "sim/GravityModel.h" #include "sim/GravityModel.h"
#include "utils/Logger.h"
#include "model/MotorModel.h"
/** /**
* @brief The QtRocket class is the master controller for the QtRocket application. * @brief The QtRocket class is the master controller for the QtRocket application.
@ -37,6 +42,11 @@ public:
void addMotorModels(std::vector<MotorModel>& m); void addMotorModels(std::vector<MotorModel>& m);
void addRocket(std::shared_ptr<Rocket> r) { rocket = r; }
std::shared_ptr<Rocket> getRocket() { return rocket; }
private: private:
QtRocket(); QtRocket();

View File

@ -1,9 +1,3 @@
# qtrocket # qtrocket
Model Rocket Simulator written in C++ and Qt Toolkit Soon to be model Rocket Simulator written in C++ and Qt Toolkit
QtRocket is still in the very early stages of development, and not suitable for any real use. It currently calculates the trajectory of a cannonball with the effects of air resistance. Some of the basic architecture is coming together, but the current implementation is only mature enough to create a cannonball and launch it.
This is also an experiment and learning platform for me to learn Qt GUI programming, so if it is non-standard or very strange to experienced Qt programmers, that's why.
Another feature is the use of ANSI standard C++17 for the bulk of the application. Qt specific features are limited to the GUI.

0
docs/doxygen/.gitkeep Normal file
View File

View File

@ -1,4 +1,5 @@
#include "AboutWindow.h" #include "AboutWindow.h"
#include "ui_AboutWindow.h" #include "ui_AboutWindow.h"
AboutWindow::AboutWindow(QWidget *parent) : AboutWindow::AboutWindow(QWidget *parent) :

View File

@ -1,12 +1,25 @@
#ifndef ABOUTWINDOW_H #ifndef ABOUTWINDOW_H
#define ABOUTWINDOW_H #define ABOUTWINDOW_H
/// \cond
// C headers
// C++ headers
// 3rd party headers
#include <QDialog> #include <QDialog>
/// \endcond
// qtrocket headers
namespace Ui { namespace Ui {
class AboutWindow; class AboutWindow;
} }
/**
* @brief The AboutWindow class
*
* The AboutWindow just displays some copyright information.
*
*/
class AboutWindow : public QDialog class AboutWindow : public QDialog
{ {
Q_OBJECT Q_OBJECT

View File

@ -1,14 +1,48 @@
#include "AnalysisWindow.h" #include "AnalysisWindow.h"
#include "ui_AnalysisWindow.h" #include "ui_AnalysisWindow.h"
#include "QtRocket.h"
AnalysisWindow::AnalysisWindow(QWidget *parent) : AnalysisWindow::AnalysisWindow(QWidget *parent) :
QMainWindow(parent), QDialog(parent),
ui(new Ui::AnalysisWindow) ui(new Ui::AnalysisWindow)
{ {
ui->setupUi(this); ui->setupUi(this);
this->setWindowModality(Qt::NonModal);
this->hide();
this->show();
std::shared_ptr<Rocket> rocket = QtRocket::getInstance()->getRocket();
const std::vector<std::pair<double, std::vector<double>>>& res = rocket->getStates();
/*
for(const auto& i : res)
{
std::cout << i.first << ": " << "(" << i.second[0] << ", " << i.second[1] << ", " << i.second[2] << ")\n";
}
*/
auto& plot = ui->plotWidget;
plot->setInteraction(QCP::iRangeDrag, true);
plot->setInteraction(QCP::iRangeZoom, true);
// generate some data:
QVector<double> tData(res.size()), zData(res.size());
for (int i = 0; i < tData.size(); ++i)
{
tData[i] = res[i].first;
zData[i] = res[i].second[2];
}
// create graph and assign data to it:
plot->addGraph();
plot->graph(0)->setData(tData, zData);
// give the axes some labels:
plot->xAxis->setLabel("time");
plot->yAxis->setLabel("Z");
// set axes ranges, so we see all data:
plot->xAxis->setRange(*std::min_element(std::begin(tData), std::end(tData)), *std::max_element(std::begin(tData), std::end(tData)));
plot->yAxis->setRange(*std::min_element(std::begin(zData), std::end(zData)), *std::max_element(std::begin(zData), std::end(zData)));
plot->replot();
} }
AnalysisWindow::~AnalysisWindow() AnalysisWindow::~AnalysisWindow()
{ {
delete ui; delete ui;
} }

View File

@ -1,22 +1,36 @@
#ifndef ANALYSISWINDOW_H #ifndef ANALYSISWINDOW_H
#define ANALYSISWINDOW_H #define ANALYSISWINDOW_H
#include <QMainWindow> /// \cond
// C
// C++
// 3rd party
#include <QDialog>
/// \endcond
// qtrocket headers
namespace Ui { namespace Ui {
class AnalysisWindow; class AnalysisWindow;
} }
class AnalysisWindow : public QMainWindow /**
* @brief The AnalysisWindow class.
*
* The Analysis Windows class shows a plot of data. This allows visual inspection of
* data
*/
class AnalysisWindow : public QDialog
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit AnalysisWindow(QWidget *parent = nullptr); explicit AnalysisWindow(QWidget *parent = nullptr);
~AnalysisWindow(); ~AnalysisWindow();
private: private:
Ui::AnalysisWindow *ui; Ui::AnalysisWindow *ui;
}; };
#endif // ANALYSISWINDOW_H #endif // ANALYSISWINDOW_H

View File

@ -1,48 +1,37 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0"> <ui version="4.0">
<class>AnalysisWindow</class> <class>AnalysisWindow</class>
<widget class="QMainWindow" name="AnalysisWindow"> <widget class="QDialog" name="AnalysisWindow">
<property name="geometry"> <property name="geometry">
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>800</width> <width>989</width>
<height>600</height> <height>821</height>
</rect> </rect>
</property> </property>
<property name="windowTitle"> <property name="windowTitle">
<string>MainWindow</string> <string>Dialog</string>
</property> </property>
<widget class="QWidget" name="centralwidget"> <widget class="QCustomPlot" name="plotWidget" native="true">
<widget class="QWidget" name="widget" native="true">
<property name="geometry">
<rect>
<x>9</x>
<y>9</y>
<width>701</width>
<height>351</height>
</rect>
</property>
</widget>
</widget>
<widget class="QMenuBar" name="menubar">
<property name="geometry"> <property name="geometry">
<rect> <rect>
<x>0</x> <x>19</x>
<y>0</y> <y>29</y>
<width>800</width> <width>961</width>
<height>22</height> <height>671</height>
</rect> </rect>
</property> </property>
<widget class="QMenu" name="menuFile">
<property name="title">
<string>File</string>
</property>
</widget>
<addaction name="menuFile"/>
</widget> </widget>
<widget class="QStatusBar" name="statusbar"/>
</widget> </widget>
<customwidgets>
<customwidget>
<class>QCustomPlot</class>
<extends>QWidget</extends>
<header>gui/qcustomplot.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<resources/> <resources/>
<connections/> <connections/>
</ui> </ui>

View File

@ -1,18 +1,28 @@
#include "MainWindow.h"
#include "ui_MainWindow.h"
#include "AboutWindow.h"
#include "utils/math/Vector3.h" /// \cond
#include "sim/RK4Solver.h" // C headers
#include "model/Rocket.h" // C++ headers
#include <cmath>
#include "utils/RSEDatabaseLoader.h" #include <iostream>
#include <memory>
// 3rd party headers
#include <QFileDialog> #include <QFileDialog>
#include <memory> /// \endcond
#include <iostream>
#include <cmath>
// qtrocket headers
#include "ui_MainWindow.h"
#include "gui/AboutWindow.h"
#include "gui/AnalysisWindow.h"
#include "gui/MainWindow.h"
#include "gui/ThrustCurveMotorSelector.h"
#include "model/Rocket.h"
#include "utils/RSEDatabaseLoader.h"
MainWindow::MainWindow(QtRocket* _qtRocket, QWidget *parent) MainWindow::MainWindow(QtRocket* _qtRocket, QWidget *parent)
: QMainWindow(parent), : QMainWindow(parent),
@ -79,13 +89,19 @@ void MainWindow::on_testButton2_clicked()
double initialVelocityX = initialVelocity * std::cos(initialAngle / 57.2958); double initialVelocityX = initialVelocity * std::cos(initialAngle / 57.2958);
double initialVelocityZ = initialVelocity * std::sin(initialAngle / 57.2958); double initialVelocityZ = initialVelocity * std::sin(initialAngle / 57.2958);
Rocket rocket; std::shared_ptr<Rocket> rocket = std::make_shared<Rocket>();
QtRocket::getInstance()->addRocket(rocket);
std::vector<double> initialState = {0.0, 0.0, 0.0, initialVelocityX, 0.0, initialVelocityZ, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}; std::vector<double> initialState = {0.0, 0.0, 0.0, initialVelocityX, 0.0, initialVelocityZ, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
rocket.setInitialState(initialState); rocket->setInitialState(initialState);
rocket.setMass(mass); rocket->setMass(mass);
rocket.setDragCoefficient(dragCoeff); rocket->setDragCoefficient(dragCoeff);
rocket.launch(); rocket->launch();
AnalysisWindow aWindow;
aWindow.setModal(false);
aWindow.exec();
/*
const std::vector<std::pair<double, std::vector<double>>>& res = rocket.getStates(); const std::vector<std::pair<double, std::vector<double>>>& res = rocket.getStates();
for(const auto& i : res) for(const auto& i : res)
{ {
@ -109,10 +125,10 @@ void MainWindow::on_testButton2_clicked()
plot->xAxis->setRange(*std::min_element(std::begin(tData), std::end(tData)), *std::max_element(std::begin(tData), std::end(tData))); plot->xAxis->setRange(*std::min_element(std::begin(tData), std::end(tData)), *std::max_element(std::begin(tData), std::end(tData)));
plot->yAxis->setRange(*std::min_element(std::begin(zData), std::end(zData)), *std::max_element(std::begin(zData), std::end(zData))); plot->yAxis->setRange(*std::min_element(std::begin(zData), std::end(zData)), *std::max_element(std::begin(zData), std::end(zData)));
plot->replot(); plot->replot();
*/
} }
void MainWindow::on_loadRSE_button_clicked() void MainWindow::on_loadRSE_button_clicked()
{ {
QString rseFile = QFileDialog::getOpenFileName(this, QString rseFile = QFileDialog::getOpenFileName(this,
@ -135,3 +151,12 @@ void MainWindow::on_loadRSE_button_clicked()
} }
} }
void MainWindow::on_getTCMotorData_clicked()
{
ThrustCurveMotorSelector window;
window.setModal(false);
window.exec();
}

View File

@ -1,8 +1,14 @@
#ifndef MAINWINDOW_H #ifndef MAINWINDOW_H
#define MAINWINDOW_H #define MAINWINDOW_H
/// \cond
// C headers
// C++ headers
// 3rd Party headers
#include <QMainWindow> #include <QMainWindow>
/// \endcond
// qtrocket headers
#include "QtRocket.h" #include "QtRocket.h"
@ -10,6 +16,13 @@ QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; } namespace Ui { class MainWindow; }
QT_END_NAMESPACE QT_END_NAMESPACE
/**
* @brief The MainWindow class
*
* The MainWindow class holds the primary GUI window of the application. All user interactions
* with QtRocket begin with interactions in this window. This window can spawn other windows.
*/
class MainWindow : public QMainWindow class MainWindow : public QMainWindow
{ {
Q_OBJECT Q_OBJECT
@ -27,6 +40,8 @@ private slots:
void on_loadRSE_button_clicked(); void on_loadRSE_button_clicked();
void on_getTCMotorData_clicked();
private: private:
Ui::MainWindow* ui; Ui::MainWindow* ui;
QtRocket* qtRocket; QtRocket* qtRocket;

View File

@ -188,7 +188,7 @@
<property name="geometry"> <property name="geometry">
<rect> <rect>
<x>90</x> <x>90</x>
<y>220</y> <y>250</y>
<width>421</width> <width>421</width>
<height>80</height> <height>80</height>
</rect> </rect>
@ -213,6 +213,19 @@
</item> </item>
</layout> </layout>
</widget> </widget>
<widget class="QPushButton" name="getTCMotorData">
<property name="geometry">
<rect>
<x>240</x>
<y>360</y>
<width>201</width>
<height>25</height>
</rect>
</property>
<property name="text">
<string>Get Thrustcurve Motor Data</string>
</property>
</widget>
</widget> </widget>
</widget> </widget>
<widget class="QCustomPlot" name="plotWindow" native="true"/> <widget class="QCustomPlot" name="plotWindow" native="true"/>

View File

@ -1,11 +1,21 @@
#ifndef ROCKETTREEVIEW_H #ifndef ROCKETTREEVIEW_H
#define ROCKETTREEVIEW_H #define ROCKETTREEVIEW_H
/// \cond
// C headers
// C++ headers
// 3rd party headers
#include <QTreeView> #include <QTreeView>
/// \endcond
// qtrocket headers
/** /**
* @brief RocketTreeView basically just renames QTreeView with a specific * @brief RocketTreeView basically just renames QTreeView with a specific
* memorable name. * memorable name.
*
* The purpose is to provide an exploded view of the components that make up the
* rocket design, and their relationships.
*/ */
class RocketTreeView : public QTreeView class RocketTreeView : public QTreeView
{ {

View File

@ -0,0 +1,67 @@
// qtrocket headers
#include "ThrustCurveMotorSelector.h"
#include "ui_ThrustCurveMotorSelector.h"
ThrustCurveMotorSelector::ThrustCurveMotorSelector(QWidget *parent) :
QDialog(parent),
ui(new Ui::ThrustCurveMotorSelector),
tcApi(new utils::ThrustCurveAPI)
{
ui->setupUi(this);
this->setWindowModality(Qt::NonModal);
this->hide();
this->show();
}
ThrustCurveMotorSelector::~ThrustCurveMotorSelector()
{
delete ui;
}
void ThrustCurveMotorSelector::on_getMetadata_clicked()
{
// When the user clicks "Get Metadata", we want to pull in Metadata from thrustcurve.org
// and populate the Manufacturer, Diameter, and Impulse Class combo boxes
utils::ThrustcurveMetadata metadata = tcApi->getMetadata();
for(const auto& i : metadata.diameters)
{
ui->diameter->addItem(QString::number(i));
}
for(const auto& i : metadata.manufacturers)
{
ui->manufacturer->addItem(QString::fromStdString(i.first));
}
for(const auto& i : metadata.impulseClasses)
{
ui->impulseClass->addItem(QString::fromStdString(i));
}
}
void ThrustCurveMotorSelector::on_searchButton_clicked()
{
//double diameter = ui->diameter->
std::string diameter = ui->diameter->currentText().toStdString();
std::string manufacturer = ui->manufacturer->currentText().toStdString();
std::string impulseClass = ui->impulseClass->currentText().toStdString();
utils::SearchCriteria c;
c.addCriteria("diameter", diameter);
c.addCriteria("manufacturer", manufacturer);
c.addCriteria("impulseClass", impulseClass);
std::vector<MotorModel> motors = tcApi->searchMotors(c);
for(const auto& i : motors)
{
ui->motorSelection->addItem(QString::fromStdString(i.commonName));
}
}

View File

@ -0,0 +1,42 @@
#ifndef THRUSTCURVEMOTORSELECTOR_H
#define THRUSTCURVEMOTORSELECTOR_H
/// \cond
// C headers
// C++ headers
#include <memory>
// 3rd party headers
#include <QDialog>
/// \endcond
// qtrocket headers
#include "utils/ThrustCurveAPI.h"
namespace Ui {
class ThrustCurveMotorSelector;
}
/**
* @brief The ThrustCurveMotorSelector class is a Window that provides an interface to Thrustcurve.org
*/
class ThrustCurveMotorSelector : public QDialog
{
Q_OBJECT
public:
explicit ThrustCurveMotorSelector(QWidget *parent = nullptr);
~ThrustCurveMotorSelector();
private slots:
void on_getMetadata_clicked();
void on_searchButton_clicked();
private:
Ui::ThrustCurveMotorSelector *ui;
std::unique_ptr<utils::ThrustCurveAPI> tcApi;
};
#endif // THRUSTCURVEMOTORSELECTOR_H

View File

@ -0,0 +1,127 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>ThrustCurveMotorSelector</class>
<widget class="QDialog" name="ThrustCurveMotorSelector">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>622</width>
<height>878</height>
</rect>
</property>
<property name="windowTitle">
<string>Dialog</string>
</property>
<widget class="QWidget" name="formLayoutWidget">
<property name="geometry">
<rect>
<x>170</x>
<y>90</y>
<width>160</width>
<height>101</height>
</rect>
</property>
<layout class="QFormLayout" name="formLayout">
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Manufacturer</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Diameter</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Impulse Class</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QComboBox" name="manufacturer"/>
</item>
<item row="1" column="1">
<widget class="QComboBox" name="diameter"/>
</item>
<item row="2" column="1">
<widget class="QComboBox" name="impulseClass"/>
</item>
</layout>
</widget>
<widget class="QPushButton" name="getMetadata">
<property name="geometry">
<rect>
<x>200</x>
<y>40</y>
<width>91</width>
<height>25</height>
</rect>
</property>
<property name="text">
<string>Get Metadata</string>
</property>
</widget>
<widget class="QCustomPlot" name="plot" native="true">
<property name="geometry">
<rect>
<x>10</x>
<y>320</y>
<width>601</width>
<height>551</height>
</rect>
</property>
</widget>
<widget class="QPushButton" name="searchButton">
<property name="geometry">
<rect>
<x>210</x>
<y>210</y>
<width>80</width>
<height>25</height>
</rect>
</property>
<property name="text">
<string>Search</string>
</property>
</widget>
<widget class="QWidget" name="formLayoutWidget_2">
<property name="geometry">
<rect>
<x>170</x>
<y>260</y>
<width>160</width>
<height>41</height>
</rect>
</property>
<layout class="QFormLayout" name="formLayout_2">
<item row="0" column="0">
<widget class="QPushButton" name="pushButton_2">
<property name="text">
<string>Download</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QComboBox" name="motorSelection"/>
</item>
</layout>
</widget>
</widget>
<customwidgets>
<customwidget>
<class>QCustomPlot</class>
<extends>QWidget</extends>
<header>gui/qcustomplot.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>

View File

@ -1,3 +1,11 @@
/// \cond
// C headers
// C++ headers
// 3rd party headers
/// \endcond
#include "QtRocket.h" #include "QtRocket.h"
#include "utils/Logger.h" #include "utils/Logger.h"

View File

@ -1,13 +1,19 @@
#ifndef MODEL_MOTORMODEL_H #ifndef MODEL_MOTORMODEL_H
#define MODEL_MOTORMODEL_H #define MODEL_MOTORMODEL_H
/// \cond
// C headers
// C++ headers
#include <string>
// 3rd party headers
// For boost serialization. We're using boost::serialize to save // For boost serialization. We're using boost::serialize to save
// and load Motor data to file // and load Motor data to file
#include <boost/archive/text_iarchive.hpp> #include <boost/archive/text_iarchive.hpp>
#include <boost/archive/text_oarchive.hpp> #include <boost/archive/text_oarchive.hpp>
/// \endcond
#include <string> // qtrocke theaders
#include "Thrustcurve.h" #include "Thrustcurve.h"
class MotorModel class MotorModel
@ -29,6 +35,8 @@ public:
OOP // Out of Production OOP // Out of Production
}; };
enum class CERTORG enum class CERTORG
{ {
AMRS, AMRS,
@ -116,7 +124,6 @@ public:
} }
}; };
// TODO: make these private. Public just for testing // TODO: make these private. Public just for testing
//private: //private:
// Needed for boost serialize // Needed for boost serialize
@ -132,7 +139,7 @@ public:
// int dataFiles // int dataFiles
std::vector<int> delays; // -1 delay means no ejection charge std::vector<int> delays; // -1 delay means no ejection charge
std::string designation{""}; std::string designation{""};
int diameter{0}; double diameter{0};
std::string impulseClass; // 'A', 'B', '1/2A', 'M', etc std::string impulseClass; // 'A', 'B', '1/2A', 'M', etc
std::string infoUrl{""}; std::string infoUrl{""};
double length{0.0}; double length{0.0};

View File

@ -1,11 +1,18 @@
#ifndef ROCKET_H #ifndef ROCKET_H
#define ROCKET_H #define ROCKET_H
#include "sim/Propagator.h" /// \cond
#include "model/Thrustcurve.h" // C headers
// C++ headers
#include <utility> // std::move
#include <memory> #include <memory>
#include <utility> // std::move
// 3rd party headers
/// \endcond
// qtrocket headers
#include "model/Thrustcurve.h"
#include "sim/Propagator.h"
class Rocket class Rocket
{ {
@ -27,8 +34,11 @@ public:
void setThrustCurve(const Thrustcurve& curve); void setThrustCurve(const Thrustcurve& curve);
bool terminateCondition(const std::pair<double, std::vector<double>>& cond); bool terminateCondition(const std::pair<double, std::vector<double>>& cond);
void setName(const std::string& n) { name = n; }
private: private:
std::string name;
sim::Propagator propagator; sim::Propagator propagator;
double dragCoeff; double dragCoeff;
double mass; double mass;

View File

@ -1,6 +1,14 @@
/// \cond
// C headers
// C++ headers
#include <algorithm>
// 3rd party headers
/// \endcond
#include "Thrustcurve.h" #include "Thrustcurve.h"
#include <algorithm>
Thrustcurve::Thrustcurve(std::vector<std::pair<double, double>>& tc) Thrustcurve::Thrustcurve(std::vector<std::pair<double, double>>& tc)
: thrustCurve(tc), : thrustCurve(tc),

View File

@ -1,11 +1,15 @@
#ifndef MODEL_THRUSTCURVE_H #ifndef MODEL_THRUSTCURVE_H
#define MODEL_THRUSTCURVE_H #define MODEL_THRUSTCURVE_H
/// \cond
// C headers
// C++ headers
#include <vector> #include <vector>
#include <tuple>
// 3rd party headers
#include <boost/archive/text_iarchive.hpp> #include <boost/archive/text_iarchive.hpp>
#include <boost/archive/text_oarchive.hpp> #include <boost/archive/text_oarchive.hpp>
/// \endcond
class Thrustcurve class Thrustcurve
{ {

View File

@ -12,6 +12,7 @@ SOURCES += \
QtRocket.cpp \ QtRocket.cpp \
gui/AboutWindow.cpp \ gui/AboutWindow.cpp \
gui/AnalysisWindow.cpp \ gui/AnalysisWindow.cpp \
gui/ThrustCurveMotorSelector.cpp \
gui/qcustomplot.cpp \ gui/qcustomplot.cpp \
main.cpp \ main.cpp \
gui/RocketTreeView.cpp \ gui/RocketTreeView.cpp \
@ -44,6 +45,7 @@ HEADERS += \
gui/AnalysisWindow.h \ gui/AnalysisWindow.h \
gui/RocketTreeView.h \ gui/RocketTreeView.h \
gui/MainWindow.h \ gui/MainWindow.h \
gui/ThrustCurveMotorSelector.h \
gui/qcustomplot.h \ gui/qcustomplot.h \
model/MotorCase.h \ model/MotorCase.h \
model/MotorModel.h \ model/MotorModel.h \
@ -78,7 +80,8 @@ HEADERS += \
FORMS += \ FORMS += \
gui/AboutWindow.ui \ gui/AboutWindow.ui \
gui/AnalysisWindow.ui \ gui/AnalysisWindow.ui \
gui/MainWindow.ui gui/MainWindow.ui \
gui/ThrustCurveMotorSelector.ui
TRANSLATIONS += \ TRANSLATIONS += \
qtrocket_en_US.ts qtrocket_en_US.ts
@ -92,8 +95,8 @@ else: unix:!android: target.path = /opt/$${TARGET}/bin
unix: CONFIG += link_pkgconfig unix: CONFIG += link_pkgconfig
unix: PKGCONFIG += libcurl unix: PKGCONFIG += libcurl
unix: PKGCONFIG += fmt unix: PKGCONFIG += fmt
unix: PKGCONFIG += jsoncpp
RESOURCES += \ RESOURCES += \
qtrocket.qrc qtrocket.qrc

BIN
resources/rocket48.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

View File

@ -1,6 +1,7 @@
#ifndef SIM_CONSTANTATMOSPHERE_H #ifndef SIM_CONSTANTATMOSPHERE_H
#define SIM_CONSTANTATMOSPHERE_H #define SIM_CONSTANTATMOSPHERE_H
// qtrocket headers
#include "AtmosphericModel.h" #include "AtmosphericModel.h"
namespace sim { namespace sim {

View File

@ -1,7 +1,8 @@
#ifndef SIM_CONSTANTGRAVITYMODEL_H #ifndef SIM_CONSTANTGRAVITYMODEL_H
#define SIM_CONSTANTGRAVITYMODEL_H #define SIM_CONSTANTGRAVITYMODEL_H
#include "GravityModel.h" // qtrocket headers
#include "sim/GravityModel.h"
#include "utils/Triplet.h" #include "utils/Triplet.h"
namespace sim { namespace sim {

View File

@ -1,8 +1,14 @@
#ifndef SIM_DESOLVER_H #ifndef SIM_DESOLVER_H
#define SIM_DESOLVER_H #define SIM_DESOLVER_H
/// \cond
// C headers
// C++ headers
#include <vector> #include <vector>
// 3rd party headers
/// \endcond
namespace sim namespace sim
{ {

View File

@ -1,6 +1,7 @@
#ifndef SIM_GRAVITYMODEL_H #ifndef SIM_GRAVITYMODEL_H
#define SIM_GRAVITYMODEL_H #define SIM_GRAVITYMODEL_H
// qtrocket headers
#include "utils/Triplet.h" #include "utils/Triplet.h"
namespace sim namespace sim

View File

@ -1,14 +1,23 @@
/// \cond
// C headers
// C++ headers
#include <chrono>
#include <iostream> #include <iostream>
#include <sstream>
#include <utility>
// 3rd party headers
/// \endcond
// qtrocket headers
#include "Propagator.h" #include "Propagator.h"
#include "sim/RK4Solver.h"
#include "model/Rocket.h"
#include "utils/Logger.h"
#include "QtRocket.h" #include "QtRocket.h"
#include "model/Rocket.h"
#include "sim/RK4Solver.h"
#include "utils/Logger.h"
#include <utility>
#include <chrono>
#include <sstream>
namespace sim { namespace sim {

View File

@ -1,11 +1,19 @@
#ifndef SIM_PROPAGATOR_H #ifndef SIM_PROPAGATOR_H
#define SIM_PROPAGATOR_H #define SIM_PROPAGATOR_H
#include "sim/DESolver.h" /// \cond
// C headers
// C++ headers
#include <memory> #include <memory>
#include <vector> #include <vector>
// 3rd party headers
/// \endcond
// qtrocket headers
#include "sim/DESolver.h"
// Forward declare // Forward declare
class Rocket; class Rocket;
class QtRocket; class QtRocket;

View File

@ -1,13 +1,21 @@
#ifndef SIM_RK4SOLVER_H #ifndef SIM_RK4SOLVER_H
#define SIM_RK4SOLVER_H #define SIM_RK4SOLVER_H
#include <functional> /// \cond
#include <vector> // C headers
#include <limits> // C++ headers
#include <cmath> #include <cmath>
#include <functional>
#include <limits>
#include <vector>
#include "utils/Logger.h" // 3rd party headers
/// \endcond
// qtrocket headers
#include "sim/DESolver.h" #include "sim/DESolver.h"
#include "utils/Logger.h"
namespace sim { namespace sim {

View File

@ -1,4 +1,6 @@
#include "SphericalGeoidModel.h"
// qtrocket headers
#include "sim/SphericalGeoidModel.h"
#include "utils/math/Constants.h" #include "utils/math/Constants.h"
namespace sim namespace sim

View File

@ -1,6 +1,7 @@
#ifndef SIM_SPHERICALGEOIDMODEL_H #ifndef SIM_SPHERICALGEOIDMODEL_H
#define SIM_SPHERICALGEOIDMODEL_H #define SIM_SPHERICALGEOIDMODEL_H
// qtrocket headers
#include "GeoidModel.h" #include "GeoidModel.h"
namespace sim namespace sim

View File

@ -1,8 +1,16 @@
#include "SphericalGravityModel.h"
/// \cond
// C headers
// C++ headers
#include <cmath>
// 3rd party headers
/// \endcond
// qtrocket headers
#include "sim/SphericalGravityModel.h"
#include "utils/math/Constants.h" #include "utils/math/Constants.h"
#include <cmath>
namespace sim namespace sim
{ {

View File

@ -1,6 +1,7 @@
#ifndef SIM_SPHERICALGRAVITYMODEL_H #ifndef SIM_SPHERICALGRAVITYMODEL_H
#define SIM_SPHERICALGRAVITYMODEL_H #define SIM_SPHERICALGRAVITYMODEL_H
// qtrocket headers
#include "GravityModel.h" #include "GravityModel.h"
namespace sim namespace sim

View File

@ -1,6 +1,7 @@
#ifndef STATEDATA_H #ifndef STATEDATA_H
#define STATEDATA_H #define STATEDATA_H
// qtrocket headers
#include "utils/math/Vector3.h" #include "utils/math/Vector3.h"
#include "utils/math/Quaternion.h" #include "utils/math/Quaternion.h"

View File

@ -1,8 +1,16 @@
#include "USStandardAtmosphere.h"
#include "utils/math/Constants.h" /// \cond
// C headers
// C++ headers
#include <cmath> #include <cmath>
// 3rd party headers
/// \endcond
// qtrocket headers
#include "sim/USStandardAtmosphere.h"
#include "utils/math/Constants.h"
using namespace utils::math; using namespace utils::math;
namespace sim namespace sim

View File

@ -1,7 +1,8 @@
#ifndef SIM_USSTANDARDATMOSPHERE_H #ifndef SIM_USSTANDARDATMOSPHERE_H
#define SIM_USSTANDARDATMOSPHERE_H #define SIM_USSTANDARDATMOSPHERE_H
#include "AtmosphericModel.h" // qtrocket headers
#include "sim/AtmosphericModel.h"
#include "utils/BinMap.h" #include "utils/BinMap.h"
namespace sim namespace sim

View File

@ -1,3 +1,5 @@
// qtrocket headers
#include "WindModel.h" #include "WindModel.h"
namespace sim namespace sim

View File

@ -1,6 +1,7 @@
#ifndef SIM_WINDMODEL_H #ifndef SIM_WINDMODEL_H
#define SIM_WINDMODEL_H #define SIM_WINDMODEL_H
// qtrocket headers
#include "utils/Triplet.h" #include "utils/Triplet.h"
namespace sim namespace sim

View File

@ -1,11 +1,17 @@
#include "BinMap.h"
/// \cond
// C headers
// C++ headers
#include <algorithm> #include <algorithm>
#include <stdexcept>
#include <sstream> #include <sstream>
#include <stdexcept>
// 3rd party headers
#include <fmt/core.h> #include <fmt/core.h>
/// \endcond
// qtrocket headers
#include "BinMap.h"
// TODO: Check on the availability of this in Clang. // TODO: Check on the availability of this in Clang.
// Replace libfmt with format when LLVM libc++ supports it // Replace libfmt with format when LLVM libc++ supports it

View File

@ -1,8 +1,14 @@
#ifndef UTILS_BINMAP_H #ifndef UTILS_BINMAP_H
#define UTILS_BINMAP_H #define UTILS_BINMAP_H
#include <vector> /// \cond
// C headers
// C++ headers
#include <utility> #include <utility>
#include <vector>
// 3rd party headers
/// \endcond
namespace utils { namespace utils {

View File

@ -1,7 +1,16 @@
#include "CurlConnection.h"
/// \cond
// C headers
// C++ headers
#include <iostream> #include <iostream>
// 3rd party headers
/// \endcond
// qtrocket headers
#include "utils/CurlConnection.h"
namespace namespace
{ {
size_t curlCallback(void* content, size_t size, size_t nmemb, std::string* buffer) size_t curlCallback(void* content, size_t size, size_t nmemb, std::string* buffer)

View File

@ -1,10 +1,17 @@
#ifndef UTILS_CURLCONNECTION_H #ifndef UTILS_CURLCONNECTION_H
#define UTILS_CURLCONNECTION_H #define UTILS_CURLCONNECTION_H
#include <vector> /// \cond
#include <string> // C headers
#include <curl/curl.h> #include <curl/curl.h>
// C++ headers
#include <string>
#include <vector>
// 3rd party headers
/// \endcond
namespace utils { namespace utils {
class CurlConnection class CurlConnection

View File

@ -1,7 +1,15 @@
#include "Logger.h"
/// \cond
// C headers
// C++ headers
#include <iostream> #include <iostream>
// 3rd party headers
/// \endcond
// qtrocket headers
#include "Logger.h"
namespace utils namespace utils
{ {
Logger* Logger::instance = nullptr; Logger* Logger::instance = nullptr;

View File

@ -1,16 +1,22 @@
#ifndef UTILS_LOGGER_H #ifndef UTILS_LOGGER_H
#define UTILS_LOGGER_H #define UTILS_LOGGER_H
/// \cond
// C headers
// C++ headers
#include <fstream> #include <fstream>
#include <mutex> #include <mutex>
#include <string_view> #include <string_view>
/** // 3rd party headers
* @todo write docs /// \endcond
*/
namespace utils namespace utils
{ {
/**
* @todo write docs
*/
class Logger class Logger
{ {
public: public:

View File

@ -1,10 +1,16 @@
#include "RSEDatabaseLoader.h"
#include <boost/property_tree/xml_parser.hpp>
/// \cond
// C headers
// C++ headers
#include <iostream> #include <iostream>
#include <cmath> #include <cmath>
// 3rd party headers
#include <boost/property_tree/xml_parser.hpp>
/// \endcond
// qtrocket headers
#include "utils/RSEDatabaseLoader.h"
#include "QtRocket.h" #include "QtRocket.h"
namespace utils { namespace utils {

View File

@ -1,12 +1,19 @@
#ifndef UTILS_RSEDATABASELOADER_H #ifndef UTILS_RSEDATABASELOADER_H
#define UTILS_RSEDATABASELOADER_H #define UTILS_RSEDATABASELOADER_H
#include "model/MotorModel.h"
#include <vector> /// \cond
// C headers
// C++ headers
#include <string> #include <string>
#include <vector>
// 3rd party headers
#include <boost/property_tree/ptree.hpp> #include <boost/property_tree/ptree.hpp>
/// \endcond
// qtrocket headers
#include "model/MotorModel.h"
namespace utils { namespace utils {

View File

@ -1,10 +1,16 @@
#ifndef TSQUEUE_H #ifndef TSQUEUE_H
#define TSQUEUE_H #define TSQUEUE_H
#include <mutex> /// \cond
#include <memory> // C headers
#include <queue> // C++ headers
#include <condition_variable> #include <condition_variable>
#include <memory>
#include <mutex>
#include <queue>
// 3rd party headers
/// \endcond
/** /**
* @brief The TSQueue class is a very basic thread-safe queue * @brief The TSQueue class is a very basic thread-safe queue

View File

@ -1,6 +1,15 @@
/// \cond
// C headers
// C++ headers
#include <cstdint>
// 3rd party headers
/// \endcond
// qtrocket headers
#include "ThreadPool.h" #include "ThreadPool.h"
#include <cstdint>
ThreadPool::ThreadPool() ThreadPool::ThreadPool()
: done(false), : done(false),

View File

@ -1,12 +1,19 @@
#ifndef THREADPOOL_H #ifndef THREADPOOL_H
#define THREADPOOL_H #define THREADPOOL_H
/// \cond
// C headers
// C++ headers
#include <atomic> #include <atomic>
#include <functional> #include <functional>
#include <vector>
#include <thread> #include <thread>
#include <vector>
#include "TSQueue.h" // 3rd party headers
/// \endcond
// qtrocket headers
#include "utils/TSQueue.h"
/** /**

View File

@ -1,4 +1,14 @@
#include "ThrustCurveAPI.h"
/// \cond
// C headers
// C++ headers
// 3rd party headers
#include <json/json.h>
/// \endcond
// qtrocket headers
#include "utils/ThrustCurveAPI.h"
#include "utils/Logger.h"
namespace utils namespace utils
{ {
@ -29,4 +39,168 @@ MotorModel ThrustCurveAPI::getMotorData(const std::string& motorId)
return mm; return mm;
} }
ThrustcurveMetadata ThrustCurveAPI::getMetadata()
{
std::string endpoint = hostname;
endpoint += "metadata.json";
std::string result = curlConnection.get(endpoint, extraHeaders);
ThrustcurveMetadata ret;
if(!result.empty())
{
try
{
Json::Reader reader;
Json::Value jsonResult;
reader.parse(result, jsonResult);
for(Json::ValueConstIterator iter = jsonResult["certOrgs"].begin();
iter != jsonResult["certOrgs"].end();
++iter)
{
std::string org = (*iter)["abbrev"].asString();
if(org == "AMRS")
ret.certOrgs.emplace_back(MotorModel::CERTORG::AMRS);
else if(org == "CAR")
ret.certOrgs.emplace_back(MotorModel::CERTORG::CAR);
else if(org == "NAR")
ret.certOrgs.emplace_back(MotorModel::CERTORG::NAR);
else if(org == "TRA")
ret.certOrgs.emplace_back(MotorModel::CERTORG::TRA);
else if(org == "UNC")
ret.certOrgs.emplace_back(MotorModel::CERTORG::UNC);
else
ret.certOrgs.emplace_back(MotorModel::CERTORG::UNK);
}
for(Json::ValueConstIterator iter = jsonResult["diameters"].begin();
iter != jsonResult["diameters"].end();
++iter)
{
ret.diameters.push_back((*iter).asDouble());
}
for(Json::ValueConstIterator iter = jsonResult["impulseClasses"].begin();
iter != jsonResult["impulseClasses"].end();
++iter)
{
ret.impulseClasses.emplace_back((*iter).asString());
}
for(Json::ValueConstIterator iter = jsonResult["manufacturers"].begin();
iter != jsonResult["manufacturers"].end();
++iter)
{
ret.manufacturers[(*iter)["abbrev"].asString()] = (*iter)["name"].asString();
}
for(Json::ValueConstIterator iter = jsonResult["types"].begin();
iter != jsonResult["types"].end();
++iter)
{
std::string type = (*iter)["types"].asString();
if(type == "SU")
ret.types.emplace_back(MotorModel::MOTORTYPE::SU);
else if(type == "reload")
ret.types.emplace_back(MotorModel::MOTORTYPE::RELOAD);
else
ret.types.emplace_back(MotorModel::MOTORTYPE::HYBRID);
}
}
catch(const std::exception& e)
{
std::string err("Unable to parse JSON from Thrustcurve metadata request. Error: ");
err += e.what();
Logger::getInstance()->error(err);
}
}
return ret;
}
std::vector<MotorModel> ThrustCurveAPI::searchMotors(const SearchCriteria& c)
{
std::vector<MotorModel> retVal;
std::string endpoint = hostname;
endpoint += "search.json?";
for(const auto& i : c.criteria)
{
endpoint += i.first;
endpoint += "=";
endpoint += i.second;
endpoint += "&";
}
endpoint = endpoint.substr(0, endpoint.length() - 1);
Logger::getInstance()->debug("endpoint: " + endpoint);
std::string result = curlConnection.get(endpoint, extraHeaders);
if(!result.empty())
{
try
{
Json::Reader reader;
Json::Value jsonResult;
reader.parse(result, jsonResult);
for(Json::ValueConstIterator iter = jsonResult["results"].begin();
iter != jsonResult["results"].end();
++iter)
{
MotorModel mm;
mm.commonName = (*iter)["commonName"].asString();
std::string availability = (*iter)["availability"].asString();
if(availability == "regular")
mm.availability = MotorModel::MotorAvailability(MotorModel::AVAILABILITY::REGULAR);
else
mm.availability = MotorModel::MotorAvailability(MotorModel::AVAILABILITY::OOP);
mm.avgThrust = (*iter)["avgThrustN"].asDouble();
mm.burnTime = (*iter)["burnTimeS"].asDouble();
// TODO fill in certOrg
// TODO fill in delays
mm.designation = (*iter)["designation"].asString();
mm.diameter = (*iter)["diameter"].asDouble();
mm.impulseClass = (*iter)["impulseClass"].asString();
mm.length = (*iter)["length"].asDouble();
mm.manufacturer = (*iter)["manufacturer"].asString();
mm.maxThrust = (*iter)["maxThrustN"].asDouble();
mm.motorIdTC = (*iter)["motorId"].asString();
mm.propType = (*iter)["propInfo"].asString();
mm.propWeight = (*iter)["propWeightG"].asDouble();
mm.sparky = (*iter)["sparky"].asBool();
mm.totalImpulse = (*iter)["totImpulseNs"].asDouble();
mm.totalWeight = (*iter)["totalWeightG"].asDouble();
std::string type = (*iter)["type"].asString();
if(type == "SU")
mm.type = MotorModel::MotorType(MotorModel::MOTORTYPE::SU);
else if(type == "reload")
mm.type = MotorModel::MotorType(MotorModel::MOTORTYPE::RELOAD);
else
mm.type = MotorModel::MotorType(MotorModel::MOTORTYPE::HYBRID);
retVal.push_back(mm);
}
}
catch(const std::exception& e)
{
std::string err("Unable to parse JSON from Thrustcurve metadata request. Error: ");
err += e.what();
Logger::getInstance()->error(err);
}
}
return retVal;
}
void SearchCriteria::addCriteria(const std::string& name,
const std::string& value)
{
criteria[name] = value;
}
} // namespace utils } // namespace utils

View File

@ -2,15 +2,61 @@
#define UTILS_THRUSTCURVEAPI_H #define UTILS_THRUSTCURVEAPI_H
/// \cond
// C headers
// C++ headers
#include <map>
#include <string> #include <string>
#include "CurlConnection.h" // 3rd party headers
/// \endcond
// qtrocket headers
#include "utils/CurlConnection.h"
#include "model/MotorModel.h" #include "model/MotorModel.h"
#include "model/Thrustcurve.h"
namespace utils namespace utils
{ {
class ThrustcurveMetadata
{
public:
ThrustcurveMetadata() = default;
~ThrustcurveMetadata() = default;
ThrustcurveMetadata(const ThrustcurveMetadata&) = default;
ThrustcurveMetadata(ThrustcurveMetadata&&) = default;
ThrustcurveMetadata& operator=(const ThrustcurveMetadata&) = default;
ThrustcurveMetadata& operator=(ThrustcurveMetadata&&) = default;
//private:
std::vector<MotorModel::CertOrg> certOrgs;
std::vector<double> diameters;
std::vector<std::string> impulseClasses;
std::map<std::string, std::string> manufacturers;
std::vector<MotorModel::MotorType> types;
};
class SearchCriteria
{
public:
SearchCriteria() = default;
~SearchCriteria() = default;
SearchCriteria(const SearchCriteria&) = default;
SearchCriteria(SearchCriteria&&) = default;
SearchCriteria& operator=(const SearchCriteria&) = default;
SearchCriteria& operator=(SearchCriteria&&) = default;
void addCriteria(const std::string& name,
const std::string& vaue);
std::map<std::string, std::string> criteria;
};
/** /**
* @brief This API for Thrustcurve.org - It will provide an interface for querying thrustcurve.org * @brief This API for Thrustcurve.org - It will provide an interface for querying thrustcurve.org
* for motor data * for motor data
@ -30,12 +76,23 @@ public:
MotorModel getMotorData(const std::string& motorId); MotorModel getMotorData(const std::string& motorId);
/**
* @brief getMetaData
*/
ThrustcurveMetadata getMetadata();
std::vector<MotorModel> searchMotors(const SearchCriteria& c);
private: private:
const std::string hostname; const std::string hostname;
CurlConnection curlConnection; CurlConnection curlConnection;
// no extra headers, but CurlConnection library wants them
const std::vector<std::string> extraHeaders{};
}; };
} // namespace utils } // namespace utils

View File

@ -1,4 +1,6 @@
#include "Quaternion.h"
// qtrocket headers
#include "utils/math/Quaternion.h"
namespace math namespace math
{ {

View File

@ -1,9 +1,17 @@
#ifndef MATH_QUATERNION_H #ifndef MATH_QUATERNION_H
#define MATH_QUATERNION_H #define MATH_QUATERNION_H
/// \cond
// C headers
// C++ headers
#include <utility>
// 3rd party headers
/// \endcond
// qtrocket headers
#include "Vector3.h" #include "Vector3.h"
#include <utility>
namespace math namespace math
{ {

View File

@ -1,4 +1,6 @@
#include "Vector3.h"
// qtrocket headers
#include "utils/math/Vector3.h"
namespace math namespace math
{ {