mirror of
https://bitbucket.org/librepilot/librepilot.git
synced 2025-03-15 07:29:15 +01:00
Merged in f5soh/librepilot/laurent/LP-66_FixedWing_Roll_differential (pull request #9)
LP-66 - Add differential Roll mixing to Fixed Wing frames
This commit is contained in:
commit
05494eebcc
@ -9,6 +9,7 @@
|
||||
*
|
||||
* @file actuator.c
|
||||
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
|
||||
* @author The LibrePilot Project, http://www.librepilot.org Copyright (C) 2015.
|
||||
* @brief Actuator module. Drives the actuators (servos, motors etc).
|
||||
*
|
||||
* @see The GNU Public License (GPL) Version 3
|
||||
@ -110,7 +111,7 @@ static void ActuatorSettingsUpdatedCb(UAVObjEvent *ev);
|
||||
static void SettingsUpdatedCb(UAVObjEvent *ev);
|
||||
float ProcessMixer(const int index, const float curve1, const float curve2,
|
||||
ActuatorDesiredData *desired,
|
||||
const float period, bool multirotor);
|
||||
const float period, bool multirotor, bool fixedwing);
|
||||
|
||||
// this structure is equivalent to the UAVObjects for one mixer.
|
||||
typedef struct {
|
||||
@ -271,6 +272,7 @@ static void actuatorTask(__attribute__((unused)) void *parameters)
|
||||
bool activeThrottle = (throttleDesired < -0.001f || throttleDesired > 0.001f); // for ground and reversible motors
|
||||
bool positiveThrottle = (throttleDesired > 0.00f);
|
||||
bool multirotor = (GetCurrentFrameType() == FRAME_TYPE_MULTIROTOR); // check if frame is a multirotor.
|
||||
bool fixedwing = (GetCurrentFrameType() == FRAME_TYPE_FIXED_WING); // check if frame is a fixedwing.
|
||||
bool alwaysArmed = settings.Arming == FLIGHTMODESETTINGS_ARMING_ALWAYSARMED;
|
||||
bool AlwaysStabilizeWhenArmed = settings.AlwaysStabilizeWhenArmed == FLIGHTMODESETTINGS_ALWAYSSTABILIZEWHENARMED_TRUE;
|
||||
|
||||
@ -406,7 +408,7 @@ static void actuatorTask(__attribute__((unused)) void *parameters)
|
||||
nonreversible_curve2 = 0.0f;
|
||||
}
|
||||
}
|
||||
status[ct] = ProcessMixer(ct, nonreversible_curve1, nonreversible_curve2, &desired, dTSeconds, multirotor);
|
||||
status[ct] = ProcessMixer(ct, nonreversible_curve1, nonreversible_curve2, &desired, dTSeconds, multirotor, fixedwing);
|
||||
// If not armed or motors aren't meant to spin all the time
|
||||
if (!armed ||
|
||||
(!spinWhileArmed && !positiveThrottle)) {
|
||||
@ -424,7 +426,7 @@ static void actuatorTask(__attribute__((unused)) void *parameters)
|
||||
}
|
||||
}
|
||||
} else if (mixer_type == MIXERSETTINGS_MIXER1TYPE_REVERSABLEMOTOR) {
|
||||
status[ct] = ProcessMixer(ct, curve1, curve2, &desired, dTSeconds, multirotor);
|
||||
status[ct] = ProcessMixer(ct, curve1, curve2, &desired, dTSeconds, multirotor, fixedwing);
|
||||
// Reversable Motors are like Motors but go to neutral instead of minimum
|
||||
// If not armed or motor is inactive - no "spinwhilearmed" for this engine type
|
||||
if (!armed || !activeThrottle) {
|
||||
@ -433,7 +435,7 @@ static void actuatorTask(__attribute__((unused)) void *parameters)
|
||||
status[ct] = 0; // force neutral throttle
|
||||
}
|
||||
} else if (mixer_type == MIXERSETTINGS_MIXER1TYPE_SERVO) {
|
||||
status[ct] = ProcessMixer(ct, curve1, curve2, &desired, dTSeconds, multirotor);
|
||||
status[ct] = ProcessMixer(ct, curve1, curve2, &desired, dTSeconds, multirotor, fixedwing);
|
||||
} else {
|
||||
status[ct] = -1;
|
||||
|
||||
@ -555,15 +557,35 @@ static void actuatorTask(__attribute__((unused)) void *parameters)
|
||||
* Process mixing for one actuator
|
||||
*/
|
||||
float ProcessMixer(const int index, const float curve1, const float curve2,
|
||||
ActuatorDesiredData *desired, const float period, bool multirotor)
|
||||
ActuatorDesiredData *desired, const float period, bool multirotor, bool fixedwing)
|
||||
{
|
||||
static float lastFilteredResult[MAX_MIX_ACTUATORS];
|
||||
const Mixer_t *mixers = (Mixer_t *)&mixerSettings.Mixer1Type; // pointer to array of mixers in UAVObjects
|
||||
const Mixer_t *mixer = &mixers[index];
|
||||
float differential = 1.0f;
|
||||
|
||||
// Apply differential only for fixedwing and Roll servos
|
||||
if (fixedwing && (mixerSettings.FirstRollServo > 0) &&
|
||||
(mixer->type == MIXERSETTINGS_MIXER1TYPE_SERVO) &&
|
||||
(mixer->matrix[MIXERSETTINGS_MIXER1VECTOR_ROLL] != 0)) {
|
||||
// Positive differential
|
||||
if (mixerSettings.RollDifferential > 0) {
|
||||
// Check for first Roll servo (should be left aileron or elevon) and Roll desired (positive/negative)
|
||||
if (((index == mixerSettings.FirstRollServo - 1) && (desired->Roll > 0.0f))
|
||||
|| ((index != mixerSettings.FirstRollServo - 1) && (desired->Roll < 0.0f))) {
|
||||
differential -= (mixerSettings.RollDifferential * 0.01f);
|
||||
}
|
||||
} else if (mixerSettings.RollDifferential < 0) {
|
||||
if (((index == mixerSettings.FirstRollServo - 1) && (desired->Roll < 0.0f))
|
||||
|| ((index != mixerSettings.FirstRollServo - 1) && (desired->Roll > 0.0f))) {
|
||||
differential -= (-mixerSettings.RollDifferential * 0.01f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
float result = ((((float)mixer->matrix[MIXERSETTINGS_MIXER1VECTOR_THROTTLECURVE1]) * curve1) +
|
||||
(((float)mixer->matrix[MIXERSETTINGS_MIXER1VECTOR_THROTTLECURVE2]) * curve2) +
|
||||
(((float)mixer->matrix[MIXERSETTINGS_MIXER1VECTOR_ROLL]) * desired->Roll) +
|
||||
(((float)mixer->matrix[MIXERSETTINGS_MIXER1VECTOR_ROLL]) * desired->Roll * differential) +
|
||||
(((float)mixer->matrix[MIXERSETTINGS_MIXER1VECTOR_PITCH]) * desired->Pitch) +
|
||||
(((float)mixer->matrix[MIXERSETTINGS_MIXER1VECTOR_YAW]) * desired->Yaw)) / 128.0f;
|
||||
|
||||
@ -575,36 +597,38 @@ float ProcessMixer(const int index, const float curve1, const float curve2,
|
||||
}
|
||||
}
|
||||
|
||||
// feed forward
|
||||
float accumulator = filterAccumulator[index];
|
||||
accumulator += (result - lastResult[index]) * mixerSettings.FeedForward;
|
||||
lastResult[index] = result;
|
||||
result += accumulator;
|
||||
if (period > 0.0f) {
|
||||
if (accumulator > 0.0f) {
|
||||
float invFilter = period / mixerSettings.AccelTime;
|
||||
if (invFilter > 1) {
|
||||
invFilter = 1;
|
||||
if (!fixedwing) {
|
||||
// feed forward, do not apply to fixedwing
|
||||
float accumulator = filterAccumulator[index];
|
||||
accumulator += (result - lastResult[index]) * mixerSettings.FeedForward;
|
||||
lastResult[index] = result;
|
||||
result += accumulator;
|
||||
if (period > 0.0f) {
|
||||
if (accumulator > 0.0f) {
|
||||
float invFilter = period / mixerSettings.AccelTime;
|
||||
if (invFilter > 1) {
|
||||
invFilter = 1;
|
||||
}
|
||||
accumulator -= accumulator * invFilter;
|
||||
} else {
|
||||
float invFilter = period / mixerSettings.DecelTime;
|
||||
if (invFilter > 1) {
|
||||
invFilter = 1;
|
||||
}
|
||||
accumulator -= accumulator * invFilter;
|
||||
}
|
||||
accumulator -= accumulator * invFilter;
|
||||
} else {
|
||||
float invFilter = period / mixerSettings.DecelTime;
|
||||
if (invFilter > 1) {
|
||||
invFilter = 1;
|
||||
}
|
||||
accumulator -= accumulator * invFilter;
|
||||
}
|
||||
}
|
||||
filterAccumulator[index] = accumulator;
|
||||
result += accumulator;
|
||||
filterAccumulator[index] = accumulator;
|
||||
result += accumulator;
|
||||
|
||||
// acceleration limit
|
||||
float dt = result - lastFilteredResult[index];
|
||||
float maxDt = mixerSettings.MaxAccel * period;
|
||||
if (dt > maxDt) { // we are accelerating too hard
|
||||
result = lastFilteredResult[index] + maxDt;
|
||||
// acceleration limit
|
||||
float dt = result - lastFilteredResult[index];
|
||||
float maxDt = mixerSettings.MaxAccel * period;
|
||||
if (dt > maxDt) { // we are accelerating too hard
|
||||
result = lastFilteredResult[index] + maxDt;
|
||||
}
|
||||
lastFilteredResult[index] = result;
|
||||
}
|
||||
lastFilteredResult[index] = result;
|
||||
}
|
||||
|
||||
return result;
|
||||
|
@ -222,7 +222,7 @@ margin:1px;</string>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>50</width>
|
||||
<width>65</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
@ -290,7 +290,7 @@ margin:1px;</string>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>50</width>
|
||||
<width>65</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
@ -326,6 +326,77 @@ margin:1px;</string>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="0" column="2">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||
<item>
|
||||
<widget class="QLabel" name="elevonLabel3">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>50</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">background-color: qlineargradient(spread:reflect, x1:0.507, y1:0, x2:0.507, y2:0.772, stop:0.208955 rgba(74, 74, 74, 255), stop:0.78607 rgba(36, 36, 36, 255));
|
||||
color: rgb(255, 255, 255);
|
||||
border-radius: 5;
|
||||
font: bold 12px;
|
||||
margin:1px;</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string> Roll Diff</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSlider" name="elevonSlider3">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>65</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Value of Roll differential in percent</string>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>-100</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>100</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="elevonSliderLabel3">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>0</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
@ -735,5 +806,21 @@ margin:1px;</string>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>elevonSlider3</sender>
|
||||
<signal>valueChanged(int)</signal>
|
||||
<receiver>elevonSliderLabel3</receiver>
|
||||
<slot>setNum(int)</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>511</x>
|
||||
<y>222</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>511</x>
|
||||
<y>378</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
||||
|
@ -3,6 +3,7 @@
|
||||
*
|
||||
* @file configfixedwingwidget.cpp
|
||||
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2012.
|
||||
* @author The LibrePilot Project, http://www.librepilot.org Copyright (C) 2015.
|
||||
* @addtogroup GCSPlugins GCS Plugins
|
||||
* @{
|
||||
* @addtogroup ConfigPlugin Config Plugin
|
||||
@ -136,9 +137,17 @@ void ConfigFixedWingWidget::setupUI(QString frameType)
|
||||
|
||||
m_aircraft->elevonSlider1->setEnabled(false);
|
||||
m_aircraft->elevonSlider2->setEnabled(false);
|
||||
m_aircraft->elevonSlider3->setEnabled(true);
|
||||
|
||||
m_aircraft->elevonSlider1->setValue(100);
|
||||
m_aircraft->elevonSlider2->setValue(100);
|
||||
|
||||
// Get values saved if frameType = current frameType set on board
|
||||
if (field->getValue().toString() == "FixedWing") {
|
||||
m_aircraft->elevonSlider3->setValue(getMixerValue(mixer, "RollDifferential"));
|
||||
} else {
|
||||
m_aircraft->elevonSlider3->setValue(0);
|
||||
}
|
||||
} else if (frameType == "FixedWingElevon" || frameType == "Elevon") {
|
||||
planeimg->setElementId("elevon");
|
||||
setComboCurrentIndex(m_aircraft->fixedWingType, m_aircraft->fixedWingType->findText("Elevon"));
|
||||
@ -157,22 +166,27 @@ void ConfigFixedWingWidget::setupUI(QString frameType)
|
||||
|
||||
m_aircraft->elevonSlider1->setEnabled(true);
|
||||
m_aircraft->elevonSlider2->setEnabled(true);
|
||||
m_aircraft->elevonSlider3->setEnabled(true);
|
||||
|
||||
// Get values saved if frameType = current frameType set on board
|
||||
if (field->getValue().toString() == "FixedWingElevon") {
|
||||
m_aircraft->elevonSlider1->setValue(getMixerValue(mixer, "MixerValueRoll"));
|
||||
m_aircraft->elevonSlider2->setValue(getMixerValue(mixer, "MixerValuePitch"));
|
||||
m_aircraft->elevonSlider3->setValue(getMixerValue(mixer, "RollDifferential"));
|
||||
} else {
|
||||
m_aircraft->elevonSlider1->setValue(100);
|
||||
m_aircraft->elevonSlider2->setValue(100);
|
||||
m_aircraft->elevonSlider3->setValue(0);
|
||||
}
|
||||
} else if (frameType == "FixedWingVtail" || frameType == "Vtail") {
|
||||
planeimg->setElementId("vtail");
|
||||
setComboCurrentIndex(m_aircraft->fixedWingType, m_aircraft->fixedWingType->findText("Vtail"));
|
||||
m_aircraft->fwRudder1ChannelBox->setEnabled(false);
|
||||
m_aircraft->fwRudder1ChannelBox->setCurrentText("None");
|
||||
m_aircraft->fwRudder1ChannelBox->setToolTip("");
|
||||
m_aircraft->fwRudder2ChannelBox->setEnabled(false);
|
||||
m_aircraft->fwRudder2ChannelBox->setCurrentText("None");
|
||||
m_aircraft->fwRudder2ChannelBox->setToolTip("");
|
||||
|
||||
m_aircraft->fwElevator1Label->setText("Vtail 1");
|
||||
m_aircraft->fwElevator1ChannelBox->setEnabled(true);
|
||||
@ -187,14 +201,17 @@ void ConfigFixedWingWidget::setupUI(QString frameType)
|
||||
|
||||
m_aircraft->elevonSlider1->setEnabled(true);
|
||||
m_aircraft->elevonSlider2->setEnabled(true);
|
||||
m_aircraft->elevonSlider3->setEnabled(true);
|
||||
|
||||
// Get values saved if frameType = current frameType set on board
|
||||
if (field->getValue().toString() == "FixedWingVtail") {
|
||||
m_aircraft->elevonSlider1->setValue(getMixerValue(mixer, "MixerValueYaw"));
|
||||
m_aircraft->elevonSlider2->setValue(getMixerValue(mixer, "MixerValuePitch"));
|
||||
m_aircraft->elevonSlider3->setValue(getMixerValue(mixer, "RollDifferential"));
|
||||
} else {
|
||||
m_aircraft->elevonSlider1->setValue(100);
|
||||
m_aircraft->elevonSlider2->setValue(100);
|
||||
m_aircraft->elevonSlider3->setValue(0);
|
||||
}
|
||||
}
|
||||
|
||||
@ -220,6 +237,7 @@ void ConfigFixedWingWidget::registerWidgets(ConfigTaskWidget &parent)
|
||||
parent.addWidget(m_aircraft->fwRudder2ChannelBox);
|
||||
parent.addWidget(m_aircraft->elevonSlider1);
|
||||
parent.addWidget(m_aircraft->elevonSlider2);
|
||||
parent.addWidget(m_aircraft->elevonSlider3);
|
||||
}
|
||||
|
||||
void ConfigFixedWingWidget::resetActuators(GUIConfigDataUnion *configData)
|
||||
@ -270,6 +288,7 @@ void ConfigFixedWingWidget::refreshWidgetsValues(QString frameType)
|
||||
setComboCurrentIndex(m_aircraft->fwRudder2ChannelBox, fixed.FixedWingYaw2);
|
||||
|
||||
// Get mixing values for GUI sliders (values stored onboard)
|
||||
m_aircraft->elevonSlider3->setValue(getMixerValue(mixer, "RollDifferential"));
|
||||
if (frameType == "FixedWingElevon" || frameType == "Elevon") {
|
||||
m_aircraft->elevonSlider1->setValue(getMixerValue(mixer, "MixerValueRoll"));
|
||||
m_aircraft->elevonSlider2->setValue(getMixerValue(mixer, "MixerValuePitch"));
|
||||
@ -336,6 +355,7 @@ bool ConfigFixedWingWidget::setupFrameFixedWing(QString airframeType)
|
||||
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);
|
||||
@ -361,8 +381,12 @@ bool ConfigFixedWingWidget::setupFrameFixedWing(QString airframeType)
|
||||
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);
|
||||
|
||||
@ -442,6 +466,7 @@ bool ConfigFixedWingWidget::setupFrameElevon(QString airframeType)
|
||||
setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_YAW, -yaw);
|
||||
|
||||
// ailerons
|
||||
setMixerValue(mixer, "FirstRollServo", m_aircraft->fwAileron1ChannelBox->currentIndex());
|
||||
channel = m_aircraft->fwAileron1ChannelBox->currentIndex() - 1;
|
||||
if (channel > -1) {
|
||||
// Compute mixer absolute values
|
||||
@ -449,6 +474,7 @@ bool ConfigFixedWingWidget::setupFrameElevon(QString airframeType)
|
||||
roll = (double)(m_aircraft->elevonSlider1->value() * 1.27);
|
||||
|
||||
// Store sliders values onboard
|
||||
setMixerValue(mixer, "RollDifferential", m_aircraft->elevonSlider3->value());
|
||||
setMixerValue(mixer, "MixerValuePitch", m_aircraft->elevonSlider2->value());
|
||||
setMixerValue(mixer, "MixerValueRoll", m_aircraft->elevonSlider1->value());
|
||||
|
||||
@ -511,12 +537,14 @@ bool ConfigFixedWingWidget::setupFrameVtail(QString airframeType)
|
||||
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 value onboard
|
||||
// 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);
|
||||
@ -572,85 +600,57 @@ bool ConfigFixedWingWidget::throwConfigError(QString airframeType)
|
||||
// Initialize configuration error flag
|
||||
bool error = false;
|
||||
|
||||
// Create a red block. All combo boxes are the same size, so any one should do as a model
|
||||
int size = m_aircraft->fwEngineChannelBox->style()->pixelMetric(QStyle::PM_SmallIconSize);
|
||||
QPixmap pixmap(size, size);
|
||||
QList<QComboBox *> comboChannelsName;
|
||||
comboChannelsName << m_aircraft->fwEngineChannelBox
|
||||
<< m_aircraft->fwAileron1ChannelBox << m_aircraft->fwAileron2ChannelBox
|
||||
<< m_aircraft->fwElevator1ChannelBox << m_aircraft->fwElevator2ChannelBox
|
||||
<< m_aircraft->fwRudder1ChannelBox << m_aircraft->fwRudder2ChannelBox;
|
||||
QString channelNames = "";
|
||||
|
||||
pixmap.fill(QColor("red"));
|
||||
|
||||
if (airframeType == "FixedWing") {
|
||||
if (m_aircraft->fwEngineChannelBox->currentText() == "None") {
|
||||
m_aircraft->fwEngineChannelBox->setItemData(0, pixmap, Qt::DecorationRole); // Set color palettes
|
||||
error = true;
|
||||
} else {
|
||||
m_aircraft->fwEngineChannelBox->setItemData(0, 0, Qt::DecorationRole); // Reset color palettes
|
||||
}
|
||||
|
||||
if (m_aircraft->fwElevator1ChannelBox->currentText() == "None") {
|
||||
m_aircraft->fwElevator1ChannelBox->setItemData(0, pixmap, Qt::DecorationRole); // Set color palettes
|
||||
error = true;
|
||||
} else {
|
||||
m_aircraft->fwElevator1ChannelBox->setItemData(0, 0, Qt::DecorationRole); // Reset color palettes
|
||||
}
|
||||
|
||||
if ((m_aircraft->fwAileron1ChannelBox->currentText() == "None")
|
||||
&& (m_aircraft->fwRudder1ChannelBox->currentText() == "None")) {
|
||||
pixmap.fill(QColor("green"));
|
||||
m_aircraft->fwAileron1ChannelBox->setItemData(0, pixmap, Qt::DecorationRole); // Set color palettes
|
||||
m_aircraft->fwRudder1ChannelBox->setItemData(0, pixmap, Qt::DecorationRole); // Set color palettes
|
||||
error = true;
|
||||
} else {
|
||||
m_aircraft->fwAileron1ChannelBox->setItemData(0, 0, Qt::DecorationRole); // Reset color palettes
|
||||
m_aircraft->fwRudder1ChannelBox->setItemData(0, 0, Qt::DecorationRole); // Reset color palettes
|
||||
}
|
||||
} else if (airframeType == "FixedWingElevon") {
|
||||
if (m_aircraft->fwEngineChannelBox->currentText() == "None") {
|
||||
m_aircraft->fwEngineChannelBox->setItemData(0, pixmap, Qt::DecorationRole); // Set color palettes
|
||||
error = true;
|
||||
} else {
|
||||
m_aircraft->fwEngineChannelBox->setItemData(0, 0, Qt::DecorationRole); // Reset color palettes
|
||||
}
|
||||
|
||||
if (m_aircraft->fwAileron1ChannelBox->currentText() == "None") {
|
||||
m_aircraft->fwAileron1ChannelBox->setItemData(0, pixmap, Qt::DecorationRole); // Set color palettes
|
||||
error = true;
|
||||
} else {
|
||||
m_aircraft->fwAileron1ChannelBox->setItemData(0, 0, Qt::DecorationRole); // Reset color palettes
|
||||
}
|
||||
|
||||
if (m_aircraft->fwAileron2ChannelBox->currentText() == "None") {
|
||||
m_aircraft->fwAileron2ChannelBox->setItemData(0, pixmap, Qt::DecorationRole); // Set color palettes
|
||||
error = true;
|
||||
} else {
|
||||
m_aircraft->fwAileron2ChannelBox->setItemData(0, 0, Qt::DecorationRole); // Reset color palettes
|
||||
}
|
||||
} else if (airframeType == "FixedWingVtail") {
|
||||
if (m_aircraft->fwEngineChannelBox->currentText() == "None") {
|
||||
m_aircraft->fwEngineChannelBox->setItemData(0, pixmap, Qt::DecorationRole); // Set color palettes
|
||||
error = true;
|
||||
} else {
|
||||
m_aircraft->fwEngineChannelBox->setItemData(0, 0, Qt::DecorationRole); // Reset color palettes
|
||||
}
|
||||
|
||||
if (m_aircraft->fwElevator1ChannelBox->currentText() == "None") {
|
||||
m_aircraft->fwElevator1ChannelBox->setItemData(0, pixmap, Qt::DecorationRole); // Set color palettes
|
||||
error = true;
|
||||
} else {
|
||||
m_aircraft->fwElevator1ChannelBox->setItemData(0, 0, Qt::DecorationRole); // Reset color palettes
|
||||
}
|
||||
|
||||
if (m_aircraft->fwElevator2ChannelBox->currentText() == "None") {
|
||||
m_aircraft->fwElevator2ChannelBox->setItemData(0, pixmap, Qt::DecorationRole); // Set color palettes
|
||||
error = true;
|
||||
} else {
|
||||
m_aircraft->fwElevator2ChannelBox->setItemData(0, 0, Qt::DecorationRole); // Reset color palettes
|
||||
for (int i = 0; i < 7; i++) {
|
||||
QComboBox *combobox = comboChannelsName[i];
|
||||
if (combobox && (combobox->isEnabled())) {
|
||||
if (combobox->currentText() == "None") {
|
||||
int size = combobox->style()->pixelMetric(QStyle::PM_SmallIconSize);
|
||||
QPixmap pixmap(size, size);
|
||||
if ((airframeType == "FixedWingElevon") && (i > 2)) {
|
||||
pixmap.fill(QColor("green"));
|
||||
// Rudders are optional for elevon frame
|
||||
combobox->setToolTip(tr("Rudders are optional for Elevon frame"));
|
||||
} else if (((airframeType == "FixedWing") || (airframeType == "FixedWingVtail")) && (i == 2)) {
|
||||
pixmap.fill(QColor("green"));
|
||||
// Second aileron servo is optional for FixedWing frame
|
||||
combobox->setToolTip(tr("Second aileron servo is optional"));
|
||||
} else if ((airframeType == "FixedWing") && (i > 3)) {
|
||||
pixmap.fill(QColor("green"));
|
||||
// Second elevator and rudders are optional for FixedWing frame
|
||||
combobox->setToolTip(tr("Second elevator servo is optional"));
|
||||
if (i > 4) {
|
||||
combobox->setToolTip(tr("Rudder is highly recommended for fixed wing."));
|
||||
}
|
||||
} else {
|
||||
pixmap.fill(QColor("red"));
|
||||
combobox->setToolTip(tr("Please assign Channel"));
|
||||
m_aircraft->fwStatusLabel->setText(tr("<font color='red'>ERROR: Assign all necessary channels</font>"));
|
||||
error = true;
|
||||
}
|
||||
combobox->setItemData(0, pixmap, Qt::DecorationRole); // Set color palettes
|
||||
} else if (channelNames.contains(combobox->currentText(), Qt::CaseInsensitive)) {
|
||||
int size = combobox->style()->pixelMetric(QStyle::PM_SmallIconSize);
|
||||
QPixmap pixmap(size, size);
|
||||
pixmap.fill(QColor("orange"));
|
||||
combobox->setItemData(combobox->currentIndex(), pixmap, Qt::DecorationRole); // Set color palettes
|
||||
combobox->setToolTip(tr("Channel already used"));
|
||||
error = true;
|
||||
} else {
|
||||
for (int index = 0; index < (int)ConfigFixedWingWidget::CHANNEL_NUMELEM; index++) {
|
||||
combobox->setItemData(index, 0, Qt::DecorationRole); // Reset all color palettes
|
||||
combobox->setToolTip("");
|
||||
}
|
||||
}
|
||||
channelNames += (combobox->currentText() == "None") ? "" : combobox->currentText();
|
||||
}
|
||||
}
|
||||
|
||||
if (error) {
|
||||
m_aircraft->fwStatusLabel->setText(QString("<font color='red'>ERROR: Assign all necessary channels</font>"));
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
|
@ -5,6 +5,8 @@
|
||||
<field name="MixerValueRoll" units="percent" type="int8" elements="1" defaultvalue="50"/>
|
||||
<field name="MixerValuePitch" units="percent" type="int8" elements="1" defaultvalue="50"/>
|
||||
<field name="MixerValueYaw" units="percent" type="int8" elements="1" defaultvalue="50"/>
|
||||
<field name="RollDifferential" units="percent" type="int8" elements="1" defaultvalue="0"/>
|
||||
<field name="FirstRollServo" units="" type="uint8" elements="1" defaultvalue="0"/>
|
||||
<field name="FeedForward" units="" type="float" elements="1" defaultvalue="0"/>
|
||||
<field name="AccelTime" units="ms" type="float" elements="1" defaultvalue="0"/>
|
||||
<field name="DecelTime" units="ms" type="float" elements="1" defaultvalue="0"/>
|
||||
|
Loading…
x
Reference in New Issue
Block a user