1
0
mirror of https://bitbucket.org/librepilot/librepilot.git synced 2024-11-30 08:24:11 +01:00

Merge branch 'bugfix-ground' of git.openpilot.org:OpenPilot into bugfix-ground

Conflicts:
	ground/openpilotgcs/src/plugins/config/configairframewidget.cpp
This commit is contained in:
elafargue 2011-05-30 07:26:44 +02:00
commit 93dd254c77
36 changed files with 3077 additions and 2346 deletions

View File

@ -4,10 +4,12 @@ include(../shared/qtsingleapplication/qtsingleapplication.pri)
TEMPLATE = app
TARGET = $$GCS_APP_TARGET
DESTDIR = $$GCS_APP_PATH
QT += xml
SOURCES += main.cpp
include(../rpath.pri)
include(../libs/utils/utils.pri)
win32 {
CONFIG(debug, debug|release):LIBS *= -lExtensionSystemd -lAggregationd -lQExtSerialPortd

View File

@ -27,6 +27,7 @@
*/
#include "qtsingleapplication.h"
#include "utils/xmlconfig.h"
#include <extensionsystem/pluginmanager.h>
#include <extensionsystem/pluginspec.h>
@ -243,10 +244,10 @@ int main(int argc, char **argv)
QString locale = QLocale::system().name();
// Must be done before any QSettings class is created
QSettings::setPath(QSettings::IniFormat, QSettings::SystemScope,
QSettings::setPath(XmlConfig::XmlSettingsFormat, QSettings::SystemScope,
QCoreApplication::applicationDirPath()+QLatin1String(SHARE_PATH));
// keep this in sync with the MainWindow ctor in coreplugin/mainwindow.cpp
QSettings settings(QSettings::IniFormat, QSettings::UserScope,
QSettings settings(XmlConfig::XmlSettingsFormat, QSettings::UserScope,
QLatin1String("OpenPilot"), QLatin1String("OpenPilotGCS"));
overrideSettings(settings, argc, argv);

View File

@ -26,6 +26,7 @@
*/
#include "pathutils.h"
#include "xmlconfig.h"
#include <stdint.h>
#include <QDebug>
@ -97,7 +98,7 @@ QString PathUtils::GetStoragePath()
{
// This routine works with "/" as the standard:
// Work out where the settings are stored on the machine
QSettings set(QSettings::IniFormat, QSettings::UserScope,QLatin1String("OpenPilot"), QLatin1String("OpenPilotGCS"));
QSettings set(XmlConfig::XmlSettingsFormat, QSettings::UserScope,QLatin1String("OpenPilot"), QLatin1String("OpenPilotGCS"));
QFileInfo f(set.fileName());
QDir dir(f.absoluteDir());

View File

@ -2,7 +2,8 @@ TEMPLATE = lib
TARGET = Utils
QT += gui \
network
network \
xml
DEFINES += QTCREATOR_UTILS_LIB
@ -45,6 +46,7 @@ SOURCES += reloadpromptutils.cpp \
pathutils.cpp \
worldmagmodel.cpp \
homelocationutil.cpp
SOURCES += xmlconfig.cpp
win32 {
SOURCES += abstractprocess_win.cpp \
@ -95,6 +97,7 @@ HEADERS += utils_global.h \
pathutils.h \
worldmagmodel.h \
homelocationutil.h
HEADERS += xmlconfig.h
FORMS += filewizardpage.ui \
projectintropage.ui \

View File

@ -38,6 +38,7 @@
#include <QRect>
#include <QSize>
#include <QPoint>
#include <QtCore/QUrl>
#define NUM_PREFIX "arr_"
@ -84,6 +85,10 @@ void XmlConfig::handleNode(QDomElement* node, QSettings::SettingsMap &map, QStri
if ( nodeName.startsWith(NUM_PREFIX) ){
nodeName.replace(NUM_PREFIX, "");
}
// Xml tags are restrictive with allowed characters,
// so we urlencode and replace % with __PCT__ on file
nodeName = nodeName.replace("__PCT__", "%");
nodeName = QUrl::fromPercentEncoding(nodeName.toAscii());
if ( nodeName == XmlConfig::rootName )
;
@ -99,7 +104,7 @@ void XmlConfig::handleNode(QDomElement* node, QSettings::SettingsMap &map, QStri
handleNode( static_cast<QDomElement*>(&child), map, path);
}
else if ( child.isText() ){
qDebug() << "Key: " << path << " Value:" << node->text();
// qDebug() << "Key: " << path << " Value:" << node->text();
map.insert(path, stringToVariant(node->text()));
}
else{
@ -123,6 +128,10 @@ bool XmlConfig::writeXmlFile(QIODevice &device, const QSettings::SettingsMap &ma
if ( elem == "" ){
continue;
}
// Xml tags are restrictive with allowed characters,
// so we urlencode and replace % with __PCT__ on file
elem = QString(QUrl::toPercentEncoding(elem));
elem = elem.replace("%", "__PCT__");
// For arrays, QT will use simple numbers as keys, which is not a valid element in XML.
// Therefore we prefixed these.
if ( elem.startsWith(NUM_PREFIX) ){

View File

@ -26,13 +26,18 @@
#ifndef XMLCONFIG_H
#define XMLCONFIG_H
#include "importexport_global.h"
#if defined(QTCREATOR_UTILS_LIB)
# define XMLCONFIG_EXPORT Q_DECL_EXPORT
#else
# define XMLCONFIG_EXPORT Q_DECL_IMPORT
#endif
#include <QtCore/qglobal.h>
#include <QSettings>
#include <QDomElement>
#include <QObject>
class IMPORTEXPORT_EXPORT XmlConfig : QObject
class XMLCONFIG_EXPORT XmlConfig : QObject
{
public:

View File

@ -1,2169 +0,0 @@
/**
******************************************************************************
*
* @file configairframewidget.cpp
* @author E. Lafargue & The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
* @addtogroup GCSPlugins GCS Plugins
* @{
* @addtogroup ConfigPlugin Config Plugin
* @{
* @brief Airframe configuration panel
*****************************************************************************/
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "configairframewidget.h"
#include <QDebug>
#include <QStringList>
#include <QTimer>
#include <QtGui/QWidget>
#include <QtGui/QTextEdit>
#include <QtGui/QVBoxLayout>
#include <QtGui/QPushButton>
#include <math.h>
#include <QSignalMapper>
/**
Helper delegate for the custom mixer editor table.
Taken straight from Qt examples, thanks!
*/
SpinBoxDelegate::SpinBoxDelegate(QObject *parent)
: QItemDelegate(parent)
{
}
QWidget *SpinBoxDelegate::createEditor(QWidget *parent,
const QStyleOptionViewItem &/* option */,
const QModelIndex &/* index */) const
{
QSpinBox *editor = new QSpinBox(parent);
editor->setMinimum(-127);
editor->setMaximum(127);
return editor;
}
void SpinBoxDelegate::setEditorData(QWidget *editor,
const QModelIndex &index) const
{
int value = index.model()->data(index, Qt::EditRole).toInt();
QSpinBox *spinBox = static_cast<QSpinBox*>(editor);
spinBox->setValue(value);
}
void SpinBoxDelegate::setModelData(QWidget *editor, QAbstractItemModel *model,
const QModelIndex &index) const
{
QSpinBox *spinBox = static_cast<QSpinBox*>(editor);
spinBox->interpretText();
int value = spinBox->value();
model->setData(index, value, Qt::EditRole);
}
void SpinBoxDelegate::updateEditorGeometry(QWidget *editor,
const QStyleOptionViewItem &option, const QModelIndex &/* index */) const
{
editor->setGeometry(option.rect);
}
/**********************************************************************************/
ConfigAirframeWidget::ConfigAirframeWidget(QWidget *parent) : ConfigTaskWidget(parent)
{
m_aircraft = new Ui_AircraftWidget();
m_aircraft->setupUi(this);
ffTuningInProgress = false;
ffTuningPhase = false;
mixerTypes << "Mixer1Type" << "Mixer2Type" << "Mixer3Type"
<< "Mixer4Type" << "Mixer5Type" << "Mixer6Type" << "Mixer7Type" << "Mixer8Type";
mixerVectors << "Mixer1Vector" << "Mixer2Vector" << "Mixer3Vector"
<< "Mixer4Vector" << "Mixer5Vector" << "Mixer6Vector" << "Mixer7Vector" << "Mixer8Vector";
QStringList airframeTypes;
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" << "Hexacopter X" << "Octocopter V" << "Octo Coax +"
<< "Octo Coax X" << "Hexacopter Y6" << "Tricopter Y";
m_aircraft->multirotorFrameType->addItems(multiRotorTypes);
QStringList channels;
channels << "None" << "Channel1" << "Channel2" << "Channel3" <<
"Channel4" << "Channel5" << "Channel6" << "Channel7" << "Channel8";
// 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->fwRudder1Channel->addItems(channels);
m_aircraft->fwRudder2Channel->addItems(channels);
m_aircraft->fwAileron1Channel->addItems(channels);
m_aircraft->fwAileron2Channel->addItems(channels);
m_aircraft->multiMotor1->addItems(channels);
m_aircraft->multiMotor2->addItems(channels);
m_aircraft->multiMotor3->addItems(channels);
m_aircraft->multiMotor4->addItems(channels);
m_aircraft->multiMotor5->addItems(channels);
m_aircraft->multiMotor6->addItems(channels);
m_aircraft->multiMotor7->addItems(channels);
m_aircraft->multiMotor8->addItems(channels);
m_aircraft->triYawChannel->addItems(channels);
// Setup the Multirotor picture in the Quad settings interface
m_aircraft->quadShape->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
m_aircraft->quadShape->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
QSvgRenderer *renderer = new QSvgRenderer();
renderer->load(QString(":/configgadget/images/quad-shapes.svg"));
quad = new QGraphicsSvgItem();
quad->setSharedRenderer(renderer);
quad->setElementId("quad-plus");
QGraphicsScene *scene = new QGraphicsScene(this);
scene->addItem(quad);
scene->setSceneRect(quad->boundingRect());
m_aircraft->quadShape->setScene(scene);
// Put combo boxes in line one of the custom mixer table:
UAVDataObject* obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
UAVObjectField* field = obj->getField(QString("Mixer1Type"));
QStringList list = field->getOptions();
for (int i=0;i<8;i++) {
QComboBox* qb = new QComboBox(m_aircraft->customMixerTable);
qb->addItems(list);
m_aircraft->customMixerTable->setCellWidget(0,i,qb);
}
SpinBoxDelegate *sbd = new SpinBoxDelegate();
for (int i=1;i<8; i++) {
m_aircraft->customMixerTable->setItemDelegateForRow(i, sbd);
}
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->ffSave, SIGNAL(clicked()), this, SLOT(saveAircraftUpdate()));
connect(m_aircraft->ffApply, SIGNAL(clicked()), this, SLOT(sendAircraftUpdate()));
connect(m_aircraft->ffGetCurrent, SIGNAL(clicked()), this, SLOT(requestAircraftUpdate()));
connect(m_aircraft->fixedWingType, SIGNAL(currentIndexChanged(QString)), this, SLOT(setupAirframeUI(QString)));
connect(m_aircraft->multirotorFrameType, SIGNAL(currentIndexChanged(QString)), this, SLOT(setupAirframeUI(QString)));
connect(m_aircraft->aircraftType, SIGNAL(currentIndexChanged(int)), this, SLOT(switchAirframeType(int)));
requestAircraftUpdate();
connect(m_aircraft->fwThrottleReset, SIGNAL(clicked()), this, SLOT(resetFwMixer()));
connect(m_aircraft->mrThrottleCurveReset, SIGNAL(clicked()), this, SLOT(resetMrMixer()));
connect(m_aircraft->customReset1, SIGNAL(clicked()), this, SLOT(resetCt1Mixer()));
connect(m_aircraft->customReset2, SIGNAL(clicked()), this, SLOT(resetCt2Mixer()));
connect(m_aircraft->fixedWingThrottle, SIGNAL(curveUpdated(QList<double>,double)), this, SLOT(updateFwThrottleCurveValue(QList<double>,double)));
connect(m_aircraft->multiThrottleCurve, SIGNAL(curveUpdated(QList<double>,double)), this, SLOT(updateMrThrottleCurveValue(QList<double>,double)));
connect(m_aircraft->customThrottle1Curve, SIGNAL(curveUpdated(QList<double>,double)), this, SLOT(updateCustomThrottle1CurveValue(QList<double>,double)));
connect(m_aircraft->customThrottle2Curve, SIGNAL(curveUpdated(QList<double>,double)), this, SLOT(updateCustomThrottle2CurveValue(QList<double>,double)));
// connect(m_aircraft->fwAileron1Channel, SIGNAL(currentIndexChanged(int)), this, SLOT(toggleAileron2(int)));
// connect(m_aircraft->fwElevator1Channel, SIGNAL(currentIndexChanged(int)), this, SLOT(toggleElevator2(int)));
// Now connect the three feed forward test checkboxes
connect(m_aircraft->ffTestBox1, SIGNAL(clicked(bool)), this, SLOT(enableFFTest()));
connect(m_aircraft->ffTestBox2, SIGNAL(clicked(bool)), this, SLOT(enableFFTest()));
connect(m_aircraft->ffTestBox3, SIGNAL(clicked(bool)), this, SLOT(enableFFTest()));
connect(parent, SIGNAL(autopilotConnected()),this, SLOT(requestAircraftUpdate()));
// Connect all the help buttons to signal mapper that passes button name to SLOT function
QSignalMapper* signalMapper = new QSignalMapper(this);
connect( m_aircraft->acftTypeHelp, SIGNAL(clicked()), signalMapper, SLOT(map()) );
signalMapper->setMapping(m_aircraft->acftTypeHelp, m_aircraft->acftTypeHelp->objectName());
connect( m_aircraft->airplaneTypeHelp, SIGNAL(clicked()), signalMapper, SLOT(map()) );
signalMapper->setMapping(m_aircraft->airplaneTypeHelp, m_aircraft->airplaneTypeHelp->objectName());
connect( m_aircraft->channelAssignmentHelp, SIGNAL(clicked()), signalMapper, SLOT(map()) );
signalMapper->setMapping(m_aircraft->channelAssignmentHelp, m_aircraft->channelAssignmentHelp->objectName());
connect( m_aircraft->commandHelp, SIGNAL(clicked()), signalMapper, SLOT(map()) );
signalMapper->setMapping(m_aircraft->commandHelp, QString("commandHelp"));
connect( m_aircraft->throttleCurveHelp, SIGNAL(clicked()), signalMapper, SLOT(map()) );
signalMapper->setMapping(m_aircraft->throttleCurveHelp, QString("throttleCurveHelp"));
connect( m_aircraft->multiFrameTypeHelp, SIGNAL(clicked()), signalMapper, SLOT(map()) );
signalMapper->setMapping(m_aircraft->multiFrameTypeHelp, m_aircraft->multiFrameTypeHelp->objectName());
connect( m_aircraft->throttleCurveHelp_2, SIGNAL(clicked()), signalMapper, SLOT(map()) );
signalMapper->setMapping(m_aircraft->throttleCurveHelp_2, QString("throttleCurveHelp"));
connect( m_aircraft->tricopterYawHelp, SIGNAL(clicked()), signalMapper, SLOT(map()) );
signalMapper->setMapping(m_aircraft->tricopterYawHelp, m_aircraft->tricopterYawHelp->objectName());
connect( m_aircraft->motorOutputChanHelp, SIGNAL(clicked()), signalMapper, SLOT(map()) );
signalMapper->setMapping(m_aircraft->motorOutputChanHelp, m_aircraft->motorOutputChanHelp->objectName());
connect( m_aircraft->feedForwardHelp, SIGNAL(clicked()), signalMapper, SLOT(map()) );
signalMapper->setMapping(m_aircraft->feedForwardHelp, m_aircraft->feedForwardHelp->objectName());
connect( m_aircraft->commandHelp_2, SIGNAL(clicked()), signalMapper, SLOT(map()) );
signalMapper->setMapping(m_aircraft->commandHelp_2, QString("commandHelp"));
connect(signalMapper, SIGNAL(mapped(const QString &)), parent, SLOT(showHelp(const QString &)));
}
ConfigAirframeWidget::~ConfigAirframeWidget()
{
// Do nothing
}
/**
Slot for switching the airframe type. We do it explicitely
rather than a signal in the UI, because we want to force a fitInView of the quad shapes.
This is because this method (fitinview) only works when the widget is shown.
*/
void ConfigAirframeWidget::switchAirframeType(int index){
m_aircraft->airframesWidget->setCurrentIndex(index);
m_aircraft->quadShape->setSceneRect(quad->boundingRect());
m_aircraft->quadShape->fitInView(quad, Qt::KeepAspectRatio);
if (m_aircraft->aircraftType->findText("Custom")) {
m_aircraft->customMixerTable->resizeColumnsToContents();
for (int i=0;i<8;i++) {
m_aircraft->customMixerTable->setColumnWidth(i,(m_aircraft->customMixerTable->width()-
m_aircraft->customMixerTable->verticalHeader()->width())/8);
}
}
}
void ConfigAirframeWidget::showEvent(QShowEvent *event)
{
Q_UNUSED(event)
// Thit fitInView method should only be called now, once the
// widget is shown, otherwise it cannot compute its values and
// the result is usually a ahrsbargraph that is way too small.
m_aircraft->quadShape->fitInView(quad, Qt::KeepAspectRatio);
m_aircraft->customMixerTable->resizeColumnsToContents();
for (int i=0;i<8;i++) {
m_aircraft->customMixerTable->setColumnWidth(i,(m_aircraft->customMixerTable->width()-
m_aircraft->customMixerTable->verticalHeader()->width())/8);
}
}
void ConfigAirframeWidget::resizeEvent(QResizeEvent* event)
{
Q_UNUSED(event);
m_aircraft->quadShape->fitInView(quad, Qt::KeepAspectRatio);
// Make the custom table columns autostretch:
m_aircraft->customMixerTable->resizeColumnsToContents();
for (int i=0;i<8;i++) {
m_aircraft->customMixerTable->setColumnWidth(i,(m_aircraft->customMixerTable->width()-
m_aircraft->customMixerTable->verticalHeader()->width())/8);
}
}
void ConfigAirframeWidget::toggleAileron2(int index)
{
if (index) {
m_aircraft->fwAileron2Channel->setEnabled(true);
m_aircraft->fwAileron2Label->setEnabled(true);
} else {
m_aircraft->fwAileron2Channel->setEnabled(false);
m_aircraft->fwAileron2Label->setEnabled(false);
}
}
void ConfigAirframeWidget::toggleElevator2(int index)
{
if (index) {
m_aircraft->fwElevator2Channel->setEnabled(true);
m_aircraft->fwElevator2Label->setEnabled(true);
} else {
m_aircraft->fwElevator2Channel->setEnabled(false);
m_aircraft->fwElevator2Label->setEnabled(false);
}
}
void ConfigAirframeWidget::toggleRudder2(int index)
{
if (index) {
m_aircraft->fwRudder2Channel->setEnabled(true);
m_aircraft->fwRudder2Label->setEnabled(true);
} else {
m_aircraft->fwRudder2Channel->setEnabled(false);
m_aircraft->fwRudder2Label->setEnabled(false);
}
}
/////////////////////////////////////////////////////////
/// Feed Forward Testing
/////////////////////////////////////////////////////////
/**
Enables and runs feed forward testing
*/
void ConfigAirframeWidget::enableFFTest()
{
// Role:
// - Check if all three checkboxes are checked
// - Every other timer event: toggle engine from 45% to 55%
// - Every other time event: send FF settings to flight FW
if (m_aircraft->ffTestBox1->isChecked() &&
m_aircraft->ffTestBox2->isChecked() &&
m_aircraft->ffTestBox3->isChecked()) {
if (!ffTuningInProgress)
{
// Initiate tuning:
UAVDataObject* obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("ManualControlCommand")));
UAVObject::Metadata mdata = obj->getMetadata();
accInitialData = mdata;
mdata.flightAccess = UAVObject::ACCESS_READONLY;
obj->setMetadata(mdata);
}
// Depending on phase, either move actuator or send FF settings:
if (ffTuningPhase) {
// Send FF settings to the board
UAVDataObject* obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
UAVObjectField* field = obj->getField(QString("FeedForward"));
field->setDouble((double)m_aircraft->feedForwardSlider->value()/100);
field = obj->getField(QString("AccelTime"));
field->setDouble(m_aircraft->accelTime->value());
field = obj->getField(QString("DecelTime"));
field->setDouble(m_aircraft->decelTime->value());
field = obj->getField(QString("MaxAccel"));
field->setDouble(m_aircraft->maxAccelSlider->value());
obj->updated();
} else {
// Toggle motor state
UAVDataObject* obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("ManualControlCommand")));
double value = obj->getField("Throttle")->getDouble();
double target = (value < 0.5) ? 0.55 : 0.45;
obj->getField("Throttle")->setValue(target);
obj->updated();
}
ffTuningPhase = !ffTuningPhase;
ffTuningInProgress = true;
QTimer::singleShot(1000, this, SLOT(enableFFTest()));
} else {
// - If no: disarm timer, restore actuatorcommand metadata
// Disarm!
if (ffTuningInProgress) {
ffTuningInProgress = false;
UAVDataObject* obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("ManualControlCommand")));
UAVObject::Metadata mdata = obj->getMetadata();
mdata = accInitialData; // Restore metadata
obj->setMetadata(mdata);
}
}
}
/**
Resets Fixed wing throttle mixer
*/
void ConfigAirframeWidget::resetFwMixer()
{
UAVDataObject* obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
UAVObjectField* field = obj->getField(QString("ThrottleCurve1"));
resetMixer(m_aircraft->fixedWingThrottle, field->getNumElements());
}
/**
Resets Multirotor throttle mixer
*/
void ConfigAirframeWidget::resetMrMixer()
{
UAVDataObject* obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
UAVObjectField* field = obj->getField(QString("ThrottleCurve1"));
resetMixer(m_aircraft->multiThrottleCurve, field->getNumElements());
}
/**
Resets Custom throttle 1 mixer
*/
void ConfigAirframeWidget::resetCt1Mixer()
{
UAVDataObject* obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
UAVObjectField* field = obj->getField(QString("ThrottleCurve1"));
resetMixer(m_aircraft->customThrottle1Curve, field->getNumElements());
}
/**
Resets Custom throttle 2 mixer
*/
void ConfigAirframeWidget::resetCt2Mixer()
{
UAVDataObject* obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
UAVObjectField* field = obj->getField(QString("ThrottleCurve2"));
resetMixer(m_aircraft->customThrottle2Curve, field->getNumElements());
}
/**
Resets a mixer curve
*/
void ConfigAirframeWidget::resetMixer(MixerCurveWidget *mixer, int numElements)
{
QList<double> curveValues;
for (double i=0; i<numElements; i++) {
curveValues.append(i/(numElements-1));
}
// Setup all Throttle1 curves for all types of airframes
mixer->initCurve(curveValues);
}
/**
Updates the currently moved throttle curve item value
*/
void ConfigAirframeWidget::updateFwThrottleCurveValue(QList<double> list, double value)
{
Q_UNUSED(list);
m_aircraft->fwThrottleCurveItemValue->setText(QString().sprintf("Val: %.2f",value));
}
/**
Updates the currently moved throttle curve item value
*/
void ConfigAirframeWidget::updateMrThrottleCurveValue(QList<double> list, double value)
{
Q_UNUSED(list);
m_aircraft->mrThrottleCurveItemValue->setText(QString().sprintf("Val: %.2f",value));
}
/**
Updates the currently moved throttle curve item value (Custom throttle 1)
*/
void ConfigAirframeWidget::updateCustomThrottle1CurveValue(QList<double> list, double value)
{
Q_UNUSED(list);
m_aircraft->customThrottleCurve1Value->setText(QString().sprintf("Val: %.2f",value));
}
/**
Updates the currently moved throttle curve item value (Custom throttle 2)
*/
void ConfigAirframeWidget::updateCustomThrottle2CurveValue(QList<double> list, double value)
{
Q_UNUSED(list);
m_aircraft->customThrottleCurve2Value->setText(QString().sprintf("Val: %.2f",value));
}
/**************************
* Aircraft settings
**************************/
/**
Request the current value of the SystemSettings which holds the aircraft type
*/
void ConfigAirframeWidget::requestAircraftUpdate()
{
// Get the Airframe type from the system settings:
UAVDataObject* obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("SystemSettings")));
Q_ASSERT(obj);
obj->requestUpdate();
UAVObjectField *field = obj->getField(QString("AirframeType"));
Q_ASSERT(field);
// 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);
obj = dynamic_cast<UAVDataObject*>(getObjectManager()->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(i/(field->getNumElements()-1));
}
} else {
for (unsigned int i=0; i < field->getNumElements(); i++) {
curveValues.append(field->getValue(i).toDouble());
}
}
// Setup all Throttle1 curves for all types of airframes
m_aircraft->fixedWingThrottle->initCurve(curveValues);
m_aircraft->multiThrottleCurve->initCurve(curveValues);
// Load the Settings for fixed wing frames:
if (frameType.startsWith("FixedWing")) {
// Then retrieve how channels are setup
obj = dynamic_cast<UAVDataObject*>(getObjectManager()->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("FixedWingYaw1"));
Q_ASSERT(field);
m_aircraft->fwRudder1Channel->setCurrentIndex(m_aircraft->fwRudder1Channel->findText(field->getValue().toString()));
field = obj->getField(QString("FixedWingYaw2"));
Q_ASSERT(field);
m_aircraft->fwRudder2Channel->setCurrentIndex(m_aircraft->fwRudder2Channel->findText(field->getValue().toString()));
if (frameType == "FixedWingElevon") {
// If the airframe is elevon, restore the slider setting
// Find the channel number for Elevon1 (FixedWingRoll1)
obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
Q_ASSERT(obj);
int chMixerNumber = m_aircraft->fwAileron1Channel->currentIndex()-1;
if (chMixerNumber >= 0) { // If for some reason the actuators were incoherent, we might fail here, hence the check.
field = obj->getField(mixerVectors.at(chMixerNumber));
int ti = field->getElementNames().indexOf("Roll");
m_aircraft->elevonSlider1->setValue(field->getDouble(ti)*100);
ti = field->getElementNames().indexOf("Pitch");
m_aircraft->elevonSlider2->setValue(field->getDouble(ti)*100);
}
}
if (frameType == "FixedWingVtail") {
obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
Q_ASSERT(obj);
int chMixerNumber = m_aircraft->fwElevator1Channel->currentIndex()-1;
if (chMixerNumber >=0) {
field = obj->getField(mixerVectors.at(chMixerNumber));
int ti = field->getElementNames().indexOf("Yaw");
m_aircraft->elevonSlider1->setValue(field->getDouble(ti)*100);
ti = field->getElementNames().indexOf("Pitch");
m_aircraft->elevonSlider2->setValue(field->getDouble(ti)*100);
}
}
} else if (frameType == "QuadX" || frameType == "QuadP" ||
frameType == "Hexa" || frameType == "Octo" ||
frameType == "HexaCoax" || frameType == "OctoV" ||
frameType == "HexaX" || frameType == "OctoCoaxP" ||
frameType == "OctoCoaxX" || frameType == "Tri") {
//////////////////////////////////////////////////////////////////
// Retrieve Multirotor settings
//////////////////////////////////////////////////////////////////
obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("ActuatorSettings")));
Q_ASSERT(obj);
if (frameType == "QuadP") {
// Motors 1/2/3/4 are: N / E / S / W
field = obj->getField(QString("VTOLMotorN"));
Q_ASSERT(field);
m_aircraft->multiMotor1->setCurrentIndex(m_aircraft->multiMotor1->findText(field->getValue().toString()));
field = obj->getField(QString("VTOLMotorE"));
Q_ASSERT(field);
m_aircraft->multiMotor2->setCurrentIndex(m_aircraft->multiMotor2->findText(field->getValue().toString()));
field = obj->getField(QString("VTOLMotorS"));
Q_ASSERT(field);
m_aircraft->multiMotor3->setCurrentIndex(m_aircraft->multiMotor3->findText(field->getValue().toString()));
field = obj->getField(QString("VTOLMotorW"));
Q_ASSERT(field);
m_aircraft->multiMotor4->setCurrentIndex(m_aircraft->multiMotor4->findText(field->getValue().toString()));
// Now, read the 1st mixer R/P/Y levels and initialize the mix sliders.
// This assumes that all vectors are identical - if not, the user should use the
// "custom" setting.
obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
Q_ASSERT(obj);
int eng= m_aircraft->multiMotor1->currentIndex()-1;
// eng will be -1 if value is set to "None"
if (eng > -1) {
field = obj->getField(mixerVectors.at(eng));
int i = field->getElementNames().indexOf("Pitch");
double val = field->getDouble(i)/1.27;
m_aircraft->mrPitchMixLevel->setValue(val);
i = field->getElementNames().indexOf("Yaw");
val = (1-field->getDouble(i)/1.27);
m_aircraft->mrYawMixLevel->setValue(val);
eng = m_aircraft->multiMotor2->currentIndex()-1;
field = obj->getField(mixerVectors.at(eng));
i = field->getElementNames().indexOf("Roll");
val = -field->getDouble(i)/1.27;
m_aircraft->mrRollMixLevel->setValue(val);
}
} else if (frameType == "QuadX") {
// Motors 1/2/3/4 are: NW / NE / SE / SW
field = obj->getField(QString("VTOLMotorNW"));
Q_ASSERT(field);
m_aircraft->multiMotor1->setCurrentIndex(m_aircraft->multiMotor1->findText(field->getValue().toString()));
field = obj->getField(QString("VTOLMotorNE"));
Q_ASSERT(field);
m_aircraft->multiMotor2->setCurrentIndex(m_aircraft->multiMotor2->findText(field->getValue().toString()));
field = obj->getField(QString("VTOLMotorSE"));
Q_ASSERT(field);
m_aircraft->multiMotor3->setCurrentIndex(m_aircraft->multiMotor3->findText(field->getValue().toString()));
field = obj->getField(QString("VTOLMotorSW"));
Q_ASSERT(field);
m_aircraft->multiMotor4->setCurrentIndex(m_aircraft->multiMotor4->findText(field->getValue().toString()));
// Now, read the 1st mixer R/P/Y levels and initialize the mix sliders.
// This assumes that all vectors are identical - if not, the user should use the
// "custom" setting.
obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
Q_ASSERT(obj);
int eng= m_aircraft->multiMotor1->currentIndex()-1;
// eng will be -1 if value is set to "None"
if (eng > -1) {
field = obj->getField(mixerVectors.at(eng));
int i = field->getElementNames().indexOf("Pitch");
double val = field->getDouble(i)/1.27;
m_aircraft->mrPitchMixLevel->setValue(val);
i = field->getElementNames().indexOf("Yaw");
val = 1-field->getDouble(i)/1.27;
m_aircraft->mrYawMixLevel->setValue(val);
i = field->getElementNames().indexOf("Roll");
val = field->getDouble(i)/1.27;
m_aircraft->mrRollMixLevel->setValue(val);
}
} else if (frameType == "Hexa") {
// Motors 1/2/3 4/5/6 are: N / NE / SE / S / SW / NW
field = obj->getField(QString("VTOLMotorN"));
m_aircraft->multiMotor1->setCurrentIndex(m_aircraft->multiMotor1->findText(field->getValue().toString()));
field = obj->getField(QString("VTOLMotorNE"));
m_aircraft->multiMotor2->setCurrentIndex(m_aircraft->multiMotor2->findText(field->getValue().toString()));
field = obj->getField(QString("VTOLMotorSE"));
m_aircraft->multiMotor3->setCurrentIndex(m_aircraft->multiMotor3->findText(field->getValue().toString()));
field = obj->getField(QString("VTOLMotorS"));
m_aircraft->multiMotor4->setCurrentIndex(m_aircraft->multiMotor4->findText(field->getValue().toString()));
field = obj->getField(QString("VTOLMotorSW"));
m_aircraft->multiMotor5->setCurrentIndex(m_aircraft->multiMotor4->findText(field->getValue().toString()));
field = obj->getField(QString("VTOLMotorNW"));
m_aircraft->multiMotor6->setCurrentIndex(m_aircraft->multiMotor4->findText(field->getValue().toString()));
// Now, read the 1st mixer R/P/Y levels and initialize the mix sliders.
// This assumes that all vectors are identical - if not, the user should use the
// "custom" setting.
obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
int eng= m_aircraft->multiMotor1->currentIndex()-1;
// eng will be -1 if value is set to "None"
if (eng > -1) {
field = obj->getField(mixerVectors.at(eng));
int i = field->getElementNames().indexOf("Pitch");
double val = floor(field->getDouble(i)/1.27);
m_aircraft->mrPitchMixLevel->setValue(val);
i = field->getElementNames().indexOf("Yaw");
val = floor(-field->getDouble(i)/1.27);
m_aircraft->mrYawMixLevel->setValue(val);
eng = m_aircraft->multiMotor2->currentIndex()-1;
field = obj->getField(mixerVectors.at(eng));
i = field->getElementNames().indexOf("Roll");
val = floor(1-field->getDouble(i)/1.27);
m_aircraft->mrRollMixLevel->setValue(val);
}
} else if (frameType == "HexaX") {
// Motors 1/2/3 4/5/6 are: NE / E / SE / SW / W / NW
field = obj->getField(QString("VTOLMotorNE"));
m_aircraft->multiMotor1->setCurrentIndex(m_aircraft->multiMotor1->findText(field->getValue().toString()));
field = obj->getField(QString("VTOLMotorE"));
m_aircraft->multiMotor2->setCurrentIndex(m_aircraft->multiMotor2->findText(field->getValue().toString()));
field = obj->getField(QString("VTOLMotorSE"));
m_aircraft->multiMotor3->setCurrentIndex(m_aircraft->multiMotor3->findText(field->getValue().toString()));
field = obj->getField(QString("VTOLMotorSW"));
m_aircraft->multiMotor4->setCurrentIndex(m_aircraft->multiMotor4->findText(field->getValue().toString()));
field = obj->getField(QString("VTOLMotorW"));
m_aircraft->multiMotor5->setCurrentIndex(m_aircraft->multiMotor4->findText(field->getValue().toString()));
field = obj->getField(QString("VTOLMotorNW"));
m_aircraft->multiMotor6->setCurrentIndex(m_aircraft->multiMotor4->findText(field->getValue().toString()));
// Now, read the 1st mixer R/P/Y levels and initialize the mix sliders.
// This assumes that all vectors are identical - if not, the user should use the
// "custom" setting.
obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
int eng= m_aircraft->multiMotor1->currentIndex()-1;
// eng will be -1 if value is set to "None"
if (eng > -1) {
field = obj->getField(mixerVectors.at(eng));
int i = field->getElementNames().indexOf("Pitch");
double val = floor(field->getDouble(i)/1.27);
m_aircraft->mrPitchMixLevel->setValue(val);
i = field->getElementNames().indexOf("Yaw");
val = floor(-field->getDouble(i)/1.27);
m_aircraft->mrYawMixLevel->setValue(val);
eng = m_aircraft->multiMotor2->currentIndex()-1;
field = obj->getField(mixerVectors.at(eng));
i = field->getElementNames().indexOf("Roll");
val = floor(1-field->getDouble(i)/1.27);
m_aircraft->mrRollMixLevel->setValue(val);
}
} else if (frameType == "HexaCoax") {
// Motors 1/2/3 4/5/6 are: NW/W NE/E S/SE
field = obj->getField(QString("VTOLMotorNW"));
m_aircraft->multiMotor1->setCurrentIndex(m_aircraft->multiMotor1->findText(field->getValue().toString()));
field = obj->getField(QString("VTOLMotorW"));
m_aircraft->multiMotor2->setCurrentIndex(m_aircraft->multiMotor2->findText(field->getValue().toString()));
field = obj->getField(QString("VTOLMotorNE"));
m_aircraft->multiMotor3->setCurrentIndex(m_aircraft->multiMotor3->findText(field->getValue().toString()));
field = obj->getField(QString("VTOLMotorE"));
m_aircraft->multiMotor4->setCurrentIndex(m_aircraft->multiMotor4->findText(field->getValue().toString()));
field = obj->getField(QString("VTOLMotorS"));
m_aircraft->multiMotor5->setCurrentIndex(m_aircraft->multiMotor4->findText(field->getValue().toString()));
field = obj->getField(QString("VTOLMotorSE"));
m_aircraft->multiMotor6->setCurrentIndex(m_aircraft->multiMotor4->findText(field->getValue().toString()));
// Now, read the 1st mixer R/P/Y levels and initialize the mix sliders.
// This assumes that all vectors are identical - if not, the user should use the
// "custom" setting.
obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
int eng= m_aircraft->multiMotor1->currentIndex()-1;
// eng will be -1 if value is set to "None"
if (eng > -1) {
field = obj->getField(mixerVectors.at(eng));
int i = field->getElementNames().indexOf("Pitch");
double val = floor(2*field->getDouble(i)/1.27);
m_aircraft->mrPitchMixLevel->setValue(val);
i = field->getElementNames().indexOf("Yaw");
val = floor(-field->getDouble(i)/1.27);
m_aircraft->mrYawMixLevel->setValue(val);
i = field->getElementNames().indexOf("Roll");
val = floor(field->getDouble(i)/1.27);
m_aircraft->mrRollMixLevel->setValue(val);
}
} else if (frameType == "Octo" || frameType == "OctoV" ||
frameType == "OctoCoaxP") {
// Motors 1 to 8 are N / NE / E / etc
field = obj->getField(QString("VTOLMotorN"));
Q_ASSERT(field);
m_aircraft->multiMotor1->setCurrentIndex(m_aircraft->multiMotor1->findText(field->getValue().toString()));
field = obj->getField(QString("VTOLMotorNE"));
Q_ASSERT(field);
m_aircraft->multiMotor2->setCurrentIndex(m_aircraft->multiMotor2->findText(field->getValue().toString()));
field = obj->getField(QString("VTOLMotorE"));
Q_ASSERT(field);
m_aircraft->multiMotor3->setCurrentIndex(m_aircraft->multiMotor3->findText(field->getValue().toString()));
field = obj->getField(QString("VTOLMotorSE"));
Q_ASSERT(field);
m_aircraft->multiMotor4->setCurrentIndex(m_aircraft->multiMotor4->findText(field->getValue().toString()));
field = obj->getField(QString("VTOLMotorS"));
Q_ASSERT(field);
m_aircraft->multiMotor5->setCurrentIndex(m_aircraft->multiMotor4->findText(field->getValue().toString()));
field = obj->getField(QString("VTOLMotorSW"));
Q_ASSERT(field);
m_aircraft->multiMotor6->setCurrentIndex(m_aircraft->multiMotor4->findText(field->getValue().toString()));
field = obj->getField(QString("VTOLMotorW"));
Q_ASSERT(field);
m_aircraft->multiMotor7->setCurrentIndex(m_aircraft->multiMotor4->findText(field->getValue().toString()));
field = obj->getField(QString("VTOLMotorNW"));
Q_ASSERT(field);
m_aircraft->multiMotor8->setCurrentIndex(m_aircraft->multiMotor4->findText(field->getValue().toString()));
// Now, read the 1st mixer R/P/Y levels and initialize the mix sliders.
// This assumes that all vectors are identical - if not, the user should use the
// "custom" setting.
obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
int eng= m_aircraft->multiMotor1->currentIndex()-1;
// eng will be -1 if value is set to "None"
if (eng > -1) {
if (frameType == "Octo") {
field = obj->getField(mixerVectors.at(eng));
int i = field->getElementNames().indexOf("Pitch");
double val = floor(field->getDouble(i)/1.27);
m_aircraft->mrPitchMixLevel->setValue(val);
i = field->getElementNames().indexOf("Yaw");
val = floor(-field->getDouble(i)/1.27);
m_aircraft->mrYawMixLevel->setValue(val);
eng = m_aircraft->multiMotor2->currentIndex()-1;
field = obj->getField(mixerVectors.at(eng));
i = field->getElementNames().indexOf("Roll");
val = floor(-field->getDouble(i)/1.27);
m_aircraft->mrRollMixLevel->setValue(val);
} else if (frameType == "OctoV") {
field = obj->getField(mixerVectors.at(eng));
int i = field->getElementNames().indexOf("Yaw");
double val = floor(-field->getDouble(i)/1.27);
m_aircraft->mrYawMixLevel->setValue(val);
i = field->getElementNames().indexOf("Roll");
val = floor(-field->getDouble(i)/1.27);
m_aircraft->mrRollMixLevel->setValue(val);
eng = m_aircraft->multiMotor2->currentIndex()-1;
field = obj->getField(mixerVectors.at(eng));
i = field->getElementNames().indexOf("Pitch");
val = floor(field->getDouble(i)/1.27);
m_aircraft->mrPitchMixLevel->setValue(val);
} else if (frameType == "OctoCoaxP") {
field = obj->getField(mixerVectors.at(eng));
int i = field->getElementNames().indexOf("Pitch");
double val = floor(field->getDouble(i)/1.27);
m_aircraft->mrPitchMixLevel->setValue(val);
i = field->getElementNames().indexOf("Yaw");
val = floor(-field->getDouble(i)/1.27);
m_aircraft->mrYawMixLevel->setValue(val);
eng = m_aircraft->multiMotor3->currentIndex()-1;
field = obj->getField(mixerVectors.at(eng));
i = field->getElementNames().indexOf("Roll");
val = floor(-field->getDouble(i)/1.27);
m_aircraft->mrRollMixLevel->setValue(val);
}
}
} else if (frameType == "OctoCoaxX") {
// Motors 1 to 8 are N / NE / E / etc
field = obj->getField(QString("VTOLMotorNW"));
Q_ASSERT(field);
m_aircraft->multiMotor1->setCurrentIndex(m_aircraft->multiMotor1->findText(field->getValue().toString()));
field = obj->getField(QString("VTOLMotorN"));
Q_ASSERT(field);
m_aircraft->multiMotor2->setCurrentIndex(m_aircraft->multiMotor2->findText(field->getValue().toString()));
field = obj->getField(QString("VTOLMotorNE"));
Q_ASSERT(field);
m_aircraft->multiMotor3->setCurrentIndex(m_aircraft->multiMotor3->findText(field->getValue().toString()));
field = obj->getField(QString("VTOLMotorE"));
Q_ASSERT(field);
m_aircraft->multiMotor4->setCurrentIndex(m_aircraft->multiMotor4->findText(field->getValue().toString()));
field = obj->getField(QString("VTOLMotorSE"));
Q_ASSERT(field);
m_aircraft->multiMotor5->setCurrentIndex(m_aircraft->multiMotor4->findText(field->getValue().toString()));
field = obj->getField(QString("VTOLMotorS"));
Q_ASSERT(field);
m_aircraft->multiMotor6->setCurrentIndex(m_aircraft->multiMotor4->findText(field->getValue().toString()));
field = obj->getField(QString("VTOLMotorSW"));
Q_ASSERT(field);
m_aircraft->multiMotor7->setCurrentIndex(m_aircraft->multiMotor4->findText(field->getValue().toString()));
field = obj->getField(QString("VTOLMotorW"));
Q_ASSERT(field);
m_aircraft->multiMotor8->setCurrentIndex(m_aircraft->multiMotor4->findText(field->getValue().toString()));
// Now, read the 1st mixer R/P/Y levels and initialize the mix sliders.
// This assumes that all vectors are identical - if not, the user should use the
// "custom" setting.
obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
int eng= m_aircraft->multiMotor1->currentIndex()-1;
// eng will be -1 if value is set to "None"
if (eng > -1) {
field = obj->getField(mixerVectors.at(eng));
int i = field->getElementNames().indexOf("Pitch");
double val = floor(field->getDouble(i)/1.27);
m_aircraft->mrPitchMixLevel->setValue(val);
i = field->getElementNames().indexOf("Yaw");
val = floor(-field->getDouble(i)/1.27);
m_aircraft->mrYawMixLevel->setValue(val);
i = field->getElementNames().indexOf("Roll");
val = floor(field->getDouble(i)/1.27);
m_aircraft->mrRollMixLevel->setValue(val);
}
} else if (frameType == "Tri") {
// Motors 1 to 8 are N / NE / E / etc
field = obj->getField(QString("VTOLMotorNW"));
Q_ASSERT(field);
m_aircraft->multiMotor1->setCurrentIndex(m_aircraft->multiMotor1->findText(field->getValue().toString()));
field = obj->getField(QString("VTOLMotorNE"));
Q_ASSERT(field);
m_aircraft->multiMotor2->setCurrentIndex(m_aircraft->multiMotor2->findText(field->getValue().toString()));
field = obj->getField(QString("VTOLMotorS"));
Q_ASSERT(field);
m_aircraft->multiMotor3->setCurrentIndex(m_aircraft->multiMotor3->findText(field->getValue().toString()));
field = obj->getField(QString("FixedWingYaw1"));
Q_ASSERT(field);
m_aircraft->triYawChannel->setCurrentIndex(m_aircraft->multiMotor3->findText(field->getValue().toString()));
obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
int eng= m_aircraft->multiMotor1->currentIndex()-1;
// eng will be -1 if value is set to "None"
if (eng > -1) {
field = obj->getField(mixerVectors.at(eng));
int i = field->getElementNames().indexOf("Pitch");
double val = floor(2*field->getDouble(i)/1.27);
m_aircraft->mrPitchMixLevel->setValue(val);
i = field->getElementNames().indexOf("Roll");
val = floor(field->getDouble(i)/1.27);
m_aircraft->mrRollMixLevel->setValue(val);
}
}
obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
Q_ASSERT(obj);
// Now, retrieve the Feedforward values:
field = obj->getField(QString("FeedForward"));
Q_ASSERT(field);
m_aircraft->feedForwardSlider->setValue(field->getDouble()*100);
field = obj->getField(QString("AccelTime"));
Q_ASSERT(field);
m_aircraft->accelTime->setValue(field->getDouble());
field = obj->getField(QString("DecelTime"));
Q_ASSERT(field);
m_aircraft->decelTime->setValue(field->getDouble());
field = obj->getField(QString("MaxAccel"));
Q_ASSERT(field);
m_aircraft->maxAccelSlider->setValue(field->getDouble());
} else if (frameType == "HeliCP") {
m_aircraft->widget_3->requestccpmUpdate();
m_aircraft->aircraftType->setCurrentIndex(m_aircraft->aircraftType->findText("Helicopter"));//"Helicopter"
} else if (frameType == "Custom") {
m_aircraft->aircraftType->setCurrentIndex(m_aircraft->aircraftType->findText("Custom"));
}
updateCustomAirframeUI();
}
/**
\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->fwRudder1Channel->setEnabled(true);
m_aircraft->fwRudder1Label->setEnabled(true);
m_aircraft->fwRudder2Channel->setEnabled(true);
m_aircraft->fwRudder2Label->setEnabled(true);
m_aircraft->fwElevator1Channel->setEnabled(true);
m_aircraft->fwElevator1Label->setEnabled(true);
m_aircraft->fwElevator2Channel->setEnabled(true);
m_aircraft->fwElevator2Label->setEnabled(true);
m_aircraft->fwAileron1Channel->setEnabled(true);
m_aircraft->fwAileron1Label->setEnabled(true);
m_aircraft->fwAileron2Channel->setEnabled(true);
m_aircraft->fwAileron2Label->setEnabled(true);
m_aircraft->fwAileron1Label->setText("Aileron 1");
m_aircraft->fwAileron2Label->setText("Aileron 2");
m_aircraft->fwElevator1Label->setText("Elevator 1");
m_aircraft->fwElevator2Label->setText("Elevator 2");
m_aircraft->elevonMixBox->setHidden(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->fwAileron1Label->setText("Elevon 1");
m_aircraft->fwAileron2Label->setText("Elevon 2");
m_aircraft->fwElevator1Channel->setEnabled(false);
m_aircraft->fwElevator1Label->setEnabled(false);
m_aircraft->fwElevator2Channel->setEnabled(false);
m_aircraft->fwElevator2Label->setEnabled(false);
m_aircraft->fwRudder1Channel->setEnabled(true);
m_aircraft->fwRudder1Label->setEnabled(true);
m_aircraft->fwRudder2Channel->setEnabled(true);
m_aircraft->fwRudder2Label->setEnabled(true);
m_aircraft->fwElevator1Label->setText("Elevator 1");
m_aircraft->fwElevator2Label->setText("Elevator 2");
m_aircraft->elevonMixBox->setHidden(false);
m_aircraft->elevonLabel1->setText("Roll");
m_aircraft->elevonLabel2->setText("Pitch");
} 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->fwRudder1Channel->setEnabled(false);
m_aircraft->fwRudder1Label->setEnabled(false);
m_aircraft->fwRudder2Channel->setEnabled(false);
m_aircraft->fwRudder2Label->setEnabled(false);
m_aircraft->fwElevator1Channel->setEnabled(true);
m_aircraft->fwElevator1Label->setEnabled(true);
m_aircraft->fwElevator1Label->setText("Vtail 1");
m_aircraft->fwElevator2Label->setText("Vtail 2");
m_aircraft->elevonMixBox->setHidden(false);
m_aircraft->fwElevator2Channel->setEnabled(true);
m_aircraft->fwElevator2Label->setEnabled(true);
m_aircraft->fwAileron1Label->setText("Aileron 1");
m_aircraft->fwAileron2Label->setText("Aileron 2");
m_aircraft->elevonLabel1->setText("Rudder");
m_aircraft->elevonLabel2->setText("Pitch");
} else if (frameType == "QuadX" || frameType == "Quad X") {
m_aircraft->aircraftType->setCurrentIndex(m_aircraft->aircraftType->findText("Multirotor"));
m_aircraft->multirotorFrameType->setCurrentIndex(m_aircraft->multirotorFrameType->findText("Quad X"));
quad->setElementId("quad-X");
m_aircraft->multiMotor4->setEnabled(true);
m_aircraft->multiMotor5->setEnabled(false);
m_aircraft->multiMotor6->setEnabled(false);
m_aircraft->multiMotor7->setEnabled(false);
m_aircraft->multiMotor8->setEnabled(false);
m_aircraft->triYawChannel->setEnabled(false);
m_aircraft->mrRollMixLevel->setValue(50);
m_aircraft->mrPitchMixLevel->setValue(50);
m_aircraft->mrYawMixLevel->setValue(50);
} else if (frameType == "QuadP" || frameType == "Quad +") {
m_aircraft->aircraftType->setCurrentIndex(m_aircraft->aircraftType->findText("Multirotor"));
m_aircraft->multirotorFrameType->setCurrentIndex(m_aircraft->multirotorFrameType->findText("Quad +"));
quad->setElementId("quad-plus");
m_aircraft->multiMotor4->setEnabled(true);
m_aircraft->multiMotor5->setEnabled(false);
m_aircraft->multiMotor6->setEnabled(false);
m_aircraft->multiMotor7->setEnabled(false);
m_aircraft->multiMotor8->setEnabled(false);
m_aircraft->triYawChannel->setEnabled(false);
m_aircraft->mrRollMixLevel->setValue(100);
m_aircraft->mrPitchMixLevel->setValue(100);
m_aircraft->mrYawMixLevel->setValue(50);
} else if (frameType == "Hexa" || frameType == "Hexacopter") {
m_aircraft->aircraftType->setCurrentIndex(m_aircraft->aircraftType->findText("Multirotor"));
m_aircraft->multirotorFrameType->setCurrentIndex(m_aircraft->multirotorFrameType->findText("Hexacopter"));
quad->setElementId("quad-hexa");
m_aircraft->multiMotor4->setEnabled(true);
m_aircraft->multiMotor5->setEnabled(true);
m_aircraft->multiMotor6->setEnabled(true);
m_aircraft->multiMotor7->setEnabled(false);
m_aircraft->multiMotor8->setEnabled(false);
m_aircraft->triYawChannel->setEnabled(false);
m_aircraft->mrRollMixLevel->setValue(50);
m_aircraft->mrPitchMixLevel->setValue(33);
m_aircraft->mrYawMixLevel->setValue(33);
} else if (frameType == "Octo" || frameType == "Octocopter") {
m_aircraft->aircraftType->setCurrentIndex(m_aircraft->aircraftType->findText("Multirotor"));
m_aircraft->multirotorFrameType->setCurrentIndex(m_aircraft->multirotorFrameType->findText("Octocopter"));
quad->setElementId("quad-octo");
m_aircraft->multiMotor4->setEnabled(true);
m_aircraft->multiMotor5->setEnabled(true);
m_aircraft->multiMotor6->setEnabled(true);
m_aircraft->multiMotor7->setEnabled(true);
m_aircraft->multiMotor8->setEnabled(true);
m_aircraft->triYawChannel->setEnabled(false);
m_aircraft->mrRollMixLevel->setValue(33);
m_aircraft->mrPitchMixLevel->setValue(33);
m_aircraft->mrYawMixLevel->setValue(25);
} else if (frameType == "HexaX" || frameType == "Hexacopter X" ) {
m_aircraft->aircraftType->setCurrentIndex(m_aircraft->aircraftType->findText("Multirotor"));
m_aircraft->multirotorFrameType->setCurrentIndex(m_aircraft->multirotorFrameType->findText("Hexacopter X"));
quad->setElementId("quad-hexa-H");
m_aircraft->multiMotor4->setEnabled(true);
m_aircraft->multiMotor5->setEnabled(true);
m_aircraft->multiMotor6->setEnabled(true);
m_aircraft->multiMotor7->setEnabled(false);
m_aircraft->multiMotor8->setEnabled(false);
m_aircraft->triYawChannel->setEnabled(false);
m_aircraft->mrRollMixLevel->setValue(33);
m_aircraft->mrPitchMixLevel->setValue(50);
m_aircraft->mrYawMixLevel->setValue(33);
} else if (frameType == "OctoV" || frameType == "Octocopter V") {
m_aircraft->aircraftType->setCurrentIndex(m_aircraft->aircraftType->findText("Multirotor"));
m_aircraft->multirotorFrameType->setCurrentIndex(m_aircraft->multirotorFrameType->findText("Octocopter V"));
quad->setElementId("quad-octo-v");
m_aircraft->multiMotor4->setEnabled(true);
m_aircraft->multiMotor5->setEnabled(true);
m_aircraft->multiMotor6->setEnabled(true);
m_aircraft->multiMotor7->setEnabled(true);
m_aircraft->multiMotor8->setEnabled(true);
m_aircraft->triYawChannel->setEnabled(false);
m_aircraft->mrRollMixLevel->setValue(25);
m_aircraft->mrPitchMixLevel->setValue(25);
m_aircraft->mrYawMixLevel->setValue(25);
} else if (frameType == "OctoCoaxP" || frameType == "Octo Coax +") {
m_aircraft->aircraftType->setCurrentIndex(m_aircraft->aircraftType->findText("Multirotor"));
m_aircraft->multirotorFrameType->setCurrentIndex(m_aircraft->multirotorFrameType->findText("Octo Coax +"));
quad->setElementId("octo-coax-P");
m_aircraft->multiMotor4->setEnabled(true);
m_aircraft->multiMotor5->setEnabled(true);
m_aircraft->multiMotor6->setEnabled(true);
m_aircraft->multiMotor7->setEnabled(true);
m_aircraft->multiMotor8->setEnabled(true);
m_aircraft->triYawChannel->setEnabled(false);
m_aircraft->mrRollMixLevel->setValue(100);
m_aircraft->mrPitchMixLevel->setValue(100);
m_aircraft->mrYawMixLevel->setValue(50);
} else if (frameType == "OctoCoaxX" || frameType == "Octo Coax X") {
m_aircraft->aircraftType->setCurrentIndex(m_aircraft->aircraftType->findText("Multirotor"));
m_aircraft->multirotorFrameType->setCurrentIndex(m_aircraft->multirotorFrameType->findText("Octo Coax X"));
quad->setElementId("octo-coax-X");
m_aircraft->multiMotor4->setEnabled(true);
m_aircraft->multiMotor5->setEnabled(true);
m_aircraft->multiMotor6->setEnabled(true);
m_aircraft->multiMotor7->setEnabled(true);
m_aircraft->multiMotor8->setEnabled(true);
m_aircraft->triYawChannel->setEnabled(false);
m_aircraft->mrRollMixLevel->setValue(50);
m_aircraft->mrPitchMixLevel->setValue(50);
m_aircraft->mrYawMixLevel->setValue(50);
} else if (frameType == "HexaCoax" || frameType == "Hexacopter Y6") {
m_aircraft->aircraftType->setCurrentIndex(m_aircraft->aircraftType->findText("Multirotor"));
m_aircraft->multirotorFrameType->setCurrentIndex(m_aircraft->multirotorFrameType->findText("Hexacopter Y6"));
quad->setElementId("hexa-coax");
m_aircraft->multiMotor4->setEnabled(true);
m_aircraft->multiMotor5->setEnabled(true);
m_aircraft->multiMotor6->setEnabled(true);
m_aircraft->multiMotor7->setEnabled(false);
m_aircraft->multiMotor8->setEnabled(false);
m_aircraft->triYawChannel->setEnabled(false);
m_aircraft->mrRollMixLevel->setValue(100);
m_aircraft->mrPitchMixLevel->setValue(50);
m_aircraft->mrYawMixLevel->setValue(66);
} else if (frameType == "Tri" || frameType == "Tricopter Y") {
m_aircraft->aircraftType->setCurrentIndex(m_aircraft->aircraftType->findText("Multirotor"));
m_aircraft->multirotorFrameType->setCurrentIndex(m_aircraft->multirotorFrameType->findText("Tricopter Y"));
quad->setElementId("tri");
m_aircraft->multiMotor4->setEnabled(false);
m_aircraft->multiMotor5->setEnabled(false);
m_aircraft->multiMotor6->setEnabled(false);
m_aircraft->multiMotor7->setEnabled(false);
m_aircraft->multiMotor8->setEnabled(false);
m_aircraft->triYawChannel->setEnabled(true);
}
m_aircraft->quadShape->setSceneRect(quad->boundingRect());
m_aircraft->quadShape->fitInView(quad, Qt::KeepAspectRatio);
}
/**
Reset the contents of a field
*/
void ConfigAirframeWidget::resetField(UAVObjectField * field)
{
for (unsigned int i=0;i<field->getNumElements();i++) {
field->setValue(0,i);
}
}
/**
Reset actuator values
*/
void ConfigAirframeWidget::resetActuators()
{
UAVDataObject* obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("ActuatorSettings")));
Q_ASSERT(obj);
QList<UAVObjectField*> fieldList = obj->getFields();
// Reset all assignements first:
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());
}
}
}
/**
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->fwEngineChannel->currentText() == "None" ||
m_aircraft->fwElevator1Channel->currentText() == "None" ||
((m_aircraft->fwAileron1Channel->currentText() == "None") &&
(m_aircraft->fwRudder1Channel->currentText() == "None"))) {
// TODO: explain the problem in the UI
m_aircraft->fwStatusLabel->setText("ERROR: check channel assignment");
return false;
}
// Now setup the channels:
resetActuators();
UAVDataObject* obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("ActuatorSettings")));
Q_ASSERT(obj);
// 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("FixedWingYaw1");
Q_ASSERT(field);
field->setValue(m_aircraft->fwRudder1Channel->currentText());
// Throttle
field = obj->getField("FixedWingThrottle");
Q_ASSERT(field);
field->setValue(m_aircraft->fwEngineChannel->currentText());
obj->updated();
obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
Q_ASSERT(obj);
// ... 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
// 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
resetField(field);
int ti = field->getElementNames().indexOf("ThrottleCurve1");
field->setValue(127, ti);
// Rudder
eng = m_aircraft->fwRudder1Channel->currentIndex()-1;
// eng will be -1 if rudder is set to "None"
if (eng > -1) {
field = obj->getField(mixerTypes.at(eng));
field->setValue("Servo");
field = obj->getField(mixerVectors.at(eng));
resetField(field);
ti = field->getElementNames().indexOf("Yaw");
field->setValue(127, ti);
} // Else: we have no rudder, only ailerons, we're fine with it.
// Ailerons
eng = m_aircraft->fwAileron1Channel->currentIndex()-1;
if (eng > -1) {
field = obj->getField(mixerTypes.at(eng));
field->setValue("Servo");
field = obj->getField(mixerVectors.at(eng));
resetField(field);
ti = field->getElementNames().indexOf("Roll");
field->setValue(127, ti);
// Only set Aileron 2 if Aileron 1 is defined
eng = m_aircraft->fwAileron2Channel->currentIndex()-1;
if (eng > -1) {
field = obj->getField(mixerTypes.at(eng));
field->setValue("Servo");
field = obj->getField(mixerVectors.at(eng));
resetField(field);
ti = field->getElementNames().indexOf("Roll");
field->setValue(127, ti);
}
} // Else we have no ailerons. Our consistency check guarantees we have
// rudder in this case, so we're fine with it too.
// Elevator
eng = m_aircraft->fwElevator1Channel->currentIndex()-1;
field = obj->getField(mixerTypes.at(eng));
field->setValue("Servo");
field = obj->getField(mixerVectors.at(eng));
resetField(field);
ti = field->getElementNames().indexOf("Pitch");
field->setValue(127, ti);
// Only set Elevator 2 if it is defined
eng = m_aircraft->fwElevator2Channel->currentIndex()-1;
if (eng > -1) {
field = obj->getField(mixerTypes.at(eng));
field->setValue("Servo");
field = obj->getField(mixerVectors.at(eng));
resetField(field);
ti = field->getElementNames().indexOf("Pitch");
field->setValue(127, ti);
}
obj->updated();
m_aircraft->fwStatusLabel->setText("Mixer generated");
return true;
}
/**
Setup Elevon
*/
bool ConfigAirframeWidget::setupFrameElevon()
{
// Check coherence:
// - At least Aileron1 and Aileron 2, and engine
if (m_aircraft->fwEngineChannel->currentText() == "None" ||
m_aircraft->fwAileron1Channel->currentText() == "None" ||
m_aircraft->fwAileron2Channel->currentText() == "None") {
// TODO: explain the problem in the UI
m_aircraft->fwStatusLabel->setText("ERROR: check channel assignment");
return false;
}
resetActuators();
UAVDataObject* obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("ActuatorSettings")));
Q_ASSERT(obj);
// Elevons
UAVObjectField *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 1 (can be None)
field = obj->getField("FixedWingYaw1");
Q_ASSERT(field);
field->setValue(m_aircraft->fwRudder1Channel->currentText());
// Rudder 2 (can be None)
field = obj->getField("FixedWingYaw2");
Q_ASSERT(field);
field->setValue(m_aircraft->fwRudder2Channel->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);
// ... 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
// 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
resetField(field);
int ti = field->getElementNames().indexOf("ThrottleCurve1");
field->setValue(127, ti);
// Rudder 1
eng = m_aircraft->fwRudder1Channel->currentIndex()-1;
// eng will be -1 if rudder 1 is set to "None"
if (eng > -1) {
field = obj->getField(mixerTypes.at(eng));
field->setValue("Servo");
field = obj->getField(mixerVectors.at(eng));
resetField(field);
ti = field->getElementNames().indexOf("Yaw");
field->setValue(127, ti);
} // Else: we have no rudder, only elevons, we're fine with it.
// Rudder 2
eng = m_aircraft->fwRudder2Channel->currentIndex()-1;
// eng will be -1 if rudder 2 is set to "None"
if (eng > -1) {
field = obj->getField(mixerTypes.at(eng));
field->setValue("Servo");
field = obj->getField(mixerVectors.at(eng));
resetField(field);
ti = field->getElementNames().indexOf("Yaw");
field->setValue(-127, ti);
} // Else: we have no rudder, only elevons, we're fine with it.
eng = m_aircraft->fwAileron1Channel->currentIndex()-1;
if (eng > -1) {
field = obj->getField(mixerTypes.at(eng));
field->setValue("Servo");
field = obj->getField(mixerVectors.at(eng));
resetField(field);
ti = field->getElementNames().indexOf("Pitch");
field->setValue((double)m_aircraft->elevonSlider2->value()*1.27, ti);
ti = field->getElementNames().indexOf("Roll");
field->setValue((double)m_aircraft->elevonSlider1->value()*1.27,ti);
}
eng = m_aircraft->fwAileron2Channel->currentIndex()-1;
if (eng > -1) {
field = obj->getField(mixerTypes.at(eng));
field->setValue("Servo");
field = obj->getField(mixerVectors.at(eng));
resetField(field);
ti = field->getElementNames().indexOf("Pitch");
field->setValue((double)m_aircraft->elevonSlider2->value()*1.27, ti);
ti = field->getElementNames().indexOf("Roll");
field->setValue(-(double)m_aircraft->elevonSlider1->value()*1.27,ti);
}
obj->updated();
m_aircraft->fwStatusLabel->setText("Mixer generated");
return true;
}
/**
Setup VTail
*/
bool ConfigAirframeWidget::setupFrameVtail()
{
// Check coherence:
// - At least Pitch1 and Pitch2, and engine
if (m_aircraft->fwEngineChannel->currentText() == "None" ||
m_aircraft->fwElevator1Channel->currentText() == "None" ||
m_aircraft->fwElevator2Channel->currentText() == "None") {
// TODO: explain the problem in the UI
m_aircraft->fwStatusLabel->setText("WARNING: check channel assignment");
return false;
}
resetActuators();
UAVDataObject* obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("ActuatorSettings")));
Q_ASSERT(obj);
// Elevons
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());
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());
// Throttle
field = obj->getField("FixedWingThrottle");
Q_ASSERT(field);
field->setValue(m_aircraft->fwEngineChannel->currentText());
obj->updated();
obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
Q_ASSERT(obj);
// ... 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
// 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
resetField(field);
int ti = field->getElementNames().indexOf("ThrottleCurve1");
field->setValue(127, ti);
eng = m_aircraft->fwAileron1Channel->currentIndex()-1;
if (eng > -1) {
field = obj->getField(mixerTypes.at(eng));
field->setValue("Servo");
field = obj->getField(mixerVectors.at(eng));
resetField(field);
ti = field->getElementNames().indexOf("Roll");
field->setValue(127,ti);
}
eng = m_aircraft->fwAileron2Channel->currentIndex()-1;
if (eng > -1) {
field = obj->getField(mixerTypes.at(eng));
field->setValue("Servo");
field = obj->getField(mixerVectors.at(eng));
resetField(field);
ti = field->getElementNames().indexOf("Roll");
field->setValue(-127,ti);
}
// Now compute the VTail
eng = m_aircraft->fwElevator1Channel->currentIndex()-1;
field = obj->getField(mixerTypes.at(eng));
field->setValue("Servo");
field = obj->getField(mixerVectors.at(eng));
resetField(field);
ti = field->getElementNames().indexOf("Pitch");
field->setValue((double)m_aircraft->elevonSlider2->value()*1.27, ti);
ti = field->getElementNames().indexOf("Yaw");
field->setValue((double)m_aircraft->elevonSlider1->value()*1.27,ti);
eng = m_aircraft->fwElevator2Channel->currentIndex()-1;
field = obj->getField(mixerTypes.at(eng));
field->setValue("Servo");
field = obj->getField(mixerVectors.at(eng));
resetField(field);
ti = field->getElementNames().indexOf("Pitch");
field->setValue((double)m_aircraft->elevonSlider2->value()*1.27, ti);
ti = field->getElementNames().indexOf("Yaw");
field->setValue(-(double)m_aircraft->elevonSlider1->value()*1.27,ti);
obj->updated();
m_aircraft->fwStatusLabel->setText("Mixer generated");
return true;
}
/**
Set up a complete mixer, taking a table of factors. The factors
shoudl mainly be +/- 1 factors, since they will be weighted by the
value of the Pitch/Roll/Yaw sliders.
Example:
double xMixer [8][3] = {
P R Y
{ 1, 1, -1}, Motor 1
{ 1, -1, 1}, Motor 2
{-1, -1, -1}, Motor 3
{-1, 1, 1}, ...
{ 0, 0, 0},
{ 0, 0, 0},
{ 0, 0, 0},
{ 0, 0, 0}
};
*/
bool ConfigAirframeWidget::setupMixer(double mixerFactors[8][3])
{
UAVObjectField *field;
QList<QComboBox*> mmList;
mmList << m_aircraft->multiMotor1 << m_aircraft->multiMotor2 << m_aircraft->multiMotor3
<< m_aircraft->multiMotor4 << m_aircraft->multiMotor5 << m_aircraft->multiMotor6
<< m_aircraft->multiMotor7 << m_aircraft->multiMotor8;
UAVDataObject *obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
// 1. Assign the servo/motor/none for each channel
// Disable all
foreach(QString mixer, mixerTypes) {
field = obj->getField(mixer);
Q_ASSERT(field);
field->setValue("Disabled");
}
// and enable only the relevant channels:
double pFactor = (double)m_aircraft->mrPitchMixLevel->value()/100;
double rFactor = (double)m_aircraft->mrRollMixLevel->value()/100;
double yFactor = (double)m_aircraft->mrYawMixLevel->value()/100;
for (int i=0 ; i<8; i++) {
int channel = mmList.at(i)->currentIndex()-1;
if (channel > -1)
setupQuadMotor(channel, mixerFactors[i][0]*pFactor,
rFactor*mixerFactors[i][1], yFactor*mixerFactors[i][2]);
}
// obj->updated(); // Let caller do this...
return true;
}
/**
Help function: setupQuadMotor
*/
void ConfigAirframeWidget::setupQuadMotor(int channel, double pitch, double roll, double yaw)
{
UAVDataObject* obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
Q_ASSERT(obj);
UAVObjectField *field = obj->getField(mixerTypes.at(channel));
field->setValue("Motor");
field = obj->getField(mixerVectors.at(channel));
// First of all reset the vector
resetField(field);
int ti = field->getElementNames().indexOf("ThrottleCurve1");
field->setValue(127, ti);
ti = field->getElementNames().indexOf("Roll");
field->setValue(roll*127,ti);
ti = field->getElementNames().indexOf("Pitch");
field->setValue(pitch*127,ti);
ti = field->getElementNames().indexOf("Yaw");
field->setValue(yaw*127,ti);
}
/**
Helper function: setup motors. Takes a list of channel names in input.
*/
void ConfigAirframeWidget::setupMotors(QList<QString> motorList)
{
resetActuators();
UAVDataObject* obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("ActuatorSettings")));
Q_ASSERT(obj);
UAVObjectField *field;
QList<QComboBox*> mmList;
mmList << m_aircraft->multiMotor1 << m_aircraft->multiMotor2 << m_aircraft->multiMotor3
<< m_aircraft->multiMotor4 << m_aircraft->multiMotor5 << m_aircraft->multiMotor6
<< m_aircraft->multiMotor7 << m_aircraft->multiMotor8;
foreach (QString motor, motorList) {
field = obj->getField(motor);
field->setValue(mmList.takeFirst()->currentText());
}
// obj->updated(); // Do not Save, let the caller do it...
}
/**
Set up a Quad-X or Quad-P
*/
bool ConfigAirframeWidget::setupQuad(bool pLayout)
{
// Check coherence:
// - Four engines have to be defined
if (m_aircraft->multiMotor1->currentText() == "None" ||
m_aircraft->multiMotor2->currentText() == "None" ||
m_aircraft->multiMotor3->currentText() == "None" ||
m_aircraft->multiMotor4->currentText() == "None") {
m_aircraft->mrStatusLabel->setText("ERROR: Assign 4 motor channels");
return false;
}
QList<QString> motorList;
if (pLayout) {
motorList << "VTOLMotorN" << "VTOLMotorE" << "VTOLMotorS"
<< "VTOLMotorW";
} else {
motorList << "VTOLMotorNW" << "VTOLMotorNE" << "VTOLMotorSE"
<< "VTOLMotorSW";
}
setupMotors(motorList);
// Now, setup the mixer:
// Motor 1 to 4, X Layout:
// pitch roll yaw
// {0.5 ,0.5 ,-0.5 //Front left motor (CW)
// {0.5 ,-0.5 ,0.5 //Front right motor(CCW)
// {-0.5 ,-0.5 ,-0.5 //rear right motor (CW)
// {-0.5 ,0.5 ,0.5 //Rear left motor (CCW)
double xMixer [8][3] = {
{ 1, 1, -1},
{ 1, -1, 1},
{-1, -1, -1},
{-1, 1, 1},
{ 0, 0, 0},
{ 0, 0, 0},
{ 0, 0, 0},
{ 0, 0, 0}
};
//
// Motor 1 to 4, P Layout:
// pitch roll yaw
// {1 ,0 ,-0.5 //Front motor (CW)
// {0 ,-1 ,0.5 //Right motor(CCW)
// {-1 ,0 ,-0.5 //Rear motor (CW)
// {0 ,1 ,0.5 //Left motor (CCW)
double pMixer [8][3] = {
{ 1, 0, -1},
{ 0, -1, 1},
{-1, 0, -1},
{ 0, 1, 1},
{ 0, 0, 0},
{ 0, 0, 0},
{ 0, 0, 0},
{ 0, 0, 0}
};
if (pLayout) {
setupMixer(pMixer);
} else {
setupMixer(xMixer);
}
m_aircraft->mrStatusLabel->setText("SUCCESS: Mixer Saved OK");
return true;
}
/**
Set up a Hexa-X or Hexa-P
*/
bool ConfigAirframeWidget::setupHexa(bool pLayout)
{
// Check coherence:
// - Four engines have to be defined
if (m_aircraft->multiMotor1->currentText() == "None" ||
m_aircraft->multiMotor2->currentText() == "None" ||
m_aircraft->multiMotor3->currentText() == "None" ||
m_aircraft->multiMotor4->currentText() == "None" ||
m_aircraft->multiMotor5->currentText() == "None" ||
m_aircraft->multiMotor6->currentText() == "None") {
m_aircraft->mrStatusLabel->setText("ERROR: Assign 6 motor channels");
return false;
}
QList<QString> motorList;
if (pLayout) {
motorList << "VTOLMotorN" << "VTOLMotorNE" << "VTOLMotorSE"
<< "VTOLMotorS" << "VTOLMotorSW" << "VTOLMotorNW";
} else {
motorList << "VTOLMotorNE" << "VTOLMotorE" << "VTOLMotorSE"
<< "VTOLMotorSW" << "VTOLMotorW" << "VTOLMotorNW";
}
setupMotors(motorList);
// and set only the relevant channels:
// Motor 1 to 6, P Layout:
// pitch roll yaw
// 1 { 0.3 , 0 ,-0.3 // N CW
// 2 { 0.3 ,-0.5 , 0.3 // NE CCW
// 3 {-0.3 ,-0.5 ,-0.3 // SE CW
// 4 {-0.3 , 0 , 0.3 // S CCW
// 5 {-0.3 , 0.5 ,-0.3 // SW CW
// 6 { 0.3 , 0.5 , 0.3 // NW CCW
double pMixer [8][3] = {
{ 1, 0, -1},
{ 1, -1, 1},
{-1, -1, -1},
{-1, 0, 1},
{-1, 1, -1},
{ 1, 1, 1},
{ 0, 0, 0},
{ 0, 0, 0}
};
//
// Motor 1 to 6, X Layout:
// 1 [ 0.5, -0.3, -0.3 ] NE
// 2 [ 0 , -0.3, 0.3 ] E
// 3 [ -0.5, -0.3, -0.3 ] SE
// 4 [ -0.5, 0.3, 0.3 ] SW
// 5 [ 0 , 0.3, -0.3 ] W
// 6 [ 0.5, 0.3, 0.3 ] NW
double xMixer [8][3] = {
{ 1, -1, -1},
{ 0, -1, 1},
{ -1, -1, -1},
{ -1, 1, 1},
{ 0, 1, -1},
{ 1, 1, 1},
{ 0, 0, 0},
{ 0, 0, 0}
};
if (pLayout) {
setupMixer(pMixer);
} else {
setupMixer(xMixer);
}
m_aircraft->mrStatusLabel->setText("SUCCESS: Mixer Saved OK");
return true;
}
/**
Updates the custom airframe settings based on the current airframe.
Note: does NOT ask for an object refresh itself!
*/
void ConfigAirframeWidget::updateCustomAirframeUI()
{
UAVDataObject* obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
UAVObjectField* field = obj->getField(QString("ThrottleCurve1"));
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(i/(field->getNumElements()-1));
}
} else {
for (unsigned int i=0; i < field->getNumElements(); i++) {
curveValues.append(field->getValue(i).toDouble());
}
}
m_aircraft->customThrottle1Curve->initCurve(curveValues);
field = obj->getField(QString("ThrottleCurve2"));
curveValues.clear();;
// 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(i/(field->getNumElements()-1));
}
} else {
for (unsigned int i=0; i < field->getNumElements(); i++) {
curveValues.append(field->getValue(i).toDouble());
}
}
m_aircraft->customThrottle2Curve->initCurve(curveValues);
// Retrieve Feed Forward:
field = obj->getField(QString("FeedForward"));
m_aircraft->customFFSlider->setValue(field->getDouble()*100);
field = obj->getField(QString("AccelTime"));
m_aircraft->customFFaccel->setValue(field->getDouble());
field = obj->getField(QString("DecelTime"));
m_aircraft->customFFdecel->setValue(field->getDouble());
field = obj->getField(QString("MaxAccel"));
m_aircraft->customFFMaxAccel->setValue(field->getDouble());
// Update the table:
for (int i=0; i<8; i++) {
field = obj->getField(mixerTypes.at(i));
QComboBox* q = (QComboBox*)m_aircraft->customMixerTable->cellWidget(0,i);
QString s = field->getValue().toString();
q->setCurrentIndex(q->findText(s));
//bool en = (s != "Disabled");
field = obj->getField(mixerVectors.at(i));
int ti = field->getElementNames().indexOf("ThrottleCurve1");
m_aircraft->customMixerTable->item(1,i)->setText(field->getValue(ti).toString());
ti = field->getElementNames().indexOf("ThrottleCurve2");
m_aircraft->customMixerTable->item(2,i)->setText(field->getValue(ti).toString());
ti = field->getElementNames().indexOf("Roll");
m_aircraft->customMixerTable->item(3,i)->setText(field->getValue(ti).toString());
ti = field->getElementNames().indexOf("Pitch");
m_aircraft->customMixerTable->item(4,i)->setText(field->getValue(ti).toString());
ti = field->getElementNames().indexOf("Yaw");
m_aircraft->customMixerTable->item(5,i)->setText(field->getValue(ti).toString());
}
}
/**
Sends the config to the board (airframe type)
We do all the tasks common to all airframes, or family of airframes, and
we call additional methods for specific frames, so that we do not have a code
that is too heavy.
*/
void ConfigAirframeWidget::sendAircraftUpdate()
{
QString airframeType = "Custom";
if (m_aircraft->aircraftType->currentText() == "Fixed Wing") {
// Save the curve (common to all Fixed wing frames)
UAVDataObject *obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
// Remove Feed Forward, it is pointless on a plane:
UAVObjectField* field = obj->getField(QString("FeedForward"));
field->setDouble(0);
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);
}
if (m_aircraft->fixedWingType->currentText() == "Elevator aileron rudder" ) {
airframeType = "FixedWing";
setupFrameFixedWing();
} else if (m_aircraft->fixedWingType->currentText() == "Elevon") {
airframeType = "FixedWingElevon";
setupFrameElevon();
} else { // "Vtail"
airframeType = "FixedWingVtail";
setupFrameVtail();
}
// Now reflect those settings in the "Custom" panel as well
updateCustomAirframeUI();
} else if (m_aircraft->aircraftType->currentText() == "Multirotor") {
QList<QString> motorList;
// We can already setup the feedforward here, as it is common to all platforms
UAVDataObject* obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
UAVObjectField* field = obj->getField(QString("FeedForward"));
field->setDouble((double)m_aircraft->feedForwardSlider->value()/100);
field = obj->getField(QString("AccelTime"));
field->setDouble(m_aircraft->accelTime->value());
field = obj->getField(QString("DecelTime"));
field->setDouble(m_aircraft->decelTime->value());
field = obj->getField(QString("MaxAccel"));
field->setDouble(m_aircraft->maxAccelSlider->value());
// Curve is also common to all quads:
field = obj->getField("ThrottleCurve1");
QList<double> curve = m_aircraft->multiThrottleCurve->getCurve();
for (int i=0;i<curve.length();i++) {
field->setValue(curve.at(i),i);
}
if (m_aircraft->multirotorFrameType->currentText() == "Quad +") {
airframeType = "QuadP";
setupQuad(true);
} else if (m_aircraft->multirotorFrameType->currentText() == "Quad X") {
airframeType = "QuadX";
setupQuad(false);
} else if (m_aircraft->multirotorFrameType->currentText() == "Hexacopter") {
airframeType = "Hexa";
setupHexa(true);
} else if (m_aircraft->multirotorFrameType->currentText() == "Octocopter") {
airframeType = "Octo";
if (m_aircraft->multiMotor1->currentText() == "None" ||
m_aircraft->multiMotor2->currentText() == "None" ||
m_aircraft->multiMotor3->currentText() == "None" ||
m_aircraft->multiMotor4->currentText() == "None" ||
m_aircraft->multiMotor5->currentText() == "None" ||
m_aircraft->multiMotor6->currentText() == "None" ||
m_aircraft->multiMotor7->currentText() == "None" ||
m_aircraft->multiMotor8->currentText() == "None") {
m_aircraft->mrStatusLabel->setText("ERROR: Assign 8 motor channels");
return;
}
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}
};
setupMixer(mixer);
m_aircraft->mrStatusLabel->setText("SUCCESS: Mixer Saved OK");
} else if (m_aircraft->multirotorFrameType->currentText() == "Hexacopter X") {
airframeType = "HexaX";
setupHexa(false);
} else if (m_aircraft->multirotorFrameType->currentText() == "Octocopter V") {
airframeType = "OctoV";
if (m_aircraft->multiMotor1->currentText() == "None" ||
m_aircraft->multiMotor2->currentText() == "None" ||
m_aircraft->multiMotor3->currentText() == "None" ||
m_aircraft->multiMotor4->currentText() == "None" ||
m_aircraft->multiMotor5->currentText() == "None" ||
m_aircraft->multiMotor6->currentText() == "None" ||
m_aircraft->multiMotor7->currentText() == "None" ||
m_aircraft->multiMotor8->currentText() == "None") {
m_aircraft->mrStatusLabel->setText("ERROR: Assign 8 motor channels");
return;
}
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}
};
setupMixer(mixer);
m_aircraft->mrStatusLabel->setText("SUCCESS: Mixer Saved OK");
} else if (m_aircraft->multirotorFrameType->currentText() == "Octo Coax +") {
airframeType = "OctoCoaxP";
if (m_aircraft->multiMotor1->currentText() == "None" ||
m_aircraft->multiMotor2->currentText() == "None" ||
m_aircraft->multiMotor3->currentText() == "None" ||
m_aircraft->multiMotor4->currentText() == "None" ||
m_aircraft->multiMotor5->currentText() == "None" ||
m_aircraft->multiMotor6->currentText() == "None" ||
m_aircraft->multiMotor7->currentText() == "None" ||
m_aircraft->multiMotor8->currentText() == "None") {
m_aircraft->mrStatusLabel->setText("ERROR: Assign 8 motor channels");
return;
}
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}
};
setupMixer(mixer);
m_aircraft->mrStatusLabel->setText("SUCCESS: Mixer Saved OK");
} else if (m_aircraft->multirotorFrameType->currentText() == "Octo Coax X") {
airframeType = "OctoCoaxX";
if (m_aircraft->multiMotor1->currentText() == "None" ||
m_aircraft->multiMotor2->currentText() == "None" ||
m_aircraft->multiMotor3->currentText() == "None" ||
m_aircraft->multiMotor4->currentText() == "None" ||
m_aircraft->multiMotor5->currentText() == "None" ||
m_aircraft->multiMotor6->currentText() == "None" ||
m_aircraft->multiMotor7->currentText() == "None" ||
m_aircraft->multiMotor8->currentText() == "None") {
m_aircraft->mrStatusLabel->setText("ERROR: Assign 8 motor channels");
return;
}
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}
};
setupMixer(mixer);
m_aircraft->mrStatusLabel->setText("SUCCESS: Mixer Saved OK");
} else if (m_aircraft->multirotorFrameType->currentText() == "Hexacopter Y6") {
airframeType = "HexaCoax";
if (m_aircraft->multiMotor1->currentText() == "None" ||
m_aircraft->multiMotor2->currentText() == "None" ||
m_aircraft->multiMotor3->currentText() == "None" ||
m_aircraft->multiMotor4->currentText() == "None" ||
m_aircraft->multiMotor5->currentText() == "None" ||
m_aircraft->multiMotor6->currentText() == "None" ) {
m_aircraft->mrStatusLabel->setText("ERROR: Assign 6 motor channels");
return;
}
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}
};
setupMixer(mixer);
m_aircraft->mrStatusLabel->setText("SUCCESS: Mixer Saved OK");
} else if (m_aircraft->multirotorFrameType->currentText() == "Tricopter Y") {
airframeType = "Tri";
if (m_aircraft->multiMotor1->currentText() == "None" ||
m_aircraft->multiMotor2->currentText() == "None" ||
m_aircraft->multiMotor3->currentText() == "None" ) {
m_aircraft->mrStatusLabel->setText("ERROR: Assign 3 motor channels");
return;
}
if (m_aircraft->triYawChannel->currentText() == "None") {
m_aircraft->mrStatusLabel->setText("Error: Assign a Yaw channel");
return;
}
obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("ActuatorSettings")));
Q_ASSERT(obj);
motorList << "VTOLMotorNW" << "VTOLMotorNE" << "VTOLMotorS";
setupMotors(motorList);
field = obj->getField("FixedWingYaw1");
field->setValue(m_aircraft->triYawChannel->currentText());
// 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}
};
setupMixer(mixer);
int eng = m_aircraft->triYawChannel->currentIndex()-1;
obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
field = obj->getField(mixerTypes.at(eng));
field->setValue("Servo");
field = obj->getField(mixerVectors.at(eng));
resetField(field);
int ti = field->getElementNames().indexOf("Yaw");
field->setValue(127,ti);
m_aircraft->mrStatusLabel->setText("SUCCESS: Mixer Saved OK");
}
// Now reflect those settings in the "Custom" panel as well
updateCustomAirframeUI();
} else if (m_aircraft->aircraftType->currentText() == "Helicopter") {
airframeType = "HeliCP";
m_aircraft->widget_3->sendccpmUpdate();
} else {
airframeType = "Custom";
UAVDataObject* obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
UAVObjectField* field = obj->getField(QString("FeedForward"));
field->setDouble((double)m_aircraft->customFFSlider->value()/100);
field = obj->getField(QString("AccelTime"));
field->setDouble(m_aircraft->customFFaccel->value());
field = obj->getField(QString("DecelTime"));
field->setDouble(m_aircraft->customFFdecel->value());
field = obj->getField(QString("MaxAccel"));
field->setDouble(m_aircraft->customFFMaxAccel->value());
// Curve is also common to all quads:
field = obj->getField("ThrottleCurve1");
QList<double> curve = m_aircraft->customThrottle1Curve->getCurve();
for (int i=0;i<curve.length();i++) {
field->setValue(curve.at(i),i);
}
field = obj->getField("ThrottleCurve2");
curve.clear();
curve = m_aircraft->customThrottle2Curve->getCurve();
for (int i=0;i<curve.length();i++) {
field->setValue(curve.at(i),i);
}
// Update the table:
for (int i=0; i<8; i++) {
field = obj->getField(mixerTypes.at(i));
QComboBox* q = (QComboBox*)m_aircraft->customMixerTable->cellWidget(0,i);
field->setValue(q->currentText());
field = obj->getField(mixerVectors.at(i));
int ti = field->getElementNames().indexOf("ThrottleCurve1");
field->setValue(m_aircraft->customMixerTable->item(1,i)->text(),ti);
ti = field->getElementNames().indexOf("ThrottleCurve2");
field->setValue(m_aircraft->customMixerTable->item(2,i)->text(),ti);
ti = field->getElementNames().indexOf("Roll");
field->setValue(m_aircraft->customMixerTable->item(3,i)->text(),ti);
ti = field->getElementNames().indexOf("Pitch");
field->setValue(m_aircraft->customMixerTable->item(4,i)->text(),ti);
ti = field->getElementNames().indexOf("Yaw");
field->setValue(m_aircraft->customMixerTable->item(5,i)->text(),ti);
}
// obj->updated();
}
UAVDataObject* obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("ActuatorSettings")));
Q_ASSERT(obj);
obj->updated();
obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
Q_ASSERT(obj);
obj->updated();
obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("SystemSettings")));
UAVObjectField* field = obj->getField(QString("AirframeType"));
field->setValue(airframeType);
obj->updated();
}
/**
Send airframe type to the board and request saving to SD card
*/
void ConfigAirframeWidget::saveAircraftUpdate()
{
// Send update so that the latest value is saved
sendAircraftUpdate();
UAVDataObject* obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("SystemSettings")));
Q_ASSERT(obj);
saveObjectToSD(obj);
obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
saveObjectToSD(obj);
obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("ActuatorSettings")));
saveObjectToSD(obj);
}

