634 lines
20 KiB
C++
634 lines
20 KiB
C++
#include "mainwindow.h"
|
|
#include "./ui_mainwindow.h"
|
|
#include <QLibrary>
|
|
#include <QHostAddress>
|
|
#include <QFileDialog>
|
|
#include <QDateTime>
|
|
|
|
extern "C"{
|
|
#include "SIL_capi.h"
|
|
}
|
|
|
|
void MainWindow::scan_param()
|
|
{
|
|
const rtwCAPI_ModelMappingStaticInfo *sm = (*getmap_func)();
|
|
if (sm)
|
|
{
|
|
//unsigned int n = rtwCAPI_GetNumBlockParametersFromStaticMap(sm);
|
|
unsigned int m = rtwCAPI_GetNumModelParametersFromStaticMap(sm);
|
|
ui->tableWidget->setRowCount(512);
|
|
QStringList hdr;
|
|
hdr.push_back(tr("Parameter"));
|
|
hdr.push_back(tr("Value"));
|
|
ui->tableWidget->setHorizontalHeaderLabels(hdr);
|
|
int cur = 0;
|
|
|
|
rtwCAPI_ModelParameters const *prm = rtwCAPI_GetModelParametersFromStaticMap(sm);
|
|
rtwCAPI_DataTypeMap const *dtm = rtwCAPI_GetDataTypeMapFromStaticMap(sm);
|
|
rtwCAPI_DimensionMap const *dmm = rtwCAPI_GetDimensionMapFromStaticMap(sm);
|
|
uint_T const *dam = rtwCAPI_GetDimensionArrayFromStaticMap(sm);
|
|
rtwCAPI_ModelMappingInfo *MMI = &(rtmGetDataMapInfo(this->m).mmi);
|
|
void **da = rtwCAPI_GetDataAddressMap(MMI);
|
|
for (unsigned int i = 0; i < m; ++i)
|
|
{
|
|
const char *name = rtwCAPI_GetModelParameterName(prm, i);
|
|
int idx = rtwCAPI_GetModelParameterAddrIdx(prm, i);
|
|
uint16_t dti = rtwCAPI_GetModelParameterDataTypeIdx(prm, i);
|
|
uint16_t dmi = rtwCAPI_GetModelParameterDimensionIdx(prm, i);
|
|
uint8_t ss = rtwCAPI_GetDataTypeSLId(dtm, dti);
|
|
uint16_t dai = rtwCAPI_GetDimArrayIndex(dmm, dmi);
|
|
uint8_t nd = rtwCAPI_GetNumDims(dmm, dmi);
|
|
uint16_t n = 1;
|
|
for (int j = 0; j < nd; ++j)
|
|
{
|
|
n *= dam[dai + j];
|
|
}
|
|
for (int j = 0; j < n; ++j)
|
|
{
|
|
QString param_name = QString::fromLatin1(name);
|
|
if (j>0)
|
|
{
|
|
param_name = param_name+QString("(%1)").arg(j);
|
|
}
|
|
QString param_value;
|
|
switch (ss)
|
|
{
|
|
case SS_DOUBLE:
|
|
{
|
|
double *d = (double *)da[idx];
|
|
param_value = QString("%1").arg(d[j]);
|
|
}
|
|
break;
|
|
case SS_SINGLE:
|
|
{
|
|
float *s = (float *)da[idx];
|
|
param_value = QString("%1").arg(s[j]);
|
|
}
|
|
break;
|
|
case SS_INT8:
|
|
{
|
|
int8_T *c = (int8_T *)da[idx];
|
|
param_value = QString("%1").arg(c[j]);
|
|
}
|
|
break;
|
|
case SS_INT16:
|
|
{
|
|
int16_T *h = (int16_T *)da[idx];
|
|
param_value = QString("%1").arg(h[j]);
|
|
}
|
|
break;
|
|
case SS_INT32:
|
|
{
|
|
int32_T *I = (int32_T *)da[idx];
|
|
param_value = QString("%1").arg(I[j]);
|
|
}
|
|
break;
|
|
case SS_UINT8:
|
|
{
|
|
uint8_T *c = (uint8_T *)da[idx];
|
|
param_value = QString("%1").arg(c[j]);
|
|
}
|
|
break;
|
|
case SS_BOOLEAN:
|
|
{
|
|
boolean_T *c = (boolean_T *)da[idx];
|
|
param_value = QString("%1").arg(c[j]);
|
|
}
|
|
break;
|
|
case SS_UINT16:
|
|
{
|
|
uint16_T *h = (uint16_T *)da[idx];
|
|
param_value = QString("%1").arg(h[j]);
|
|
}
|
|
break;
|
|
case SS_UINT32:
|
|
{
|
|
uint32_T *I = (uint32_T *)da[idx];
|
|
param_value = QString("%1").arg(I[j]);
|
|
}
|
|
break;
|
|
}
|
|
QTableWidgetItem *newItem = new QTableWidgetItem(param_name);
|
|
ui->tableWidget->setItem(cur, 0, newItem);
|
|
newItem = new QTableWidgetItem(param_value);
|
|
ui->tableWidget->setItem(cur++, 1, newItem);
|
|
if (param_name == "X0")
|
|
{
|
|
X0[0] = param_value.toDouble();
|
|
}
|
|
else if (param_name == "X0(1)")
|
|
{
|
|
X0[1] = param_value.toDouble();
|
|
}
|
|
else if (param_name == "X0(2)")
|
|
{
|
|
X0[2] = param_value.toDouble();
|
|
}
|
|
else if (param_name == "Att0")
|
|
{
|
|
Att0[0] = param_value.toDouble();
|
|
}
|
|
else if (param_name == "Att0(1)")
|
|
{
|
|
Att0[1] = param_value.toDouble();
|
|
}
|
|
else if (param_name == "Att0(2)")
|
|
{
|
|
Att0[2] = param_value.toDouble();
|
|
}
|
|
else if (param_name == "V0")
|
|
{
|
|
V0[0] = param_value.toDouble();
|
|
}
|
|
else if (param_name == "V0(1)")
|
|
{
|
|
V0[1] = param_value.toDouble();
|
|
}
|
|
else if (param_name == "V0(2)")
|
|
{
|
|
V0[2] = param_value.toDouble();
|
|
}
|
|
else if (param_name == "hground")
|
|
{
|
|
hground = param_value.toDouble();
|
|
}
|
|
}
|
|
}
|
|
ui->tableWidget->setRowCount(cur);
|
|
}
|
|
}
|
|
|
|
|
|
void MainWindow::setup_param(const QVector<QString> &head, const QVector<double> &onecase)
|
|
{
|
|
const rtwCAPI_ModelMappingStaticInfo *sm = (*getmap_func)();
|
|
if (sm)
|
|
{
|
|
//unsigned int n = rtwCAPI_GetNumBlockParametersFromStaticMap(sm);
|
|
unsigned int m = rtwCAPI_GetNumModelParametersFromStaticMap(sm);
|
|
rtwCAPI_ModelParameters const *prm = rtwCAPI_GetModelParametersFromStaticMap(sm);
|
|
rtwCAPI_DataTypeMap const *dtm = rtwCAPI_GetDataTypeMapFromStaticMap(sm);
|
|
rtwCAPI_DimensionMap const *dmm = rtwCAPI_GetDimensionMapFromStaticMap(sm);
|
|
uint_T const *dam = rtwCAPI_GetDimensionArrayFromStaticMap(sm);
|
|
rtwCAPI_ModelMappingInfo *MMI = &(rtmGetDataMapInfo(this->m).mmi);
|
|
void **da = rtwCAPI_GetDataAddressMap(MMI);
|
|
for (unsigned int i = 0; i < m; ++i)
|
|
{
|
|
const char *name = rtwCAPI_GetModelParameterName(prm, i);
|
|
int idx = rtwCAPI_GetModelParameterAddrIdx(prm, i);
|
|
uint16_t dti = rtwCAPI_GetModelParameterDataTypeIdx(prm, i);
|
|
uint16_t dmi = rtwCAPI_GetModelParameterDimensionIdx(prm, i);
|
|
uint8_t ss = rtwCAPI_GetDataTypeSLId(dtm, dti);
|
|
uint16_t dai = rtwCAPI_GetDimArrayIndex(dmm, dmi);
|
|
uint8_t nd = rtwCAPI_GetNumDims(dmm, dmi);
|
|
uint16_t n = 1;
|
|
for (int j = 0; j < nd; ++j)
|
|
{
|
|
n *= dam[dai + j];
|
|
}
|
|
int j = 0;
|
|
for (auto i = head.begin(); i != head.end(); ++i, ++j)
|
|
{
|
|
QStringList s = i->split(QRegExp("[()]"));
|
|
if (*i == name || ((s.size() >= 2) && (s.value(0) == name)))
|
|
{
|
|
int target_idx = 0;
|
|
double target_value = onecase[j];
|
|
if (s.size() >= 2)
|
|
{
|
|
target_idx = s.value(1).toInt();
|
|
}
|
|
switch (ss)
|
|
{
|
|
case SS_DOUBLE:
|
|
{
|
|
double *d = (double *)da[idx];
|
|
d[target_idx] = target_value;
|
|
}
|
|
break;
|
|
case SS_SINGLE:
|
|
{
|
|
float *s = (float *)da[idx];
|
|
s[target_idx] = target_value;
|
|
}
|
|
break;
|
|
case SS_INT8:
|
|
{
|
|
int8_T *c = (int8_T *)da[idx];
|
|
c[target_idx] = target_value;
|
|
}
|
|
break;
|
|
case SS_INT16:
|
|
{
|
|
int16_T *h = (int16_T *)da[idx];
|
|
h[target_idx] = target_value;
|
|
}
|
|
break;
|
|
case SS_INT32:
|
|
{
|
|
int32_T *I = (int32_T *)da[idx];
|
|
I[target_idx] = target_value;
|
|
}
|
|
break;
|
|
case SS_UINT8:
|
|
{
|
|
uint8_T *c = (uint8_T *)da[idx];
|
|
c[target_idx] = target_value;
|
|
}
|
|
break;
|
|
case SS_BOOLEAN:
|
|
{
|
|
bool *c = (bool *)da[idx];
|
|
c[target_idx] = target_value >=0.5?true:false;
|
|
}
|
|
break;
|
|
case SS_UINT16:
|
|
{
|
|
uint16_T *h = (uint16_T *)da[idx];
|
|
h[target_idx] = target_value;
|
|
}
|
|
break;
|
|
case SS_UINT32:
|
|
{
|
|
uint32_T *I = (uint32_T *)da[idx];
|
|
I[target_idx] = target_value;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
MainWindow::MainWindow(QWidget *parent)
|
|
: QMainWindow(parent), ui(new Ui::MainWindow), times(1), idx(0)
|
|
{
|
|
ui->setupUi(this);
|
|
|
|
QLibrary *mdl = new QLibrary("SIL_win64.dll");
|
|
if (mdl->isLoaded())
|
|
{
|
|
init_func = static_cast<SIL_initialize_ptr>(mdl->resolve("SIL_initialize"));
|
|
step_func = static_cast<SIL_step_ptr>(mdl->resolve("SIL_step"));
|
|
getmap_func = (SIL_GetCAPIStaticMap_ptr)(mdl->resolve("SIL_GetCAPIStaticMap"));
|
|
u = (ExtU_SIL_T *)mdl->resolve("SIL_U");
|
|
y = (ExtY_SIL_T *)mdl->resolve("SIL_Y");
|
|
V0 = (double *)mdl->resolve("V0");
|
|
m = (RT_MODEL_SIL_T *)mdl->resolve("SIL_M_");
|
|
}
|
|
else
|
|
{
|
|
init_func = &SIL_initialize;
|
|
step_func = &SIL_step;
|
|
getmap_func = &SIL_GetCAPIStaticMap;
|
|
u = &SIL_U;
|
|
y = &SIL_Y;
|
|
V0 = ::V0;
|
|
m = (RT_MODEL_SIL_T *)SIL_M;
|
|
}
|
|
|
|
ui->pushButton_start->setText(QString("Fail"));
|
|
stage = 0;
|
|
|
|
if (init_func && step_func && u && y && getmap_func)
|
|
{
|
|
SIL_InitializeDataMapInfo();
|
|
scan_param();
|
|
|
|
ui->lineEditLat->setText(QString("%1").arg(X0[0]));
|
|
ui->lineEditLon->setText(QString("%1").arg(X0[1]));
|
|
ui->lineEditAlt->setText(QString("%1").arg(hground));
|
|
ui->lineEditHdg->setText(QString("%1").arg(Att0[2]*57.3));
|
|
ui->lineEditSpeed->setText(QString("%1").arg(V0[0]));
|
|
gear_height = X0[2] - hground;
|
|
ui->lineEditAGL->setText(QString("%1").arg(gear_height));
|
|
|
|
qgc_sock = new QUdpSocket(this);
|
|
if (qgc_sock->bind(QHostAddress::LocalHost, 6061))
|
|
{
|
|
ui->pushButton_start->setText(QString("Start"));
|
|
stage = 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
MainWindow::~MainWindow()
|
|
{
|
|
delete ui;
|
|
}
|
|
|
|
void MainWindow::update200Hz(void)
|
|
{
|
|
for (int j=0;j<times;++j)
|
|
{
|
|
u->data_len = 0u;
|
|
if (qgc_sock->hasPendingDatagrams())
|
|
{
|
|
qint64 len = qgc_sock->readDatagram((char *)u->data_in, 255);
|
|
if (len > 0)
|
|
{
|
|
u->data_len = static_cast<uint16_t>(len);
|
|
}
|
|
}
|
|
|
|
for (int i = 0; i < 1; ++i)
|
|
{
|
|
(*step_func)();
|
|
}
|
|
|
|
if (y->seq != seq)
|
|
{
|
|
seq = y->seq;
|
|
qgc_sock->writeDatagram((char *)y->buff, y->buff_len, QHostAddress::LocalHost, 6060);
|
|
}
|
|
if (y->rec_seq != seq_rec)
|
|
{
|
|
seq_rec = y->rec_seq;
|
|
rec_file->write((const char *)y->rec_buff, y->rec_len);
|
|
}
|
|
}
|
|
if (++idx >= 20)
|
|
{
|
|
idx = 0;
|
|
ui->lineEditMass->setText(QString("%1").arg(y->mass,6,'f',2));
|
|
ui->lineEditRPM->setText(QString("%1").arg(y->RPM,5,'f',0));
|
|
ui->lineEditDel->setText(QString("%1").arg(y->de*57.3,6,'f',2));
|
|
ui->lineEditDer->setText(QString("%1").arg(y->de*57.3,6,'f',2));
|
|
ui->lineEditDal->setText(QString("%1").arg(y->da*-57.3,6,'f',2));
|
|
ui->lineEditDar->setText(QString("%1").arg(y->da*57.3,6,'f',2));
|
|
ui->lineEditDr->setText(QString("%1").arg(y->dr*57.3,6,'f',2));
|
|
if (y->RPM > 44500 && u->launch_trigger == 0)
|
|
{
|
|
u->launch_trigger = 1.0;
|
|
ui->pushButton_start->setText(QString("Flying"));
|
|
ui->pushButtonLaunch->setText(QString("Flying"));
|
|
ui->pushButton_start->setEnabled(false);
|
|
ui->pushButtonLaunch->setEnabled(false);
|
|
stage = 3;
|
|
ui->tabWidget->setCurrentIndex(1);
|
|
}
|
|
if (ui->checkBoxTurbine->checkState() == Qt::Checked)
|
|
{
|
|
u->fault |= 1;
|
|
}
|
|
else
|
|
{
|
|
u->fault &= 0xFFFFFFFE;
|
|
}
|
|
if (ui->checkBoxDel->checkState() == Qt::Checked)
|
|
{
|
|
u->fault |= 2;
|
|
}
|
|
else
|
|
{
|
|
u->fault &= 0xFFFFFFFD;
|
|
}
|
|
if (ui->checkBoxDer->checkState() == Qt::Checked)
|
|
{
|
|
u->fault |= 4;
|
|
}
|
|
else
|
|
{
|
|
u->fault &= 0xFFFFFFFB;
|
|
}
|
|
if (ui->checkBoxDr->checkState() == Qt::Checked)
|
|
{
|
|
u->fault |= 8;
|
|
}
|
|
else
|
|
{
|
|
u->fault &= 0xFFFFFFF7;
|
|
}
|
|
if (ui->checkBoxDal->checkState() == Qt::Checked)
|
|
{
|
|
u->fault |= 0x10;
|
|
}
|
|
else
|
|
{
|
|
u->fault &= 0xFFFFFFEF;
|
|
}
|
|
if (ui->checkBoxDar->checkState() == Qt::Checked)
|
|
{
|
|
u->fault |= 0x20;
|
|
}
|
|
else
|
|
{
|
|
u->fault &= 0xFFFFFFDF;
|
|
}
|
|
}
|
|
}
|
|
|
|
void MainWindow::onFire()
|
|
{
|
|
if (stage == 1)
|
|
{
|
|
QVector<QString> head;
|
|
QVector<double> onecase;
|
|
|
|
int n = ui->tableWidget->rowCount();
|
|
for (int i=0;i<n;++i)
|
|
{
|
|
head.push_back(ui->tableWidget->item(i,0)->text());
|
|
onecase.push_back(ui->tableWidget->item(i,1)->text().toDouble());
|
|
}
|
|
|
|
double val;
|
|
bool ok;
|
|
val = ui->lineEditLat->text().toDouble(&ok);
|
|
if (ok)
|
|
{
|
|
head.push_back("X0");
|
|
onecase.push_back(val);
|
|
}
|
|
|
|
val = ui->lineEditLon->text().toDouble(&ok);
|
|
if (ok)
|
|
{
|
|
head.push_back("X0(1)");
|
|
onecase.push_back(val);
|
|
}
|
|
|
|
double hground;
|
|
val = ui->lineEditAlt->text().toDouble(&ok);
|
|
if (ok)
|
|
{
|
|
hground = val;
|
|
head.push_back("hground");
|
|
onecase.push_back(hground);
|
|
if (ui->radioButtonOnGround->isChecked())
|
|
{
|
|
head.push_back("X0(2)");
|
|
onecase.push_back(hground+gear_height);
|
|
}
|
|
}
|
|
|
|
val = ui->lineEditHdg->text().toDouble(&ok);
|
|
if (ok)
|
|
{
|
|
head.push_back("Att0(2)");
|
|
onecase.push_back(val/57.3);
|
|
}
|
|
|
|
if (ui->radioButtonInAir->isChecked())
|
|
{
|
|
head.push_back("Att0(1)");
|
|
onecase.push_back(0);
|
|
val = ui->lineEditSpeed->text().toDouble(&ok);
|
|
if (ok)
|
|
{
|
|
head.push_back("V0");
|
|
onecase.push_back(val);
|
|
}
|
|
val = ui->lineEditAGL->text().toDouble(&ok);
|
|
if (ok)
|
|
{
|
|
head.push_back("X0(2)");
|
|
onecase.push_back(hground+val);
|
|
}
|
|
head.push_back("force_sysauto_level");
|
|
onecase.push_back(0);
|
|
}
|
|
else
|
|
{
|
|
head.push_back("force_sysauto_level");
|
|
onecase.push_back(1);
|
|
}
|
|
|
|
setup_param(head, onecase);
|
|
(*init_func)();
|
|
|
|
QString filename = QString("sil")
|
|
+QDateTime::currentDateTime().toString("yyyyMMddhhmmss")
|
|
+".DAT";
|
|
rec_file = new QFile(filename, this);
|
|
rec_file->open(QFile::WriteOnly);
|
|
|
|
seq = 0;
|
|
seq_rec = 0;
|
|
|
|
timer200Hz = new QTimer(this);
|
|
connect(timer200Hz, SIGNAL(timeout()), this, SLOT(update200Hz()));
|
|
timer200Hz->start(5);
|
|
|
|
if (ui->radioButtonOnGround->isChecked())
|
|
{
|
|
stage = 2;
|
|
ui->pushButton_start->setText(QString("Launch"));
|
|
ui->pushButtonLaunch->setEnabled(true);
|
|
ui->tabWidget->setCurrentIndex(1);
|
|
u->fault = 0x0;
|
|
}
|
|
if (ui->radioButtonInAir->isChecked())
|
|
{
|
|
stage = 3;
|
|
ui->pushButton_start->setText(QString("Flying"));
|
|
ui->pushButtonLaunch->setText(QString("Flying"));
|
|
ui->pushButton_start->setEnabled(false);
|
|
ui->pushButtonLaunch->setEnabled(false);
|
|
ui->tabWidget->setCurrentIndex(1);
|
|
u->fault = 0x40;
|
|
}
|
|
}
|
|
else if (stage == 2)
|
|
{
|
|
u->launch_trigger = 1.0;
|
|
ui->pushButton_start->setText(QString("Flying"));
|
|
ui->pushButtonLaunch->setText(QString("Flying"));
|
|
ui->pushButton_start->setEnabled(false);
|
|
ui->pushButtonLaunch->setEnabled(false);
|
|
stage = 3;
|
|
ui->tabWidget->setCurrentIndex(1);
|
|
}
|
|
}
|
|
|
|
void MainWindow::onExport()
|
|
{
|
|
QString filename = QFileDialog::getSaveFileName(this, tr("Save to"), QString(), tr("Text File (*.txt)"));
|
|
if (!filename.isEmpty())
|
|
{
|
|
QFile data(filename);
|
|
if (data.open(QFile::WriteOnly | QFile::Truncate)) {
|
|
QTextStream out(&data);
|
|
int n = ui->tableWidget->rowCount();
|
|
for (int i=0;i<n;++i)
|
|
{
|
|
out << ui->tableWidget->item(i,0)->text() << ',';
|
|
out << ui->tableWidget->item(i,1)->text() << '\n';
|
|
}
|
|
out << QString("X0") << ',' << ui->lineEditLat->text() << '\n';
|
|
out << QString("X0(1)") << ',' << ui->lineEditLon->text() << '\n';
|
|
out << QString("hground") << ',' << ui->lineEditAlt->text() << '\n';
|
|
out << QString("Att0(2)") << ',' << ui->lineEditHdg->text().toDouble()/57.3 << '\n';
|
|
}
|
|
}
|
|
}
|
|
|
|
void MainWindow::onImport()
|
|
{
|
|
QString filename = QFileDialog::getOpenFileName(this, tr("Save to"), QString(), tr("Text File (*.txt)"));
|
|
if (!filename.isEmpty())
|
|
{
|
|
QFile data(filename);
|
|
if (data.open(QFile::ReadOnly)) {
|
|
QTextStream stream(&data);
|
|
QString line;
|
|
while (stream.readLineInto(&line)) {
|
|
QStringList items = line.split(QString(","));
|
|
int n = ui->tableWidget->rowCount();
|
|
for (int i=0;i<n;++i)
|
|
{
|
|
if (ui->tableWidget->item(i,0)->text() == items[0])
|
|
{
|
|
ui->tableWidget->item(i,1)->setText(items[1]);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
{
|
|
int n = ui->tableWidget->rowCount();
|
|
for (int i=0;i<n;++i)
|
|
{
|
|
if (ui->tableWidget->item(i,0)->text() == "X0")
|
|
{
|
|
ui->lineEditLat->setText(ui->tableWidget->item(i,1)->text());
|
|
}
|
|
else if (ui->tableWidget->item(i,0)->text() == "X0(1)")
|
|
{
|
|
ui->lineEditLon->setText(ui->tableWidget->item(i,1)->text());
|
|
}
|
|
else if (ui->tableWidget->item(i,0)->text() == "hground")
|
|
{
|
|
ui->lineEditAlt->setText(ui->tableWidget->item(i,1)->text());
|
|
}
|
|
else if (ui->tableWidget->item(i,0)->text() == "Att0(2)")
|
|
{
|
|
ui->lineEditHdg->setText(QString("%1").arg(ui->tableWidget->item(i,1)->text().toDouble()*57.3));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
void MainWindow::onTimes(int i)
|
|
{
|
|
times = i;
|
|
}
|
|
|
|
void MainWindow::onAG()
|
|
{
|
|
if (ui->radioButtonOnGround->isChecked())
|
|
{
|
|
ui->lineEditSpeed->setEnabled(false);
|
|
ui->lineEditAGL->setEnabled(false);
|
|
}
|
|
if (ui->radioButtonInAir->isChecked())
|
|
{
|
|
ui->lineEditSpeed->setEnabled(true);
|
|
ui->lineEditAGL->setEnabled(true);
|
|
}
|
|
}
|