MixerCurve::MixerCurve(QWidget *parent) :
    QFrame(parent),
    m_mixerUI(new Ui::MixerCurve)
{
    m_mixerUI->setupUi(this);

    // setup some convienence pointers
    m_curve    = m_mixerUI->CurveWidget;
    m_settings = m_mixerUI->CurveSettings;


    m_mixerUI->SettingsGroup->hide();

    // create our spin delegate
    m_spinDelegate = new DoubleSpinDelegate();

    // set the default mixer type
    setMixerType(MixerCurve::MIXERCURVE_THROTTLE);

    // paint the ui
    UpdateCurveUI();

    // wire up our signals
    connect(m_mixerUI->CurveType, SIGNAL(currentIndexChanged(int)), this, SLOT(CurveTypeChanged()));
    connect(m_mixerUI->ResetCurve, SIGNAL(clicked()), this, SLOT(ResetCurve()));
    connect(m_mixerUI->PopupCurve, SIGNAL(clicked()), this, SLOT(PopupCurve()));
    connect(m_mixerUI->GenerateCurve, SIGNAL(clicked()), this, SLOT(GenerateCurve()));
    connect(m_curve, SIGNAL(curveUpdated()), this, SLOT(UpdateSettingsTable()));
    connect(m_settings, SIGNAL(cellChanged(int, int)), this, SLOT(SettingsTableChanged()));
    connect(m_mixerUI->CurveMin, SIGNAL(valueChanged(double)), this, SLOT(CurveMinChanged(double)));
    connect(m_mixerUI->CurveMax, SIGNAL(valueChanged(double)), this, SLOT(CurveMaxChanged(double)));
    connect(m_mixerUI->CurveStep, SIGNAL(valueChanged(double)), this, SLOT(GenerateCurve()));
}
/**
   Setup steerable ground vehicle.

   Returns False if impossible to create the mixer.
 */
bool ConfigGroundVehicleWidget::setupGroundVehicleCar(QString airframeType)
{
    // Check coherence:
    // Show any config errors in GUI
    if (throwConfigError(airframeType)) {
        return false;
    }

    // Now setup the channels:
    GUIConfigDataUnion config = getConfigData();
    resetActuators(&config);

    config.ground.GroundVehicleThrottle1 = m_aircraft->gvMotor1ChannelBox->currentIndex();
    config.ground.GroundVehicleThrottle2 = m_aircraft->gvMotor2ChannelBox->currentIndex();
    config.ground.GroundVehicleSteering1 = m_aircraft->gvSteering1ChannelBox->currentIndex();
    config.ground.GroundVehicleSteering2 = m_aircraft->gvSteering2ChannelBox->currentIndex();

    setConfigData(config);

    UAVDataObject *mixer = dynamic_cast<UAVDataObject *>(getObjectManager()->getObject(QString("MixerSettings")));
    Q_ASSERT(mixer);
    resetMotorAndServoMixers(mixer);

    int channel = m_aircraft->gvSteering1ChannelBox->currentIndex() - 1;
    setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_SERVO);
    setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_YAW, 127);

    channel = m_aircraft->gvSteering2ChannelBox->currentIndex() - 1;
    setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_SERVO);
    setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_YAW, -127);

    channel = m_aircraft->gvMotor1ChannelBox->currentIndex() - 1;
    setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_REVERSABLEMOTOR);
    setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_THROTTLECURVE1, 127);

    channel = m_aircraft->gvMotor2ChannelBox->currentIndex() - 1;
    setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_REVERSABLEMOTOR);
    setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_THROTTLECURVE1, 127);

    // Output success message
    m_aircraft->gvStatusLabel->setText("Mixer generated");

    return true;
}
/**
 Setup steerable ground vehicle.
 
 Returns False if impossible to create the mixer.
 */