View File

@ -32,7 +32,7 @@
#include <coreplugin/iuavgadget.h>
ConfigGadgetFactory::ConfigGadgetFactory(QObject *parent) :
IUAVGadgetFactory(QString("ConfigGadget"), tr("Config Gadget"), parent)
IUAVGadgetFactory(QString("ConfigGadget"), tr("Config"), parent)
{
}
@ -50,8 +50,3 @@ IUAVGadgetConfiguration *ConfigGadgetFactory::createConfiguration(QSettings* qSe
{
return new ConfigGadgetConfiguration(QString("ConfigGadget"), qSettings);
}
IOptionsPage *ConfigGadgetFactory::createOptionsPage(IUAVGadgetConfiguration *config)
{
return new ConfigGadgetOptionsPage(qobject_cast<ConfigGadgetConfiguration*>(config));
}

View File

@ -46,7 +46,6 @@ public:
IUAVGadget *createGadget(QWidget *parent);
IUAVGadgetConfiguration *createConfiguration(QSettings* qSettings);
IOptionsPage *createOptionsPage(IUAVGadgetConfiguration *config);
};
#endif // CONFIGGADGETFACTORY_H

View File

@ -0,0 +1,2832 @@
<gcs>
<General>
<OverrideLanguage>en_AU</OverrideLanguage>
<SaveSettingsOnExit>true</SaveSettingsOnExit>
</General>
<KeyBindings>
<size>0</size>
</KeyBindings>
<MainWindow>
<Color>#666666</Color>
<FullScreen>false</FullScreen>
<Maximized>true</Maximized>
</MainWindow>
<Plugins>
<SoundNotifyPlugin>
<configInfo>
<locked>false</locked>
<version>1.0.0</version>
</configInfo>
<data>
<Current>
<arr_1>
<CurrentLanguage></CurrentLanguage>
<DataObject></DataObject>
<ExpireTimeout>0</ExpireTimeout>
<ObjectField></ObjectField>
<Repeat></Repeat>
<SayOrder></SayOrder>
<Sound1></Sound1>
<Sound2></Sound2>
<Sound3></Sound3>
<SoundCollectionPath></SoundCollectionPath>
<Value></Value>
<ValueSpinBox>0</ValueSpinBox>
</arr_1>
<size>1</size>
</Current>
<EnableSound>false</EnableSound>
<listNotifies>
<size>0</size>
</listNotifies>
</data>
</SoundNotifyPlugin>
</Plugins>
<UAVGadgetConfigurations>
<ConfigGadget>
<default>
<configInfo>
<locked>false</locked>
<version>0.0.0</version>
</configInfo>
</default>
</ConfigGadget>
<DialGadget>
<Attitude>
<configInfo>
<locked>false</locked>
<version>0.0.0</version>
</configInfo>
<data>
<beSmooth>false</beSmooth>
<dialBackgroundID>background</dialBackgroundID>
<dialFile>%%DATAPATH%%dials/default/attitude.svg</dialFile>
<dialForegroundID>foreground</dialForegroundID>
<dialNeedleID1>needle</dialNeedleID1>
<dialNeedleID2>needle</dialNeedleID2>
<dialNeedleID3>needle3</dialNeedleID3>
<font>Ubuntu,11,-1,5,50,0,0,0,0,0</font>
<needle1DataObject>AttitudeActual</needle1DataObject>
<needle1Factor>-1</needle1Factor>
<needle1MaxValue>360</needle1MaxValue>
<needle1MinValue>0</needle1MinValue>
<needle1Move>Rotate</needle1Move>
<needle1ObjectField>Roll</needle1ObjectField>
<needle2DataObject>AttitudeActual</needle2DataObject>
<needle2Factor>75</needle2Factor>
<needle2MaxValue>20</needle2MaxValue>
<needle2MinValue>0</needle2MinValue>
<needle2Move>Vertical</needle2Move>
<needle2ObjectField>Pitch</needle2ObjectField>
<needle3DataObject>AttitudeActual</needle3DataObject>
<needle3Factor>-1</needle3Factor>
<needle3MaxValue>360</needle3MaxValue>
<needle3MinValue>0</needle3MinValue>
<needle3Move>Rotate</needle3Move>
<needle3ObjectField>Roll</needle3ObjectField>
<useOpenGLFlag>false</useOpenGLFlag>
</data>
</Attitude>
<Baro__PCT__20Altimeter>
<configInfo>
<locked>false</locked>
<version>0.0.0</version>
</configInfo>
<data>
<beSmooth>false</beSmooth>
<dialBackgroundID>background</dialBackgroundID>
<dialFile>%%DATAPATH%%dials/default/altimeter.svg</dialFile>
<dialForegroundID>foreground</dialForegroundID>
<dialNeedleID1>needle</dialNeedleID1>
<dialNeedleID2>needle2</dialNeedleID2>
<dialNeedleID3>needle3</dialNeedleID3>
<font>Ubuntu,11,-1,5,50,0,0,0,0,0</font>
<needle1DataObject>BaroAltitude</needle1DataObject>
<needle1Factor>1</needle1Factor>
<needle1MaxValue>10</needle1MaxValue>
<needle1MinValue>0</needle1MinValue>
<needle1Move>Rotate</needle1Move>
<needle1ObjectField>Altitude</needle1ObjectField>
<needle2DataObject>BaroAltitude</needle2DataObject>
<needle2Factor>1</needle2Factor>
<needle2MaxValue>100</needle2MaxValue>
<needle2MinValue>0</needle2MinValue>
<needle2Move>Rotate</needle2Move>
<needle2ObjectField>Altitude</needle2ObjectField>
<needle3DataObject>BaroAltitude</needle3DataObject>
<needle3Factor>1</needle3Factor>
<needle3MaxValue>1000</needle3MaxValue>
<needle3MinValue>0</needle3MinValue>
<needle3Move>Rotate</needle3Move>
<needle3ObjectField>Altitude</needle3ObjectField>
<useOpenGLFlag>false</useOpenGLFlag>
</data>
</Baro__PCT__20Altimeter>
<Barometer>
<configInfo>
<locked>false</locked>
<version>0.0.0</version>
</configInfo>
<data>
<beSmooth>false</beSmooth>
<dialBackgroundID>background</dialBackgroundID>
<dialFile>%%DATAPATH%%dials/default/barometer.svg</dialFile>
<dialForegroundID></dialForegroundID>
<dialNeedleID1>needle</dialNeedleID1>
<dialNeedleID2></dialNeedleID2>
<dialNeedleID3></dialNeedleID3>
<font>Ubuntu,11,-1,5,50,0,0,0,0,0</font>
<needle1DataObject>BaroAltitude</needle1DataObject>
<needle1Factor>10</needle1Factor>
<needle1MaxValue>1120</needle1MaxValue>
<needle1MinValue>1000</needle1MinValue>
<needle1Move>Rotate</needle1Move>
<needle1ObjectField>Pressure</needle1ObjectField>
<needle2DataObject>BaroAltitude</needle2DataObject>
<needle2Factor>1</needle2Factor>
<needle2MaxValue>100</needle2MaxValue>
<needle2MinValue>0</needle2MinValue>
<needle2Move>Rotate</needle2Move>
<needle2ObjectField>Altitude</needle2ObjectField>
<needle3DataObject>BaroAltitude</needle3DataObject>
<needle3Factor>1</needle3Factor>
<needle3MaxValue>1000</needle3MaxValue>
<needle3MinValue>0</needle3MinValue>
<needle3Move>Rotate</needle3Move>
<needle3ObjectField>Altitude</needle3ObjectField>
<useOpenGLFlag>false</useOpenGLFlag>
</data>
</Barometer>
<Climbrate>
<configInfo>
<locked>false</locked>
<version>0.0.0</version>
</configInfo>
<data>
<beSmooth>false</beSmooth>
<dialBackgroundID>background</dialBackgroundID>
<dialFile>%%DATAPATH%%dials/default/vsi.svg</dialFile>
<dialForegroundID></dialForegroundID>
<dialNeedleID1>needle</dialNeedleID1>
<dialNeedleID2></dialNeedleID2>
<dialNeedleID3></dialNeedleID3>
<font>Ubuntu,11,-1,5,50,0,0,0,0,0</font>
<needle1DataObject>VelocityActual</needle1DataObject>
<needle1Factor>0.01</needle1Factor>
<needle1MaxValue>12</needle1MaxValue>
<needle1MinValue>-12</needle1MinValue>
<needle1Move>Rotate</needle1Move>
<needle1ObjectField>Down</needle1ObjectField>
<needle2DataObject>BaroAltitude</needle2DataObject>
<needle2Factor>1</needle2Factor>
<needle2MaxValue>100</needle2MaxValue>
<needle2MinValue>0</needle2MinValue>
<needle2Move>Rotate</needle2Move>
<needle2ObjectField>Altitude</needle2ObjectField>
<needle3DataObject>BaroAltitude</needle3DataObject>
<needle3Factor>1</needle3Factor>
<needle3MaxValue>1000</needle3MaxValue>
<needle3MinValue>0</needle3MinValue>
<needle3Move>Rotate</needle3Move>
<needle3ObjectField>Altitude</needle3ObjectField>
<useOpenGLFlag>false</useOpenGLFlag>
</data>
</Climbrate>
<Compass>
<configInfo>
<locked>false</locked>
<version>0.0.0</version>
</configInfo>
<data>
<beSmooth>false</beSmooth>
<dialBackgroundID>background</dialBackgroundID>
<dialFile>%%DATAPATH%%dials/default/compass.svg</dialFile>
<dialForegroundID>foreground</dialForegroundID>
<dialNeedleID1>needle</dialNeedleID1>
<dialNeedleID2></dialNeedleID2>
<dialNeedleID3></dialNeedleID3>
<font>Ubuntu,11,-1,5,50,0,0,0,0,0</font>
<needle1DataObject>AttitudeActual</needle1DataObject>
<needle1Factor>-1</needle1Factor>
<needle1MaxValue>360</needle1MaxValue>
<needle1MinValue>0</needle1MinValue>
<needle1Move>Rotate</needle1Move>
<needle1ObjectField>Yaw</needle1ObjectField>
<needle2DataObject>BaroAltitude</needle2DataObject>
<needle2Factor>1</needle2Factor>
<needle2MaxValue>100</needle2MaxValue>
<needle2MinValue>0</needle2MinValue>
<needle2Move>Rotate</needle2Move>
<needle2ObjectField>Altitude</needle2ObjectField>
<needle3DataObject>BaroAltitude</needle3DataObject>
<needle3Factor>1</needle3Factor>
<needle3MaxValue>1000</needle3MaxValue>
<needle3MinValue>0</needle3MinValue>
<needle3Move>Rotate</needle3Move>
<needle3ObjectField>Altitude</needle3ObjectField>
<useOpenGLFlag>false</useOpenGLFlag>
</data>
</Compass>
<Deluxe__PCT__20Attitude>
<configInfo>
<locked>false</locked>
<version>0.0.0</version>
</configInfo>
<data>
<beSmooth>false</beSmooth>
<dialBackgroundID>background</dialBackgroundID>
<dialFile>%%DATAPATH%%dials/deluxe/attitude.svg</dialFile>
<dialForegroundID>foreground</dialForegroundID>
<dialNeedleID1>needle</dialNeedleID1>
<dialNeedleID2>needle</dialNeedleID2>
<dialNeedleID3>needle3</dialNeedleID3>
<font>Ubuntu,11,-1,5,50,0,0,0,0,0</font>
<needle1DataObject>AttitudeActual</needle1DataObject>
<needle1Factor>-1</needle1Factor>
<needle1MaxValue>360</needle1MaxValue>
<needle1MinValue>0</needle1MinValue>
<needle1Move>Rotate</needle1Move>
<needle1ObjectField>Roll</needle1ObjectField>
<needle2DataObject>AttitudeActual</needle2DataObject>
<needle2Factor>75</needle2Factor>
<needle2MaxValue>20</needle2MaxValue>
<needle2MinValue>0</needle2MinValue>
<needle2Move>Vertical</needle2Move>
<needle2ObjectField>Pitch</needle2ObjectField>
<needle3DataObject>AttitudeActual</needle3DataObject>
<needle3Factor>-1</needle3Factor>
<needle3MaxValue>360</needle3MaxValue>
<needle3MinValue>0</needle3MinValue>
<needle3Move>Rotate</needle3Move>
<needle3ObjectField>Roll</needle3ObjectField>
<useOpenGLFlag>false</useOpenGLFlag>
</data>
</Deluxe__PCT__20Attitude>
<Deluxe__PCT__20Baro__PCT__20Altimeter>
<configInfo>
<locked>false</locked>
<version>0.0.0</version>
</configInfo>
<data>
<beSmooth>false</beSmooth>
<dialBackgroundID>background</dialBackgroundID>
<dialFile>%%DATAPATH%%dials/deluxe/altimeter.svg</dialFile>
<dialForegroundID>foreground</dialForegroundID>
<dialNeedleID1>needle</dialNeedleID1>
<dialNeedleID2>needle2</dialNeedleID2>
<dialNeedleID3>needle3</dialNeedleID3>
<font>Ubuntu,11,-1,5,50,0,0,0,0,0</font>
<needle1DataObject>BaroAltitude</needle1DataObject>
<needle1Factor>1</needle1Factor>
<needle1MaxValue>10</needle1MaxValue>
<needle1MinValue>0</needle1MinValue>
<needle1Move>Rotate</needle1Move>
<needle1ObjectField>Altitude</needle1ObjectField>
<needle2DataObject>BaroAltitude</needle2DataObject>
<needle2Factor>1</needle2Factor>
<needle2MaxValue>100</needle2MaxValue>
<needle2MinValue>0</needle2MinValue>
<needle2Move>Rotate</needle2Move>
<needle2ObjectField>Altitude</needle2ObjectField>
<needle3DataObject>BaroAltitude</needle3DataObject>
<needle3Factor>1</needle3Factor>
<needle3MaxValue>1000</needle3MaxValue>
<needle3MinValue>0</needle3MinValue>
<needle3Move>Rotate</needle3Move>
<needle3ObjectField>Altitude</needle3ObjectField>
<useOpenGLFlag>false</useOpenGLFlag>
</data>
</Deluxe__PCT__20Baro__PCT__20Altimeter>
<Deluxe__PCT__20Barometer>
<configInfo>
<locked>false</locked>
<version>0.0.0</version>
</configInfo>
<data>
<beSmooth>false</beSmooth>
<dialBackgroundID>background</dialBackgroundID>
<dialFile>%%DATAPATH%%dials/deluxe/barometer.svg</dialFile>
<dialForegroundID>foreground</dialForegroundID>
<dialNeedleID1>needle</dialNeedleID1>
<dialNeedleID2></dialNeedleID2>
<dialNeedleID3></dialNeedleID3>
<font>Ubuntu,11,-1,5,50,0,0,0,0,0</font>
<needle1DataObject>BaroAltitude</needle1DataObject>
<needle1Factor>10</needle1Factor>
<needle1MaxValue>1120</needle1MaxValue>
<needle1MinValue>1000</needle1MinValue>
<needle1Move>Rotate</needle1Move>
<needle1ObjectField>Pressure</needle1ObjectField>
<needle2DataObject>BaroAltitude</needle2DataObject>
<needle2Factor>1</needle2Factor>
<needle2MaxValue>100</needle2MaxValue>
<needle2MinValue>0</needle2MinValue>
<needle2Move>Rotate</needle2Move>
<needle2ObjectField>Altitude</needle2ObjectField>
<needle3DataObject>BaroAltitude</needle3DataObject>
<needle3Factor>1</needle3Factor>
<needle3MaxValue>1000</needle3MaxValue>
<needle3MinValue>0</needle3MinValue>
<needle3Move>Rotate</needle3Move>
<needle3ObjectField>Altitude</needle3ObjectField>
<useOpenGLFlag>false</useOpenGLFlag>
</data>
</Deluxe__PCT__20Barometer>
<Deluxe__PCT__20Climbrate>
<configInfo>
<locked>false</locked>
<version>0.0.0</version>
</configInfo>
<data>
<beSmooth>false</beSmooth>
<dialBackgroundID>background</dialBackgroundID>
<dialFile>%%DATAPATH%%dials/deluxe/vsi.svg</dialFile>
<dialForegroundID>foreground</dialForegroundID>
<dialNeedleID1>needle</dialNeedleID1>
<dialNeedleID2></dialNeedleID2>
<dialNeedleID3></dialNeedleID3>
<font>Ubuntu,11,-1,5,50,0,0,0,0,0</font>
<needle1DataObject>VelocityActual</needle1DataObject>
<needle1Factor>0.01</needle1Factor>
<needle1MaxValue>11.2</needle1MaxValue>
<needle1MinValue>-11.2</needle1MinValue>
<needle1Move>Rotate</needle1Move>
<needle1ObjectField>Down</needle1ObjectField>
<needle2DataObject>BaroAltitude</needle2DataObject>
<needle2Factor>1</needle2Factor>
<needle2MaxValue>100</needle2MaxValue>
<needle2MinValue>0</needle2MinValue>
<needle2Move>Rotate</needle2Move>
<needle2ObjectField>Altitude</needle2ObjectField>
<needle3DataObject>BaroAltitude</needle3DataObject>
<needle3Factor>1</needle3Factor>
<needle3MaxValue>1000</needle3MaxValue>
<needle3MinValue>0</needle3MinValue>
<needle3Move>Rotate</needle3Move>
<needle3ObjectField>Altitude</needle3ObjectField>
<useOpenGLFlag>false</useOpenGLFlag>
</data>
</Deluxe__PCT__20Climbrate>
<Deluxe__PCT__20Compass>
<configInfo>
<locked>false</locked>
<version>0.0.0</version>
</configInfo>
<data>
<beSmooth>false</beSmooth>
<dialBackgroundID>background</dialBackgroundID>
<dialFile>%%DATAPATH%%dials/deluxe/compass.svg</dialFile>
<dialForegroundID>foreground</dialForegroundID>
<dialNeedleID1>needle</dialNeedleID1>
<dialNeedleID2></dialNeedleID2>
<dialNeedleID3></dialNeedleID3>
<font>Ubuntu,11,-1,5,50,0,0,0,0,0</font>
<needle1DataObject>AttitudeActual</needle1DataObject>
<needle1Factor>-1</needle1Factor>
<needle1MaxValue>360</needle1MaxValue>
<needle1MinValue>0</needle1MinValue>
<needle1Move>Rotate</needle1Move>
<needle1ObjectField>Yaw</needle1ObjectField>
<needle2DataObject>BaroAltitude</needle2DataObject>
<needle2Factor>1</needle2Factor>
<needle2MaxValue>100</needle2MaxValue>
<needle2MinValue>0</needle2MinValue>
<needle2Move>Rotate</needle2Move>
<needle2ObjectField>Altitude</needle2ObjectField>
<needle3DataObject>BaroAltitude</needle3DataObject>
<needle3Factor>1</needle3Factor>
<needle3MaxValue>1000</needle3MaxValue>
<needle3MinValue>0</needle3MinValue>
<needle3Move>Rotate</needle3Move>
<needle3ObjectField>Altitude</needle3ObjectField>
<useOpenGLFlag>false</useOpenGLFlag>
</data>
</Deluxe__PCT__20Compass>
<Deluxe__PCT__20Groundspeed__PCT__20kph>
<configInfo>
<locked>false</locked>
<version>0.0.0</version>
</configInfo>
<data>
<beSmooth>false</beSmooth>
<dialBackgroundID>background</dialBackgroundID>
<dialFile>%%DATAPATH%%dials/deluxe/speed.svg</dialFile>
<dialForegroundID>foreground</dialForegroundID>
<dialNeedleID1>needle</dialNeedleID1>
<dialNeedleID2></dialNeedleID2>
<dialNeedleID3></dialNeedleID3>
<font>Ubuntu,11,-1,5,50,0,0,0,0,0</font>
<needle1DataObject>GPSPosition</needle1DataObject>
<needle1Factor>3.6</needle1Factor>
<needle1MaxValue>120</needle1MaxValue>
<needle1MinValue>0</needle1MinValue>
<needle1Move>Rotate</needle1Move>
<needle1ObjectField>Groundspeed</needle1ObjectField>
<needle2DataObject>BaroAltitude</needle2DataObject>
<needle2Factor>1</needle2Factor>
<needle2MaxValue>100</needle2MaxValue>
<needle2MinValue>0</needle2MinValue>
<needle2Move>Rotate</needle2Move>
<needle2ObjectField>Altitude</needle2ObjectField>
<needle3DataObject>BaroAltitude</needle3DataObject>
<needle3Factor>1</needle3Factor>
<needle3MaxValue>1000</needle3MaxValue>
<needle3MinValue>0</needle3MinValue>
<needle3Move>Rotate</needle3Move>
<needle3ObjectField>Altitude</needle3ObjectField>
<useOpenGLFlag>false</useOpenGLFlag>
</data>
</Deluxe__PCT__20Groundspeed__PCT__20kph>
<Deluxe__PCT__20Temperature>
<configInfo>
<locked>false</locked>
<version>0.0.0</version>
</configInfo>
<data>
<beSmooth>false</beSmooth>
<dialBackgroundID>background</dialBackgroundID>
<dialFile>%%DATAPATH%%dials/deluxe/thermometer.svg</dialFile>
<dialForegroundID>foreground</dialForegroundID>
<dialNeedleID1>needle</dialNeedleID1>
<dialNeedleID2>needle2</dialNeedleID2>
<dialNeedleID3>needle3</dialNeedleID3>
<font>Ubuntu,11,-1,5,50,0,0,0,0,0</font>
<needle1DataObject>BaroAltitude</needle1DataObject>
<needle1Factor>1</needle1Factor>
<needle1MaxValue>120</needle1MaxValue>
<needle1MinValue>0</needle1MinValue>
<needle1Move>Rotate</needle1Move>
<needle1ObjectField>Temperature</needle1ObjectField>
<needle2DataObject>BaroAltitude</needle2DataObject>
<needle2Factor>1</needle2Factor>
<needle2MaxValue>100</needle2MaxValue>
<needle2MinValue>0</needle2MinValue>
<needle2Move>Rotate</needle2Move>
<needle2ObjectField>Altitude</needle2ObjectField>
<needle3DataObject>BaroAltitude</needle3DataObject>
<needle3Factor>1</needle3Factor>
<needle3MaxValue>1000</needle3MaxValue>
<needle3MinValue>0</needle3MinValue>
<needle3Move>Rotate</needle3Move>
<needle3ObjectField>Altitude</needle3ObjectField>
<useOpenGLFlag>false</useOpenGLFlag>
</data>
</Deluxe__PCT__20Temperature>
<Deluxe__PCT__20Turn__PCT__20Coordinator>
<configInfo>
<locked>false</locked>
<version>0.0.0</version>
</configInfo>
<data>
<beSmooth>false</beSmooth>
<dialBackgroundID>background</dialBackgroundID>
<dialFile>/home/lafargue/OP/OpenPilot/trunk/artwork/Dials/deluxe/turncoordinator.svg</dialFile>
<dialForegroundID>foreground</dialForegroundID>
<dialNeedleID1>needle</dialNeedleID1>
<dialNeedleID2>needle2</dialNeedleID2>
<dialNeedleID3>needle2</dialNeedleID3>
<font>Ubuntu,11,-1,5,50,0,0,0,0,0</font>
<needle1DataObject>AttitudeActual</needle1DataObject>
<needle1Factor>-1</needle1Factor>
<needle1MaxValue>360</needle1MaxValue>
<needle1MinValue>0</needle1MinValue>
<needle1Move>Rotate</needle1Move>
<needle1ObjectField>Roll</needle1ObjectField>
<needle2DataObject>AttitudeRaw</needle2DataObject>
<needle2Factor>1</needle2Factor>
<needle2MaxValue>20</needle2MaxValue>
<needle2MinValue>-20</needle2MinValue>
<needle2Move>Horizontal</needle2Move>
<needle2ObjectField>accels-X</needle2ObjectField>
<needle3DataObject>AttitudeRaw</needle3DataObject>
<needle3Factor>-1</needle3Factor>
<needle3MaxValue>360</needle3MaxValue>
<needle3MinValue>0</needle3MinValue>
<needle3Move>Rotate</needle3Move>
<needle3ObjectField>accels-X</needle3ObjectField>
<useOpenGLFlag>false</useOpenGLFlag>
</data>
</Deluxe__PCT__20Turn__PCT__20Coordinator>
<Groundspeed__PCT__20kph>
<configInfo>
<locked>false</locked>
<version>0.0.0</version>
</configInfo>
<data>
<beSmooth>false</beSmooth>
<dialBackgroundID>background</dialBackgroundID>
<dialFile>%%DATAPATH%%dials/default/speed.svg</dialFile>
<dialForegroundID></dialForegroundID>
<dialNeedleID1>needle</dialNeedleID1>
<dialNeedleID2></dialNeedleID2>
<dialNeedleID3></dialNeedleID3>
<font>Ubuntu,11,-1,5,50,0,0,0,0,0</font>
<needle1DataObject>GPSPosition</needle1DataObject>
<needle1Factor>3.6</needle1Factor>
<needle1MaxValue>120</needle1MaxValue>
<needle1MinValue>0</needle1MinValue>
<needle1Move>Rotate</needle1Move>
<needle1ObjectField>Groundspeed</needle1ObjectField>
<needle2DataObject>BaroAltitude</needle2DataObject>
<needle2Factor>1</needle2Factor>
<needle2MaxValue>100</needle2MaxValue>
<needle2MinValue>0</needle2MinValue>
<needle2Move>Rotate</needle2Move>
<needle2ObjectField>Altitude</needle2ObjectField>
<needle3DataObject>BaroAltitude</needle3DataObject>
<needle3Factor>1</needle3Factor>
<needle3MaxValue>1000</needle3MaxValue>
<needle3MinValue>0</needle3MinValue>
<needle3Move>Rotate</needle3Move>
<needle3ObjectField>Altitude</needle3ObjectField>
<useOpenGLFlag>false</useOpenGLFlag>
</data>
</Groundspeed__PCT__20kph>
<HiContrast__PCT__20Attitude>
<configInfo>
<locked>false</locked>
<version>0.0.0</version>
</configInfo>
<data>
<beSmooth>false</beSmooth>
<dialBackgroundID>background</dialBackgroundID>
<dialFile>%%DATAPATH%%dials/hi-contrast/attitude.svg</dialFile>
<dialForegroundID>foreground</dialForegroundID>
<dialNeedleID1>needle</dialNeedleID1>
<dialNeedleID2>needle</dialNeedleID2>
<dialNeedleID3>needle3</dialNeedleID3>
<font>Ubuntu,11,-1,5,50,0,0,0,0,0</font>
<needle1DataObject>AttitudeActual</needle1DataObject>
<needle1Factor>-1</needle1Factor>
<needle1MaxValue>360</needle1MaxValue>
<needle1MinValue>0</needle1MinValue>
<needle1Move>Rotate</needle1Move>
<needle1ObjectField>Roll</needle1ObjectField>
<needle2DataObject>AttitudeActual</needle2DataObject>
<needle2Factor>75</needle2Factor>
<needle2MaxValue>20</needle2MaxValue>
<needle2MinValue>0</needle2MinValue>
<needle2Move>Vertical</needle2Move>
<needle2ObjectField>Pitch</needle2ObjectField>
<needle3DataObject>AttitudeActual</needle3DataObject>
<needle3Factor>-1</needle3Factor>
<needle3MaxValue>360</needle3MaxValue>
<needle3MinValue>0</needle3MinValue>
<needle3Move>Rotate</needle3Move>
<needle3ObjectField>Roll</needle3ObjectField>
<useOpenGLFlag>false</useOpenGLFlag>
</data>
</HiContrast__PCT__20Attitude>
<HiContrast__PCT__20Baro__PCT__20Altimeter>
<configInfo>
<locked>false</locked>
<version>0.0.0</version>
</configInfo>
<data>
<beSmooth>false</beSmooth>
<dialBackgroundID>background</dialBackgroundID>
<dialFile>%%DATAPATH%%dials/hi-contrast/altimeter.svg</dialFile>
<dialForegroundID>foreground</dialForegroundID>
<dialNeedleID1>needle</dialNeedleID1>
<dialNeedleID2>needle2</dialNeedleID2>
<dialNeedleID3>needle3</dialNeedleID3>
<font>Ubuntu,11,-1,5,50,0,0,0,0,0</font>
<needle1DataObject>BaroAltitude</needle1DataObject>
<needle1Factor>1</needle1Factor>
<needle1MaxValue>10</needle1MaxValue>
<needle1MinValue>0</needle1MinValue>
<needle1Move>Rotate</needle1Move>
<needle1ObjectField>Altitude</needle1ObjectField>
<needle2DataObject>BaroAltitude</needle2DataObject>
<needle2Factor>1</needle2Factor>
<needle2MaxValue>100</needle2MaxValue>
<needle2MinValue>0</needle2MinValue>
<needle2Move>Rotate</needle2Move>
<needle2ObjectField>Altitude</needle2ObjectField>
<needle3DataObject>BaroAltitude</needle3DataObject>
<needle3Factor>1</needle3Factor>
<needle3MaxValue>1000</needle3MaxValue>
<needle3MinValue>0</needle3MinValue>
<needle3Move>Rotate</needle3Move>
<needle3ObjectField>Altitude</needle3ObjectField>
<useOpenGLFlag>false</useOpenGLFlag>
</data>
</HiContrast__PCT__20Baro__PCT__20Altimeter>
<HiContrast__PCT__20Barometer>
<configInfo>
<locked>false</locked>
<version>0.0.0</version>
</configInfo>
<data>
<beSmooth>false</beSmooth>
<dialBackgroundID>background</dialBackgroundID>
<dialFile>%%DATAPATH%%dials/hi-contrast/barometer.svg</dialFile>
<dialForegroundID></dialForegroundID>
<dialNeedleID1>needle</dialNeedleID1>
<dialNeedleID2></dialNeedleID2>
<dialNeedleID3></dialNeedleID3>
<font>Ubuntu,11,-1,5,50,0,0,0,0,0</font>
<needle1DataObject>BaroAltitude</needle1DataObject>
<needle1Factor>10</needle1Factor>
<needle1MaxValue>1120</needle1MaxValue>
<needle1MinValue>1000</needle1MinValue>
<needle1Move>Rotate</needle1Move>
<needle1ObjectField>Pressure</needle1ObjectField>
<needle2DataObject>BaroAltitude</needle2DataObject>
<needle2Factor>1</needle2Factor>
<needle2MaxValue>100</needle2MaxValue>
<needle2MinValue>0</needle2MinValue>
<needle2Move>Rotate</needle2Move>
<needle2ObjectField>Altitude</needle2ObjectField>
<needle3DataObject>BaroAltitude</needle3DataObject>
<needle3Factor>1</needle3Factor>
<needle3MaxValue>1000</needle3MaxValue>
<needle3MinValue>0</needle3MinValue>
<needle3Move>Rotate</needle3Move>
<needle3ObjectField>Altitude</needle3ObjectField>
<useOpenGLFlag>false</useOpenGLFlag>
</data>
</HiContrast__PCT__20Barometer>
<HiContrast__PCT__20Climbrate>
<configInfo>
<locked>false</locked>
<version>0.0.0</version>
</configInfo>
<data>
<beSmooth>false</beSmooth>
<dialBackgroundID>background</dialBackgroundID>
<dialFile>%%DATAPATH%%dials/hi-contrast/vsi.svg</dialFile>
<dialForegroundID></dialForegroundID>
<dialNeedleID1>needle</dialNeedleID1>
<dialNeedleID2></dialNeedleID2>
<dialNeedleID3></dialNeedleID3>
<font>Ubuntu,11,-1,5,50,0,0,0,0,0</font>
<needle1DataObject>VelocityActual</needle1DataObject>
<needle1Factor>0.01</needle1Factor>
<needle1MaxValue>12</needle1MaxValue>
<needle1MinValue>-12</needle1MinValue>
<needle1Move>Rotate</needle1Move>
<needle1ObjectField>Down</needle1ObjectField>
<needle2DataObject>BaroAltitude</needle2DataObject>
<needle2Factor>1</needle2Factor>
<needle2MaxValue>100</needle2MaxValue>
<needle2MinValue>0</needle2MinValue>
<needle2Move>Rotate</needle2Move>
<needle2ObjectField>Altitude</needle2ObjectField>
<needle3DataObject>BaroAltitude</needle3DataObject>
<needle3Factor>1</needle3Factor>
<needle3MaxValue>1000</needle3MaxValue>
<needle3MinValue>0</needle3MinValue>
<needle3Move>Rotate</needle3Move>
<needle3ObjectField>Altitude</needle3ObjectField>
<useOpenGLFlag>false</useOpenGLFlag>
</data>
</HiContrast__PCT__20Climbrate>
<HiContrast__PCT__20Compass>
<configInfo>
<locked>false</locked>
<version>0.0.0</version>
</configInfo>
<data>
<beSmooth>false</beSmooth>
<dialBackgroundID>background</dialBackgroundID>
<dialFile>%%DATAPATH%%dials/hi-contrast/compass.svg</dialFile>
<dialForegroundID>foreground</dialForegroundID>
<dialNeedleID1>needle</dialNeedleID1>
<dialNeedleID2></dialNeedleID2>
<dialNeedleID3></dialNeedleID3>
<font>Ubuntu,11,-1,5,50,0,0,0,0,0</font>
<needle1DataObject>AttitudeActual</needle1DataObject>
<needle1Factor>-1</needle1Factor>
<needle1MaxValue>360</needle1MaxValue>
<needle1MinValue>0</needle1MinValue>
<needle1Move>Rotate</needle1Move>
<needle1ObjectField>Yaw</needle1ObjectField>
<needle2DataObject>BaroAltitude</needle2DataObject>
<needle2Factor>1</needle2Factor>
<needle2MaxValue>100</needle2MaxValue>
<needle2MinValue>0</needle2MinValue>
<needle2Move>Rotate</needle2Move>
<needle2ObjectField>Altitude</needle2ObjectField>
<needle3DataObject>BaroAltitude</needle3DataObject>
<needle3Factor>1</needle3Factor>
<needle3MaxValue>1000</needle3MaxValue>
<needle3MinValue>0</needle3MinValue>
<needle3Move>Rotate</needle3Move>
<needle3ObjectField>Altitude</needle3ObjectField>
<useOpenGLFlag>false</useOpenGLFlag>
</data>
</HiContrast__PCT__20Compass>
<HiContrast__PCT__20Groundspeed__PCT__20kph>
<configInfo>
<locked>false</locked>
<version>0.0.0</version>
</configInfo>
<data>
<beSmooth>false</beSmooth>
<dialBackgroundID>background</dialBackgroundID>
<dialFile>%%DATAPATH%%dials/hi-contrast/speed.svg</dialFile>
<dialForegroundID></dialForegroundID>
<dialNeedleID1>needle</dialNeedleID1>
<dialNeedleID2></dialNeedleID2>
<dialNeedleID3></dialNeedleID3>
<font>Ubuntu,11,-1,5,50,0,0,0,0,0</font>
<needle1DataObject>GPSPosition</needle1DataObject>
<needle1Factor>3.6</needle1Factor>
<needle1MaxValue>120</needle1MaxValue>
<needle1MinValue>0</needle1MinValue>
<needle1Move>Rotate</needle1Move>
<needle1ObjectField>Groundspeed</needle1ObjectField>
<needle2DataObject>BaroAltitude</needle2DataObject>
<needle2Factor>1</needle2Factor>
<needle2MaxValue>100</needle2MaxValue>
<needle2MinValue>0</needle2MinValue>
<needle2Move>Rotate</needle2Move>
<needle2ObjectField>Altitude</needle2ObjectField>
<needle3DataObject>BaroAltitude</needle3DataObject>
<needle3Factor>1</needle3Factor>
<needle3MaxValue>1000</needle3MaxValue>
<needle3MinValue>0</needle3MinValue>
<needle3Move>Rotate</needle3Move>
<needle3ObjectField>Altitude</needle3ObjectField>
<useOpenGLFlag>false</useOpenGLFlag>
</data>
</HiContrast__PCT__20Groundspeed__PCT__20kph>
<HiContrast__PCT__20Temperature>
<configInfo>
<locked>false</locked>
<version>0.0.0</version>
</configInfo>
<data>
<beSmooth>false</beSmooth>
<dialBackgroundID>background</dialBackgroundID>
<dialFile>%%DATAPATH%%dials/hi-contrast/thermometer.svg</dialFile>
<dialForegroundID></dialForegroundID>
<dialNeedleID1>needle</dialNeedleID1>
<dialNeedleID2>needle2</dialNeedleID2>
<dialNeedleID3>needle3</dialNeedleID3>
<font>Ubuntu,11,-1,5,50,0,0,0,0,0</font>
<needle1DataObject>BaroAltitude</needle1DataObject>
<needle1Factor>1</needle1Factor>
<needle1MaxValue>120</needle1MaxValue>
<needle1MinValue>0</needle1MinValue>
<needle1Move>Rotate</needle1Move>
<needle1ObjectField>Temperature</needle1ObjectField>
<needle2DataObject>BaroAltitude</needle2DataObject>
<needle2Factor>1</needle2Factor>
<needle2MaxValue>100</needle2MaxValue>
<needle2MinValue>0</needle2MinValue>
<needle2Move>Rotate</needle2Move>
<needle2ObjectField>Altitude</needle2ObjectField>
<needle3DataObject>BaroAltitude</needle3DataObject>
<needle3Factor>1</needle3Factor>
<needle3MaxValue>1000</needle3MaxValue>
<needle3MinValue>0</needle3MinValue>
<needle3Move>Rotate</needle3Move>
<needle3ObjectField>Altitude</needle3ObjectField>
<useOpenGLFlag>false</useOpenGLFlag>
</data>
</HiContrast__PCT__20Temperature>
<Servo__PCT__20Channel__PCT__201>
<configInfo>
<locked>false</locked>
<version>0.0.0</version>
</configInfo>
<data>
<beSmooth>false</beSmooth>
<dialBackgroundID>background</dialBackgroundID>
<dialFile>%%DATAPATH%%dials/default/thermometer.svg</dialFile>
<dialForegroundID></dialForegroundID>
<dialNeedleID1>needle</dialNeedleID1>
<dialNeedleID2>needle2</dialNeedleID2>
<dialNeedleID3>needle3</dialNeedleID3>
<font>Ubuntu,11,-1,5,50,0,0,0,0,0</font>
<needle1DataObject>ManualControlCommand</needle1DataObject>
<needle1Factor>1</needle1Factor>
<needle1MaxValue>2000</needle1MaxValue>
<needle1MinValue>1000</needle1MinValue>
<needle1Move>Rotate</needle1Move>
<needle1ObjectField>Channel-3</needle1ObjectField>
<needle2DataObject>BaroAltitude</needle2DataObject>
<needle2Factor>1</needle2Factor>
<needle2MaxValue>100</needle2MaxValue>
<needle2MinValue>0</needle2MinValue>
<needle2Move>Rotate</needle2Move>
<needle2ObjectField>Altitude</needle2ObjectField>
<needle3DataObject>BaroAltitude</needle3DataObject>
<needle3Factor>1</needle3Factor>
<needle3MaxValue>1000</needle3MaxValue>
<needle3MinValue>0</needle3MinValue>
<needle3Move>Rotate</needle3Move>
<needle3ObjectField>Altitude</needle3ObjectField>
<useOpenGLFlag>false</useOpenGLFlag>
</data>
</Servo__PCT__20Channel__PCT__201>
<Temperature>
<configInfo>
<locked>false</locked>
<version>0.0.0</version>
</configInfo>
<data>
<beSmooth>false</beSmooth>
<dialBackgroundID>background</dialBackgroundID>
<dialFile>%%DATAPATH%%dials/default/thermometer.svg</dialFile>
<dialForegroundID></dialForegroundID>
<dialNeedleID1>needle</dialNeedleID1>
<dialNeedleID2>needle2</dialNeedleID2>
<dialNeedleID3>needle3</dialNeedleID3>
<font>Ubuntu,11,-1,5,50,0,0,0,0,0</font>
<needle1DataObject>BaroAltitude</needle1DataObject>
<needle1Factor>1</needle1Factor>
<needle1MaxValue>120</needle1MaxValue>
<needle1MinValue>0</needle1MinValue>
<needle1Move>Rotate</needle1Move>
<needle1ObjectField>Temperature</needle1ObjectField>
<needle2DataObject>BaroAltitude</needle2DataObject>
<needle2Factor>1</needle2Factor>
<needle2MaxValue>100</needle2MaxValue>
<needle2MinValue>0</needle2MinValue>
<needle2Move>Rotate</needle2Move>
<needle2ObjectField>Altitude</needle2ObjectField>
<needle3DataObject>BaroAltitude</needle3DataObject>
<needle3Factor>1</needle3Factor>
<needle3MaxValue>1000</needle3MaxValue>
<needle3MinValue>0</needle3MinValue>
<needle3Move>Rotate</needle3Move>
<needle3ObjectField>Altitude</needle3ObjectField>
<useOpenGLFlag>false</useOpenGLFlag>
</data>
</Temperature>
</DialGadget>
<GCSControlGadget>
<MS__PCT__20Sidewinder>
<configInfo>
<locked>false</locked>
<version>0.0.0</version>
</configInfo>
<data>
<button0Action>0</button0Action>
<button0Amount>0</button0Amount>
<button0Function>0</button0Function>
<button1Action>0</button1Action>
<button1Amount>0</button1Amount>
<button1Function>0</button1Function>
<button2Action>0</button2Action>
<button2Amount>0.1</button2Amount>
<button2Function>3</button2Function>
<button3Action>0</button3Action>
<button3Amount>0.1</button3Amount>
<button3Function>3</button3Function>
<button4Action>0</button4Action>
<button4Amount>0</button4Amount>
<button4Function>0</button4Function>
<button5Action>0</button5Action>
<button5Amount>0</button5Amount>
<button5Function>0</button5Function>
<button6Action>0</button6Action>
<button6Amount>0</button6Amount>
<button6Function>0</button6Function>
<button7Action>0</button7Action>
<button7Amount>0</button7Amount>
<button7Function>0</button7Function>
<channel0Reverse>false</channel0Reverse>
<channel1Reverse>false</channel1Reverse>
<channel2Reverse>true</channel2Reverse>
<channel3Reverse>false</channel3Reverse>
<channel4Reverse>false</channel4Reverse>
<channel5Reverse>false</channel5Reverse>
<channel6Reverse>false</channel6Reverse>
<channel7Reverse>false</channel7Reverse>
<controlsMode>2</controlsMode>
<pitchChannel>1</pitchChannel>
<rollChannel>0</rollChannel>
<throttleChannel>2</throttleChannel>
<yawChannel>3</yawChannel>
</data>
</MS__PCT__20Sidewinder>
</GCSControlGadget>
<GpsDisplayGadget>
<Flight__PCT__20GPS>
<configInfo>
<locked>false</locked>
<version>0.0.0</version>
</configInfo>
<data>
<connectionMode>Telemetry</connectionMode>
<defaultDataBits>3</defaultDataBits>
<defaultFlow>0</defaultFlow>
<defaultParity>0</defaultParity>
<defaultPort>Serial port 0</defaultPort>
<defaultSpeed>11</defaultSpeed>
<defaultStopBits>0</defaultStopBits>
</data>
</Flight__PCT__20GPS>
<GPS__PCT__20Mouse>
<configInfo>
<locked>false</locked>
<version>0.0.0</version>
</configInfo>
<data>
<connectionMode>Serial</connectionMode>
<defaultDataBits>3</defaultDataBits>
<defaultFlow>0</defaultFlow>
<defaultParity>0</defaultParity>
<defaultPort>Serial port 0</defaultPort>
<defaultSpeed>17</defaultSpeed>
<defaultStopBits>0</defaultStopBits>
</data>
</GPS__PCT__20Mouse>
</GpsDisplayGadget>
<HITL>
<Flightgear__PCT__20HITL>
<configInfo>
<locked>false</locked>
<version>0.0.0</version>
</configInfo>
<data>
<binPath>\usr\games\fgfs</binPath>
<dataPath>\usr\share\games\FlightGear</dataPath>
<hostAddress>127.0.0.1</hostAddress>
<inPort>9009</inPort>
<latitude></latitude>
<longitude></longitude>
<manual>false</manual>
<outPort>9010</outPort>
<remoteHostAddress>127.0.0.1</remoteHostAddress>
<simulatorId>FG</simulatorId>
<startSim>true</startSim>
</data>
</Flightgear__PCT__20HITL>
<XPlane__PCT__20HITL>
<configInfo>
<locked>false</locked>
<version>0.0.0</version>
</configInfo>
<data>
<binPath>\home\lafargue\X-Plane 9\X-Plane-i686</binPath>
<dataPath>\usr\share\games\FlightGear</dataPath>
<hostAddress>127.0.0.3</hostAddress>
<inPort>6756</inPort>
<latitude></latitude>
<longitude></longitude>
<manual>false</manual>
<outPort>49000</outPort>
<remoteHostAddress>127.0.0.1</remoteHostAddress>
<simulatorId>X-Plane</simulatorId>
<startSim>false</startSim>
</data>
</XPlane__PCT__20HITL>
</HITL>
<ImportExportGadget>
<default>
<configInfo>
<locked>false</locked>
<version>1.0.1</version>
</configInfo>
<data>
<iniFile>gcs.ini</iniFile>
</data>
</default>
</ImportExportGadget>
<LineardialGadget>
<AHRS__PCT__20CPU>
<configInfo>
<locked>false</locked>
<version>0.0.0</version>
</configInfo>
<data>
<dFile>%%DATAPATH%%dials/default/lineardial-vertical.svg</dFile>
<decimalPlaces>0</decimalPlaces>
<factor>1</factor>
<font>Andale Mono,12,-1,5,75,0,0,0,0,0</font>
<greenMax>50</greenMax>
<greenMin>0</greenMin>
<maxValue>100</maxValue>
<minValue>0</minValue>
<redMax>100</redMax>
<redMin>80</redMin>
<sourceDataObject>AhrsStatus</sourceDataObject>
<sourceObjectField>CPULoad</sourceObjectField>
<useOpenGLFlag>false</useOpenGLFlag>
<yellowMax>80</yellowMax>
<yellowMin>50</yellowMin>
</data>
</AHRS__PCT__20CPU>
<Accel__PCT__20Horizontal__PCT__20X>
<configInfo>
<locked>false</locked>
<version>0.0.0</version>
</configInfo>
<data>
<dFile>%%DATAPATH%%dials/default/lineardial-horizontal.svg</dFile>
<decimalPlaces>2</decimalPlaces>
<factor>1</factor>
<font>Andale Mono,8,-1,5,50,0,0,0,0,0</font>
<greenMax>-9</greenMax>
<greenMin>-10</greenMin>
<maxValue>11</maxValue>
<minValue>-11</minValue>
<redMax>11</redMax>
<redMin>-11</redMin>
<sourceDataObject>AttitudeRaw</sourceDataObject>
<sourceObjectField>accels-X</sourceObjectField>
<useOpenGLFlag>false</useOpenGLFlag>
<yellowMax>-5</yellowMax>
<yellowMin>-11</yellowMin>
</data>
</Accel__PCT__20Horizontal__PCT__20X>
<Accel__PCT__20Horizontal__PCT__20Y>
<configInfo>
<locked>false</locked>
<version>0.0.0</version>
</configInfo>
<data>
<dFile>%%DATAPATH%%dials/default/lineardial-horizontal.svg</dFile>
<decimalPlaces>2</decimalPlaces>
<factor>1</factor>
<font>Andale Mono,6,-1,5,50,0,0,0,0,0</font>
<greenMax>-9</greenMax>
<greenMin>-10</greenMin>
<maxValue>11</maxValue>
<minValue>-11</minValue>
<redMax>11</redMax>
<redMin>-11</redMin>
<sourceDataObject>AttitudeRaw</sourceDataObject>
<sourceObjectField>accels-Y</sourceObjectField>
<useOpenGLFlag>false</useOpenGLFlag>
<yellowMax>-5</yellowMax>
<yellowMin>-11</yellowMin>
</data>
</Accel__PCT__20Horizontal__PCT__20Y>
<Accel__PCT__20Horizontal__PCT__20Z>
<configInfo>
<locked>false</locked>
<version>0.0.0</version>
</configInfo>
<data>
<dFile>%%DATAPATH%%dials/default/lineardial-horizontal.svg</dFile>
<decimalPlaces>2</decimalPlaces>
<factor>1</factor>
<font>Andale Mono,8,-1,5,50,0,0,0,0,0</font>
<greenMax>-9</greenMax>
<greenMin>-10</greenMin>
<maxValue>11</maxValue>
<minValue>-11</minValue>
<redMax>11</redMax>
<redMin>-11</redMin>
<sourceDataObject>AttitudeRaw</sourceDataObject>
<sourceObjectField>accels-Z</sourceObjectField>
<useOpenGLFlag>false</useOpenGLFlag>
<yellowMax>-5</yellowMax>
<yellowMin>-11</yellowMin>
</data>
</Accel__PCT__20Horizontal__PCT__20Z>
<Arm__PCT__20Status>
<configInfo>
<locked>false</locked>
<version>0.0.0</version>
</configInfo>
<data>
<dFile>%%DATAPATH%%dials/default/arm-status.svg</dFile>
<decimalPlaces>0</decimalPlaces>
<factor>1</factor>
<font>,12,-1,5,50,0,0,0,0,0</font>
<greenMax>100</greenMax>
<greenMin>66</greenMin>
<maxValue>100</maxValue>
<minValue>0</minValue>
<redMax>33</redMax>
<redMin>0</redMin>
<sourceDataObject>FlightStatus</sourceDataObject>
<sourceObjectField>Armed</sourceObjectField>
<useOpenGLFlag>false</useOpenGLFlag>
<yellowMax>66</yellowMax>
<yellowMin>33</yellowMin>
</data>
</Arm__PCT__20Status>
<Flight__PCT__20Time>
<configInfo>
<locked>false</locked>
<version>0.0.0</version>
</configInfo>
<data>
<dFile>%%DATAPATH%%dials/default/textonly.svg</dFile>
<decimalPlaces>0</decimalPlaces>
<factor>0.001</factor>
<font>,12,-1,5,50,0,0,0,0,0</font>
<greenMax>100</greenMax>
<greenMin>66</greenMin>
<maxValue>100</maxValue>
<minValue>0</minValue>
<redMax>33</redMax>
<redMin>0</redMin>
<sourceDataObject>SystemStats</sourceDataObject>
<sourceObjectField>FlightTime</sourceObjectField>
<useOpenGLFlag>false</useOpenGLFlag>
<yellowMax>66</yellowMax>
<yellowMin>33</yellowMin>
</data>
</Flight__PCT__20Time>
<Flight__PCT__20mode>
<configInfo>
<locked>false</locked>
<version>0.0.0</version>
</configInfo>
<data>
<dFile>%%DATAPATH%%dials/default/flightmode-status.svg</dFile>
<decimalPlaces>0</decimalPlaces>
<factor>1</factor>
<font>,12,-1,5,50,0,0,0,0,0</font>
<greenMax>100</greenMax>
<greenMin>66</greenMin>
<maxValue>100</maxValue>
<minValue>0</minValue>
<redMax>33</redMax>
<redMin>0</redMin>
<sourceDataObject>FlightStatus</sourceDataObject>
<sourceObjectField>FlightMode</sourceObjectField>
<useOpenGLFlag>false</useOpenGLFlag>
<yellowMax>66</yellowMax>
<yellowMin>33</yellowMin>
</data>
</Flight__PCT__20mode>
<GPS__PCT__20Sats>
<configInfo>
<locked>false</locked>
<version>0.0.0</version>
</configInfo>
<data>
<dFile>%%DATAPATH%%dials/default/gps-signal.svg</dFile>
<decimalPlaces>0</decimalPlaces>
<factor>1</factor>
<font>,12,-1,5,50,0,0,0,0,0</font>
<greenMax>0</greenMax>
<greenMin>0</greenMin>
<maxValue>12</maxValue>
<minValue>0</minValue>
<redMax>0</redMax>
<redMin>0</redMin>
<sourceDataObject>GPSPosition</sourceDataObject>
<sourceObjectField>Satellites</sourceObjectField>
<useOpenGLFlag>false</useOpenGLFlag>
<yellowMax>0</yellowMax>
<yellowMin>0</yellowMin>
</data>
</GPS__PCT__20Sats>
<GPS__PCT__20Status>
<configInfo>
<locked>false</locked>
<version>0.0.0</version>
</configInfo>
<data>
<dFile>%%DATAPATH%%dials/default/gps-status.svg</dFile>
<decimalPlaces>0</decimalPlaces>
<factor>1</factor>
<font>,12,-1,5,50,0,0,0,0,0</font>
<greenMax>100</greenMax>
<greenMin>66</greenMin>
<maxValue>100</maxValue>
<minValue>0</minValue>
<redMax>33</redMax>
<redMin>0</redMin>
<sourceDataObject>GPSPosition</sourceDataObject>
<sourceObjectField>Status</sourceObjectField>
<useOpenGLFlag>false</useOpenGLFlag>
<yellowMax>66</yellowMax>
<yellowMin>33</yellowMin>
</data>
</GPS__PCT__20Status>
<Mainboard__PCT__20CPU>
<configInfo>
<locked>false</locked>
<version>0.0.0</version>
</configInfo>
<data>
<dFile>%%DATAPATH%%dials/default/lineardial-vertical.svg</dFile>
<decimalPlaces>0</decimalPlaces>
<factor>1</factor>
<font>Andale Mono,12,-1,5,75,0,0,0,0,0</font>
<greenMax>50</greenMax>
<greenMin>0</greenMin>
<maxValue>100</maxValue>
<minValue>0</minValue>
<redMax>100</redMax>
<redMin>80</redMin>
<sourceDataObject>SystemStats</sourceDataObject>
<sourceObjectField>CPULoad</sourceObjectField>
<useOpenGLFlag>false</useOpenGLFlag>
<yellowMax>80</yellowMax>
<yellowMin>50</yellowMin>
</data>
</Mainboard__PCT__20CPU>
<Pitch__PCT__20Desired>
<configInfo>
<locked>false</locked>
<version>0.0.0</version>
</configInfo>
<data>
<dFile>%%DATAPATH%%dials/default/lineardial-vertical.svg</dFile>
<decimalPlaces>2</decimalPlaces>
<factor>1</factor>
<font>Andale Mono,12,-1,5,75,0,0,0,0,0</font>
<greenMax>0.5</greenMax>
<greenMin>-0.5</greenMin>
<maxValue>1</maxValue>
<minValue>-1</minValue>
<redMax>1</redMax>
<redMin>-1</redMin>
<sourceDataObject>ActuatorDesired</sourceDataObject>
<sourceObjectField>Pitch</sourceObjectField>
<useOpenGLFlag>false</useOpenGLFlag>
<yellowMax>0.8</yellowMax>
<yellowMin>-0.8</yellowMin>
</data>
</Pitch__PCT__20Desired>
<Pitch>
<configInfo>
<locked>false</locked>
<version>0.0.0</version>
</configInfo>
<data>
<dFile>%%DATAPATH%%dials/default/lineardial-vertical.svg</dFile>
<decimalPlaces>2</decimalPlaces>
<factor>1</factor>
<font>Andale Mono,12,-1,5,75,0,0,0,0,0</font>
<greenMax>0.5</greenMax>
<greenMin>-0.5</greenMin>
<maxValue>1</maxValue>
<minValue>-1</minValue>
<redMax>1</redMax>
<redMin>-1</redMin>
<sourceDataObject>ManualControlCommand</sourceDataObject>
<sourceObjectField>Pitch</sourceObjectField>
<useOpenGLFlag>false</useOpenGLFlag>
<yellowMax>0.8</yellowMax>
<yellowMin>-0.8</yellowMin>
</data>
</Pitch>
<PitchActual>
<configInfo>
<locked>false</locked>
<version>0.0.0</version>
</configInfo>
<data>
<dFile>%%DATAPATH%%dials/default/lineardial-vertical.svg</dFile>
<decimalPlaces>2</decimalPlaces>
<factor>1</factor>
<font>Andale Mono,12,-1,5,75,0,0,0,0,0</font>
<greenMax>0.8</greenMax>
<greenMin>0.3</greenMin>
<maxValue>90</maxValue>
<minValue>-90</minValue>
<redMax>1</redMax>
<redMin>0</redMin>
<sourceDataObject>AttitudeActual</sourceDataObject>
<sourceObjectField>Pitch</sourceObjectField>
<useOpenGLFlag>false</useOpenGLFlag>
<yellowMax>0.9</yellowMax>
<yellowMin>0.1</yellowMin>
</data>
</PitchActual>
<Roll__PCT__20Desired>
<configInfo>
<locked>false</locked>
<version>0.0.0</version>
</configInfo>
<data>
<dFile>%%DATAPATH%%dials/default/lineardial-vertical.svg</dFile>
<decimalPlaces>2</decimalPlaces>
<factor>1</factor>
<font>Andale Mono,12,-1,5,75,0,0,0,0,0</font>
<greenMax>0.5</greenMax>
<greenMin>-0.5</greenMin>
<maxValue>1</maxValue>
<minValue>-1</minValue>
<redMax>1</redMax>
<redMin>-1</redMin>
<sourceDataObject>ActuatorDesired</sourceDataObject>
<sourceObjectField>Roll</sourceObjectField>
<useOpenGLFlag>false</useOpenGLFlag>
<yellowMax>0.8</yellowMax>
<yellowMin>-0.8</yellowMin>
</data>
</Roll__PCT__20Desired>
<Roll>
<configInfo>
<locked>false</locked>
<version>0.0.0</version>
</configInfo>
<data>
<dFile>%%DATAPATH%%dials/default/lineardial-vertical.svg</dFile>
<decimalPlaces>2</decimalPlaces>
<factor>1</factor>
<font>Andale Mono,12,-1,5,75,0,0,0,0,0</font>
<greenMax>0.5</greenMax>
<greenMin>-0.5</greenMin>
<maxValue>1</maxValue>
<minValue>-1</minValue>
<redMax>1</redMax>
<redMin>-1</redMin>
<sourceDataObject>ManualControlCommand</sourceDataObject>
<sourceObjectField>Roll</sourceObjectField>
<useOpenGLFlag>false</useOpenGLFlag>
<yellowMax>0.8</yellowMax>
<yellowMin>-0.8</yellowMin>
</data>
</Roll>
<Telemetry__PCT__20RX__PCT__20Rate__PCT__20Horizontal>
<configInfo>
<locked>false</locked>
<version>0.0.0</version>
</configInfo>
<data>
<dFile>%%DATAPATH%%dials/default/lineardial-horizontal.svg</dFile>
<decimalPlaces>0</decimalPlaces>
<factor>1</factor>
<font>Andale Mono,12,-1,5,75,0,0,0,0,0</font>
<greenMax>650</greenMax>
<greenMin>0</greenMin>
<maxValue>1200</maxValue>
<minValue>0</minValue>
<redMax>1200</redMax>
<redMin>900</redMin>
<sourceDataObject>GCSTelemetryStats</sourceDataObject>
<sourceObjectField>RxDataRate</sourceObjectField>
<useOpenGLFlag>false</useOpenGLFlag>
<yellowMax>900</yellowMax>
<yellowMin>650</yellowMin>
</data>
</Telemetry__PCT__20RX__PCT__20Rate__PCT__20Horizontal>
<Telemetry__PCT__20TX__PCT__20Rate__PCT__20Horizontal>
<configInfo>
<locked>false</locked>
<version>0.0.0</version>
</configInfo>
<data>
<dFile>%%DATAPATH%%dials/default/lineardial-horizontal.svg</dFile>
<decimalPlaces>0</decimalPlaces>
<factor>1</factor>
<font>Andale Mono,12,-1,5,75,0,0,0,0,0</font>
<greenMax>650</greenMax>
<greenMin>0</greenMin>
<maxValue>1200</maxValue>
<minValue>0</minValue>
<redMax>1200</redMax>
<redMin>900</redMin>
<sourceDataObject>GCSTelemetryStats</sourceDataObject>
<sourceObjectField>TxDataRate</sourceObjectField>
<useOpenGLFlag>false</useOpenGLFlag>
<yellowMax>900</yellowMax>
<yellowMin>650</yellowMin>
</data>
</Telemetry__PCT__20TX__PCT__20Rate__PCT__20Horizontal>
<Throttle>
<configInfo>
<locked>false</locked>
<version>0.0.0</version>
</configInfo>
<data>
<dFile>%%DATAPATH%%dials/default/lineardial-vertical.svg</dFile>
<decimalPlaces>2</decimalPlaces>
<factor>1</factor>
<font>Andale Mono,12,-1,5,75,0,0,0,0,0</font>
<greenMax>0.5</greenMax>
<greenMin>0</greenMin>
<maxValue>1</maxValue>
<minValue>0</minValue>
<redMax>1</redMax>
<redMin>0.75</redMin>
<sourceDataObject>ManualControlCommand</sourceDataObject>
<sourceObjectField>Throttle</sourceObjectField>
<useOpenGLFlag>false</useOpenGLFlag>
<yellowMax>0.75</yellowMax>
<yellowMin>0.5</yellowMin>
</data>
</Throttle>
<Yaw__PCT__20Desired>
<configInfo>
<locked>false</locked>
<version>0.0.0</version>
</configInfo>
<data>
<dFile>%%DATAPATH%%dials/default/lineardial-vertical.svg</dFile>
<decimalPlaces>2</decimalPlaces>
<factor>1</factor>
<font>Andale Mono,12,-1,5,75,0,0,0,0,0</font>
<greenMax>0.5</greenMax>
<greenMin>-0.5</greenMin>
<maxValue>1</maxValue>
<minValue>-1</minValue>
<redMax>1</redMax>
<redMin>-1</redMin>
<sourceDataObject>ActuatorDesired</sourceDataObject>
<sourceObjectField>Yaw</sourceObjectField>
<useOpenGLFlag>false</useOpenGLFlag>
<yellowMax>0.8</yellowMax>
<yellowMin>-0.8</yellowMin>
</data>
</Yaw__PCT__20Desired>
<Yaw>
<configInfo>
<locked>false</locked>
<version>0.0.0</version>
</configInfo>
<data>
<dFile>%%DATAPATH%%dials/default/lineardial-vertical.svg</dFile>
<decimalPlaces>2</decimalPlaces>
<factor>1</factor>
<font>Andale Mono,12,-1,5,75,0,0,0,0,0</font>
<greenMax>0.5</greenMax>
<greenMin>-0.5</greenMin>
<maxValue>1</maxValue>
<minValue>-1</minValue>
<redMax>1</redMax>
<redMin>-1</redMin>
<sourceDataObject>ManualControlCommand</sourceDataObject>
<sourceObjectField>Yaw</sourceObjectField>
<useOpenGLFlag>false</useOpenGLFlag>
<yellowMax>0.8</yellowMax>
<yellowMin>-0.8</yellowMin>
</data>
</Yaw>
</LineardialGadget>
<ModelViewGadget>
<Aeroquad__PCT__20__PCT__2B>
<configInfo>
<locked>false</locked>
<version>0.0.0</version>
</configInfo>
<data>
<acFilename>%%DATAPATH%%models/multi/aeroquad/aeroquad_+.3ds</acFilename>
<bgFilename>%%DATAPATH%%models/backgrounds/default_background.png</bgFilename>
<enableVbo>false</enableVbo>
</data>
</Aeroquad__PCT__20__PCT__2B>
<Easyquad__PCT__20X>
<configInfo>
<locked>false</locked>
<version>0.0.0</version>
</configInfo>
<data>
<acFilename>%%DATAPATH%%models/multi/easy_quad/easy_quad_X.3ds</acFilename>
<bgFilename>%%DATAPATH%%models/backgrounds/default_background.png</bgFilename>
<enableVbo>false</enableVbo>
</data>
</Easyquad__PCT__20X>
<Easystar>
<configInfo>
<locked>false</locked>
<version>0.0.0</version>
</configInfo>
<data>
<acFilename>%%DATAPATH%%models/planes/Easystar/easystar.3ds</acFilename>
<bgFilename>%%DATAPATH%%models/backgrounds/default_background.png</bgFilename>
<enableVbo>false</enableVbo>
</data>
</Easystar>
<Firecracker>
<configInfo>
<locked>false</locked>
<version>0.0.0</version>
</configInfo>
<data>
<acFilename>%%DATAPATH%%models/planes/firecracker/firecracker.3ds</acFilename>
<bgFilename>%%DATAPATH%%models/backgrounds/default_background.png</bgFilename>
<enableVbo>false</enableVbo>
</data>
</Firecracker>
<Funjet>
<configInfo>
<locked>false</locked>
<version>0.0.0</version>
</configInfo>
<data>
<acFilename>%%DATAPATH%%models/planes/funjet/funjet.3ds</acFilename>
<bgFilename>%%DATAPATH%%models/backgrounds/default_background.png</bgFilename>
<enableVbo>false</enableVbo>
</data>
</Funjet>
<Gaui__PCT__20330X>
<configInfo>
<locked>false</locked>
<version>0.0.0</version>
</configInfo>
<data>
<acFilename>%%DATAPATH%%models/multi/gaui_330x/gaui_330x.3ds</acFilename>
<bgFilename>%%DATAPATH%%models/backgrounds/default_background.png</bgFilename>
<enableVbo>false</enableVbo>
</data>
</Gaui__PCT__20330X>
<Helicopter__PCT__20-__PCT__20TRex__PCT__20450>
<configInfo>
<locked>false</locked>
<version>0.0.0</version>
</configInfo>
<data>
<acFilename>%%DATAPATH%%models/helis/t-rex/t-rex_450_xl.3ds</acFilename>
<bgFilename>%%DATAPATH%%models/backgrounds/default_background.png</bgFilename>
<enableVbo>false</enableVbo>
</data>
</Helicopter__PCT__20-__PCT__20TRex__PCT__20450>
<Hexacopter>
<configInfo>
<locked>false</locked>
<version>0.0.0</version>
</configInfo>
<data>
<acFilename>%%DATAPATH%%models/multi/mikrokopter/MK_Hexa.3ds</acFilename>
<bgFilename>%%DATAPATH%%models/backgrounds/default_background.png</bgFilename>
<enableVbo>false</enableVbo>
</data>
</Hexacopter>
<Quadcopter>
<configInfo>
<locked>false</locked>
<version>0.0.0</version>
</configInfo>
<data>
<acFilename>%%DATAPATH%%models/multi/mikrokopter/MK_L4-ME.3ds</acFilename>
<bgFilename>%%DATAPATH%%models/backgrounds/default_background.png</bgFilename>
<enableVbo>false</enableVbo>
</data>
</Quadcopter>
<Scorpion__PCT__20Tricopter>
<configInfo>
<locked>false</locked>
<version>0.0.0</version>
</configInfo>
<data>
<acFilename>%%DATAPATH%%models/multi/scorpion_tricopter/scorpion_tricopter.3ds</acFilename>
<bgFilename>%%DATAPATH%%models/backgrounds/default_background.png</bgFilename>
<enableVbo>false</enableVbo>
</data>
</Scorpion__PCT__20Tricopter>
<Test__PCT__20Quad__PCT__20__PCT__2B>
<configInfo>
<locked>false</locked>
<version>0.0.0</version>
</configInfo>
<data>
<acFilename>%%DATAPATH%%models/multi/test_quad/test_quad_+.3ds</acFilename>
<bgFilename>%%DATAPATH%%models/backgrounds/default_background.png</bgFilename>
<enableVbo>false</enableVbo>
</data>
</Test__PCT__20Quad__PCT__20__PCT__2B>
<Test__PCT__20Quad__PCT__20X>
<configInfo>
<locked>false</locked>
<version>0.0.0</version>
</configInfo>
<data>
<acFilename>%%DATAPATH%%models/multi/test_quad/test_quad_X.3ds</acFilename>
<bgFilename>%%DATAPATH%%models/backgrounds/default_background.png</bgFilename>
<enableVbo>false</enableVbo>
</data>
</Test__PCT__20Quad__PCT__20X>
</ModelViewGadget>
<OPMapGadget>
<Google__PCT__20Sat>
<configInfo>
<locked>false</locked>
<version>0.0.0</version>
</configInfo>
<data>
<accessMode>ServerAndCache</accessMode>
<cacheLocation>%%STOREPATH%%mapscache/</cacheLocation>
<defaultLatitude>0</defaultLatitude>
<defaultLongitude>0</defaultLongitude>
<defaultZoom>2</defaultZoom>
<mapProvider>GoogleSatellite</mapProvider>
<maxUpdateRate>2000</maxUpdateRate>
<showTileGridLines>false</showTileGridLines>
<uavSymbol>mapquad.png</uavSymbol>
<useMemoryCache>true</useMemoryCache>
<useOpenGL>false</useOpenGL>
</data>
</Google__PCT__20Sat>
<Memory__PCT__20Only>
<configInfo>
<locked>false</locked>
<version>0.0.0</version>
</configInfo>
<data>
<accessMode>CacheOnly</accessMode>
<cacheLocation>%%STOREPATH%%mapscache/</cacheLocation>
<defaultLatitude>0</defaultLatitude>
<defaultLongitude>0</defaultLongitude>
<defaultZoom>2</defaultZoom>
<mapProvider>GoogleMap</mapProvider>
<maxUpdateRate>2000</maxUpdateRate>
<showTileGridLines>false</showTileGridLines>
<uavSymbol>airplanepip.png</uavSymbol>
<useMemoryCache>true</useMemoryCache>
<useOpenGL>false</useOpenGL>
</data>
</Memory__PCT__20Only>
<default>
<configInfo>
<locked>false</locked>
<version>0.0.0</version>
</configInfo>
<data>
<accessMode>ServerAndCache</accessMode>
<cacheLocation>%%STOREPATH%%mapscache/</cacheLocation>
<defaultLatitude>0</defaultLatitude>
<defaultLongitude>0</defaultLongitude>
<defaultZoom>2</defaultZoom>
<mapProvider>GoogleMap</mapProvider>
<maxUpdateRate>2000</maxUpdateRate>
<showTileGridLines>false</showTileGridLines>
<uavSymbol>mapquad.png</uavSymbol>
<useMemoryCache>true</useMemoryCache>
<useOpenGL>false</useOpenGL>
</data>
</default>
</OPMapGadget>
<PFDGadget>
<raw>
<configInfo>
<locked>false</locked>
<version>0.0.0</version>
</configInfo>
<data>
<beSmooth>false</beSmooth>
<dialFile>%%DATAPATH%%pfd/default/pfd.svg</dialFile>
<hqFonts>false</hqFonts>
<useOpenGLFlag>false</useOpenGLFlag>
</data>
</raw>
<smooth>
<configInfo>
<locked>false</locked>
<version>0.0.0</version>
</configInfo>
<data>
<beSmooth>true</beSmooth>
<dialFile>%%DATAPATH%%pfd/default/pfd.svg</dialFile>
<hqFonts>false</hqFonts>
<useOpenGLFlag>false</useOpenGLFlag>
</data>
</smooth>
</PFDGadget>
<PipXtreme>
<default>
<configInfo>
<locked>false</locked>
<version>0.0.0</version>
</configInfo>
</default>
</PipXtreme>
<ScopeGadget>
<Accel>
<configInfo>
<locked>false</locked>
<version>0.0.0</version>
</configInfo>
<data>
<LoggingEnabled>false</LoggingEnabled>
<LoggingNewFileOnConnect>false</LoggingNewFileOnConnect>
<LoggingPath></LoggingPath>
<configurationStreamVersion>1000</configurationStreamVersion>
<dataSize>60</dataSize>
<plotCurve0>
<color>4294901760</color>
<uavField>accels-X</uavField>
<uavObject>AttitudeRaw</uavObject>
<yMaximum>0</yMaximum>
<yMinimum>0</yMinimum>
<yScalePower>0</yScalePower>
</plotCurve0>
<plotCurve1>
<color>4283782655</color>
<uavField>accels-Y</uavField>
<uavObject>AttitudeRaw</uavObject>
<yMaximum>0</yMaximum>
<yMinimum>0</yMinimum>
<yScalePower>0</yScalePower>
</plotCurve1>
<plotCurve2>
<color>4283804160</color>
<uavField>accels-Z</uavField>
<uavObject>AttitudeRaw</uavObject>
<yMaximum>0</yMaximum>
<yMinimum>0</yMinimum>
<yScalePower>0</yScalePower>
</plotCurve2>
<plotCurveCount>3</plotCurveCount>
<plotType>1</plotType>
<refreshInterval>100</refreshInterval>
</data>
</Accel>
<Actuators>
<configInfo>
<locked>false</locked>
<version>0.0.0</version>
</configInfo>
<data>
<LoggingEnabled>false</LoggingEnabled>
<LoggingNewFileOnConnect>false</LoggingNewFileOnConnect>
<LoggingPath></LoggingPath>
<configurationStreamVersion>1000</configurationStreamVersion>
<dataSize>20</dataSize>
<plotCurve0>
<color>4294901760</color>
<uavField>Channel-4</uavField>
<uavObject>ActuatorCommand</uavObject>
<yMaximum>0</yMaximum>
<yMinimum>0</yMinimum>
<yScalePower>0</yScalePower>
</plotCurve0>
<plotCurve1>
<color>4294901760</color>
<uavField>Channel-5</uavField>
<uavObject>ActuatorCommand</uavObject>
<yMaximum>0</yMaximum>
<yMinimum>0</yMinimum>
<yScalePower>0</yScalePower>
</plotCurve1>
<plotCurve2>
<color>4289374847</color>
<uavField>Channel-6</uavField>
<uavObject>ActuatorCommand</uavObject>
<yMaximum>0</yMaximum>
<yMinimum>0</yMinimum>
<yScalePower>0</yScalePower>
</plotCurve2>
<plotCurve3>
<color>4289374847</color>
<uavField>Channel-7</uavField>
<uavObject>ActuatorCommand</uavObject>
<yMaximum>0</yMaximum>
<yMinimum>0</yMinimum>
<yScalePower>0</yScalePower>
</plotCurve3>
<plotCurveCount>4</plotCurveCount>
<plotType>1</plotType>
<refreshInterval>100</refreshInterval>
</data>
</Actuators>
<Attitude>
<configInfo>
<locked>false</locked>
<version>0.0.0</version>
</configInfo>
<data>
<LoggingEnabled>false</LoggingEnabled>
<LoggingNewFileOnConnect>false</LoggingNewFileOnConnect>
<LoggingPath></LoggingPath>
<configurationStreamVersion>1000</configurationStreamVersion>
<dataSize>60</dataSize>
<plotCurve0>
<color>4283760895</color>
<uavField>Roll</uavField>
<uavObject>AttitudeActual</uavObject>
<yMaximum>0</yMaximum>
<yMinimum>0</yMinimum>
<yScalePower>0</yScalePower>
</plotCurve0>
<plotCurve1>
<color>4278233600</color>
<uavField>Yaw</uavField>
<uavObject>AttitudeActual</uavObject>
<yMaximum>0</yMaximum>
<yMinimum>0</yMinimum>
<yScalePower>0</yScalePower>
</plotCurve1>
<plotCurve2>
<color>4294901760</color>
<uavField>Pitch</uavField>
<uavObject>AttitudeActual</uavObject>
<yMaximum>0</yMaximum>
<yMinimum>0</yMinimum>
<yScalePower>0</yScalePower>
</plotCurve2>
<plotCurveCount>3</plotCurveCount>
<plotType>1</plotType>
<refreshInterval>100</refreshInterval>
</data>
</Attitude>
<Barometer>
<configInfo>
<locked>false</locked>
<version>0.0.0</version>
</configInfo>
<data>
<LoggingEnabled>false</LoggingEnabled>
<LoggingNewFileOnConnect>false</LoggingNewFileOnConnect>
<LoggingPath></LoggingPath>
<configurationStreamVersion>1000</configurationStreamVersion>
<dataSize>60</dataSize>
<plotCurve0>
<color>4278190080</color>
<uavField>Pressure</uavField>
<uavObject>BaroAltitude</uavObject>
<yMaximum>0</yMaximum>
<yMinimum>0</yMinimum>
<yScalePower>0</yScalePower>
</plotCurve0>
<plotCurveCount>1</plotCurveCount>
<plotType>1</plotType>
<refreshInterval>1000</refreshInterval>
</data>
</Barometer>
<Inputs>
<configInfo>
<locked>false</locked>
<version>0.0.0</version>
</configInfo>
<data>
<LoggingEnabled>false</LoggingEnabled>
<LoggingNewFileOnConnect>false</LoggingNewFileOnConnect>
<LoggingPath></LoggingPath>
<configurationStreamVersion>1000</configurationStreamVersion>
<dataSize>40</dataSize>
<plotCurve0>
<color>4278190207</color>
<uavField>Channel-1</uavField>
<uavObject>ManualControlCommand</uavObject>
<yMaximum>0</yMaximum>
<yMinimum>0</yMinimum>
<yScalePower>0</yScalePower>
</plotCurve0>
<plotCurve1>
<color>4294901760</color>
<uavField>Channel-4</uavField>
<uavObject>ManualControlCommand</uavObject>
<yMaximum>0</yMaximum>
<yMinimum>0</yMinimum>
<yScalePower>0</yScalePower>
</plotCurve1>
<plotCurve2>
<color>4294901760</color>
<uavField>Channel-5</uavField>
<uavObject>ManualControlCommand</uavObject>
<yMaximum>0</yMaximum>
<yMinimum>0</yMinimum>
<yScalePower>0</yScalePower>
</plotCurve2>
<plotCurve3>
<color>4294901760</color>
<uavField>Channel-6</uavField>
<uavObject>ManualControlCommand</uavObject>
<yMaximum>0</yMaximum>
<yMinimum>0</yMinimum>
<yScalePower>0</yScalePower>
</plotCurve3>
<plotCurve4>
<color>4294901760</color>
<uavField>Channel-7</uavField>
<uavObject>ManualControlCommand</uavObject>
<yMaximum>0</yMaximum>
<yMinimum>0</yMinimum>
<yScalePower>0</yScalePower>
</plotCurve4>
<plotCurve5>
<color>4283825920</color>
<uavField>Channel-2</uavField>
<uavObject>ManualControlCommand</uavObject>
<yMaximum>0</yMaximum>
<yMinimum>0</yMinimum>
<yScalePower>0</yScalePower>
</plotCurve5>
<plotCurve6>
<color>4294923520</color>
<uavField>Channel-3</uavField>
<uavObject>ManualControlCommand</uavObject>
<yMaximum>0</yMaximum>
<yMinimum>0</yMinimum>
<yScalePower>0</yScalePower>
</plotCurve6>
<plotCurve7>
<color>4294967040</color>
<uavField>Channel-0</uavField>
<uavObject>ManualControlCommand</uavObject>
<yMaximum>0</yMaximum>
<yMinimum>0</yMinimum>
<yScalePower>0</yScalePower>
</plotCurve7>
<plotCurveCount>8</plotCurveCount>
<plotType>1</plotType>
<refreshInterval>200</refreshInterval>
</data>
</Inputs>
<Raw__PCT__20Accels>
<configInfo>
<locked>false</locked>
<version>0.0.0</version>
</configInfo>
<data>
<LoggingEnabled>false</LoggingEnabled>
<LoggingNewFileOnConnect>false</LoggingNewFileOnConnect>
<LoggingPath></LoggingPath>
<configurationStreamVersion>1000</configurationStreamVersion>
<dataSize>60</dataSize>
<plotCurve0>
<color>4294901760</color>
<uavField>accels-X</uavField>
<uavObject>AttitudeRaw</uavObject>
<yMaximum>0</yMaximum>
<yMinimum>0</yMinimum>
<yScalePower>0</yScalePower>
</plotCurve0>
<plotCurve1>
<color>4283782655</color>
<uavField>accels-Y</uavField>
<uavObject>AttitudeRaw</uavObject>
<yMaximum>0</yMaximum>
<yMinimum>0</yMinimum>
<yScalePower>0</yScalePower>
</plotCurve1>
<plotCurve2>
<color>4283804160</color>
<uavField>accels-Z</uavField>
<uavObject>AttitudeRaw</uavObject>
<yMaximum>0</yMaximum>
<yMinimum>0</yMinimum>
<yScalePower>0</yScalePower>
</plotCurve2>
<plotCurveCount>3</plotCurveCount>
<plotType>1</plotType>
<refreshInterval>500</refreshInterval>
</data>
</Raw__PCT__20Accels>
<Raw__PCT__20Gyros>
<configInfo>
<locked>false</locked>
<version>0.0.0</version>
</configInfo>
<data>
<LoggingEnabled>false</LoggingEnabled>
<LoggingNewFileOnConnect>false</LoggingNewFileOnConnect>
<LoggingPath></LoggingPath>
<configurationStreamVersion>1000</configurationStreamVersion>
<dataSize>60</dataSize>
<plotCurve0>
<color>4283804160</color>
<uavField>gyros-Z</uavField>
<uavObject>AttitudeRaw</uavObject>
<yMaximum>0</yMaximum>
<yMinimum>0</yMinimum>
<yScalePower>0</yScalePower>
</plotCurve0>
<plotCurve1>
<color>4283782655</color>
<uavField>gyros-Y</uavField>
<uavObject>AttitudeRaw</uavObject>
<yMaximum>0</yMaximum>
<yMinimum>0</yMinimum>
<yScalePower>0</yScalePower>
</plotCurve1>
<plotCurve2>
<color>4294901760</color>
<uavField>gyros-X</uavField>
<uavObject>AttitudeRaw</uavObject>
<yMaximum>0</yMaximum>
<yMinimum>0</yMinimum>
<yScalePower>0</yScalePower>
</plotCurve2>
<plotCurveCount>3</plotCurveCount>
<plotType>1</plotType>
<refreshInterval>500</refreshInterval>
</data>
</Raw__PCT__20Gyros>
<Raw__PCT__20magnetometers>
<configInfo>
<locked>false</locked>
<version>0.0.0</version>
</configInfo>
<data>
<LoggingEnabled>false</LoggingEnabled>
<LoggingNewFileOnConnect>false</LoggingNewFileOnConnect>
<LoggingPath></LoggingPath>
<configurationStreamVersion>1000</configurationStreamVersion>
<dataSize>60</dataSize>
<plotCurve0>
<color>4294901760</color>
<uavField>magnetometers-X</uavField>
<uavObject>AttitudeRaw</uavObject>
<yMaximum>0</yMaximum>
<yMinimum>0</yMinimum>
<yScalePower>0</yScalePower>
</plotCurve0>
<plotCurve1>
<color>4283782655</color>
<uavField>magnetometers-Y</uavField>
<uavObject>AttitudeRaw</uavObject>
<yMaximum>0</yMaximum>
<yMinimum>0</yMinimum>
<yScalePower>0</yScalePower>
</plotCurve1>
<plotCurve2>
<color>4283804160</color>
<uavField>magnetometers-Z</uavField>
<uavObject>AttitudeRaw</uavObject>
<yMaximum>0</yMaximum>
<yMinimum>0</yMinimum>
<yScalePower>0</yScalePower>
</plotCurve2>
<plotCurveCount>3</plotCurveCount>
<plotType>1</plotType>
<refreshInterval>500</refreshInterval>
</data>
</Raw__PCT__20magnetometers>
<Stacks__PCT__20monitor>
<configInfo>
<locked>false</locked>
<version>0.0.0</version>
</configInfo>
<data>
<LoggingEnabled>false</LoggingEnabled>
<LoggingNewFileOnConnect>false</LoggingNewFileOnConnect>
<LoggingPath></LoggingPath>
<configurationStreamVersion>1000</configurationStreamVersion>
<dataSize>240</dataSize>
<plotCurve0>
<color>4294945280</color>
<uavField>StackRemaining-System</uavField>
<uavObject>TaskInfo</uavObject>
<yMaximum>0</yMaximum>
<yMinimum>0</yMinimum>
<yScalePower>0</yScalePower>
</plotCurve0>
<plotCurve1>
<color>4294945280</color>
<uavField>StackRemaining-Actuator</uavField>
<uavObject>TaskInfo</uavObject>
<yMaximum>0</yMaximum>
<yMinimum>0</yMinimum>
<yScalePower>0</yScalePower>
</plotCurve1>
<plotCurve10>
<color>4294945280</color>
<uavField>StackRemaining-Guidance</uavField>
<uavObject>TaskInfo</uavObject>
<yMaximum>0</yMaximum>
<yMinimum>0</yMinimum>
<yScalePower>0</yScalePower>
</plotCurve10>
<plotCurve11>
<color>4294945280</color>
<uavField>StackRemaining-Watchdog</uavField>
<uavObject>TaskInfo</uavObject>
<yMaximum>0</yMaximum>
<yMinimum>0</yMinimum>
<yScalePower>0</yScalePower>
</plotCurve11>
<plotCurve2>
<color>4294945280</color>
<uavField>StackRemaining-TelemetryTx</uavField>
<uavObject>TaskInfo</uavObject>
<yMaximum>0</yMaximum>
<yMinimum>0</yMinimum>
<yScalePower>0</yScalePower>
</plotCurve2>
<plotCurve3>
<color>4294945280</color>
<uavField>StackRemaining-TelemetryTxPri</uavField>
<uavObject>TaskInfo</uavObject>
<yMaximum>0</yMaximum>
<yMinimum>0</yMinimum>
<yScalePower>0</yScalePower>
</plotCurve3>
<plotCurve4>
<color>4294945280</color>
<uavField>StackRemaining-TelemetryRx</uavField>
<uavObject>TaskInfo</uavObject>
<yMaximum>0</yMaximum>
<yMinimum>0</yMinimum>
<yScalePower>0</yScalePower>
</plotCurve4>
<plotCurve5>
<color>4294945280</color>
<uavField>StackRemaining-GPS</uavField>
<uavObject>TaskInfo</uavObject>
<yMaximum>0</yMaximum>
<yMinimum>0</yMinimum>
<yScalePower>0</yScalePower>
</plotCurve5>
<plotCurve6>
<color>4294945280</color>
<uavField>StackRemaining-ManualControl</uavField>
<uavObject>TaskInfo</uavObject>
<yMaximum>0</yMaximum>
<yMinimum>0</yMinimum>
<yScalePower>0</yScalePower>
</plotCurve6>
<plotCurve7>
<color>4294945280</color>
<uavField>StackRemaining-Altitude</uavField>
<uavObject>TaskInfo</uavObject>
<yMaximum>0</yMaximum>
<yMinimum>0</yMinimum>
<yScalePower>0</yScalePower>
</plotCurve7>
<plotCurve8>
<color>4294945280</color>
<uavField>StackRemaining-AHRSComms</uavField>
<uavObject>TaskInfo</uavObject>
<yMaximum>0</yMaximum>
<yMinimum>0</yMinimum>
<yScalePower>0</yScalePower>
</plotCurve8>
<plotCurve9>
<color>4294945280</color>
<uavField>StackRemaining-Stabilization</uavField>
<uavObject>TaskInfo</uavObject>
<yMaximum>0</yMaximum>
<yMinimum>0</yMinimum>
<yScalePower>0</yScalePower>
</plotCurve9>
<plotCurveCount>12</plotCurveCount>
<plotType>1</plotType>
<refreshInterval>1000</refreshInterval>
</data>
</Stacks__PCT__20monitor>
<Telemetry__PCT__20quality>
<configInfo>
<locked>false</locked>
<version>0.0.0</version>
</configInfo>
<data>
<LoggingEnabled>false</LoggingEnabled>
<LoggingNewFileOnConnect>false</LoggingNewFileOnConnect>
<LoggingPath></LoggingPath>
<configurationStreamVersion>1000</configurationStreamVersion>
<dataSize>20</dataSize>
<plotCurve0>
<color>4289374847</color>
<uavField>TxFailures</uavField>
<uavObject>GCSTelemetryStats</uavObject>
<yMaximum>0</yMaximum>
<yMinimum>0</yMinimum>
<yScalePower>0</yScalePower>
</plotCurve0>
<plotCurve1>
<color>4283782655</color>
<uavField>RxFailures</uavField>
<uavObject>GCSTelemetryStats</uavObject>
<yMaximum>0</yMaximum>
<yMinimum>0</yMinimum>
<yScalePower>0</yScalePower>
</plotCurve1>
<plotCurve2>
<color>4294901760</color>
<uavField>TxRetries</uavField>
<uavObject>GCSTelemetryStats</uavObject>
<yMaximum>0</yMaximum>
<yMinimum>0</yMinimum>
<yScalePower>0</yScalePower>
</plotCurve2>
<plotCurveCount>3</plotCurveCount>
<plotType>1</plotType>
<refreshInterval>100</refreshInterval>
</data>
</Telemetry__PCT__20quality>
<Uptimes>
<configInfo>
<locked>false</locked>
<version>0.0.0</version>
</configInfo>
<data>
<LoggingEnabled>false</LoggingEnabled>
<LoggingNewFileOnConnect>false</LoggingNewFileOnConnect>
<LoggingPath></LoggingPath>
<configurationStreamVersion>1000</configurationStreamVersion>
<dataSize>240</dataSize>
<plotCurve0>
<color>4289374847</color>
<uavField>RunningTime</uavField>
<uavObject>AhrsStatus</uavObject>
<yMaximum>0</yMaximum>
<yMinimum>0</yMinimum>
<yScalePower>0</yScalePower>
</plotCurve0>
<plotCurve1>
<color>4294945407</color>
<uavField>FlightTime</uavField>
<uavObject>SystemStats</uavObject>
<yMaximum>0</yMaximum>
<yMinimum>0</yMinimum>
<yScalePower>0</yScalePower>
</plotCurve1>
<plotCurveCount>2</plotCurveCount>
<plotType>1</plotType>
<refreshInterval>800</refreshInterval>
</data>
</Uptimes>
</ScopeGadget>
<SystemHealthGadget>
<default>
<configInfo>
<locked>false</locked>
<version>0.0.0</version>
</configInfo>
<data>
<diagram>%%DATAPATH%%diagrams/default/system-health.svg</diagram>
</data>
</default>
</SystemHealthGadget>
<UAVObjectBrowser>
<default>
<configInfo>
<locked>false</locked>
<version>0.0.0</version>
</configInfo>
<data>
<manuallyChangedColor>#5baa56</manuallyChangedColor>
<recentlyUpdatedColor>#ff7957</recentlyUpdatedColor>
<recentlyUpdatedTimeout>500</recentlyUpdatedTimeout>
</data>
</default>
</UAVObjectBrowser>
<Uploader>
<default>
<configInfo>
<locked>false</locked>
<version>0.0.0</version>
</configInfo>
<data>
<defaultDataBits>3</defaultDataBits>
<defaultFlow>0</defaultFlow>
<defaultParity>0</defaultParity>
<defaultPort>/dev/ttyS0</defaultPort>
<defaultSpeed>14</defaultSpeed>
<defaultStopBits>0</defaultStopBits>
</data>
</default>
</Uploader>
<configInfo>
<locked>false</locked>
<version>1.2.0</version>
</configInfo>
</UAVGadgetConfigurations>
<UAVGadgetManager>
<Mode1>
<showToolbars>false</showToolbars>
<splitter>
<side0>
<side0>
<side0>
<side0>
<side0>
<classId>LineardialGadget</classId>
<gadget>
<activeConfiguration>Flight Time</activeConfiguration>
</gadget>
<type>uavGadget</type>
</side0>
<side1>
<classId>LineardialGadget</classId>
<gadget>
<activeConfiguration>GPS Sats</activeConfiguration>
</gadget>
<type>uavGadget</type>
</side1>
<splitterOrientation>2</splitterOrientation>
<splitterSizes>@Variant(AAAACQAAAAA=)</splitterSizes>
<type>splitter</type>
</side0>
<side1>
<side0>
<classId>LineardialGadget</classId>
<gadget>
<activeConfiguration>Flight mode</activeConfiguration>
</gadget>
<type>uavGadget</type>
</side0>
<side1>
<classId>LineardialGadget</classId>
<gadget>
<activeConfiguration>Arm Status</activeConfiguration>
</gadget>
<type>uavGadget</type>
</side1>
<splitterOrientation>2</splitterOrientation>
<splitterSizes>@Variant(AAAACQAAAAA=)</splitterSizes>
<type>splitter</type>
</side1>
<splitterOrientation>2</splitterOrientation>
<splitterSizes>@Variant(AAAACQAAAAIAAAACAAAA1wAAAAIAAADt)</splitterSizes>
<type>splitter</type>
</side0>
<side1>
<classId>PFDGadget</classId>
<gadget>
<activeConfiguration>raw</activeConfiguration>
</gadget>
<type>uavGadget</type>
</side1>
<splitterOrientation>1</splitterOrientation>
<splitterSizes>@Variant(AAAACQAAAAIAAAACAAAAkAAAAAIAAAJg)</splitterSizes>
<type>splitter</type>
</side0>
<side1>
<side0>
<classId>ModelViewGadget</classId>
<gadget>
<activeConfiguration>Test Quad X</activeConfiguration>
</gadget>
<type>uavGadget</type>
</side0>
<side1>
<side0>
<side0>
<classId>SystemHealthGadget</classId>
<gadget>
<activeConfiguration>default</activeConfiguration>
</gadget>
<type>uavGadget</type>
</side0>
<side1>
<side0>
<classId>LineardialGadget</classId>
<gadget>
<activeConfiguration>Mainboard CPU</activeConfiguration>
</gadget>
<type>uavGadget</type>
</side0>
<side1>
<classId>LineardialGadget</classId>
<gadget>
<activeConfiguration>AHRS CPU</activeConfiguration>
</gadget>
<type>uavGadget</type>
</side1>
<splitterOrientation>1</splitterOrientation>
<splitterSizes>@Variant(AAAACQAAAAIAAAACAAAAQAAAAAIAAABA)</splitterSizes>
<type>splitter</type>
</side1>
<splitterOrientation>1</splitterOrientation>
<splitterSizes>@Variant(AAAACQAAAAIAAAACAAABIwAAAAIAAACN)</splitterSizes>
<type>splitter</type>
</side0>
<side1>
<side0>
<classId>LineardialGadget</classId>
<gadget>
<activeConfiguration>Telemetry RX Rate Horizontal</activeConfiguration>
</gadget>
<type>uavGadget</type>
</side0>
<side1>
<classId>LineardialGadget</classId>
<gadget>
<activeConfiguration>Telemetry TX Rate Horizontal</activeConfiguration>
</gadget>
<type>uavGadget</type>
</side1>
<splitterOrientation>1</splitterOrientation>
<splitterSizes>@Variant(AAAACQAAAAA=)</splitterSizes>
<type>splitter</type>
</side1>
<splitterOrientation>2</splitterOrientation>
<splitterSizes>@Variant(AAAACQAAAAIAAAACAAABJQAAAAIAAABA)</splitterSizes>
<type>splitter</type>
</side1>
<splitterOrientation>1</splitterOrientation>
<splitterSizes>@Variant(AAAACQAAAAIAAAACAAABMAAAAAIAAAGx)</splitterSizes>
<type>splitter</type>
</side1>
<splitterOrientation>2</splitterOrientation>
<splitterSizes>@Variant(AAAACQAAAAIAAAACAAABxQAAAAIAAAFH)</splitterSizes>
<type>splitter</type>
</side0>
<side1>
<side0>
<classId>OPMapGadget</classId>
<gadget>
<activeConfiguration>Google Sat</activeConfiguration>
</gadget>
<type>uavGadget</type>
</side0>
<side1>
<side0>
<side0>
<side0>
<side0>
<classId>DialGadget</classId>
<gadget>
<activeConfiguration>Deluxe Groundspeed kph</activeConfiguration>
</gadget>
<type>uavGadget</type>
</side0>
<side1>
<classId>DialGadget</classId>
<gadget>
<activeConfiguration>Deluxe Barometer</activeConfiguration>
</gadget>
<type>uavGadget</type>
</side1>
<splitterOrientation>2</splitterOrientation>
<splitterSizes>@Variant(AAAACQAAAAA=)</splitterSizes>
<type>splitter</type>
</side0>
<side1>
<side0>
<classId>DialGadget</classId>
<gadget>
<activeConfiguration>Deluxe Attitude</activeConfiguration>
</gadget>
<type>uavGadget</type>
</side0>
<side1>
<classId>DialGadget</classId>
<gadget>
<activeConfiguration>Deluxe Compass</activeConfiguration>
</gadget>
<type>uavGadget</type>
</side1>
<splitterOrientation>2</splitterOrientation>
<splitterSizes>@Variant(AAAACQAAAAA=)</splitterSizes>
<type>splitter</type>
</side1>
<splitterOrientation>1</splitterOrientation>
<splitterSizes>@Variant(AAAACQAAAAIAAAACAAAAgwAAAAIAAACK)</splitterSizes>
<type>splitter</type>
</side0>
<side1>
<side0>
<classId>DialGadget</classId>
<gadget>
<activeConfiguration>Deluxe Baro Altimeter</activeConfiguration>
</gadget>
<type>uavGadget</type>
</side0>
<side1>
<classId>DialGadget</classId>
<gadget>
<activeConfiguration>Deluxe Climbrate</activeConfiguration>
</gadget>
<type>uavGadget</type>
</side1>
<splitterOrientation>2</splitterOrientation>
<splitterSizes>@Variant(AAAACQAAAAA=)</splitterSizes>
<type>splitter</type>
</side1>
<splitterOrientation>1</splitterOrientation>
<splitterSizes>@Variant(AAAACQAAAAIAAAACAAABFQAAAAIAAACH)</splitterSizes>
<type>splitter</type>
</side0>
<side1>
<side0>
<classId>LineardialGadget</classId>
<gadget>
<activeConfiguration>Throttle</activeConfiguration>
</gadget>
<type>uavGadget</type>
</side0>
<side1>
<side0>
<classId>LineardialGadget</classId>
<gadget>
<activeConfiguration>Roll Desired</activeConfiguration>
</gadget>
<type>uavGadget</type>
</side0>
<side1>
<side0>
<classId>LineardialGadget</classId>
<gadget>
<activeConfiguration>Pitch Desired</activeConfiguration>
</gadget>
<type>uavGadget</type>
</side0>
<side1>
<classId>LineardialGadget</classId>
<gadget>
<activeConfiguration>Yaw Desired</activeConfiguration>
</gadget>
<type>uavGadget</type>
</side1>
<splitterOrientation>1</splitterOrientation>
<splitterSizes>@Variant(AAAACQAAAAIAAAACAAAAQAAAAAIAAAE3)</splitterSizes>
<type>splitter</type>
</side1>
<splitterOrientation>1</splitterOrientation>
<splitterSizes>@Variant(AAAACQAAAAIAAAACAAAAQAAAAAIAAAF4)</splitterSizes>
<type>splitter</type>
</side1>
<splitterOrientation>1</splitterOrientation>
<splitterSizes>@Variant(AAAACQAAAAIAAAACAAAAQAAAAAIAAAG5)</splitterSizes>
<type>splitter</type>
</side1>
<splitterOrientation>1</splitterOrientation>
<splitterSizes>@Variant(AAAACQAAAAIAAAACAAABuQAAAAIAAAED)</splitterSizes>
<type>splitter</type>
</side1>
<splitterOrientation>2</splitterOrientation>
<splitterSizes>@Variant(AAAACQAAAAIAAAACAAAB7AAAAAIAAAEg)</splitterSizes>
<type>splitter</type>
</side1>
<splitterOrientation>1</splitterOrientation>
<splitterSizes>@Variant(AAAACQAAAAIAAAACAAAC4gAAAAIAAAK9)</splitterSizes>
<type>splitter</type>
</splitter>
<version>UAVGadgetManagerV1</version>
</Mode1>
<Mode2>
<showToolbars>false</showToolbars>
<splitter>
<side0>
<side0>
<classId>ConfigGadget</classId>
<gadget>
<activeConfiguration>default</activeConfiguration>
</gadget>
<type>uavGadget</type>
</side0>
<side1>
<side0>
<classId>LineardialGadget</classId>
<gadget>
<activeConfiguration>Telemetry RX Rate Horizontal</activeConfiguration>
</gadget>
<type>uavGadget</type>
</side0>
<side1>
<classId>LineardialGadget</classId>
<gadget>
<activeConfiguration>Telemetry TX Rate Horizontal</activeConfiguration>
</gadget>
<type>uavGadget</type>
</side1>
<splitterOrientation>1</splitterOrientation>
<splitterSizes>@Variant(AAAACQAAAAA=)</splitterSizes>
<type>splitter</type>
</side1>
<splitterOrientation>2</splitterOrientation>
<splitterSizes>@Variant(AAAACQAAAAIAAAACAAACNQAAAAIAAABC)</splitterSizes>
<type>splitter</type>
</side0>
<side1>
<side0>
<classId>UAVObjectBrowser</classId>
<gadget>
<activeConfiguration>default</activeConfiguration>
</gadget>
<type>uavGadget</type>
</side0>
<side1>
<classId>GCSControlGadget</classId>
<gadget>
<activeConfiguration>MS Sidewinder</activeConfiguration>
</gadget>
<type>uavGadget</type>
</side1>
<splitterOrientation>2</splitterOrientation>
<splitterSizes>@Variant(AAAACQAAAAIAAAACAAABqgAAAAIAAAFi)</splitterSizes>
<type>splitter</type>
</side1>
<splitterOrientation>1</splitterOrientation>
<splitterSizes>@Variant(AAAACQAAAAIAAAACAAAC3gAAAAIAAAJ3)</splitterSizes>
<type>splitter</type>
</splitter>
<version>UAVGadgetManagerV1</version>
</Mode2>
<Mode3>
<showToolbars>false</showToolbars>
<splitter>
<side0>
<classId>OPMapGadget</classId>
<gadget>
<activeConfiguration>default</activeConfiguration>
</gadget>
<type>uavGadget</type>
</side0>
<side1>
<side0>
<classId>ModelViewGadget</classId>
<gadget>
<activeConfiguration>Test Quad X</activeConfiguration>
</gadget>
<type>uavGadget</type>
</side0>
<side1>
<side0>
<classId>DialGadget</classId>
<gadget>
<activeConfiguration>Attitude</activeConfiguration>
</gadget>
<type>uavGadget</type>
</side0>
<side1>
<classId>DialGadget</classId>
<gadget>
<activeConfiguration>Compass</activeConfiguration>
</gadget>
<type>uavGadget</type>
</side1>
<splitterOrientation>1</splitterOrientation>
<splitterSizes>@Variant(AAAACQAAAAA=)</splitterSizes>
<type>splitter</type>
</side1>
<splitterOrientation>2</splitterOrientation>
<splitterSizes>@Variant(AAAACQAAAAIAAAACAAABiwAAAAIAAADs)</splitterSizes>
<type>splitter</type>
</side1>
<splitterOrientation>1</splitterOrientation>
<splitterSizes>@Variant(AAAACQAAAAIAAAACAAAD1AAAAAIAAAGB)</splitterSizes>
<type>splitter</type>
</splitter>
<version>UAVGadgetManagerV1</version>
</Mode3>
<Mode4>
<showToolbars>false</showToolbars>
<splitter>
<side0>
<side0>
<classId>ScopeGadget</classId>
<gadget>
<activeConfiguration>Accel</activeConfiguration>
</gadget>
<type>uavGadget</type>
</side0>
<side1>
<classId>ScopeGadget</classId>
<gadget>
<activeConfiguration>Raw Gyros</activeConfiguration>
</gadget>
<type>uavGadget</type>
</side1>
<splitterOrientation>2</splitterOrientation>
<splitterSizes>@Variant(AAAACQAAAAA=)</splitterSizes>
<type>splitter</type>
</side0>
<side1>
<side0>
<side0>
<classId>ScopeGadget</classId>
<gadget>
<activeConfiguration>Attitude</activeConfiguration>
</gadget>
<type>uavGadget</type>
</side0>
<side1>
<classId>ScopeGadget</classId>
<gadget>
<activeConfiguration>Uptimes</activeConfiguration>
</gadget>
<type>uavGadget</type>
</side1>
<splitterOrientation>2</splitterOrientation>
<splitterSizes>@Variant(AAAACQAAAAIAAAACAAABhgAAAAIAAAEO)</splitterSizes>
<type>splitter</type>
</side0>
<side1>
<classId>LoggingGadget</classId>
<type>uavGadget</type>
</side1>
<splitterOrientation>2</splitterOrientation>
<splitterSizes>@Variant(AAAACQAAAAIAAAACAAAClQAAAAIAAAB3)</splitterSizes>
<type>splitter</type>
</side1>
<splitterOrientation>1</splitterOrientation>
<splitterSizes>@Variant(AAAACQAAAAIAAAACAAACjQAAAAIAAAKU)</splitterSizes>
<type>splitter</type>
</splitter>
<version>UAVGadgetManagerV1</version>
</Mode4>
<Mode5>
<showToolbars>false</showToolbars>
<splitter>
<side0>
<side0>
<classId>HITL</classId>
<gadget>
<activeConfiguration>XPlane HITL</activeConfiguration>
</gadget>
<type>uavGadget</type>
</side0>
<side1>
<side0>
<classId>GCSControlGadget</classId>
<gadget>
<activeConfiguration>MS Sidewinder</activeConfiguration>
</gadget>
<type>uavGadget</type>
</side0>
<side1>
<side0>
<side0>
<classId>LineardialGadget</classId>
<gadget>
<activeConfiguration>Pitch Desired</activeConfiguration>
</gadget>
<type>uavGadget</type>
</side0>
<side1>
<classId>LineardialGadget</classId>
<gadget>
<activeConfiguration>PitchActual</activeConfiguration>
</gadget>
<type>uavGadget</type>
</side1>
<splitterOrientation>1</splitterOrientation>
<splitterSizes>@Variant(AAAACQAAAAA=)</splitterSizes>
<type>splitter</type>
</side0>
<side1>
<classId>LineardialGadget</classId>
<gadget>
<activeConfiguration>Pitch</activeConfiguration>
</gadget>
<type>uavGadget</type>
</side1>
<splitterOrientation>1</splitterOrientation>
<splitterSizes>@Variant(AAAACQAAAAIAAAACAAABFAAAAAIAAABA)</splitterSizes>
<type>splitter</type>
</side1>
<splitterOrientation>1</splitterOrientation>
<splitterSizes>@Variant(AAAACQAAAAIAAAACAAAB6AAAAAIAAADC)</splitterSizes>
<type>splitter</type>
</side1>
<splitterOrientation>2</splitterOrientation>
<splitterSizes>@Variant(AAAACQAAAAIAAAACAAABaQAAAAIAAAEO)</splitterSizes>
<type>splitter</type>
</side0>
<side1>
<classId>UAVObjectBrowser</classId>
<gadget>
<activeConfiguration>default</activeConfiguration>
</gadget>
<type>uavGadget</type>
</side1>
<splitterOrientation>1</splitterOrientation>
<splitterSizes>@Variant(AAAACQAAAAIAAAACAAADDAAAAAIAAAJJ)</splitterSizes>
<type>splitter</type>
</splitter>
<version>UAVGadgetManagerV1</version>
</Mode5>
<Mode6>
<showToolbars>false</showToolbars>
<splitter>
<side0>
<classId>Uploader</classId>
<gadget>
<activeConfiguration>default</activeConfiguration>
</gadget>
<type>uavGadget</type>
</side0>
<side1>
<side0>
<side0>
<classId>SystemHealthGadget</classId>
<gadget>
<activeConfiguration>default</activeConfiguration>
</gadget>
<type>uavGadget</type>
</side0>
<side1>
<classId>PFDGadget</classId>
<gadget>
<activeConfiguration>raw</activeConfiguration>
</gadget>
<type>uavGadget</type>
</side1>
<splitterOrientation>1</splitterOrientation>
<splitterSizes>@Variant(AAAACQAAAAIAAAACAAABQgAAAAIAAAGM)</splitterSizes>
<type>splitter</type>
</side0>
<side1>
<classId>ScopeGadget</classId>
<gadget>
<activeConfiguration>Uptimes</activeConfiguration>
</gadget>
<type>uavGadget</type>
</side1>
<splitterOrientation>2</splitterOrientation>
<splitterSizes>@Variant(AAAACQAAAAIAAAACAAABEgAAAAIAAAH6)</splitterSizes>
<type>splitter</type>
</side1>
<splitterOrientation>1</splitterOrientation>
<splitterSizes>@Variant(AAAACQAAAAA=)</splitterSizes>
<type>splitter</type>
</splitter>
<version>UAVGadgetManagerV1</version>
</Mode6>
</UAVGadgetManager>
<ViewGroup_Default>@ByteArray(AAAA/wAAAAD9AAAAAAAABQAAAALCAAAABAAAAAQAAAABAAAACPwAAAAA)</ViewGroup_Default>
<Workspace>
<Icon1>:/core/images/ah.png</Icon1>
<Icon10>:/core/images/openpilot_logo_64.png</Icon10>
<Icon2>:/core/images/config.png</Icon2>
<Icon3>:/core/images/world.png</Icon3>
<Icon4>:/core/images/scopes.png</Icon4>
<Icon5>:/core/images/joystick.png</Icon5>
<Icon6>:/core/images/cog.png</Icon6>
<Icon7>:/core/images/openpilot_logo_64.png</Icon7>
<Icon8>:/core/images/openpilot_logo_64.png</Icon8>
<Icon9>:/core/images/openpilot_logo_64.png</Icon9>
<NumberOfWorkspaces>6</NumberOfWorkspaces>
<Workspace1>Flight data</Workspace1>
<Workspace10>Workspace10</Workspace10>
<Workspace2>Configuration</Workspace2>
<Workspace3>Flight Planner</Workspace3>
<Workspace4>Scopes</Workspace4>
<Workspace5>HITL</Workspace5>
<Workspace6>Firmware</Workspace6>
<Workspace7>Workspace7</Workspace7>
<Workspace8>Workspace8</Workspace8>
<Workspace9>Workspace9</Workspace9>
</Workspace>
</gcs>

