Commit 04293e2c authored by Don Gagne's avatar Don Gagne

Moved RC Cal to it's own separate widget code

parent a167021b
......@@ -23,6 +23,7 @@
#include "ui_QGCPX4VehicleConfig.h"
#include "px4_configuration/QGCPX4AirframeConfig.h"
#include "px4_configuration/QGCPX4SensorCalibration.h"
#include "px4_configuration/PX4RCCalibration.h"
#ifdef QGC_QUPGRADE_ENABLED
#include <dialog_bare.h>
......@@ -41,23 +42,6 @@
QGCPX4VehicleConfig::QGCPX4VehicleConfig(QWidget *parent) :
QWidget(parent),
mav(NULL),
chanCount(0),
channelWanted(-1),
channelReverseStateWanted(-1),
rcRoll(0.0f),
rcPitch(0.0f),
rcYaw(0.0f),
rcThrottle(0.0f),
rcMode(0.0f),
rcAssist(0.0f),
rcLoiter(0.0f),
rcReturn(0.0f),
rcFlaps(0.0f),
rcAux1(0.0f),
rcAux2(0.0f),
dataModelChanged(true),
calibrationEnabled(false),
configEnabled(false),
px4AirframeConfig(NULL),
planeBack(":/files/images/px4/rc/cessna_back.png"),
planeSide(":/files/images/px4/rc/cessna_side.png"),
......@@ -66,24 +50,6 @@ QGCPX4VehicleConfig::QGCPX4VehicleConfig(QWidget *parent) :
{
doneLoadingConfig = false;
channelNames << "Roll / Aileron";
channelNames << "Pitch / Elevator";
channelNames << "Yaw / Rudder";
channelNames << "Throttle";
channelNames << "Main Mode Switch";
channelNames << "Posctl Switch";
channelNames << "Loiter Switch";
channelNames << "Return Switch";
channelNames << "Flaps";
channelNames << "Aux1";
channelNames << "Aux2";
channelNames << "Aux3";
channelNames << "Aux4";
channelNames << "Aux5";
channelNames << "Aux6";
channelNames << "Aux7";
channelNames << "Aux8";
setObjectName("QGC_VEHICLECONFIG");
ui->setupUi(this);
......@@ -95,18 +61,12 @@ QGCPX4VehicleConfig::QGCPX4VehicleConfig(QWidget *parent) :
px4AirframeConfig = new QGCPX4AirframeConfig(this);
ui->airframeLayout->addWidget(px4AirframeConfig);
// px4SafetyConfig = new QGCPX4SafetyConfig(this);
// ui->safetyConfigLayout->addWidget(px4SafetyConfig);
// px4TuningConfig = new QGCPX4TuningConfig(this);
// ui->tuningLayout->addWidget(px4TuningConfig);
// px4FlightModeConfig = new QGCPX4FlightModeConfig(this);
// ui->flightModeLayout->addWidget(px4FlightModeConfig);
px4SensorCalibration = new QGCPX4SensorCalibration(this);
ui->sensorLayout->addWidget(px4SensorCalibration);
px4RCCalibration = new PX4RCCalibration(this);
ui->rcLayout->addWidget(px4RCCalibration);
#ifdef QGC_QUPGRADE_ENABLED
DialogBare *firmwareDialog = new DialogBare(this);
ui->firmwareLayout->addWidget(firmwareDialog);
......@@ -120,45 +80,8 @@ QGCPX4VehicleConfig::QGCPX4VehicleConfig(QWidget *parent) :
ui->firmwareLayout->addWidget(label);
#endif
ui->rollWidget->setOrientation(Qt::Horizontal);
ui->rollWidget->setName("Roll");
ui->yawWidget->setOrientation(Qt::Horizontal);
ui->yawWidget->setName("Yaw");
ui->pitchWidget->setName("Pitch");
ui->throttleWidget->setName("Throttle");
ui->radio5Widget->setOrientation(Qt::Horizontal);
ui->radio5Widget->setName("Radio 5");
ui->radio6Widget->setOrientation(Qt::Horizontal);
ui->radio6Widget->setName("Radio 6");
ui->radio7Widget->setOrientation(Qt::Horizontal);
ui->radio7Widget->setName("Radio 7");
ui->radio8Widget->setOrientation(Qt::Horizontal);
ui->radio8Widget->setName("Radio 8");
ui->radio9Widget->setOrientation(Qt::Horizontal);
ui->radio9Widget->setName("Radio 9");
ui->radio10Widget->setOrientation(Qt::Horizontal);
ui->radio10Widget->setName("Radio 10");
ui->radio11Widget->setOrientation(Qt::Horizontal);
ui->radio11Widget->setName("Radio 11");
ui->radio12Widget->setOrientation(Qt::Horizontal);
ui->radio12Widget->setName("Radio 12");
ui->radio13Widget->setOrientation(Qt::Horizontal);
ui->radio13Widget->setName("Radio 13");
ui->radio14Widget->setOrientation(Qt::Horizontal);
ui->radio14Widget->setName("Radio 14");
ui->radio15Widget->setOrientation(Qt::Horizontal);
ui->radio15Widget->setName("Radio 15");
ui->radio16Widget->setOrientation(Qt::Horizontal);
ui->radio16Widget->setName("Radio 16");
ui->radio17Widget->setOrientation(Qt::Horizontal);
ui->radio17Widget->setName("Radio 17");
ui->radio18Widget->setOrientation(Qt::Horizontal);
ui->radio18Widget->setName("Radio 18");
connect(ui->rcMenuButton,SIGNAL(clicked()),
this,SLOT(rcMenuButtonClicked()));
connect(ui->rcCopyTrimButton, SIGNAL(clicked()),
this, SLOT(copyAttitudeTrim()));
connect(ui->sensorMenuButton,SIGNAL(clicked()),
this,SLOT(sensorMenuButtonClicked()));
connect(ui->flightModeMenuButton, SIGNAL(clicked()),
......@@ -174,32 +97,6 @@ QGCPX4VehicleConfig::QGCPX4VehicleConfig(QWidget *parent) :
connect(ui->firmwareMenuButton, SIGNAL(clicked()),
this, SLOT(firmwareMenuButtonClicked()));
// HIDE THE ADVANCED RC CONFIG MENUS
// TOO MANY USERS FOOL THEMSELVES WITH IT
ui->advancedCheckBox->setVisible(false);
//connect(ui->advancedCheckBox, SIGNAL(clicked(bool)), ui->advancedGroupBox, SLOT(setVisible(bool)));
ui->advancedGroupBox->setVisible(false);
#if 0
// XXX WIP don't connect signal until completed, otherwise view will show after advanced is turned on and then off
connect(ui->advancedCheckBox, SIGNAL(clicked(bool)), ui->graphicsView, SLOT(setHidden(bool)));
ui->graphicsView->setVisible(true);
ui->graphicsView->setScene(&scene);
scene.addPixmap(planeBack);
scene.addPixmap(planeSide);
#else
// XXX hide while WIP
ui->graphicsView->hide();
#endif
ui->rcCalibrationButton->setCheckable(true);
ui->rcCalibrationButton->setEnabled(false);
connect(ui->rcCalibrationButton, SIGNAL(clicked(bool)), this, SLOT(toggleCalibrationRC(bool)));
ui->spektrumPairButton->setCheckable(false);
ui->spektrumPairButton->setEnabled(false);
connect(ui->spektrumPairButton, SIGNAL(clicked(bool)), this, SLOT(toggleSpektrumPairing(bool)));
//TODO connect buttons here to save/clear actions?
UASInterface* tmpMav = UASManager::instance()->getActiveUAS();
if (tmpMav) {
......@@ -211,80 +108,7 @@ QGCPX4VehicleConfig::QGCPX4VehicleConfig(QWidget *parent) :
connect(UASManager::instance(), SIGNAL(activeUASSet(UASInterface*)),
this, SLOT(setActiveUAS(UASInterface*)));
// Connect RC mapping assignments
connect(ui->rollSpinBox, SIGNAL(valueChanged(int)), this, SLOT(setRollChan(int)));
connect(ui->pitchSpinBox, SIGNAL(valueChanged(int)), this, SLOT(setPitchChan(int)));
connect(ui->yawSpinBox, SIGNAL(valueChanged(int)), this, SLOT(setYawChan(int)));
connect(ui->throttleSpinBox, SIGNAL(valueChanged(int)), this, SLOT(setThrottleChan(int)));
connect(ui->modeSpinBox, SIGNAL(valueChanged(int)), this, SLOT(setModeChan(int)));
connect(ui->posctlSwSpinBox, SIGNAL(valueChanged(int)), this, SLOT(setAssistChan(int)));
connect(ui->loiterSwSpinBox, SIGNAL(valueChanged(int)), this, SLOT(setMissionChan(int)));
connect(ui->returnSwSpinBox, SIGNAL(valueChanged(int)), this, SLOT(setReturnChan(int)));
connect(ui->flapsSpinBox, SIGNAL(valueChanged(int)), this, SLOT(setFlapsChan(int)));
connect(ui->aux1SpinBox, SIGNAL(valueChanged(int)), this, SLOT(setAux1Chan(int)));
connect(ui->aux2SpinBox, SIGNAL(valueChanged(int)), this, SLOT(setAux2Chan(int)));
// Connect RC reverse assignments
connect(ui->invertCheckBox, SIGNAL(clicked(bool)), this, SLOT(setRollInverted(bool)));
connect(ui->invertCheckBox_2, SIGNAL(clicked(bool)), this, SLOT(setPitchInverted(bool)));
connect(ui->invertCheckBox_3, SIGNAL(clicked(bool)), this, SLOT(setYawInverted(bool)));
connect(ui->invertCheckBox_4, SIGNAL(clicked(bool)), this, SLOT(setThrottleInverted(bool)));
connect(ui->invertCheckBox_5, SIGNAL(clicked(bool)), this, SLOT(setModeInverted(bool)));
connect(ui->posctlSwInvertCheckBox, SIGNAL(clicked(bool)), this, SLOT(setAssistInverted(bool)));
connect(ui->loiterSwInvertCheckBox, SIGNAL(clicked(bool)), this, SLOT(setMissionInverted(bool)));
connect(ui->returnSwInvertCheckBox, SIGNAL(clicked(bool)), this, SLOT(setReturnInverted(bool)));
connect(ui->flapsInvertCheckBox, SIGNAL(clicked(bool)), this, SLOT(setFlapsInverted(bool)));
connect(ui->aux1InvertCheckBox, SIGNAL(clicked(bool)), this, SLOT(setAux1Inverted(bool)));
connect(ui->aux2InvertCheckBox, SIGNAL(clicked(bool)), this, SLOT(setAux2Inverted(bool)));
connect(ui->rollButton, SIGNAL(clicked()), this, SLOT(identifyRollChannel()));
connect(ui->pitchButton, SIGNAL(clicked()), this, SLOT(identifyPitchChannel()));
connect(ui->yawButton, SIGNAL(clicked()), this, SLOT(identifyYawChannel()));
connect(ui->throttleButton, SIGNAL(clicked()), this, SLOT(identifyThrottleChannel()));
connect(ui->modeButton, SIGNAL(clicked()), this, SLOT(identifyModeChannel()));
connect(ui->posctlSwButton, SIGNAL(clicked()), this, SLOT(identifyAssistChannel()));
connect(ui->loiterSwButton, SIGNAL(clicked()), this, SLOT(identifyMissionChannel()));
connect(ui->returnSwButton, SIGNAL(clicked()), this, SLOT(identifyReturnChannel()));
connect(ui->flapsButton, SIGNAL(clicked()), this, SLOT(identifyFlapsChannel()));
connect(ui->aux1Button, SIGNAL(clicked()), this, SLOT(identifyAux1Channel()));
connect(ui->aux2Button, SIGNAL(clicked()), this, SLOT(identifyAux2Channel()));
connect(ui->persistRcValuesButt,SIGNAL(clicked()), this, SLOT(writeCalibrationRC()));
//set rc values to defaults
for (unsigned int i = 0; i < chanMax; i++) {
rcValue[i] = UINT16_MAX;
rcValueReversed[i] = UINT16_MAX;
rcMapping[i] = i;
rcToFunctionMapping[i] = i;
channelWantedList[i] = (float)UINT16_MAX;//TODO need to clean these up!
rcMin[i] = 1000.0f;
rcMax[i] = 2000.0f;
// Mapping not established here, so can't pick values via mapping yet!
rcMappedMin[i] = 1000;
rcMappedMax[i] = 2000;
rcMappedValue[i] = UINT16_MAX;
rcMappedValueRev[i] = UINT16_MAX;
rcMappedNormalizedValue[i] = 0.0f;
}
for (unsigned int i = chanMax -1; i < chanMappedMax; i++) {
rcMapping[i] = -1;
rcMappedMin[i] = 1000;
rcMappedMax[i] = 2000;
rcMappedValue[i] = UINT16_MAX;
rcMappedValueRev[i] = UINT16_MAX;
rcMappedNormalizedValue[i] = 0.0f;
}
firmwareMenuButtonClicked();
updateTimer.setInterval(150);
connect(&updateTimer, SIGNAL(timeout()), this, SLOT(updateView()));
updateTimer.start();
ui->rcLabel->setText(tr("NO RADIO CONTROL INPUT DETECTED. PLEASE ENSURE THE TRANSMITTER IS ON."));
}
QGCPX4VehicleConfig::~QGCPX4VehicleConfig()
......@@ -340,50 +164,7 @@ void QGCPX4VehicleConfig::firmwareMenuButtonClicked()
ui->tabTitleLabel->setText(tr("Firmware Upgrade"));
}
void QGCPX4VehicleConfig::identifyChannelMapping(int aert_index)
{
if (chanCount == 0 || aert_index < 0)
return;
int oldmapping = rcMapping[aert_index];
channelWanted = aert_index;
for (unsigned i = 0; i < chanMax; i++) {
if (i >= chanCount) {
channelWantedList[i] = 0;
}
else {
channelWantedList[i] = rcValue[i];
}
}
msgBox.setText(tr("Detecting %1 ...\t\t").arg(channelNames[channelWanted]));
msgBox.setInformativeText(tr("Please move stick, switch or potentiometer for this channel all the way up/down or left/right."));
msgBox.setStandardButtons(QMessageBox::NoButton);
skipActionButton = msgBox.addButton(tr("Skip"),QMessageBox::RejectRole);
msgBox.exec();
skipActionButton->hide();
msgBox.removeButton(skipActionButton);
if (msgBox.clickedButton() == skipActionButton ){
channelWanted = -1;
rcMapping[aert_index] = oldmapping;
}
skipActionButton = NULL;
}
void QGCPX4VehicleConfig::toggleCalibrationRC(bool enabled)
{
if (enabled)
{
startCalibrationRC();
}
else
{
stopCalibrationRC();
}
}
#if 0
void QGCPX4VehicleConfig::toggleSpektrumPairing(bool enabled)
{
Q_UNUSED(enabled);
......@@ -412,287 +193,7 @@ void QGCPX4VehicleConfig::toggleSpektrumPairing(bool enabled)
mav->pairRX(0, rxSubType);
}
}
void QGCPX4VehicleConfig::copyAttitudeTrim() {
if (configEnabled) {
QMessageBox warnMsgBox;
warnMsgBox.setText(tr("Attitude trim denied during RC calibration"));
warnMsgBox.setInformativeText(tr("Please end the RC calibration before doing attitude trim."));
warnMsgBox.setStandardButtons(QMessageBox::Ok);
warnMsgBox.setDefaultButton(QMessageBox::Ok);
(void)warnMsgBox.exec();
}
// Not aborted, but warn user
msgBox.setText(tr("Confirm Attitude Trim"));
msgBox.setInformativeText(tr("On clicking OK, the current Roll / Pitch / Yaw stick positions will be set as trim values in auto flight. Do NOT reset your trim values after this step."));
msgBox.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel);//allow user to cancel upload after reviewing values
int msgBoxResult = msgBox.exec();
if (QMessageBox::Cancel == msgBoxResult) {
return;
// do not execute
}
mav->startRadioControlCalibration(2);
QGC::SLEEP::msleep(100);
mav->endRadioControlCalibration();
}
void QGCPX4VehicleConfig::setTrimPositions()
{
int rollMap = rcMapping[0];
int pitchMap = rcMapping[1];
int yawMap = rcMapping[2];
int throttleMap = rcMapping[3];
// Reset all trims, as some might not be touched
for (unsigned i = 0; i < chanCount; i++) {
rcTrim[i] = 1500;
}
bool throttleDone = false;
while (!throttleDone) {
// Set trim to min if stick is close to min
if (abs(rcValue[throttleMap] - rcMin[throttleMap]) < 200) {
rcTrim[throttleMap] = rcMin[throttleMap]; // throttle
throttleDone = true;
}
// Set trim to max if stick is close to max
else if (abs(rcValue[throttleMap] - rcMax[throttleMap]) < 200) {
rcTrim[throttleMap] = rcMax[throttleMap]; // throttle
throttleDone = true;
}
else
{
// Reject
QMessageBox warnMsgBox;
warnMsgBox.setText(tr("Throttle Stick Trim Position Invalid"));
warnMsgBox.setInformativeText(tr("The throttle stick is not in the min position. Please set it to the zero throttle position and then click OK."));
warnMsgBox.setStandardButtons(QMessageBox::Ok | QMessageBox::Abort);
warnMsgBox.setDefaultButton(QMessageBox::Ok);
if (warnMsgBox.exec() == QMessageBox::Abort) {
return;
}
// wait long enough to get some data
QGC::SLEEP::msleep(500);
}
}
// Set trim for roll, pitch, yaw, throttle
rcTrim[rollMap] = rcValue[rollMap]; // roll
rcTrim[pitchMap] = rcValue[pitchMap]; // pitch
rcTrim[yawMap] = rcValue[yawMap]; // yaw
// Mode switch and optional modes, might not be mapped (== -1)
for (unsigned i = 4; i < chanMappedMax; i++) {
if (rcMapping[i] >= 0 && rcMapping[i] < (int)chanCount) {
rcTrim[rcMapping[i]] = ((rcMax[rcMapping[i]] - rcMin[rcMapping[i]]) / 2.0f) + rcMin[rcMapping[i]];
} else if (rcMapping[i] != -1){
qDebug() << "RC MAPPING FAILED #" << i << "VAL:" << rcMapping[i];
}
}
}
void QGCPX4VehicleConfig::detectChannelInversion(int aert_index)
{
if (chanCount == 0 || aert_index < 0 || aert_index >= (int)chanMappedMax)
return;
bool oldstatus = rcRev[rcMapping[aert_index]];
channelReverseStateWanted = aert_index;
// Reset search list
for (unsigned i = 0; i < chanMax; i++) {
if (i >= chanCount) {
channelReverseStateWantedList[i] = 0;
}
else {
channelReverseStateWantedList[i] = rcValue[i];
}
}
QStringList instructions;
instructions << "ROLL: Move stick left";
instructions << "PITCH: Move stick down";//matches the other sticks: should cause DECREASE in raw rc channel value when not reversed
instructions << "YAW: Move stick left";
instructions << "THROTTLE: Move stick down";
instructions << "MODE SWITCH: Push down / towards you";
instructions << "POSITION CONTROL SWITCH: Push down / towards you";
instructions << "LOITER SWITCH: Push down / towards you";
instructions << "RETURN SWITCH: Push down / towards you";
instructions << "FLAPS: Push down / towards you or turn dial to the leftmost position";
instructions << "AUX1: Push down / towards you or turn dial to the leftmost position";
instructions << "AUX2: Push down / towards you or turn dial to the leftmost position";
msgBox.setText(tr("%1 Direction").arg(channelNames[channelReverseStateWanted]));
msgBox.setInformativeText(tr("%2").arg((aert_index < instructions.length()) ? instructions[aert_index] : ""));
msgBox.setStandardButtons(QMessageBox::NoButton);
skipActionButton = msgBox.addButton(tr("Skip"),QMessageBox::RejectRole);
msgBox.exec();
skipActionButton->hide();
msgBox.removeButton(skipActionButton);
if (msgBox.clickedButton() == skipActionButton ){
channelReverseStateWanted = -1;
rcRev[rcMapping[aert_index]] = oldstatus;
}
skipActionButton = NULL;
}
void QGCPX4VehicleConfig::startCalibrationRC()
{
if (chanCount < 5 && !mav) {
QMessageBox::warning(0,
tr("RC not Connected"),
tr("Is the RC receiver connected and transmitter turned on? Detected %1 radio channels. To operate PX4, you need at least 5 channels. ").arg(chanCount));
ui->rcCalibrationButton->setChecked(false);
return;
}
// XXX magic number: Set to 1 for radio input disable
mav->startRadioControlCalibration(1);
// reset all channel mappings above Ch 5 to invalid/unused value before starting calibration
for (unsigned int j= 5; j < chanMappedMax; j++) {
rcMapping[j] = -1;
}
configEnabled = true;
QMessageBox::warning(0,tr("Safety Warning"),
tr("Starting RC calibration.\n\nEnsure RC transmitter and receiver are powered and connected. It is recommended to disconnect all motors for additional safety, however, the system is designed to not arm during the calibration.\n\nReset transmitter trims to center, then click OK to continue"));
//go ahead and try to map first 8 channels, now that user can skip channels
for (int i = 0; i < 8; i++) {
identifyChannelMapping(i);
}
//QMessageBox::information(0,"Information","Additional channels have not been mapped, but can be mapped in the channel table below.");
configEnabled = false;
ui->rcCalibrationButton->setText(tr("Finish RC Calibration"));
resetCalibrationRC();
calibrationEnabled = true;
ui->rollWidget->showMinMax();
ui->pitchWidget->showMinMax();
ui->yawWidget->showMinMax();
ui->throttleWidget->showMinMax();
ui->radio5Widget->showMinMax();
ui->radio6Widget->showMinMax();
ui->radio7Widget->showMinMax();
ui->radio8Widget->showMinMax();
ui->radio9Widget->showMinMax();
ui->radio10Widget->showMinMax();
ui->radio11Widget->showMinMax();
ui->radio12Widget->showMinMax();
ui->radio13Widget->showMinMax();
ui->radio14Widget->showMinMax();
ui->radio15Widget->showMinMax();
ui->radio16Widget->showMinMax();
ui->radio17Widget->showMinMax();
ui->radio18Widget->showMinMax();
msgBox.setText(tr("Information"));
msgBox.setInformativeText(tr("Please move the sticks to their extreme positions, including all switches. Then click on the OK button once finished"));
msgBox.setStandardButtons(QMessageBox::Ok);
msgBox.show();
msgBox.move((frameGeometry().width() - msgBox.width()) / 4.0f,(frameGeometry().height() - msgBox.height()) / 1.5f);
int msgBoxResult = msgBox.exec();
if (QMessageBox::Ok == msgBoxResult) {
stopCalibrationRC();
}
}
void QGCPX4VehicleConfig::stopCalibrationRC()
{
if (!calibrationEnabled)
return;
// Check where the throttle is
while (rcValue[rcMapping[3]] < 1300 || rcValue[rcMapping[3]] > 1700) {
// Force user to center the throttle
msgBox.setText(tr("Please center the throttle stick"));
msgBox.setInformativeText(tr("The stick should be roughly centered - the exact position is not relevant."));
msgBox.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel);//allow user to cancel upload after reviewing values
int msgBoxResult = msgBox.exec();
if (QMessageBox::Cancel == msgBoxResult) {
return; // abort
}
}
// Try to identify inverted channels, but only for R/P/Y/T
for (int i = 0; i < 4; i++) {
detectChannelInversion(i);
}
QMessageBox::information(0,"Trims","Ensure THROTTLE is in the LOW THROTTLE / MOTOR OFF position and roll / pitch / yaw are CENTERED. Click OK to continue");
calibrationEnabled = false;
configEnabled = false;
ui->rcCalibrationButton->setText(tr("Start RC Calibration"));
ui->rcCalibrationButton->blockSignals(true);
ui->rcCalibrationButton->setChecked(false);
ui->rcCalibrationButton->blockSignals(false);
ui->rollWidget->hideMinMax();
ui->pitchWidget->hideMinMax();
ui->yawWidget->hideMinMax();
ui->throttleWidget->hideMinMax();
ui->radio5Widget->hideMinMax();
ui->radio6Widget->hideMinMax();
ui->radio7Widget->hideMinMax();
ui->radio8Widget->hideMinMax();
ui->radio9Widget->hideMinMax();
ui->radio10Widget->hideMinMax();
ui->radio11Widget->hideMinMax();
ui->radio12Widget->hideMinMax();
ui->radio13Widget->hideMinMax();
ui->radio14Widget->hideMinMax();
ui->radio15Widget->hideMinMax();
ui->radio16Widget->hideMinMax();
ui->radio17Widget->hideMinMax();
ui->radio18Widget->hideMinMax();
for (unsigned int i = 0; i < chanCount; i++) {
if (rcMin[i] > 1350) {
rcMin[i] = 1000;
}
if (rcMax[i] < 1650) {
rcMax[i] = 2000;
}
}
qDebug() << "SETTING TRIM";
setTrimPositions();
QString statusstr = tr("The calibration has been finished. Please click OK to upload it to the autopilot.");
// statusstr = tr("This is the RC calibration information that will be sent to the autopilot if you click OK. To prevent transmission, click Cancel.");
// statusstr += tr(" Normal values range from 1000 to 2000, with disconnected channels reading 1000, 1500, 2000\n\n");
// statusstr += tr("Channel\tMin\tCenter\tMax\n");
// statusstr += "-------\t---\t------\t---\n";
// for (unsigned int i=0; i < chanCount; i++) {
// statusstr += QString::number(i) +"\t"+ QString::number(rcMin[i]) +"\t"+ QString::number(rcValue[i]) +"\t"+ QString::number(rcMax[i]) +"\n";
// }
msgBox.setText(tr("Confirm Calibration"));
msgBox.setInformativeText(statusstr);
msgBox.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel);//allow user to cancel upload after reviewing values
int msgBoxResult = msgBox.exec();
// Done, exit calibration mode now
mav->endRadioControlCalibration();
if (QMessageBox::Cancel == msgBoxResult) {
QMessageBox::information(0,"Aborting Calibration","Aborted writing configuration.");
return; //don't commit these values
} else {
QMessageBox::information(0,"Uploading the RC Calibration","The configuration will now be uploaded and permanently stored.");
writeCalibrationRC();
}
}
#endif
void QGCPX4VehicleConfig::loadQgcConfig(bool primary)
{
......@@ -1221,9 +722,6 @@ void QGCPX4VehicleConfig::setActiveUAS(UASInterface* active)
if (mav)
{
// Disconnect old system
disconnect(mav, SIGNAL(remoteControlChannelRawChanged(int,float)), this,
SLOT(remoteControlChannelRawChanged(int,float)));
//TODO use paramCommsMgr instead
disconnect(mav, SIGNAL(parameterChanged(int,int,QString,QVariant)), this,
SLOT(parameterChanged(int,int,QString,QVariant)));
......@@ -1269,16 +767,10 @@ void QGCPX4VehicleConfig::setActiveUAS(UASInterface* active)
ui->pendingCommitsWidget->setUAS(mav);
ui->paramTreeWidget->setUAS(mav);
// Reset current state
resetCalibrationRC();
//TODO eliminate the separate RC_TYPE call
mav->requestParameter(0, "RC_TYPE");
chanCount = 0;
// Connect new system
connect(mav, SIGNAL(remoteControlChannelRawChanged(int,float)), this,
SLOT(remoteControlChannelRawChanged(int,float)));
connect(mav, SIGNAL(parameterChanged(int,int,QString,QVariant)), this,
SLOT(parameterChanged(int,int,QString,QVariant)));
......@@ -1310,539 +802,6 @@ void QGCPX4VehicleConfig::setActiveUAS(UASInterface* active)
ui->airframeMenuButton->setEnabled(true);
ui->sensorMenuButton->setEnabled(true);
ui->rcMenuButton->setEnabled(true);
ui->rcCalibrationButton->setEnabled(true);
ui->spektrumPairButton->setEnabled(true);
}
void QGCPX4VehicleConfig::resetCalibrationRC()
{
for (unsigned int i = 0; i < chanMax; ++i) {
rcMin[i] = 1500;
rcMax[i] = 1500;
}
}
/**
* Sends the RC calibration to the vehicle and stores it in EEPROM
*/
void QGCPX4VehicleConfig::writeCalibrationRC()
{
if (!mav) return;
updateStatus(tr("Sending RC configuration and storing to persistent memory."));
QString minTpl("RC%1_MIN");
QString maxTpl("RC%1_MAX");
QString trimTpl("RC%1_TRIM");
QString revTpl("RC%1_REV");
// Do not write the RC type, as these values depend on this
// active onboard parameter
for (unsigned int i = 0; i < chanCount; ++i) {
//qDebug() << "SENDING" << minTpl.arg(i+1) << rcMin[i];
paramMgr->setPendingParam(0, minTpl.arg(i+1), rcMin[i]);
paramMgr->setPendingParam(0, trimTpl.arg(i+1), rcTrim[i]);
paramMgr->setPendingParam(0, maxTpl.arg(i+1), rcMax[i]);
paramMgr->setPendingParam(0, revTpl.arg(i+1), (rcRev[i]) ? -1.0f : 1.0f);
}
// Write mappings
paramMgr->setPendingParam(0, "RC_MAP_ROLL", (int32_t)(rcMapping[0]+1));
paramMgr->setPendingParam(0, "RC_MAP_PITCH", (int32_t)(rcMapping[1]+1));
paramMgr->setPendingParam(0, "RC_MAP_YAW", (int32_t)(rcMapping[2]+1));
paramMgr->setPendingParam(0, "RC_MAP_THROTTLE", (int32_t)(rcMapping[3]+1));
paramMgr->setPendingParam(0, "RC_MAP_MODE_SW", (int32_t)(rcMapping[4]+1));
paramMgr->setPendingParam(0, "RC_MAP_POSCTL_SW", (int32_t)(rcMapping[5]+1));
paramMgr->setPendingParam(0, "RC_MAP_LOITER_SW", (int32_t)(rcMapping[6]+1));
paramMgr->setPendingParam(0, "RC_MAP_RETURN_SW", (int32_t)(rcMapping[7]+1));
paramMgr->setPendingParam(0, "RC_MAP_FLAPS", (int32_t)(rcMapping[8]+1));
paramMgr->setPendingParam(0, "RC_MAP_AUX1", (int32_t)(rcMapping[9]+1));
paramMgr->setPendingParam(0, "RC_MAP_AUX2", (int32_t)(rcMapping[10]+1));
//let the param mgr manage sending all the pending RC_foo updates and persisting after
paramMgr->sendPendingParameters(true, true);
}
void QGCPX4VehicleConfig::requestCalibrationRC()
{
paramMgr->requestRcCalibrationParamsUpdate();
}
void QGCPX4VehicleConfig::writeParameters()
{
updateStatus(tr("Writing all onboard parameters."));
writeCalibrationRC();
}
void QGCPX4VehicleConfig::remoteControlChannelRawChanged(int chan, float fval)
{
// Check if index and values are sane
if (chan < 0 || static_cast<unsigned int>(chan) >= chanMax || fval < 500.0f || fval > 2500.0f)
return;
if (chan + 1 > (int)chanCount) {
chanCount = chan+1;
}
// Raw value
float deltaRaw = fabsf(fval - rcValue[chan]);
float delta = fabsf(fval - rcMappedValue[rcToFunctionMapping[chan]]);
if (!configEnabled && !calibrationEnabled &&
(deltaRaw < 12.0f && delta < 12.0f && rcValue[chan] > 800 && rcValue[chan] < 2200))
{
// ignore tiny jitter values
return;
}
else {
rcValue[chan] = fval;
}
// Update calibration data
if (calibrationEnabled) {
if (fval < rcMin[chan]) {
rcMin[chan] = fval;
}
if (fval > rcMax[chan]) {
rcMax[chan] = fval;
}
}
if (channelWanted >= 0) {
// If the first channel moved considerably, pick it
if (fabsf(channelWantedList[chan] - fval) > 300.0f) {
rcMapping[channelWanted] = chan;
updateMappingView(channelWanted);
int chanFound = channelWanted;
channelWanted = -1;
// Confirm found channel
msgBox.setText(tr("Found %1 \t\t").arg(channelNames[chanFound]));
msgBox.setInformativeText(tr("Assigned raw RC channel %2").arg(chan + 1));
msgBox.setStandardButtons(QMessageBox::Ok);
msgBox.setDefaultButton(QMessageBox::Ok);
skipActionButton->hide();
msgBox.removeButton(skipActionButton);
(void)msgBox.exec();
// XXX fuse with parameter update handling
switch (chanFound) {
case 0:
ui->rollSpinBox->setValue(chan + 1);
break;
case 1:
ui->pitchSpinBox->setValue(chan + 1);
break;
case 2:
ui->yawSpinBox->setValue(chan + 1);
break;
case 3:
ui->throttleSpinBox->setValue(chan + 1);
break;
case 4:
ui->modeSpinBox->setValue(chan + 1);
break;
case 5:
ui->posctlSwSpinBox->setValue(chan + 1);
break;
case 6:
ui->loiterSwSpinBox->setValue(chan + 1);
break;
case 7:
ui->returnSwSpinBox->setValue(chan + 1);
break;
case 8:
ui->flapsSpinBox->setValue(chan + 1);
break;
case 9:
ui->aux1SpinBox->setValue(chan + 1);
break;
case 10:
ui->aux2SpinBox->setValue(chan + 1);
break;
}
}
}
// Reverse raw value
rcValueReversed[chan] = (rcRev[chan]) ? rcMax[chan] - (fval - rcMin[chan]) : fval;
// Normalized value
float normalized;
float chanTrim = rcTrim[chan];
if (fval >= rcTrim[chan]) {
normalized = (fval - chanTrim)/(rcMax[chan] - chanTrim);
}
else {
normalized = -(chanTrim - fval)/(chanTrim - rcMin[chan]);
}
// Bound
normalized = qBound(-1.0f, normalized, 1.0f);
// Invert
normalized = (rcRev[chan]) ? -1.0f*normalized : normalized;
// Find correct mapped channel
rcMappedValueRev[rcToFunctionMapping[chan]] = rcValueReversed[chan];
rcMappedValue[rcToFunctionMapping[chan]] = fval;
// Copy min / max
rcMappedMin[rcToFunctionMapping[chan]] = rcMin[chan];
rcMappedMax[rcToFunctionMapping[chan]] = rcMax[chan];
rcMappedNormalizedValue[rcToFunctionMapping[chan]] = normalized;
if (chan == rcMapping[0]) {
rcRoll = normalized;
}
else if (chan == rcMapping[1]) {
rcPitch = normalized;
}
else if (chan == rcMapping[2]) {
rcYaw = normalized;
}
else if (chan == rcMapping[3]) {
rcThrottle = normalized;
// if (rcRev[chan]) {
// rcThrottle = 1.0f + normalized;
// }
// else {
// rcThrottle = normalized;
// }
// rcThrottle = qBound(0.0f, rcThrottle, 1.0f);
}
else if (chan == rcMapping[4]) {
rcMode = normalized; // MODE SWITCH
}
else if (chan == rcMapping[5]) {
rcAssist = normalized; // ASSIST SWITCH
}
else if (chan == rcMapping[6]) {
rcLoiter = normalized; // LOITER SWITCH
}
else if (chan == rcMapping[7]) {
rcReturn = normalized; // RETURN SWITCH
}
else if (chan == rcMapping[8]) {
rcFlaps = normalized; // FLAPS
}
else if (chan == rcMapping[9]) {
rcAux1 = normalized; // AUX2
}
else if (chan == rcMapping[10]) {
rcAux2 = normalized; // AUX3
}
if (channelReverseStateWanted >= 0) {
// If the *right* channel moved considerably, evaluate it
if (fabsf(fval - 1500) > 350.0f &&
rcMapping[channelReverseStateWanted] == chan) {
// Check if the output is positive
if (fval > 1750) {
rcRev[rcMapping[channelReverseStateWanted]] = true;
} else {
rcRev[rcMapping[channelReverseStateWanted]] = false;
}
unsigned currRevFunc = channelReverseStateWanted;
channelReverseStateWanted = -1;
// Confirm found channel
msgBox.setText(tr("%1 direction assigned").arg(channelNames[currRevFunc]));
msgBox.setInformativeText(tr("%1").arg((rcRev[rcMapping[currRevFunc]]) ? tr("Reversed channel.") : tr("Did not reverse channel.") ));
msgBox.setStandardButtons(QMessageBox::Ok);
msgBox.setDefaultButton(QMessageBox::Ok);
skipActionButton->hide();
msgBox.removeButton(skipActionButton);
(void)msgBox.exec();
}
}
dataModelChanged = true;
//qDebug() << "RC CHAN:" << chan << "PPM:" << fval << "NORMALIZED:" << normalized;
}
void QGCPX4VehicleConfig::updateAllInvertedCheckboxes()
{
for (unsigned function_index = 0; function_index < chanMappedMax; function_index++) {
int rc_input_index = rcMapping[function_index];
if (rc_input_index < 0 || rc_input_index > (int)chanMax)
continue;
// Map index to checkbox.
// TODO(lm) Would be better to stick the checkboxes into a vector upfront
switch (function_index)
{
case 0:
ui->invertCheckBox->setChecked(rcRev[rc_input_index]);
ui->rollWidget->setName(tr("Roll (#%1)").arg(rcMapping[0] + 1));
break;
case 1:
ui->invertCheckBox_2->setChecked(rcRev[rc_input_index]);
ui->pitchWidget->setName(tr("Pitch (#%1)").arg(rcMapping[1] + 1));
break;
case 2:
ui->invertCheckBox_3->setChecked(rcRev[rc_input_index]);
ui->yawWidget->setName(tr("Yaw (#%1)").arg(rcMapping[2] + 1));
break;
case 3:
ui->invertCheckBox_4->setChecked(rcRev[rc_input_index]);
ui->throttleWidget->setName(tr("Throt. (#%1)").arg(rcMapping[3] + 1));
break;
case 4:
ui->invertCheckBox_5->setChecked(rcRev[rc_input_index]);
//ui->radio5Widget->setName(tr("Mode Switch (#%1)").arg(rcMapping[4] + 1));
break;
case 5:
ui->posctlSwInvertCheckBox->setChecked(rcRev[rc_input_index]);
break;
case 6:
ui->loiterSwInvertCheckBox->setChecked(rcRev[rc_input_index]);
break;
case 7:
ui->returnSwInvertCheckBox->setChecked(rcRev[rc_input_index]);
break;
case 8:
ui->flapsInvertCheckBox->setChecked(rcRev[rc_input_index]);
break;
case 9:
ui->aux1InvertCheckBox->setChecked(rcRev[rc_input_index]);
break;
case 10:
ui->aux2InvertCheckBox->setChecked(rcRev[rc_input_index]);
break;
}
}
}
void QGCPX4VehicleConfig::updateMappingView(int function_index)
{
Q_UNUSED(function_index);
updateAllInvertedCheckboxes();
QStringList assignments;
for (unsigned i = 0; i < chanMax; i++) {
assignments << "";
}
for (unsigned i = 0; i < chanMappedMax; i++) {
if (rcMapping[i] >= 0 && rcMapping[i] < (int)chanMax) {
assignments.replace(rcMapping[i], assignments[rcMapping[i]].append(QString(" / ").append(channelNames[i])));
}
}
for (unsigned i = 0; i < chanMax; i++) {
if (assignments[i] == "")
assignments[i] = "UNUSED";
}
for (unsigned i = 0; i < chanMax; i++) {
switch (i) {
case 4:
ui->radio5Widget->setName(tr("%1 (#5)").arg(assignments[4]));
break;
case 5:
ui->radio6Widget->setName(tr("%1 (#6)").arg(assignments[5]));
break;
case 6:
ui->radio7Widget->setName(tr("%1 (#7)").arg(assignments[6]));
break;
case 7:
ui->radio8Widget->setName(tr("%1 (#8)").arg(assignments[7]));
break;
case 8:
ui->radio9Widget->setName(tr("%1 (#9)").arg(assignments[8]));
break;
case 9:
ui->radio10Widget->setName(tr("%1 (#10)").arg(assignments[9]));
break;
case 10:
ui->radio11Widget->setName(tr("%1 (#11)").arg(assignments[10]));
break;
case 11:
ui->radio12Widget->setName(tr("%1 (#12)").arg(assignments[11]));
break;
case 12:
ui->radio13Widget->setName(tr("%1 (#13)").arg(assignments[12]));
break;
case 13:
ui->radio14Widget->setName(tr("%1 (#14)").arg(assignments[13]));
break;
case 14:
ui->radio15Widget->setName(tr("%1 (#15)").arg(assignments[14]));
break;
case 15:
ui->radio16Widget->setName(tr("%1 (#16)").arg(assignments[15]));
break;
case 16:
ui->radio17Widget->setName(tr("%1 (#17)").arg(assignments[16]));
break;
case 17:
ui->radio18Widget->setName(tr("%1 (#18)").arg(assignments[17]));
break;
}
}
}
void QGCPX4VehicleConfig::handleRcParameterChange(QString parameterName, QVariant value)
{
if (parameterName.startsWith("RC_")) {
if (parameterName.startsWith("RC_MAP_")) {
//RC Mapping radio channels to meaning
// Order is: roll, pitch, yaw, throttle, mode sw, aux 1-3
int intValue = value.toInt() - 1;
if (parameterName.startsWith("RC_MAP_ROLL")) {
setChannelToFunctionMapping(0, intValue);
ui->rollSpinBox->setValue(rcMapping[0]+1);
ui->rollSpinBox->setEnabled(true);
}
else if (parameterName.startsWith("RC_MAP_PITCH")) {
setChannelToFunctionMapping(1, intValue);
ui->pitchSpinBox->setValue(rcMapping[1]+1);
ui->pitchSpinBox->setEnabled(true);
}
else if (parameterName.startsWith("RC_MAP_YAW")) {
setChannelToFunctionMapping(2, intValue);
ui->yawSpinBox->setValue(rcMapping[2]+1);
ui->yawSpinBox->setEnabled(true);
}
else if (parameterName.startsWith("RC_MAP_THROTTLE")) {
setChannelToFunctionMapping(3, intValue);
ui->throttleSpinBox->setValue(rcMapping[3]+1);
ui->throttleSpinBox->setEnabled(true);
}
else if (parameterName.startsWith("RC_MAP_MODE_SW")) {
setChannelToFunctionMapping(4, intValue);
ui->modeSpinBox->setValue(rcMapping[4]+1);
ui->modeSpinBox->setEnabled(true);
}
else if (parameterName.startsWith("RC_MAP_POSCTL_SW")) {
setChannelToFunctionMapping(5, intValue);
ui->posctlSwSpinBox->setValue(rcMapping[5]+1);
ui->posctlSwSpinBox->setEnabled(true);
}
else if (parameterName.startsWith("RC_MAP_LOITER_SW")) {
setChannelToFunctionMapping(6, intValue);
ui->loiterSwSpinBox->setValue(rcMapping[6]+1);
ui->loiterSwSpinBox->setEnabled(true);
}
else if (parameterName.startsWith("RC_MAP_RETURN_SW")) {
setChannelToFunctionMapping(7, intValue);
ui->returnSwSpinBox->setValue(rcMapping[7]+1);
ui->returnSwSpinBox->setEnabled(true);
}
else if (parameterName.startsWith("RC_MAP_FLAPS")) {
setChannelToFunctionMapping(8, intValue);
ui->flapsSpinBox->setValue(rcMapping[8]+1);
ui->flapsSpinBox->setEnabled(true);
}
else if (parameterName.startsWith("RC_MAP_AUX1")) {
setChannelToFunctionMapping(9, intValue);
ui->aux1SpinBox->setValue(rcMapping[9]+1);
ui->aux1SpinBox->setEnabled(true);
}
else if (parameterName.startsWith("RC_MAP_AUX2")) {
setChannelToFunctionMapping(10, intValue);
ui->aux2SpinBox->setValue(rcMapping[10]+1);
ui->aux2SpinBox->setEnabled(true);
}
}
else if (parameterName.startsWith("RC_SCALE_")) {
// Scaling
float floatVal = value.toFloat();
if (parameterName.startsWith("RC_SCALE_ROLL")) {
rcScaling[0] = floatVal;
}
else if (parameterName.startsWith("RC_SCALE_PITCH")) {
rcScaling[1] = floatVal;
}
else if (parameterName.startsWith("RC_SCALE_YAW")) {
rcScaling[2] = floatVal;
}
// Not implemented at this point
// else if (parameterName.startsWith("RC_SCALE_THROTTLE")) {
// rcScaling[3] = floatVal;
// }
// else if (parameterName.startsWith("RC_SCALE_AUX1")) {
// rcScaling[5] = floatVal;
// }
// else if (parameterName.startsWith("RC_SCALE_AUX2")) {
// rcScaling[6] = floatVal;
// }
}
}
else {
// Channel calibration values
bool ok = false;
unsigned int index = chanMax;
QRegExp minTpl("RC?_MIN");
minTpl.setPatternSyntax(QRegExp::Wildcard);
QRegExp maxTpl("RC?_MAX");
maxTpl.setPatternSyntax(QRegExp::Wildcard);
QRegExp trimTpl("RC?_TRIM");
trimTpl.setPatternSyntax(QRegExp::Wildcard);
QRegExp revTpl("RC?_REV");
revTpl.setPatternSyntax(QRegExp::Wildcard);
// Do not write the RC type, as these values depend on this
// active onboard parameter
int intVal = value.toInt();
if (minTpl.exactMatch(parameterName)) {
index = parameterName.mid(2, 1).toInt(&ok) - 1;
if (ok && index < chanMax) {
rcMin[index] = intVal;
updateRcWidgetValues();
}
}
else if (maxTpl.exactMatch(parameterName)) {
index = parameterName.mid(2, 1).toInt(&ok) - 1;
if (ok && index < chanMax) {
rcMax[index] = intVal;
updateRcWidgetValues();
}
}
else if (trimTpl.exactMatch(parameterName)) {
index = parameterName.mid(2, 1).toInt(&ok) - 1;
if (ok && index < chanMax) {
rcTrim[index] = intVal;
}
}
else if (revTpl.exactMatch(parameterName)) {
index = parameterName.mid(2, 1).toInt(&ok) - 1;
if (ok && index < chanMax) {
rcRev[index] = (intVal == -1) ? true : false;
for (unsigned i = 0; i < chanMappedMax; i++)
{
if (rcMapping[i] == (int)index)
updateMappingView(i);
}
}
}
}
}
void QGCPX4VehicleConfig::setChannelToFunctionMapping(int function, int channel)
{
if (function >= 0 && function < (int)chanMappedMax)
rcMapping[function] = channel;
if (channel >= 0 && channel < (int)chanMax)
rcToFunctionMapping[channel] = function;
}
void QGCPX4VehicleConfig::parameterChanged(int uas, int component, QString parameterName, QVariant value)
......@@ -1853,12 +812,6 @@ void QGCPX4VehicleConfig::parameterChanged(int uas, int component, QString param
return;
}
//TODO this may introduce a bug with param editor widgets not receiving param updates
if (parameterName.startsWith("RC")) {
handleRcParameterChange(parameterName,value);
return;
}
if (paramToWidgetMap.contains(parameterName)) {
//Main group of parameters of the selected airframe
paramToWidgetMap.value(parameterName)->setParameterValue(uas,component,parameterName,value);
......@@ -1934,103 +887,3 @@ void QGCPX4VehicleConfig::updateError(const QString& str)
ui->advancedStatusLabel->setText(str);
ui->advancedStatusLabel->setStyleSheet(QString("QLabel { margin: 0px 2px; font: 14px; color: %1; background-color: %2; }").arg(QGC::colorDarkWhite.name()).arg(QGC::colorMagenta.name()));
}
void QGCPX4VehicleConfig::checktimeOuts()
{
}
void QGCPX4VehicleConfig::updateRcWidgetValues()
{
ui->rollWidget->setValueAndRange(rcMappedValueRev[0],rcMappedMin[0],rcMappedMax[0]);
ui->pitchWidget->setValueAndRange(rcMappedValueRev[1],rcMappedMin[1],rcMappedMax[1]);
ui->yawWidget->setValueAndRange(rcMappedValueRev[2],rcMappedMin[2],rcMappedMax[2]);
ui->throttleWidget->setValueAndRange(rcMappedValueRev[3],rcMappedMin[3],rcMappedMax[3]);
ui->radio5Widget->setValueAndRange(rcValueReversed[4],rcMin[4],rcMax[4]);
ui->radio6Widget->setValueAndRange(rcValueReversed[5],rcMin[5],rcMax[5]);
ui->radio7Widget->setValueAndRange(rcValueReversed[6],rcMin[6],rcMax[6]);
ui->radio8Widget->setValueAndRange(rcValueReversed[7],rcMin[7],rcMax[7]);
ui->radio9Widget->setValueAndRange(rcValueReversed[8],rcMin[8],rcMax[8]);
ui->radio10Widget->setValueAndRange(rcValueReversed[9],rcMin[9],rcMax[9]);
ui->radio11Widget->setValueAndRange(rcValueReversed[10],rcMin[10],rcMax[10]);
ui->radio12Widget->setValueAndRange(rcValueReversed[11],rcMin[11],rcMax[11]);
ui->radio13Widget->setValueAndRange(rcValueReversed[12],rcMin[12],rcMax[12]);
ui->radio14Widget->setValueAndRange(rcValueReversed[13],rcMin[13],rcMax[13]);
ui->radio15Widget->setValueAndRange(rcValueReversed[14],rcMin[14],rcMax[14]);
ui->radio16Widget->setValueAndRange(rcValueReversed[15],rcMin[15],rcMax[15]);
ui->radio17Widget->setValueAndRange(rcValueReversed[16],rcMin[16],rcMax[16]);
ui->radio18Widget->setValueAndRange(rcValueReversed[17],rcMin[17],rcMax[17]);
}
void QGCPX4VehicleConfig::updateRcChanLabels()
{
ui->rollChanLabel->setText(labelForRcValue(rcRoll));
ui->pitchChanLabel->setText(labelForRcValue(rcPitch));
ui->yawChanLabel->setText(labelForRcValue(rcYaw));
ui->throttleChanLabel->setText(labelForRcValue(rcThrottle));
QString blankLabel = tr("---");
if (rcValue[rcMapping[4]] != UINT16_MAX) {
ui->modeChanLabel->setText(labelForRcValue(rcMode));
}
else {
ui->modeChanLabel->setText(blankLabel);
}
if (rcValue[rcMapping[5]] != UINT16_MAX) {
ui->posctlSwChanLabel->setText(labelForRcValue(rcAssist));
}
else {
ui->posctlSwChanLabel->setText(blankLabel);
}
if (rcValue[rcMapping[6]] != UINT16_MAX) {
ui->loiterSwChanLabel->setText(labelForRcValue(rcLoiter));
}
else {
ui->loiterSwChanLabel->setText(blankLabel);
}
if (rcValue[rcMapping[7]] != UINT16_MAX) {
ui->returnSwChanLabel->setText(labelForRcValue(rcReturn));
}
else {
ui->returnSwChanLabel->setText(blankLabel);
}
if (rcValue[rcMapping[8]] != UINT16_MAX) {
ui->flapsChanLabel->setText(labelForRcValue(rcFlaps));
}
else {
ui->flapsChanLabel->setText(blankLabel);
}
if (rcValue[rcMapping[9]] != UINT16_MAX) {
ui->aux1ChanLabel->setText(labelForRcValue(rcAux1));
}
else {
ui->aux1ChanLabel->setText(blankLabel);
}
if (rcValue[rcMapping[10]] != UINT16_MAX) {
ui->aux2ChanLabel->setText(labelForRcValue(rcAux2));
}
else {
ui->aux2ChanLabel->setText(blankLabel);
}
}
void QGCPX4VehicleConfig::updateView()
{
if (dataModelChanged) {
dataModelChanged = false;
updateRcWidgetValues();
updateRcChanLabels();
if (chanCount > 0)
ui->rcLabel->setText(tr("Radio control detected with %1 channels.").arg(chanCount));
}
}
......@@ -16,6 +16,7 @@
class UASParameterCommsMgr;
class QGCPX4SensorCalibration;
class PX4RCCalibration;
namespace Ui {
class QGCPX4VehicleConfig;
......@@ -47,279 +48,27 @@ public slots:
void airframeMenuButtonClicked();
void firmwareMenuButtonClicked();
void identifyChannelMapping(int aert_index);
/** Set the MAV currently being calibrated */
void setActiveUAS(UASInterface* active);
/** Fallback function, automatically called by loadConfig() upon failure to find and xml file*/
void loadQgcConfig(bool primary);
/** Load configuration from xml file */
void loadConfig();
/** Start the RC calibration routine */
void startCalibrationRC();
/** Stop the RC calibration routine */
void stopCalibrationRC();
/** Start/stop the RC calibration routine */
void toggleCalibrationRC(bool enabled);
/** Start/stop the Spektrum pair routine */
void toggleSpektrumPairing(bool enabled);
/** Set the current trim values as attitude trim values */
void copyAttitudeTrim();
/** Set trim positions */
void setTrimPositions();
/** Detect which channels need to be inverted */
void detectChannelInversion(int aert_index);
/** Render the data updated */
void updateView();
void handleRcParameterChange(QString parameterName, QVariant value);
/** Set the RC channel */
void setRollChan(int channel) {
rcMapping[0] = channel - 1;
updateMappingView(0);
}
/** Set the RC channel */
void setPitchChan(int channel) {
rcMapping[1] = channel - 1;
updateMappingView(1);
}
/** Set the RC channel */
void setYawChan(int channel) {
rcMapping[2] = channel - 1;
updateMappingView(2);
}
/** Set the RC channel */
void setThrottleChan(int channel) {
rcMapping[3] = channel - 1;
updateMappingView(3);
}
/** Set the RC channel */
void setModeChan(int channel) {
rcMapping[4] = channel - 1;
updateMappingView(4);
}
/** Set the RC channel */
void setAssistChan(int channel) {
rcMapping[5] = channel - 1;
updateMappingView(5);
}
/** Set the RC channel */
void setMissionChan(int channel) {
rcMapping[6] = channel - 1;
updateMappingView(6);
}
/** Set the RC channel */
void setReturnChan(int channel) {
rcMapping[7] = channel - 1;
updateMappingView(7);
}
/** Set the RC channel */
void setFlapsChan(int channel) {
rcMapping[8] = channel - 1;
updateMappingView(8);
}
/** Set the RC channel */
void setAux1Chan(int channel) {
rcMapping[9] = channel - 1;
updateMappingView(9);
}
/** Set the RC channel */
void setAux2Chan(int channel) {
rcMapping[10] = channel - 1;
updateMappingView(10);
}
/** Set channel inversion status */
void setRollInverted(bool inverted) {
rcRev[rcMapping[0]] = inverted;
updateMappingView(0);
}
/** Set channel inversion status */
void setPitchInverted(bool inverted) {
rcRev[rcMapping[1]] = inverted;
updateMappingView(1);
}
/** Set channel inversion status */
void setYawInverted(bool inverted) {
rcRev[rcMapping[2]] = inverted;
updateMappingView(2);
}
/** Set channel inversion status */
void setThrottleInverted(bool inverted) {
rcRev[rcMapping[3]] = inverted;
updateMappingView(3);
}
/** Set channel inversion status */
void setModeInverted(bool inverted) {
rcRev[rcMapping[4]] = inverted;
updateMappingView(4);
}
/** Set channel inversion status */
void setAssistInverted(bool inverted) {
rcRev[rcMapping[5]] = inverted;
updateMappingView(5);
}
/** Set channel inversion status */
void setMissionInverted(bool inverted) {
rcRev[rcMapping[6]] = inverted;
updateMappingView(6);
}
/** Set channel inversion status */
void setReturnInverted(bool inverted) {
rcRev[rcMapping[7]] = inverted;
updateMappingView(7);
}
/** Set channel inversion status */
void setFlapsInverted(bool inverted) {
rcRev[rcMapping[8]] = inverted;
updateMappingView(8);
}
/** Set channel inversion status */
void setAux1Inverted(bool inverted) {
rcRev[rcMapping[9]] = inverted;
updateMappingView(9);
}
/** Set channel inversion status */
void setAux2Inverted(bool inverted) {
rcRev[rcMapping[10]] = inverted;
updateMappingView(10);
}
/** Identify roll */
void identifyRollChannel() {
identifyChannelMapping(0);
}
/** Identify pitch */
void identifyPitchChannel() {
identifyChannelMapping(1);
}
/** Identify yaw */
void identifyYawChannel() {
identifyChannelMapping(2);
}
/** Identify throttle */
void identifyThrottleChannel() {
identifyChannelMapping(3);
}
/** Identify mode */
void identifyModeChannel() {
identifyChannelMapping(4);
}
/** Identify assist channel */
void identifyAssistChannel() {
identifyChannelMapping(5);
}
/** Identify mission channel */
void identifyMissionChannel() {
identifyChannelMapping(6);
}
/** Identify return channel */
void identifyReturnChannel() {
identifyChannelMapping(7);
}
/** Identify flaps channel */
void identifyFlapsChannel() {
identifyChannelMapping(8);
}
/** Identify aux 1 */
void identifyAux1Channel() {
identifyChannelMapping(9);
}
/** Identify aux 2 */
void identifyAux2Channel() {
identifyChannelMapping(10);
}
protected slots:
void menuButtonClicked();
/** Reset the RC calibration */
void resetCalibrationRC();
/** Write the RC calibration */
void writeCalibrationRC();
/** Request the RC calibration */
void requestCalibrationRC();
/** Store all parameters in onboard EEPROM */
void writeParameters();
/** Receive remote control updates from MAV */
void remoteControlChannelRawChanged(int chan, float val);
/** Parameter changed onboard */
void parameterChanged(int uas, int component, QString parameterName, QVariant value);
void updateStatus(const QString& str);
void updateError(const QString& str);
/** Check timeouts */
void checktimeOuts();
/** Update checkbox status */
void updateAllInvertedCheckboxes();
/** Update mapping view state */
void updateMappingView(int index);
/** Update the displayed values */
void updateRcWidgetValues();
/** update the channel labels */
void updateRcChanLabels();
QString labelForRcValue(float val) {
return QString("%1").arg(val, 5, 'f', 2, QChar(' '));
}
protected:
void setChannelToFunctionMapping(int function, int channel);
bool doneLoadingConfig;
UASInterface* mav; ///< The current MAV
QGCUASParamManagerInterface* paramMgr; ///< params mgr for the mav
static const unsigned int chanMax = 18; ///< Maximum number of channels
static const unsigned int chanMappedMax = 18; ///< Maximum number of mapped channels (can be higher than input channel count)
unsigned int chanCount; ///< Actual channels
float rcMin[chanMax]; ///< Minimum values
float rcMax[chanMax]; ///< Maximum values
float rcTrim[chanMax]; ///< Zero-position (center for roll/pitch/yaw, 0 throttle for throttle)
int rcMapping[chanMappedMax]; ///< PWM to function mappings
int rcToFunctionMapping[chanMax];
float rcScaling[chanMax]; ///< Scaling of channel input to control commands
bool rcRev[chanMax]; ///< Channel reverse
int rcValue[chanMax]; ///< Last values, RAW
int rcValueReversed[chanMax]; ///< Last values, accounted for reverse
int rcMappedMin[chanMappedMax]; ///< Mapped channels in default order
int rcMappedMax[chanMappedMax]; ///< Mapped channels in default order
int rcMappedValue[chanMappedMax]; ///< Mapped channels in default order
int rcMappedValueRev[chanMappedMax];
float rcMappedNormalizedValue[chanMappedMax]; ///< Mapped channels in default order
int channelWanted; ///< During channel assignment search the requested default index
int channelReverseStateWanted;
float channelWantedList[chanMax]; ///< During channel assignment search the start values
float channelReverseStateWantedList[chanMax];
QStringList channelNames; ///< List of channel names in standard order
float rcRoll; ///< PPM input channel used as roll control input
float rcPitch; ///< PPM input channel used as pitch control input
float rcYaw; ///< PPM input channel used as yaw control input
float rcThrottle; ///< PPM input channel used as throttle control input
float rcMode; ///< PPM input channel used as mode switch control input
float rcAssist; ///< PPM input channel used as assist switch control input
float rcLoiter; ///< PPM input channel used as loiter switch control input
float rcReturn; ///< PPM input channel used as return switch control input
float rcFlaps; ///< PPM input channel used as flaps control input
float rcAux1; ///< PPM input channel used as aux 1 input
float rcAux2; ///< PPM input channel used as aux 2 input
bool rcCalChanged; ///< Set if the calibration changes (and needs to be written)
bool dataModelChanged; ///< Set if any of the input data changed
QTimer updateTimer; ///< Controls update intervals
QList<QGCToolWidget*> toolWidgets; ///< Configurable widgets
QMap<QString,QGCToolWidget*> toolWidgetsByName; ///<
bool calibrationEnabled; ///< calibration mode on / off
bool configEnabled; ///< config mode on / off
QMap<QString,QGCToolWidget*> paramToWidgetMap; ///< Holds the current active MAV's parameter widgets.
QList<QWidget*> additionalTabs; ///< Stores additional tabs loaded for this vehicle/autopilot configuration. Used for cleaning up.
......@@ -332,6 +81,7 @@ protected:
QPixmap planeBack;
QPixmap planeSide;
QGCPX4SensorCalibration* px4SensorCalibration;
PX4RCCalibration* px4RCCalibration;
QMessageBox msgBox;
QGraphicsScene scene;
QPushButton* skipActionButton;
......
......@@ -51,929 +51,20 @@
<item>
<widget class="QStackedWidget" name="stackedWidget">
<property name="currentIndex">
<number>4</number>
<number>1</number>
</property>
<widget class="QWidget" name="firmwareTab">
<layout class="QVBoxLayout" name="firmwareLayout"/>
</widget>
<widget class="QWidget" name="rcTab">
<layout class="QGridLayout" name="gridLayout_4">
<item row="4" column="0">
<widget class="QGroupBox" name="advancedGroupBox">
<property name="title">
<string>Stick to Channel Mapping and Reverse</string>
<property name="font">
<font>
<pointsize>16</pointsize>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<layout class="QVBoxLayout" name="verticalLayout_16">
<item>
<layout class="QGridLayout" name="gridLayout_2">
<item row="6" column="0">
<widget class="QLabel" name="posctlSwChanName">
<property name="text">
<string>Posctl Switch</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QLabel" name="yawChanLabel">
<property name="text">
<string>0000</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item row="5" column="2">
<widget class="QCheckBox" name="invertCheckBox_5">
<property name="text">
<string>Reverse</string>
</property>
</widget>
</item>
<item row="5" column="3">
<widget class="QSpinBox" name="modeSpinBox">
<property name="enabled">
<bool>false</bool>
</property>
<property name="minimum">
<number>0</number>
</property>
<property name="maximum">
<number>16</number>
</property>
</widget>
</item>
<item row="10" column="4">
<widget class="QPushButton" name="aux1Button">
<property name="text">
<string>Identify Aux 1 Channel</string>
</property>
</widget>
</item>
<item row="0" column="3" colspan="2">
<widget class="QLabel" name="label_4">
<property name="text">
<string>Mapping to Index of RC Channel used for (0 if not used)</string>
</property>
</widget>
</item>
<item row="8" column="0">
<widget class="QLabel" name="returnChanName">
<property name="text">
<string>Return Switch</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="8" column="1">
<widget class="QLabel" name="returnSwChanLabel">
<property name="text">
<string>0000</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item row="10" column="0">
<widget class="QLabel" name="aux1ChanName">
<property name="text">
<string>Aux 1</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="5" column="4">
<widget class="QPushButton" name="modeButton">
<property name="text">
<string>Identify Mode Switch</string>
</property>
</widget>
</item>
<item row="3" column="4">
<widget class="QPushButton" name="yawButton">
<property name="text">
<string>Identify Yaw Channel</string>
</property>
</widget>
</item>
<item row="4" column="3">
<widget class="QSpinBox" name="throttleSpinBox">
<property name="enabled">
<bool>false</bool>
</property>
<property name="minimum">
<number>0</number>
</property>
<property name="maximum">
<number>16</number>
</property>
</widget>
</item>
<item row="10" column="1">
<widget class="QLabel" name="aux1ChanLabel">
<property name="text">
<string>0000</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="pitchChanName">
<property name="text">
<string>Pitch / Elevator</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Reverse / Invert</string>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="yawChanName">
<property name="text">
<string>Yaw / Rudder</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="1" column="3">
<widget class="QSpinBox" name="rollSpinBox">
<property name="enabled">
<bool>false</bool>
</property>
<property name="minimum">
<number>0</number>
</property>
<property name="maximum">
<number>16</number>
</property>
</widget>
</item>
<item row="4" column="2">
<widget class="QCheckBox" name="invertCheckBox_4">
<property name="text">
<string>Reverse</string>
</property>
</widget>
</item>
<item row="5" column="1">
<widget class="QLabel" name="modeChanLabel">
<property name="text">
<string>0000</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item row="11" column="1">
<widget class="QLabel" name="aux2ChanLabel">
<property name="text">
<string>0000</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item row="11" column="3">
<widget class="QSpinBox" name="aux2SpinBox">
<property name="enabled">
<bool>false</bool>
</property>
<property name="minimum">
<number>0</number>
</property>
<property name="maximum">
<number>16</number>
</property>
</widget>
</item>
<item row="10" column="3">
<widget class="QSpinBox" name="aux1SpinBox">
<property name="enabled">
<bool>false</bool>
</property>
<property name="minimum">
<number>0</number>
</property>
<property name="maximum">
<number>16</number>
</property>
</widget>
</item>
<item row="11" column="2">
<widget class="QCheckBox" name="aux2InvertCheckBox">
<property name="text">
<string>Reverse</string>
</property>
</widget>
</item>
<item row="7" column="1">
<widget class="QLabel" name="loiterSwChanLabel">
<property name="text">
<string>0000</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item row="5" column="0">
<widget class="QLabel" name="modeSwChanName">
<property name="text">
<string>Mode Switch</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="11" column="4">
<widget class="QPushButton" name="aux2Button">
<property name="text">
<string>Identify Aux 2 Channel</string>
</property>
</widget>
</item>
<item row="2" column="3">
<widget class="QSpinBox" name="pitchSpinBox">
<property name="enabled">
<bool>false</bool>
</property>
<property name="minimum">
<number>0</number>
</property>
<property name="maximum">
<number>16</number>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="rollChanName">
<property name="text">
<string>Roll / Ailerons</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="4" column="4">
<widget class="QPushButton" name="throttleButton">
<property name="text">
<string>Identify Throttle Channel</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Channel Name</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="6" column="2">
<widget class="QCheckBox" name="posctlSwInvertCheckBox">
<property name="text">
<string>Reverse</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLabel" name="rollChanLabel">
<property name="text">
<string>0000</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item row="6" column="4">
<widget class="QPushButton" name="posctlSwButton">
<property name="text">
<string>Identify Posctl Switch</string>
</property>
</widget>
</item>
<item row="11" column="0">
<widget class="QLabel" name="aux2ChanName">
<property name="text">
<string>Aux 2</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="QCheckBox" name="invertCheckBox">
<property name="text">
<string>Reverse</string>
</property>
</widget>
</item>
<item row="6" column="3">
<widget class="QSpinBox" name="posctlSwSpinBox">
<property name="enabled">
<bool>false</bool>
</property>
<property name="minimum">
<number>0</number>
</property>
<property name="maximum">
<number>16</number>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QLabel" name="pitchChanLabel">
<property name="text">
<string>0000</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item row="3" column="2">
<widget class="QCheckBox" name="invertCheckBox_3">
<property name="text">
<string>Reverse</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Normalized Value</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item row="2" column="2">
<widget class="QCheckBox" name="invertCheckBox_2">
<property name="text">
<string>Reverse</string>
</property>
</widget>
</item>
<item row="2" column="4">
<widget class="QPushButton" name="pitchButton">
<property name="text">
<string>Identify Pitch Channel</string>
</property>
</widget>
</item>
<item row="10" column="2">
<widget class="QCheckBox" name="aux1InvertCheckBox">
<property name="text">
<string>Reverse</string>
</property>
</widget>
</item>
<item row="6" column="1">
<widget class="QLabel" name="posctlSwChanLabel">
<property name="text">
<string>0000</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item row="3" column="3">
<widget class="QSpinBox" name="yawSpinBox">
<property name="enabled">
<bool>false</bool>
</property>
<property name="minimum">
<number>0</number>
</property>
<property name="maximum">
<number>16</number>
</property>
</widget>
</item>
<item row="1" column="4">
<widget class="QPushButton" name="rollButton">
<property name="text">
<string>Identify Roll Channel</string>
</property>
</widget>
</item>
<item row="7" column="0">
<widget class="QLabel" name="loiterSwChanName">
<property name="text">
<string>Loiter Switch</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QLabel" name="throttleChanLabel">
<property name="text">
<string>0000</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QLabel" name="throttleChanName">
<property name="text">
<string>Throttle</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="9" column="0">
<widget class="QLabel" name="flapsChanName">
<property name="text">
<string>Flaps</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="9" column="1">
<widget class="QLabel" name="flapsChanLabel">
<property name="text">
<string>0000</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item row="7" column="2">
<widget class="QCheckBox" name="loiterSwInvertCheckBox">
<property name="text">
<string>Reverse</string>
</property>
</widget>
</item>
<item row="8" column="2">
<widget class="QCheckBox" name="returnSwInvertCheckBox">
<property name="text">
<string>Reverse</string>
</property>
</widget>
</item>
<item row="9" column="2">
<widget class="QCheckBox" name="flapsInvertCheckBox">
<property name="text">
<string>Reverse</string>
</property>
</widget>
</item>
<item row="7" column="3">
<widget class="QSpinBox" name="loiterSwSpinBox">
<property name="enabled">
<bool>false</bool>
</property>
</widget>
</item>
<item row="8" column="3">
<widget class="QSpinBox" name="returnSwSpinBox">
<property name="enabled">
<bool>false</bool>
</property>
</widget>
</item>
<item row="9" column="3">
<widget class="QSpinBox" name="flapsSpinBox">
<property name="enabled">
<bool>false</bool>
</property>
<property name="cursor">
<cursorShape>ArrowCursor</cursorShape>
</property>
</widget>
</item>
<item row="7" column="4">
<widget class="QPushButton" name="loiterSwButton">
<property name="text">
<string>Identify Loiter Switch</string>
</property>
</widget>
</item>
<item row="8" column="4">
<widget class="QPushButton" name="returnSwButton">
<property name="text">
<string>Identify Return Switch</string>
</property>
</widget>
</item>
<item row="9" column="4">
<widget class="QPushButton" name="flapsButton">
<property name="text">
<string>Identify Flaps Channel</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QPushButton" name="persistRcValuesButt">
<property name="text">
<string>Persist RC Mapping and Calibration</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="5" column="0">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item row="0" column="0">
<layout class="QGridLayout" name="gridLayout" rowstretch="0,0" columnstretch="0,0,0">
<item row="0" column="1">
<widget class="QGCRadioChannelDisplay" name="throttleWidget" native="true">
<property name="minimumSize">
<size>
<width>50</width>
<height>200</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>50</width>
<height>200</height>
</size>
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="QGCRadioChannelDisplay" name="rollWidget" native="true">
<property name="minimumSize">
<size>
<width>250</width>
<height>40</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>250</width>
<height>40</height>
</size>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QGCRadioChannelDisplay" name="pitchWidget" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>1</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>50</width>
<height>200</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>50</width>
<height>200</height>
</size>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QGCRadioChannelDisplay" name="yawWidget" native="true">
<property name="minimumSize">
<size>
<width>250</width>
<height>40</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>250</width>
<height>40</height>
</size>
</property>
</widget>
</item>
<item row="0" column="0">
<layout class="QVBoxLayout" name="verticalLayout_9">
<item>
<widget class="QPushButton" name="rcCalibrationButton">
<property name="text">
<string>Start Calibration</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="rcCopyTrimButton">
<property name="toolTip">
<string>Copy the trim values from roll / pitch / yaw from manual flight to the autonomous flight modes.</string>
</property>
<property name="text">
<string>Copy Attitude Trims</string>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer_3">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QGroupBox" name="groupBox">
<property name="title">
<string>Spektrum RC</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_10">
<item>
<widget class="QPushButton" name="spektrumPairButton">
<property name="text">
<string>Pair Receiver</string>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="dsm2RadioButton">
<property name="text">
<string>DSM2 Mode</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="dsmxRadioButton">
<property name="text">
<string>DSMX Mode (3 to 7 channels)</string>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="dsmx8RadioButton">
<property name="text">
<string>DSMX Mode (8 or more channels)</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</item>
</layout>
</item>
<item row="2" column="0">
<widget class="QCheckBox" name="advancedCheckBox">
<property name="text">
<string>Show Advanced Configuration Options</string>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QGraphicsView" name="graphicsView"/>
</item>
<item row="1" column="0">
<widget class="QLabel" name="rcLabel">
<property name="text">
<string>Waiting for RC channel data..</string>
</property>
</widget>
</item>
<item row="0" column="1" rowspan="5">
<layout class="QVBoxLayout" name="verticalLayout_6">
<item>
<widget class="QGCRadioChannelDisplay" name="radio5Widget" native="true">
<property name="minimumSize">
<size>
<width>250</width>
<height>40</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>250</width>
<height>40</height>
</size>
</property>
</widget>
</item>
<item>
<widget class="QGCRadioChannelDisplay" name="radio6Widget" native="true">
<property name="minimumSize">
<size>
<width>250</width>
<height>40</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>250</width>
<height>40</height>
</size>
</property>
</widget>
</item>
<item>
<widget class="QGCRadioChannelDisplay" name="radio7Widget" native="true">
<property name="minimumSize">
<size>
<width>250</width>
<height>40</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>250</width>
<height>40</height>
</size>
</property>
</widget>
</item>
<item>
<widget class="QGCRadioChannelDisplay" name="radio8Widget" native="true">
<property name="minimumSize">
<size>
<width>250</width>
<height>40</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>250</width>
<height>40</height>
</size>
</property>
</widget>
</item>
<item>
<widget class="QGCRadioChannelDisplay" name="radio9Widget" native="true">
<property name="minimumSize">
<size>
<width>250</width>
<height>40</height>
</size>
</property>
</widget>
</item>
<item>
<widget class="QGCRadioChannelDisplay" name="radio10Widget" native="true">
<property name="minimumSize">
<size>
<width>250</width>
<height>40</height>
</size>
</property>
</widget>
</item>
<item>
<widget class="QGCRadioChannelDisplay" name="radio11Widget" native="true">
<property name="minimumSize">
<size>
<width>250</width>
<height>40</height>
</size>
</property>
</widget>
</item>
<item>
<widget class="QGCRadioChannelDisplay" name="radio12Widget" native="true">
<property name="minimumSize">
<size>
<width>250</width>
<height>40</height>
</size>
</property>
</widget>
</item>
<item>
<widget class="QGCRadioChannelDisplay" name="radio13Widget" native="true">
<property name="minimumSize">
<size>
<width>250</width>
<height>40</height>
</size>
</property>
</widget>
</item>
<item>
<widget class="QGCRadioChannelDisplay" name="radio14Widget" native="true">
<property name="minimumSize">
<size>
<width>250</width>
<height>40</height>
</size>
</property>
</widget>
</item>
<item>
<widget class="QGCRadioChannelDisplay" name="radio15Widget" native="true">
<property name="minimumSize">
<size>
<width>250</width>
<height>40</height>
</size>
</property>
</widget>
</item>
<item>
<widget class="QGCRadioChannelDisplay" name="radio16Widget" native="true">
<property name="minimumSize">
<size>
<width>250</width>
<height>40</height>
</size>
</property>
</widget>
</item>
<item>
<widget class="QGCRadioChannelDisplay" name="radio17Widget" native="true">
<property name="minimumSize">
<size>
<width>250</width>
<height>40</height>
</size>
</property>
</widget>
</item>
<item>
<widget class="QGCRadioChannelDisplay" name="radio18Widget" native="true">
<property name="minimumSize">
<size>
<width>250</width>
<height>40</height>
</size>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer_4">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
</layout>
<layout class="QHBoxLayout" name="rcLayout"/>
</widget>
<widget class="QWidget" name="sensorTab">
<property name="font">
......@@ -1151,8 +242,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>600</width>
<height>1017</height>
<width>98</width>
<height>28</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout_7">
......@@ -1513,12 +604,6 @@ Config</string>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>QGCRadioChannelDisplay</class>
<extends>QWidget</extends>
<header>ui/designer/QGCRadioChannelDisplay.h</header>
<container>1</container>
</customwidget>
<customwidget>
<class>QGCPendingParamWidget</class>
<extends>QWidget</extends>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment