mirror of
https://bitbucket.org/librepilot/librepilot.git
synced 2025-02-20 10:54:14 +01:00
OP-138 Start of the new Mixer configuration interface, for fixed wing only. This does not work yet, takes a long time to fully implement.
The system settings UAVObject is updated, you will have to recompile your firmware. If you want to take a look and let me know, please do! git-svn-id: svn://svn.openpilot.org/OpenPilot/trunk@1737 ebee16cc-31ac-478f-84a7-5cbb03baadba
This commit is contained in:
parent
fa4818542e
commit
eedf85a5ac
@ -78,7 +78,7 @@ typedef struct {
|
||||
// Field information
|
||||
// Field AirframeType information
|
||||
/* Enumeration options for field AirframeType */
|
||||
typedef enum { SYSTEMSETTINGS_AIRFRAMETYPE_FIXEDWING=0, SYSTEMSETTINGS_AIRFRAMETYPE_FIXEDWINGELEVON=1, SYSTEMSETTINGS_AIRFRAMETYPE_VTOL=2, SYSTEMSETTINGS_AIRFRAMETYPE_HELICP=3 } SystemSettingsAirframeTypeOptions;
|
||||
typedef enum { SYSTEMSETTINGS_AIRFRAMETYPE_FIXEDWING=0, SYSTEMSETTINGS_AIRFRAMETYPE_FIXEDWINGELEVON=1, SYSTEMSETTINGS_AIRFRAMETYPE_FIXEDWINGVTAIL=2, SYSTEMSETTINGS_AIRFRAMETYPE_VTOL=3, SYSTEMSETTINGS_AIRFRAMETYPE_HELICP=4, SYSTEMSETTINGS_AIRFRAMETYPE_QUADX=5, SYSTEMSETTINGS_AIRFRAMETYPE_QUADP=6, SYSTEMSETTINGS_AIRFRAMETYPE_HEXA=7, SYSTEMSETTINGS_AIRFRAMETYPE_OCTO=8, SYSTEMSETTINGS_AIRFRAMETYPE_CUSTOM=9 } SystemSettingsAirframeTypeOptions;
|
||||
|
||||
|
||||
// Generic interface functions
|
||||
|
@ -69,7 +69,7 @@
|
||||
<item>
|
||||
<widget class="QStackedWidget" name="stackedWidget">
|
||||
<property name="currentIndex">
|
||||
<number>0</number>
|
||||
<number>3</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="fixedWing">
|
||||
<property name="enabled">
|
||||
@ -78,14 +78,7 @@
|
||||
<property name="autoFillBackground">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3" stretch="0,1">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>Fixed Wing</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3" stretch="0">
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_6">
|
||||
<item>
|
||||
@ -99,12 +92,12 @@
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Airframe type:</string>
|
||||
<string>Airplane type:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="comboBox"/>
|
||||
<widget class="QComboBox" name="fixedWingType"/>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_3">
|
||||
@ -121,6 +114,136 @@
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_7">
|
||||
<property name="text">
|
||||
<string>Channel Assignment</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_4">
|
||||
<item>
|
||||
<layout class="QFormLayout" name="formLayout">
|
||||
<property name="fieldGrowthPolicy">
|
||||
<enum>QFormLayout::AllNonFixedFieldsGrow</enum>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="fwEngineLabel">
|
||||
<property name="text">
|
||||
<string>Engine</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QComboBox" name="fwEngineChannel"/>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="fwAileron1Label">
|
||||
<property name="text">
|
||||
<string>Aileron 1</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QComboBox" name="fwAileron1Channel"/>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="fwAileron2Label">
|
||||
<property name="text">
|
||||
<string>Aileron 2</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="fwElevator1Label">
|
||||
<property name="text">
|
||||
<string>Elevator 1</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QComboBox" name="fwElevator1Channel"/>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<widget class="QLabel" name="fwRudderLabel">
|
||||
<property name="text">
|
||||
<string>Rudder</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="1">
|
||||
<widget class="QComboBox" name="fwRudderChannel"/>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QComboBox" name="fwAileron2Channel"/>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="fwElevator2Label">
|
||||
<property name="text">
|
||||
<string>Elevator 2</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<widget class="QComboBox" name="fwElevator2Channel"/>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_4">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_7">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_13">
|
||||
<property name="text">
|
||||
<string>Throttle Curve</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="MixerCurveWidget" name="fixedWingThrottle" native="true">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>100</width>
|
||||
<height>100</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>250</width>
|
||||
<height>250</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="sizeIncrement">
|
||||
<size>
|
||||
<width>10</width>
|
||||
<height>10</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
@ -148,7 +271,55 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QFormLayout" name="formLayout_2"/>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_8">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_5">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_15">
|
||||
<property name="text">
|
||||
<string>Frame type:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="multirotorFrameType"/>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_5">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_14">
|
||||
<property name="text">
|
||||
<string>TextLabel</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
@ -174,6 +345,17 @@
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="custom">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_9">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>Custom / Advanced setup UI</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
@ -228,6 +410,14 @@
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>MixerCurveWidget</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>mixercurvewidget.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
|
@ -41,25 +41,46 @@ ConfigAirframeWidget::ConfigAirframeWidget(QWidget *parent) : ConfigTaskWidget(p
|
||||
m_aircraft->setupUi(this);
|
||||
|
||||
// Now connect the widget to the ManualControlCommand / Channel UAVObject
|
||||
ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance();
|
||||
/*
|
||||
ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance();
|
||||
UAVObjectManager *objManager = pm->getObject<UAVObjectManager>();
|
||||
|
||||
/*
|
||||
UAVObject *obj = dynamic_cast<UAVDataObject*>(objManager->getObject(QString("SystemSettings")));
|
||||
UAVObject *obj = dynamic_cast<UAVDataObject*>(objManager->getObject(QString("SystemSettings")));
|
||||
QString fieldName = QString("AirframeType");
|
||||
UAVObjectField *field = obj->getField(fieldName);
|
||||
m_aircraft->aircraftType->addItems(field->getOptions());
|
||||
*/
|
||||
QStringList airframeTypes;
|
||||
airframeTypes << "Fixed Wing" << "Multirotor" << "Helicopter";
|
||||
airframeTypes << "Fixed Wing" << "Multirotor" << "Helicopter" << "Custom";
|
||||
m_aircraft->aircraftType->addItems(airframeTypes);
|
||||
m_aircraft->aircraftType->setCurrentIndex(1);
|
||||
|
||||
QStringList fixedWingTypes;
|
||||
fixedWingTypes << "Elevator aileron rudder" << "Elevon" << "Vtail";
|
||||
m_aircraft->fixedWingType->addItems(fixedWingTypes);
|
||||
|
||||
QStringList multiRotorTypes;
|
||||
multiRotorTypes << "Quad +" << "Quad X" << "Hexacopter" << "Octocopter";
|
||||
m_aircraft->multirotorFrameType->addItems(multiRotorTypes);
|
||||
|
||||
QStringList channels;
|
||||
channels << "None" << "Channel0" << "Channel1" << "Channel2" <<
|
||||
"Channel3" << "Channel4" << "Channel5" << "Channel6" << "Channel7";
|
||||
// Now load all the channel assignements for fixed wing
|
||||
m_aircraft->fwElevator1Channel->addItems(channels);
|
||||
m_aircraft->fwElevator2Channel->addItems(channels);
|
||||
m_aircraft->fwEngineChannel->addItems(channels);
|
||||
m_aircraft->fwRudderChannel->addItems(channels);
|
||||
m_aircraft->fwAileron1Channel->addItems(channels);
|
||||
m_aircraft->fwAileron2Channel->addItems(channels);
|
||||
|
||||
|
||||
|
||||
requestAircraftUpdate();
|
||||
connect(m_aircraft->saveAircraftToSD, SIGNAL(clicked()), this, SLOT(saveAircraftUpdate()));
|
||||
connect(m_aircraft->saveAircraftToRAM, SIGNAL(clicked()), this, SLOT(sendAircraftUpdate()));
|
||||
connect(m_aircraft->getAircraftCurrent, SIGNAL(clicked()), this, SLOT(requestAircraftUpdate()));
|
||||
connect(m_aircraft->fixedWingType, SIGNAL(currentIndexChanged(QString)), this, SLOT(setupAirframeUI(QString)));
|
||||
|
||||
connect(parent, SIGNAL(autopilotConnected()),this, SLOT(requestAircraftUpdate()));
|
||||
|
||||
@ -87,10 +108,207 @@ void ConfigAirframeWidget::requestAircraftUpdate()
|
||||
Q_ASSERT(obj);
|
||||
obj->requestUpdate();
|
||||
UAVObjectField *field = obj->getField(QString("AirframeType"));
|
||||
m_aircraft->aircraftType->setCurrentIndex(m_aircraft->aircraftType->findText(field->getValue().toString()));
|
||||
Q_ASSERT(field);
|
||||
// m_aircraft->aircraftType->setCurrentIndex(m_aircraft->aircraftType->findText(field->getValue().toString()));
|
||||
// At this stage, we will need to have some hardcoded settings in this code, this
|
||||
// is not ideal, but here you go.
|
||||
QString frameType = field->getValue().toString();
|
||||
setupAirframeUI(frameType);
|
||||
|
||||
// Load the throttle curve for fixed wing frames:
|
||||
if (frameType.startsWith("FixedWing")) {
|
||||
obj = dynamic_cast<UAVDataObject*>(objManager->getObject(QString("MixerSettings")));
|
||||
Q_ASSERT(obj);
|
||||
obj->requestUpdate();
|
||||
field = obj->getField(QString("ThrottleCurve1"));
|
||||
Q_ASSERT(field);
|
||||
QList<double> curveValues;
|
||||
// If the 1st element of the curve is <= -10, then the curve
|
||||
// is a straight line (that's how the mixer works on the mainboard):
|
||||
if (field->getValue(0).toInt() <= -10) {
|
||||
for (double i=0; i<field->getNumElements(); i++) {
|
||||
curveValues.append(-1.0 + 2*i/(field->getNumElements()-1));
|
||||
}
|
||||
} else {
|
||||
for (unsigned int i=0; i < field->getNumElements(); i++) {
|
||||
curveValues.append(field->getValue(i).toDouble());
|
||||
}
|
||||
}
|
||||
m_aircraft->fixedWingThrottle->initCurve(curveValues);
|
||||
// Then retrieve how channels are setup
|
||||
obj = dynamic_cast<UAVDataObject*>(objManager->getObject(QString("ActuatorSettings")));
|
||||
Q_ASSERT(obj);
|
||||
field = obj->getField(QString("FixedWingThrottle"));
|
||||
Q_ASSERT(field);
|
||||
m_aircraft->fwEngineChannel->setCurrentIndex(m_aircraft->fwEngineChannel->findText(field->getValue().toString()));
|
||||
field = obj->getField(QString("FixedWingRoll1"));
|
||||
Q_ASSERT(field);
|
||||
m_aircraft->fwAileron1Channel->setCurrentIndex(m_aircraft->fwAileron1Channel->findText(field->getValue().toString()));
|
||||
field = obj->getField(QString("FixedWingRoll2"));
|
||||
Q_ASSERT(field);
|
||||
m_aircraft->fwAileron2Channel->setCurrentIndex(m_aircraft->fwAileron2Channel->findText(field->getValue().toString()));
|
||||
field = obj->getField(QString("FixedWingPitch1"));
|
||||
Q_ASSERT(field);
|
||||
m_aircraft->fwElevator1Channel->setCurrentIndex(m_aircraft->fwElevator1Channel->findText(field->getValue().toString()));
|
||||
field = obj->getField(QString("FixedWingPitch2"));
|
||||
Q_ASSERT(field);
|
||||
m_aircraft->fwElevator2Channel->setCurrentIndex(m_aircraft->fwElevator2Channel->findText(field->getValue().toString()));
|
||||
field = obj->getField(QString("FixedWingYaw"));
|
||||
Q_ASSERT(field);
|
||||
m_aircraft->fwRudderChannel->setCurrentIndex(m_aircraft->fwRudderChannel->findText(field->getValue().toString()));
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Sets up the mixer depending on Airframe type. Accepts either system settings or
|
||||
combo box entry from airframe type, as those do not overlap.
|
||||
*/
|
||||
void ConfigAirframeWidget::setupAirframeUI(QString frameType)
|
||||
{
|
||||
if (frameType == "FixedWing" || frameType == "Elevator aileron rudder") {
|
||||
// Setup the UI
|
||||
m_aircraft->aircraftType->setCurrentIndex(m_aircraft->aircraftType->findText("Fixed Wing"));
|
||||
m_aircraft->fixedWingType->setCurrentIndex(m_aircraft->fixedWingType->findText("Elevator aileron rudder"));
|
||||
m_aircraft->fwRudderChannel->setEnabled(true);
|
||||
m_aircraft->fwRudderLabel->setEnabled(true);
|
||||
m_aircraft->fwElevator1Channel->setEnabled(true);
|
||||
m_aircraft->fwElevator1Label->setEnabled(true);
|
||||
m_aircraft->fwElevator2Channel->setEnabled(true);
|
||||
m_aircraft->fwElevator2Label->setEnabled(true);
|
||||
|
||||
} else if (frameType == "FixedWingElevon" || frameType == "Elevon") {
|
||||
m_aircraft->aircraftType->setCurrentIndex(m_aircraft->aircraftType->findText("Fixed Wing"));
|
||||
m_aircraft->fixedWingType->setCurrentIndex(m_aircraft->fixedWingType->findText("Elevon"));
|
||||
m_aircraft->fwElevator1Channel->setEnabled(false);
|
||||
m_aircraft->fwElevator1Label->setEnabled(false);
|
||||
m_aircraft->fwElevator2Channel->setEnabled(false);
|
||||
m_aircraft->fwElevator2Label->setEnabled(false);
|
||||
m_aircraft->fwRudderChannel->setEnabled(true);
|
||||
m_aircraft->fwRudderLabel->setEnabled(true);
|
||||
|
||||
} else if (frameType == "FixedWingVtail" || frameType == "Vtail") {
|
||||
m_aircraft->aircraftType->setCurrentIndex(m_aircraft->aircraftType->findText("Fixed Wing"));
|
||||
m_aircraft->fixedWingType->setCurrentIndex(m_aircraft->fixedWingType->findText("Vtail"));
|
||||
m_aircraft->fwRudderChannel->setEnabled(false);
|
||||
m_aircraft->fwRudderLabel->setEnabled(false);
|
||||
m_aircraft->fwElevator1Channel->setEnabled(true);
|
||||
m_aircraft->fwElevator1Label->setEnabled(true);
|
||||
m_aircraft->fwElevator2Channel->setEnabled(true);
|
||||
m_aircraft->fwElevator2Label->setEnabled(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 ConfigAirframeWidget::setupFrameFixedWing()
|
||||
{
|
||||
// Check coherence:
|
||||
// - At least Pitch and either Roll or Yaw
|
||||
if (m_aircraft->fwElevator1Channel->currentText() == "None" ||
|
||||
((m_aircraft->fwAileron1Channel->currentText() == "None") &&
|
||||
(m_aircraft->fwRudderChannel->currentText() == "None"))) {
|
||||
// TODO: explain the problem in the UI
|
||||
return false;
|
||||
}
|
||||
// Now setup the channels:
|
||||
UAVDataObject* obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("ActuatorSettings")));
|
||||
Q_ASSERT(obj);
|
||||
QList<UAVObjectField*> fieldList = obj->getFields();
|
||||
foreach (UAVObjectField* field, fieldList) {
|
||||
// NOTE: we assume that all options in ActuatorSettings are a channel assignement
|
||||
// except for the options called "ChannelXXX"
|
||||
if (field->getUnits().contains("channel")) {
|
||||
field->setValue(field->getOptions().last());
|
||||
}
|
||||
}
|
||||
// Elevator
|
||||
UAVObjectField *field = obj->getField("FixedWingPitch1");
|
||||
Q_ASSERT(field);
|
||||
field->setValue(m_aircraft->fwElevator1Channel->currentText());
|
||||
field = obj->getField("FixedWingPitch2");
|
||||
Q_ASSERT(field);
|
||||
field->setValue(m_aircraft->fwElevator2Channel->currentText());
|
||||
// Aileron
|
||||
field = obj->getField("FixedWingRoll1");
|
||||
Q_ASSERT(field);
|
||||
field->setValue(m_aircraft->fwAileron1Channel->currentText());
|
||||
field = obj->getField("FixedWingRoll2");
|
||||
Q_ASSERT(field);
|
||||
field->setValue(m_aircraft->fwAileron2Channel->currentText());
|
||||
// Rudder
|
||||
field = obj->getField("FixedWingYaw");
|
||||
Q_ASSERT(field);
|
||||
field->setValue(m_aircraft->fwRudderChannel->currentText());
|
||||
// Throttle
|
||||
field = obj->getField("FixedWingThrottle");
|
||||
Q_ASSERT(field);
|
||||
field->setValue(m_aircraft->fwEngineChannel->currentText());
|
||||
|
||||
obj->updated();
|
||||
|
||||
// Save the curve:
|
||||
obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
|
||||
Q_ASSERT(obj);
|
||||
field = obj->getField("ThrottleCurve1");
|
||||
QList<double> curve = m_aircraft->fixedWingThrottle->getCurve();
|
||||
for (int i=0;i<curve.length();i++) {
|
||||
field->setValue(curve.at(i),i);
|
||||
}
|
||||
|
||||
// ... 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
|
||||
QStringList mixerTypes;
|
||||
mixerTypes << "Mixer0Type" << "Mixer1Type" << "Mixer2Type" << "Mixer3Type"
|
||||
<< "Mixer4Type" << "Mixer5Type" << "Mixer6Type" << "Mixer7Type";
|
||||
QStringList mixerVectors;
|
||||
mixerVectors << "Mixer0Vector" << "Mixer1Vector" << "Mixer2Vector" << "Mixer3Vector"
|
||||
<< "Mixer4Vector" << "Mixer5Vector" << "Mixer6Vector" << "Mixer7Vector";
|
||||
// Disable all
|
||||
foreach(QString mixer, mixerTypes) {
|
||||
field = obj->getField(mixer);
|
||||
Q_ASSERT(field);
|
||||
field->setValue("Disabled");
|
||||
}
|
||||
// and set only the relevant channels:
|
||||
// Engine
|
||||
int eng = m_aircraft->fwEngineChannel->currentIndex()-1;
|
||||
field = obj->getField(mixerTypes.at(eng));
|
||||
field->setValue("Motor");
|
||||
field = obj->getField(mixerVectors.at(eng));
|
||||
// First of all reset the vector
|
||||
for (int i=0;i<field->getNumElements();i++) {
|
||||
field->setValue(0,i);
|
||||
}
|
||||
int ti = field->getElementNames().indexOf("ThrottleCurve1");
|
||||
field->setValue(1, ti);
|
||||
|
||||
obj->updated();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Setup Elevon
|
||||
*/
|
||||
/*
|
||||
void ConfigAirframeWidget::setupFrameElevon()
|
||||
{
|
||||
// Check coherence:
|
||||
// - At least Aileron1 and Aileron 2
|
||||
|
||||
}
|
||||
*/
|
||||
|
||||
/**
|
||||
Sends the config to the board (airframe type)
|
||||
@ -99,10 +317,25 @@ void ConfigAirframeWidget::sendAircraftUpdate()
|
||||
{
|
||||
ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance();
|
||||
UAVObjectManager *objManager = pm->getObject<UAVObjectManager>();
|
||||
QString airframeType;
|
||||
if (m_aircraft->aircraftType->currentText() == "Fixed Wing") {
|
||||
if (m_aircraft->fixedWingType->currentText() == "Elevator aileron rudder" ) {
|
||||
airframeType = "FixedWing";
|
||||
setupFrameFixedWing();
|
||||
|
||||
} else if (m_aircraft->fixedWingType->currentText() == "Elevon") {
|
||||
airframeType = "FixedWingElevon";
|
||||
} else { // Vtail
|
||||
airframeType = "FixedWingVtail";
|
||||
}
|
||||
} else {
|
||||
airframeType = "FixedWing";
|
||||
}
|
||||
|
||||
UAVDataObject* obj = dynamic_cast<UAVDataObject*>(objManager->getObject(QString("SystemSettings")));
|
||||
Q_ASSERT(obj);
|
||||
UAVObjectField* field = obj->getField(QString("AirframeType"));
|
||||
field->setValue(m_aircraft->aircraftType->currentText());
|
||||
field->setValue(airframeType);
|
||||
obj->updated();
|
||||
}
|
||||
|
||||
|
@ -46,12 +46,15 @@ public:
|
||||
~ConfigAirframeWidget();
|
||||
|
||||
private:
|
||||
Ui_AircraftWidget *m_aircraft;
|
||||
Ui_AircraftWidget *m_aircraft;
|
||||
bool setupFrameFixedWing();
|
||||
|
||||
private slots:
|
||||
void requestAircraftUpdate();
|
||||
void sendAircraftUpdate();
|
||||
void saveAircraftUpdate();
|
||||
|
||||
private slots:
|
||||
void requestAircraftUpdate();
|
||||
void sendAircraftUpdate();
|
||||
void saveAircraftUpdate();
|
||||
void setupAirframeUI(QString type);
|
||||
|
||||
};
|
||||
|
||||
|
@ -56,60 +56,6 @@ QList<Edge *> Node::edges() const
|
||||
return edgeList;
|
||||
}
|
||||
|
||||
void Node::calculateForces()
|
||||
{
|
||||
if (!scene() || scene()->mouseGrabberItem() == this) {
|
||||
newPos = pos();
|
||||
return;
|
||||
}
|
||||
|
||||
// Sum up all forces pushing this item away
|
||||
qreal xvel = 0;
|
||||
qreal yvel = 0;
|
||||
foreach (QGraphicsItem *item, scene()->items()) {
|
||||
Node *node = qgraphicsitem_cast<Node *>(item);
|
||||
if (!node)
|
||||
continue;
|
||||
|
||||
QLineF line(mapFromItem(node, 0, 0), QPointF(0, 0));
|
||||
qreal dx = line.dx();
|
||||
qreal dy = line.dy();
|
||||
double l = 2.0 * (dx * dx + dy * dy);
|
||||
if (l > 0) {
|
||||
xvel += (dx * 150.0) / l;
|
||||
yvel += (dy * 150.0) / l;
|
||||
}
|
||||
}
|
||||
|
||||
// Now subtract all forces pulling items together
|
||||
double weight = (edgeList.size() + 1) * 10;
|
||||
foreach (Edge *edge, edgeList) {
|
||||
QPointF pos;
|
||||
if (edge->sourceNode() == this)
|
||||
pos = mapFromItem(edge->destNode(), 0, 0);
|
||||
else
|
||||
pos = mapFromItem(edge->sourceNode(), 0, 0);
|
||||
xvel += pos.x() / weight;
|
||||
yvel += pos.y() / weight;
|
||||
}
|
||||
|
||||
if (qAbs(xvel) < 0.1 && qAbs(yvel) < 0.1)
|
||||
xvel = yvel = 0;
|
||||
|
||||
QRectF sceneRect = scene()->sceneRect();
|
||||
newPos = pos() + QPointF(xvel, yvel);
|
||||
newPos.setX(qMin(qMax(newPos.x(), sceneRect.left() + 10), sceneRect.right() - 10));
|
||||
newPos.setY(qMin(qMax(newPos.y(), sceneRect.top() + 10), sceneRect.bottom() - 10));
|
||||
}
|
||||
|
||||
bool Node::advance()
|
||||
{
|
||||
if (newPos == pos())
|
||||
return false;
|
||||
|
||||
setPos(newPos);
|
||||
return true;
|
||||
}
|
||||
|
||||
QRectF Node::boundingRect() const
|
||||
{
|
||||
@ -127,19 +73,21 @@ QPainterPath Node::shape() const
|
||||
|
||||
void Node::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *)
|
||||
{
|
||||
/*
|
||||
painter->setPen(Qt::NoPen);
|
||||
painter->setBrush(Qt::darkGray);
|
||||
painter->drawEllipse(-7, -7, 20, 20);
|
||||
*/
|
||||
|
||||
QRadialGradient gradient(-3, -3, 10);
|
||||
if (option->state & QStyle::State_Sunken) {
|
||||
gradient.setCenter(3, 3);
|
||||
gradient.setFocalPoint(3, 3);
|
||||
gradient.setColorAt(1, QColor(Qt::yellow).light(120));
|
||||
gradient.setColorAt(0, QColor(Qt::darkYellow).light(120));
|
||||
gradient.setColorAt(1, QColor("#1c870b").light(120));
|
||||
gradient.setColorAt(0, QColor("#116703").light(120));
|
||||
} else {
|
||||
gradient.setColorAt(0, Qt::yellow);
|
||||
gradient.setColorAt(1, Qt::darkYellow);
|
||||
gradient.setColorAt(0, "#1c870b");
|
||||
gradient.setColorAt(1, "#116703");
|
||||
}
|
||||
painter->setBrush(gradient);
|
||||
painter->setPen(QPen(Qt::black, 0));
|
||||
@ -157,9 +105,14 @@ QVariant Node::itemChange(GraphicsItemChange change, const QVariant &value)
|
||||
case ItemPositionChange: {
|
||||
if (!vertical)
|
||||
break;
|
||||
// Foce node to move vertically
|
||||
// Force node to move vertically
|
||||
QPointF newPos = value.toPointF();
|
||||
newPos.setX(pos().x());
|
||||
// Stay inside graph
|
||||
if (newPos.y() < 0)
|
||||
newPos.setY(0);
|
||||
if (newPos.y() > graph->height())
|
||||
newPos.setY(graph->height());
|
||||
return newPos;
|
||||
}
|
||||
case ItemPositionHasChanged:
|
||||
|
@ -50,8 +50,6 @@ public:
|
||||
int type() const { return Type; }
|
||||
|
||||
void verticalMove(bool flag);
|
||||
void calculateForces();
|
||||
bool advance();
|
||||
|
||||
QRectF boundingRect() const;
|
||||
QPainterPath shape() const;
|
||||
|
@ -67,12 +67,6 @@ MixerCurveWidget::MixerCurveWidget(QWidget *parent) : QGraphicsView(parent)
|
||||
scene->setSceneRect(plot->boundingRect());
|
||||
setScene(scene);
|
||||
|
||||
QList<double> list;
|
||||
list << 0 << 0.3 << 0.6 << -0.4 << -0.8;
|
||||
initCurve(list);
|
||||
|
||||
qDebug() << getCurve();
|
||||
|
||||
}
|
||||
|
||||
MixerCurveWidget::~MixerCurveWidget()
|
||||
|
@ -47,8 +47,14 @@ SystemSettings::SystemSettings(): UAVDataObject(OBJID, ISSINGLEINST, ISSETTINGS,
|
||||
QStringList AirframeTypeEnumOptions;
|
||||
AirframeTypeEnumOptions.append("FixedWing");
|
||||
AirframeTypeEnumOptions.append("FixedWingElevon");
|
||||
AirframeTypeEnumOptions.append("FixedWingVtail");
|
||||
AirframeTypeEnumOptions.append("VTOL");
|
||||
AirframeTypeEnumOptions.append("HeliCP");
|
||||
AirframeTypeEnumOptions.append("QuadX");
|
||||
AirframeTypeEnumOptions.append("QuadP");
|
||||
AirframeTypeEnumOptions.append("Hexa");
|
||||
AirframeTypeEnumOptions.append("Octo");
|
||||
AirframeTypeEnumOptions.append("Custom");
|
||||
fields.append( new UAVObjectField(QString("AirframeType"), QString(""), UAVObjectField::ENUM, AirframeTypeElemNames, AirframeTypeEnumOptions) );
|
||||
|
||||
// Initialize object
|
||||
|
@ -50,7 +50,7 @@ public:
|
||||
// Field information
|
||||
// Field AirframeType information
|
||||
/* Enumeration options for field AirframeType */
|
||||
typedef enum { AIRFRAMETYPE_FIXEDWING=0, AIRFRAMETYPE_FIXEDWINGELEVON=1, AIRFRAMETYPE_VTOL=2, AIRFRAMETYPE_HELICP=3 } AirframeTypeOptions;
|
||||
typedef enum { AIRFRAMETYPE_FIXEDWING=0, AIRFRAMETYPE_FIXEDWINGELEVON=1, AIRFRAMETYPE_FIXEDWINGVTAIL=2, AIRFRAMETYPE_VTOL=3, AIRFRAMETYPE_HELICP=4, AIRFRAMETYPE_QUADX=5, AIRFRAMETYPE_QUADP=6, AIRFRAMETYPE_HEXA=7, AIRFRAMETYPE_OCTO=8, AIRFRAMETYPE_CUSTOM=9 } AirframeTypeOptions;
|
||||
|
||||
|
||||
// Constants
|
||||
|
@ -47,8 +47,14 @@ _fields = [ \
|
||||
{
|
||||
'0' : 'FixedWing',
|
||||
'1' : 'FixedWingElevon',
|
||||
'2' : 'VTOL',
|
||||
'3' : 'HeliCP',
|
||||
'2' : 'FixedWingVtail',
|
||||
'3' : 'VTOL',
|
||||
'4' : 'HeliCP',
|
||||
'5' : 'QuadX',
|
||||
'6' : 'QuadP',
|
||||
'7' : 'Hexa',
|
||||
'8' : 'Octo',
|
||||
'9' : 'Custom',
|
||||
}
|
||||
),
|
||||
]
|
||||
|
@ -1,7 +1,7 @@
|
||||
<xml>
|
||||
<object name="SystemSettings" singleinstance="true" settings="true">
|
||||
<description>Select airframe type. Currently used by @ref ActuatorModule to choose mixing from @ref ActuatorDesired to @ref ActuatorCommand</description>
|
||||
<field name="AirframeType" units="" type="enum" elements="1" options="FixedWing,FixedWingElevon,VTOL, HeliCP" defaultvalue="FixedWing"/>
|
||||
<field name="AirframeType" units="" type="enum" elements="1" options="FixedWing,FixedWingElevon,FixedWingVtail,VTOL,HeliCP,QuadX,QuadP,Hexa,Octo,Custom" defaultvalue="FixedWing"/>
|
||||
<access gcs="readwrite" flight="readwrite"/>
|
||||
<telemetrygcs acked="true" updatemode="onchange" period="0"/>
|
||||
<telemetryflight acked="true" updatemode="onchange" period="0"/>
|
||||
|
Loading…
x
Reference in New Issue
Block a user