View File

@ -50,7 +50,6 @@
<file>images/optionsicon.png</file>
<file>images/helpicon.png</file>
<file>images/openpiloticon.png</file>
<file>OpenPilotGCS.ini</file>
<file>CREDITS.html</file>
<file>images/ah.png</file>
<file>images/config.png</file>
@ -60,5 +59,6 @@
<file>images/scopes.png</file>
<file>images/world.png</file>
<file>images/cog.png</file>
<file>OpenPilotGCS.xml</file>
</qresource>
</RCC>

View File

@ -32,6 +32,7 @@
#include <coreplugin/core_global.h>
#include <QtCore/QObject>
#include <QtGui/QIcon>
QT_BEGIN_NAMESPACE
class QWidget;
@ -43,9 +44,14 @@ class CORE_EXPORT IOptionsPage : public QObject
{
Q_OBJECT
public:
IOptionsPage(QObject *parent = 0) : QObject(parent) {}
IOptionsPage(QObject *parent = 0) :
QObject(parent),
m_icon(QIcon()) {}
virtual ~IOptionsPage() {}
void setIcon(QIcon icon) { m_icon = icon; }
QIcon icon() { return m_icon; }
/* gadget options pages can leave these 4 functions as is,
since they are decorated by UAVGadgetOptionsPageDecorator,
all other options pages must override these */
@ -57,6 +63,8 @@ public:
virtual QWidget *createPage(QWidget *parent) = 0;
virtual void apply() = 0;
virtual void finish() = 0;
private:
QIcon m_icon;
};
} // namespace Core