bool ConfigGroundVehicleWidget::setupGroundVehicleCar(SystemSettings::AirframeTypeOptions airframeType)
{
    // Check coherence:
	//Show any config errors in GUI
    if (throwConfigError(airframeType)) {
		return false;
	}

    // Now setup the channels:
    GUIConfigDataUnion config = GetConfigData();
    ResetActuators(&config);
	
    config.ground.GroundVehicleThrottle1 = m_aircraft->gvMotor1ChannelBox->currentIndex();
    config.ground.GroundVehicleThrottle2 = m_aircraft->gvMotor2ChannelBox->currentIndex();
    config.ground.GroundVehicleSteering1 = m_aircraft->gvSteering1ChannelBox->currentIndex();
    config.ground.GroundVehicleSteering2 = m_aircraft->gvSteering2ChannelBox->currentIndex();

    SetConfigData(config);

    MixerSettings *mixerSettings = MixerSettings::GetInstance(getObjectManager());
    Q_ASSERT(mixerSettings);
    resetMixers(mixerSettings);

    int channel = m_aircraft->gvSteering1ChannelBox->currentIndex()-1;
    setMixerType(mixerSettings,channel, MixerSettings::MIXER1TYPE_SERVO);
    setMixerVectorValue(mixerSettings, channel, MixerSettings::MIXER1VECTOR_YAW, 127);

    channel = m_aircraft->gvSteering2ChannelBox->currentIndex()-1;
    setMixerType(mixerSettings,channel, MixerSettings::MIXER1TYPE_SERVO);
    setMixerVectorValue(mixerSettings, channel, MixerSettings::MIXER1VECTOR_YAW, -127);

    channel = m_aircraft->gvMotor1ChannelBox->currentIndex()-1;
    setMixerType(mixerSettings,channel, MixerSettings::MIXER1TYPE_MOTOR);
    setMixerVectorValue(mixerSettings, channel, MixerSettings::MIXER1VECTOR_THROTTLECURVE1, 127);

    channel = m_aircraft->gvMotor2ChannelBox->currentIndex()-1;
    setMixerType(mixerSettings,channel, MixerSettings::MIXER1TYPE_MOTOR);
    setMixerVectorValue(mixerSettings, channel, MixerSettings::MIXER1VECTOR_THROTTLECURVE2, 127);

	//Output success message
    m_aircraft->gvStatusLabel->setText("Mixer generated");
	
    return true;
}
/**
 Helper function: setupQuadMotor
 */
void ConfigMultiRotorWidget::setupQuadMotor(int channel, double pitch, double roll, double yaw)
{
    MixerSettings *mixerSettings = MixerSettings::GetInstance(getObjectManager());
    Q_ASSERT(mixerSettings);

    setMixerType(mixerSettings, channel, MixerSettings::MIXER1TYPE_MOTOR);

    setMixerVectorValue(mixerSettings, channel, MixerSettings::MIXER1VECTOR_THROTTLECURVE1, 127);
    setMixerVectorValue(mixerSettings, channel, MixerSettings::MIXER1VECTOR_THROTTLECURVE2, 0);
    setMixerVectorValue(mixerSettings, channel, MixerSettings::MIXER1VECTOR_ROLL, roll*127);
    setMixerVectorValue(mixerSettings, channel, MixerSettings::MIXER1VECTOR_PITCH, pitch*127);
    setMixerVectorValue(mixerSettings, channel, MixerSettings::MIXER1VECTOR_YAW, yaw*127);
}
示例#5
0
MixerCurve::MixerCurve(QWidget *parent) :
    QFrame(parent),
    m_mixerUI(new Ui::MixerCurvePlot)
{
    m_mixerUI->setupUi(this);

    // setup some convienence pointers
    m_curve = m_mixerUI->CurveWidget;
    m_settings = m_mixerUI->CurveSettings;

    // by default mixcurve isn't used for curve2source
    m_mixerUI->CBCurve2Source->hide();

    m_mixerUI->SettingsGroup->hide();
    m_curve->showCommands(false);
    m_curve->showCommand("Reset", false);
    m_curve->showCommand("Popup", false);
    m_curve->showCommand("Commands", false);

    // create our spin delegate
    m_spinDelegate = new DoubleSpinDelegate();

    // set the default mixer type
    setMixerType(MixerCurve::MIXERCURVE_THROTTLE);

    // setup and turn off advanced mode
    CommandActivated();

    // paint the ui
    UpdateCurveUI();

    // wire up our signals

    connect(m_mixerUI->CurveType, SIGNAL(currentIndexChanged(int)), this, SLOT(CurveTypeChanged()));
    connect(m_mixerUI->ResetCurve, SIGNAL(clicked()), this, SLOT(ResetCurve()));
    connect(m_mixerUI->PopupCurve, SIGNAL(clicked()),this,SLOT(PopupCurve()));
    connect(m_mixerUI->GenerateCurve, SIGNAL(clicked()), this, SLOT(GenerateCurve()));
    connect(m_curve, SIGNAL(curveUpdated()), this, SLOT(UpdateSettingsTable()));
    connect(m_curve, SIGNAL(commandActivated(MixerNode*)),this, SLOT(CommandActivated(MixerNode*)));
    connect(m_settings, SIGNAL(cellChanged(int,int)), this, SLOT(SettingsTableChanged()));
    connect(m_mixerUI->CurveMin, SIGNAL(valueChanged(double)), this, SLOT(CurveMinChanged(double)));
    connect(m_mixerUI->CurveMax, SIGNAL(valueChanged(double)), this, SLOT(CurveMaxChanged(double)));
    connect(m_mixerUI->CurveStep, SIGNAL(valueChanged(double)), this, SLOT(GenerateCurve()));



}
/**
   Helper function to
 */
