Now with ThrustCurve.org integration
This commit is contained in:
parent
eeea751fbc
commit
fb6f221137
2
.gitignore
vendored
2
.gitignore
vendored
@ -38,7 +38,7 @@ build/
|
||||
docs/doxygen/*
|
||||
|
||||
# IDE
|
||||
.vscode/qtrocket.pro.user
|
||||
.vscode/
|
||||
qtrocket.pro.user
|
||||
.qmake.stash
|
||||
|
||||
|
@ -99,6 +99,7 @@ set(PROJECT_SOURCES
|
||||
|
||||
if(${QT_VERSION_MAJOR} GREATER_EQUAL 6)
|
||||
qt_add_executable(qtrocket
|
||||
qtrocket.qrc
|
||||
MANUAL_FINALIZATION
|
||||
${PROJECT_SOURCES}
|
||||
)
|
||||
|
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE QtCreatorProject>
|
||||
<!-- Written by QtCreator 10.0.0, 2023-04-26T15:16:57. -->
|
||||
<!-- Written by QtCreator 10.0.0, 2023-04-26T18:22:10. -->
|
||||
<qtcreator>
|
||||
<data>
|
||||
<variable>EnvironmentId</variable>
|
||||
|
@ -45,6 +45,8 @@ public:
|
||||
|
||||
void addMotorModels(std::vector<model::MotorModel>& m);
|
||||
|
||||
const std::vector<model::MotorModel>& getMotorModels() const { return motorModels; }
|
||||
|
||||
void addRocket(std::shared_ptr<Rocket> r) { rocket = r; }
|
||||
|
||||
void setSimulationOptions(std::shared_ptr<sim::SimulationOptions> options) { simOptions = options; }
|
||||
|
@ -2,6 +2,8 @@
|
||||
#include "ui_AnalysisWindow.h"
|
||||
|
||||
#include "QtRocket.h"
|
||||
#include "model/MotorModel.h"
|
||||
#include "model/ThrustCurve.h"
|
||||
|
||||
AnalysisWindow::AnalysisWindow(QWidget *parent) :
|
||||
QDialog(parent),
|
||||
@ -12,10 +14,25 @@ AnalysisWindow::AnalysisWindow(QWidget *parent) :
|
||||
this->hide();
|
||||
this->show();
|
||||
|
||||
connect(ui->plotAltitudeBtn, SIGNAL(clicked()), this, SLOT(plotAltitude()));
|
||||
//connect(ui->plotAtmosphereBtn, SIGNAL(clicked()), this, SLOT(plotAtmosphere()));
|
||||
connect(ui->plotVelocityBtn, SIGNAL(clicked()), this, SLOT(plotVelocity()));
|
||||
connect(ui->plotMotorCurveBtn, SIGNAL(clicked()), this, SLOT(plotMotorCurveBtn()));
|
||||
|
||||
|
||||
}
|
||||
|
||||
AnalysisWindow::~AnalysisWindow()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void AnalysisWindow::plotAltitude()
|
||||
{
|
||||
std::shared_ptr<Rocket> rocket = QtRocket::getInstance()->getRocket();
|
||||
const std::vector<std::pair<double, std::vector<double>>>& res = rocket->getStates();
|
||||
auto& plot = ui->plotWidget;
|
||||
plot->clearGraphs();
|
||||
plot->setInteraction(QCP::iRangeDrag, true);
|
||||
plot->setInteraction(QCP::iRangeZoom, true);
|
||||
// generate some data:
|
||||
@ -37,7 +54,66 @@ AnalysisWindow::AnalysisWindow(QWidget *parent) :
|
||||
plot->replot();
|
||||
}
|
||||
|
||||
AnalysisWindow::~AnalysisWindow()
|
||||
void AnalysisWindow::plotVelocity()
|
||||
{
|
||||
delete ui;
|
||||
std::shared_ptr<Rocket> rocket = QtRocket::getInstance()->getRocket();
|
||||
const std::vector<std::pair<double, std::vector<double>>>& res = rocket->getStates();
|
||||
auto& plot = ui->plotWidget;
|
||||
plot->clearGraphs();
|
||||
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[5];
|
||||
}
|
||||
// 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 Velocity");
|
||||
// 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();
|
||||
|
||||
}
|
||||
|
||||
void AnalysisWindow::plotMotorCurveBtn()
|
||||
{
|
||||
std::shared_ptr<Rocket> rocket = QtRocket::getInstance()->getRocket();
|
||||
model::MotorModel motor = rocket->getCurrentMotorModel();
|
||||
ThrustCurve tc = motor.getThrustCurve();
|
||||
|
||||
|
||||
const std::vector<std::pair<double, double>>& res = tc.getThrustCurveData();
|
||||
auto& plot = ui->plotWidget;
|
||||
plot->clearGraphs();
|
||||
plot->setInteraction(QCP::iRangeDrag, true);
|
||||
plot->setInteraction(QCP::iRangeZoom, true);
|
||||
|
||||
// generate some data:
|
||||
QVector<double> tData(res.size());
|
||||
QVector<double> fData(res.size());
|
||||
for (int i = 0; i < tData.size(); ++i)
|
||||
{
|
||||
tData[i] = res[i].first;
|
||||
fData[i] = res[i].second;
|
||||
}
|
||||
// create graph and assign data to it:
|
||||
plot->addGraph();
|
||||
plot->graph(0)->setScatterStyle(QCPScatterStyle(QCPScatterStyle::ssCircle, 5));
|
||||
plot->graph(0)->setData(tData, fData);
|
||||
// give the axes some labels:
|
||||
plot->xAxis->setLabel("time");
|
||||
plot->yAxis->setLabel("Thrust (N)");
|
||||
// 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(fData), std::end(fData)), *std::max_element(std::begin(fData), std::end(fData)));
|
||||
plot->replot();
|
||||
|
||||
}
|
@ -36,6 +36,13 @@ public:
|
||||
explicit AnalysisWindow(QWidget *parent = nullptr);
|
||||
~AnalysisWindow();
|
||||
|
||||
private slots:
|
||||
|
||||
void plotAltitude();
|
||||
//void plotAtmosphere();
|
||||
void plotVelocity();
|
||||
void plotMotorCurveBtn();
|
||||
|
||||
private:
|
||||
Ui::AnalysisWindow *ui;
|
||||
};
|
||||
|
@ -16,13 +16,68 @@
|
||||
<widget class="QCustomPlot" name="plotWidget" native="true">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>19</x>
|
||||
<x>149</x>
|
||||
<y>29</y>
|
||||
<width>961</width>
|
||||
<height>671</height>
|
||||
<width>831</width>
|
||||
<height>541</height>
|
||||
</rect>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QPushButton" name="plotAltitudeBtn">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>20</x>
|
||||
<y>50</y>
|
||||
<width>121</width>
|
||||
<height>36</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Plot Altitude</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QPushButton" name="plotVelocityBtn">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>20</x>
|
||||
<y>110</y>
|
||||
<width>121</width>
|
||||
<height>36</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Plot Velocity</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QPushButton" name="plotAtmosphereBtn">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>20</x>
|
||||
<y>170</y>
|
||||
<width>121</width>
|
||||
<height>36</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Plot Atmosphere</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QPushButton" name="plotMotorCurveBtn">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>20</x>
|
||||
<y>230</y>
|
||||
<width>121</width>
|
||||
<height>36</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Motor Curve</string>
|
||||
</property>
|
||||
</widget>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
@ -33,5 +88,25 @@
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>plotAltitudeBtn</sender>
|
||||
<signal>clicked()</signal>
|
||||
<receiver>AnalysisWindow</receiver>
|
||||
<slot>plotAltitude()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>78</x>
|
||||
<y>61</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>88</x>
|
||||
<y>17</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
<slots>
|
||||
<slot>plotAltitude()</slot>
|
||||
</slots>
|
||||
</ui>
|
||||
|
@ -151,7 +151,7 @@ void MainWindow::on_setMotor_clicked()
|
||||
QString motorName = ui->engineSelectorComboBox->currentText();
|
||||
model::MotorModel mm = rseDatabase->getMotorModelByName(motorName.toStdString());
|
||||
QtRocket::getInstance()->getRocket()->setMotorModel(mm);
|
||||
|
||||
QtRocket::getInstance()->addMotorModels(rseDatabase->getMotors());
|
||||
|
||||
}
|
||||
|
||||
|
@ -62,6 +62,9 @@
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<widget class="QPushButton" name="testButton1">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>30</x>
|
||||
@ -83,8 +86,8 @@
|
||||
<widget class="QPushButton" name="testButton2">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>30</x>
|
||||
<y>70</y>
|
||||
<x>240</x>
|
||||
<y>440</y>
|
||||
<width>191</width>
|
||||
<height>25</height>
|
||||
</rect>
|
||||
@ -96,7 +99,7 @@
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Calculate Ballistic Trajectory</string>
|
||||
<string>Calculate Trajectory</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QWidget" name="layoutWidget">
|
||||
@ -105,12 +108,15 @@
|
||||
<x>260</x>
|
||||
<y>80</y>
|
||||
<width>161</width>
|
||||
<height>151</height>
|
||||
<height>196</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="1" column="1">
|
||||
<widget class="QLineEdit" name="initialAngle">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>90.0</string>
|
||||
</property>
|
||||
@ -143,7 +149,7 @@
|
||||
<item row="0" column="1">
|
||||
<widget class="QLineEdit" name="initialVelocity">
|
||||
<property name="text">
|
||||
<string>50.0</string>
|
||||
<string>5.0</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@ -164,7 +170,7 @@
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Velocity</string>
|
||||
<string>Initial Velocity</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@ -188,7 +194,7 @@
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>90</x>
|
||||
<y>250</y>
|
||||
<y>290</y>
|
||||
<width>421</width>
|
||||
<height>80</height>
|
||||
</rect>
|
||||
@ -224,7 +230,7 @@
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>240</x>
|
||||
<y>360</y>
|
||||
<y>390</y>
|
||||
<width>201</width>
|
||||
<height>25</height>
|
||||
</rect>
|
||||
@ -244,7 +250,7 @@
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>1031</width>
|
||||
<height>22</height>
|
||||
<height>32</height>
|
||||
</rect>
|
||||
</property>
|
||||
<widget class="QMenu" name="menuFile">
|
||||
|
@ -90,6 +90,34 @@ void ThrustCurveMotorSelector::on_setMotor_clicked()
|
||||
return item.data.commonName == commonName;
|
||||
});
|
||||
|
||||
ThrustCurve tc = tcApi->getMotorData(mm.data.motorIdTC).getThrustCurve();
|
||||
mm.addThrustCurve(tc);
|
||||
QtRocket::getInstance()->getRocket()->setMotorModel(mm);
|
||||
|
||||
const std::vector<std::pair<double, double>>& res = tc.getThrustCurveData();
|
||||
auto& plot = ui->plot;
|
||||
plot->clearGraphs();
|
||||
plot->setInteraction(QCP::iRangeDrag, true);
|
||||
plot->setInteraction(QCP::iRangeZoom, true);
|
||||
|
||||
// generate some data:
|
||||
QVector<double> tData(res.size());
|
||||
QVector<double> fData(res.size());
|
||||
for (int i = 0; i < tData.size(); ++i)
|
||||
{
|
||||
tData[i] = res[i].first;
|
||||
fData[i] = res[i].second;
|
||||
}
|
||||
// create graph and assign data to it:
|
||||
plot->addGraph();
|
||||
plot->graph(0)->setScatterStyle(QCPScatterStyle(QCPScatterStyle::ssCircle, 5));
|
||||
plot->graph(0)->setData(tData, fData);
|
||||
// give the axes some labels:
|
||||
plot->xAxis->setLabel("time");
|
||||
plot->yAxis->setLabel("Thrust (N)");
|
||||
// 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(fData), std::end(fData)), *std::max_element(std::begin(fData), std::end(fData)));
|
||||
plot->replot();
|
||||
}
|
||||
|
||||
|
@ -398,6 +398,8 @@ public:
|
||||
|
||||
void addThrustCurve(const ThrustCurve& tc) { thrust = tc; }
|
||||
|
||||
const ThrustCurve& getThrustCurve() const { return thrust; }
|
||||
|
||||
// Thrust parameters
|
||||
MetaData data;
|
||||
private:
|
||||
|
@ -81,19 +81,18 @@ public:
|
||||
*/
|
||||
double getThrust(double t);
|
||||
|
||||
/**
|
||||
* @brief setThrustCurve sets the current thrust curve
|
||||
* @param curve
|
||||
* @todo Remove this
|
||||
*/
|
||||
void setThrustCurve(const ThrustCurve& curve);
|
||||
|
||||
/**
|
||||
* @brief setMotorModel
|
||||
* @param motor
|
||||
*/
|
||||
void setMotorModel(const model::MotorModel& motor);
|
||||
|
||||
/**
|
||||
* @brief Returns the current motor model.
|
||||
* @return The current motor model
|
||||
*/
|
||||
const model::MotorModel& getCurrentMotorModel() const { return mm; }
|
||||
|
||||
/**
|
||||
* @brief terminateCondition returns true or false, whether the passed-in time/state matches the terminate condition
|
||||
* @param cond time/state pair
|
||||
|
@ -48,6 +48,8 @@ public:
|
||||
*/
|
||||
void setThrustCurveVector(const std::vector<std::pair<double, double>>& v);
|
||||
|
||||
const std::vector<std::pair<double, double>> getThrustCurveData() const { return thrustCurve; }
|
||||
|
||||
private:
|
||||
std::vector<std::pair<double, double>> thrustCurve;
|
||||
double maxTime{0.0};
|
||||
|
@ -14,7 +14,7 @@ namespace utils
|
||||
{
|
||||
|
||||
ThrustCurveAPI::ThrustCurveAPI()
|
||||
: hostname("https://www.thrustcurve.org/api/v1/"),
|
||||
: hostname("https://www.thrustcurve.org/"),
|
||||
curlConnection()
|
||||
{
|
||||
|
||||
@ -29,13 +29,53 @@ ThrustCurveAPI::~ThrustCurveAPI()
|
||||
model::MotorModel ThrustCurveAPI::getMotorData(const std::string& motorId)
|
||||
{
|
||||
std::stringstream endpoint;
|
||||
endpoint << hostname << "download.json?motorId=" << motorId << "&data=samples";
|
||||
endpoint << hostname << "api/v1/download.json?motorId=" << motorId << "&data=samples";
|
||||
std::vector<std::string> extraHeaders = {};
|
||||
|
||||
std::string res = curlConnection.get(endpoint.str(), extraHeaders);
|
||||
|
||||
/// TODO: fix this
|
||||
model::MotorModel mm;
|
||||
|
||||
if(!res.empty())
|
||||
{
|
||||
try
|
||||
{
|
||||
Json::Reader reader;
|
||||
Json::Value jsonResult;
|
||||
reader.parse(res, jsonResult);
|
||||
|
||||
std::vector<std::pair<double, double>> samples;
|
||||
for(Json::ValueConstIterator iter = jsonResult["results"].begin();
|
||||
iter != jsonResult["results"].end();
|
||||
++iter)
|
||||
{
|
||||
// if there are more than 1 items in the results list, we only want the RASP data
|
||||
// Otherwise just take whatever is there
|
||||
if(std::next(iter) != jsonResult["results"].end())
|
||||
{
|
||||
if( (*iter)["format"].asString() != "RASP")
|
||||
continue;
|
||||
}
|
||||
for(Json::ValueConstIterator samplesIter = (*iter)["samples"].begin();
|
||||
samplesIter != (*iter)["samples"].end();
|
||||
++samplesIter)
|
||||
{
|
||||
samples.push_back(std::make_pair((*samplesIter)["time"].asDouble(),
|
||||
(*samplesIter)["thrust"].asDouble()));
|
||||
|
||||
}
|
||||
}
|
||||
ThrustCurve tc(samples);
|
||||
mm.addThrustCurve(tc);
|
||||
}
|
||||
catch(const std::exception& e)
|
||||
{
|
||||
std::string err("Unable to parse JSON from Thrustcurve motor data request. Error: ");
|
||||
err += e.what();
|
||||
|
||||
Logger::getInstance()->error(err);
|
||||
}
|
||||
}
|
||||
|
||||
return mm;
|
||||
}
|
||||
|
||||
@ -43,7 +83,7 @@ ThrustcurveMetadata ThrustCurveAPI::getMetadata()
|
||||
{
|
||||
|
||||
std::string endpoint = hostname;
|
||||
endpoint += "metadata.json";
|
||||
endpoint += "api/v1/metadata.json";
|
||||
std::string result = curlConnection.get(endpoint, extraHeaders);
|
||||
ThrustcurveMetadata ret;
|
||||
|
||||
@ -123,7 +163,7 @@ std::vector<model::MotorModel> ThrustCurveAPI::searchMotors(const SearchCriteria
|
||||
{
|
||||
std::vector<model::MotorModel> retVal;
|
||||
std::string endpoint = hostname;
|
||||
endpoint += "search.json?";
|
||||
endpoint += "api/v1/search.json?";
|
||||
for(const auto& i : c.criteria)
|
||||
{
|
||||
endpoint += i.first;
|
||||
|
Loading…
x
Reference in New Issue
Block a user