View File

@ -114,6 +114,7 @@ SettingsDialog::SettingsDialog(QWidget *parent, const QString &categoryId,
splitter->setCollapsible(0, false);
splitter->setCollapsible(1, false);
pageTree->header()->setVisible(false);
// pageTree->setIconSize(QSize(24, 24));
connect(pageTree, SIGNAL(currentItemChanged(QTreeWidgetItem *, QTreeWidgetItem *)),
this, SLOT(pageSelected()));
@ -150,6 +151,7 @@ SettingsDialog::SettingsDialog(QWidget *parent, const QString &categoryId,
}
}
categoryItem = new QTreeWidgetItem(pageTree);
categoryItem->setIcon(0, page->icon());
categoryItem->setText(0, trCategories);
categoryItem->setData(0, Qt::UserRole, qVariantFromValue(pageData));
categories.insert(currentCategory, categoryItem);

View File

@ -31,6 +31,7 @@
#include "core_global.h"
#include <QtCore/QObject>
#include <QtGui/QIcon>
#include <QSettings>
#include "uavconfiginfo.h"
@ -51,7 +52,9 @@ public:
IUAVGadgetFactory(QString classId, QString name, QObject *parent = 0) :
QObject(parent),
m_classId(classId),
m_name(name) {}
m_name(name),
m_icon(QIcon()),
m_singleConfigurationGadget(false) {}
virtual ~IUAVGadgetFactory() {}
virtual IUAVGadget *createGadget(QWidget *parent) = 0;
@ -60,9 +63,16 @@ public:
virtual IOptionsPage *createOptionsPage(IUAVGadgetConfiguration */*config*/) { return 0; }
QString classId() const { return m_classId; }
QString name() const { return m_name; }
QIcon icon() const { return m_icon; }
bool isSingleConfigurationGadget() { return m_singleConfigurationGadget; }
protected:
void setIcon(QIcon icon) { m_icon = icon; }
void setSingleConfigurationGadgetTrue() { m_singleConfigurationGadget = true; }
private:
QString m_classId; // unique class id
QString m_name; // display name, should also be unique
QIcon m_icon;
bool m_singleConfigurationGadget; // true if there is exactly one configuration for this gadget
};
} // namespace Core