QString ConfigCustomWidget::updateConfigObjectsFromWidgets()
{
    UAVDataObject *system = dynamic_cast<UAVDataObject *>(getObjectManager()->getObject(QString("SystemSettings")));

    Q_ASSERT(system);

    QPointer<UAVObjectField> field = system->getField(QString("AirframeType"));

    // Do not allow changes until AirframeType == Custom
    // If user want to save custom mixer : first set AirframeType to 'Custom' without changes and next modify.
    if (field->getValue().toString() == "Custom") {
        UAVDataObject *mixer = dynamic_cast<UAVDataObject *>(getObjectManager()->getObject(QString("MixerSettings")));

        Q_ASSERT(mixer);

        setThrottleCurve(mixer, VehicleConfig::MIXER_THROTTLECURVE1, m_aircraft->customThrottle1Curve->getCurve());
        setThrottleCurve(mixer, VehicleConfig::MIXER_THROTTLECURVE2, m_aircraft->customThrottle2Curve->getCurve());

        GUIConfigDataUnion configData = getConfigData();
        resetActuators(&configData);

        // Update the table:
        for (int channel = 0; channel < (int)VehicleConfig::CHANNEL_NUMELEM; channel++) {
            QComboBox *q = (QComboBox *)m_aircraft->customMixerTable->cellWidget(0, channel);
            if (q->currentText() == "Disabled") {
                setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_DISABLED);
            } else if (q->currentText() == "Motor") {
                setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_MOTOR);
                if (configData.custom.Motor1 == 0) {
                    configData.custom.Motor1 = channel + 1;
                } else if (configData.custom.Motor2 == 0) {
                    configData.custom.Motor2 = channel + 1;
                } else if (configData.custom.Motor3 == 0) {
                    configData.custom.Motor3 = channel + 1;
                } else if (configData.custom.Motor4 == 0) {
                    configData.custom.Motor4 = channel + 1;
                } else if (configData.custom.Motor5 == 0) {
                    configData.custom.Motor5 = channel + 1;
                } else if (configData.custom.Motor6 == 0) {
                    configData.custom.Motor6 = channel + 1;
                } else if (configData.custom.Motor7 == 0) {
                    configData.custom.Motor7 = channel + 1;
                } else if (configData.custom.Motor8 == 0) {
                    configData.custom.Motor8 = channel + 1;
                }
            } else if (q->currentText() == "ReversableMotor") {
                setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_REVERSABLEMOTOR);
                if (configData.custom.RevMotor1 == 0) {
                    configData.custom.RevMotor1 = channel + 1;
                } else if (configData.custom.RevMotor2 == 0) {
                    configData.custom.RevMotor2 = channel + 1;
                } else if (configData.custom.RevMotor3 == 0) {
                    configData.custom.RevMotor3 = channel + 1;
                } else if (configData.custom.RevMotor4 == 0) {
                    configData.custom.RevMotor4 = channel + 1;
                } else if (configData.custom.RevMotor5 == 0) {
                    configData.custom.RevMotor5 = channel + 1;
                } else if (configData.custom.RevMotor6 == 0) {
                    configData.custom.RevMotor6 = channel;
                } else if (configData.custom.RevMotor7 == 0) {
                    configData.custom.RevMotor7 = channel;
                } else if (configData.custom.RevMotor8 == 0) {
                    configData.custom.RevMotor8 = channel;
                }
            } else if (q->currentText() == "Servo") {
                setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_SERVO);
                if (configData.custom.Servo1 == 0) {
                    configData.custom.Servo1 = channel + 1;
                } else if (configData.custom.Servo2 == 0) {
                    configData.custom.Servo2 = channel + 1;
                } else if (configData.custom.Servo3 == 0) {
                    configData.custom.Servo3 = channel + 1;
                } else if (configData.custom.Servo4 == 0) {
                    configData.custom.Servo4 = channel + 1;
                } else if (configData.custom.Servo5 == 0) {
                    configData.custom.Servo5 = channel + 1;
                } else if (configData.custom.Servo6 == 0) {
                    configData.custom.Servo6 = channel + 1;
                } else if (configData.custom.Servo7 == 0) {
                    configData.custom.Servo7 = channel + 1;
                } else if (configData.custom.Servo8 == 0) {
                    configData.custom.Servo8 = channel + 1;
                }
            } else if (q->currentText() == "CameraRoll") {
                setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_CAMERAROLL);
            } else if (q->currentText() == "CameraPitch") {
                setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_CAMERAPITCH);
            } else if (q->currentText() == "CameraYaw") {
                setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_CAMERAYAW);
            } else if (q->currentText() == "Accessory0") {
                setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_ACCESSORY0);
            } else if (q->currentText() == "Accessory1") {
                setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_ACCESSORY1);
            } else if (q->currentText() == "Accessory2") {
                setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_ACCESSORY2);
            } else if (q->currentText() == "Accessory3") {
                setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_ACCESSORY3);
            } else if (q->currentText() == "Accessory4") {
                setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_ACCESSORY4);
            } else if (q->currentText() == "Accessory5") {
                setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_ACCESSORY5);
            }
            setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_THROTTLECURVE1,
                                m_aircraft->customMixerTable->item(1, channel)->text().toDouble());
            setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_THROTTLECURVE2,
                                m_aircraft->customMixerTable->item(2, channel)->text().toDouble());
            setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_ROLL,
                                m_aircraft->customMixerTable->item(3, channel)->text().toDouble());
            setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_PITCH,
                                m_aircraft->customMixerTable->item(4, channel)->text().toDouble());
            setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_YAW,
                                m_aircraft->customMixerTable->item(5, channel)->text().toDouble());
        }
        setConfigData(configData);
    }
    return "Custom";
}
/**
   Helper function to
 */
