Newer
Older
#include <QMessageBox>
Lorenz Meier
committed
#include <QProgressDialog>
Lorenz Meier
committed
#include <QTimer>
#include "QGCPX4AirframeConfig.h"
#include "ui_QGCPX4AirframeConfig.h"
Lorenz Meier
committed
#include "UASManager.h"
#include "LinkManager.h"
Lorenz Meier
committed
#include "UAS.h"
Lorenz Meier
committed
#include "QGC.h"
Lorenz Meier
committed
QGCPX4AirframeConfig::QGCPX4AirframeConfig(QWidget *parent) :
QWidget(parent),
Lorenz Meier
committed
mav(NULL),
Lorenz Meier
committed
progress(NULL),
pendingParams(0),
configState(CONFIG_STATE_ABORT),
ui(new Ui::QGCPX4AirframeConfig)
{
ui->setupUi(this);
Lorenz Meier
committed
// Fill the lists here manually in accordance with the list from:
// https://github.com/PX4/Firmware/blob/master/ROMFS/px4fmu_common/init.d/rcS
ui->simComboBox->addItem(tr("Plane (HilStar, X-Plane)"), 1000);
ui->simComboBox->addItem(tr("Plane (Rascal, FlightGear)"), 1004);
ui->simComboBox->addItem(tr("Quad X HIL"), 1001);
ui->simComboBox->addItem(tr("Quad + HIL"), 1003);
connect(ui->simPushButton, SIGNAL(clicked()), this, SLOT(simSelected()));
connect(ui->simComboBox, SIGNAL(activated(int)), this, SLOT(simSelected(int)));
ui->simPushButton->setEnabled(ui->simComboBox->count() > 0);
ui->planeComboBox->addItem(tr("Multiplex Easystar 1/2"), 2100);
ui->planeComboBox->addItem(tr("Hobbyking Bixler 1/2"), 2101);
ui->planeComboBox->addItem(tr("3DR Skywalker"), 2102);
ui->planeComboBox->addItem(tr("Skyhunter (1800 mm)"), 2103);
Lorenz Meier
committed
connect(ui->planePushButton, SIGNAL(clicked()), this, SLOT(planeSelected()));
connect(ui->planeComboBox, SIGNAL(activated(int)), this, SLOT(planeSelected(int)));
ui->planePushButton->setEnabled(ui->planeComboBox->count() > 0);
Lorenz Meier
committed
ui->flyingWingComboBox->addItem(tr("Z-84 Wing Wing (845 mm)"), 3033);
ui->flyingWingComboBox->addItem(tr("TBS Caipirinha (850 mm)"), 3100);
ui->flyingWingComboBox->addItem(tr("Bormatec Camflyer Q (800 mm)"), 3030);
ui->flyingWingComboBox->addItem(tr("FX-61 Phantom FPV (1550 mm)"), 3031);
ui->flyingWingComboBox->addItem(tr("FX-79 Buffalo (2000 mm)"), 3034);
ui->flyingWingComboBox->addItem(tr("Skywalker X5 (1180 mm)"), 3032);
ui->flyingWingComboBox->addItem(tr("Viper v2 (3000 mm)"), 3035);
Lorenz Meier
committed
connect(ui->flyingWingPushButton, SIGNAL(clicked()), this, SLOT(flyingWingSelected()));
connect(ui->flyingWingComboBox, SIGNAL(activated(int)), this, SLOT(flyingWingSelected(int)));
Lorenz Meier
committed
ui->quadXComboBox->addItem(tr("DJI F330 8\" Quad"), 4010);
ui->quadXComboBox->addItem(tr("DJI F450 10\" Quad"), 4011);
ui->quadXComboBox->addItem(tr("X frame Quad UAVCAN"), 4012);
ui->quadXComboBox->addItem(tr("AR.Drone Frame Quad"), 4008);
// ui->quadXComboBox->addItem(tr("DJI F330 with MK BLCTRL"), 4017);
// ui->quadXComboBox->addItem(tr("Mikrokopter X frame"), 4019);
Lorenz Meier
committed
connect(ui->quadXPushButton, SIGNAL(clicked()), this, SLOT(quadXSelected()));
connect(ui->quadXComboBox, SIGNAL(activated(int)), this, SLOT(quadXSelected(int)));
ui->quadXPushButton->setEnabled(ui->quadXComboBox->count() > 0);
ui->quadPlusComboBox->addItem(tr("Generic 10\" Quad +"), 5001);
// ui->quadXComboBox->addItem(tr("Mikrokopter + frame"), 5020);
Lorenz Meier
committed
connect(ui->quadPlusPushButton, SIGNAL(clicked()), this, SLOT(quadPlusSelected()));
connect(ui->quadPlusComboBox, SIGNAL(activated(int)), this, SLOT(quadPlusSelected(int)));
ui->quadPlusPushButton->setEnabled(ui->quadPlusComboBox->count() > 0);
Lorenz Meier
committed
ui->hexaXComboBox->addItem(tr("Standard 10\" Hexa X"), 6001);
ui->hexaXComboBox->addItem(tr("Coaxial 10\" Hexa X"), 11001);
connect(ui->hexaXPushButton, SIGNAL(clicked()), this, SLOT(hexaXSelected()));
connect(ui->hexaXComboBox, SIGNAL(activated(int)), this, SLOT(hexaXSelected(int)));
ui->hexaXPushButton->setEnabled(ui->hexaXComboBox->count() > 0);
Lorenz Meier
committed
ui->hexaPlusComboBox->addItem(tr("Standard 10\" Hexa"), 7001);
connect(ui->hexaPlusPushButton, SIGNAL(clicked()), this, SLOT(hexaPlusSelected()));
connect(ui->hexaPlusComboBox, SIGNAL(activated(int)), this, SLOT(hexaPlusSelected(int)));
ui->hexaPlusPushButton->setEnabled(ui->hexaPlusComboBox->count() > 0);
Lorenz Meier
committed
ui->octoXComboBox->addItem(tr("Standard 10\" Octo"), 8001);
ui->octoXComboBox->addItem(tr("Coaxial 10\" Octo"), 12001);
connect(ui->octoXPushButton, SIGNAL(clicked()), this, SLOT(octoXSelected()));
connect(ui->octoXComboBox, SIGNAL(activated(int)), this, SLOT(octoXSelected(int)));
ui->octoXPushButton->setEnabled(ui->octoXComboBox->count() > 0);
Lorenz Meier
committed
ui->octoPlusComboBox->addItem(tr("Standard 10\" Octo"), 9001);
connect(ui->octoPlusPushButton, SIGNAL(clicked()), this, SLOT(octoPlusSelected()));
connect(ui->octoPlusComboBox, SIGNAL(activated(int)), this, SLOT(octoPlusSelected(int)));
ui->octoPlusPushButton->setEnabled(ui->octoPlusComboBox->count() > 0);
Lorenz Meier
committed
ui->hComboBox->addItem(tr("3DR Iris"), 10016);
ui->hComboBox->addItem(tr("TBS Discovery"), 10015);
connect(ui->hPushButton, SIGNAL(clicked()), this, SLOT(hSelected()));
connect(ui->hComboBox, SIGNAL(activated(int)), this, SLOT(hSelected(int)));
ui->hPushButton->setEnabled(ui->hComboBox->count() > 0);
Lorenz Meier
committed
connect(ui->applyButton, SIGNAL(clicked()), this, SLOT(applyAndReboot()));
connect(UASManager::instance(), SIGNAL(activeUASSet(UASInterface*)), this, SLOT(setActiveUAS(UASInterface*)));
Lorenz Meier
committed
Lorenz Meier
committed
uncheckAll();
setActiveUAS(UASManager::instance()->getActiveUAS());
Lorenz Meier
committed
}
void QGCPX4AirframeConfig::parameterChanged(int uas, int component, QString parameterName, QVariant value)
{
Q_UNUSED(uas);
Q_UNUSED(component);
if (parameterName.contains("SYS_AUTOSTART"))
{
int index = value.toInt();
if (index > 0) {
setAirframeID(index);
ui->statusLabel->setText(tr("Onboard start script ID: #%1").arg(index));
} else {
Lorenz Meier
committed
uncheckAll();
ui->statusLabel->setText(tr("System not configured for autostart."));
}
}
}
Lorenz Meier
committed
void QGCPX4AirframeConfig::setActiveUAS(UASInterface* uas)
{
if (mav)
{
disconnect(mav, SIGNAL(parameterChanged(int,int,QString,QVariant)), this, SLOT(parameterChanged(int,int,QString,QVariant)));
Lorenz Meier
committed
if (!uas)
return;
mav = uas;
Lorenz Meier
committed
connect(mav, SIGNAL(parameterChanged(int,int,QString,QVariant)), this, SLOT(parameterChanged(int,int,QString,QVariant)));
// If the parameters are ready, we aren't going to get paramterChanged signals. So fake them in order to make the UI work.
if (uas->getParamManager()->parametersReady()) {
QVariant value;
static const char* param = "SYS_AUTOSTART";
QGCUASParamManagerInterface* paramMgr = uas->getParamManager();
QList<int> compIds = paramMgr->getComponentForParam(param);
Q_ASSERT(compIds.count() == 1);
paramMgr->getParameterValue(compIds[0], param, value);
parameterChanged(uas->getUASID(), compIds[0], param, value);
}
void QGCPX4AirframeConfig::uncheckAll()
{
ui->planePushButton->setChecked(false);
ui->flyingWingPushButton->setChecked(false);
ui->quadXPushButton->setChecked(false);
ui->quadPlusPushButton->setChecked(false);
ui->hexaXPushButton->setChecked(false);
ui->hexaPlusPushButton->setChecked(false);
ui->octoXPushButton->setChecked(false);
ui->octoPlusPushButton->setChecked(false);
ui->hPushButton->setChecked(false);
Lorenz Meier
committed
}
void QGCPX4AirframeConfig::setAirframeID(int id)
{
qDebug() << "setAirframeID" << id;
ui->statusLabel->setText(tr("Start script ID: #%1").arg(id));
// XXX too much boilerplate code here - this widget is really just
// a quick hack to get started
uncheckAll();
if (id >= 1000 && id < 2000)
{
ui->simPushButton->setChecked(true);
ui->simComboBox->setCurrentIndex(ui->simComboBox->findData(id));
ui->statusLabel->setText(tr("Selected simulation (ID: #%1)").arg(selectedId));
else if (id >= 2000 && id < 3000)
ui->planePushButton->setChecked(true);
ui->planeComboBox->setCurrentIndex(ui->planeComboBox->findData(id));
ui->statusLabel->setText(tr("Selected plane (ID: #%1)").arg(selectedId));
else if (id >= 3000 && id < 4000)
{
ui->flyingWingPushButton->setChecked(true);
ui->flyingWingComboBox->setCurrentIndex(ui->flyingWingComboBox->findData(id));
ui->statusLabel->setText(tr("Selected flying wing (ID: #%1)").arg(selectedId));
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
else if (id >= 4000 && id < 5000) {
ui->quadXPushButton->setChecked(true);
ui->quadXComboBox->setCurrentIndex(ui->quadXComboBox->findData(id));
ui->statusLabel->setText(tr("Selected quadrotor in X config (ID: #%1)").arg(selectedId));
}
else if (id >= 5000 && id < 6000) {
ui->quadPlusPushButton->setChecked(true);
ui->quadPlusComboBox->setCurrentIndex(ui->quadPlusComboBox->findData(id));
ui->statusLabel->setText(tr("Selected quadrotor in + config (ID: #%1)").arg(selectedId));
}
else if (id >= 6000 && id < 7000) {
ui->hexaXPushButton->setChecked(true);
ui->hexaXComboBox->setCurrentIndex(ui->hexaXComboBox->findData(id));
ui->statusLabel->setText(tr("Selected hexarotor in X config (ID: #%1)").arg(selectedId));
}
else if (id >= 7000 && id < 8000) {
ui->hexaPlusPushButton->setChecked(true);
ui->hexaPlusComboBox->setCurrentIndex(ui->hexaPlusComboBox->findData(id));
ui->statusLabel->setText(tr("Selected hexarotor in + config (ID: #%1)").arg(selectedId));
}
else if (id >= 8000 && id < 9000) {
ui->octoXPushButton->setChecked(true);
ui->octoXComboBox->setCurrentIndex(ui->octoXComboBox->findData(id));
ui->statusLabel->setText(tr("Selected octorotor in X config (ID: #%1)").arg(selectedId));
}
else if (id >= 9000 && id < 10000) {
ui->octoPlusPushButton->setChecked(true);
ui->octoPlusComboBox->setCurrentIndex(ui->octoPlusComboBox->findData(id));
ui->statusLabel->setText(tr("Selected octorotor in + config (ID: #%1)").arg(selectedId));
}
else if (id >= 10000 && id < 11000)
ui->hPushButton->setChecked(true);
ui->hComboBox->setCurrentIndex(ui->hComboBox->findData(id));
ui->statusLabel->setText(tr("Selected H frame multirotor (ID: #%1)").arg(selectedId));
Lorenz Meier
committed
}
void QGCPX4AirframeConfig::applyAndReboot()
{
// Guard against the case of an edit where we didn't receive all params yet
{
QMessageBox msgBox;
msgBox.setText(tr("No airframe selected"));
msgBox.setInformativeText(tr("Please select an airframe first."));
msgBox.setStandardButtons(QMessageBox::Ok);
msgBox.setDefaultButton(QMessageBox::Ok);
(void)msgBox.exec();
return;
}
if (!mav)
return;
if (paramMgr->countOnboardParams() == 0 &&
paramMgr->countPendingParams() == 0)
Lorenz Meier
committed
paramMgr->requestParameterList();
QGC::SLEEP::msleep(300);
Lorenz Meier
committed
QList<int> components = paramMgr->getComponentForParam("SYS_AUTOSTART");
// Guard against the case of an edit where we didn't receive all params yet
Lorenz Meier
committed
if (paramMgr->countPendingParams() > 0 || components.count() == 0)
{
QMessageBox msgBox;
msgBox.setText(tr("Parameter sync with UAS not yet complete"));
msgBox.setInformativeText(tr("Please wait a few moments and retry"));
msgBox.setStandardButtons(QMessageBox::Ok);
msgBox.setDefaultButton(QMessageBox::Ok);
(void)msgBox.exec();
Lorenz Meier
committed
return;
}
// Guard against multiple components responding - this will never show in practice
if (components.count() != 1) {
QMessageBox msgBox;
msgBox.setText(tr("Invalid system setup detected"));
msgBox.setInformativeText(tr("None or more than one component advertised to provide the main system configuration option. This is an invalid system setup - please check your autopilot."));
msgBox.setStandardButtons(QMessageBox::Ok);
msgBox.setDefaultButton(QMessageBox::Ok);
(void)msgBox.exec();
return;
}
Lorenz Meier
committed
// This is really evil: 'fake' a thread by
// periodic work queue calls and clock
// through a small state machine
// ugh.. if we just had time to do this properly.
// To the reader who can't program and wants to whine:
// this is not beautiful, but technically completely
// sound. If you want to fix it, you'd be welcome
// to rebase the link, param manager and UI classes
// on a proper threading framework - which I'd love to do
// if I just had more time..
configState = CONFIG_STATE_SEND;
QTimer::singleShot(200, this, SLOT(checkConfigState()));
Lorenz Meier
committed
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
}
void QGCPX4AirframeConfig::checkConfigState()
{
if (configState == CONFIG_STATE_SEND)
{
QList<int> components = paramMgr->getComponentForParam("SYS_AUTOSTART");
qDebug() << "Setting comp" << components.first() << "SYS_AUTOSTART" << (qint32)selectedId;
paramMgr->setPendingParam(components.first(),"SYS_AUTOSTART", (qint32)selectedId);
//need to set autoconfig in order for PX4 to pick up the selected airframe params
if (ui->defaultGainsCheckBox->checkState() == Qt::Checked)
setAutoConfig(true);
// Send pending params and then write them to persistent storage when done
paramMgr->sendPendingParameters(true);
configState = CONFIG_STATE_WAIT_PENDING;
pendingParams = 0;
QTimer::singleShot(2000, this, SLOT(checkConfigState()));
return;
}
if (configState == CONFIG_STATE_WAIT_PENDING) {
// Guard against the case of an edit where we didn't receive all params yet
if (paramMgr->countPendingParams() > 0)
{
if (pendingParams == 0) {
pendingParams = paramMgr->countPendingParams();
if (progress)
delete progress;
progress = new QProgressDialog("Writing parameters", "Abort Send", 0, pendingParams, this);
progress->setWindowModality(Qt::WindowModal);
progress->setMinimumDuration(2000);
}
qDebug() << "PENDING" << paramMgr->countPendingParams() << "PROGRESS" << pendingParams - paramMgr->countPendingParams();
progress->setValue(pendingParams - paramMgr->countPendingParams());
if (progress->wasCanceled()) {
configState = CONFIG_STATE_ABORT;
Lorenz Meier
committed
pendingParams = 0;
return;
}
} else {
pendingParams = 0;
configState = CONFIG_STATE_REBOOT;
}
qDebug() << "PENDING PARAMS WAIT PENDING: " << paramMgr->countPendingParams();
QTimer::singleShot(1000, this, SLOT(checkConfigState()));
return;
}
if (configState == CONFIG_STATE_REBOOT) {
// Reboot
//TODO right now this relies upon the above send & persist finishing before the reboot command is received...
Lorenz Meier
committed
qDebug() << "PENDING PARAMS REBOOT BEFORE" << pendingParams;
if (pendingParams == 0) {
pendingParams = 1;
if (progress)
delete progress;
progress = new QProgressDialog("Waiting for autopilot reboot", "Abort", 0, pendingMax, this);
progress->setWindowModality(Qt::WindowModal);
qDebug() << "Waiting for reboot, pending" << pendingParams;
} else {
if (progress->wasCanceled()) {
configState = CONFIG_STATE_ABORT;
setEnabled(true);
pendingParams = 0;
return;
}
Lorenz Meier
committed
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
}
if (pendingParams == 3) {
qDebug() << "REQUESTING REBOOT";
mav->executeCommand(MAV_CMD_PREFLIGHT_REBOOT_SHUTDOWN, 1, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0);
mav->executeCommand(MAV_CMD_PREFLIGHT_REBOOT_SHUTDOWN, 1, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0);
}
if (pendingParams == 4) {
qDebug() << "DISCONNECT AIRFRAME";
LinkManager::instance()->disconnectAll();
}
if (pendingParams == 14) {
qDebug() << "CONNECT AIRFRAME";
LinkManager::instance()->connectAll();
}
if (pendingParams < pendingMax) {
progress->setValue(pendingParams);
QTimer::singleShot(1000, this, SLOT(checkConfigState()));
} else {
paramMgr->requestParameterList();
progress->setValue(pendingMax);
configState = CONFIG_STATE_ABORT;
pendingParams = 0;
Lorenz Meier
committed
return;
}
qDebug() << "PENDING PARAMS REBOOT AFTER:" << pendingParams;
pendingParams++;
return;
}
Lorenz Meier
committed
}
void QGCPX4AirframeConfig::setAutoConfig(bool enabled)
{
if (!mav)
return;
paramMgr->setPendingParam(0, "SYS_AUTOCONFIG", (qint32) ((enabled) ? 1 : 0));
Lorenz Meier
committed
}
void QGCPX4AirframeConfig::simSelected()
{
simSelected(ui->simComboBox->currentIndex());
}
void QGCPX4AirframeConfig::simSelected(int index)
{
int system_index = ui->simComboBox->itemData(index).toInt();
setAirframeID(system_index);
}
Lorenz Meier
committed
void QGCPX4AirframeConfig::flyingWingSelected()
{
flyingWingSelected(ui->flyingWingComboBox->currentIndex());
Lorenz Meier
committed
void QGCPX4AirframeConfig::flyingWingSelected(int index)
{
int system_index = ui->flyingWingComboBox->itemData(index).toInt();
setAirframeID(system_index);
}
void QGCPX4AirframeConfig::planeSelected()
{
planeSelected(ui->planeComboBox->currentIndex());
Lorenz Meier
committed
}
void QGCPX4AirframeConfig::planeSelected(int index)
{
int system_index = ui->planeComboBox->itemData(index).toInt();
setAirframeID(system_index);
}
void QGCPX4AirframeConfig::quadXSelected()
{
quadXSelected(ui->quadXComboBox->currentIndex());
Lorenz Meier
committed
}
void QGCPX4AirframeConfig::quadXSelected(int index)
{
int system_index = ui->quadXComboBox->itemData(index).toInt();
setAirframeID(system_index);
}
void QGCPX4AirframeConfig::quadPlusSelected()
{
quadPlusSelected(ui->quadPlusComboBox->currentIndex());
Lorenz Meier
committed
}
void QGCPX4AirframeConfig::quadPlusSelected(int index)
{
int system_index = ui->quadPlusComboBox->itemData(index).toInt();
setAirframeID(system_index);
}
void QGCPX4AirframeConfig::hexaXSelected()
{
hexaXSelected(ui->hexaXComboBox->currentIndex());
Lorenz Meier
committed
}
void QGCPX4AirframeConfig::hexaXSelected(int index)
{
int system_index = ui->hexaXComboBox->itemData(index).toInt();
setAirframeID(system_index);
}
void QGCPX4AirframeConfig::hexaPlusSelected()
{
hexaPlusSelected(ui->hexaPlusComboBox->currentIndex());
Lorenz Meier
committed
}
void QGCPX4AirframeConfig::hexaPlusSelected(int index)
{
int system_index = ui->hexaPlusComboBox->itemData(index).toInt();
setAirframeID(system_index);
}
void QGCPX4AirframeConfig::octoXSelected()
{
octoXSelected(ui->octoXComboBox->currentIndex());
Lorenz Meier
committed
}
void QGCPX4AirframeConfig::octoXSelected(int index)
{
int system_index = ui->octoXComboBox->itemData(index).toInt();
setAirframeID(system_index);
}
void QGCPX4AirframeConfig::octoPlusSelected()
{
octoPlusSelected(ui->octoPlusComboBox->currentIndex());
Lorenz Meier
committed
}
void QGCPX4AirframeConfig::octoPlusSelected(int index)
{
int system_index = ui->octoPlusComboBox->itemData(index).toInt();
setAirframeID(system_index);
}
void QGCPX4AirframeConfig::hSelected()
{
hSelected(ui->hComboBox->currentIndex());
Lorenz Meier
committed
}
void QGCPX4AirframeConfig::hSelected(int index)
{
int system_index = ui->hComboBox->itemData(index).toInt();
setAirframeID(system_index);
}
QGCPX4AirframeConfig::~QGCPX4AirframeConfig()
{
delete ui;
}