diff --git a/.gitignore b/.gitignore index dba50a0..0067128 100644 --- a/.gitignore +++ b/.gitignore @@ -37,3 +37,5 @@ build/ # IDE .vscode/qtrocket.pro.user qtrocket.pro.user +.qmake.stash + diff --git a/QtRocket.cpp b/QtRocket.cpp index 69454b9..caef6ff 100644 --- a/QtRocket.cpp +++ b/QtRocket.cpp @@ -1,15 +1,17 @@ #include "QtRocket.h" -#include "ui_QtRocket.h" -QtRocket::QtRocket(QWidget *parent) - : QMainWindow(parent) - , ui(new Ui::QtRocket) +QtRocket* QtRocket::instance = nullptr; + +QtRocket* QtRocket::getInstance() { - ui->setupUi(this); + if(!instance) + { + instance = new QtRocket(); + } + return instance; } -QtRocket::~QtRocket() +QtRocket::QtRocket() { - delete ui; + logger = utils::Logger::getInstance(); } - diff --git a/QtRocket.h b/QtRocket.h index a68464b..33e5216 100644 --- a/QtRocket.h +++ b/QtRocket.h @@ -1,21 +1,27 @@ #ifndef QTROCKET_H #define QTROCKET_H -#include +#include "utils/Logger.h" +#include "gui/MainWindow.h" -QT_BEGIN_NAMESPACE -namespace Ui { class QtRocket; } -QT_END_NAMESPACE - -class QtRocket : public QMainWindow +/** + * @brief The QtRocket class is the master controller for the QtRocket application. + * It is the singleton that controls the interaction of the various components of + * the QtRocket program + */ +class QtRocket { - Q_OBJECT - public: - QtRocket(QWidget *parent = nullptr); - ~QtRocket(); - + static QtRocket* getInstance(); private: - Ui::QtRocket *ui; + QtRocket(); + + static QtRocket* instance; + + utils::Logger* logger; + + + }; + #endif // QTROCKET_H diff --git a/QtRocket.ui b/QtRocket.ui deleted file mode 100644 index 4dc9439..0000000 --- a/QtRocket.ui +++ /dev/null @@ -1,116 +0,0 @@ - - - QtRocket - - - - 0 - 0 - 1031 - 694 - - - - QtRocket - - - - :/qtrocket.png:/qtrocket.png - - - - - - - Qt::Vertical - - - - - 0 - 2 - - - - Qt::Horizontal - - - - - 0 - 0 - - - - - - - 2 - 0 - - - - - - 30 - 20 - 80 - 25 - - - - PushButton - - - - - - 30 - 70 - 80 - 25 - - - - PushButton - - - - - - - - 0 - 1 - - - - - - - - - - - 0 - 0 - 1031 - 22 - - - - - - - - QCustomPlot - QWidget -
qcustomplot.h
- 1 -
-
- - - - -
diff --git a/gui/AboutWindow.cpp b/gui/AboutWindow.cpp new file mode 100644 index 0000000..4fc59fe --- /dev/null +++ b/gui/AboutWindow.cpp @@ -0,0 +1,21 @@ +#include "AboutWindow.h" +#include "ui_AboutWindow.h" + +AboutWindow::AboutWindow(QWidget *parent) : + QDialog(parent), + ui(new Ui::AboutWindow) +{ + ui->setupUi(this); + + setWindowTitle(QString("About QtRocket")); +} + +AboutWindow::~AboutWindow() +{ + delete ui; +} + +void AboutWindow::on_pushButton_clicked() +{ + this->close(); +} diff --git a/gui/AboutWindow.h b/gui/AboutWindow.h new file mode 100644 index 0000000..8e05a10 --- /dev/null +++ b/gui/AboutWindow.h @@ -0,0 +1,25 @@ +#ifndef ABOUTWINDOW_H +#define ABOUTWINDOW_H + +#include + +namespace Ui { +class AboutWindow; +} + +class AboutWindow : public QDialog +{ + Q_OBJECT + +public: + explicit AboutWindow(QWidget *parent = nullptr); + ~AboutWindow(); + +private slots: + void on_pushButton_clicked(); + +private: + Ui::AboutWindow *ui; +}; + +#endif // ABOUTWINDOW_H diff --git a/gui/AboutWindow.ui b/gui/AboutWindow.ui new file mode 100644 index 0000000..9293576 --- /dev/null +++ b/gui/AboutWindow.ui @@ -0,0 +1,48 @@ + + + AboutWindow + + + + 0 + 0 + 400 + 300 + + + + Dialog + + + + + 80 + 60 + 261 + 151 + + + + true + + + Copyright (c) 2023 by Travis Hunter + + + + + + 250 + 240 + 80 + 25 + + + + OK + + + + + + diff --git a/gui/MainWindow.cpp b/gui/MainWindow.cpp new file mode 100644 index 0000000..93a8feb --- /dev/null +++ b/gui/MainWindow.cpp @@ -0,0 +1,130 @@ +#include "MainWindow.h" +#include "ui_MainWindow.h" +#include "AboutWindow.h" + +#include "utils/math/Vector3.h" +#include "sim/RK4Solver.h" + +#include + +#include +#include + +MainWindow::MainWindow(QWidget *parent) + : QMainWindow(parent) + , ui(new Ui::MainWindow) +{ + ui->setupUi(this); +} + +MainWindow::~MainWindow() +{ + delete ui; +} + + +void MainWindow::on_actionAbout_triggered() +{ + AboutWindow about; + about.setModal(true); + about.exec(); + +} + + +void MainWindow::on_testButton1_clicked() +{ + auto& plot = ui->plotWindow; + // generate some data: + QVector x(101), y(101); // initialize with entries 0..100 + for (int i=0; i<101; ++i) + { + x[i] = i/50.0 - 1; // x goes from -1 to 1 + y[i] = x[i]*x[i]; // let's plot a quadratic function + } + // create graph and assign data to it: + plot->addGraph(); + plot->graph(0)->setData(x, y); + // give the axes some labels: + plot->xAxis->setLabel("x"); + plot->yAxis->setLabel("y"); + // set axes ranges, so we see all data: + plot->xAxis->setRange(-1, 1); + plot->yAxis->setRange(0, 1); + plot->replot(); + +} + + +void MainWindow::on_testButton2_clicked() +{ + // Get the initial conditions + double initialVelocity = + ui->rocketPartButtons->findChild(QString("initialVelocity"))->text().toDouble(); + + double mass = + ui->rocketPartButtons->findChild(QString("mass"))->text().toDouble(); + + double initialAngle = + ui->rocketPartButtons->findChild(QString("initialAngle"))->text().toDouble(); + + double dragCoeff = + ui->rocketPartButtons->findChild(QString("dragCoeff"))->text().toDouble(); + + double initialVelocityX = initialVelocity * std::cos(initialAngle / 57.2958); + double initialVelocityY = initialVelocity * std::sin(initialAngle / 57.2958); + math::Vector3 initialVelVector(initialVelocityX, initialVelocityY, 0.0); + std::vector position; + position.emplace_back(0.0, 0.0, 0.0); + + std::vector velocity; + velocity.push_back(initialVelVector); + + double ts = 0.01; + + sim::RK4Solver velXSolver([=](double x, double t) -> double { return 0.0; }); + velXSolver.setTimeStep(ts); + sim::RK4Solver velYSolver([=](double y, double t) -> double { return -9.8; }); + velYSolver.setTimeStep(ts); + + sim::RK4Solver posXSolver([=](double x, double t) -> double { return velXSolver.step(x, t); }); + posXSolver.setTimeStep(ts); + sim::RK4Solver posYSolver([=](double y, double t) -> double { return velYSolver.step(x, t); }); + posYSolver.setTimeStep(ts); + + + // These can be solved independently for now. Maybe figure out how to merge them later + size_t maxTs = std::ceil(100.0 / ts); + QTextStream cout(stdout); + cout << "Initial X velocity: " << initialVelocityX << "\n"; + cout << "Initial Y velocity: " << initialVelocityY << "\n"; + for(size_t i = 0; i < maxTs; ++i) + { + position.emplace_back(posXSolver.step(position[i].getX1(), i * ts), + posYSolver.step(position[i].getX2(), i * ts), + 0.0); + + cout << "(" << position[i].getX1() << ", " << position[i].getX2() << ")\n"; + + } + + auto& plot = ui->plotWindow; + // generate some data: + QVector x(position.size()), y(position.size()); + for (int i = 0; i < x.size(); ++i) + { + x[i] = position[i].getX1(); + y[i] = position[i].getX2(); + } + // create graph and assign data to it: + plot->addGraph(); + plot->graph(0)->setData(x, y); + // give the axes some labels: + plot->xAxis->setLabel("x"); + plot->yAxis->setLabel("y"); + // set axes ranges, so we see all data: + plot->xAxis->setRange(*std::min_element(std::begin(x), std::end(x)), *std::max_element(std::begin(x), std::end(x))); + plot->yAxis->setRange(*std::min_element(std::begin(y), std::end(y)), *std::max_element(std::begin(y), std::end(y))); + plot->replot(); +} + diff --git a/gui/MainWindow.h b/gui/MainWindow.h new file mode 100644 index 0000000..767356f --- /dev/null +++ b/gui/MainWindow.h @@ -0,0 +1,28 @@ +#ifndef QTROCKET_H +#define QTROCKET_H + +#include + +QT_BEGIN_NAMESPACE +namespace Ui { class MainWindow; } +QT_END_NAMESPACE + +class MainWindow : public QMainWindow +{ + Q_OBJECT + +public: + MainWindow(QWidget *parent = nullptr); + ~MainWindow(); + +private slots: + void on_actionAbout_triggered(); + + void on_testButton1_clicked(); + + void on_testButton2_clicked(); + +private: + Ui::MainWindow* ui; +}; +#endif // QTROCKET_H diff --git a/gui/MainWindow.ui b/gui/MainWindow.ui new file mode 100644 index 0000000..25efea6 --- /dev/null +++ b/gui/MainWindow.ui @@ -0,0 +1,279 @@ + + + MainWindow + + + + 0 + 0 + 1031 + 694 + + + + QtRocket + + + + :/images/resources/rocket64.png:/images/resources/rocket64.png + + + + + + 6 + 6 + 1021 + 631 + + + + + 0 + 0 + + + + Qt::Vertical + + + true + + + + Qt::Horizontal + + + true + + + + + 0 + 0 + + + + + + + 2 + 0 + + + + + + 30 + 20 + 80 + 25 + + + + + 0 + 0 + + + + TestButton1 + + + + + + 30 + 70 + 191 + 25 + + + + + 0 + 0 + + + + Calculate Ballistic Trajectory + + + + + + 260 + 80 + 161 + 120 + + + + + + + Velocity + + + + + + + + + + Angle + + + + + + + + + + mass + + + + + + + + + + Cd + + + + + + + + + + + + + + + + + 0 + 0 + 1031 + 22 + + + + + File + + + + + + + + + + + + Edit + + + + + Tools + + + + + Help + + + + + + + + + + + + + .. + + + About + + + + + + .. + + + New + + + + + + .. + + + Open + + + + + + .. + + + Save + + + + + Close + + + + + + .. + + + Quit + + + + + + .. + + + Save As + + + + + + RocketTreeView + QTreeView +
gui/RocketTreeView.h
+
+ + QCustomPlot + QWidget +
gui/qcustomplot.h
+ 1 +
+
+ + + + +
diff --git a/gui/RocketTreeView.cpp b/gui/RocketTreeView.cpp new file mode 100644 index 0000000..7052800 --- /dev/null +++ b/gui/RocketTreeView.cpp @@ -0,0 +1,6 @@ +#include "RocketTreeView.h" + +RocketTreeView::RocketTreeView(QWidget* parent) : QTreeView(parent) +{ + +} diff --git a/gui/RocketTreeView.h b/gui/RocketTreeView.h new file mode 100644 index 0000000..82b72d8 --- /dev/null +++ b/gui/RocketTreeView.h @@ -0,0 +1,18 @@ +#ifndef ROCKETTREEVIEW_H +#define ROCKETTREEVIEW_H + +#include + +/** + * @brief RocketTreeView basically just renames QTreeView with a specific + * memorable name. + */ +class RocketTreeView : public QTreeView +{ + Q_OBJECT + +public: + RocketTreeView(QWidget* parent = nullptr); +}; + +#endif // ROCKETTREEVIEW_H diff --git a/qcustomplot.cpp b/gui/qcustomplot.cpp similarity index 100% rename from qcustomplot.cpp rename to gui/qcustomplot.cpp diff --git a/qcustomplot.h b/gui/qcustomplot.h similarity index 100% rename from qcustomplot.h rename to gui/qcustomplot.h diff --git a/main.cpp b/main.cpp index e0c4bb5..db1c204 100644 --- a/main.cpp +++ b/main.cpp @@ -1,4 +1,4 @@ -#include "QtRocket.h" +#include "gui/MainWindow.h" #include #include @@ -24,7 +24,7 @@ int main(int argc, char *argv[]) } // Go! - QtRocket w; + MainWindow w; w.show(); return a.exec(); } diff --git a/qtrocket.pro b/qtrocket.pro index 5ede81c..ebddb06 100644 --- a/qtrocket.pro +++ b/qtrocket.pro @@ -9,33 +9,41 @@ CONFIG += c++17 #DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 SOURCES += \ - main.cpp \ QtRocket.cpp \ + gui/AboutWindow.cpp \ + gui/qcustomplot.cpp \ + main.cpp \ + gui/RocketTreeView.cpp \ + gui/MainWindow.cpp \ model/Motor.cpp \ model/MotorCase.cpp \ model/Thrustcurve.cpp \ - qcustomplot.cpp \ sim/AtmosphericModel.cpp \ sim/GravityModel.cpp \ sim/Propagator.cpp \ sim/RK4Solver.cpp \ sim/SphericalGeoidModel.cpp \ sim/SphericalGravityModel.cpp \ + sim/StateData.cpp \ sim/USStandardAtmosphere.cpp \ sim/WindModel.cpp \ utils/BinMap.cpp \ utils/CurlConnection.cpp \ utils/Logger.cpp \ + utils/ThreadPool.cpp \ utils/ThrustCurveAPI.cpp \ utils/math/Quaternion.cpp \ utils/math/Vector3.cpp HEADERS += \ QtRocket.h \ + gui/AboutWindow.h \ + gui/RocketTreeView.h \ + gui/MainWindow.h \ + gui/qcustomplot.h \ model/Motor.h \ model/MotorCase.h \ model/Thrustcurve.h \ - qcustomplot.h \ sim/AtmosphericModel.h \ sim/DESolver.h \ sim/GeoidModel.h \ @@ -44,18 +52,21 @@ HEADERS += \ sim/RK4Solver.h \ sim/SphericalGeoidModel.h \ sim/SphericalGravityModel.h \ + sim/StateData.h \ sim/USStandardAtmosphere.h \ sim/WindModel.h \ utils/BinMap.h \ utils/CurlConnection.h \ utils/Logger.h \ + utils/ThreadPool.h \ utils/ThrustCurveAPI.h \ utils/math/Constants.h \ utils/math/Quaternion.h \ utils/math/Vector3.h FORMS += \ - QtRocket.ui + gui/AboutWindow.ui \ + gui/MainWindow.ui TRANSLATIONS += \ qtrocket_en_US.ts diff --git a/qtrocket.qrc b/qtrocket.qrc index 32c6ffd..a00b530 100644 --- a/qtrocket.qrc +++ b/qtrocket.qrc @@ -1,7 +1,6 @@ - - - - resources/qtrocket.png - + + + + resources/rocket64.png + - diff --git a/resources/qtrocket.png b/resources/qtrocket.png deleted file mode 100644 index b41bf2b..0000000 Binary files a/resources/qtrocket.png and /dev/null differ diff --git a/resources/rocket64.png b/resources/rocket64.png new file mode 100644 index 0000000..a97b07c Binary files /dev/null and b/resources/rocket64.png differ diff --git a/sim/DESolver.h b/sim/DESolver.h index 46b979d..34e903c 100644 --- a/sim/DESolver.h +++ b/sim/DESolver.h @@ -10,7 +10,8 @@ public: DESolver() {} virtual ~DESolver() {} - virtual double step(double curVal, double t, double dt) = 0; + virtual void setTimeStep(double ts) = 0; + virtual double step(double curVal, double t) const = 0; }; } // namespace sim diff --git a/sim/RK4Solver.cpp b/sim/RK4Solver.cpp index c6ef857..b475329 100644 --- a/sim/RK4Solver.cpp +++ b/sim/RK4Solver.cpp @@ -2,14 +2,14 @@ namespace sim { -double RK4Solver::step(double curVal, double t, double dt) +double RK4Solver::step(double curVal, double t) const { double retVal(0.0); - k1 = de(t, curVal); - k2 = de(t + dt / 2.0, curVal + (dt * k1 / 2.0)); - k3 = de(t + dt / 2.0, curVal + (dt * k2 / 2.0)); - k4 = de(t + dt, curVal + dt * k3); + double k1 = de(curVal, t); + double k2 = de(curVal + (dt * k1 / 2.0), t + dt / 2.0); + double k3 = de(curVal + (dt * k2 / 2.0), t + dt / 2.0); + double k4 = de(curVal + dt * k3, t + dt); retVal = curVal + (1.0 / 6.0)*dt*(k1 + 2.0*k2 + 2.0*k3 + k4); return retVal; diff --git a/sim/RK4Solver.h b/sim/RK4Solver.h index 2c89a5e..cda08a4 100644 --- a/sim/RK4Solver.h +++ b/sim/RK4Solver.h @@ -10,15 +10,18 @@ namespace sim { class RK4Solver : public DESolver { public: - RK4Solver(const std::function& d) : de(d) {} + RK4Solver(std::function d) : de(d) {} virtual ~RK4Solver() {} - virtual double step(double curVal, double t, double dt) override; + void setTimeStep(double inTs) override { dt = inTs; } + double step(double curVal, double t) const override; private: std::function de; - double k1, k2, k3, k4; + //double k1, k2, k3, k4; + + double dt; }; diff --git a/sim/StateData.cpp b/sim/StateData.cpp new file mode 100644 index 0000000..2af9702 --- /dev/null +++ b/sim/StateData.cpp @@ -0,0 +1,6 @@ +#include "StateData.h" + +StateData::StateData() +{ + +} diff --git a/sim/StateData.h b/sim/StateData.h new file mode 100644 index 0000000..4af6ac2 --- /dev/null +++ b/sim/StateData.h @@ -0,0 +1,29 @@ +#ifndef STATEDATA_H +#define STATEDATA_H + +#include "utils/math/Vector3.h" + +/** + * @brief The StateData class holds physical state data. Things such as position, velocity, + * and acceleration of the center of mass, as well as orientation and orientation + * change rates. + */ +class StateData +{ +public: + StateData(); + +private: + math::Vector3 position; + math::Vector3 velocity; + math::Vector3 acceleration; + + math::Vector3 orientation; // roll, pitch, yaw + math::Vector3 orientationVelocity; // roll-rate, pitch-rate, yaw-rate + // Necessary? + //math::Vector3 orientationAccel; + + +}; + +#endif // STATEDATA_H diff --git a/utils/Logger.h b/utils/Logger.h index 95b9d1e..d716df7 100644 --- a/utils/Logger.h +++ b/utils/Logger.h @@ -24,6 +24,7 @@ public: }; static Logger* getInstance(); + ~Logger(); Logger(Logger const&) = delete; Logger(Logger&&) = delete; @@ -54,7 +55,6 @@ private: static Logger* instance; std::mutex mtx; Logger(); - ~Logger(); }; } // namespace utils diff --git a/utils/ThreadPool.cpp b/utils/ThreadPool.cpp new file mode 100644 index 0000000..6f03add --- /dev/null +++ b/utils/ThreadPool.cpp @@ -0,0 +1,6 @@ +#include "ThreadPool.h" + +ThreadPool::ThreadPool() +{ + +} diff --git a/utils/ThreadPool.h b/utils/ThreadPool.h new file mode 100644 index 0000000..fd75a4e --- /dev/null +++ b/utils/ThreadPool.h @@ -0,0 +1,17 @@ +#ifndef THREADPOOL_H +#define THREADPOOL_H + +#include + +/** + * @brief A basic ThreadPool class + */ +class ThreadPool +{ +public: + ThreadPool(); +private: + std::atomic_bool done; +}; + +#endif // THREADPOOL_H diff --git a/utils/math/Vector3.h b/utils/math/Vector3.h index 5dc7f39..6a42472 100644 --- a/utils/math/Vector3.h +++ b/utils/math/Vector3.h @@ -29,7 +29,7 @@ public: double getX3() { return x3; } -private: +//private: double x1; double x2; double x3;