QString ConfigCustomWidget::updateConfigObjectsFromWidgets()
{
    UAVDataObject *mixer = dynamic_cast<UAVDataObject *>(getObjectManager()->getObject(QString("MixerSettings")));

    Q_ASSERT(mixer);

    setThrottleCurve(mixer, VehicleConfig::MIXER_THROTTLECURVE1, m_aircraft->customThrottle1Curve->getCurve());
    setThrottleCurve(mixer, VehicleConfig::MIXER_THROTTLECURVE2, m_aircraft->customThrottle2Curve->getCurve());

    // Update the table:
    for (int channel = 0; channel < (int)VehicleConfig::CHANNEL_NUMELEM; channel++) {
        QComboBox *q = (QComboBox *)m_aircraft->customMixerTable->cellWidget(0, channel);
        if (q->currentText() == "Disabled") {
            setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_DISABLED);
        } else if (q->currentText() == "Motor") {
            setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_MOTOR);
        } else if (q->currentText() == "ReversableMotor") {
            setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_REVERSABLEMOTOR);
        } else if (q->currentText() == "Servo") {
            setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_SERVO);
        } else if (q->currentText() == "CameraRoll") {
            setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_CAMERAROLL);
        } else if (q->currentText() == "CameraPitch") {
            setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_CAMERAPITCH);
        } else if (q->currentText() == "CameraYaw") {
            setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_CAMERAYAW);
        } else if (q->currentText() == "Accessory0") {
            setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_ACCESSORY0);
        } else if (q->currentText() == "Accessory1") {
            setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_ACCESSORY1);
        } else if (q->currentText() == "Accessory2") {
            setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_ACCESSORY2);
        } else if (q->currentText() == "Accessory3") {
            setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_ACCESSORY3);
        } else if (q->currentText() == "Accessory4") {
            setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_ACCESSORY4);
        } else if (q->currentText() == "Accessory5") {
            setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_ACCESSORY5);
        }
        setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_THROTTLECURVE1,
                            m_aircraft->customMixerTable->item(1, channel)->text().toDouble());
        setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_THROTTLECURVE2,
                            m_aircraft->customMixerTable->item(2, channel)->text().toDouble());
        setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_ROLL,
                            m_aircraft->customMixerTable->item(3, channel)->text().toDouble());
        setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_PITCH,
                            m_aircraft->customMixerTable->item(4, channel)->text().toDouble());
        setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_YAW,
                            m_aircraft->customMixerTable->item(5, channel)->text().toDouble());
    }

    return "Custom";
}
/**
   Setup VTail
 */