View File

@ -30,6 +30,7 @@
#include "actioncontainer.h"
#include "actionmanager_p.h"
#include "basemode.h"
#include "connectionmanager.h"
#include "coreimpl.h"
#include "coreconstants.h"
#include "fancytabwidget.h"
@ -39,35 +40,34 @@
#include "mimedatabase.h"
#include "outputpane.h"
#include "plugindialog.h"
#include "qxtlogger.h"
#include "qxtbasicstdloggerengine.h"
#include "shortcutsettings.h"
#include "workspacesettings.h"
#include "modemanager.h"
#include "uavgadgetmode.h"
#include "uavgadgetmanager.h"
#include "uavgadgetinstancemanager.h"
#include "connectionmanager.h"
#include "qxtlogger.h"
#include "qxtbasicstdloggerengine.h"
#include "workspacesettings.h"
#include "settingsdialog.h"
#include "variablemanager.h"
#include "threadmanager.h"
#include "versiondialog.h"
#include "authorsdialog.h"
#include "viewmanager.h"
#include "uniqueidmanager.h"
#include "manhattanstyle.h"
#include "dialogs/iwizard.h"
#include "rightpane.h"
#include "baseview.h"
#include "ioutputpane.h"
#include "icorelistener.h"
#include "iconfigurableplugin.h"
#include "manhattanstyle.h"
#include "rightpane.h"
#include "settingsdialog.h"
#include "threadmanager.h"
#include "uniqueidmanager.h"
#include "variablemanager.h"
#include "versiondialog.h"
#include "viewmanager.h"
#include <coreplugin/settingsdatabase.h>
#include <extensionsystem/pluginmanager.h>
#include "dialogs/iwizard.h"
#include <utils/pathchooser.h>
#include <utils/stylehelper.h>
#include <extensionsystem/pluginmanager.h>
#include <utils/xmlconfig.h>
#include <QtCore/QDebug>
#include <QtCore/QFileInfo>
@ -112,9 +112,9 @@ MainWindow::MainWindow() :
m_globalContext(QList<int>() << Constants::C_GLOBAL_ID),
m_additionalContexts(m_globalContext),
// keep this in sync with main() in app/main.cpp
m_settings(new QSettings(QSettings::IniFormat, QSettings::UserScope,
m_settings(new QSettings(XmlConfig::XmlSettingsFormat, QSettings::UserScope,
QLatin1String("OpenPilot"), QLatin1String("OpenPilotGCS"), this)),
m_globalSettings(new QSettings(QSettings::IniFormat, QSettings::SystemScope,
m_globalSettings(new QSettings(XmlConfig::XmlSettingsFormat, QSettings::SystemScope,
QLatin1String("OpenPilot"), QLatin1String("OpenPilotGCS"), this)),
m_settingsDatabase(new SettingsDatabase(QFileInfo(m_settings->fileName()).path(),
QLatin1String("OpenPilotGCS"),
@ -155,7 +155,7 @@ MainWindow::MainWindow() :
QCoreApplication::setApplicationVersion(QLatin1String(Core::Constants::GCS_VERSION_LONG));
QCoreApplication::setOrganizationName(QLatin1String("OpenPilot"));
QCoreApplication::setOrganizationDomain(QLatin1String("openpilot.org"));
QSettings::setDefaultFormat(QSettings::IniFormat);
QSettings::setDefaultFormat(XmlConfig::XmlSettingsFormat);
QString baseName = qApp->style()->objectName();
#ifdef Q_WS_X11
if (baseName == QLatin1String("windows")) {
@ -284,7 +284,8 @@ void MainWindow::extensionsInitialized()
{
QSettings* qs = m_settings;
QSettings defaultSettings(":/core/OpenPilotGCS.ini", QSettings::IniFormat);
QSettings defaultSettings(":/core/OpenPilotGCS.xml", XmlConfig::XmlSettingsFormat);
// QSettings defaultSettings(":/core/OpenPilotGCS.ini", QSettings::IniFormat);
if ( ! qs->allKeys().count() ){
QMessageBox msgBox;
@ -293,7 +294,7 @@ void MainWindow::extensionsInitialized()
msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
msgBox.setDefaultButton(QMessageBox::Yes);
if ( msgBox.exec() == QMessageBox::Yes ){
qDebug() << "Load default config from resource /core/OpenPilotGCS.ini";
qDebug() << "Load default config from resource /core/OpenPilotGCS.xml";
qs = &defaultSettings;
}
}

View File

@ -56,7 +56,9 @@ UAVGadgetInstanceManager::UAVGadgetInstanceManager(QObject *parent) :
m_factories.append(f);
QString classId = f->classId();
QString name = f->name();
m_classIds.insert(classId, name);
QIcon icon = f->icon();
m_classIdNameMap.insert(classId, name);
m_classIdIconMap.insert(classId, icon);
}
}
}
@ -108,7 +110,7 @@ void UAVGadgetInstanceManager::readConfigs_1_2_0(QSettings *qs)
{
UAVConfigInfo configInfo;
foreach (QString classId, m_classIds.keys())
foreach (QString classId, m_classIdNameMap.keys())
{
IUAVGadgetFactory *f = factory(classId);
qs->beginGroup(classId);
@ -159,7 +161,7 @@ void UAVGadgetInstanceManager::readConfigs_1_1_0(QSettings *qs)
{
UAVConfigInfo configInfo;
foreach (QString classId, m_classIds.keys())
foreach (QString classId, m_classIdNameMap.keys())
{
IUAVGadgetFactory *f = factory(classId);
qs->beginGroup(classId);
@ -242,7 +244,8 @@ void UAVGadgetInstanceManager::createOptionsPages()
IUAVGadgetFactory *f = factory(config->classId());
IOptionsPage *p = f->createOptionsPage(config);
if (p) {
IOptionsPage *page = new UAVGadgetOptionsPageDecorator(p, config);
IOptionsPage *page = new UAVGadgetOptionsPageDecorator(p, config, f->isSingleConfigurationGadget());
page->setIcon(f->icon());
m_optionsPages.append(page);
m_pm->addObject(page);
}
@ -334,6 +337,7 @@ void UAVGadgetInstanceManager::cloneConfiguration(IUAVGadgetConfiguration *conf
IUAVGadgetFactory *f = factory(config->classId());
IOptionsPage *p = f->createOptionsPage(config);
IOptionsPage *page = new UAVGadgetOptionsPageDecorator(p, config);
page->setIcon(f->icon());
m_provisionalConfigs.append(config);
m_provisionalOptionsPages.append(page);
m_settingsDialog->insertPage(page);
@ -452,7 +456,12 @@ QStringList UAVGadgetInstanceManager::configurationNames(QString classId) const
QString UAVGadgetInstanceManager::gadgetName(QString classId) const
{
return m_classIds.value(classId);
return m_classIdNameMap.value(classId);
}
QIcon UAVGadgetInstanceManager::gadgetIcon(QString classId) const
{
return m_classIdIconMap.value(classId);
}
IUAVGadgetFactory *UAVGadgetInstanceManager::factory(QString classId) const

View File

@ -32,6 +32,7 @@
#include <QSettings>
#include <QtCore/QMap>
#include <QtCore/QStringList>
#include <QtGui/QIcon>
#include "core_global.h"
#include "uavconfiginfo.h"
@ -68,9 +69,10 @@ public:
void cloneConfiguration(IUAVGadgetConfiguration *config);
void applyChanges(IUAVGadgetConfiguration *config);
void configurationNameEdited(QString text, bool hasText = true);
QStringList classIds() const { return m_classIds.keys(); }
QStringList classIds() const { return m_classIdNameMap.keys(); }
QStringList configurationNames(QString classId) const;
QString gadgetName(QString classId) const;
QIcon gadgetIcon(QString classId) const;
signals:
void configurationChanged(IUAVGadgetConfiguration* config);
@ -91,7 +93,8 @@ private:
QList<IUAVGadgetFactory*> m_factories;
QList<IUAVGadgetConfiguration*> m_configurations;
QList<IOptionsPage*> m_optionsPages;
QMap<QString, QString> m_classIds;
QMap<QString, QString> m_classIdNameMap;
QMap<QString, QIcon> m_classIdIconMap;
QMap<QString, QStringList> m_takenNames;
QList<IUAVGadgetConfiguration*> m_provisionalConfigs;
QList<IUAVGadgetConfiguration*> m_provisionalDeletes;

View File

@ -91,6 +91,7 @@ UAVGadgetView::UAVGadgetView(Core::UAVGadgetManager *uavGadgetManager, IUAVGadge
m_defaultIndex = 0;
startFromOne = true;
m_uavGadgetList->insertItem(0, im->gadgetName(classId), classId);
m_uavGadgetList->setItemIcon(0, im->gadgetIcon(classId));
m_uavGadgetList->insertSeparator(1);
} else {
@ -101,6 +102,7 @@ UAVGadgetView::UAVGadgetView(Core::UAVGadgetManager *uavGadgetManager, IUAVGadge
break;
}
m_uavGadgetList->insertItem(i, im->gadgetName(classId), classId);
m_uavGadgetList->setItemIcon(i, im->gadgetIcon(classId));
}
++index;
}

View File

@ -34,10 +34,12 @@
using namespace Core;
UAVGadgetOptionsPageDecorator::UAVGadgetOptionsPageDecorator(IOptionsPage *page, IUAVGadgetConfiguration *config, QObject *parent) :
UAVGadgetOptionsPageDecorator::UAVGadgetOptionsPageDecorator(IOptionsPage *page, IUAVGadgetConfiguration *config,
bool isSingleConfigurationGadget, QObject *parent) :
Core::IOptionsPage(parent),
m_optionsPage(page),
m_config(config),
m_isSingleConfigurationGadget(isSingleConfigurationGadget),
m_id(config->name()),
m_category(config->classId())
{
@ -65,6 +67,11 @@ QWidget *UAVGadgetOptionsPageDecorator::createPage(QWidget *parent)
wi->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);
m_page->verticalLayout_4->addWidget(wi);
// For some gadgets it might not make sense to have multiple configurations
if (m_isSingleConfigurationGadget) {
m_page->configurationBox->hide();
}
connect(m_page->cloneButton, SIGNAL(clicked()), this, SLOT(cloneConfiguration()));
connect(m_page->deleteButton, SIGNAL(clicked()), this, SLOT(deleteConfiguration()));
connect(m_page->nameLineEdit, SIGNAL(textEdited(QString)), this, SLOT(textEdited(QString)));

View File

@ -43,7 +43,7 @@ class CORE_EXPORT UAVGadgetOptionsPageDecorator : public Core::IOptionsPage
{
Q_OBJECT
public:
explicit UAVGadgetOptionsPageDecorator(IOptionsPage *page, IUAVGadgetConfiguration *config, QObject *parent = 0);
explicit UAVGadgetOptionsPageDecorator(IOptionsPage *page, IUAVGadgetConfiguration *config, bool isSingleConfigurationGadget = false, QObject *parent = 0);
QString id() const { return m_id; }
QString trName() const { return m_id; }
@ -66,6 +66,7 @@ private slots:
private:
IOptionsPage *m_optionsPage;
IUAVGadgetConfiguration *m_config;
bool m_isSingleConfigurationGadget;
UAVGadgetInstanceManager *m_instanceManager;
QString m_id;
QString m_category;

View File

@ -34,7 +34,7 @@
DialGadgetFactory::DialGadgetFactory(QObject *parent) :
IUAVGadgetFactory(QString("DialGadget"),
tr("Analog Dial Gadget"),
tr("Analog Dial"),
parent)
{
}

View File

@ -33,7 +33,7 @@
GpsDisplayGadgetFactory::GpsDisplayGadgetFactory(QObject *parent) :
IUAVGadgetFactory(QString("GpsDisplayGadget"),
tr("GPS Display Gadget"),
tr("GPS Display"),
parent)
{
}

View File

@ -6,16 +6,14 @@ include(../../openpilotgcsplugin.pri)
include(importexport_dependencies.pri)
HEADERS += importexportplugin.h \
importexportgadgetwidget.h \
importexportdialog.h \
xmlconfig.h
importexportdialog.h
HEADERS += importexportgadget.h
HEADERS += importexportgadgetfactory.h
HEADERS += importexportgadgetconfiguration.h
HEADERS += importexportgadgetoptionspage.h
SOURCES += importexportplugin.cpp \
importexportgadgetwidget.cpp \
importexportdialog.cpp \
xmlconfig.cpp
importexportdialog.cpp
SOURCES += importexportgadget.cpp
SOURCES += importexportgadgetfactory.cpp
SOURCES += importexportgadgetconfiguration.cpp

View File

@ -28,7 +28,7 @@
*/
#include "importexportgadgetwidget.h"
#include "ui_importexportgadgetwidget.h"
#include "xmlconfig.h"
#include "utils/xmlconfig.h"
#include "coreplugin/uavgadgetinstancemanager.h"
#include "coreplugin/icore.h"
#include <extensionsystem/pluginmanager.h>

View File

@ -33,7 +33,7 @@
LineardialGadgetFactory::LineardialGadgetFactory(QObject *parent) :
IUAVGadgetFactory(QString("LineardialGadget"),
tr("Bargraph Dial Gadget"),
tr("Bargraph Dial"),
parent)
{
}

View File

@ -33,7 +33,7 @@
#include <coreplugin/iuavgadget.h>
ModelViewGadgetFactory::ModelViewGadgetFactory(QObject *parent) :
IUAVGadgetFactory(QString("ModelViewGadget"), tr("ModelView Gadget"), parent)
IUAVGadgetFactory(QString("ModelViewGadget"), tr("ModelView"), parent)
{
}

View File

@ -32,7 +32,7 @@
#include <coreplugin/iuavgadget.h>
OPMapGadgetFactory::OPMapGadgetFactory(QObject *parent) :
IUAVGadgetFactory(QString("OPMapGadget"), tr("OPMap Gadget"), parent)
IUAVGadgetFactory(QString("OPMapGadget"), tr("OPMap"), parent)
{
}

View File

@ -33,7 +33,7 @@
PFDGadgetFactory::PFDGadgetFactory(QObject *parent) :
IUAVGadgetFactory(QString("PFDGadget"),
tr("Primary Flight Display Gadget"),
tr("Primary Flight Display"),
parent)
{
}

View File

@ -31,7 +31,7 @@
#include <coreplugin/iuavgadget.h>
PipXtremeGadgetFactory::PipXtremeGadgetFactory(QObject *parent) :
IUAVGadgetFactory(QString("PipXtreme"), tr("PipXtreme Gadget"), parent)
IUAVGadgetFactory(QString("PipXtreme"), tr("PipXtreme"), parent)
{
}
@ -49,8 +49,3 @@ IUAVGadgetConfiguration * PipXtremeGadgetFactory::createConfiguration(QSettings
{
return new PipXtremeGadgetConfiguration(QString("PipXtreme"), qSettings);
}
IOptionsPage * PipXtremeGadgetFactory::createOptionsPage(IUAVGadgetConfiguration *config)
{
return new PipXtremeGadgetOptionsPage(qobject_cast<PipXtremeGadgetConfiguration *>(config));
}

View File

@ -45,7 +45,6 @@ public:
Core::IUAVGadget * createGadget(QWidget *parent);
IUAVGadgetConfiguration * createConfiguration(QSettings *qSettings);
IOptionsPage * createOptionsPage(IUAVGadgetConfiguration *config);
};
#endif

View File

@ -33,7 +33,7 @@
ScopeGadgetFactory::ScopeGadgetFactory(QObject *parent) :
IUAVGadgetFactory(QString("ScopeGadget"),
tr("Scope Gadget"),
tr("Scope"),
parent)
{
}

View File

@ -33,7 +33,7 @@
SystemHealthGadgetFactory::SystemHealthGadgetFactory(QObject *parent) :
IUAVGadgetFactory(QString("SystemHealthGadget"),
tr("System Health Gadget"),
tr("System Health"),
parent)
{
}

View File

@ -33,7 +33,7 @@
#include <coreplugin/iuavgadget.h>
UploaderGadgetFactory::UploaderGadgetFactory(QObject *parent) :
IUAVGadgetFactory(QString("Uploader"), tr("Uploader Gadget"), parent)
IUAVGadgetFactory(QString("Uploader"), tr("Uploader"), parent)
{
}
@ -52,8 +52,3 @@ IUAVGadgetConfiguration *UploaderGadgetFactory::createConfiguration(QSettings* q
return new UploaderGadgetConfiguration(QString("Uploader"), qSettings);
}
IOptionsPage *UploaderGadgetFactory::createOptionsPage(IUAVGadgetConfiguration *config)
{
return new UploaderGadgetOptionsPage(qobject_cast<UploaderGadgetConfiguration*>(config));
}

View File

@ -46,7 +46,6 @@ public:
Core::IUAVGadget *createGadget(QWidget *parent);
IUAVGadgetConfiguration *createConfiguration(QSettings* qSettings);
IOptionsPage *createOptionsPage(IUAVGadgetConfiguration *config);
};
#endif // UPLOADERGADGETFACTORY_H

View File

@ -33,7 +33,6 @@ UploaderGadgetWidget::UploaderGadgetWidget(QWidget *parent) : QWidget(parent)
m_config = new Ui_UploaderWidget();
m_config->setupUi(this);
currentStep = IAP_STATE_READY;
rescueStep = RESCUE_STEP0;
resetOnly=false;
dfu = NULL;
@ -393,89 +392,93 @@ void UploaderGadgetWidget::systemBoot()
void UploaderGadgetWidget::systemRescue()
{
Core::ConnectionManager *cm = Core::ICore::instance()->connectionManager();
switch (rescueStep) {
case RESCUE_STEP0: {
cm->disconnectDevice();
// stop the polling thread: otherwise it will mess up DFU
cm->suspendPolling();
// Delete all previous tabs:
while (m_config->systemElements->count()) {
QWidget *qw = m_config->systemElements->widget(0);
m_config->systemElements->removeTab(0);
delete qw;
}
// Existing DFU objects will have a handle over USB and will
// disturb everything for the rescue process:
if (dfu) {
delete dfu;
dfu = NULL;
}
// Avoid dumb users pressing Rescue twice. It can happen.
m_config->rescueButton->setEnabled(false);
// Now we're good to go:
clearLog();
log("**********************************************************");
log("** Follow those instructions to attempt a system rescue **");
log("**********************************************************");
log("You will be prompted to first connect USB, then system power");
log ("Connect USB in 2 seconds...");
rescueStep = RESCUE_STEP1;
QTimer::singleShot(1000, this, SLOT(systemRescue()));
cm->disconnectDevice();
// stop the polling thread: otherwise it will mess up DFU
cm->suspendPolling();
// Delete all previous tabs:
while (m_config->systemElements->count()) {
QWidget *qw = m_config->systemElements->widget(0);
m_config->systemElements->removeTab(0);
delete qw;
}
break;
case RESCUE_STEP1:
rescueStep = RESCUE_STEP2;
log (" ...1...");
QTimer::singleShot(1000, this, SLOT(systemRescue()));
break;
case RESCUE_STEP2:
rescueStep = RESCUE_STEP3;
log(" ...Now!");
QTimer::singleShot(1000, this, SLOT(systemRescue()));
break;
case RESCUE_STEP3:
log("... Detecting First Board...");
repaint();
dfu = new DFUObject(DFU_DEBUG, false, QString());
dfu->AbortOperation();
if(!dfu->enterDFU(0))
// Existing DFU objects will have a handle over USB and will
// disturb everything for the rescue process:
if (dfu) {
delete dfu;
dfu = NULL;
}
// Avoid dumb users pressing Rescue twice. It can happen.
m_config->rescueButton->setEnabled(false);
// Now we're good to go:
clearLog();
log("**********************************************************");
log("** Follow those instructions to attempt a system rescue **");
log("**********************************************************");
log("You will be prompted to first connect USB, then system power");
if(USBMonitor::instance()->availableDevices(0x20a0,-1,-1,-1).length()>0)
{
if(QMessageBox::warning(this,tr("OpenPilot Uploader"),tr("Please disconnect all openpilot boards"),QMessageBox::Ok,QMessageBox::Cancel)==QMessageBox::Cancel)
{
rescueStep = RESCUE_STEP0;
log("Could not enter DFU mode.");
delete dfu;
dfu = NULL;
cm->resumePolling();
m_config->rescueButton->setEnabled(true);
return;
}
if(!dfu->findDevices() || (dfu->numberOfDevices != 1))
{
rescueStep = RESCUE_STEP0;
log("Could not detect a board, aborting!");
delete dfu;
dfu = NULL;
cm->resumePolling();
m_config->rescueButton->setEnabled(true);
return;
}
rescueStep = RESCUE_POWER1;
log("Connect Power in 2 second...");
log("(not required on CopterControl)");
QTimer::singleShot(1000, this, SLOT(systemRescue()));
break;
case RESCUE_POWER1:
rescueStep = RESCUE_POWER2;
log(" ...1...");
QTimer::singleShot(1000, this, SLOT(systemRescue()));
break;
case RESCUE_POWER2:
log("... NOW!\n***\nWaiting...");
rescueStep = RESCUE_DETECT;
QTimer::singleShot(5000, this, SLOT(systemRescue()));
break;
case RESCUE_DETECT:
rescueStep = RESCUE_STEP0;
}
// Now we're good to go:
clearLog();
log("**********************************************************");
log("** Follow those instructions to attempt a system rescue **");
log("**********************************************************");
log("You will be prompted to first connect USB, then system power");
pd = new QProgressDialog(tr("Please connect the board (USB only!)"), tr("Cancel"), 0, 20);
QProgressBar * bar=new QProgressBar(pd);
bar->setFormat("Timeout");
pd->setBar(bar);
pd->setMinimumDuration(0);
pd->setRange(0,20);
connect(pd, SIGNAL(canceled()), this, SLOT(cancel()));
t = new QTimer(this);
connect(t, SIGNAL(timeout()), this, SLOT(perform()));
t->start(1000);
connect(USBMonitor::instance(), SIGNAL(deviceDiscovered(USBPortInfo)),&q, SLOT(quit()));
q.exec();
if(!t->isActive())
{
pd->close();
t->stop();
QMessageBox::warning(this,tr("Openpilot Uploader"),tr("No board connection was detected!"));
m_config->rescueButton->setEnabled(true);
return;
}
pd->close();
t->stop();
log("... Detecting First Board...");
repaint();
dfu = new DFUObject(DFU_DEBUG, false, QString());
dfu->AbortOperation();
if(!dfu->enterDFU(0))
{
log("Could not enter DFU mode.");
delete dfu;
dfu = NULL;
cm->resumePolling();
m_config->rescueButton->setEnabled(true);
return;
}
if(!dfu->findDevices() || (dfu->numberOfDevices != 1))
{
log("Could not detect a board, aborting!");
delete dfu;
dfu = NULL;
cm->resumePolling();
m_config->rescueButton->setEnabled(true);
return;
}
if(QMessageBox::question(this,tr("OpenPilot Uploader"),tr("If you want to search for other boards connect power now and press Yes"),QMessageBox::Yes,QMessageBox::No)==QMessageBox::Yes)
{
log("\nWaiting...");
QTimer::singleShot(3000, &q, SLOT(quit()));
q.exec();
log("Detecting second board...");
repaint();
if(!dfu->findDevices())
@ -489,28 +492,42 @@ void UploaderGadgetWidget::systemRescue()
m_config->rescueButton->setEnabled(true);
return;
}
log(QString("Found ") + QString::number(dfu->numberOfDevices) + QString(" device(s)."));
if (dfu->numberOfDevices > 5) {
log("Inconsistent number of devices, aborting!");
delete dfu;
dfu = NULL;
cm->resumePolling();
m_config->rescueButton->setEnabled(true);
return;
}
for(int i=0;i<dfu->numberOfDevices;i++) {
deviceWidget* dw = new deviceWidget(this);
dw->setDeviceID(i);
dw->setDfu(dfu);
dw->populate();
m_config->systemElements->addTab(dw, QString("Device") + QString::number(i));
}
m_config->haltButton->setEnabled(false);
m_config->resetButton->setEnabled(false);
m_config->bootButton->setEnabled(true);
m_config->rescueButton->setEnabled(false);
currentStep = IAP_STATE_BOOTLOADER; // So that we can boot from the GUI afterwards.
}
log(QString("Found ") + QString::number(dfu->numberOfDevices) + QString(" device(s)."));
if (dfu->numberOfDevices > 5) {
log("Inconsistent number of devices, aborting!");
delete dfu;
dfu = NULL;
cm->resumePolling();
m_config->rescueButton->setEnabled(true);
return;
}
for(int i=0;i<dfu->numberOfDevices;i++) {
deviceWidget* dw = new deviceWidget(this);
dw->setDeviceID(i);
dw->setDfu(dfu);
dw->populate();
m_config->systemElements->addTab(dw, QString("Device") + QString::number(i));
}
m_config->haltButton->setEnabled(false);
m_config->resetButton->setEnabled(false);
m_config->bootButton->setEnabled(true);
m_config->rescueButton->setEnabled(false);
currentStep = IAP_STATE_BOOTLOADER; // So that we can boot from the GUI afterwards.
}
void UploaderGadgetWidget::perform()
{
if(pd->value()==19)
{
t->stop();
q.exit();
}
pd->setValue(pd->value()+1);
}
void UploaderGadgetWidget::cancel()
{
t->stop();
q.exit();
}
/**
@ -538,6 +555,11 @@ UploaderGadgetWidget::~UploaderGadgetWidget()
m_config->systemElements->removeTab(0);
delete qw;
}
if (pd)
delete pd;
if (t)
delete t;
}

View File

@ -53,6 +53,7 @@
#include <QMessageBox>
#include <QTimer>
#include <QProgressDialog>
using namespace OP_DFU;
@ -64,7 +65,6 @@ public:
UploaderGadgetWidget(QWidget *parent = 0);
~UploaderGadgetWidget();
typedef enum { IAP_STATE_READY, IAP_STATE_STEP_1, IAP_STATE_STEP_2, IAP_STEP_RESET, IAP_STATE_BOOTLOADER} IAPStep;
typedef enum { RESCUE_STEP0, RESCUE_STEP1, RESCUE_STEP2, RESCUE_STEP3, RESCUE_POWER1, RESCUE_POWER2, RESCUE_DETECT } RescueStep;
void log(QString str);
public slots:
@ -75,13 +75,13 @@ private:
Ui_UploaderWidget *m_config;
DFUObject *dfu;
IAPStep currentStep;
RescueStep rescueStep;
bool resetOnly;
void clearLog();
QString getPortDevice(const QString &friendName);
QProgressDialog* pd;
QTimer* t;
QLineEdit* openFileNameLE;
QEventLoop q;
private slots:
void error(QString errorString,int errorNumber);
void info(QString infoString,int infoNumber);
@ -90,6 +90,8 @@ private slots:
void systemBoot();
void systemRescue();
void getSerialPorts();
void perform();
void cancel();
};