diff --git a/ground/openpilotgcs/src/plugins/config/configgadgetwidget.cpp b/ground/openpilotgcs/src/plugins/config/configgadgetwidget.cpp index a8509d091..4eca15bf9 100644 --- a/ground/openpilotgcs/src/plugins/config/configgadgetwidget.cpp +++ b/ground/openpilotgcs/src/plugins/config/configgadgetwidget.cpp @@ -169,6 +169,7 @@ void ConfigGadgetWidget::onAutopilotConnect() { void ConfigGadgetWidget::tabAboutToChange(int i,bool * proceed) { + Q_UNUSED(i); *proceed=true; ConfigTaskWidget * wid=qobject_cast(ftw->currentWidget()); if(!wid) diff --git a/ground/openpilotgcs/src/plugins/config/configinputwidget.cpp b/ground/openpilotgcs/src/plugins/config/configinputwidget.cpp index 038c411ed..6982ef91d 100644 --- a/ground/openpilotgcs/src/plugins/config/configinputwidget.cpp +++ b/ground/openpilotgcs/src/plugins/config/configinputwidget.cpp @@ -46,9 +46,7 @@ #define STICK_MIN_MOVE -8 #define STICK_MAX_MOVE 8 -QList inputList; - -ConfigInputWidget::ConfigInputWidget(QWidget *parent) : ConfigTaskWidget(parent),wizardStep(wizardWelcome),loop(NULL),skipflag(false),transmitterType(heli) +ConfigInputWidget::ConfigInputWidget(QWidget *parent) : ConfigTaskWidget(parent),wizardStep(wizardNone),loop(NULL),skipflag(false),transmitterType(heli) { manualCommandObj = ManualControlCommand::GetInstance(getObjectManager()); manualSettingsObj = ManualControlSettings::GetInstance(getObjectManager()); @@ -58,9 +56,7 @@ ConfigInputWidget::ConfigInputWidget(QWidget *parent) : ConfigTaskWidget(parent) setupButtons(m_config->saveRCInputToRAM,m_config->saveRCInputToSD); - inputList.clear(); - - int index=0; + unsigned int index=0; foreach(QString name,manualSettingsObj->getFields().at(0)->getElementNames()) { Q_ASSERT(index < ManualControlSettings::CHANNELGROUPS_NUMELEM); @@ -72,11 +68,10 @@ ConfigInputWidget::ConfigInputWidget(QWidget *parent) : ConfigTaskWidget(parent) addUAVObjectToWidgetRelation("ManualControlSettings","ChannelMin",inp->ui->channelMin,index); addUAVObjectToWidgetRelation("ManualControlSettings","ChannelNeutral",inp->ui->channelNeutral,index); addUAVObjectToWidgetRelation("ManualControlSettings","ChannelMax",inp->ui->channelMax,index); - inputList.append(inp); ++index; } - connect(m_config->configurationWizard,SIGNAL(clicked()),this,SLOT(goToNormalWizard())); + connect(m_config->configurationWizard,SIGNAL(clicked()),this,SLOT(goToWizard())); connect(m_config->runCalibration,SIGNAL(toggled(bool)),this, SLOT(simpleCalibration(bool))); connect(m_config->wzNext,SIGNAL(clicked()),this,SLOT(wzNext())); @@ -228,6 +223,25 @@ ConfigInputWidget::ConfigInputWidget(QWidget *parent) : ConfigTaskWidget(parent) m_config->graphicsView->fitInView(m_txMainBody, Qt::KeepAspectRatio ); animate=new QTimer(this); connect(animate,SIGNAL(timeout()),this,SLOT(moveTxControls())); + + heliChannelOrder << ManualControlSettings::CHANNELGROUPS_COLLECTIVE << + ManualControlSettings::CHANNELGROUPS_THROTTLE << + ManualControlSettings::CHANNELGROUPS_ROLL << + ManualControlSettings::CHANNELGROUPS_PITCH << + ManualControlSettings::CHANNELGROUPS_YAW << + ManualControlSettings::CHANNELGROUPS_FLIGHTMODE << + ManualControlSettings::CHANNELGROUPS_ACCESSORY0 << + ManualControlSettings::CHANNELGROUPS_ACCESSORY1 << + ManualControlSettings::CHANNELGROUPS_ACCESSORY2; + + acroChannelOrder << ManualControlSettings::CHANNELGROUPS_THROTTLE << + ManualControlSettings::CHANNELGROUPS_ROLL << + ManualControlSettings::CHANNELGROUPS_PITCH << + ManualControlSettings::CHANNELGROUPS_YAW << + ManualControlSettings::CHANNELGROUPS_FLIGHTMODE << + ManualControlSettings::CHANNELGROUPS_ACCESSORY0 << + ManualControlSettings::CHANNELGROUPS_ACCESSORY1 << + ManualControlSettings::CHANNELGROUPS_ACCESSORY2; } void ConfigInputWidget::resetTxControls() { @@ -258,16 +272,6 @@ void ConfigInputWidget::openHelp() QDesktopServices::openUrl( QUrl("http://wiki.openpilot.org/display/Doc/Input+Configuration", QUrl::StrictMode) ); } -void ConfigInputWidget::goToSimpleWizard() -{ - isSimple=true; - goToWizard(); -} -void ConfigInputWidget::goToNormalWizard() -{ - isSimple=false; - goToWizard(); -} void ConfigInputWidget::goToWizard() { QMessageBox msgBox; @@ -276,7 +280,7 @@ void ConfigInputWidget::goToWizard() msgBox.setStandardButtons(QMessageBox::Ok); msgBox.setDefaultButton(QMessageBox::Ok); msgBox.exec(); - setupWizardWidget(wizardWelcome); + wizardSetUpStep(wizardWelcome); m_config->graphicsView->fitInView(m_txBackground, Qt::KeepAspectRatio ); } @@ -285,250 +289,51 @@ void ConfigInputWidget::wzCancel() dimOtherControls(false); manualCommandObj->setMetadata(manualCommandObj->getDefaultMetadata()); m_config->stackedWidget->setCurrentIndex(0); - foreach (QWidget * wd, extraWidgets) - { - if(wd) - delete wd; - } - extraWidgets.clear(); - switch(wizardStep) - { - case wizardWelcome: - break; - case wizardChooseMode: - case wizardChooseType: - break; - case wizardIdentifySticks: - disconnect(receiverActivityObj, SIGNAL(objectUpdated(UAVObject*)), this, SLOT(identifyControls())); - break; - case wizardIdentifyCenter: - break; - case wizardIdentifyLimits: - disconnect(manualCommandObj, SIGNAL(objectUpdated(UAVObject*)), this, SLOT(identifyLimits())); - manualSettingsObj->setData(manualSettingsData); - break; - case wizardIdentifyInverted: - break; - case wizardFinish: - break; - default: - break; - } - wizardStep=wizardWelcome; + + if(wizardStep != wizardNone) + wizardTearDownStep(wizardStep); + wizardStep=wizardNone; + + // Load settings back from beginning of wizard + manualSettingsObj->setData(previousManualSettingsData); } void ConfigInputWidget::wzNext() { - setupWizardWidget(wizardStep+1); -} + // In identify sticks mode the next button can indicate + // channel advance + if(wizardStep != wizardNone && + wizardStep != wizardIdentifySticks) + wizardTearDownStep(wizardStep); -void ConfigInputWidget::wzBack() -{ - if(wizardStep == wizardIdentifySticks && currentCommand != 0) { - currentCommand --; - usedChannels.removeLast(); - getChannelFromStep(currentCommand); - } else - setupWizardWidget(wizardStep-1); -} - -void ConfigInputWidget::setupWizardWidget(int step) -{ - if(step==wizardWelcome) - { - m_config->graphicsView->setVisible(false); - setTxMovement(nothing); - if(wizardStep==wizardChooseMode) - { - delete extraWidgets.at(0); - delete extraWidgets.at(1); - extraWidgets.clear(); + // State transitions for next button + switch(wizardStep) { + case wizardWelcome: + wizardSetUpStep(wizardChooseMode); + break; + case wizardChooseMode: + wizardSetUpStep(wizardChooseType); + break; + case wizardChooseType: + wizardSetUpStep(wizardIdentifySticks); + break; + case wizardIdentifySticks: + nextChannel(); + if(currentChannelNum==-1) { // Gone through all channels + wizardTearDownStep(wizardIdentifySticks); + wizardSetUpStep(wizardIdentifyCenter); } - manualSettingsData=manualSettingsObj->getData(); - manualSettingsData.Arming=ManualControlSettings::ARMING_ALWAYSDISARMED; - manualSettingsObj->setData(manualSettingsData); - m_config->wzText->setText(tr("Welcome to the inputs configuration wizard.\n" - "Please follow the instructions on the screen and only move your controls when asked to.\n" - "Make sure you already configured your hardware settings on the proper tab and restarted your board.\n" - "At any time you can press 'back' to return to the previous screeen or 'Cancel' to cancel the wizard.\n")); - m_config->stackedWidget->setCurrentIndex(1); - m_config->wzBack->setEnabled(false); - wizardStep=wizardWelcome; - } - else if(step==wizardChooseMode) - { - m_config->graphicsView->setVisible(true); - setTxMovement(nothing); - if(wizardStep==wizardIdentifySticks) - { - disconnect(receiverActivityObj, SIGNAL(objectUpdated(UAVObject*)), this, SLOT(identifyControls())); - m_config->wzNext->setEnabled(true); - } - m_config->wzText->setText(tr("Please choose your transmiter type.\n" - "Mode 1 means your throttle stick is on the right\n" - "Mode 2 means your throttle stick is on the left\n")); - m_config->wzBack->setEnabled(true); - QRadioButton * mode1=new QRadioButton(tr("Mode 1"),this); - QRadioButton * mode2=new QRadioButton(tr("Mode 2"),this); - mode2->setChecked(true); - extraWidgets.clear(); - extraWidgets.append(mode1); - extraWidgets.append(mode2); - m_config->checkBoxesLayout->layout()->addWidget(mode1); - m_config->checkBoxesLayout->layout()->addWidget(mode2); - wizardStep=wizardChooseMode; - } - else if(step==wizardChooseType) - { - if(wizardStep==wizardChooseMode) - { - QRadioButton * mode=qobject_cast(extraWidgets.at(0)); - if(mode->isChecked()) - transmitterMode=mode1; - else - transmitterMode=mode2; - delete extraWidgets.at(0); - delete extraWidgets.at(1); - extraWidgets.clear(); - } - - m_config->wzText->setText(tr("Please choose your transmiter mode.\n" - "Acro means normal transmitter\n" - "Heli means there is a collective pitch and throttle input\n")); - m_config->wzBack->setEnabled(true); - QRadioButton * typeAcro=new QRadioButton(tr("Acro"),this); - QRadioButton * typeHeli=new QRadioButton(tr("Heli"),this); - typeAcro->setChecked(true); - typeHeli->setChecked(false); - extraWidgets.clear(); - extraWidgets.append(typeAcro); - extraWidgets.append(typeHeli); - m_config->checkBoxesLayout->layout()->addWidget(typeAcro); - m_config->checkBoxesLayout->layout()->addWidget(typeHeli); - wizardStep=wizardChooseType; - } else if(step==wizardIdentifySticks && !isSimple) { - usedChannels.clear(); - if(wizardStep==wizardChooseType) - { - qDebug() << "Chosing type"; - QRadioButton * type=qobject_cast(extraWidgets.at(0)); - if(type->isChecked()) - transmitterType=acro; - else - transmitterType=heli; - qDebug() << "Checked: " << type->isChecked() << " " << "type is" << transmitterType; - delete extraWidgets.at(0); - delete extraWidgets.at(1); - extraWidgets.clear(); - } - wizardStep=wizardIdentifySticks; - currentCommand=0; - getChannelFromStep(currentCommand); - manualSettingsData=manualSettingsObj->getData(); - connect(receiverActivityObj, SIGNAL(objectUpdated(UAVObject*)), this, SLOT(identifyControls())); - m_config->wzNext->setEnabled(false); - } - else if(step==wizardIdentifyCenter || (isSimple && step==wizardIdentifySticks)) - { - setTxMovement(centerAll); - if(wizardStep==wizardIdentifySticks) - disconnect(receiverActivityObj, SIGNAL(objectUpdated(UAVObject*)), this, SLOT(identifyControls())); - else - { - disconnect(manualCommandObj, SIGNAL(objectUpdated(UAVObject*)), this, SLOT(identifyLimits())); - manualSettingsObj->setData(manualSettingsData); - manualCommandObj->setMetadata(manualCommandObj->getDefaultMetadata()); - } - wizardStep=wizardIdentifyCenter; - m_config->wzText->setText(QString(tr("Please center all control controls and press next when ready (if your FlightMode switch has only two positions, leave it on either position)"))); - } - else if(step==wizardIdentifyLimits) - { - dimOtherControls(false); - setTxMovement(moveAll); - if(wizardStep==wizardIdentifyCenter) - { - wizardStep=wizardIdentifyLimits; - manualCommandData=manualCommandObj->getData(); - manualSettingsData=manualSettingsObj->getData(); - for(unsigned int i=0;isetData(manualSettingsData); - } - if(wizardStep==wizardIdentifyInverted) - { - foreach(QWidget * wd,extraWidgets) - { - QCheckBox * cb=qobject_cast(wd); - if(cb) - { - disconnect(cb,SIGNAL(toggled(bool)),this,SLOT(invertControls())); - delete cb; - } - } - } - extraWidgets.clear(); - disconnect(manualCommandObj, SIGNAL(objectUpdated(UAVObject*)), this, SLOT(moveSticks())); - wizardStep=wizardIdentifyLimits; - m_config->wzText->setText(QString(tr("Please move all controls to their maximum extents on both directions and press next when ready"))); - UAVObject::Metadata mdata= manualCommandObj->getMetadata(); - mdata.flightTelemetryUpdateMode = UAVObject::UPDATEMODE_PERIODIC; - mdata.flightTelemetryUpdatePeriod = 150; - manualCommandObj->setMetadata(mdata); - manualSettingsData=manualSettingsObj->getData(); - for(uint i=0;isetData(manualSettingsData); - } - extraWidgets.clear(); - foreach(QString name,manualSettingsObj->getFields().at(0)->getElementNames()) - { - if(!name.contains("Access") && !name.contains("Flight")) - { - QCheckBox * cb=new QCheckBox(name,this); - extraWidgets.append(cb); - m_config->checkBoxesLayout->layout()->addWidget(cb); - connect(cb,SIGNAL(toggled(bool)),this,SLOT(invertControls())); - } - } - connect(manualCommandObj, SIGNAL(objectUpdated(UAVObject*)), this, SLOT(moveSticks())); - wizardStep=wizardIdentifyInverted; - m_config->wzText->setText(QString(tr("Please check the picture below and check all the sticks which show an inverted movement and press next when ready"))); - } - else if(step==wizardFinish) - { - foreach(QWidget * wd,extraWidgets) - { - QCheckBox * cb=qobject_cast(wd); - if(cb) - { - disconnect(cb,SIGNAL(toggled(bool)),this,SLOT(invertControls())); - delete cb; - } - } - wizardStep=wizardFinish; - extraWidgets.clear(); - m_config->wzText->setText(QString(tr("You have completed this wizard, please check below if the picture below mimics your sticks movement.\n" - "This new settings aren't saved to the board yet, after pressing next you will go to the initial screen where you can do that."))); - - } - - else if(step==wizardFinish+1) - { + break; + case wizardIdentifyCenter: + wizardSetUpStep(wizardIdentifyLimits); + break; + case wizardIdentifyLimits: + wizardSetUpStep(wizardIdentifyInverted); + break; + case wizardIdentifyInverted: + wizardSetUpStep(wizardFinish); + break; + case wizardFinish: setTxMovement(nothing); manualCommandObj->setMetadata(manualCommandObj->getDefaultMetadata()); disconnect(manualCommandObj, SIGNAL(objectUpdated(UAVObject*)), this, SLOT(moveSticks())); @@ -545,46 +350,560 @@ void ConfigInputWidget::setupWizardWidget(int step) } manualSettingsObj->setData(manualSettingsData); m_config->stackedWidget->setCurrentIndex(0); - wizardStep=wizardWelcome; + wizardStep=wizardNone; + break; + default: + Q_ASSERT(0); } +} +void ConfigInputWidget::wzBack() +{ + if(wizardStep != wizardNone && + wizardStep != wizardIdentifySticks) + wizardTearDownStep(wizardStep); + + // State transitions for next button + switch(wizardStep) { + case wizardChooseMode: + wizardSetUpStep(wizardWelcome); + break; + case wizardChooseType: + wizardSetUpStep(wizardChooseMode); + break; + case wizardIdentifySticks: + prevChannel(); + if(currentChannelNum == -1) { + wizardTearDownStep(wizardIdentifySticks); + wizardSetUpStep(wizardChooseType); + } + break; + case wizardIdentifyCenter: + wizardSetUpStep(wizardIdentifySticks); + break; + case wizardIdentifyLimits: + wizardSetUpStep(wizardIdentifyCenter); + break; + case wizardIdentifyInverted: + wizardSetUpStep(wizardIdentifyLimits); + break; + case wizardFinish: + wizardSetUpStep(wizardIdentifyInverted); + break; + default: + Q_ASSERT(0); + } +} + +void ConfigInputWidget::wizardSetUpStep(enum wizardSteps step) +{ + switch(step) { + case wizardWelcome: + m_config->graphicsView->setVisible(false); + setTxMovement(nothing); + manualSettingsData=manualSettingsObj->getData(); + manualSettingsData.Arming=ManualControlSettings::ARMING_ALWAYSDISARMED; + previousManualSettingsData = manualSettingsData; + manualSettingsObj->setData(manualSettingsData); + m_config->wzText->setText(tr("Welcome to the inputs configuration wizard.\n" + "Please follow the instructions on the screen and only move your controls when asked to.\n" + "Make sure you already configured your hardware settings on the proper tab and restarted your board.\n" + "At any time you can press 'back' to return to the previous screeen or 'Cancel' to cancel the wizard.\n")); + m_config->stackedWidget->setCurrentIndex(1); + m_config->wzBack->setEnabled(false); + break; + case wizardChooseMode: + { + m_config->graphicsView->setVisible(true); + setTxMovement(nothing); + m_config->wzText->setText(tr("Please choose your transmiter type.\n" + "Mode 1 means your throttle stick is on the right\n" + "Mode 2 means your throttle stick is on the left\n")); + m_config->wzBack->setEnabled(true); + QRadioButton * mode1=new QRadioButton(tr("Mode 1"),this); + QRadioButton * mode2=new QRadioButton(tr("Mode 2"),this); + mode2->setChecked(true); + extraWidgets.clear(); + extraWidgets.append(mode1); + extraWidgets.append(mode2); + m_config->checkBoxesLayout->layout()->addWidget(mode1); + m_config->checkBoxesLayout->layout()->addWidget(mode2); + } + break; + case wizardChooseType: + { + m_config->wzText->setText(tr("Please choose your transmiter mode.\n" + "Acro means normal transmitter\n" + "Heli means there is a collective pitch and throttle input\n" + "If you are using a heli transmitter please engage throttle hold now please.\n")); + m_config->wzBack->setEnabled(true); + QRadioButton * typeAcro=new QRadioButton(tr("Acro"),this); + QRadioButton * typeHeli=new QRadioButton(tr("Heli"),this); + typeAcro->setChecked(true); + typeHeli->setChecked(false); + extraWidgets.clear(); + extraWidgets.append(typeAcro); + extraWidgets.append(typeHeli); + m_config->checkBoxesLayout->layout()->addWidget(typeAcro); + m_config->checkBoxesLayout->layout()->addWidget(typeHeli); + wizardStep=wizardChooseType; + } + break; + case wizardIdentifySticks: + usedChannels.clear(); + currentChannelNum=-1; + nextChannel(); + manualSettingsData=manualSettingsObj->getData(); + connect(receiverActivityObj, SIGNAL(objectUpdated(UAVObject*)), this, SLOT(identifyControls())); + m_config->wzNext->setEnabled(false); + break; + case wizardIdentifyCenter: + setTxMovement(centerAll); + m_config->wzText->setText(QString(tr("Please center all control controls and press next when ready (if your FlightMode switch has only two positions, leave it on either position)"))); + break; + case wizardIdentifyLimits: + { + dimOtherControls(false); + setTxMovement(moveAll); + m_config->wzText->setText(QString(tr("Please move all controls to their maximum extents on both directions and press next when ready"))); + fastMdata(); + manualSettingsData=manualSettingsObj->getData(); + for(uint i=0;igetFields().at(0)->getElementNames()) + { + if(!name.contains("Access") && !name.contains("Flight")) + { + QCheckBox * cb=new QCheckBox(name,this); + extraWidgets.append(cb); + m_config->checkBoxesLayout->layout()->addWidget(cb); + connect(cb,SIGNAL(toggled(bool)),this,SLOT(invertControls())); + } + } + connect(manualCommandObj, SIGNAL(objectUpdated(UAVObject*)), this, SLOT(moveSticks())); + m_config->wzText->setText(QString(tr("Please check the picture below and check all the sticks which show an inverted movement and press next when ready"))); + fastMdata(); + break; + case wizardFinish: + foreach(QWidget * wd,extraWidgets) + { + QCheckBox * cb=qobject_cast(wd); + if(cb) + { + disconnect(cb,SIGNAL(toggled(bool)),this,SLOT(invertControls())); + delete cb; + } + } + extraWidgets.clear(); + connect(manualCommandObj, SIGNAL(objectUpdated(UAVObject*)), this, SLOT(moveSticks())); + m_config->wzText->setText(QString(tr("You have completed this wizard, please check below if the picture below mimics your sticks movement.\n" + "This new settings aren't saved to the board yet, after pressing next you will go to the initial screen where you can do that."))); + fastMdata(); + + manualSettingsData.ChannelNeutral[ManualControlSettings::CHANNELNEUTRAL_THROTTLE]= + manualSettingsData.ChannelMin[ManualControlSettings::CHANNELMIN_THROTTLE]+ + ((manualSettingsData.ChannelMax[ManualControlSettings::CHANNELMAX_THROTTLE]- + manualSettingsData.ChannelMin[ManualControlSettings::CHANNELMIN_THROTTLE])*0.02); + if((abs(manualSettingsData.ChannelMax[ManualControlSettings::CHANNELMAX_FLIGHTMODE]-manualSettingsData.ChannelNeutral[ManualControlSettings::CHANNELNEUTRAL_FLIGHTMODE])<100) || + (abs(manualSettingsData.ChannelMin[ManualControlSettings::CHANNELMIN_FLIGHTMODE]-manualSettingsData.ChannelNeutral[ManualControlSettings::CHANNELNEUTRAL_FLIGHTMODE])<100)) + { + manualSettingsData.ChannelNeutral[ManualControlSettings::CHANNELNEUTRAL_FLIGHTMODE]=manualSettingsData.ChannelMin[ManualControlSettings::CHANNELMIN_FLIGHTMODE]+ + (manualSettingsData.ChannelMax[ManualControlSettings::CHANNELMAX_FLIGHTMODE]-manualSettingsData.ChannelMin[ManualControlSettings::CHANNELMIN_FLIGHTMODE])/2; + } + manualSettingsObj->setData(manualSettingsData); + break; + default: + Q_ASSERT(0); + } + wizardStep = step; +} + +void ConfigInputWidget::wizardTearDownStep(enum wizardSteps step) +{ + QRadioButton * mode, * type; + Q_ASSERT(step == wizardStep); + switch(step) { + case wizardWelcome: + break; + case wizardChooseMode: + mode=qobject_cast(extraWidgets.at(0)); + if(mode->isChecked()) + transmitterMode=mode1; + else + transmitterMode=mode2; + delete extraWidgets.at(0); + delete extraWidgets.at(1); + extraWidgets.clear(); + break; + case wizardChooseType: + type=qobject_cast(extraWidgets.at(0)); + if(type->isChecked()) + transmitterType=acro; + else + transmitterType=heli; + delete extraWidgets.at(0); + delete extraWidgets.at(1); + extraWidgets.clear(); + break; + case wizardIdentifySticks: + disconnect(receiverActivityObj, SIGNAL(objectUpdated(UAVObject*)), this, SLOT(identifyControls())); + m_config->wzNext->setEnabled(true); + break; + case wizardIdentifyCenter: + manualCommandData=manualCommandObj->getData(); + manualSettingsData=manualSettingsObj->getData(); + for(unsigned int i=0;isetData(manualSettingsData); + break; + case wizardIdentifyLimits: + disconnect(manualCommandObj, SIGNAL(objectUpdated(UAVObject*)), this, SLOT(identifyLimits())); + manualSettingsObj->setData(manualSettingsData); + restoreMdata(); + break; + case wizardIdentifyInverted: + foreach(QWidget * wd,extraWidgets) + { + QCheckBox * cb=qobject_cast(wd); + if(cb) + { + disconnect(cb,SIGNAL(toggled(bool)),this,SLOT(invertControls())); + delete cb; + } + } + extraWidgets.clear(); + disconnect(manualCommandObj, SIGNAL(objectUpdated(UAVObject*)), this, SLOT(moveSticks())); + restoreMdata(); + break; + case wizardFinish: + setTxMovement(nothing); + m_config->stackedWidget->setCurrentIndex(0); + disconnect(manualCommandObj, SIGNAL(objectUpdated(UAVObject*)), this, SLOT(moveSticks())); + restoreMdata(); + break; + default: + Q_ASSERT(0); + } } /** - * Unfortunately order of channel should be different in different conditions + * Set manual control command to fast updates */ -int ConfigInputWidget::getChannelFromStep(int currentStep) +void ConfigInputWidget::fastMdata() { - int channelToSet; - if(transmitterType == heli) { - // For heli swap order of collective to beginning - qDebug() << "Transmitter type: " << heli << " channelToSet: " << currentStep; - if(currentStep == 0) - channelToSet = ManualControlSettings::CHANNELGROUPS_COLLECTIVE; - else if(currentStep <= ManualControlSettings::CHANNELGROUPS_COLLECTIVE) - channelToSet = currentStep - 1; - else channelToSet = currentStep; - qDebug() << "Channel to set: " << channelToSet; - } else - channelToSet = currentStep; + manualControlMdata = manualCommandObj->getMetadata(); + UAVObject::Metadata mdata = manualControlMdata; + mdata.flightTelemetryUpdateMode = UAVObject::UPDATEMODE_PERIODIC; + mdata.flightTelemetryUpdatePeriod = 150; + manualCommandObj->setMetadata(mdata); +} - Q_ASSERT(channelToSet >= 0 && channelToSet < ManualControlSettings::CHANNELGROUPS_NUMELEM); +/** + * Restore previous update settings for manual control data + */ +void ConfigInputWidget::restoreMdata() +{ + manualCommandObj->setMetadata(manualControlMdata); +} - if(channelToSet == ManualControlSettings::CHANNELGROUPS_COLLECTIVE) +//void ConfigInputWidget::setupWizardWidget(int step) +//{ +// if(step==wizardWelcome) +// { +// m_config->graphicsView->setVisible(false); +// setTxMovement(nothing); +// if(wizardStep==wizardChooseMode) +// { +// delete extraWidgets.at(0); +// delete extraWidgets.at(1); +// extraWidgets.clear(); +// } +// manualSettingsData=manualSettingsObj->getData(); +// manualSettingsData.Arming=ManualControlSettings::ARMING_ALWAYSDISARMED; +// manualSettingsObj->setData(manualSettingsData); +// m_config->wzText->setText(tr("Welcome to the inputs configuration wizard.\n" +// "Please follow the instructions on the screen and only move your controls when asked to.\n" +// "Make sure you already configured your hardware settings on the proper tab and restarted your board.\n" +// "At any time you can press 'back' to return to the previous screeen or 'Cancel' to cancel the wizard.\n")); +// m_config->stackedWidget->setCurrentIndex(1); +// m_config->wzBack->setEnabled(false); +// wizardStep=wizardWelcome; +// } +// else if(step==wizardChooseMode) +// { +// m_config->graphicsView->setVisible(true); +// setTxMovement(nothing); +// if(wizardStep==wizardIdentifySticks) +// { +// disconnect(receiverActivityObj, SIGNAL(objectUpdated(UAVObject*)), this, SLOT(identifyControls())); +// m_config->wzNext->setEnabled(true); +// } +// m_config->wzText->setText(tr("Please choose your transmiter type.\n" +// "Mode 1 means your throttle stick is on the right\n" +// "Mode 2 means your throttle stick is on the left\n")); +// m_config->wzBack->setEnabled(true); +// QRadioButton * mode1=new QRadioButton(tr("Mode 1"),this); +// QRadioButton * mode2=new QRadioButton(tr("Mode 2"),this); +// mode2->setChecked(true); +// extraWidgets.clear(); +// extraWidgets.append(mode1); +// extraWidgets.append(mode2); +// m_config->checkBoxesLayout->layout()->addWidget(mode1); +// m_config->checkBoxesLayout->layout()->addWidget(mode2); +// wizardStep=wizardChooseMode; +// } +// else if(step==wizardChooseType) +// { +// if(wizardStep==wizardChooseMode) +// { +// QRadioButton * mode=qobject_cast(extraWidgets.at(0)); +// if(mode->isChecked()) +// transmitterMode=mode1; +// else +// transmitterMode=mode2; +// delete extraWidgets.at(0); +// delete extraWidgets.at(1); +// extraWidgets.clear(); +// } + +// m_config->wzText->setText(tr("Please choose your transmiter mode.\n" +// "Acro means normal transmitter\n" +// "Heli means there is a collective pitch and throttle input\n")); +// m_config->wzBack->setEnabled(true); +// QRadioButton * typeAcro=new QRadioButton(tr("Acro"),this); +// QRadioButton * typeHeli=new QRadioButton(tr("Heli"),this); +// typeAcro->setChecked(true); +// typeHeli->setChecked(false); +// extraWidgets.clear(); +// extraWidgets.append(typeAcro); +// extraWidgets.append(typeHeli); +// m_config->checkBoxesLayout->layout()->addWidget(typeAcro); +// m_config->checkBoxesLayout->layout()->addWidget(typeHeli); +// wizardStep=wizardChooseType; +// } else if(step==wizardIdentifySticks && !isSimple) { +// usedChannels.clear(); +// if(wizardStep==wizardChooseType) +// { +// qDebug() << "Chosing type"; +// QRadioButton * type=qobject_cast(extraWidgets.at(0)); +// if(type->isChecked()) +// transmitterType=acro; +// else +// transmitterType=heli; +// qDebug() << "Checked: " << type->isChecked() << " " << "type is" << transmitterType; +// delete extraWidgets.at(0); +// delete extraWidgets.at(1); +// extraWidgets.clear(); +// } +// wizardStep=wizardIdentifySticks; +// currentCommand=0; +// getChannelFromStep(currentCommand); +// manualSettingsData=manualSettingsObj->getData(); +// connect(receiverActivityObj, SIGNAL(objectUpdated(UAVObject*)), this, SLOT(identifyControls())); +// m_config->wzNext->setEnabled(false); +// } +// else if(step==wizardIdentifyCenter || (isSimple && step==wizardIdentifySticks)) +// { +// setTxMovement(centerAll); +// if(wizardStep==wizardIdentifySticks) +// disconnect(receiverActivityObj, SIGNAL(objectUpdated(UAVObject*)), this, SLOT(identifyControls())); +// else +// { +// disconnect(manualCommandObj, SIGNAL(objectUpdated(UAVObject*)), this, SLOT(identifyLimits())); +// manualSettingsObj->setData(manualSettingsData); +// manualCommandObj->setMetadata(manualCommandObj->getDefaultMetadata()); +// } +// wizardStep=wizardIdentifyCenter; +// m_config->wzText->setText(QString(tr("Please center all control controls and press next when ready (if your FlightMode switch has only two positions, leave it on either position)"))); +// } +// else if(step==wizardIdentifyLimits) +// { +// dimOtherControls(false); +// setTxMovement(moveAll); +// if(wizardStep==wizardIdentifyCenter) +// { +// wizardStep=wizardIdentifyLimits; +// manualCommandData=manualCommandObj->getData(); +// manualSettingsData=manualSettingsObj->getData(); +// for(unsigned int i=0;isetData(manualSettingsData); +// } +// if(wizardStep==wizardIdentifyInverted) +// { +// foreach(QWidget * wd,extraWidgets) +// { +// QCheckBox * cb=qobject_cast(wd); +// if(cb) +// { +// disconnect(cb,SIGNAL(toggled(bool)),this,SLOT(invertControls())); +// delete cb; +// } +// } +// } +// extraWidgets.clear(); +// disconnect(manualCommandObj, SIGNAL(objectUpdated(UAVObject*)), this, SLOT(moveSticks())); +// wizardStep=wizardIdentifyLimits; +// m_config->wzText->setText(QString(tr("Please move all controls to their maximum extents on both directions and press next when ready"))); +// UAVObject::Metadata mdata= manualCommandObj->getMetadata(); +// mdata.flightTelemetryUpdateMode = UAVObject::UPDATEMODE_PERIODIC; +// mdata.flightTelemetryUpdatePeriod = 150; +// manualCommandObj->setMetadata(mdata); +// manualSettingsData=manualSettingsObj->getData(); +// for(uint i=0;isetData(manualSettingsData); +// } +// extraWidgets.clear(); +// foreach(QString name,manualSettingsObj->getFields().at(0)->getElementNames()) +// { +// if(!name.contains("Access") && !name.contains("Flight")) +// { +// QCheckBox * cb=new QCheckBox(name,this); +// extraWidgets.append(cb); +// m_config->checkBoxesLayout->layout()->addWidget(cb); +// connect(cb,SIGNAL(toggled(bool)),this,SLOT(invertControls())); +// } +// } +// connect(manualCommandObj, SIGNAL(objectUpdated(UAVObject*)), this, SLOT(moveSticks())); +// wizardStep=wizardIdentifyInverted; +// m_config->wzText->setText(QString(tr("Please check the picture below and check all the sticks which show an inverted movement and press next when ready"))); +// } +// else if(step==wizardFinish) +// { +// foreach(QWidget * wd,extraWidgets) +// { +// QCheckBox * cb=qobject_cast(wd); +// if(cb) +// { +// disconnect(cb,SIGNAL(toggled(bool)),this,SLOT(invertControls())); +// delete cb; +// } +// } +// wizardStep=wizardFinish; +// extraWidgets.clear(); +// m_config->wzText->setText(QString(tr("You have completed this wizard, please check below if the picture below mimics your sticks movement.\n" +// "This new settings aren't saved to the board yet, after pressing next you will go to the initial screen where you can do that."))); + +// } + +// else if(step==wizardFinish+1) +// { +// setTxMovement(nothing); +// manualCommandObj->setMetadata(manualCommandObj->getDefaultMetadata()); +// disconnect(manualCommandObj, SIGNAL(objectUpdated(UAVObject*)), this, SLOT(moveSticks())); +// manualSettingsData=manualSettingsObj->getData(); +// manualSettingsData.ChannelNeutral[ManualControlSettings::CHANNELNEUTRAL_THROTTLE]= +// manualSettingsData.ChannelMin[ManualControlSettings::CHANNELMIN_THROTTLE]+ +// ((manualSettingsData.ChannelMax[ManualControlSettings::CHANNELMAX_THROTTLE]- +// manualSettingsData.ChannelMin[ManualControlSettings::CHANNELMIN_THROTTLE])*0.02); +// if((abs(manualSettingsData.ChannelMax[ManualControlSettings::CHANNELMAX_FLIGHTMODE]-manualSettingsData.ChannelNeutral[ManualControlSettings::CHANNELNEUTRAL_FLIGHTMODE])<100) || +// (abs(manualSettingsData.ChannelMin[ManualControlSettings::CHANNELMIN_FLIGHTMODE]-manualSettingsData.ChannelNeutral[ManualControlSettings::CHANNELNEUTRAL_FLIGHTMODE])<100)) +// { +// manualSettingsData.ChannelNeutral[ManualControlSettings::CHANNELNEUTRAL_FLIGHTMODE]=manualSettingsData.ChannelMin[ManualControlSettings::CHANNELMIN_FLIGHTMODE]+ +// (manualSettingsData.ChannelMax[ManualControlSettings::CHANNELMAX_FLIGHTMODE]-manualSettingsData.ChannelMin[ManualControlSettings::CHANNELMIN_FLIGHTMODE])/2; +// } +// manualSettingsObj->setData(manualSettingsData); +// m_config->stackedWidget->setCurrentIndex(0); +// wizardStep=wizardWelcome; +// } + +//} + +/** + * Set the display to indicate which channel the person should move + */ +void ConfigInputWidget::setChannel(int newChan) +{ + if(newChan == ManualControlSettings::CHANNELGROUPS_COLLECTIVE) m_config->wzText->setText(QString(tr("Please enable throttle hold mode and move the collective pitch stick"))); + else if (newChan == ManualControlSettings::CHANNELGROUPS_FLIGHTMODE) + m_config->wzText->setText(QString(tr("Please flick the flight mode switch. For switches you may have to repeat this rapidly."))); else m_config->wzText->setText(QString(tr("Please move each control once at a time according to the instructions and picture below.\n\n" - "Move the %1 stick")).arg(manualSettingsObj->getField("ChannelGroups")->getElementNames().at(channelToSet))); + "Move the %1 stick")).arg(manualSettingsObj->getField("ChannelGroups")->getElementNames().at(newChan))); - return channelToSet; + if(manualSettingsObj->getField("ChannelGroups")->getElementNames().at(newChan).contains("Accessory")) + m_config->wzNext->setEnabled(true); + + setMoveFromCommand(newChan); + + currentChannelNum = newChan; +} + +/** + * Unfortunately order of channel should be different in different conditions. Selects + * next channel based on heli or acro mode + */ +void ConfigInputWidget::nextChannel() +{ + QList order = (transmitterType == heli) ? heliChannelOrder : acroChannelOrder; + + if(currentChannelNum == -1) { + setChannel(order[0]); + return; + } + for (int i = 0; i < order.length() - 1; i++) { + if(order[i] == currentChannelNum) { + setChannel(order[i+1]); + return; + } + } + currentChannelNum = -1; // hit end of list +} + +/** + * Unfortunately order of channel should be different in different conditions. Selects + * previous channel based on heli or acro mode + */ +void ConfigInputWidget::prevChannel() +{ + QList order = transmitterType == heli ? heliChannelOrder : acroChannelOrder; + + // No previous from unset channel or next state + if(currentChannelNum == -1) + return; + + for (int i = 1; i < order.length(); i++) { + if(order[i] == currentChannelNum) { + setChannel(order[i-1]); + usedChannels.removeLast(); + return; + } + } + currentChannelNum = -1; // hit end of list } void ConfigInputWidget::identifyControls() { static int debounce=0; - int channelToSet = getChannelFromStep(currentCommand); - receiverActivityData=receiverActivityObj->getData(); if(receiverActivityData.ActiveChannel==255) return; @@ -602,26 +921,18 @@ void ConfigInputWidget::identifyControls() debounce=0; usedChannels.append(lastChannel); manualSettingsData=manualSettingsObj->getData(); - manualSettingsData.ChannelGroups[channelToSet]=currentChannel.group; - manualSettingsData.ChannelNumber[channelToSet]=currentChannel.number; + manualSettingsData.ChannelGroups[currentChannelNum]=currentChannel.group; + manualSettingsData.ChannelNumber[currentChannelNum]=currentChannel.number; manualSettingsObj->setData(manualSettingsData); } else return; } - ++currentCommand; - channelToSet = getChannelFromStep(currentCommand); - setMoveFromCommand(channelToSet); - if(currentCommand>ManualControlSettings::CHANNELGROUPS_NUMELEM-1) - { - disconnect(receiverActivityObj, SIGNAL(objectUpdated(UAVObject*)), this, SLOT(identifyControls())); - m_config->wzNext->setEnabled(true); - } - if(manualSettingsObj->getField("ChannelGroups")->getElementNames().at(currentCommand).contains("Accessory") || - manualSettingsObj->getField("ChannelGroups")->getElementNames().at(currentCommand).contains("Collective")) - { - m_config->wzNext->setEnabled(true); - } + + m_config->wzText->clear(); + setTxMovement(nothing); + + QTimer::singleShot(300, this, SLOT(wzNext())); } void ConfigInputWidget::identifyLimits() @@ -1080,17 +1391,14 @@ void ConfigInputWidget::simpleCalibration(bool enable) manualSettingsData.ChannelMax[i] = manualCommandData.Channel[i]; } - UAVObject::Metadata mdata= manualCommandObj->getMetadata(); - mdata.flightTelemetryUpdateMode = UAVObject::UPDATEMODE_PERIODIC; - mdata.flightTelemetryUpdatePeriod = 150; - manualCommandObj->setMetadata(mdata); + fastMdata(); connect(manualCommandObj, SIGNAL(objectUnpacked(UAVObject*)), this, SLOT(updateCalibration())); } else { manualCommandData = manualCommandObj->getData(); manualSettingsData = manualSettingsObj->getData(); - manualCommandObj->setMetadata(manualCommandObj->getDefaultMetadata()); + restoreMdata(); for (int i = 0; i < ManualControlCommand::CHANNEL_NUMELEM; i++) manualSettingsData.ChannelNeutral[i] = manualCommandData.Channel[i]; diff --git a/ground/openpilotgcs/src/plugins/config/configinputwidget.h b/ground/openpilotgcs/src/plugins/config/configinputwidget.h index fd6b14001..b8dc664ea 100644 --- a/ground/openpilotgcs/src/plugins/config/configinputwidget.h +++ b/ground/openpilotgcs/src/plugins/config/configinputwidget.h @@ -52,7 +52,7 @@ class ConfigInputWidget: public ConfigTaskWidget public: ConfigInputWidget(QWidget *parent = 0); ~ConfigInputWidget(); - enum wizardSteps{wizardWelcome,wizardChooseMode,wizardChooseType,wizardIdentifySticks,wizardIdentifyCenter,wizardIdentifyLimits,wizardIdentifyInverted,wizardFinish}; + enum wizardSteps{wizardWelcome,wizardChooseMode,wizardChooseType,wizardIdentifySticks,wizardIdentifyCenter,wizardIdentifyLimits,wizardIdentifyInverted,wizardFinish,wizardNone}; enum txMode{mode1,mode2}; enum txMovements{moveLeftVerticalStick,moveRightVerticalStick,moveLeftHorizontalStick,moveRightHorizontalStick,moveAccess0,moveAccess1,moveAccess2,moveFlightMode,centerAll,moveAll,nothing}; enum txMovementType{vertical,horizontal,jump,mix}; @@ -67,7 +67,6 @@ private: void setTxMovement(txMovements movement); Ui_InputWidget *m_config; wizardSteps wizardStep; - void setupWizardWidget(int step); QList extraWidgets; txMode transmitterMode; txType transmitterType; @@ -85,12 +84,16 @@ private: QEventLoop * loop; bool skipflag; - uint currentCommand; + int currentChannelNum; + QList heliChannelOrder; + QList acroChannelOrder; ManualControlCommand * manualCommandObj; ManualControlCommand::DataFields manualCommandData; + UAVObject::Metadata manualControlMdata; ManualControlSettings * manualSettingsObj; ManualControlSettings::DataFields manualSettingsData; + ManualControlSettings::DataFields previousManualSettingsData; ReceiverActivity * receiverActivityObj; ReceiverActivity::DataFields receiverActivityData; @@ -121,7 +124,16 @@ private: void setMoveFromCommand(int command); bool isSimple; void goToWizard(); - int getChannelFromStep(int); + + void fastMdata(); + void restoreMdata(); + + void setChannel(int); + void nextChannel(); + void prevChannel(); + + void wizardSetUpStep(enum wizardSteps); + void wizardTearDownStep(enum wizardSteps); private slots: void wzNext(); void wzBack();