bool ConfigFixedWingWidget::setupFrameVtail(QString airframeType)
{
    // Check coherence:
    // Show any config errors in GUI
    if (throwConfigError(airframeType)) {
        return false;
    }

    GUIConfigDataUnion config = getConfigData();
    resetActuators(&config);

    config.fixedwing.FixedWingPitch1   = m_aircraft->fwElevator1ChannelBox->currentIndex();
    config.fixedwing.FixedWingPitch2   = m_aircraft->fwElevator2ChannelBox->currentIndex();
    config.fixedwing.FixedWingRoll1    = m_aircraft->fwAileron1ChannelBox->currentIndex();
    config.fixedwing.FixedWingRoll2    = m_aircraft->fwAileron2ChannelBox->currentIndex();
    config.fixedwing.FixedWingThrottle = m_aircraft->fwEngineChannelBox->currentIndex();

    setConfigData(config);

    UAVDataObject *mixer = dynamic_cast<UAVDataObject *>(getObjectManager()->getObject(QString("MixerSettings")));
    Q_ASSERT(mixer);
    resetMotorAndServoMixers(mixer);

    // Save the curve:
    // ... and compute the matrix:
    // In order to make code a bit nicer, we assume:
    // - Channel dropdowns start with 'None', then 0 to 7

    // 1. Assign the servo/motor/none for each channel

    double pitch;
    double roll;
    double yaw;

    // motor
    int channel = m_aircraft->fwEngineChannelBox->currentIndex() - 1;
    setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_MOTOR);
    setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_THROTTLECURVE1, 127);

    // ailerons
    setMixerValue(mixer, "FirstRollServo", m_aircraft->fwAileron1ChannelBox->currentIndex());
    channel = m_aircraft->fwAileron1ChannelBox->currentIndex() - 1;
    if (channel > -1) {
        // Roll mixer value, currently no slider (should be added for Ailerons response ?)
        roll = 127;
        // Store Roll fixed and RollDifferential values onboard
        setMixerValue(mixer, "MixerValueRoll", 100);
        setMixerValue(mixer, "RollDifferential", m_aircraft->elevonSlider3->value());

        // First Aileron (left)
        setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_SERVO);
        setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_ROLL, roll);

        // Second Aileron (right)
        channel = m_aircraft->fwAileron2ChannelBox->currentIndex() - 1;
        setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_SERVO);
        setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_ROLL, roll);
    }

    // vtail (pitch / yaw mixing)
    channel = m_aircraft->fwElevator1ChannelBox->currentIndex() - 1;
    if (channel > -1) {
        // Compute mixer absolute values
        pitch = (double)(m_aircraft->elevonSlider2->value() * 1.27);
        yaw   = (double)(m_aircraft->elevonSlider1->value() * 1.27);

        // Store sliders values onboard
        setMixerValue(mixer, "MixerValuePitch", m_aircraft->elevonSlider2->value());
        setMixerValue(mixer, "MixerValueYaw", m_aircraft->elevonSlider1->value());

        // First Vtail servo
        setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_SERVO);
        setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_PITCH, -pitch);
        setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_YAW, -yaw);

        // Second Vtail servo
        channel = m_aircraft->fwElevator2ChannelBox->currentIndex() - 1;
        setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_SERVO);
        setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_PITCH, pitch);
        setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_YAW, -yaw);
    }

    m_aircraft->fwStatusLabel->setText("Mixer generated");
    return true;
}
/**
   Setup Elevator/Aileron/Rudder airframe.

   If both Aileron channels are set to 'None' (EasyStar), do Pitch/Rudder mixing

   Returns False if impossible to create the mixer.
 */
bool ConfigFixedWingWidget::setupFrameFixedWing(QString airframeType)
{
    // Check coherence:
    // Show any config errors in GUI
    if (throwConfigError(airframeType)) {
        return false;
    }

    // Now setup the channels:
    GUIConfigDataUnion config = getConfigData();
    resetActuators(&config);

    config.fixedwing.FixedWingPitch1   = m_aircraft->fwElevator1ChannelBox->currentIndex();
    config.fixedwing.FixedWingPitch2   = m_aircraft->fwElevator2ChannelBox->currentIndex();
    config.fixedwing.FixedWingRoll1    = m_aircraft->fwAileron1ChannelBox->currentIndex();
    config.fixedwing.FixedWingRoll2    = m_aircraft->fwAileron2ChannelBox->currentIndex();
    config.fixedwing.FixedWingYaw1     = m_aircraft->fwRudder1ChannelBox->currentIndex();
    config.fixedwing.FixedWingYaw2     = m_aircraft->fwRudder2ChannelBox->currentIndex();
    config.fixedwing.FixedWingThrottle = m_aircraft->fwEngineChannelBox->currentIndex();

    setConfigData(config);

    UAVDataObject *mixer = dynamic_cast<UAVDataObject *>(getObjectManager()->getObject(QString("MixerSettings")));
    Q_ASSERT(mixer);
    resetMotorAndServoMixers(mixer);

    // ... and compute the matrix:
    // In order to make code a bit nicer, we assume:
    // - Channel dropdowns start with 'None', then 0 to 7

    // 1. Assign the servo/motor/none for each channel

    // motor
    int channel = m_aircraft->fwEngineChannelBox->currentIndex() - 1;
    setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_MOTOR);
    setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_THROTTLECURVE1, 127);

    // rudder
    channel = m_aircraft->fwRudder1ChannelBox->currentIndex() - 1;
    setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_SERVO);
    setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_YAW, -127);

    // ailerons
    setMixerValue(mixer, "FirstRollServo", m_aircraft->fwAileron1ChannelBox->currentIndex());
    channel = m_aircraft->fwAileron1ChannelBox->currentIndex() - 1;
    if (channel > -1) {
        // Store differential value onboard
        setMixerValue(mixer, "RollDifferential", m_aircraft->elevonSlider3->value());

        setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_SERVO);
        setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_ROLL, 127);

        channel = m_aircraft->fwAileron2ChannelBox->currentIndex() - 1;
        setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_SERVO);
        setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_ROLL, 127);
    }

    // elevators
    channel = m_aircraft->fwElevator1ChannelBox->currentIndex() - 1;
    if (channel > -1) {
        setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_SERVO);
        setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_PITCH, 127);

        channel = m_aircraft->fwElevator2ChannelBox->currentIndex() - 1;
        setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_SERVO);
        setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_PITCH, 127);
    }

    m_aircraft->fwStatusLabel->setText("Mixer generated");

    return true;
}
/**
 Helper function to update the UI widget objects
 */
SystemSettings::AirframeTypeOptions ConfigMultiRotorWidget::updateConfigObjectsFromWidgets()
{
    SystemSettings::AirframeTypeOptions airframeType = SystemSettings::AIRFRAMETYPE_FIXEDWING;
    QList<QString> motorList;

    MixerSettings *mixerSettings = MixerSettings::GetInstance(getObjectManager());
    Q_ASSERT(mixerSettings);

    // Curve is also common to all quads:
    setThrottleCurve(mixerSettings, MixerSettings::MIXER1VECTOR_THROTTLECURVE1, m_aircraft->multiThrottleCurve->getCurve() );

    if (m_aircraft->multirotorFrameType->itemData(m_aircraft->multirotorFrameType->currentIndex()) == SystemSettings::AIRFRAMETYPE_QUADP) {
        airframeType = SystemSettings::AIRFRAMETYPE_QUADP;
        setupQuad(true);
    } else if (m_aircraft->multirotorFrameType->itemData(m_aircraft->multirotorFrameType->currentIndex()) == SystemSettings::AIRFRAMETYPE_QUADX) {
        airframeType = SystemSettings::AIRFRAMETYPE_QUADX;
        setupQuad(false);
    } else if (m_aircraft->multirotorFrameType->itemData(m_aircraft->multirotorFrameType->currentIndex()) == SystemSettings::AIRFRAMETYPE_HEXA) {
        airframeType = SystemSettings::AIRFRAMETYPE_HEXA;
        setupHexa(true);
    } else if (m_aircraft->multirotorFrameType->itemData(m_aircraft->multirotorFrameType->currentIndex()) == SystemSettings::AIRFRAMETYPE_HEXAX) {
        airframeType = SystemSettings::AIRFRAMETYPE_HEXAX;
        setupHexa(false);
    } else if (m_aircraft->multirotorFrameType->itemData(m_aircraft->multirotorFrameType->currentIndex()) == SystemSettings::AIRFRAMETYPE_HEXACOAX) {
        airframeType = SystemSettings::AIRFRAMETYPE_HEXACOAX;

        //Show any config errors in GUI
        if (throwConfigError(6)) {
            return airframeType;
        }
        motorList << "VTOLMotorNW" << "VTOLMotorW" << "VTOLMotorNE" << "VTOLMotorE"
                  << "VTOLMotorS" << "VTOLMotorSE";
        setupMotors(motorList);

        // Motor 1 to 6, Y6 Layout:
        //     pitch   roll    yaw
        double mixer [8][3] = {
            {  0.5,  1, -1},
            {  0.5,  1,  1},
            {  0.5, -1, -1},
            {  0.5, -1,  1},
            { -1,    0, -1},
            { -1,    0,  1},
            {  0,    0,  0},
            {  0,    0,  0}
        };
        setupMultiRotorMixer(mixer);
        m_aircraft->mrStatusLabel->setText("Configuration OK");

    } else if (m_aircraft->multirotorFrameType->itemData(m_aircraft->multirotorFrameType->currentIndex()) == SystemSettings::AIRFRAMETYPE_OCTO) {
        airframeType = SystemSettings::AIRFRAMETYPE_OCTO;

        //Show any config errors in GUI
        if (throwConfigError(8)) {
            return airframeType;

        }
        motorList << "VTOLMotorN" << "VTOLMotorNE" << "VTOLMotorE" << "VTOLMotorSE"
                  << "VTOLMotorS" << "VTOLMotorSW" << "VTOLMotorW" << "VTOLMotorNW";
        setupMotors(motorList);
        // Motor 1 to 8:
        //     pitch   roll    yaw
        double mixer [8][3] = {
            {  1,  0, -1},
            {  1, -1,  1},
            {  0, -1, -1},
            { -1, -1,  1},
            { -1,  0, -1},
            { -1,  1,  1},
            {  0,  1, -1},
            {  1,  1,  1}
        };
        setupMultiRotorMixer(mixer);
        m_aircraft->mrStatusLabel->setText("Configuration OK");

    } else if (m_aircraft->multirotorFrameType->itemData(m_aircraft->multirotorFrameType->currentIndex()) == SystemSettings::AIRFRAMETYPE_OCTOV) {
        airframeType = SystemSettings::AIRFRAMETYPE_OCTOV;

        //Show any config errors in GUI
        if (throwConfigError(8)) {
            return airframeType;
        }
        motorList << "VTOLMotorN" << "VTOLMotorNE" << "VTOLMotorE" << "VTOLMotorSE"
                  << "VTOLMotorS" << "VTOLMotorSW" << "VTOLMotorW" << "VTOLMotorNW";
        setupMotors(motorList);
        // Motor 1 to 8:
        // IMPORTANT: Assumes evenly spaced engines
        //     pitch   roll    yaw
        double mixer [8][3] = {
            {  0.33, -1, -1},
            {  1   , -1,  1},
            { -1   , -1, -1},
            { -0.33, -1,  1},
            { -0.33,  1, -1},
            { -1   ,  1,  1},
            {  1   ,  1, -1},
            {  0.33,  1,  1}
        };
        setupMultiRotorMixer(mixer);
        m_aircraft->mrStatusLabel->setText("Configuration OK");

    } else if (m_aircraft->multirotorFrameType->itemData(m_aircraft->multirotorFrameType->currentIndex()) == SystemSettings::AIRFRAMETYPE_OCTOCOAXP) {
        airframeType = SystemSettings::AIRFRAMETYPE_OCTOCOAXP;

        //Show any config errors in GUI
        if (throwConfigError(8)) {
            return airframeType;
        }
        motorList << "VTOLMotorN" << "VTOLMotorNE" << "VTOLMotorE" << "VTOLMotorSE"
                  << "VTOLMotorS" << "VTOLMotorSW" << "VTOLMotorW" << "VTOLMotorNW";
        setupMotors(motorList);
        // Motor 1 to 8:
        //     pitch   roll    yaw
        double mixer [8][3] = {
            {  1,  0, -1},
            {  1,  0,  1},
            {  0, -1, -1},
            {  0, -1,  1},
            { -1,  0, -1},
            { -1,  0,  1},
            {  0,  1, -1},
            {  0,  1,  1}
        };
        setupMultiRotorMixer(mixer);
        m_aircraft->mrStatusLabel->setText("Configuration OK");

    } else if (m_aircraft->multirotorFrameType->itemData(m_aircraft->multirotorFrameType->currentIndex()) == SystemSettings::AIRFRAMETYPE_OCTOCOAXX) {
        airframeType = SystemSettings::AIRFRAMETYPE_OCTOCOAXX;

        //Show any config errors in GUI
        if (throwConfigError(8)) {
            return airframeType;
        }
        motorList << "VTOLMotorNW" << "VTOLMotorN" << "VTOLMotorNE" << "VTOLMotorE"
                  << "VTOLMotorSE" << "VTOLMotorS" << "VTOLMotorSW" << "VTOLMotorW";
        setupMotors(motorList);
        // Motor 1 to 8:
        //     pitch   roll    yaw
        double mixer [8][3] = {
            {  1,  1, -1},
            {  1,  1,  1},
            {  1, -1, -1},
            {  1, -1,  1},
            { -1, -1, -1},
            { -1, -1,  1},
            { -1,  1, -1},
            { -1,  1,  1}
        };
        setupMultiRotorMixer(mixer);
        m_aircraft->mrStatusLabel->setText("Configuration OK");

    } else if (m_aircraft->multirotorFrameType->itemData(m_aircraft->multirotorFrameType->currentIndex()) == SystemSettings::AIRFRAMETYPE_TRI) {
        airframeType = SystemSettings::AIRFRAMETYPE_TRI;

        //Show any config errors in GUI
        if (throwConfigError(3)) {
            return airframeType;

        }
        if (m_aircraft->triYawChannelBox->currentText() == "None") {
            m_aircraft->mrStatusLabel->setText("<font color='red'>Error: Assign a Yaw channel</font>");
            return airframeType;
        }
        motorList << "VTOLMotorNW" << "VTOLMotorNE" << "VTOLMotorS";
        setupMotors(motorList);

        GUIConfigDataUnion config = GetConfigData();
        config.multi.TRIYaw = m_aircraft->triYawChannelBox->currentIndex();
        SetConfigData(config);


        // Motor 1 to 6, Y6 Layout:
        //     pitch   roll    yaw
        double mixer [8][3] = {
            {  0.5,  1,  0},
            {  0.5, -1,  0},
            { -1,  0,  0},
            {  0,  0,  0},
            {  0,  0,  0},
            {  0,  0,  0},
            {  0,  0,  0},
            {  0,  0,  0}
        };
        setupMultiRotorMixer(mixer);

        //tell the mixer about tricopter yaw channel

        int channel = m_aircraft->triYawChannelBox->currentIndex()-1;
        if (channel > -1) {
            setMixerType(mixerSettings, channel, MixerSettings::MIXER1TYPE_SERVO);
            setMixerVectorValue(mixerSettings, channel, MixerSettings::MIXER1VECTOR_YAW, 127);
        }

        m_aircraft->mrStatusLabel->setText(tr("Configuration OK"));

    }

    return airframeType;
}