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

Merge remote-tracking branch 'origin/filnet/OP-907_gcs_vehicle_config_overhaul' into next

This commit is contained in:
Fredrik Arvidsson 2013-05-01 13:01:55 +02:00
commit 4e823874fb
28 changed files with 9341 additions and 5947 deletions

View File

@ -17,27 +17,96 @@
<property name="margin"> <property name="margin">
<number>12</number> <number>12</number>
</property> </property>
<item>
<widget class="QGroupBox" name="vehicleTypeGroupBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="title">
<string/>
</property>
<layout class="QHBoxLayout" name="horizontalLayout">
<property name="margin">
<number>9</number>
</property>
<item>
<widget class="QLabel" name="label">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>Vehicle type:</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="aircraftType">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="font">
<font>
<weight>50</weight>
<bold>false</bold>
</font>
</property>
<property name="toolTip">
<string>Select aircraft type here</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Expanding</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>2</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</item>
<item> <item>
<widget class="QTabWidget" name="tabWidget"> <widget class="QTabWidget" name="tabWidget">
<property name="currentIndex"> <property name="currentIndex">
<number>0</number> <number>0</number>
</property> </property>
<widget class="QWidget" name="tabWidgetPage1"> <widget class="QWidget" name="mixerSettingsPage">
<property name="autoFillBackground"> <property name="autoFillBackground">
<bool>true</bool> <bool>true</bool>
</property> </property>
<attribute name="title"> <attribute name="title">
<string>Mixer Settings</string> <string>Mixer Settings</string>
</attribute> </attribute>
<layout class="QGridLayout" name="gridLayout_9"> <layout class="QVBoxLayout" name="verticalLayout_3">
<property name="horizontalSpacing">
<number>0</number>
</property>
<property name="margin"> <property name="margin">
<number>0</number> <number>9</number>
</property> </property>
<item row="0" column="0"> <item>
<widget class="QScrollArea" name="scrollArea"> <widget class="QScrollArea" name="airframesScrollArea">
<property name="sizePolicy"> <property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred"> <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch> <horstretch>0</horstretch>
@ -128,75 +197,14 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>852</width> <width>832</width>
<height>518</height> <height>461</height>
</rect> </rect>
</property> </property>
<layout class="QVBoxLayout" name="verticalLayout"> <layout class="QVBoxLayout" name="verticalLayout">
<property name="margin"> <property name="margin">
<number>12</number> <number>0</number>
</property> </property>
<item>
<widget class="QGroupBox" name="groupBox_8">
<property name="title">
<string/>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<property name="margin">
<number>12</number>
</property>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<property name="sizeConstraint">
<enum>QLayout::SetFixedSize</enum>
</property>
<item>
<widget class="QLabel" name="label">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>Vehicle type:</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="aircraftType">
<property name="toolTip">
<string>Select aircraft type here</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Expanding</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>2</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
</layout>
</widget>
</item>
<item> <item>
<widget class="QStackedWidget" name="airframesWidget"> <widget class="QStackedWidget" name="airframesWidget">
<property name="sizePolicy"> <property name="sizePolicy">
@ -215,2639 +223,8 @@
<enum>QFrame::NoFrame</enum> <enum>QFrame::NoFrame</enum>
</property> </property>
<property name="currentIndex"> <property name="currentIndex">
<number>4</number> <number>-1</number>
</property> </property>
<widget class="QWidget" name="fixedWing">
<property name="enabled">
<bool>true</bool>
</property>
<property name="autoFillBackground">
<bool>false</bool>
</property>
<layout class="QVBoxLayout" name="verticalLayout_3" stretch="0">
<item>
<layout class="QVBoxLayout" name="verticalLayout_6">
<item>
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<widget class="QLabel" name="label_5">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>Airplane type:</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="fixedWingType"/>
</item>
<item>
<spacer name="horizontalSpacer_3">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_23"/>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_4">
<item>
<widget class="QGroupBox" name="groupBox_2">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>230</width>
<height>100</height>
</size>
</property>
<property name="title">
<string>Output Channel Assignments</string>
</property>
<layout class="QFormLayout" name="formLayout_3">
<item row="1" column="0">
<widget class="QLabel" name="fwEngineLabel">
<property name="text">
<string>Engine</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QComboBox" name="fwEngineChannelBox">
<property name="toolTip">
<string>Select output channel for the engine</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="fwAileron1Label">
<property name="minimumSize">
<size>
<width>60</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>Aileron 1</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QComboBox" name="fwAileron1ChannelBox">
<property name="toolTip">
<string>Select output channel for the first aileron (or elevon)</string>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="fwAileron2Label">
<property name="enabled">
<bool>false</bool>
</property>
<property name="minimumSize">
<size>
<width>60</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>Aileron 2</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QComboBox" name="fwAileron2ChannelBox">
<property name="enabled">
<bool>false</bool>
</property>
<property name="toolTip">
<string>Select output channel for the second aileron (or elevon)</string>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QLabel" name="fwElevator1Label">
<property name="minimumSize">
<size>
<width>67</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>Elevator 1</string>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QComboBox" name="fwElevator1ChannelBox">
<property name="toolTip">
<string>Select output channel for the first elevator</string>
</property>
</widget>
</item>
<item row="5" column="0">
<widget class="QLabel" name="fwElevator2Label">
<property name="enabled">
<bool>false</bool>
</property>
<property name="minimumSize">
<size>
<width>67</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>Elevator 2</string>
</property>
</widget>
</item>
<item row="5" column="1">
<widget class="QComboBox" name="fwElevator2ChannelBox">
<property name="enabled">
<bool>false</bool>
</property>
<property name="toolTip">
<string>Select output channel for a secondary elevator</string>
</property>
</widget>
</item>
<item row="6" column="0">
<widget class="QLabel" name="fwRudder1Label">
<property name="text">
<string>Rudder 1</string>
</property>
</widget>
</item>
<item row="6" column="1">
<widget class="QComboBox" name="fwRudder1ChannelBox">
<property name="toolTip">
<string>Select output channel for the first rudder</string>
</property>
</widget>
</item>
<item row="7" column="0">
<widget class="QLabel" name="fwRudder2Label">
<property name="text">
<string>Rudder 2</string>
</property>
</widget>
</item>
<item row="7" column="1">
<widget class="QComboBox" name="fwRudder2ChannelBox">
<property name="toolTip">
<string>Select output channel for a secondary rudder</string>
</property>
</widget>
</item>
<item row="0" column="1">
<spacer name="verticalSpacer_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="elevonMixBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="title">
<string>Elevon Mix</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_13">
<item>
<spacer name="verticalSpacer_3">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>0</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_8">
<item>
<layout class="QVBoxLayout" name="verticalLayout_14">
<item>
<widget class="QLabel" name="elevonLabel1">
<property name="minimumSize">
<size>
<width>65</width>
<height>0</height>
</size>
</property>
<property name="styleSheet">
<string notr="true">background-color: qlineargradient(spread:reflect, x1:0.507, y1:0, x2:0.507, y2:0.772, stop:0.208955 rgba(74, 74, 74, 255), stop:0.78607 rgba(36, 36, 36, 255));
color: rgb(255, 255, 255);
border-radius: 5;
font: bold 12px;
margin:1px;</string>
</property>
<property name="text">
<string>Rudder %</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QSlider" name="elevonSlider1">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximum">
<number>100</number>
</property>
<property name="value">
<number>50</number>
</property>
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="elevonSliderLabel1">
<property name="text">
<string>50</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QVBoxLayout" name="verticalLayout_15">
<item>
<widget class="QLabel" name="elevonLabel2">
<property name="minimumSize">
<size>
<width>50</width>
<height>0</height>
</size>
</property>
<property name="styleSheet">
<string notr="true">background-color: qlineargradient(spread:reflect, x1:0.507, y1:0, x2:0.507, y2:0.772, stop:0.208955 rgba(74, 74, 74, 255), stop:0.78607 rgba(36, 36, 36, 255));
color: rgb(255, 255, 255);
border-radius: 5;
font: bold 12px;
margin:1px;</string>
</property>
<property name="text">
<string>Pitch %</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QSlider" name="elevonSlider2">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximum">
<number>100</number>
</property>
<property name="value">
<number>50</number>
</property>
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="elevonSliderLabel2">
<property name="text">
<string>50</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</item>
</layout>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_4">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QGroupBox" name="groupBox_3">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>100</verstretch>
</sizepolicy>
</property>
<property name="title">
<string>Throttle Curve</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_16">
<item>
<widget class="MixerCurve" name="fixedWingThrottle" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>1</horstretch>
<verstretch>1</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>500</width>
<height>500</height>
</size>
</property>
<property name="sizeIncrement">
<size>
<width>10</width>
<height>10</height>
</size>
</property>
<property name="baseSize">
<size>
<width>300</width>
<height>350</height>
</size>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_13">
<item>
<spacer name="horizontalSpacer_11">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="fwStatusLabel">
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>Mixer OK</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</item>
</layout>
</widget>
<widget class="QWidget" name="multiRotor">
<layout class="QGridLayout" name="gridLayout_7" columnstretch="0,0,0">
<property name="margin">
<number>0</number>
</property>
<property name="verticalSpacing">
<number>6</number>
</property>
<item row="0" column="0">
<widget class="QGroupBox" name="groupBox_10">
<property name="minimumSize">
<size>
<width>10</width>
<height>10</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>16777215</height>
</size>
</property>
<property name="title">
<string>Frame Type</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_8" stretch="0,0,1,0">
<property name="margin">
<number>12</number>
</property>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_7">
<property name="sizeConstraint">
<enum>QLayout::SetFixedSize</enum>
</property>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>10</width>
<height>13</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QComboBox" name="multirotorFrameType">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Minimum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>25</width>
<height>25</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>25</height>
</size>
</property>
<property name="toolTip">
<string>Select the Multirotor frame type here.</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_5">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>10</width>
<height>13</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<spacer name="verticalSpacer_6">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>8</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QGraphicsView" name="quadShape">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Minimum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>10</width>
<height>10</height>
</size>
</property>
<property name="styleSheet">
<string notr="true">background:transparent</string>
</property>
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Plain</enum>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer_7">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>8</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</item>
<item row="0" column="2">
<widget class="QGroupBox" name="groupBox_6">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>10</width>
<height>10</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>16777215</height>
</size>
</property>
<property name="title">
<string>Throttle Curve</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_9">
<property name="margin">
<number>12</number>
</property>
<item>
<widget class="MixerCurve" name="multiThrottleCurve" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>10</width>
<height>10</height>
</size>
</property>
<property name="sizeIncrement">
<size>
<width>10</width>
<height>10</height>
</size>
</property>
<property name="baseSize">
<size>
<width>50</width>
<height>50</height>
</size>
</property>
<property name="styleSheet">
<string notr="true">background:transparent</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="0" column="1">
<widget class="QGroupBox" name="groupBox_9">
<property name="maximumSize">
<size>
<width>16777215</width>
<height>16777215</height>
</size>
</property>
<property name="title">
<string>Mix Level</string>
</property>
<layout class="QGridLayout" name="gridLayout_2">
<property name="horizontalSpacing">
<number>0</number>
</property>
<property name="margin">
<number>12</number>
</property>
<item row="0" column="0">
<layout class="QGridLayout" name="gridLayout_3" columnstretch="0">
<item row="0" column="0">
<widget class="QLabel" name="mrRollMixValue">
<property name="minimumSize">
<size>
<width>30</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>100</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QSlider" name="mrRollMixLevel">
<property name="minimumSize">
<size>
<width>35</width>
<height>0</height>
</size>
</property>
<property name="toolTip">
<string>Weight of Roll mixing in percent.
Typical values are 100% for + configuration and 50% for X configuration on quads.</string>
</property>
<property name="maximum">
<number>100</number>
</property>
<property name="value">
<number>100</number>
</property>
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_42">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>30</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>30</width>
<height>16777215</height>
</size>
</property>
<property name="styleSheet">
<string notr="true">background-color: qlineargradient(spread:reflect, x1:0.507, y1:0, x2:0.507, y2:0.772, stop:0.208955 rgba(74, 74, 74, 255), stop:0.78607 rgba(36, 36, 36, 255));
color: rgb(255, 255, 255);
border-radius: 5;
font: bold 12px;
margin:1px;</string>
</property>
<property name="text">
<string>Roll</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
</layout>
</item>
<item row="0" column="1">
<layout class="QGridLayout" name="gridLayout_4">
<item row="0" column="0">
<widget class="QLabel" name="mrPitchMixValue">
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>100</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QSlider" name="mrPitchMixLevel">
<property name="minimumSize">
<size>
<width>35</width>
<height>0</height>
</size>
</property>
<property name="toolTip">
<string>Weight of Pitch mixing in percent.
Typical values are 100% for + configuration and 50% for X configuration on quads.</string>
</property>
<property name="maximum">
<number>100</number>
</property>
<property name="value">
<number>100</number>
</property>
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_40">
<property name="styleSheet">
<string notr="true">background-color: qlineargradient(spread:reflect, x1:0.507, y1:0, x2:0.507, y2:0.772, stop:0.208955 rgba(74, 74, 74, 255), stop:0.78607 rgba(36, 36, 36, 255));
color: rgb(255, 255, 255);
border-radius: 5;
font: bold 12px;
margin:1px;</string>
</property>
<property name="text">
<string>Pitch</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
</layout>
</item>
<item row="0" column="2">
<layout class="QGridLayout" name="gridLayout_5">
<item row="0" column="0">
<widget class="QLabel" name="mrYawMixValue">
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>50</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QSlider" name="mrYawMixLevel">
<property name="minimumSize">
<size>
<width>40</width>
<height>0</height>
</size>
</property>
<property name="toolTip">
<string>Weight of Yaw mixing in percent.
Typical value is 50% for + or X configuration on quads.</string>
</property>
<property name="minimum">
<number>0</number>
</property>
<property name="maximum">
<number>100</number>
</property>
<property name="value">
<number>50</number>
</property>
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_6">
<property name="autoFillBackground">
<bool>false</bool>
</property>
<property name="styleSheet">
<string notr="true">background-color: qlineargradient(spread:reflect, x1:0.507, y1:0, x2:0.507, y2:0.772, stop:0.208955 rgba(74, 74, 74, 255), stop:0.78607 rgba(36, 36, 36, 255));
color: rgb(255, 255, 255);
border-radius: 5;
font: bold 12px;
margin:1px;</string>
</property>
<property name="text">
<string>Yaw</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
</layout>
</item>
<item row="1" column="0" colspan="3">
<layout class="QHBoxLayout" name="horizontalLayout_6">
<item>
<spacer name="horizontalSpacer_6">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>10</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="mrStatusLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>Mixer OK</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_9">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>10</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
</layout>
</widget>
</item>
<item row="1" column="0" colspan="3">
<widget class="QGroupBox" name="groupBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>140</height>
</size>
</property>
<property name="title">
<string>Motor output channels</string>
</property>
<layout class="QGridLayout" name="gridLayout_6" columnstretch="1,1,0,0,1">
<property name="margin">
<number>12</number>
</property>
<item row="0" column="0" rowspan="5">
<layout class="QFormLayout" name="formLayout_2">
<property name="sizeConstraint">
<enum>QLayout::SetMaximumSize</enum>
</property>
<property name="fieldGrowthPolicy">
<enum>QFormLayout::AllNonFixedFieldsGrow</enum>
</property>
<property name="verticalSpacing">
<number>6</number>
</property>
<item row="0" column="0">
<widget class="QLabel" name="MotorOutputLabel1">
<property name="styleSheet">
<string notr="true">background-color: qlineargradient(spread:reflect, x1:0.507, y1:0, x2:0.507, y2:0.772, stop:0.208955 rgba(74, 74, 74, 255), stop:0.78607 rgba(36, 36, 36, 255));
color: rgb(255, 255, 255);
border-radius: 5;
font: bold 12px;
margin:1px;</string>
</property>
<property name="text">
<string>1</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QComboBox" name="multiMotorChannelBox1">
<property name="toolTip">
<string>Assign your motor output channels using the drawing above as a reference. Respect propeller rotation.</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_8">
<property name="styleSheet">
<string notr="true">background-color: qlineargradient(spread:reflect, x1:0.507, y1:0, x2:0.507, y2:0.772, stop:0.208955 rgba(74, 74, 74, 255), stop:0.78607 rgba(36, 36, 36, 255));
color: rgb(255, 255, 255);
border-radius: 5;
font: bold 12px;
margin:1px;</string>
</property>
<property name="text">
<string>2</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QComboBox" name="multiMotorChannelBox2">
<property name="toolTip">
<string>Assign your motor output channels using the drawing above as a reference. Respect propeller rotation.</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_9">
<property name="styleSheet">
<string notr="true">background-color: qlineargradient(spread:reflect, x1:0.507, y1:0, x2:0.507, y2:0.772, stop:0.208955 rgba(74, 74, 74, 255), stop:0.78607 rgba(36, 36, 36, 255));
color: rgb(255, 255, 255);
border-radius: 5;
font: bold 12px;
margin:1px;</string>
</property>
<property name="text">
<string>3</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QComboBox" name="multiMotorChannelBox3">
<property name="toolTip">
<string>Assign your motor output channels using the drawing above as a reference. Respect propeller rotation.</string>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_10">
<property name="styleSheet">
<string notr="true">background-color: qlineargradient(spread:reflect, x1:0.507, y1:0, x2:0.507, y2:0.772, stop:0.208955 rgba(74, 74, 74, 255), stop:0.78607 rgba(36, 36, 36, 255));
color: rgb(255, 255, 255);
border-radius: 5;
font: bold 12px;
margin:1px;</string>
</property>
<property name="text">
<string>4</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QComboBox" name="multiMotorChannelBox4">
<property name="toolTip">
<string>Assign your motor output channels using the drawing above as a reference. Respect propeller rotation.</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="0" column="1" rowspan="5">
<layout class="QFormLayout" name="formLayout_4">
<property name="sizeConstraint">
<enum>QLayout::SetMaximumSize</enum>
</property>
<property name="fieldGrowthPolicy">
<enum>QFormLayout::AllNonFixedFieldsGrow</enum>
</property>
<property name="verticalSpacing">
<number>6</number>
</property>
<item row="0" column="0">
<widget class="QLabel" name="label_11">
<property name="styleSheet">
<string notr="true">background-color: qlineargradient(spread:reflect, x1:0.507, y1:0, x2:0.507, y2:0.772, stop:0.208955 rgba(74, 74, 74, 255), stop:0.78607 rgba(36, 36, 36, 255));
color: rgb(255, 255, 255);
border-radius: 5;
font: bold 12px;
margin:1px;</string>
</property>
<property name="text">
<string>5</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QComboBox" name="multiMotorChannelBox5">
<property name="enabled">
<bool>false</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="toolTip">
<string>Assign your motor output channels using the drawing above as a reference. Respect propeller rotation.</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_12">
<property name="styleSheet">
<string notr="true">background-color: qlineargradient(spread:reflect, x1:0.507, y1:0, x2:0.507, y2:0.772, stop:0.208955 rgba(74, 74, 74, 255), stop:0.78607 rgba(36, 36, 36, 255));
color: rgb(255, 255, 255);
border-radius: 5;
font: bold 12px;
margin:1px;</string>
</property>
<property name="text">
<string>6</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QComboBox" name="multiMotorChannelBox6">
<property name="enabled">
<bool>false</bool>
</property>
<property name="toolTip">
<string>Assign your motor output channels using the drawing above as a reference. Respect propeller rotation.</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_16">
<property name="styleSheet">
<string notr="true">background-color: qlineargradient(spread:reflect, x1:0.507, y1:0, x2:0.507, y2:0.772, stop:0.208955 rgba(74, 74, 74, 255), stop:0.78607 rgba(36, 36, 36, 255));
color: rgb(255, 255, 255);
border-radius: 5;
font: bold 12px;
margin:1px;</string>
</property>
<property name="text">
<string>7</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QComboBox" name="multiMotorChannelBox7">
<property name="enabled">
<bool>false</bool>
</property>
<property name="toolTip">
<string>Assign your motor output channels using the drawing above as a reference. Respect propeller rotation.</string>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_17">
<property name="styleSheet">
<string notr="true">background-color: qlineargradient(spread:reflect, x1:0.507, y1:0, x2:0.507, y2:0.772, stop:0.208955 rgba(74, 74, 74, 255), stop:0.78607 rgba(36, 36, 36, 255));
color: rgb(255, 255, 255);
border-radius: 5;
font: bold 12px;
margin:1px;</string>
</property>
<property name="text">
<string>8</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QComboBox" name="multiMotorChannelBox8">
<property name="enabled">
<bool>false</bool>
</property>
<property name="toolTip">
<string>Assign your motor output channels using the drawing above as a reference. Respect propeller rotation.</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="0" column="2" rowspan="5" colspan="2">
<widget class="Line" name="line">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
</widget>
</item>
<item row="2" column="4">
<widget class="QLabel" name="label_3">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>16</height>
</size>
</property>
<property name="styleSheet">
<string notr="true">background-color: qlineargradient(spread:reflect, x1:0.507, y1:0, x2:0.507, y2:0.772, stop:0.208955 rgba(74, 74, 74, 255), stop:0.78607 rgba(36, 36, 36, 255));
color: rgb(255, 255, 255);
border-radius: 5;
font: bold 12px;
margin:1px;</string>
</property>
<property name="text">
<string>Multirotor Motor Direction</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item row="1" column="4">
<widget class="QComboBox" name="triYawChannelBox">
<property name="enabled">
<bool>false</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>40</width>
<height>0</height>
</size>
</property>
</widget>
</item>
<item row="0" column="4">
<widget class="QLabel" name="label_2">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>16</height>
</size>
</property>
<property name="styleSheet">
<string notr="true">background-color: qlineargradient(spread:reflect, x1:0.507, y1:0, x2:0.507, y2:0.772, stop:0.208955 rgba(74, 74, 74, 255), stop:0.78607 rgba(36, 36, 36, 255));
color: rgb(255, 255, 255);
border-radius: 5;
font: bold 12px;
margin:1px;</string>
</property>
<property name="text">
<string>Tricopter Yaw Servo channel</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item row="3" column="4">
<widget class="QCheckBox" name="MultirotorRevMixercheckBox">
<property name="text">
<string>Reverse all motors</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="ccpmHeli">
<layout class="QVBoxLayout" name="verticalLayout_5" stretch="1">
<property name="spacing">
<number>0</number>
</property>
<property name="margin">
<number>0</number>
</property>
<item>
<layout class="QVBoxLayout" name="verticalLayout_19">
<property name="spacing">
<number>0</number>
</property>
<item>
<widget class="ConfigCcpmWidget" name="widget_3" native="true"/>
</item>
</layout>
</item>
</layout>
</widget>
<widget class="QWidget" name="groundVehicle">
<property name="enabled">
<bool>true</bool>
</property>
<property name="autoFillBackground">
<bool>false</bool>
</property>
<layout class="QVBoxLayout" name="verticalLayout_4">
<item>
<widget class="QScrollArea" name="scrollArea_3">
<property name="widgetResizable">
<bool>true</bool>
</property>
<widget class="QWidget" name="scrollAreaWidgetContents_3">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>808</width>
<height>397</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout_11">
<item>
<layout class="QVBoxLayout" name="verticalLayout_61">
<item>
<layout class="QHBoxLayout" name="horizontalLayout_31">
<item>
<widget class="QLabel" name="label_51">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>Vehicle type:</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="groundVehicleType"/>
</item>
<item>
<spacer name="horizontalSpacer_31">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_33">
<item>
<widget class="QLabel" name="label_7">
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>Channel Assignment</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_15">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_41">
<item>
<widget class="QGroupBox" name="groupBox_7">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>100</height>
</size>
</property>
<property name="title">
<string>Output channel asignmets</string>
</property>
<layout class="QFormLayout" name="formLayout_5">
<item row="0" column="0">
<widget class="QLabel" name="gvEngineLabel">
<property name="minimumSize">
<size>
<width>77</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>Engine</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QComboBox" name="gvEngineChannelBox">
<property name="toolTip">
<string>Select output channel for the engine</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="gvAileron1Label">
<property name="minimumSize">
<size>
<width>60</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>Aileron 1</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QComboBox" name="gvAileron1ChannelBox">
<property name="toolTip">
<string>Select output channel for the first aileron (or elevon)</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="gvAileron2Label">
<property name="enabled">
<bool>false</bool>
</property>
<property name="minimumSize">
<size>
<width>60</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>Aileron 2</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QComboBox" name="gvAileron2ChannelBox">
<property name="enabled">
<bool>false</bool>
</property>
<property name="toolTip">
<string>Select output channel for the second aileron (or elevon)</string>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="gvMotor1Label">
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>Motor</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QComboBox" name="gvMotor1ChannelBox">
<property name="toolTip">
<string>Select output channel for the first motor</string>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QLabel" name="gvMotor2Label">
<property name="enabled">
<bool>false</bool>
</property>
<property name="minimumSize">
<size>
<width>47</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>Motor 2</string>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QComboBox" name="gvMotor2ChannelBox">
<property name="enabled">
<bool>false</bool>
</property>
<property name="toolTip">
<string>Select output channel for a second motor</string>
</property>
</widget>
</item>
<item row="5" column="0">
<widget class="QLabel" name="gvSteering1Label">
<property name="text">
<string>Front Steering</string>
</property>
</widget>
</item>
<item row="5" column="1">
<widget class="QComboBox" name="gvSteering1ChannelBox">
<property name="toolTip">
<string>Select output channel for the first steering actuator</string>
</property>
</widget>
</item>
<item row="6" column="0">
<widget class="QLabel" name="gvSteering2Label">
<property name="text">
<string>Rear Steering</string>
</property>
</widget>
</item>
<item row="6" column="1">
<widget class="QComboBox" name="gvSteering2ChannelBox">
<property name="toolTip">
<string>Select output channel for a second steering actuator</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="differentialSteeringMixBox">
<property name="enabled">
<bool>true</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="title">
<string>Differential Steering Mix</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_33">
<item>
<layout class="QHBoxLayout" name="horizontalLayout_30">
<item>
<layout class="QVBoxLayout" name="verticalLayout_34">
<item>
<widget class="QLabel" name="differentialSteeringLabel1">
<property name="minimumSize">
<size>
<width>65</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>Left %</string>
</property>
</widget>
</item>
<item>
<widget class="QSlider" name="differentialSteeringSlider1">
<property name="maximum">
<number>100</number>
</property>
<property name="value">
<number>50</number>
</property>
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="gvDiffSteering1Label">
<property name="text">
<string>50</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QVBoxLayout" name="verticalLayout_35">
<item>
<widget class="QLabel" name="differentialSteeringLabel2">
<property name="minimumSize">
<size>
<width>50</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>Right %</string>
</property>
</widget>
</item>
<item>
<widget class="QSlider" name="differentialSteeringSlider2">
<property name="maximum">
<number>100</number>
</property>
<property name="value">
<number>50</number>
</property>
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="gvDiffSteering2Label">
<property name="text">
<string>50</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="gvThrottleCurve1GroupBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>100</verstretch>
</sizepolicy>
</property>
<property name="title">
<string>Front throttle curve</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_36">
<item>
<widget class="MixerCurve" name="groundVehicleThrottle1" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>500</width>
<height>500</height>
</size>
</property>
<property name="sizeIncrement">
<size>
<width>10</width>
<height>10</height>
</size>
</property>
<property name="baseSize">
<size>
<width>300</width>
<height>350</height>
</size>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="gvThrottleCurve2GroupBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="title">
<string>Rear throttle curve</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_37">
<item>
<widget class="MixerCurve" name="groundVehicleThrottle2" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>500</width>
<height>500</height>
</size>
</property>
<property name="sizeIncrement">
<size>
<width>10</width>
<height>10</height>
</size>
</property>
<property name="baseSize">
<size>
<width>300</width>
<height>350</height>
</size>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</item>
<item>
<spacer name="verticalSpacer_1">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_28">
<item>
<spacer name="horizontalSpacer_21">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="gvStatusLabel">
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>Mixer OK</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</item>
</layout>
</widget>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="custom">
<layout class="QHBoxLayout" name="horizontalLayout_15">
<item>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<layout class="QHBoxLayout" name="horizontalLayout_14">
<item>
<widget class="QGroupBox" name="groupBox_4">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="title">
<string>Curve 1</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_7">
<item>
<widget class="MixerCurve" name="customThrottle1Curve" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
<horstretch>1</horstretch>
<verstretch>1</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>50</width>
<height>50</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>1000</width>
<height>1000</height>
</size>
</property>
<property name="sizeIncrement">
<size>
<width>10</width>
<height>10</height>
</size>
</property>
<property name="baseSize">
<size>
<width>300</width>
<height>350</height>
</size>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBox_5">
<property name="title">
<string>Curve 2</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_17">
<item>
<widget class="MixerCurve" name="customThrottle2Curve" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
<horstretch>1</horstretch>
<verstretch>1</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>50</width>
<height>50</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>1000</width>
<height>1000</height>
</size>
</property>
<property name="sizeIncrement">
<size>
<width>10</width>
<height>10</height>
</size>
</property>
<property name="baseSize">
<size>
<width>300</width>
<height>350</height>
</size>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</item>
<item row="1" column="0">
<widget class="QTableWidget" name="customMixerTable">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="alternatingRowColors">
<bool>true</bool>
</property>
<property name="columnCount">
<number>12</number>
</property>
<attribute name="horizontalHeaderDefaultSectionSize">
<number>50</number>
</attribute>
<attribute name="horizontalHeaderStretchLastSection">
<bool>false</bool>
</attribute>
<row>
<property name="text">
<string>Type</string>
</property>
</row>
<row>
<property name="text">
<string>Curve 1</string>
</property>
</row>
<row>
<property name="text">
<string>Curve 2</string>
</property>
</row>
<row>
<property name="text">
<string>Roll</string>
</property>
</row>
<row>
<property name="text">
<string>Pitch</string>
</property>
</row>
<row>
<property name="text">
<string>Yaw</string>
</property>
</row>
<column>
<property name="text">
<string>Ch 1</string>
</property>
</column>
<column>
<property name="text">
<string>Ch 2</string>
</property>
</column>
<column>
<property name="text">
<string>Ch 3</string>
</property>
</column>
<column>
<property name="text">
<string>Ch 4</string>
</property>
</column>
<column>
<property name="text">
<string>Ch 5</string>
</property>
</column>
<column>
<property name="text">
<string>Ch 6</string>
</property>
</column>
<column>
<property name="text">
<string>Ch 7</string>
</property>
</column>
<column>
<property name="text">
<string>Ch 8</string>
</property>
</column>
<column>
<property name="text">
<string>Ch 9</string>
</property>
</column>
<column>
<property name="text">
<string>Ch 10</string>
</property>
</column>
<column>
<property name="text">
<string>Ch 11</string>
</property>
</column>
<column>
<property name="text">
<string>Ch 12</string>
</property>
</column>
<item row="0" column="0">
<property name="text">
<string>-</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</item>
<item row="0" column="1">
<property name="text">
<string>-</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</item>
<item row="0" column="2">
<property name="text">
<string>-</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</item>
<item row="0" column="3">
<property name="text">
<string>-</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</item>
<item row="0" column="4">
<property name="text">
<string>-</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</item>
<item row="0" column="5">
<property name="text">
<string>-</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</item>
<item row="0" column="6">
<property name="text">
<string>-</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</item>
<item row="0" column="7">
<property name="text">
<string>-</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</item>
<item row="0" column="8">
<property name="text">
<string>-</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</item>
<item row="0" column="9">
<property name="text">
<string>-</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</item>
<item row="0" column="10">
<property name="text">
<string>-</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</item>
<item row="0" column="11">
<property name="text">
<string>-</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</item>
<item row="1" column="0">
<property name="text">
<string>-</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</item>
<item row="1" column="1">
<property name="text">
<string>-</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</item>
<item row="1" column="2">
<property name="text">
<string>-</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</item>
<item row="1" column="3">
<property name="text">
<string>-</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</item>
<item row="1" column="4">
<property name="text">
<string>-</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</item>
<item row="1" column="5">
<property name="text">
<string>-</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</item>
<item row="1" column="6">
<property name="text">
<string>-</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</item>
<item row="1" column="7">
<property name="text">
<string>-</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</item>
<item row="1" column="8">
<property name="text">
<string>-</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</item>
<item row="1" column="9">
<property name="text">
<string>-</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</item>
<item row="1" column="10">
<property name="text">
<string>-</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</item>
<item row="1" column="11">
<property name="text">
<string>-</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</item>
<item row="2" column="0">
<property name="text">
<string>-</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</item>
<item row="2" column="1">
<property name="text">
<string>-</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</item>
<item row="2" column="2">
<property name="text">
<string>-</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</item>
<item row="2" column="3">
<property name="text">
<string>-</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</item>
<item row="2" column="4">
<property name="text">
<string>-</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</item>
<item row="2" column="5">
<property name="text">
<string>-</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</item>
<item row="2" column="6">
<property name="text">
<string>-</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</item>
<item row="2" column="7">
<property name="text">
<string>-</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</item>
<item row="2" column="8">
<property name="text">
<string>-</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</item>
<item row="2" column="9">
<property name="text">
<string>-</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</item>
<item row="2" column="10">
<property name="text">
<string>-</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</item>
<item row="2" column="11">
<property name="text">
<string>-</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</item>
<item row="3" column="0">
<property name="text">
<string>-</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</item>
<item row="3" column="1">
<property name="text">
<string>-</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</item>
<item row="3" column="2">
<property name="text">
<string>-</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</item>
<item row="3" column="3">
<property name="text">
<string>-</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</item>
<item row="3" column="4">
<property name="text">
<string>-</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</item>
<item row="3" column="5">
<property name="text">
<string>-</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</item>
<item row="3" column="6">
<property name="text">
<string>-</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</item>
<item row="3" column="7">
<property name="text">
<string>-</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</item>
<item row="3" column="8">
<property name="text">
<string>-</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</item>
<item row="3" column="9">
<property name="text">
<string>-</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</item>
<item row="3" column="10">
<property name="text">
<string>-</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</item>
<item row="3" column="11">
<property name="text">
<string>-</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</item>
<item row="4" column="0">
<property name="text">
<string>-</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</item>
<item row="4" column="1">
<property name="text">
<string>-</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</item>
<item row="4" column="2">
<property name="text">
<string>-</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</item>
<item row="4" column="3">
<property name="text">
<string>-</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</item>
<item row="4" column="4">
<property name="text">
<string>-</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</item>
<item row="4" column="5">
<property name="text">
<string>-</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</item>
<item row="4" column="6">
<property name="text">
<string>-</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</item>
<item row="4" column="7">
<property name="text">
<string>-</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</item>
<item row="4" column="8">
<property name="text">
<string>-</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</item>
<item row="4" column="9">
<property name="text">
<string>-</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</item>
<item row="4" column="10">
<property name="text">
<string>-</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</item>
<item row="4" column="11">
<property name="text">
<string>-</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</item>
<item row="5" column="0">
<property name="text">
<string>-</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</item>
<item row="5" column="1">
<property name="text">
<string>-</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</item>
<item row="5" column="2">
<property name="text">
<string>-</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</item>
<item row="5" column="3">
<property name="text">
<string>-</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</item>
<item row="5" column="4">
<property name="text">
<string>-</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</item>
<item row="5" column="5">
<property name="text">
<string>-</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</item>
<item row="5" column="6">
<property name="text">
<string>-</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</item>
<item row="5" column="7">
<property name="text">
<string>-</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</item>
<item row="5" column="8">
<property name="text">
<string>-</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</item>
<item row="5" column="9">
<property name="text">
<string>-</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</item>
<item row="5" column="10">
<property name="text">
<string>-</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</item>
<item row="5" column="11">
<property name="text">
<string>-</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</item>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</widget> </widget>
</item> </item>
</layout> </layout>
@ -2856,7 +233,7 @@ margin:1px;</string>
</item> </item>
</layout> </layout>
</widget> </widget>
<widget class="QWidget" name="tab"> <widget class="QWidget" name="feedForwardPage">
<property name="autoFillBackground"> <property name="autoFillBackground">
<bool>true</bool> <bool>true</bool>
</property> </property>
@ -2950,8 +327,8 @@ margin:1px;</string>
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>852</width> <width>223</width>
<height>518</height> <height>269</height>
</rect> </rect>
</property> </property>
<layout class="QVBoxLayout" name="verticalLayout_18"> <layout class="QVBoxLayout" name="verticalLayout_18">
@ -3334,13 +711,14 @@ p, li { white-space: pre-wrap; }
<string>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt; <string>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt; &lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
p, li { white-space: pre-wrap; } p, li { white-space: pre-wrap; }
&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'Ubuntu'; font-size:9pt; font-weight:400; font-style:normal;&quot;&gt; &lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;&quot;&gt;
&lt;table border=&quot;0&quot; style=&quot;-qt-table-type: root; margin-top:4px; margin-bottom:4px; margin-left:4px; margin-right:4px;&quot;&gt; &lt;table border=&quot;0&quot; style=&quot;-qt-table-type: root; margin-top:4px; margin-bottom:4px; margin-left:4px; margin-right:4px;&quot;&gt;
&lt;tr&gt; &lt;tr&gt;
&lt;td style=&quot;border: none;&quot;&gt; &lt;td style=&quot;border: none;&quot;&gt;
&lt;p align=&quot;center&quot; style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:14pt; font-weight:600; color:#ff0000;&quot;&gt;SETTING UP FEED FORWARD REQUIRES CAUTION&lt;/span&gt;&lt;/p&gt; &lt;p align=&quot;center&quot; style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-family:'Ubuntu'; font-size:14pt; font-weight:600; color:#ff0000;&quot;&gt;SETTING UP FEED FORWARD REQUIRES CAUTION&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:11pt;&quot;&gt;&lt;br /&gt;&lt;/p&gt; &lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Ubuntu'; font-size:11pt;&quot;&gt;&lt;/p&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:11pt;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt; &lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-family:'Ubuntu'; font-size:11pt;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-family:'Ubuntu'; font-size:11pt;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-family:'Lucida Grande'; font-size:13pt;&quot;&gt;Beware: Feed Forward Tuning will launch all engines around mid-throttle, you have been warned!&lt;/span&gt;&lt;/p&gt; &lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-family:'Lucida Grande'; font-size:13pt;&quot;&gt;Beware: Feed Forward Tuning will launch all engines around mid-throttle, you have been warned!&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot; margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-family:'Lucida Grande'; font-size:13pt;&quot;&gt;Remove your props initially, and for fine-tuning, make sure your airframe is safely held in place. Wear glasses and protect your face and body.&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/body&gt;&lt;/html&gt;</string> &lt;p style=&quot; margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-family:'Lucida Grande'; font-size:13pt;&quot;&gt;Remove your props initially, and for fine-tuning, make sure your airframe is safely held in place. Wear glasses and protect your face and body.&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property> </property>
@ -3355,7 +733,7 @@ p, li { white-space: pre-wrap; }
</widget> </widget>
</item> </item>
<item> <item>
<layout class="QHBoxLayout" name="horizontalLayout_2"> <layout class="QHBoxLayout" name="bottomLayout">
<property name="spacing"> <property name="spacing">
<number>4</number> <number>4</number>
</property> </property>
@ -3431,20 +809,6 @@ p, li { white-space: pre-wrap; }
</item> </item>
</layout> </layout>
</widget> </widget>
<customwidgets>
<customwidget>
<class>MixerCurve</class>
<extends>QWidget</extends>
<header location="global">mixercurve.h</header>
<container>1</container>
</customwidget>
<customwidget>
<class>ConfigCcpmWidget</class>
<extends>QWidget</extends>
<header>cfg_vehicletypes/configccpmwidget.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<resources> <resources>
<include location="../coreplugin/core.qrc"/> <include location="../coreplugin/core.qrc"/>
</resources> </resources>
@ -3481,117 +845,5 @@ p, li { white-space: pre-wrap; }
</hint> </hint>
</hints> </hints>
</connection> </connection>
<connection>
<sender>elevonSlider1</sender>
<signal>valueChanged(int)</signal>
<receiver>elevonSliderLabel1</receiver>
<slot>setNum(int)</slot>
<hints>
<hint type="sourcelabel">
<x>124</x>
<y>126</y>
</hint>
<hint type="destinationlabel">
<x>124</x>
<y>126</y>
</hint>
</hints>
</connection>
<connection>
<sender>elevonSlider2</sender>
<signal>valueChanged(int)</signal>
<receiver>elevonSliderLabel2</receiver>
<slot>setNum(int)</slot>
<hints>
<hint type="sourcelabel">
<x>362</x>
<y>299</y>
</hint>
<hint type="destinationlabel">
<x>124</x>
<y>126</y>
</hint>
</hints>
</connection>
<connection>
<sender>differentialSteeringSlider1</sender>
<signal>valueChanged(int)</signal>
<receiver>gvDiffSteering1Label</receiver>
<slot>setNum(int)</slot>
<hints>
<hint type="sourcelabel">
<x>124</x>
<y>126</y>
</hint>
<hint type="destinationlabel">
<x>315</x>
<y>391</y>
</hint>
</hints>
</connection>
<connection>
<sender>differentialSteeringSlider2</sender>
<signal>valueChanged(int)</signal>
<receiver>gvDiffSteering2Label</receiver>
<slot>setNum(int)</slot>
<hints>
<hint type="sourcelabel">
<x>124</x>
<y>126</y>
</hint>
<hint type="destinationlabel">
<x>390</x>
<y>391</y>
</hint>
</hints>
</connection>
<connection>
<sender>mrRollMixLevel</sender>
<signal>valueChanged(int)</signal>
<receiver>mrRollMixValue</receiver>
<slot>setNum(int)</slot>
<hints>
<hint type="sourcelabel">
<x>42</x>
<y>220</y>
</hint>
<hint type="destinationlabel">
<x>43</x>
<y>171</y>
</hint>
</hints>
</connection>
<connection>
<sender>mrYawMixLevel</sender>
<signal>valueChanged(int)</signal>
<receiver>mrYawMixValue</receiver>
<slot>setNum(int)</slot>
<hints>
<hint type="sourcelabel">
<x>120</x>
<y>254</y>
</hint>
<hint type="destinationlabel">
<x>121</x>
<y>172</y>
</hint>
</hints>
</connection>
<connection>
<sender>mrPitchMixLevel</sender>
<signal>valueChanged(int)</signal>
<receiver>mrPitchMixValue</receiver>
<slot>setNum(int)</slot>
<hints>
<hint type="sourcelabel">
<x>92</x>
<y>222</y>
</hint>
<hint type="destinationlabel">
<x>92</x>
<y>151</y>
</hint>
</hints>
</connection>
</connections> </connections>
</ui> </ui>

View File

@ -0,0 +1,3391 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>CcpmConfigWidget</class>
<widget class="QWidget" name="CcpmConfigWidget">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>850</width>
<height>572</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>300</width>
<height>300</height>
</size>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<property name="autoFillBackground">
<bool>false</bool>
</property>
<layout class="QGridLayout" name="gridLayout_17">
<property name="margin">
<number>0</number>
</property>
<item row="0" column="0">
<layout class="QGridLayout" name="gridLayout_13">
<item row="0" column="0">
<layout class="QHBoxLayout" name="horizontalLayout_5">
<property name="topMargin">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="label">
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>Swashplate config:</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="ccpmType">
<property name="toolTip">
<string>Select aircraft type here</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item row="1" column="0">
<widget class="QTabWidget" name="TabObject">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>300</width>
<height>300</height>
</size>
</property>
<property name="styleSheet">
<string notr="true">#SwashplateBox,#SwashplateBox_2,#SwashplateBox_3,#SwashplateBox_4,#ccpmSwashImageBox,#SwashLvlInstructionsBox,#SwashLvlccpmSwashImageBox,#SwashLvlccpmSliderBox,#SwashLvlStatusBox,#ThrottleCurveBox,#PitchCurveBox{
background-color: qlineargradient(spread:pad, x1:0.507, y1:0.869318, x2:0.507, y2:0.0965909, stop:0 rgba(243, 243, 243, 255), stop:1 rgba(250, 250, 250, 255));
border: 1px outset #999;
border-radius: 3;
font:bold;
}
QGroupBox::title {
subcontrol-origin: margin;
subcontrol-position: top center; /* position at the top center */
padding: 0 3px;
background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,
stop: 0 #FFOECE, stop: 1 #FFFFFF);
top: 5px;
}</string>
</property>
<property name="tabShape">
<enum>QTabWidget::Rounded</enum>
</property>
<property name="currentIndex">
<number>0</number>
</property>
<property name="documentMode">
<bool>false</bool>
</property>
<widget class="QWidget" name="BasicTab">
<attribute name="title">
<string>Basic settings</string>
</attribute>
<layout class="QGridLayout" name="gridLayout_6">
<property name="margin">
<number>9</number>
</property>
<property name="spacing">
<number>6</number>
</property>
<item row="0" column="0">
<layout class="QVBoxLayout" name="ccpmSettingsBox" stretch="0,1,1,0,0">
<item>
<widget class="QGroupBox" name="SwashplateBox_2">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Maximum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximumSize">
<size>
<width>190</width>
<height>16777215</height>
</size>
</property>
<property name="title">
<string>Motor outputs</string>
</property>
<layout class="QGridLayout" name="gridLayout_18">
<property name="horizontalSpacing">
<number>3</number>
</property>
<property name="verticalSpacing">
<number>2</number>
</property>
<property name="margin">
<number>3</number>
</property>
<item row="2" column="1">
<widget class="QComboBox" name="ccpmTailChannel">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>85</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>100</width>
<height>16777215</height>
</size>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QComboBox" name="ccpmEngineChannel">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>85</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>100</width>
<height>16777215</height>
</size>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="ccpmTailLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>80</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>80</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>Tail Rotor</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="ccpmEngineLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>80</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>80</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>Engine</string>
</property>
</widget>
</item>
<item row="0" column="0">
<spacer name="verticalSpacer_5">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="SwashplateBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Maximum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximumSize">
<size>
<width>190</width>
<height>16777215</height>
</size>
</property>
<property name="title">
<string>Swashplate outputs</string>
</property>
<layout class="QGridLayout" name="gridLayout_19">
<property name="horizontalSpacing">
<number>3</number>
</property>
<property name="verticalSpacing">
<number>2</number>
</property>
<property name="margin">
<number>3</number>
</property>
<item row="1" column="0">
<widget class="QLabel" name="ccpmServoWLabel">
<property name="enabled">
<bool>true</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
<horstretch>1</horstretch>
<verstretch>1</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>80</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>80</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>Servo W</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QComboBox" name="ccpmServoWChannel">
<property name="enabled">
<bool>true</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>85</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>100</width>
<height>16777215</height>
</size>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QComboBox" name="ccpmServoXChannel">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>85</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>100</width>
<height>16777215</height>
</size>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QComboBox" name="ccpmServoYChannel">
<property name="enabled">
<bool>true</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>85</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>100</width>
<height>16777215</height>
</size>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="ccpmServoXLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
<horstretch>1</horstretch>
<verstretch>1</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>80</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>80</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>Servo X</string>
</property>
</widget>
</item>
<item row="6" column="1">
<widget class="QComboBox" name="ccpmSingleServo">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>85</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>100</width>
<height>16777215</height>
</size>
</property>
<item>
<property name="text">
<string>Front</string>
</property>
</item>
<item>
<property name="text">
<string>Right</string>
</property>
</item>
<item>
<property name="text">
<string>Rear</string>
</property>
</item>
<item>
<property name="text">
<string>Left</string>
</property>
</item>
</widget>
</item>
<item row="6" column="0">
<widget class="QLabel" name="ccpmServoZLabel_3">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
<horstretch>1</horstretch>
<verstretch>1</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>80</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>80</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>1st Servo</string>
</property>
</widget>
</item>
<item row="5" column="1">
<widget class="QComboBox" name="ccpmServoZChannel">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>85</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>100</width>
<height>16777215</height>
</size>
</property>
</widget>
</item>
<item row="5" column="0">
<widget class="QLabel" name="ccpmServoZLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
<horstretch>1</horstretch>
<verstretch>1</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>80</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>80</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>Servo Z</string>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QLabel" name="ccpmServoYLabel">
<property name="enabled">
<bool>true</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
<horstretch>1</horstretch>
<verstretch>1</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>80</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>80</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>Servo Y</string>
</property>
</widget>
</item>
<item row="0" column="0">
<spacer name="verticalSpacer_6">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="SwashplateBox_3">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Maximum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>70</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>190</width>
<height>16777215</height>
</size>
</property>
<property name="title">
<string>Swashplate Servo Angles</string>
</property>
<layout class="QGridLayout" name="gridLayout_20">
<property name="horizontalSpacing">
<number>3</number>
</property>
<property name="verticalSpacing">
<number>2</number>
</property>
<property name="margin">
<number>3</number>
</property>
<item row="1" column="1">
<widget class="QDoubleSpinBox" name="ccpmAngleW">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>85</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>85</width>
<height>16777215</height>
</size>
</property>
<property name="decimals">
<number>0</number>
</property>
<property name="maximum">
<double>360.000000000000000</double>
</property>
<property name="singleStep">
<double>15.000000000000000</double>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="ccpmServoWLabel_2">
<property name="enabled">
<bool>true</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>80</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>80</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>Angle W</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="ccpmServoXLabel_2">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>80</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>80</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>Angle X</string>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="ccpmServoYLabel_2">
<property name="enabled">
<bool>true</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>80</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>80</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>Angle Y</string>
</property>
</widget>
</item>
<item row="5" column="0">
<widget class="QLabel" name="ccpmServoZLabel_2">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>80</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>80</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>Angle Z</string>
</property>
</widget>
</item>
<item row="6" column="0">
<widget class="QLabel" name="label_10">
<property name="enabled">
<bool>true</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>80</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>80</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>Correction Angle</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QDoubleSpinBox" name="ccpmAngleX">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>85</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>85</width>
<height>16777215</height>
</size>
</property>
<property name="decimals">
<number>0</number>
</property>
<property name="maximum">
<double>360.000000000000000</double>
</property>
<property name="singleStep">
<double>15.000000000000000</double>
</property>
</widget>
</item>
<item row="6" column="1">
<widget class="QDoubleSpinBox" name="ccpmCorrectionAngle">
<property name="enabled">
<bool>true</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>85</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>85</width>
<height>16777215</height>
</size>
</property>
<property name="decimals">
<number>0</number>
</property>
<property name="maximum">
<double>360.000000000000000</double>
</property>
<property name="singleStep">
<double>15.000000000000000</double>
</property>
</widget>
</item>
<item row="5" column="1">
<widget class="QDoubleSpinBox" name="ccpmAngleZ">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>85</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>85</width>
<height>16777215</height>
</size>
</property>
<property name="decimals">
<number>0</number>
</property>
<property name="maximum">
<double>360.000000000000000</double>
</property>
<property name="singleStep">
<double>15.000000000000000</double>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QDoubleSpinBox" name="ccpmAngleY">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>85</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>85</width>
<height>16777215</height>
</size>
</property>
<property name="decimals">
<number>0</number>
</property>
<property name="maximum">
<double>360.000000000000000</double>
</property>
<property name="singleStep">
<double>15.000000000000000</double>
</property>
</widget>
</item>
<item row="0" column="0">
<spacer name="verticalSpacer_7">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="SwashplateBox_4">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Maximum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximumSize">
<size>
<width>190</width>
<height>16777215</height>
</size>
</property>
<property name="title">
<string>CCPM Options</string>
</property>
<layout class="QGridLayout" name="gridLayout_21">
<property name="horizontalSpacing">
<number>3</number>
</property>
<property name="verticalSpacing">
<number>2</number>
</property>
<property name="margin">
<number>3</number>
</property>
<item row="2" column="0">
<widget class="QCheckBox" name="ccpmCollectivePassthrough">
<property name="text">
<string>Collective Pass through</string>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QCheckBox" name="ccpmLinkRoll">
<property name="text">
<string>Link Roll/Pitch</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QCheckBox" name="ccpmLinkCyclic">
<property name="text">
<string>Link Cyclic/Collective</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item row="1" column="0">
<spacer name="verticalSpacer_8">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</item>
<item>
<spacer name="verticalSpacer_3">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item row="0" column="10">
<layout class="QVBoxLayout" name="ccpmSwashImageBox_2">
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<item>
<widget class="QGroupBox" name="ccpmSwashImageBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>1</horstretch>
<verstretch>1</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>200</width>
<height>200</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>600</width>
<height>600</height>
</size>
</property>
<property name="sizeIncrement">
<size>
<width>10</width>
<height>10</height>
</size>
</property>
<property name="baseSize">
<size>
<width>200</width>
<height>200</height>
</size>
</property>
<property name="font">
<font>
<weight>75</weight>
<italic>false</italic>
<bold>true</bold>
</font>
</property>
<property name="title">
<string>Swashplate Layout</string>
</property>
<property name="alignment">
<set>Qt::AlignHCenter|Qt::AlignTop</set>
</property>
<property name="flat">
<bool>false</bool>
</property>
<property name="checkable">
<bool>false</bool>
</property>
<layout class="QGridLayout" name="gridLayout_10">
<property name="horizontalSpacing">
<number>3</number>
</property>
<property name="margin">
<number>3</number>
</property>
<item row="1" column="0">
<widget class="QSplitter" name="splitter_3">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<widget class="QGraphicsView" name="SwashplateImage">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>1</horstretch>
<verstretch>1</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>10</width>
<height>10</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>1000</width>
<height>1000</height>
</size>
</property>
<property name="sizeIncrement">
<size>
<width>10</width>
<height>10</height>
</size>
</property>
<property name="baseSize">
<size>
<width>200</width>
<height>200</height>
</size>
</property>
<property name="frameShape">
<enum>QFrame::Box</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Plain</enum>
</property>
<property name="lineWidth">
<number>1</number>
</property>
<property name="verticalScrollBarPolicy">
<enum>Qt::ScrollBarAlwaysOff</enum>
</property>
<property name="horizontalScrollBarPolicy">
<enum>Qt::ScrollBarAlwaysOff</enum>
</property>
<property name="backgroundBrush">
<brush brushstyle="DiagCrossPattern">
<color alpha="50">
<red>112</red>
<green>184</green>
<blue>138</blue>
</color>
</brush>
</property>
<property name="foregroundBrush">
<brush brushstyle="SolidPattern">
<color alpha="0">
<red>127</red>
<green>127</green>
<blue>127</blue>
</color>
</brush>
</property>
<property name="sceneRect">
<rectf>
<x>0.000000000000000</x>
<y>0.000000000000000</y>
<width>400.000000000000000</width>
<height>400.000000000000000</height>
</rectf>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
<property name="resizeAnchor">
<enum>QGraphicsView::AnchorViewCenter</enum>
</property>
</widget>
</widget>
</item>
<item row="0" column="0">
<spacer name="verticalSpacer_9">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</item>
</layout>
</item>
<item row="0" column="3">
<layout class="QHBoxLayout" name="horizontalLayout_10">
<property name="sizeConstraint">
<enum>QLayout::SetNoConstraint</enum>
</property>
<property name="rightMargin">
<number>3</number>
</property>
<property name="bottomMargin">
<number>3</number>
</property>
<item>
<widget class="QGroupBox" name="ccpmRevoMixingBox">
<property name="enabled">
<bool>true</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>50</width>
<height>100</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>50</width>
<height>600</height>
</size>
</property>
<property name="font">
<font>
<pointsize>9</pointsize>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="styleSheet">
<string notr="true">QGroupBox::title {
background-color: qlineargradient(spread:reflect, x1:0.507, y1:0, x2:0.507, y2:0.772, stop:0.208955 rgba(74, 74, 74, 255), stop:0.78607 rgba(36, 36, 36, 255));
color: rgb(255, 255, 255);
border-radius: 5;
margin:1px;
}</string>
</property>
<property name="title">
<string>REVO</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_3">
<property name="spacing">
<number>0</number>
</property>
<property name="margin">
<number>3</number>
</property>
<item>
<widget class="QLabel" name="label_14">
<property name="enabled">
<bool>false</bool>
</property>
<property name="font">
<font>
<pointsize>7</pointsize>
</font>
</property>
<property name="text">
<string>100%</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QSlider" name="ccpmRevoSlider">
<property name="enabled">
<bool>true</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>100</height>
</size>
</property>
<property name="maximum">
<number>100</number>
</property>
<property name="singleStep">
<number>5</number>
</property>
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QLabel" name="label_13">
<property name="enabled">
<bool>false</bool>
</property>
<property name="font">
<font>
<pointsize>7</pointsize>
</font>
</property>
<property name="text">
<string>0%</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="ccpmREVOspinBox"/>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="ccpmPitchMixingBox">
<property name="enabled">
<bool>true</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>60</width>
<height>100</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>50</width>
<height>600</height>
</size>
</property>
<property name="font">
<font>
<pointsize>9</pointsize>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="styleSheet">
<string notr="true">QGroupBox::title {
background-color: qlineargradient(spread:reflect, x1:0.507, y1:0, x2:0.507, y2:0.772, stop:0.208955 rgba(74, 74, 74, 255), stop:0.78607 rgba(36, 36, 36, 255));
color: rgb(255, 255, 255);
border-radius: 5;
margin:1px;
}</string>
</property>
<property name="title">
<string>CCPM</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
<layout class="QVBoxLayout" name="verticalLayout_4">
<property name="spacing">
<number>0</number>
</property>
<property name="margin">
<number>3</number>
</property>
<item>
<widget class="QLabel" name="label_15">
<property name="enabled">
<bool>true</bool>
</property>
<property name="font">
<font>
<pointsize>7</pointsize>
</font>
</property>
<property name="text">
<string>Collective</string>
</property>
<property name="scaledContents">
<bool>true</bool>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QSlider" name="ccpmCollectiveSlider">
<property name="enabled">
<bool>true</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>100</height>
</size>
</property>
<property name="maximum">
<number>100</number>
</property>
<property name="singleStep">
<number>5</number>
</property>
<property name="value">
<number>50</number>
</property>
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QLabel" name="label_16">
<property name="enabled">
<bool>true</bool>
</property>
<property name="font">
<font>
<pointsize>7</pointsize>
</font>
</property>
<property name="text">
<string>Cyclic</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="ccpmCollectivespinBox">
<property name="maximum">
<number>100</number>
</property>
<property name="singleStep">
<number>5</number>
</property>
<property name="value">
<number>50</number>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="ccpmCollectiveScalingBox">
<property name="enabled">
<bool>true</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>70</width>
<height>100</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>50</width>
<height>600</height>
</size>
</property>
<property name="font">
<font>
<pointsize>9</pointsize>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="styleSheet">
<string notr="true">QGroupBox::title {
background-color: qlineargradient(spread:reflect, x1:0.507, y1:0, x2:0.507, y2:0.772, stop:0.208955 rgba(74, 74, 74, 255), stop:0.78607 rgba(36, 36, 36, 255));
color: rgb(255, 255, 255);
border-radius: 5;
margin:1px;
}</string>
</property>
<property name="title">
<string>Collective</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
<layout class="QVBoxLayout" name="verticalLayout_12">
<property name="spacing">
<number>0</number>
</property>
<property name="margin">
<number>3</number>
</property>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_11">
<item>
<widget class="QSlider" name="ccpmCollectiveScale">
<property name="enabled">
<bool>true</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>100</height>
</size>
</property>
<property name="maximum">
<number>100</number>
</property>
<property name="singleStep">
<number>5</number>
</property>
<property name="value">
<number>50</number>
</property>
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QSpinBox" name="ccpmCollectiveScaleBox">
<property name="maximum">
<number>100</number>
</property>
<property name="singleStep">
<number>5</number>
</property>
<property name="value">
<number>50</number>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="ccpmCyclicScalingBox">
<property name="enabled">
<bool>true</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>50</width>
<height>100</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>50</width>
<height>600</height>
</size>
</property>
<property name="font">
<font>
<pointsize>9</pointsize>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="styleSheet">
<string notr="true">QGroupBox::title {
background-color: qlineargradient(spread:reflect, x1:0.507, y1:0, x2:0.507, y2:0.772, stop:0.208955 rgba(74, 74, 74, 255), stop:0.78607 rgba(36, 36, 36, 255));
color: rgb(255, 255, 255);
border-radius: 5;
margin:1px;
}</string>
</property>
<property name="title">
<string>Cyclic</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
<property name="checkable">
<bool>false</bool>
</property>
<layout class="QVBoxLayout" name="verticalLayout_7">
<property name="spacing">
<number>0</number>
</property>
<property name="margin">
<number>3</number>
</property>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_7">
<item>
<widget class="QSlider" name="ccpmCyclicScale">
<property name="enabled">
<bool>true</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>100</height>
</size>
</property>
<property name="maximum">
<number>100</number>
</property>
<property name="singleStep">
<number>5</number>
</property>
<property name="value">
<number>50</number>
</property>
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QSpinBox" name="ccpmCyclicScaleBox">
<property name="maximum">
<number>100</number>
</property>
<property name="singleStep">
<number>5</number>
</property>
<property name="value">
<number>50</number>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="ccpmPitchScalingBox">
<property name="enabled">
<bool>true</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>50</width>
<height>100</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>50</width>
<height>600</height>
</size>
</property>
<property name="font">
<font>
<pointsize>9</pointsize>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="styleSheet">
<string notr="true">QGroupBox::title {
background-color: qlineargradient(spread:reflect, x1:0.507, y1:0, x2:0.507, y2:0.772, stop:0.208955 rgba(74, 74, 74, 255), stop:0.78607 rgba(36, 36, 36, 255));
color: rgb(255, 255, 255);
border-radius: 5;
margin:1px;
}</string>
</property>
<property name="title">
<string>Pitch</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
<layout class="QVBoxLayout" name="verticalLayout_13">
<property name="spacing">
<number>0</number>
</property>
<property name="margin">
<number>3</number>
</property>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_12">
<item>
<widget class="QSlider" name="ccpmPitchScale">
<property name="enabled">
<bool>true</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>100</height>
</size>
</property>
<property name="maximum">
<number>100</number>
</property>
<property name="singleStep">
<number>5</number>
</property>
<property name="value">
<number>50</number>
</property>
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QSpinBox" name="ccpmPitchScaleBox">
<property name="maximum">
<number>100</number>
</property>
<property name="singleStep">
<number>5</number>
</property>
<property name="value">
<number>50</number>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="ccpmRollScalingBox">
<property name="enabled">
<bool>true</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>50</width>
<height>100</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>50</width>
<height>600</height>
</size>
</property>
<property name="font">
<font>
<pointsize>9</pointsize>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="styleSheet">
<string notr="true">QGroupBox::title {
background-color: qlineargradient(spread:reflect, x1:0.507, y1:0, x2:0.507, y2:0.772, stop:0.208955 rgba(74, 74, 74, 255), stop:0.78607 rgba(36, 36, 36, 255));
color: rgb(255, 255, 255);
border-radius: 5;
margin:1px;
}</string>
</property>
<property name="title">
<string>Roll</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
<layout class="QVBoxLayout" name="verticalLayout_10">
<property name="spacing">
<number>0</number>
</property>
<property name="margin">
<number>3</number>
</property>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_8">
<item>
<widget class="QSlider" name="ccpmRollScale">
<property name="enabled">
<bool>true</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>100</height>
</size>
</property>
<property name="maximum">
<number>100</number>
</property>
<property name="singleStep">
<number>5</number>
</property>
<property name="value">
<number>50</number>
</property>
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QSpinBox" name="ccpmRollScaleBox">
<property name="maximum">
<number>100</number>
</property>
<property name="singleStep">
<number>5</number>
</property>
<property name="value">
<number>50</number>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<widget class="QWidget" name="SwashPlateLevel">
<attribute name="title">
<string>Swashplate Levelling</string>
</attribute>
<layout class="QGridLayout" name="gridLayout_8">
<property name="margin">
<number>9</number>
</property>
<property name="spacing">
<number>6</number>
</property>
<item row="0" column="0">
<layout class="QVBoxLayout" name="verticalLayout_8">
<property name="leftMargin">
<number>3</number>
</property>
<item>
<widget class="QGroupBox" name="SwashLvlInstructionsBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Maximum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>228</width>
<height>0</height>
</size>
</property>
<property name="title">
<string>Commands</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<property name="margin">
<number>3</number>
</property>
<item>
<spacer name="verticalSpacer_16">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_9">
<property name="spacing">
<number>0</number>
</property>
<item>
<widget class="QPushButton" name="SwashLvlStartButton">
<property name="minimumSize">
<size>
<width>85</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>85</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>Start</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="SwashLvlNextButton">
<property name="enabled">
<bool>false</bool>
</property>
<property name="minimumSize">
<size>
<width>85</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>85</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>Next</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QTextEdit" name="SwashLvlStepInstruction">
<property name="minimumSize">
<size>
<width>0</width>
<height>150</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>220</width>
<height>450</height>
</size>
</property>
<property name="horizontalScrollBarPolicy">
<enum>Qt::ScrollBarAlwaysOff</enum>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<layout class="QGridLayout" name="gridLayout_3">
<item row="0" column="0">
<widget class="QPushButton" name="SwashLvlCancelButton">
<property name="enabled">
<bool>false</bool>
</property>
<property name="minimumSize">
<size>
<width>170</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>170</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>Cancel</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QPushButton" name="SwashLvlFinishButton">
<property name="enabled">
<bool>false</bool>
</property>
<property name="minimumSize">
<size>
<width>170</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>170</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>Finish</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="SwashLvlStatusBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Maximum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>200</width>
<height>0</height>
</size>
</property>
<property name="title">
<string>Status</string>
</property>
<layout class="QGridLayout" name="gridLayout_22">
<property name="horizontalSpacing">
<number>3</number>
</property>
<property name="verticalSpacing">
<number>2</number>
</property>
<property name="margin">
<number>3</number>
</property>
<item row="1" column="0">
<widget class="QListWidget" name="SwashLvlStepList">
<property name="minimumSize">
<size>
<width>220</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>190</width>
<height>125</height>
</size>
</property>
<property name="editTriggers">
<set>QAbstractItemView::NoEditTriggers</set>
</property>
<property name="alternatingRowColors">
<bool>true</bool>
</property>
<property name="selectionMode">
<enum>QAbstractItemView::NoSelection</enum>
</property>
<property name="selectionBehavior">
<enum>QAbstractItemView::SelectRows</enum>
</property>
<item>
<property name="text">
<string>Neutral</string>
</property>
<property name="icon">
<iconset>
<normaloff>:/configgadget/images/none.png</normaloff>
<normalon>:/configgadget/images/ok.png</normalon>:/configgadget/images/none.png</iconset>
</property>
</item>
<item>
<property name="text">
<string>Max</string>
</property>
<property name="icon">
<iconset>
<normaloff>:/configgadget/images/none.png</normaloff>
<normalon>:/configgadget/images/ok.png</normalon>:/configgadget/images/none.png</iconset>
</property>
</item>
<item>
<property name="text">
<string>Min</string>
</property>
<property name="icon">
<iconset>
<normaloff>:/configgadget/images/none.png</normaloff>
<normalon>:/configgadget/images/ok.png</normalon>:/configgadget/images/none.png</iconset>
</property>
<property name="flags">
<set>ItemIsSelectable|ItemIsEnabled</set>
</property>
</item>
<item>
<property name="text">
<string>Verify</string>
</property>
<property name="icon">
<iconset>
<normaloff>:/configgadget/images/none.png</normaloff>
<normalon>:/configgadget/images/ok.png</normalon>:/configgadget/images/none.png</iconset>
</property>
<property name="flags">
<set>ItemIsEnabled</set>
</property>
</item>
</widget>
</item>
<item row="0" column="0">
<spacer name="verticalSpacer_19">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</item>
<item>
<spacer name="verticalSpacer_4">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::MinimumExpanding</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>0</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item row="0" column="1">
<widget class="QGroupBox" name="SwashLvlccpmSliderBox">
<property name="enabled">
<bool>true</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>70</width>
<height>100</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>50</width>
<height>600</height>
</size>
</property>
<property name="title">
<string>Position</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
<layout class="QVBoxLayout" name="verticalLayout_5">
<property name="spacing">
<number>0</number>
</property>
<property name="margin">
<number>3</number>
</property>
<item>
<spacer name="verticalSpacer_18">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="label_17">
<property name="enabled">
<bool>true</bool>
</property>
<property name="styleSheet">
<string notr="true">background-color: qlineargradient(spread:reflect, x1:0.507, y1:0, x2:0.507, y2:0.772, stop:0.208955 rgba(74, 74, 74, 255), stop:0.78607 rgba(36, 36, 36, 255));
color: rgb(255, 255, 255);
border-radius: 5;
font: bold 12px;
margin:1px;</string>
</property>
<property name="text">
<string>Max</string>
</property>
<property name="scaledContents">
<bool>true</bool>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_4">
<item>
<widget class="QSlider" name="SwashLvlPositionSlider">
<property name="enabled">
<bool>true</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>100</height>
</size>
</property>
<property name="maximum">
<number>100</number>
</property>
<property name="singleStep">
<number>5</number>
</property>
<property name="value">
<number>50</number>
</property>
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QLabel" name="label_18">
<property name="enabled">
<bool>true</bool>
</property>
<property name="styleSheet">
<string notr="true">background-color: qlineargradient(spread:reflect, x1:0.507, y1:0, x2:0.507, y2:0.772, stop:0.208955 rgba(74, 74, 74, 255), stop:0.78607 rgba(36, 36, 36, 255));
color: rgb(255, 255, 255);
border-radius: 5;
font: bold 12px;
margin:1px;</string>
</property>
<property name="text">
<string>Min</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="SwashLvlPositionSpinBox">
<property name="maximum">
<number>100</number>
</property>
<property name="singleStep">
<number>5</number>
</property>
<property name="value">
<number>50</number>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="0" column="2">
<widget class="QGroupBox" name="SwashLvlccpmSwashImageBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>1</horstretch>
<verstretch>1</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>200</width>
<height>200</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>600</width>
<height>600</height>
</size>
</property>
<property name="sizeIncrement">
<size>
<width>10</width>
<height>10</height>
</size>
</property>
<property name="baseSize">
<size>
<width>200</width>
<height>200</height>
</size>
</property>
<property name="title">
<string>Swashplate Adjustment</string>
</property>
<property name="alignment">
<set>Qt::AlignHCenter|Qt::AlignTop</set>
</property>
<property name="flat">
<bool>false</bool>
</property>
<property name="checkable">
<bool>false</bool>
</property>
<layout class="QGridLayout" name="gridLayout_11">
<property name="horizontalSpacing">
<number>3</number>
</property>
<property name="margin">
<number>3</number>
</property>
<item row="1" column="0">
<widget class="QSplitter" name="splitter_4">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<widget class="QGraphicsView" name="SwashLvlSwashplateImage">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>1</horstretch>
<verstretch>1</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>10</width>
<height>10</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>1000</width>
<height>1000</height>
</size>
</property>
<property name="sizeIncrement">
<size>
<width>10</width>
<height>10</height>
</size>
</property>
<property name="baseSize">
<size>
<width>200</width>
<height>200</height>
</size>
</property>
<property name="frameShape">
<enum>QFrame::Box</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Plain</enum>
</property>
<property name="lineWidth">
<number>1</number>
</property>
<property name="midLineWidth">
<number>0</number>
</property>
<property name="verticalScrollBarPolicy">
<enum>Qt::ScrollBarAlwaysOff</enum>
</property>
<property name="horizontalScrollBarPolicy">
<enum>Qt::ScrollBarAlwaysOff</enum>
</property>
<property name="backgroundBrush">
<brush brushstyle="DiagCrossPattern">
<color alpha="25">
<red>126</red>
<green>176</green>
<blue>220</blue>
</color>
</brush>
</property>
<property name="foregroundBrush">
<brush brushstyle="NoBrush">
<color alpha="255">
<red>0</red>
<green>0</green>
<blue>0</blue>
</color>
</brush>
</property>
<property name="sceneRect">
<rectf>
<x>0.000000000000000</x>
<y>0.000000000000000</y>
<width>400.000000000000000</width>
<height>400.000000000000000</height>
</rectf>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
<property name="resizeAnchor">
<enum>QGraphicsView::AnchorViewCenter</enum>
</property>
</widget>
</widget>
</item>
<item row="0" column="0">
<spacer name="verticalSpacer_17">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="CurveTab">
<attribute name="title">
<string>Curve settings</string>
</attribute>
<layout class="QGridLayout" name="gridLayout_7">
<property name="margin">
<number>9</number>
</property>
<property name="spacing">
<number>6</number>
</property>
<item row="0" column="0">
<layout class="QHBoxLayout" name="horizontalLayout_6"/>
</item>
<item row="1" column="0">
<layout class="QHBoxLayout" name="horizontalLayout_3">
<property name="spacing">
<number>3</number>
</property>
<item>
<widget class="QGroupBox" name="ThrottleCurveBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>1</horstretch>
<verstretch>1</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>100</width>
<height>100</height>
</size>
</property>
<property name="sizeIncrement">
<size>
<width>10</width>
<height>10</height>
</size>
</property>
<property name="baseSize">
<size>
<width>100</width>
<height>100</height>
</size>
</property>
<property name="layoutDirection">
<enum>Qt::LeftToRight</enum>
</property>
<property name="title">
<string/>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
</property>
<property name="flat">
<bool>false</bool>
</property>
<layout class="QGridLayout" name="gridLayout">
<property name="margin">
<number>0</number>
</property>
<property name="spacing">
<number>0</number>
</property>
<item row="0" column="0">
<widget class="MixerCurve" name="ThrottleCurve" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>1</horstretch>
<verstretch>1</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>50</width>
<height>50</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>1000</width>
<height>1000</height>
</size>
</property>
<property name="sizeIncrement">
<size>
<width>10</width>
<height>10</height>
</size>
</property>
<property name="baseSize">
<size>
<width>200</width>
<height>200</height>
</size>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="PitchCurveBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>1</horstretch>
<verstretch>1</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>100</width>
<height>100</height>
</size>
</property>
<property name="sizeIncrement">
<size>
<width>10</width>
<height>10</height>
</size>
</property>
<property name="baseSize">
<size>
<width>100</width>
<height>100</height>
</size>
</property>
<property name="title">
<string/>
</property>
<layout class="QGridLayout" name="gridLayout_5">
<property name="margin">
<number>0</number>
</property>
<property name="spacing">
<number>0</number>
</property>
<item row="0" column="0">
<widget class="MixerCurve" name="PitchCurve" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Expanding">
<horstretch>1</horstretch>
<verstretch>1</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>50</width>
<height>50</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>1000</width>
<height>1000</height>
</size>
</property>
<property name="sizeIncrement">
<size>
<width>10</width>
<height>10</height>
</size>
</property>
<property name="baseSize">
<size>
<width>200</width>
<height>200</height>
</size>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</item>
<item row="2" column="0">
<spacer name="verticalSpacer_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Preferred</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>0</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
<widget class="QWidget" name="AdvancedTab">
<attribute name="title">
<string>Advanced settings</string>
</attribute>
<layout class="QGridLayout" name="gridLayout_4">
<property name="margin">
<number>9</number>
</property>
<property name="spacing">
<number>6</number>
</property>
<item row="0" column="0">
<widget class="QTableWidget" name="ccpmAdvancedSettingsTable">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="MinimumExpanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>200</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>1000</width>
<height>300</height>
</size>
</property>
<property name="verticalScrollBarPolicy">
<enum>Qt::ScrollBarAlwaysOff</enum>
</property>
<property name="horizontalScrollBarPolicy">
<enum>Qt::ScrollBarAlwaysOff</enum>
</property>
<property name="autoScroll">
<bool>true</bool>
</property>
<property name="alternatingRowColors">
<bool>true</bool>
</property>
<property name="selectionMode">
<enum>QAbstractItemView::NoSelection</enum>
</property>
<property name="wordWrap">
<bool>false</bool>
</property>
<property name="cornerButtonEnabled">
<bool>true</bool>
</property>
<attribute name="horizontalHeaderDefaultSectionSize">
<number>75</number>
</attribute>
<attribute name="horizontalHeaderMinimumSectionSize">
<number>20</number>
</attribute>
<row>
<property name="text">
<string>Engine</string>
</property>
</row>
<row>
<property name="text">
<string>Tail Rotor</string>
</property>
</row>
<row>
<property name="text">
<string>Servo W</string>
</property>
</row>
<row>
<property name="text">
<string>Servo X</string>
</property>
</row>
<row>
<property name="text">
<string>Servo Y</string>
</property>
</row>
<row>
<property name="text">
<string>Servo Z</string>
</property>
</row>
<column>
<property name="text">
<string>Channel</string>
</property>
</column>
<column>
<property name="text">
<string>Curve 1</string>
</property>
</column>
<column>
<property name="text">
<string>Curve 2</string>
</property>
</column>
<column>
<property name="text">
<string>Roll</string>
</property>
</column>
<column>
<property name="text">
<string>Pitch</string>
</property>
</column>
<column>
<property name="text">
<string>Yaw</string>
</property>
</column>
<item row="0" column="0">
<property name="text">
<string>-</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</item>
<item row="0" column="1">
<property name="text">
<string>-</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</item>
<item row="0" column="2">
<property name="text">
<string>-</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</item>
<item row="0" column="3">
<property name="text">
<string>-</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</item>
<item row="0" column="4">
<property name="text">
<string>-</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</item>
<item row="0" column="5">
<property name="text">
<string>-</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</item>
<item row="1" column="0">
<property name="text">
<string>-</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</item>
<item row="1" column="1">
<property name="text">
<string>-</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</item>
<item row="1" column="2">
<property name="text">
<string>-</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</item>
<item row="1" column="3">
<property name="text">
<string>-</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</item>
<item row="1" column="4">
<property name="text">
<string>-</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</item>
<item row="1" column="5">
<property name="text">
<string>-</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</item>
<item row="2" column="0">
<property name="text">
<string>-</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</item>
<item row="2" column="1">
<property name="text">
<string>-</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</item>
<item row="2" column="2">
<property name="text">
<string>-</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</item>
<item row="2" column="3">
<property name="text">
<string>-</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</item>
<item row="2" column="4">
<property name="text">
<string>-</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</item>
<item row="2" column="5">
<property name="text">
<string>-</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</item>
<item row="3" column="0">
<property name="text">
<string>-</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</item>
<item row="3" column="1">
<property name="text">
<string>-</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</item>
<item row="3" column="2">
<property name="text">
<string>-</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</item>
<item row="3" column="3">
<property name="text">
<string>-</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</item>
<item row="3" column="4">
<property name="text">
<string>-</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</item>
<item row="3" column="5">
<property name="text">
<string>-</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</item>
<item row="4" column="0">
<property name="text">
<string>-</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</item>
<item row="4" column="1">
<property name="text">
<string>-</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</item>
<item row="4" column="2">
<property name="text">
<string>-</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</item>
<item row="4" column="3">
<property name="text">
<string>-</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</item>
<item row="4" column="4">
<property name="text">
<string>-</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</item>
<item row="4" column="5">
<property name="text">
<string>-</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</item>
<item row="5" column="0">
<property name="text">
<string>-</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</item>
<item row="5" column="1">
<property name="text">
<string>-</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</item>
<item row="5" column="2">
<property name="text">
<string>-</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</item>
<item row="5" column="3">
<property name="text">
<string>-</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</item>
<item row="5" column="4">
<property name="text">
<string>-</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</item>
<item row="5" column="5">
<property name="text">
<string>-</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</item>
</widget>
</item>
<item row="1" column="0">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::MinimumExpanding</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>MixerCurve</class>
<extends>QWidget</extends>
<header location="global">mixercurve.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<tabstops>
<tabstop>ccpmType</tabstop>
<tabstop>TabObject</tabstop>
<tabstop>ccpmEngineChannel</tabstop>
<tabstop>ccpmTailChannel</tabstop>
<tabstop>ccpmServoWChannel</tabstop>
<tabstop>ccpmServoXChannel</tabstop>
<tabstop>ccpmServoYChannel</tabstop>
<tabstop>ccpmServoZChannel</tabstop>
<tabstop>ccpmSingleServo</tabstop>
<tabstop>ccpmAngleW</tabstop>
<tabstop>ccpmAngleX</tabstop>
<tabstop>ccpmAngleY</tabstop>
<tabstop>ccpmAngleZ</tabstop>
<tabstop>ccpmCorrectionAngle</tabstop>
<tabstop>ccpmRevoSlider</tabstop>
<tabstop>ccpmREVOspinBox</tabstop>
<tabstop>ccpmCollectiveSlider</tabstop>
<tabstop>ccpmCollectivespinBox</tabstop>
<tabstop>SwashplateImage</tabstop>
<tabstop>SwashLvlStartButton</tabstop>
<tabstop>SwashLvlNextButton</tabstop>
<tabstop>SwashLvlStepInstruction</tabstop>
<tabstop>SwashLvlCancelButton</tabstop>
<tabstop>SwashLvlFinishButton</tabstop>
<tabstop>SwashLvlStepList</tabstop>
<tabstop>SwashLvlPositionSlider</tabstop>
<tabstop>SwashLvlPositionSpinBox</tabstop>
<tabstop>SwashLvlSwashplateImage</tabstop>
<tabstop>ccpmAdvancedSettingsTable</tabstop>
</tabstops>
<resources/>
<connections>
<connection>
<sender>ccpmCollectiveSlider</sender>
<signal>valueChanged(int)</signal>
<receiver>ccpmCollectivespinBox</receiver>
<slot>setValue(int)</slot>
<hints>
<hint type="sourcelabel">
<x>261</x>
<y>496</y>
</hint>
<hint type="destinationlabel">
<x>269</x>
<y>546</y>
</hint>
</hints>
</connection>
<connection>
<sender>ccpmCollectivespinBox</sender>
<signal>valueChanged(int)</signal>
<receiver>ccpmCollectiveSlider</receiver>
<slot>setValue(int)</slot>
<hints>
<hint type="sourcelabel">
<x>269</x>
<y>546</y>
</hint>
<hint type="destinationlabel">
<x>261</x>
<y>511</y>
</hint>
</hints>
</connection>
<connection>
<sender>ccpmREVOspinBox</sender>
<signal>valueChanged(int)</signal>
<receiver>ccpmRevoSlider</receiver>
<slot>setValue(int)</slot>
<hints>
<hint type="sourcelabel">
<x>216</x>
<y>546</y>
</hint>
<hint type="destinationlabel">
<x>208</x>
<y>511</y>
</hint>
</hints>
</connection>
<connection>
<sender>ccpmRevoSlider</sender>
<signal>valueChanged(int)</signal>
<receiver>ccpmREVOspinBox</receiver>
<slot>setValue(int)</slot>
<hints>
<hint type="sourcelabel">
<x>208</x>
<y>412</y>
</hint>
<hint type="destinationlabel">
<x>216</x>
<y>546</y>
</hint>
</hints>
</connection>
<connection>
<sender>SwashLvlPositionSlider</sender>
<signal>valueChanged(int)</signal>
<receiver>SwashLvlPositionSpinBox</receiver>
<slot>setValue(int)</slot>
<hints>
<hint type="sourcelabel">
<x>276</x>
<y>486</y>
</hint>
<hint type="destinationlabel">
<x>270</x>
<y>537</y>
</hint>
</hints>
</connection>
<connection>
<sender>SwashLvlPositionSpinBox</sender>
<signal>valueChanged(int)</signal>
<receiver>SwashLvlPositionSlider</receiver>
<slot>setValue(int)</slot>
<hints>
<hint type="sourcelabel">
<x>301</x>
<y>546</y>
</hint>
<hint type="destinationlabel">
<x>277</x>
<y>401</y>
</hint>
</hints>
</connection>
<connection>
<sender>ccpmCollectiveScaleBox</sender>
<signal>valueChanged(int)</signal>
<receiver>ccpmCollectiveScale</receiver>
<slot>setValue(int)</slot>
<hints>
<hint type="sourcelabel">
<x>296</x>
<y>534</y>
</hint>
<hint type="destinationlabel">
<x>306</x>
<y>480</y>
</hint>
</hints>
</connection>
<connection>
<sender>ccpmCollectiveScale</sender>
<signal>valueChanged(int)</signal>
<receiver>ccpmCollectiveScaleBox</receiver>
<slot>setValue(int)</slot>
<hints>
<hint type="sourcelabel">
<x>308</x>
<y>328</y>
</hint>
<hint type="destinationlabel">
<x>292</x>
<y>534</y>
</hint>
</hints>
</connection>
<connection>
<sender>ccpmPitchScale</sender>
<signal>valueChanged(int)</signal>
<receiver>ccpmPitchScaleBox</receiver>
<slot>setValue(int)</slot>
<hints>
<hint type="sourcelabel">
<x>417</x>
<y>306</y>
</hint>
<hint type="destinationlabel">
<x>406</x>
<y>531</y>
</hint>
</hints>
</connection>
<connection>
<sender>ccpmPitchScaleBox</sender>
<signal>valueChanged(int)</signal>
<receiver>ccpmPitchScale</receiver>
<slot>setValue(int)</slot>
<hints>
<hint type="sourcelabel">
<x>394</x>
<y>531</y>
</hint>
<hint type="destinationlabel">
<x>408</x>
<y>302</y>
</hint>
</hints>
</connection>
<connection>
<sender>ccpmRollScaleBox</sender>
<signal>valueChanged(int)</signal>
<receiver>ccpmRollScale</receiver>
<slot>setValue(int)</slot>
<hints>
<hint type="sourcelabel">
<x>455</x>
<y>529</y>
</hint>
<hint type="destinationlabel">
<x>458</x>
<y>466</y>
</hint>
</hints>
</connection>
<connection>
<sender>ccpmRollScale</sender>
<signal>valueChanged(int)</signal>
<receiver>ccpmRollScaleBox</receiver>
<slot>setValue(int)</slot>
<hints>
<hint type="sourcelabel">
<x>461</x>
<y>388</y>
</hint>
<hint type="destinationlabel">
<x>474</x>
<y>533</y>
</hint>
</hints>
</connection>
<connection>
<sender>ccpmCyclicScale</sender>
<signal>valueChanged(int)</signal>
<receiver>ccpmCyclicScaleBox</receiver>
<slot>setValue(int)</slot>
<hints>
<hint type="sourcelabel">
<x>358</x>
<y>306</y>
</hint>
<hint type="destinationlabel">
<x>355</x>
<y>538</y>
</hint>
</hints>
</connection>
<connection>
<sender>ccpmCyclicScaleBox</sender>
<signal>valueChanged(int)</signal>
<receiver>ccpmCyclicScale</receiver>
<slot>setValue(int)</slot>
<hints>
<hint type="sourcelabel">
<x>341</x>
<y>538</y>
</hint>
<hint type="destinationlabel">
<x>351</x>
<y>376</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View File

@ -0,0 +1,831 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>CustomConfigWidget</class>
<widget class="QWidget" name="CustomConfigWidget">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>880</width>
<height>608</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_10">
<property name="margin">
<number>0</number>
</property>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_14">
<property name="rightMargin">
<number>0</number>
</property>
<item>
<widget class="QGroupBox" name="groupBox_4">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="title">
<string>Curve 1</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_7">
<item>
<widget class="MixerCurve" name="customThrottle1Curve" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
<horstretch>1</horstretch>
<verstretch>1</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>50</width>
<height>50</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>1000</width>
<height>1000</height>
</size>
</property>
<property name="sizeIncrement">
<size>
<width>10</width>
<height>10</height>
</size>
</property>
<property name="baseSize">
<size>
<width>300</width>
<height>350</height>
</size>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBox_5">
<property name="title">
<string>Curve 2</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_17">
<item>
<widget class="MixerCurve" name="customThrottle2Curve" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
<horstretch>1</horstretch>
<verstretch>1</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>50</width>
<height>50</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>1000</width>
<height>1000</height>
</size>
</property>
<property name="sizeIncrement">
<size>
<width>10</width>
<height>10</height>
</size>
</property>
<property name="baseSize">
<size>
<width>300</width>
<height>350</height>
</size>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QTableWidget" name="customMixerTable">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="alternatingRowColors">
<bool>true</bool>
</property>
<property name="columnCount">
<number>12</number>
</property>
<attribute name="horizontalHeaderDefaultSectionSize">
<number>50</number>
</attribute>
<attribute name="horizontalHeaderStretchLastSection">
<bool>false</bool>
</attribute>
<row>
<property name="text">
<string>Type</string>
</property>
</row>
<row>
<property name="text">
<string>Curve 1</string>
</property>
</row>
<row>
<property name="text">
<string>Curve 2</string>
</property>
</row>
<row>
<property name="text">
<string>Roll</string>
</property>
</row>
<row>
<property name="text">
<string>Pitch</string>
</property>
</row>
<row>
<property name="text">
<string>Yaw</string>
</property>
</row>
<column>
<property name="text">
<string>Ch 1</string>
</property>
</column>
<column>
<property name="text">
<string>Ch 2</string>
</property>
</column>
<column>
<property name="text">
<string>Ch 3</string>
</property>
</column>
<column>
<property name="text">
<string>Ch 4</string>
</property>
</column>
<column>
<property name="text">
<string>Ch 5</string>
</property>
</column>
<column>
<property name="text">
<string>Ch 6</string>
</property>
</column>
<column>
<property name="text">
<string>Ch 7</string>
</property>
</column>
<column>
<property name="text">
<string>Ch 8</string>
</property>
</column>
<column>
<property name="text">
<string>Ch 9</string>
</property>
</column>
<column>
<property name="text">
<string>Ch 10</string>
</property>
</column>
<column>
<property name="text">
<string>Ch 11</string>
</property>
</column>
<column>
<property name="text">
<string>Ch 12</string>
</property>
</column>
<item row="0" column="0">
<property name="text">
<string>-</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</item>
<item row="0" column="1">
<property name="text">
<string>-</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</item>
<item row="0" column="2">
<property name="text">
<string>-</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</item>
<item row="0" column="3">
<property name="text">
<string>-</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</item>
<item row="0" column="4">
<property name="text">
<string>-</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</item>
<item row="0" column="5">
<property name="text">
<string>-</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</item>
<item row="0" column="6">
<property name="text">
<string>-</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</item>
<item row="0" column="7">
<property name="text">
<string>-</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</item>
<item row="0" column="8">
<property name="text">
<string>-</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</item>
<item row="0" column="9">
<property name="text">
<string>-</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</item>
<item row="0" column="10">
<property name="text">
<string>-</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</item>
<item row="0" column="11">
<property name="text">
<string>-</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</item>
<item row="1" column="0">
<property name="text">
<string>-</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</item>
<item row="1" column="1">
<property name="text">
<string>-</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</item>
<item row="1" column="2">
<property name="text">
<string>-</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</item>
<item row="1" column="3">
<property name="text">
<string>-</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</item>
<item row="1" column="4">
<property name="text">
<string>-</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</item>
<item row="1" column="5">
<property name="text">
<string>-</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</item>
<item row="1" column="6">
<property name="text">
<string>-</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</item>
<item row="1" column="7">
<property name="text">
<string>-</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</item>
<item row="1" column="8">
<property name="text">
<string>-</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</item>
<item row="1" column="9">
<property name="text">
<string>-</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</item>
<item row="1" column="10">
<property name="text">
<string>-</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</item>
<item row="1" column="11">
<property name="text">
<string>-</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</item>
<item row="2" column="0">
<property name="text">
<string>-</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</item>
<item row="2" column="1">
<property name="text">
<string>-</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</item>
<item row="2" column="2">
<property name="text">
<string>-</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</item>
<item row="2" column="3">
<property name="text">
<string>-</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</item>
<item row="2" column="4">
<property name="text">
<string>-</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</item>
<item row="2" column="5">
<property name="text">
<string>-</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</item>
<item row="2" column="6">
<property name="text">
<string>-</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</item>
<item row="2" column="7">
<property name="text">
<string>-</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</item>
<item row="2" column="8">
<property name="text">
<string>-</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</item>
<item row="2" column="9">
<property name="text">
<string>-</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</item>
<item row="2" column="10">
<property name="text">
<string>-</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</item>
<item row="2" column="11">
<property name="text">
<string>-</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</item>
<item row="3" column="0">
<property name="text">
<string>-</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</item>
<item row="3" column="1">
<property name="text">
<string>-</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</item>
<item row="3" column="2">
<property name="text">
<string>-</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</item>
<item row="3" column="3">
<property name="text">
<string>-</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</item>
<item row="3" column="4">
<property name="text">
<string>-</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</item>
<item row="3" column="5">
<property name="text">
<string>-</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</item>
<item row="3" column="6">
<property name="text">
<string>-</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</item>
<item row="3" column="7">
<property name="text">
<string>-</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</item>
<item row="3" column="8">
<property name="text">
<string>-</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</item>
<item row="3" column="9">
<property name="text">
<string>-</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</item>
<item row="3" column="10">
<property name="text">
<string>-</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</item>
<item row="3" column="11">
<property name="text">
<string>-</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</item>
<item row="4" column="0">
<property name="text">
<string>-</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</item>
<item row="4" column="1">
<property name="text">
<string>-</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</item>
<item row="4" column="2">
<property name="text">
<string>-</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</item>
<item row="4" column="3">
<property name="text">
<string>-</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</item>
<item row="4" column="4">
<property name="text">
<string>-</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</item>
<item row="4" column="5">
<property name="text">
<string>-</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</item>
<item row="4" column="6">
<property name="text">
<string>-</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</item>
<item row="4" column="7">
<property name="text">
<string>-</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</item>
<item row="4" column="8">
<property name="text">
<string>-</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</item>
<item row="4" column="9">
<property name="text">
<string>-</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</item>
<item row="4" column="10">
<property name="text">
<string>-</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</item>
<item row="4" column="11">
<property name="text">
<string>-</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</item>
<item row="5" column="0">
<property name="text">
<string>-</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</item>
<item row="5" column="1">
<property name="text">
<string>-</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</item>
<item row="5" column="2">
<property name="text">
<string>-</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</item>
<item row="5" column="3">
<property name="text">
<string>-</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</item>
<item row="5" column="4">
<property name="text">
<string>-</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</item>
<item row="5" column="5">
<property name="text">
<string>-</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</item>
<item row="5" column="6">
<property name="text">
<string>-</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</item>
<item row="5" column="7">
<property name="text">
<string>-</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</item>
<item row="5" column="8">
<property name="text">
<string>-</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</item>
<item row="5" column="9">
<property name="text">
<string>-</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</item>
<item row="5" column="10">
<property name="text">
<string>-</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</item>
<item row="5" column="11">
<property name="text">
<string>-</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</item>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>MixerCurve</class>
<extends>QWidget</extends>
<header location="global">mixercurve.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<resources>
<include location="../coreplugin/core.qrc"/>
</resources>
<connections/>
</ui>

View File

@ -0,0 +1,507 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>FixedWingConfigWidget</class>
<widget class="QWidget" name="FixedWingConfigWidget">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>880</width>
<height>608</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_10">
<property name="margin">
<number>0</number>
</property>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QLabel" name="label_5">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>Airplane type:</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="fixedWingType"/>
</item>
<item>
<spacer name="horizontalSpacer_3">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_4">
<property name="rightMargin">
<number>0</number>
</property>
<item>
<widget class="QGroupBox" name="channelBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>230</width>
<height>100</height>
</size>
</property>
<property name="title">
<string>Output Channel Assignments</string>
</property>
<layout class="QFormLayout" name="formLayout_3">
<property name="fieldGrowthPolicy">
<enum>QFormLayout::AllNonFixedFieldsGrow</enum>
</property>
<item row="0" column="0">
<widget class="QLabel" name="fwEngineLabel">
<property name="text">
<string>Engine</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QComboBox" name="fwEngineChannelBox">
<property name="toolTip">
<string>Select output channel for the engine</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="fwAileron1Label">
<property name="minimumSize">
<size>
<width>60</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>Aileron 1</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QComboBox" name="fwAileron1ChannelBox">
<property name="toolTip">
<string>Select output channel for the first aileron (or elevon)</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="fwAileron2Label">
<property name="enabled">
<bool>true</bool>
</property>
<property name="minimumSize">
<size>
<width>60</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>Aileron 2</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QComboBox" name="fwAileron2ChannelBox">
<property name="enabled">
<bool>true</bool>
</property>
<property name="toolTip">
<string>Select output channel for the second aileron (or elevon)</string>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="fwElevator1Label">
<property name="minimumSize">
<size>
<width>67</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>Elevator 1</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QComboBox" name="fwElevator1ChannelBox">
<property name="toolTip">
<string>Select output channel for the first elevator</string>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QLabel" name="fwElevator2Label">
<property name="enabled">
<bool>true</bool>
</property>
<property name="minimumSize">
<size>
<width>67</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>Elevator 2</string>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QComboBox" name="fwElevator2ChannelBox">
<property name="enabled">
<bool>true</bool>
</property>
<property name="toolTip">
<string>Select output channel for a secondary elevator</string>
</property>
</widget>
</item>
<item row="5" column="0">
<widget class="QLabel" name="fwRudder1Label">
<property name="text">
<string>Rudder 1</string>
</property>
</widget>
</item>
<item row="5" column="1">
<widget class="QComboBox" name="fwRudder1ChannelBox">
<property name="toolTip">
<string>Select output channel for the first rudder</string>
</property>
</widget>
</item>
<item row="6" column="0">
<widget class="QLabel" name="fwRudder2Label">
<property name="text">
<string>Rudder 2</string>
</property>
</widget>
</item>
<item row="6" column="1">
<widget class="QComboBox" name="fwRudder2ChannelBox">
<property name="toolTip">
<string>Select output channel for a secondary rudder</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="elevonMixBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="title">
<string>Elevon Mix</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_13">
<item>
<layout class="QHBoxLayout" name="horizontalLayout_8">
<item>
<layout class="QVBoxLayout" name="verticalLayout_14">
<item>
<widget class="QLabel" name="elevonLabel1">
<property name="minimumSize">
<size>
<width>65</width>
<height>0</height>
</size>
</property>
<property name="styleSheet">
<string notr="true">background-color: qlineargradient(spread:reflect, x1:0.507, y1:0, x2:0.507, y2:0.772, stop:0.208955 rgba(74, 74, 74, 255), stop:0.78607 rgba(36, 36, 36, 255));
color: rgb(255, 255, 255);
border-radius: 5;
font: bold 12px;
margin:1px;</string>
</property>
<property name="text">
<string>Rudder %</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QSlider" name="elevonSlider1">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="MinimumExpanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximum">
<number>100</number>
</property>
<property name="value">
<number>50</number>
</property>
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="elevonSliderLabel1">
<property name="text">
<string>50</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QVBoxLayout" name="verticalLayout_15">
<item>
<widget class="QLabel" name="elevonLabel2">
<property name="minimumSize">
<size>
<width>65</width>
<height>0</height>
</size>
</property>
<property name="styleSheet">
<string notr="true">background-color: qlineargradient(spread:reflect, x1:0.507, y1:0, x2:0.507, y2:0.772, stop:0.208955 rgba(74, 74, 74, 255), stop:0.78607 rgba(36, 36, 36, 255));
color: rgb(255, 255, 255);
border-radius: 5;
font: bold 12px;
margin:1px;</string>
</property>
<property name="text">
<string>Pitch %</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QSlider" name="elevonSlider2">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="MinimumExpanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximum">
<number>100</number>
</property>
<property name="value">
<number>50</number>
</property>
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="elevonSliderLabel2">
<property name="text">
<string>50</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="throttleCurveBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>100</verstretch>
</sizepolicy>
</property>
<property name="title">
<string>Throttle Curve</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_16">
<item>
<widget class="MixerCurve" name="fixedWingThrottle" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>1</horstretch>
<verstretch>1</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>500</width>
<height>500</height>
</size>
</property>
<property name="sizeIncrement">
<size>
<width>10</width>
<height>10</height>
</size>
</property>
<property name="baseSize">
<size>
<width>300</width>
<height>350</height>
</size>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>0</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item>
<layout class="QHBoxLayout" name="bottomLayout">
<item>
<spacer name="horizontalSpacer_11">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="fwStatusLabel">
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>Mixer OK</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>MixerCurve</class>
<extends>QWidget</extends>
<header location="global">mixercurve.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<resources>
<include location="../coreplugin/core.qrc"/>
</resources>
<connections>
<connection>
<sender>elevonSlider1</sender>
<signal>valueChanged(int)</signal>
<receiver>elevonSliderLabel1</receiver>
<slot>setNum(int)</slot>
<hints>
<hint type="sourcelabel">
<x>124</x>
<y>126</y>
</hint>
<hint type="destinationlabel">
<x>124</x>
<y>126</y>
</hint>
</hints>
</connection>
<connection>
<sender>elevonSlider2</sender>
<signal>valueChanged(int)</signal>
<receiver>elevonSliderLabel2</receiver>
<slot>setNum(int)</slot>
<hints>
<hint type="sourcelabel">
<x>362</x>
<y>299</y>
</hint>
<hint type="destinationlabel">
<x>124</x>
<y>126</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View File

@ -0,0 +1,569 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>GroundConfigWidget</class>
<widget class="QWidget" name="GroundConfigWidget">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>880</width>
<height>608</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_10">
<property name="margin">
<number>0</number>
</property>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="label_51">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>Vehicle type:</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="groundVehicleType"/>
</item>
<item>
<spacer name="horizontalSpacer_31">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_41">
<property name="rightMargin">
<number>0</number>
</property>
<item>
<widget class="QGroupBox" name="groupBox_7">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="title">
<string>Output channel assignments</string>
</property>
<layout class="QFormLayout" name="formLayout_5">
<item row="0" column="0">
<widget class="QLabel" name="gvEngineLabel">
<property name="minimumSize">
<size>
<width>77</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>Engine</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QComboBox" name="gvEngineChannelBox">
<property name="toolTip">
<string>Select output channel for the engine</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="gvAileron1Label">
<property name="minimumSize">
<size>
<width>60</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>Aileron 1</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QComboBox" name="gvAileron1ChannelBox">
<property name="toolTip">
<string>Select output channel for the first aileron (or elevon)</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="gvAileron2Label">
<property name="enabled">
<bool>true</bool>
</property>
<property name="minimumSize">
<size>
<width>60</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>Aileron 2</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QComboBox" name="gvAileron2ChannelBox">
<property name="enabled">
<bool>true</bool>
</property>
<property name="toolTip">
<string>Select output channel for the second aileron (or elevon)</string>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="gvMotor1Label">
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>Motor</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QComboBox" name="gvMotor1ChannelBox">
<property name="toolTip">
<string>Select output channel for the first motor</string>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QLabel" name="gvMotor2Label">
<property name="enabled">
<bool>true</bool>
</property>
<property name="minimumSize">
<size>
<width>47</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>Motor 2</string>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QComboBox" name="gvMotor2ChannelBox">
<property name="enabled">
<bool>true</bool>
</property>
<property name="toolTip">
<string>Select output channel for a second motor</string>
</property>
</widget>
</item>
<item row="5" column="0">
<widget class="QLabel" name="gvSteering1Label">
<property name="text">
<string>Front Steering</string>
</property>
</widget>
</item>
<item row="5" column="1">
<widget class="QComboBox" name="gvSteering1ChannelBox">
<property name="toolTip">
<string>Select output channel for the first steering actuator</string>
</property>
</widget>
</item>
<item row="6" column="0">
<widget class="QLabel" name="gvSteering2Label">
<property name="text">
<string>Rear Steering</string>
</property>
</widget>
</item>
<item row="6" column="1">
<widget class="QComboBox" name="gvSteering2ChannelBox">
<property name="toolTip">
<string>Select output channel for a second steering actuator</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="differentialSteeringMixBox">
<property name="enabled">
<bool>true</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="title">
<string>Differential Steering Mix</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_33">
<item>
<layout class="QHBoxLayout" name="horizontalLayout_30">
<item>
<layout class="QVBoxLayout" name="diffSteering1Layout">
<item>
<widget class="QLabel" name="differentialSteeringLabel1">
<property name="minimumSize">
<size>
<width>65</width>
<height>0</height>
</size>
</property>
<property name="font">
<font>
<pointsize>-1</pointsize>
<weight>75</weight>
<italic>false</italic>
<bold>true</bold>
</font>
</property>
<property name="styleSheet">
<string notr="true">background-color: qlineargradient(spread:reflect, x1:0.507, y1:0, x2:0.507, y2:0.772, stop:0.208955 rgba(74, 74, 74, 255), stop:0.78607 rgba(36, 36, 36, 255));
color: rgb(255, 255, 255);
border-radius: 5;
font: bold 12px;
margin:1px;</string>
</property>
<property name="text">
<string>Left %</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QSlider" name="differentialSteeringSlider1">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="MinimumExpanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximum">
<number>100</number>
</property>
<property name="value">
<number>50</number>
</property>
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="gvDiffSteering1Label">
<property name="text">
<string>50</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QVBoxLayout" name="diffSteering2Layout">
<item>
<widget class="QLabel" name="differentialSteeringLabel2">
<property name="minimumSize">
<size>
<width>65</width>
<height>0</height>
</size>
</property>
<property name="styleSheet">
<string notr="true">background-color: qlineargradient(spread:reflect, x1:0.507, y1:0, x2:0.507, y2:0.772, stop:0.208955 rgba(74, 74, 74, 255), stop:0.78607 rgba(36, 36, 36, 255));
color: rgb(255, 255, 255);
border-radius: 5;
font: bold 12px;
margin:1px;</string>
</property>
<property name="text">
<string>Right %</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QSlider" name="differentialSteeringSlider2">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="MinimumExpanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximum">
<number>100</number>
</property>
<property name="value">
<number>50</number>
</property>
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="gvDiffSteering2Label">
<property name="text">
<string>50</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="gvThrottleCurve1GroupBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>100</verstretch>
</sizepolicy>
</property>
<property name="title">
<string>Front throttle curve</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_36">
<item>
<widget class="MixerCurve" name="groundVehicleThrottle1" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>16777215</height>
</size>
</property>
<property name="sizeIncrement">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="baseSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="gvThrottleCurve2GroupBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="title">
<string>Rear throttle curve</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_37">
<item>
<widget class="MixerCurve" name="groundVehicleThrottle2" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>16777215</height>
</size>
</property>
<property name="sizeIncrement">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="baseSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_28">
<item>
<spacer name="horizontalSpacer_21">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="gvStatusLabel">
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>Mixer OK</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>MixerCurve</class>
<extends>QWidget</extends>
<header location="global">mixercurve.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<resources>
<include location="../coreplugin/core.qrc"/>
</resources>
<connections>
<connection>
<sender>differentialSteeringSlider1</sender>
<signal>valueChanged(int)</signal>
<receiver>gvDiffSteering1Label</receiver>
<slot>setNum(int)</slot>
<hints>
<hint type="sourcelabel">
<x>124</x>
<y>126</y>
</hint>
<hint type="destinationlabel">
<x>315</x>
<y>391</y>
</hint>
</hints>
</connection>
<connection>
<sender>differentialSteeringSlider2</sender>
<signal>valueChanged(int)</signal>
<receiver>gvDiffSteering2Label</receiver>
<slot>setNum(int)</slot>
<hints>
<hint type="sourcelabel">
<x>124</x>
<y>126</y>
</hint>
<hint type="destinationlabel">
<x>390</x>
<y>391</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View File

@ -0,0 +1,860 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MultiRotorConfigWidget</class>
<widget class="QWidget" name="MultiRotorConfigWidget">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>880</width>
<height>608</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<property name="margin">
<number>0</number>
</property>
<item row="2" column="0">
<widget class="QGroupBox" name="groupBox_10">
<property name="minimumSize">
<size>
<width>10</width>
<height>10</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>16777215</height>
</size>
</property>
<property name="title">
<string>Frame</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_8" stretch="1">
<property name="margin">
<number>9</number>
</property>
<item>
<widget class="QGraphicsView" name="quadShape">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>10</width>
<height>10</height>
</size>
</property>
<property name="styleSheet">
<string notr="true">background:transparent</string>
</property>
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Plain</enum>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="2" column="2">
<widget class="QGroupBox" name="groupBox_6">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>10</width>
<height>10</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>16777215</height>
</size>
</property>
<property name="title">
<string>Throttle Curve</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_9">
<property name="margin">
<number>9</number>
</property>
<item>
<widget class="MixerCurve" name="multiThrottleCurve" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>10</width>
<height>10</height>
</size>
</property>
<property name="sizeIncrement">
<size>
<width>10</width>
<height>10</height>
</size>
</property>
<property name="baseSize">
<size>
<width>50</width>
<height>50</height>
</size>
</property>
<property name="styleSheet">
<string notr="true">background:transparent</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="2" column="1">
<widget class="QGroupBox" name="mixLevelGroupBox">
<property name="maximumSize">
<size>
<width>16777215</width>
<height>16777215</height>
</size>
</property>
<property name="title">
<string>Mix Level</string>
</property>
<layout class="QGridLayout" name="gridLayout_2">
<property name="horizontalSpacing">
<number>0</number>
</property>
<property name="margin">
<number>9</number>
</property>
<item row="0" column="0">
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QLabel" name="label_42">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>40</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>16777215</height>
</size>
</property>
<property name="styleSheet">
<string notr="true">background-color: qlineargradient(spread:reflect, x1:0.507, y1:0, x2:0.507, y2:0.772, stop:0.208955 rgba(74, 74, 74, 255), stop:0.78607 rgba(36, 36, 36, 255));
color: rgb(255, 255, 255);
border-radius: 5;
font: bold 12px;
margin:1px;</string>
</property>
<property name="text">
<string>Roll</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QSlider" name="mrRollMixLevel">
<property name="minimumSize">
<size>
<width>40</width>
<height>0</height>
</size>
</property>
<property name="toolTip">
<string>Weight of Roll mixing in percent.
Typical values are 100% for + configuration and 50% for X configuration on quads.</string>
</property>
<property name="maximum">
<number>100</number>
</property>
<property name="value">
<number>50</number>
</property>
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="mrRollMixValue">
<property name="minimumSize">
<size>
<width>40</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>50</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
</layout>
</item>
<item row="0" column="1">
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QLabel" name="label_40">
<property name="minimumSize">
<size>
<width>40</width>
<height>0</height>
</size>
</property>
<property name="styleSheet">
<string notr="true">background-color: qlineargradient(spread:reflect, x1:0.507, y1:0, x2:0.507, y2:0.772, stop:0.208955 rgba(74, 74, 74, 255), stop:0.78607 rgba(36, 36, 36, 255));
color: rgb(255, 255, 255);
border-radius: 5;
font: bold 12px;
margin:1px;</string>
</property>
<property name="text">
<string>Pitch</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QSlider" name="mrPitchMixLevel">
<property name="minimumSize">
<size>
<width>40</width>
<height>0</height>
</size>
</property>
<property name="toolTip">
<string>Weight of Pitch mixing in percent.
Typical values are 100% for + configuration and 50% for X configuration on quads.</string>
</property>
<property name="maximum">
<number>100</number>
</property>
<property name="value">
<number>50</number>
</property>
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="mrPitchMixValue">
<property name="minimumSize">
<size>
<width>40</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>50</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
</layout>
</item>
<item row="0" column="2">
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<widget class="QLabel" name="label_6">
<property name="minimumSize">
<size>
<width>40</width>
<height>0</height>
</size>
</property>
<property name="autoFillBackground">
<bool>false</bool>
</property>
<property name="styleSheet">
<string notr="true">background-color: qlineargradient(spread:reflect, x1:0.507, y1:0, x2:0.507, y2:0.772, stop:0.208955 rgba(74, 74, 74, 255), stop:0.78607 rgba(36, 36, 36, 255));
color: rgb(255, 255, 255);
border-radius: 5;
font: bold 12px;
margin:1px;</string>
</property>
<property name="text">
<string>Yaw</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QSlider" name="mrYawMixLevel">
<property name="minimumSize">
<size>
<width>40</width>
<height>0</height>
</size>
</property>
<property name="toolTip">
<string>Weight of Yaw mixing in percent.
Typical value is 50% for + or X configuration on quads.</string>
</property>
<property name="minimum">
<number>0</number>
</property>
<property name="maximum">
<number>100</number>
</property>
<property name="value">
<number>50</number>
</property>
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="mrYawMixValue">
<property name="minimumSize">
<size>
<width>40</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>50</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</item>
<item row="0" column="0" colspan="3">
<layout class="QHBoxLayout" name="horizontalLayout_7">
<property name="sizeConstraint">
<enum>QLayout::SetFixedSize</enum>
</property>
<item>
<widget class="QLabel" name="label">
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>Frame Type:</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="multirotorFrameType">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Minimum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>25</width>
<height>25</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>25</height>
</size>
</property>
<property name="toolTip">
<string>Select the Multirotor frame type here.</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_5">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>10</width>
<height>13</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item row="4" column="0" colspan="3">
<layout class="QHBoxLayout" name="horizontalLayout_6">
<item>
<spacer name="horizontalSpacer_6">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>10</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="mrStatusLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>Mixer OK</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
</property>
</widget>
</item>
</layout>
</item>
<item row="3" column="0" colspan="3">
<widget class="QGroupBox" name="groupBox_2">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>140</height>
</size>
</property>
<property name="title">
<string>Motor output channels</string>
</property>
<layout class="QGridLayout" name="gridLayout_7" columnstretch="1,1,0,0,1">
<property name="margin">
<number>9</number>
</property>
<item row="0" column="0" rowspan="5">
<layout class="QFormLayout" name="formLayout_3">
<property name="sizeConstraint">
<enum>QLayout::SetMaximumSize</enum>
</property>
<property name="fieldGrowthPolicy">
<enum>QFormLayout::AllNonFixedFieldsGrow</enum>
</property>
<property name="verticalSpacing">
<number>6</number>
</property>
<item row="0" column="0">
<widget class="QLabel" name="MotorOutputLabel1_2">
<property name="styleSheet">
<string notr="true">background-color: qlineargradient(spread:reflect, x1:0.507, y1:0, x2:0.507, y2:0.772, stop:0.208955 rgba(74, 74, 74, 255), stop:0.78607 rgba(36, 36, 36, 255));
color: rgb(255, 255, 255);
border-radius: 5;
font: bold 12px;
margin:1px;</string>
</property>
<property name="text">
<string>1</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QComboBox" name="multiMotorChannelBox1">
<property name="toolTip">
<string>Assign your motor output channels using the drawing above as a reference. Respect propeller rotation.</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_13">
<property name="styleSheet">
<string notr="true">background-color: qlineargradient(spread:reflect, x1:0.507, y1:0, x2:0.507, y2:0.772, stop:0.208955 rgba(74, 74, 74, 255), stop:0.78607 rgba(36, 36, 36, 255));
color: rgb(255, 255, 255);
border-radius: 5;
font: bold 12px;
margin:1px;</string>
</property>
<property name="text">
<string>2</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QComboBox" name="multiMotorChannelBox2">
<property name="toolTip">
<string>Assign your motor output channels using the drawing above as a reference. Respect propeller rotation.</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_14">
<property name="styleSheet">
<string notr="true">background-color: qlineargradient(spread:reflect, x1:0.507, y1:0, x2:0.507, y2:0.772, stop:0.208955 rgba(74, 74, 74, 255), stop:0.78607 rgba(36, 36, 36, 255));
color: rgb(255, 255, 255);
border-radius: 5;
font: bold 12px;
margin:1px;</string>
</property>
<property name="text">
<string>3</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QComboBox" name="multiMotorChannelBox3">
<property name="toolTip">
<string>Assign your motor output channels using the drawing above as a reference. Respect propeller rotation.</string>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_15">
<property name="styleSheet">
<string notr="true">background-color: qlineargradient(spread:reflect, x1:0.507, y1:0, x2:0.507, y2:0.772, stop:0.208955 rgba(74, 74, 74, 255), stop:0.78607 rgba(36, 36, 36, 255));
color: rgb(255, 255, 255);
border-radius: 5;
font: bold 12px;
margin:1px;</string>
</property>
<property name="text">
<string>4</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QComboBox" name="multiMotorChannelBox4">
<property name="toolTip">
<string>Assign your motor output channels using the drawing above as a reference. Respect propeller rotation.</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="0" column="1" rowspan="5">
<layout class="QFormLayout" name="formLayout_5">
<property name="sizeConstraint">
<enum>QLayout::SetMaximumSize</enum>
</property>
<property name="fieldGrowthPolicy">
<enum>QFormLayout::AllNonFixedFieldsGrow</enum>
</property>
<property name="verticalSpacing">
<number>6</number>
</property>
<item row="0" column="0">
<widget class="QLabel" name="label_18">
<property name="styleSheet">
<string notr="true">background-color: qlineargradient(spread:reflect, x1:0.507, y1:0, x2:0.507, y2:0.772, stop:0.208955 rgba(74, 74, 74, 255), stop:0.78607 rgba(36, 36, 36, 255));
color: rgb(255, 255, 255);
border-radius: 5;
font: bold 12px;
margin:1px;</string>
</property>
<property name="text">
<string>5</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QComboBox" name="multiMotorChannelBox5">
<property name="enabled">
<bool>true</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="toolTip">
<string>Assign your motor output channels using the drawing above as a reference. Respect propeller rotation.</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_19">
<property name="styleSheet">
<string notr="true">background-color: qlineargradient(spread:reflect, x1:0.507, y1:0, x2:0.507, y2:0.772, stop:0.208955 rgba(74, 74, 74, 255), stop:0.78607 rgba(36, 36, 36, 255));
color: rgb(255, 255, 255);
border-radius: 5;
font: bold 12px;
margin:1px;</string>
</property>
<property name="text">
<string>6</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QComboBox" name="multiMotorChannelBox6">
<property name="enabled">
<bool>true</bool>
</property>
<property name="toolTip">
<string>Assign your motor output channels using the drawing above as a reference. Respect propeller rotation.</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_20">
<property name="styleSheet">
<string notr="true">background-color: qlineargradient(spread:reflect, x1:0.507, y1:0, x2:0.507, y2:0.772, stop:0.208955 rgba(74, 74, 74, 255), stop:0.78607 rgba(36, 36, 36, 255));
color: rgb(255, 255, 255);
border-radius: 5;
font: bold 12px;
margin:1px;</string>
</property>
<property name="text">
<string>7</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QComboBox" name="multiMotorChannelBox7">
<property name="enabled">
<bool>true</bool>
</property>
<property name="toolTip">
<string>Assign your motor output channels using the drawing above as a reference. Respect propeller rotation.</string>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_21">
<property name="styleSheet">
<string notr="true">background-color: qlineargradient(spread:reflect, x1:0.507, y1:0, x2:0.507, y2:0.772, stop:0.208955 rgba(74, 74, 74, 255), stop:0.78607 rgba(36, 36, 36, 255));
color: rgb(255, 255, 255);
border-radius: 5;
font: bold 12px;
margin:1px;</string>
</property>
<property name="text">
<string>8</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QComboBox" name="multiMotorChannelBox8">
<property name="enabled">
<bool>true</bool>
</property>
<property name="toolTip">
<string>Assign your motor output channels using the drawing above as a reference. Respect propeller rotation.</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="0" column="2" rowspan="5" colspan="2">
<widget class="Line" name="line_2">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
</widget>
</item>
<item row="2" column="4">
<widget class="QLabel" name="label_4">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>16</height>
</size>
</property>
<property name="styleSheet">
<string notr="true">background-color: qlineargradient(spread:reflect, x1:0.507, y1:0, x2:0.507, y2:0.772, stop:0.208955 rgba(74, 74, 74, 255), stop:0.78607 rgba(36, 36, 36, 255));
color: rgb(255, 255, 255);
border-radius: 5;
font: bold 12px;
margin:1px;</string>
</property>
<property name="text">
<string>Multirotor Motor Direction</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item row="1" column="4">
<widget class="QComboBox" name="triYawChannelBox">
<property name="enabled">
<bool>true</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>40</width>
<height>0</height>
</size>
</property>
</widget>
</item>
<item row="0" column="4">
<widget class="QLabel" name="label_5">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>16</height>
</size>
</property>
<property name="styleSheet">
<string notr="true">background-color: qlineargradient(spread:reflect, x1:0.507, y1:0, x2:0.507, y2:0.772, stop:0.208955 rgba(74, 74, 74, 255), stop:0.78607 rgba(36, 36, 36, 255));
color: rgb(255, 255, 255);
border-radius: 5;
font: bold 12px;
margin:1px;</string>
</property>
<property name="text">
<string>Tricopter Yaw Servo channel</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item row="3" column="4">
<widget class="QCheckBox" name="MultirotorRevMixerCheckBox">
<property name="text">
<string>Reverse all motors</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>MixerCurve</class>
<extends>QWidget</extends>
<header location="global">mixercurve.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<resources>
<include location="../coreplugin/core.qrc"/>
</resources>
<connections>
<connection>
<sender>mrRollMixLevel</sender>
<signal>valueChanged(int)</signal>
<receiver>mrRollMixValue</receiver>
<slot>setNum(int)</slot>
<hints>
<hint type="sourcelabel">
<x>42</x>
<y>220</y>
</hint>
<hint type="destinationlabel">
<x>43</x>
<y>171</y>
</hint>
</hints>
</connection>
<connection>
<sender>mrYawMixLevel</sender>
<signal>valueChanged(int)</signal>
<receiver>mrYawMixValue</receiver>
<slot>setNum(int)</slot>
<hints>
<hint type="sourcelabel">
<x>120</x>
<y>254</y>
</hint>
<hint type="destinationlabel">
<x>121</x>
<y>172</y>
</hint>
</hints>
</connection>
<connection>
<sender>mrPitchMixLevel</sender>
<signal>valueChanged(int)</signal>
<receiver>mrPitchMixValue</receiver>
<slot>setNum(int)</slot>
<hints>
<hint type="sourcelabel">
<x>92</x>
<y>222</y>
</hint>
<hint type="destinationlabel">
<x>92</x>
<y>151</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View File

@ -25,6 +25,9 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/ */
#include "configccpmwidget.h" #include "configccpmwidget.h"
#include "mixersettings.h"
#include "systemsettings.h"
#include "actuatorcommand.h"
#include <QDebug> #include <QDebug>
#include <QStringList> #include <QStringList>
@ -33,52 +36,122 @@
#include <QtGui/QVBoxLayout> #include <QtGui/QVBoxLayout>
#include <QtGui/QPushButton> #include <QtGui/QPushButton>
#include <QBrush> #include <QBrush>
#include <math.h>
#include <QMessageBox> #include <QMessageBox>
#include "mixersettings.h" #include <math.h>
#include "systemsettings.h"
#include "actuatorcommand.h"
#define Pi 3.14159265358979323846 #define Pi 3.14159265358979323846
QStringList ConfigCcpmWidget::getChannelDescriptions()
ConfigCcpmWidget::ConfigCcpmWidget(QWidget *parent) : VehicleConfig(parent)
{ {
int i; // init a channel_numelem list of channel desc defaults
SwashLvlConfigurationInProgress=0; QStringList channelDesc;
SwashLvlState=0; for (int i = 0; i < (int) ConfigCcpmWidget::CHANNEL_NUMELEM; i++) {
SwashLvlServoInterlock=0; channelDesc.append(QString("-"));
updatingFromHardware=FALSE; }
updatingToHardware=FALSE;
m_ccpm = new Ui_ccpmWidget(); // get the gui config data
m_ccpm->setupUi(this); GUIConfigDataUnion configData = getConfigData();
heliGUISettingsStruct heli = configData.heli;
if (heli.Throttle > 0) {
channelDesc[heli.Throttle - 1] = QString("Throttle");
}
if (heli.Tail > 0) {
channelDesc[heli.Tail - 1] = QString("Tail");
}
switch (heli.FirstServoIndex) {
case 0:
// front
if (heli.ServoIndexW > 0) {
channelDesc[heli.ServoIndexW - 1] = QString("Elevator");
}
if (heli.ServoIndexX > 0) {
channelDesc[heli.ServoIndexX - 1] = QString("Roll1");
}
if (heli.ServoIndexY > 0) {
channelDesc[heli.ServoIndexY - 1] = QString("Roll2");
}
break;
case 1:
// right
if (heli.ServoIndexW > 0) {
channelDesc[heli.ServoIndexW - 1] = QString("ServoW");
}
if (heli.ServoIndexX > 0) {
channelDesc[heli.ServoIndexX - 1] = QString("ServoX");
}
if (heli.ServoIndexY > 0) {
channelDesc[heli.ServoIndexY - 1] = QString("ServoY");
}
break;
case 2:
// rear
if (heli.ServoIndexW > 0) {
channelDesc[heli.ServoIndexW - 1] = QString("Elevator");
}
if (heli.ServoIndexX > 0) {
channelDesc[heli.ServoIndexX - 1] = QString("Roll1");
}
if (heli.ServoIndexY > 0) {
channelDesc[heli.ServoIndexY - 1] = QString("Roll2");
}
break;
case 3:
// left
if (heli.ServoIndexW > 0) {
channelDesc[heli.ServoIndexW - 1] = QString("ServoW");
}
if (heli.ServoIndexX > 0) {
channelDesc[heli.ServoIndexX - 1] = QString("ServoX");
}
if (heli.ServoIndexY > 0) {
channelDesc[heli.ServoIndexY - 1] = QString("ServoY");
}
break;
}
if (heli.ServoIndexZ > 0) {
channelDesc[heli.ServoIndexZ - 1] = QString("ServoZ");
}
return channelDesc;
}
ConfigCcpmWidget::ConfigCcpmWidget(QWidget *parent) :
VehicleConfig(parent), m_aircraft(new Ui_CcpmConfigWidget())
{
m_aircraft->setupUi(this);
SwashLvlConfigurationInProgress = 0;
SwashLvlState = 0;
SwashLvlServoInterlock = 0;
updatingFromHardware = FALSE;
updatingToHardware = FALSE;
// Initialization of the swashplaye widget // Initialization of the swashplaye widget
m_ccpm->SwashplateImage->setScene(new QGraphicsScene(this)); m_aircraft->SwashplateImage->setScene(new QGraphicsScene(this));
m_ccpm->SwashLvlSwashplateImage->setScene(m_ccpm->SwashplateImage->scene()); m_aircraft->SwashLvlSwashplateImage->setScene(m_aircraft->SwashplateImage->scene());
m_ccpm->SwashLvlSwashplateImage->setSceneRect(-50,-50,500,500); m_aircraft->SwashLvlSwashplateImage->setSceneRect(-50, -50, 500, 500);
//m_ccpm->SwashLvlSwashplateImage->scale(.85,.85); //m_aircraft->SwashLvlSwashplateImage->scale(.85,.85);
//m_ccpm->SwashplateImage->setSceneRect(SwashplateImg->boundingRect()); //m_aircraft->SwashplateImage->setSceneRect(SwashplateImg->boundingRect());
m_ccpm->SwashplateImage->setSceneRect(-50,-30,500,500); m_aircraft->SwashplateImage->setSceneRect(-50, -30, 500, 500);
//m_ccpm->SwashplateImage->scale(.85,.85); //m_aircraft->SwashplateImage->scale(.85,.85);
QSvgRenderer *renderer = new QSvgRenderer(); QSvgRenderer *renderer = new QSvgRenderer();
renderer->load(QString(":/configgadget/images/ccpm_setup.svg")); renderer->load(QString(":/configgadget/images/ccpm_setup.svg"));
SwashplateImg = new QGraphicsSvgItem(); SwashplateImg = new QGraphicsSvgItem();
SwashplateImg->setSharedRenderer(renderer); SwashplateImg->setSharedRenderer(renderer);
SwashplateImg->setElementId("Swashplate"); SwashplateImg->setElementId("Swashplate");
SwashplateImg->setObjectName("Swashplate"); SwashplateImg->setObjectName("Swashplate");
//SwashplateImg->setScale(0.75); //SwashplateImg->setScale(0.75);
m_ccpm->SwashplateImage->scene()->addItem(SwashplateImg); m_aircraft->SwashplateImage->scene()->addItem(SwashplateImg);
QFont serifFont("Times", 24, QFont::Bold); QFont serifFont("Times", 24, QFont::Bold);
QPen pen; // creates a default pen // creates a default pen
QPen pen;
pen.setStyle(Qt::DotLine); pen.setStyle(Qt::DotLine);
pen.setWidth(2); pen.setWidth(2);
@ -86,9 +159,9 @@ ConfigCcpmWidget::ConfigCcpmWidget(QWidget *parent) : VehicleConfig(parent)
pen.setCapStyle(Qt::RoundCap); pen.setCapStyle(Qt::RoundCap);
pen.setJoinStyle(Qt::RoundJoin); pen.setJoinStyle(Qt::RoundJoin);
QBrush brush(Qt::darkBlue); QBrush brush(Qt::darkBlue);
QPen pen2; // creates a default pen // creates a default pen
QPen pen2;
//pen2.setStyle(Qt::DotLine); //pen2.setStyle(Qt::DotLine);
pen2.setWidth(1); pen2.setWidth(1);
@ -96,113 +169,107 @@ ConfigCcpmWidget::ConfigCcpmWidget(QWidget *parent) : VehicleConfig(parent)
//pen2.setCapStyle(Qt::RoundCap); //pen2.setCapStyle(Qt::RoundCap);
//pen2.setJoinStyle(Qt::RoundJoin); //pen2.setJoinStyle(Qt::RoundJoin);
//brush.setStyle(Qt::RadialGradientPattern);
//brush.setStyle(Qt::RadialGradientPattern);
QList<QString> ServoNames; QList<QString> ServoNames;
ServoNames << "ServoW" << "ServoX" << "ServoY" << "ServoZ" ; ServoNames << "ServoW" << "ServoX" << "ServoY" << "ServoZ";
for (i=0;i<CCPM_MAX_SWASH_SERVOS;i++) for (int i = 0; i < CCPM_MAX_SWASH_SERVOS; i++) {
{ ServoLines[i] = m_aircraft->SwashLvlSwashplateImage->scene()->addLine(0, 0, 100 * i, i * i * 100, pen);
ServoLines[i] = m_ccpm->SwashLvlSwashplateImage->scene()->addLine(0,0,100*i,i*i*100,pen);
Servos[i] = new QGraphicsSvgItem(); Servos[i] = new QGraphicsSvgItem();
Servos[i]->setSharedRenderer(renderer); Servos[i]->setSharedRenderer(renderer);
Servos[i]->setElementId(ServoNames.at(i)); Servos[i]->setElementId(ServoNames.at(i));
m_ccpm->SwashplateImage->scene()->addItem(Servos[i]); m_aircraft->SwashplateImage->scene()->addItem(Servos[i]);
ServosText[i] = new QGraphicsTextItem(); ServosText[i] = new QGraphicsTextItem();
ServosText[i]->setDefaultTextColor(Qt::yellow); ServosText[i]->setDefaultTextColor(Qt::yellow);
ServosText[i]->setPlainText(QString("-")); ServosText[i]->setPlainText(QString("-"));
ServosText[i]->setFont(serifFont); ServosText[i]->setFont(serifFont);
ServosTextCircles[i] = new QGraphicsEllipseItem(1,1,30,30); ServosTextCircles[i] = new QGraphicsEllipseItem(1, 1, 30, 30);
ServosTextCircles[i]->setBrush(brush); ServosTextCircles[i]->setBrush(brush);
ServosTextCircles[i]->setPen(pen2); ServosTextCircles[i]->setPen(pen2);
m_ccpm->SwashplateImage->scene()->addItem(ServosTextCircles[i]); m_aircraft->SwashplateImage->scene()->addItem(ServosTextCircles[i]);
m_ccpm->SwashplateImage->scene()->addItem(ServosText[i]); m_aircraft->SwashplateImage->scene()->addItem(ServosText[i]);
SwashLvlSpinBoxes[i] = new QSpinBox(m_aircraft->SwashLvlSwashplateImage); // use QGraphicsView
m_aircraft->SwashLvlSwashplateImage->scene()->addWidget(SwashLvlSpinBoxes[i]);
SwashLvlSpinBoxes[i] = new QSpinBox(m_ccpm->SwashLvlSwashplateImage); // use QGraphicsView
m_ccpm->SwashLvlSwashplateImage->scene()->addWidget(SwashLvlSpinBoxes[i]);
SwashLvlSpinBoxes[i]->setMaximum(10000); SwashLvlSpinBoxes[i]->setMaximum(10000);
SwashLvlSpinBoxes[i]->setMinimum(0); SwashLvlSpinBoxes[i]->setMinimum(0);
SwashLvlSpinBoxes[i]->setValue(0); SwashLvlSpinBoxes[i]->setValue(0);
} }
//initialize our two mixer curves // initialize our two mixer curves
// mixercurve defaults to mixercurve_throttle // mixercurve defaults to mixercurve_throttle
m_ccpm->ThrottleCurve->initLinearCurve(5, 1.0, 0.0); m_aircraft->ThrottleCurve->initLinearCurve(5, 1.0, 0.0);
// tell mixercurve this is a pitch curve // tell mixercurve this is a pitch curve
m_ccpm->PitchCurve->setMixerType(MixerCurve::MIXERCURVE_PITCH); m_aircraft->PitchCurve->setMixerType(MixerCurve::MIXERCURVE_PITCH);
m_ccpm->PitchCurve->initLinearCurve(5, 1.0, -1.0); m_aircraft->PitchCurve->initLinearCurve(5, 1.0, -1.0);
//initialize channel names // initialize channel names
m_ccpm->ccpmEngineChannel->addItems(channelNames); m_aircraft->ccpmEngineChannel->addItems(channelNames);
m_ccpm->ccpmEngineChannel->setCurrentIndex(0); m_aircraft->ccpmEngineChannel->setCurrentIndex(0);
m_ccpm->ccpmTailChannel->addItems(channelNames); m_aircraft->ccpmTailChannel->addItems(channelNames);
m_ccpm->ccpmTailChannel->setCurrentIndex(0); m_aircraft->ccpmTailChannel->setCurrentIndex(0);
m_ccpm->ccpmServoWChannel->addItems(channelNames); m_aircraft->ccpmServoWChannel->addItems(channelNames);
m_ccpm->ccpmServoWChannel->setCurrentIndex(0); m_aircraft->ccpmServoWChannel->setCurrentIndex(0);
m_ccpm->ccpmServoXChannel->addItems(channelNames); m_aircraft->ccpmServoXChannel->addItems(channelNames);
m_ccpm->ccpmServoXChannel->setCurrentIndex(0); m_aircraft->ccpmServoXChannel->setCurrentIndex(0);
m_ccpm->ccpmServoYChannel->addItems(channelNames); m_aircraft->ccpmServoYChannel->addItems(channelNames);
m_ccpm->ccpmServoYChannel->setCurrentIndex(0); m_aircraft->ccpmServoYChannel->setCurrentIndex(0);
m_ccpm->ccpmServoZChannel->addItems(channelNames); m_aircraft->ccpmServoZChannel->addItems(channelNames);
m_ccpm->ccpmServoZChannel->setCurrentIndex(0); m_aircraft->ccpmServoZChannel->setCurrentIndex(0);
QStringList Types; QStringList Types;
Types << QString::fromUtf8("CCPM 2 Servo 90º") << QString::fromUtf8("CCPM 3 Servo 90º") << QString::fromUtf8("CCPM 4 Servo 90º") << Types << QString::fromUtf8("CCPM 2 Servo 90º") << QString::fromUtf8("CCPM 3 Servo 90º")
QString::fromUtf8("CCPM 3 Servo 120º") << QString::fromUtf8("CCPM 3 Servo 140º") << << QString::fromUtf8("CCPM 4 Servo 90º") << QString::fromUtf8("CCPM 3 Servo 120º")
QString::fromUtf8("FP 2 Servo 90º") << << QString::fromUtf8("CCPM 3 Servo 140º") << QString::fromUtf8("FP 2 Servo 90º")
QString::fromUtf8("Coax 2 Servo 90º") << << QString::fromUtf8("Coax 2 Servo 90º") << QString::fromUtf8("Custom - User Angles")
QString::fromUtf8("Custom - User Angles") << QString::fromUtf8("Custom - Advanced Settings"); << QString::fromUtf8("Custom - Advanced Settings");
m_ccpm->ccpmType->addItems(Types); m_aircraft->ccpmType->addItems(Types);
m_ccpm->ccpmType->setCurrentIndex(m_ccpm->ccpmType->count() - 1); m_aircraft->ccpmType->setCurrentIndex(m_aircraft->ccpmType->count() - 1);
refreshWidgetsValues(QString("HeliCP")); //refreshWidgetsValues(QString("HeliCP"));
UpdateType(); UpdateType();
connect(m_ccpm->ccpmAngleW, SIGNAL(valueChanged(double)), this, SLOT(ccpmSwashplateUpdate())); connect(m_aircraft->ccpmAngleW, SIGNAL(valueChanged(double)), this, SLOT(ccpmSwashplateUpdate()));
connect(m_ccpm->ccpmAngleX, SIGNAL(valueChanged(double)), this, SLOT(ccpmSwashplateUpdate())); connect(m_aircraft->ccpmAngleX, SIGNAL(valueChanged(double)), this, SLOT(ccpmSwashplateUpdate()));
connect(m_ccpm->ccpmAngleY, SIGNAL(valueChanged(double)), this, SLOT(ccpmSwashplateUpdate())); connect(m_aircraft->ccpmAngleY, SIGNAL(valueChanged(double)), this, SLOT(ccpmSwashplateUpdate()));
connect(m_ccpm->ccpmAngleZ, SIGNAL(valueChanged(double)), this, SLOT(ccpmSwashplateUpdate())); connect(m_aircraft->ccpmAngleZ, SIGNAL(valueChanged(double)), this, SLOT(ccpmSwashplateUpdate()));
connect(m_ccpm->ccpmCorrectionAngle, SIGNAL(valueChanged(double)), this, SLOT(ccpmSwashplateUpdate())); connect(m_aircraft->ccpmCorrectionAngle, SIGNAL(valueChanged(double)), this, SLOT(ccpmSwashplateUpdate()));
connect(m_ccpm->ccpmServoWChannel, SIGNAL(currentIndexChanged(int)), this, SLOT(ccpmSwashplateUpdate())); connect(m_aircraft->ccpmServoWChannel, SIGNAL(currentIndexChanged(int)), this, SLOT(ccpmSwashplateUpdate()));
connect(m_ccpm->ccpmServoXChannel, SIGNAL(currentIndexChanged(int)), this, SLOT(ccpmSwashplateUpdate())); connect(m_aircraft->ccpmServoXChannel, SIGNAL(currentIndexChanged(int)), this, SLOT(ccpmSwashplateUpdate()));
connect(m_ccpm->ccpmServoYChannel, SIGNAL(currentIndexChanged(int)), this, SLOT(ccpmSwashplateUpdate())); connect(m_aircraft->ccpmServoYChannel, SIGNAL(currentIndexChanged(int)), this, SLOT(ccpmSwashplateUpdate()));
connect(m_ccpm->ccpmServoZChannel, SIGNAL(currentIndexChanged(int)), this, SLOT(ccpmSwashplateUpdate())); connect(m_aircraft->ccpmServoZChannel, SIGNAL(currentIndexChanged(int)), this, SLOT(ccpmSwashplateUpdate()));
connect(m_ccpm->ccpmEngineChannel, SIGNAL(currentIndexChanged(int)), this, SLOT(UpdateMixer())); connect(m_aircraft->ccpmEngineChannel, SIGNAL(currentIndexChanged(int)), this, SLOT(UpdateMixer()));
connect(m_ccpm->ccpmTailChannel, SIGNAL(currentIndexChanged(int)), this, SLOT(UpdateMixer())); connect(m_aircraft->ccpmTailChannel, SIGNAL(currentIndexChanged(int)), this, SLOT(UpdateMixer()));
connect(m_ccpm->ccpmRevoSlider, SIGNAL(valueChanged(int)), this, SLOT(UpdateMixer())); connect(m_aircraft->ccpmRevoSlider, SIGNAL(valueChanged(int)), this, SLOT(UpdateMixer()));
connect(m_ccpm->ccpmREVOspinBox, SIGNAL(valueChanged(int)), this, SLOT(UpdateMixer())); connect(m_aircraft->ccpmREVOspinBox, SIGNAL(valueChanged(int)), this, SLOT(UpdateMixer()));
connect(m_ccpm->ccpmCollectiveSlider, SIGNAL(valueChanged(int)), this, SLOT(UpdateMixer())); connect(m_aircraft->ccpmCollectiveSlider, SIGNAL(valueChanged(int)), this, SLOT(UpdateMixer()));
connect(m_ccpm->ccpmCollectivespinBox, SIGNAL(valueChanged(int)), this, SLOT(UpdateMixer())); connect(m_aircraft->ccpmCollectivespinBox, SIGNAL(valueChanged(int)), this, SLOT(UpdateMixer()));
connect(m_ccpm->ccpmType, SIGNAL(currentIndexChanged(int)), this, SLOT(UpdateType())); connect(m_aircraft->ccpmType, SIGNAL(currentIndexChanged(int)), this, SLOT(UpdateType()));
connect(m_ccpm->ccpmSingleServo, SIGNAL(currentIndexChanged(int)), this, SLOT(UpdateType())); connect(m_aircraft->ccpmSingleServo, SIGNAL(currentIndexChanged(int)), this, SLOT(UpdateType()));
connect(m_ccpm->TabObject, SIGNAL(currentChanged ( QWidget * )), this, SLOT(UpdateType())); connect(m_aircraft->TabObject, SIGNAL(currentChanged ( QWidget * )), this, SLOT(UpdateType()));
connect(m_ccpm->SwashLvlStartButton, SIGNAL(clicked()), this, SLOT(SwashLvlStartButtonPressed())); connect(m_aircraft->SwashLvlStartButton, SIGNAL(clicked()), this, SLOT(SwashLvlStartButtonPressed()));
connect(m_ccpm->SwashLvlNextButton, SIGNAL(clicked()), this, SLOT(SwashLvlNextButtonPressed())); connect(m_aircraft->SwashLvlNextButton, SIGNAL(clicked()), this, SLOT(SwashLvlNextButtonPressed()));
connect(m_ccpm->SwashLvlCancelButton, SIGNAL(clicked()), this, SLOT(SwashLvlCancelButtonPressed())); connect(m_aircraft->SwashLvlCancelButton, SIGNAL(clicked()), this, SLOT(SwashLvlCancelButtonPressed()));
connect(m_ccpm->SwashLvlFinishButton, SIGNAL(clicked()), this, SLOT(SwashLvlFinishButtonPressed())); connect(m_aircraft->SwashLvlFinishButton, SIGNAL(clicked()), this, SLOT(SwashLvlFinishButtonPressed()));
connect(m_ccpm->ccpmCollectivePassthrough, SIGNAL(clicked()),this, SLOT(SetUIComponentVisibilities())); connect(m_aircraft->ccpmCollectivePassthrough, SIGNAL(clicked()), this, SLOT(SetUIComponentVisibilities()));
connect(m_ccpm->ccpmLinkCyclic, SIGNAL(clicked()), this, SLOT(SetUIComponentVisibilities())); connect(m_aircraft->ccpmLinkCyclic, SIGNAL(clicked()), this, SLOT(SetUIComponentVisibilities()));
connect(m_ccpm->ccpmLinkRoll, SIGNAL(clicked()), this, SLOT(SetUIComponentVisibilities())); connect(m_aircraft->ccpmLinkRoll, SIGNAL(clicked()), this, SLOT(SetUIComponentVisibilities()));
ccpmSwashplateRedraw();
ccpmSwashplateRedraw();
} }
ConfigCcpmWidget::~ConfigCcpmWidget() ConfigCcpmWidget::~ConfigCcpmWidget()
{ {
// Do nothing delete m_aircraft;
} }
void ConfigCcpmWidget::setupUI(QString frameType) void ConfigCcpmWidget::setupUI(QString frameType)
@ -210,7 +277,42 @@ void ConfigCcpmWidget::setupUI(QString frameType)
Q_UNUSED(frameType); Q_UNUSED(frameType);
} }
void ConfigCcpmWidget::ResetActuators(GUIConfigDataUnion* configData) void ConfigCcpmWidget::registerWidgets(ConfigTaskWidget &parent) {
parent.addWidget(m_aircraft->ccpmType);
parent.addWidget(m_aircraft->ccpmTailChannel);
parent.addWidget(m_aircraft->ccpmEngineChannel);
parent.addWidget(m_aircraft->ccpmServoWChannel);
parent.addWidget(m_aircraft->ccpmServoXChannel);
parent.addWidget(m_aircraft->ccpmServoYChannel);
parent.addWidget(m_aircraft->ccpmSingleServo);
parent.addWidget(m_aircraft->ccpmServoZChannel);
parent.addWidget(m_aircraft->ccpmAngleW);
parent.addWidget(m_aircraft->ccpmAngleX);
parent.addWidget(m_aircraft->ccpmCorrectionAngle);
parent.addWidget(m_aircraft->ccpmAngleZ);
parent.addWidget(m_aircraft->ccpmAngleY);
parent.addWidget(m_aircraft->ccpmCollectivePassthrough);
parent.addWidget(m_aircraft->ccpmLinkRoll);
parent.addWidget(m_aircraft->ccpmLinkCyclic);
parent.addWidget(m_aircraft->ccpmRevoSlider);
parent.addWidget(m_aircraft->ccpmREVOspinBox);
parent.addWidget(m_aircraft->ccpmCollectiveSlider);
parent.addWidget(m_aircraft->ccpmCollectivespinBox);
parent.addWidget(m_aircraft->ccpmCollectiveScale);
parent.addWidget(m_aircraft->ccpmCollectiveScaleBox);
parent.addWidget(m_aircraft->ccpmCyclicScale);
parent.addWidget(m_aircraft->ccpmPitchScale);
parent.addWidget(m_aircraft->ccpmPitchScaleBox);
parent.addWidget(m_aircraft->ccpmRollScale);
parent.addWidget(m_aircraft->ccpmRollScaleBox);
parent.addWidget(m_aircraft->SwashLvlPositionSlider);
parent.addWidget(m_aircraft->SwashLvlPositionSpinBox);
parent.addWidget(m_aircraft->ThrottleCurve->getCurveWidget());
parent.addWidget(m_aircraft->PitchCurve->getCurveWidget());
parent.addWidget(m_aircraft->ccpmAdvancedSettingsTable);
}
void ConfigCcpmWidget::resetActuators(GUIConfigDataUnion *configData)
{ {
configData->heli.Throttle = 0; configData->heli.Throttle = 0;
configData->heli.Tail = 0; configData->heli.Tail = 0;
@ -220,260 +322,225 @@ void ConfigCcpmWidget::ResetActuators(GUIConfigDataUnion* configData)
configData->heli.ServoIndexZ = 0; configData->heli.ServoIndexZ = 0;
} }
QStringList ConfigCcpmWidget::getChannelDescriptions() void ConfigCcpmWidget::refreshWidgetsValues(QString frameType)
{ {
int i; Q_UNUSED(frameType);
QStringList channelDesc;
// init a channel_numelem list of channel desc defaults setupUI(frameType);
for (i=0; i < (int)(ConfigCcpmWidget::CHANNEL_NUMELEM); i++)
{
channelDesc.append(QString("-"));
}
// get the gui config data GUIConfigDataUnion config = getConfigData();
GUIConfigDataUnion configData = GetConfigData();
heliGUISettingsStruct heli = configData.heli;
if (heli.Throttle > 0) // swashplate config
channelDesc[heli.Throttle - 1] = QString("Throttle"); setComboCurrentIndex(m_aircraft->ccpmType, m_aircraft->ccpmType->count() - (config.heli.SwashplateType + 1));
if (heli.Tail > 0) setComboCurrentIndex(m_aircraft->ccpmSingleServo, config.heli.FirstServoIndex);
channelDesc[heli.Tail - 1] = QString("Tail");
switch(heli.FirstServoIndex) // ccpm mixing options
{ m_aircraft->ccpmCollectivePassthrough->setChecked(config.heli.ccpmCollectivePassthroughState);
case 0: //front m_aircraft->ccpmLinkCyclic->setChecked(config.heli.ccpmLinkCyclicState);
if (heli.ServoIndexW > 0) m_aircraft->ccpmLinkRoll->setChecked(config.heli.ccpmLinkRollState);
channelDesc[heli.ServoIndexW - 1] = QString("Elevator");
if (heli.ServoIndexX > 0)
channelDesc[heli.ServoIndexX - 1] = QString("Roll1");
if (heli.ServoIndexY > 0)
channelDesc[heli.ServoIndexY - 1] = QString("Roll2");
break;
case 1: //right // correction angle
if (heli.ServoIndexW > 0) m_aircraft->ccpmCorrectionAngle->setValue(config.heli.CorrectionAngle);
channelDesc[heli.ServoIndexW - 1] = QString("ServoW");
if (heli.ServoIndexX > 0)
channelDesc[heli.ServoIndexX - 1] = QString("ServoX");
if (heli.ServoIndexY > 0)
channelDesc[heli.ServoIndexY - 1] = QString("ServoY");
break;
case 2: //rear // update sliders
if (heli.ServoIndexW > 0) m_aircraft->ccpmCollectiveScale->setValue(config.heli.SliderValue0);
channelDesc[heli.ServoIndexW - 1] = QString("Elevator"); m_aircraft->ccpmCollectiveScaleBox->setValue(config.heli.SliderValue0);
if (heli.ServoIndexX > 0) m_aircraft->ccpmCyclicScale->setValue(config.heli.SliderValue1);
channelDesc[heli.ServoIndexX - 1] = QString("Roll1"); m_aircraft->ccpmCyclicScaleBox->setValue(config.heli.SliderValue1);
if (heli.ServoIndexY > 0) m_aircraft->ccpmPitchScale->setValue(config.heli.SliderValue1);
channelDesc[heli.ServoIndexY - 1] = QString("Roll2"); m_aircraft->ccpmPitchScaleBox->setValue(config.heli.SliderValue1);
break; m_aircraft->ccpmRollScale->setValue(config.heli.SliderValue2);
m_aircraft->ccpmRollScaleBox->setValue(config.heli.SliderValue2);
m_aircraft->ccpmCollectiveSlider->setValue(config.heli.SliderValue0);
m_aircraft->ccpmCollectivespinBox->setValue(config.heli.SliderValue0);
case 3: //left // servo assignments
if (heli.ServoIndexW > 0) setComboCurrentIndex(m_aircraft->ccpmServoWChannel, config.heli.ServoIndexW);
channelDesc[heli.ServoIndexW - 1] = QString("ServoW"); setComboCurrentIndex( m_aircraft->ccpmServoXChannel,config.heli.ServoIndexX);
if (heli.ServoIndexX > 0) setComboCurrentIndex( m_aircraft->ccpmServoYChannel,config.heli.ServoIndexY);
channelDesc[heli.ServoIndexX - 1] = QString("ServoX"); setComboCurrentIndex( m_aircraft->ccpmServoZChannel,config.heli.ServoIndexZ);
if (heli.ServoIndexY > 0)
channelDesc[heli.ServoIndexY - 1] = QString("ServoY");
break;
} // throttle
if (heli.ServoIndexZ > 0) setComboCurrentIndex( m_aircraft->ccpmEngineChannel, config.heli.Throttle);
channelDesc[heli.ServoIndexZ - 1] = QString("ServoZ"); // tail
setComboCurrentIndex( m_aircraft->ccpmTailChannel, config.heli.Tail);
return channelDesc; getMixer();
}
QString ConfigCcpmWidget::updateConfigObjectsFromWidgets()
{
QString airframeType = updateConfigObjects();
setMixer();
return airframeType;
} }
void ConfigCcpmWidget::UpdateType() void ConfigCcpmWidget::UpdateType()
{ {
int TypeInt,SingleServoIndex,NumServosDefined; int TypeInt, SingleServoIndex, NumServosDefined;
double AdjustmentAngle=0; double AdjustmentAngle = 0;
SetUIComponentVisibilities(); SetUIComponentVisibilities();
TypeInt = m_ccpm->ccpmType->count() - m_ccpm->ccpmType->currentIndex()-1; TypeInt = m_aircraft->ccpmType->count() - m_aircraft->ccpmType->currentIndex() - 1;
TypeText = m_ccpm->ccpmType->currentText(); TypeText = m_aircraft->ccpmType->currentText();
SingleServoIndex = m_ccpm->ccpmSingleServo->currentIndex(); SingleServoIndex = m_aircraft->ccpmSingleServo->currentIndex();
//set visibility of user settings //set visibility of user settings
m_ccpm->ccpmAdvancedSettingsTable->setEnabled(TypeInt==0); m_aircraft->ccpmAdvancedSettingsTable->setEnabled(TypeInt == 0);
m_ccpm->ccpmAdvancedSettingsTable->clearFocus();; m_aircraft->ccpmAdvancedSettingsTable->clearFocus();
m_ccpm->ccpmAngleW->setEnabled(TypeInt==1); m_aircraft->ccpmAngleW->setEnabled(TypeInt == 1);
m_ccpm->ccpmAngleX->setEnabled(TypeInt==1); m_aircraft->ccpmAngleX->setEnabled(TypeInt == 1);
m_ccpm->ccpmAngleY->setEnabled(TypeInt==1); m_aircraft->ccpmAngleY->setEnabled(TypeInt == 1);
m_ccpm->ccpmAngleZ->setEnabled(TypeInt==1); m_aircraft->ccpmAngleZ->setEnabled(TypeInt == 1);
m_ccpm->ccpmCorrectionAngle->setEnabled(TypeInt!=0); m_aircraft->ccpmCorrectionAngle->setEnabled(TypeInt != 0);
m_ccpm->ccpmServoWChannel->setEnabled(TypeInt>0); m_aircraft->ccpmServoWChannel->setEnabled(TypeInt > 0);
m_ccpm->ccpmServoXChannel->setEnabled(TypeInt>0); m_aircraft->ccpmServoXChannel->setEnabled(TypeInt > 0);
m_ccpm->ccpmServoYChannel->setEnabled(TypeInt>0); m_aircraft->ccpmServoYChannel->setEnabled(TypeInt > 0);
m_ccpm->ccpmServoZChannel->setEnabled(TypeInt>0); m_aircraft->ccpmServoZChannel->setEnabled(TypeInt > 0);
m_ccpm->ccpmSingleServo->setEnabled(TypeInt>1); m_aircraft->ccpmSingleServo->setEnabled(TypeInt > 1);
m_ccpm->ccpmEngineChannel->setEnabled(TypeInt>0); m_aircraft->ccpmEngineChannel->setEnabled(TypeInt > 0);
m_ccpm->ccpmTailChannel->setEnabled(TypeInt>0); m_aircraft->ccpmTailChannel->setEnabled(TypeInt > 0);
m_ccpm->ccpmCollectiveSlider->setEnabled(TypeInt>0); m_aircraft->ccpmCollectiveSlider->setEnabled(TypeInt > 0);
m_ccpm->ccpmCollectivespinBox->setEnabled(TypeInt>0); m_aircraft->ccpmCollectivespinBox->setEnabled(TypeInt > 0);
m_ccpm->ccpmRevoSlider->setEnabled(TypeInt>0); m_aircraft->ccpmRevoSlider->setEnabled(TypeInt > 0);
m_ccpm->ccpmREVOspinBox->setEnabled(TypeInt>0); m_aircraft->ccpmREVOspinBox->setEnabled(TypeInt > 0);
AdjustmentAngle=SingleServoIndex*90; AdjustmentAngle = SingleServoIndex * 90;
m_ccpm->PitchCurve->setVisible(1); m_aircraft->PitchCurve->setVisible(1);
NumServosDefined=4; NumServosDefined = 4;
//set values for pre defined heli types //set values for pre defined heli types
if (TypeText.compare(QString::fromUtf8("CCPM 2 Servo 90º"), Qt::CaseInsensitive)==0) if (TypeText.compare(QString::fromUtf8("CCPM 2 Servo 90º"), Qt::CaseInsensitive) == 0) {
{ m_aircraft->ccpmAngleW->setValue(AdjustmentAngle + 0);
m_ccpm->ccpmAngleW->setValue(AdjustmentAngle + 0); m_aircraft->ccpmAngleX->setValue(fmod(AdjustmentAngle + 90, 360));
m_ccpm->ccpmAngleX->setValue(fmod(AdjustmentAngle + 90,360)); m_aircraft->ccpmAngleY->setValue(0);
m_ccpm->ccpmAngleY->setValue(0); m_aircraft->ccpmAngleZ->setValue(0);
m_ccpm->ccpmAngleZ->setValue(0); m_aircraft->ccpmAngleY->setEnabled(0);
m_ccpm->ccpmAngleY->setEnabled(0); m_aircraft->ccpmAngleZ->setEnabled(0);
m_ccpm->ccpmAngleZ->setEnabled(0); m_aircraft->ccpmServoYChannel->setCurrentIndex(0);
m_ccpm->ccpmServoYChannel->setCurrentIndex(0); m_aircraft->ccpmServoZChannel->setCurrentIndex(0);
m_ccpm->ccpmServoZChannel->setCurrentIndex(0); m_aircraft->ccpmServoYChannel->setEnabled(0);
m_ccpm->ccpmServoYChannel->setEnabled(0); m_aircraft->ccpmServoZChannel->setEnabled(0);
m_ccpm->ccpmServoZChannel->setEnabled(0); NumServosDefined = 2;
NumServosDefined=2; } else if (TypeText.compare(QString::fromUtf8("CCPM 3 Servo 90º"), Qt::CaseInsensitive) == 0) {
m_aircraft->ccpmAngleW->setValue(AdjustmentAngle + 0);
m_aircraft->ccpmAngleX->setValue(fmod(AdjustmentAngle + 90, 360));
m_aircraft->ccpmAngleY->setValue(fmod(AdjustmentAngle + 180, 360));
m_aircraft->ccpmAngleZ->setValue(0);
m_aircraft->ccpmAngleZ->setEnabled(0);
m_aircraft->ccpmServoZChannel->setCurrentIndex(0);
m_aircraft->ccpmServoZChannel->setEnabled(0);
NumServosDefined = 3;
} else if (TypeText.compare(QString::fromUtf8("CCPM 4 Servo 90º"), Qt::CaseInsensitive) == 0) {
m_aircraft->ccpmAngleW->setValue(AdjustmentAngle + 0);
m_aircraft->ccpmAngleX->setValue(fmod(AdjustmentAngle + 90, 360));
m_aircraft->ccpmAngleY->setValue(fmod(AdjustmentAngle + 180, 360));
m_aircraft->ccpmAngleZ->setValue(fmod(AdjustmentAngle + 270, 360));
m_aircraft->ccpmSingleServo->setEnabled(0);
m_aircraft->ccpmSingleServo->setCurrentIndex(0);
NumServosDefined = 4;
} else if (TypeText.compare(QString::fromUtf8("CCPM 3 Servo 120º"), Qt::CaseInsensitive) == 0) {
m_aircraft->ccpmAngleW->setValue(AdjustmentAngle + 0);
m_aircraft->ccpmAngleX->setValue(fmod(AdjustmentAngle + 120, 360));
m_aircraft->ccpmAngleY->setValue(fmod(AdjustmentAngle + 240, 360));
m_aircraft->ccpmAngleZ->setValue(0);
m_aircraft->ccpmAngleZ->setEnabled(0);
m_aircraft->ccpmServoZChannel->setCurrentIndex(0);
m_aircraft->ccpmServoZChannel->setEnabled(0);
NumServosDefined = 3;
} else if (TypeText.compare(QString::fromUtf8("CCPM 3 Servo 140º"), Qt::CaseInsensitive) == 0) {
m_aircraft->ccpmAngleW->setValue(AdjustmentAngle + 0);
m_aircraft->ccpmAngleX->setValue(fmod(AdjustmentAngle + 140, 360));
m_aircraft->ccpmAngleY->setValue(fmod(AdjustmentAngle + 220, 360));
m_aircraft->ccpmAngleZ->setValue(0);
m_aircraft->ccpmAngleZ->setEnabled(0);
m_aircraft->ccpmServoZChannel->setCurrentIndex(0);
m_aircraft->ccpmServoZChannel->setEnabled(0);
NumServosDefined = 3;
} else if (TypeText.compare(QString::fromUtf8("FP 2 Servo 90º"), Qt::CaseInsensitive) == 0) {
m_aircraft->ccpmAngleW->setValue(AdjustmentAngle + 0);
m_aircraft->ccpmAngleX->setValue(fmod(AdjustmentAngle + 90, 360));
m_aircraft->ccpmAngleY->setValue(0);
m_aircraft->ccpmAngleZ->setValue(0);
m_aircraft->ccpmAngleY->setEnabled(0);
m_aircraft->ccpmAngleZ->setEnabled(0);
m_aircraft->ccpmServoYChannel->setCurrentIndex(0);
m_aircraft->ccpmServoZChannel->setCurrentIndex(0);
m_aircraft->ccpmServoYChannel->setEnabled(0);
m_aircraft->ccpmServoZChannel->setEnabled(0);
} m_aircraft->ccpmCollectivespinBox->setEnabled(0);
else if (TypeText.compare(QString::fromUtf8("CCPM 3 Servo 90º"), Qt::CaseInsensitive)==0) m_aircraft->ccpmCollectiveSlider->setEnabled(0);
{ m_aircraft->ccpmCollectivespinBox->setValue(0);
m_ccpm->ccpmAngleW->setValue(AdjustmentAngle + 0); m_aircraft->ccpmCollectiveSlider->setValue(0);
m_ccpm->ccpmAngleX->setValue(fmod(AdjustmentAngle + 90,360)); m_aircraft->PitchCurve->setVisible(0);
m_ccpm->ccpmAngleY->setValue(fmod(AdjustmentAngle + 180,360)); NumServosDefined = 2;
m_ccpm->ccpmAngleZ->setValue(0); } else if (TypeText.compare(QString::fromUtf8("Coax 2 Servo 90º"), Qt::CaseInsensitive) == 0) {
m_ccpm->ccpmAngleZ->setEnabled(0); m_aircraft->ccpmAngleW->setValue(AdjustmentAngle + 0);
m_ccpm->ccpmServoZChannel->setCurrentIndex(0); m_aircraft->ccpmAngleX->setValue(fmod(AdjustmentAngle + 90, 360));
m_ccpm->ccpmServoZChannel->setEnabled(0); m_aircraft->ccpmAngleY->setValue(0);
NumServosDefined=3; m_aircraft->ccpmAngleZ->setValue(0);
m_aircraft->ccpmAngleY->setEnabled(0);
} m_aircraft->ccpmAngleZ->setEnabled(0);
else if (TypeText.compare(QString::fromUtf8("CCPM 4 Servo 90º"), Qt::CaseInsensitive)==0) m_aircraft->ccpmServoYChannel->setCurrentIndex(0);
{ m_aircraft->ccpmServoZChannel->setCurrentIndex(0);
m_ccpm->ccpmAngleW->setValue(AdjustmentAngle + 0); m_aircraft->ccpmServoYChannel->setEnabled(0);
m_ccpm->ccpmAngleX->setValue(fmod(AdjustmentAngle + 90,360)); m_aircraft->ccpmServoZChannel->setEnabled(0);
m_ccpm->ccpmAngleY->setValue(fmod(AdjustmentAngle + 180,360));
m_ccpm->ccpmAngleZ->setValue(fmod(AdjustmentAngle + 270,360));
m_ccpm->ccpmSingleServo->setEnabled(0);
m_ccpm->ccpmSingleServo->setCurrentIndex(0);
NumServosDefined=4;
}
else if (TypeText.compare(QString::fromUtf8("CCPM 3 Servo 120º"), Qt::CaseInsensitive)==0)
{
m_ccpm->ccpmAngleW->setValue(AdjustmentAngle + 0);
m_ccpm->ccpmAngleX->setValue(fmod(AdjustmentAngle + 120,360));
m_ccpm->ccpmAngleY->setValue(fmod(AdjustmentAngle + 240,360));
m_ccpm->ccpmAngleZ->setValue(0);
m_ccpm->ccpmAngleZ->setEnabled(0);
m_ccpm->ccpmServoZChannel->setCurrentIndex(0);
m_ccpm->ccpmServoZChannel->setEnabled(0);
NumServosDefined=3;
}
else if (TypeText.compare(QString::fromUtf8("CCPM 3 Servo 140º"), Qt::CaseInsensitive)==0)
{
m_ccpm->ccpmAngleW->setValue(AdjustmentAngle + 0);
m_ccpm->ccpmAngleX->setValue(fmod(AdjustmentAngle + 140,360));
m_ccpm->ccpmAngleY->setValue(fmod(AdjustmentAngle + 220,360));
m_ccpm->ccpmAngleZ->setValue(0);
m_ccpm->ccpmAngleZ->setEnabled(0);
m_ccpm->ccpmServoZChannel->setCurrentIndex(0);
m_ccpm->ccpmServoZChannel->setEnabled(0);
NumServosDefined=3;
}
else if (TypeText.compare(QString::fromUtf8("FP 2 Servo 90º"), Qt::CaseInsensitive)==0)
{
m_ccpm->ccpmAngleW->setValue(AdjustmentAngle + 0);
m_ccpm->ccpmAngleX->setValue(fmod(AdjustmentAngle + 90,360));
m_ccpm->ccpmAngleY->setValue(0);
m_ccpm->ccpmAngleZ->setValue(0);
m_ccpm->ccpmAngleY->setEnabled(0);
m_ccpm->ccpmAngleZ->setEnabled(0);
m_ccpm->ccpmServoYChannel->setCurrentIndex(0);
m_ccpm->ccpmServoZChannel->setCurrentIndex(0);
m_ccpm->ccpmServoYChannel->setEnabled(0);
m_ccpm->ccpmServoZChannel->setEnabled(0);
m_ccpm->ccpmCollectivespinBox->setEnabled(0);
m_ccpm->ccpmCollectiveSlider->setEnabled(0);
m_ccpm->ccpmCollectivespinBox->setValue(0);
m_ccpm->ccpmCollectiveSlider->setValue(0);
m_ccpm->PitchCurve->setVisible(0);
NumServosDefined=2;
}
else if (TypeText.compare(QString::fromUtf8("Coax 2 Servo 90º"), Qt::CaseInsensitive)==0)
{
m_ccpm->ccpmAngleW->setValue(AdjustmentAngle + 0);
m_ccpm->ccpmAngleX->setValue(fmod(AdjustmentAngle + 90,360));
m_ccpm->ccpmAngleY->setValue(0);
m_ccpm->ccpmAngleZ->setValue(0);
m_ccpm->ccpmAngleY->setEnabled(0);
m_ccpm->ccpmAngleZ->setEnabled(0);
m_ccpm->ccpmServoYChannel->setCurrentIndex(0);
m_ccpm->ccpmServoZChannel->setCurrentIndex(0);
m_ccpm->ccpmServoYChannel->setEnabled(0);
m_ccpm->ccpmServoZChannel->setEnabled(0);
m_ccpm->ccpmCollectivespinBox->setEnabled(0);
m_ccpm->ccpmCollectiveSlider->setEnabled(0);
m_ccpm->ccpmCollectivespinBox->setValue(0);
m_ccpm->ccpmCollectiveSlider->setValue(0);
m_ccpm->PitchCurve->setVisible(0);
NumServosDefined=2;
m_aircraft->ccpmCollectivespinBox->setEnabled(0);
m_aircraft->ccpmCollectiveSlider->setEnabled(0);
m_aircraft->ccpmCollectivespinBox->setValue(0);
m_aircraft->ccpmCollectiveSlider->setValue(0);
m_aircraft->PitchCurve->setVisible(0);
NumServosDefined = 2;
} }
//Set the text of the motor boxes //Set the text of the motor boxes
if (TypeText.compare(QString::fromUtf8("Coax 2 Servo 90º"), Qt::CaseInsensitive)==0) if (TypeText.compare(QString::fromUtf8("Coax 2 Servo 90º"), Qt::CaseInsensitive) == 0) {
{ m_aircraft->ccpmEngineLabel->setText("CW motor");
m_ccpm->ccpmEngineLabel->setText("CW motor"); m_aircraft->ccpmTailLabel->setText("CCW motor");
m_ccpm->ccpmTailLabel->setText("CCW motor"); } else {
} m_aircraft->ccpmEngineLabel->setText("Engine");
else{ m_aircraft->ccpmTailLabel->setText("Tail rotor");
m_ccpm->ccpmEngineLabel->setText("Engine");
m_ccpm->ccpmTailLabel->setText("Tail rotor");
} }
//set the visibility of the swashplate servo selection boxes //set the visibility of the swashplate servo selection boxes
m_ccpm->ccpmServoWLabel->setVisible(NumServosDefined>=1); m_aircraft->ccpmServoWLabel->setVisible(NumServosDefined >= 1);
m_ccpm->ccpmServoXLabel->setVisible(NumServosDefined>=2); m_aircraft->ccpmServoXLabel->setVisible(NumServosDefined >= 2);
m_ccpm->ccpmServoYLabel->setVisible(NumServosDefined>=3); m_aircraft->ccpmServoYLabel->setVisible(NumServosDefined >= 3);
m_ccpm->ccpmServoZLabel->setVisible(NumServosDefined>=4); m_aircraft->ccpmServoZLabel->setVisible(NumServosDefined >= 4);
m_ccpm->ccpmServoWChannel->setVisible(NumServosDefined>=1); m_aircraft->ccpmServoWChannel->setVisible(NumServosDefined >= 1);
m_ccpm->ccpmServoXChannel->setVisible(NumServosDefined>=2); m_aircraft->ccpmServoXChannel->setVisible(NumServosDefined >= 2);
m_ccpm->ccpmServoYChannel->setVisible(NumServosDefined>=3); m_aircraft->ccpmServoYChannel->setVisible(NumServosDefined >= 3);
m_ccpm->ccpmServoZChannel->setVisible(NumServosDefined>=4); m_aircraft->ccpmServoZChannel->setVisible(NumServosDefined >= 4);
//set the visibility of the swashplate angle selection boxes //set the visibility of the swashplate angle selection boxes
m_ccpm->ccpmServoWLabel_2->setVisible(NumServosDefined>=1); m_aircraft->ccpmServoWLabel_2->setVisible(NumServosDefined >= 1);
m_ccpm->ccpmServoXLabel_2->setVisible(NumServosDefined>=2); m_aircraft->ccpmServoXLabel_2->setVisible(NumServosDefined >= 2);
m_ccpm->ccpmServoYLabel_2->setVisible(NumServosDefined>=3); m_aircraft->ccpmServoYLabel_2->setVisible(NumServosDefined >= 3);
m_ccpm->ccpmServoZLabel_2->setVisible(NumServosDefined>=4); m_aircraft->ccpmServoZLabel_2->setVisible(NumServosDefined >= 4);
m_ccpm->ccpmAngleW->setVisible(NumServosDefined>=1); m_aircraft->ccpmAngleW->setVisible(NumServosDefined >= 1);
m_ccpm->ccpmAngleX->setVisible(NumServosDefined>=2); m_aircraft->ccpmAngleX->setVisible(NumServosDefined >= 2);
m_ccpm->ccpmAngleY->setVisible(NumServosDefined>=3); m_aircraft->ccpmAngleY->setVisible(NumServosDefined >= 3);
m_ccpm->ccpmAngleZ->setVisible(NumServosDefined>=4); m_aircraft->ccpmAngleZ->setVisible(NumServosDefined >= 4);
QTableWidget *table = m_aircraft->ccpmAdvancedSettingsTable;
m_ccpm->ccpmAdvancedSettingsTable->resizeColumnsToContents(); table->resizeColumnsToContents();
for (int i=0;i<6;i++) { for (int i = 0; i < 6; i++) {
m_ccpm->ccpmAdvancedSettingsTable->setColumnWidth(i,(m_ccpm->ccpmAdvancedSettingsTable->width()- table->setColumnWidth(i, (table->width() - table->verticalHeader()->width()) / 6);
m_ccpm->ccpmAdvancedSettingsTable->verticalHeader()->width())/6);
} }
//update UI //update UI
ccpmSwashplateUpdate(); ccpmSwashplateUpdate();
} }
void ConfigCcpmWidget::ccpmSwashplateRedraw() void ConfigCcpmWidget::ccpmSwashplateRedraw()
{ {
double angle[CCPM_MAX_SWASH_SERVOS],CorrectionAngle,x,y,w,h,radius,CenterX,CenterY; double angle[CCPM_MAX_SWASH_SERVOS],CorrectionAngle,x,y,w,h,radius,CenterX,CenterY;
@ -483,25 +550,25 @@ void ConfigCcpmWidget::ccpmSwashplateRedraw()
double scale,xscale,yscale; double scale,xscale,yscale;
size = m_ccpm->SwashplateImage->rect(); size = m_aircraft->SwashplateImage->rect();
xscale=size.width(); xscale=size.width();
yscale=size.height(); yscale=size.height();
scale=xscale; scale=xscale;
if (yscale<scale)scale=yscale; if (yscale<scale)scale=yscale;
scale/=460.00; scale/=460.00;
m_ccpm->SwashplateImage->resetTransform (); m_aircraft->SwashplateImage->resetTransform ();
m_ccpm->SwashplateImage->scale(scale,scale); m_aircraft->SwashplateImage->scale(scale,scale);
size = m_ccpm->SwashLvlSwashplateImage->rect(); size = m_aircraft->SwashLvlSwashplateImage->rect();
xscale=size.width(); xscale=size.width();
yscale=size.height(); yscale=size.height();
scale=xscale; scale=xscale;
if (yscale<scale)scale=yscale; if (yscale<scale)scale=yscale;
scale/=590.00; scale/=590.00;
m_ccpm->SwashLvlSwashplateImage->resetTransform (); m_aircraft->SwashLvlSwashplateImage->resetTransform ();
m_ccpm->SwashLvlSwashplateImage->scale(scale,scale); m_aircraft->SwashLvlSwashplateImage->scale(scale,scale);
CorrectionAngle=m_ccpm->ccpmCorrectionAngle->value(); CorrectionAngle=m_aircraft->ccpmCorrectionAngle->value();
CenterX=200; CenterX=200;
CenterY=200; CenterY=200;
@ -510,18 +577,18 @@ void ConfigCcpmWidget::ccpmSwashplateRedraw()
SwashplateImg->setPos(CenterX-bounds.width()/2,CenterY-bounds.height()/2); SwashplateImg->setPos(CenterX-bounds.width()/2,CenterY-bounds.height()/2);
defined[0]=(m_ccpm->ccpmServoWChannel->isEnabled()); defined[0]=(m_aircraft->ccpmServoWChannel->isEnabled());
defined[1]=(m_ccpm->ccpmServoXChannel->isEnabled()); defined[1]=(m_aircraft->ccpmServoXChannel->isEnabled());
defined[2]=(m_ccpm->ccpmServoYChannel->isEnabled()); defined[2]=(m_aircraft->ccpmServoYChannel->isEnabled());
defined[3]=(m_ccpm->ccpmServoZChannel->isEnabled()); defined[3]=(m_aircraft->ccpmServoZChannel->isEnabled());
used[0]=((m_ccpm->ccpmServoWChannel->currentIndex()>0)&&(m_ccpm->ccpmServoWChannel->isEnabled())); used[0]=((m_aircraft->ccpmServoWChannel->currentIndex()>0)&&(m_aircraft->ccpmServoWChannel->isEnabled()));
used[1]=((m_ccpm->ccpmServoXChannel->currentIndex()>0)&&(m_ccpm->ccpmServoXChannel->isEnabled())); used[1]=((m_aircraft->ccpmServoXChannel->currentIndex()>0)&&(m_aircraft->ccpmServoXChannel->isEnabled()));
used[2]=((m_ccpm->ccpmServoYChannel->currentIndex()>0)&&(m_ccpm->ccpmServoYChannel->isEnabled())); used[2]=((m_aircraft->ccpmServoYChannel->currentIndex()>0)&&(m_aircraft->ccpmServoYChannel->isEnabled()));
used[3]=((m_ccpm->ccpmServoZChannel->currentIndex()>0)&&(m_ccpm->ccpmServoZChannel->isEnabled())); used[3]=((m_aircraft->ccpmServoZChannel->currentIndex()>0)&&(m_aircraft->ccpmServoZChannel->isEnabled()));
angle[0]=(CorrectionAngle+180+m_ccpm->ccpmAngleW->value())*Pi/180.00; angle[0]=(CorrectionAngle+180+m_aircraft->ccpmAngleW->value())*Pi/180.00;
angle[1]=(CorrectionAngle+180+m_ccpm->ccpmAngleX->value())*Pi/180.00; angle[1]=(CorrectionAngle+180+m_aircraft->ccpmAngleX->value())*Pi/180.00;
angle[2]=(CorrectionAngle+180+m_ccpm->ccpmAngleY->value())*Pi/180.00; angle[2]=(CorrectionAngle+180+m_aircraft->ccpmAngleY->value())*Pi/180.00;
angle[3]=(CorrectionAngle+180+m_ccpm->ccpmAngleZ->value())*Pi/180.00; angle[3]=(CorrectionAngle+180+m_aircraft->ccpmAngleZ->value())*Pi/180.00;
for (i=0;i<CCPM_MAX_SWASH_SERVOS;i++) for (i=0;i<CCPM_MAX_SWASH_SERVOS;i++)
@ -560,7 +627,7 @@ void ConfigCcpmWidget::ccpmSwashplateRedraw()
radius = (215.00+w+h); radius = (215.00+w+h);
x=CenterX-(radius*sin(angle[i]))-w; x=CenterX-(radius*sin(angle[i]))-w;
y=CenterY+(radius*cos(angle[i]))-h; y=CenterY+(radius*cos(angle[i]))-h;
SwashLvlSpinBoxes[i]->move(m_ccpm->SwashLvlSwashplateImage->mapFromScene (x, y)); SwashLvlSpinBoxes[i]->move(m_aircraft->SwashLvlSwashplateImage->mapFromScene (x, y));
SwashLvlSpinBoxes[i]->setVisible(used[i]!=0); SwashLvlSpinBoxes[i]->setVisible(used[i]!=0);
radius=220; radius=220;
@ -570,9 +637,9 @@ void ConfigCcpmWidget::ccpmSwashplateRedraw()
ServoLines[i]->setVisible(defined[i]!=0); ServoLines[i]->setVisible(defined[i]!=0);
} }
//m_ccpm->SwashplateImage->centerOn (CenterX, CenterY); //m_aircraft->SwashplateImage->centerOn (CenterX, CenterY);
//m_ccpm->SwashplateImage->fitInView(SwashplateImg, Qt::KeepAspectRatio); //m_aircraft->SwashplateImage->fitInView(SwashplateImg, Qt::KeepAspectRatio);
} }
void ConfigCcpmWidget::ccpmSwashplateUpdate() void ConfigCcpmWidget::ccpmSwashplateUpdate()
@ -586,132 +653,142 @@ void ConfigCcpmWidget::UpdateMixer()
{ {
bool useCCPM; bool useCCPM;
bool useCyclic; bool useCyclic;
int i,j,ThisEnable[6]; int ThisEnable[6];
float CollectiveConstant,PitchConstant,RollConstant,ThisAngle[6]; float CollectiveConstant, PitchConstant, RollConstant;
float ThisAngle[6];
QString Channel; QString Channel;
if (throwConfigError(QString("HeliCP"))) if (throwConfigError(QString("HeliCP")))
return; return;
GUIConfigDataUnion config = GetConfigData(); GUIConfigDataUnion config = getConfigData();
useCCPM = !(config.heli.ccpmCollectivePassthroughState || !config.heli.ccpmLinkCyclicState); useCCPM = !(config.heli.ccpmCollectivePassthroughState || !config.heli.ccpmLinkCyclicState);
useCyclic = config.heli.ccpmLinkRollState; useCyclic = config.heli.ccpmLinkRollState;
CollectiveConstant = (float)config.heli.SliderValue0 / 100.00; CollectiveConstant = (float) config.heli.SliderValue0 / 100.00;
if (useCCPM) if (useCCPM) { //cyclic = 1 - collective
{//cyclic = 1 - collective PitchConstant = 1 - CollectiveConstant;
PitchConstant = 1-CollectiveConstant;
RollConstant = PitchConstant; RollConstant = PitchConstant;
} } else {
else PitchConstant = (float) config.heli.SliderValue1 / 100.00;
{ ;
PitchConstant = (float)config.heli.SliderValue1 / 100.00;; if (useCyclic) {
if (useCyclic)
{
RollConstant = PitchConstant; RollConstant = PitchConstant;
} } else {
else RollConstant = (float) config.heli.SliderValue2 / 100.00;
{ ;
RollConstant = (float)config.heli.SliderValue2 / 100.00;;
} }
} }
if (config.heli.SwashplateType>0) if (config.heli.SwashplateType > 0) { //not advanced settings
{//not advanced settings //get the channel data from the ui
//get the channel data from the ui MixerChannelData[0] = m_aircraft->ccpmEngineChannel->currentIndex();
MixerChannelData[0] = m_ccpm->ccpmEngineChannel->currentIndex(); MixerChannelData[1] = m_aircraft->ccpmTailChannel->currentIndex();
MixerChannelData[1] = m_ccpm->ccpmTailChannel->currentIndex(); MixerChannelData[2] = m_aircraft->ccpmServoWChannel->currentIndex();
MixerChannelData[2] = m_ccpm->ccpmServoWChannel->currentIndex(); MixerChannelData[3] = m_aircraft->ccpmServoXChannel->currentIndex();
MixerChannelData[3] = m_ccpm->ccpmServoXChannel->currentIndex(); MixerChannelData[4] = m_aircraft->ccpmServoYChannel->currentIndex();
MixerChannelData[4] = m_ccpm->ccpmServoYChannel->currentIndex(); MixerChannelData[5] = m_aircraft->ccpmServoZChannel->currentIndex();
MixerChannelData[5] = m_ccpm->ccpmServoZChannel->currentIndex();
//get the angle data from the ui //get the angle data from the ui
ThisAngle[2] = m_ccpm->ccpmAngleW->value(); ThisAngle[2] = m_aircraft->ccpmAngleW->value();
ThisAngle[3] = m_ccpm->ccpmAngleX->value(); ThisAngle[3] = m_aircraft->ccpmAngleX->value();
ThisAngle[4] = m_ccpm->ccpmAngleY->value(); ThisAngle[4] = m_aircraft->ccpmAngleY->value();
ThisAngle[5] = m_ccpm->ccpmAngleZ->value(); ThisAngle[5] = m_aircraft->ccpmAngleZ->value();
//get the angle data from the ui //get the angle data from the ui
ThisEnable[2] = m_ccpm->ccpmServoWChannel->isEnabled(); ThisEnable[2] = m_aircraft->ccpmServoWChannel->isEnabled();
ThisEnable[3] = m_ccpm->ccpmServoXChannel->isEnabled(); ThisEnable[3] = m_aircraft->ccpmServoXChannel->isEnabled();
ThisEnable[4] = m_ccpm->ccpmServoYChannel->isEnabled(); ThisEnable[4] = m_aircraft->ccpmServoYChannel->isEnabled();
ThisEnable[5] = m_ccpm->ccpmServoZChannel->isEnabled(); ThisEnable[5] = m_aircraft->ccpmServoZChannel->isEnabled();
ServosText[0]->setPlainText(QString("%1").arg( MixerChannelData[2] ));
ServosText[1]->setPlainText(QString("%1").arg( MixerChannelData[3] ));
ServosText[2]->setPlainText(QString("%1").arg( MixerChannelData[4] ));
ServosText[3]->setPlainText(QString("%1").arg( MixerChannelData[5] ));
ServosText[0]->setPlainText(QString("%1").arg(MixerChannelData[2]));
ServosText[1]->setPlainText(QString("%1").arg(MixerChannelData[3]));
ServosText[2]->setPlainText(QString("%1").arg(MixerChannelData[4]));
ServosText[3]->setPlainText(QString("%1").arg(MixerChannelData[5]));
//go through the user data and update the mixer matrix //go through the user data and update the mixer matrix
for (i=0;i<6;i++) QTableWidget *table = m_aircraft->ccpmAdvancedSettingsTable;
{ for (int i = 0; i < 6; i++) {
if ((MixerChannelData[i]>0) && ((ThisEnable[i])||(i<2))) if ((MixerChannelData[i] > 0) && ((ThisEnable[i]) || (i < 2))) {
{ table->item(i, 0)->setText(QString("%1").arg(MixerChannelData[i]));
m_ccpm->ccpmAdvancedSettingsTable->item(i,0)->setText(QString("%1").arg( MixerChannelData[i] ));
//Generate the mixer vector //Generate the mixer vector
if (i==0) if (i == 0) { //main motor-engine
{//main motor-engine table->item(i, 1)->setText(QString("%1").arg(127)); //ThrottleCurve1
m_ccpm->ccpmAdvancedSettingsTable->item(i,1)->setText(QString("%1").arg(127));//ThrottleCurve1 table->item(i, 2)->setText(QString("%1").arg(0)); //ThrottleCurve2
m_ccpm->ccpmAdvancedSettingsTable->item(i,2)->setText(QString("%1").arg(0));//ThrottleCurve2 table->item(i, 3)->setText(QString("%1").arg(0)); //Roll
m_ccpm->ccpmAdvancedSettingsTable->item(i,3)->setText(QString("%1").arg(0));//Roll table->item(i, 4)->setText(QString("%1").arg(0)); //Pitch
m_ccpm->ccpmAdvancedSettingsTable->item(i,4)->setText(QString("%1").arg(0));//Pitch
if (TypeText.compare(QString::fromUtf8("Coax 2 Servo 90º"), Qt::CaseInsensitive)==0) if (TypeText.compare(QString::fromUtf8("Coax 2 Servo 90º"), Qt::CaseInsensitive) == 0) {
m_ccpm->ccpmAdvancedSettingsTable->item(i,5)->setText(QString("%1").arg(-127));//Yaw // Yaw
else table->item(i, 5)->setText(QString("%1").arg(-127));
m_ccpm->ccpmAdvancedSettingsTable->item(i,5)->setText(QString("%1").arg(0));//Yaw } else {
// Yaw
} table->item(i, 5)->setText(QString("%1").arg(0));
if (i==1)
{//tailrotor --or-- counter-clockwise motor
if (TypeText.compare(QString::fromUtf8("Coax 2 Servo 90º"), Qt::CaseInsensitive)==0)
{
m_ccpm->ccpmAdvancedSettingsTable->item(i,1)->setText(QString("%1").arg(127));//ThrottleCurve1
m_ccpm->ccpmAdvancedSettingsTable->item(i,5)->setText(QString("%1").arg(127));//Yaw
}
else{
m_ccpm->ccpmAdvancedSettingsTable->item(i,1)->setText(QString("%1").arg(0));//ThrottleCurve1
m_ccpm->ccpmAdvancedSettingsTable->item(i,5)->setText(QString("%1").arg(127));//Yaw
} }
m_ccpm->ccpmAdvancedSettingsTable->item(i,2)->setText(QString("%1").arg(0));//ThrottleCurve2 }
m_ccpm->ccpmAdvancedSettingsTable->item(i,3)->setText(QString("%1").arg(0));//Roll if (i == 1) {
m_ccpm->ccpmAdvancedSettingsTable->item(i,4)->setText(QString("%1").arg(0));//Pitch // tailrotor --or-- counter-clockwise motor
if (TypeText.compare(QString::fromUtf8("Coax 2 Servo 90º"), Qt::CaseInsensitive) == 0) {
// ThrottleCurve1
table->item(i, 1)->setText(QString("%1").arg(127));
// Yaw
table->item(i, 5)->setText(QString("%1").arg(127));
} else {
// ThrottleCurve1
table->item(i, 1)->setText(QString("%1").arg(0));
// Yaw
table->item(i, 5)->setText(QString("%1").arg(127));
}
//ThrottleCurve2
table->item(i, 2)->setText(QString("%1").arg(0));
// Roll
table->item(i, 3)->setText(QString("%1").arg(0));
// Pitch
table->item(i, 4)->setText(QString("%1").arg(0));
} }
if (i>1) if (i > 1) {
{//Swashplate // Swashplate
m_ccpm->ccpmAdvancedSettingsTable->item(i,1)->setText(QString("%1").arg(0));//ThrottleCurve1 //ThrottleCurve1
m_ccpm->ccpmAdvancedSettingsTable->item(i,2)->setText(QString("%1").arg((int)(127.0*CollectiveConstant)));//ThrottleCurve2 table->item(i, 1)->setText(QString("%1").arg(0));
m_ccpm->ccpmAdvancedSettingsTable->item(i,3)->setText(QString("%1").arg((int)(127.0*(RollConstant)*sin((180+config.heli.CorrectionAngle + ThisAngle[i])*Pi/180.00))));//Roll //ThrottleCurve2
m_ccpm->ccpmAdvancedSettingsTable->item(i,4)->setText(QString("%1").arg((int)(127.0*(PitchConstant)*cos((config.heli.CorrectionAngle + ThisAngle[i])*Pi/180.00))));//Pitch table->item(i, 2)->setText(QString("%1").arg((int) (127.0 * CollectiveConstant)));
m_ccpm->ccpmAdvancedSettingsTable->item(i,5)->setText(QString("%1").arg(0));//Yaw table->item(i, 3)->setText(
QString("%1").arg(
(int) (127.0 * (RollConstant)
* sin((180 + config.heli.CorrectionAngle + ThisAngle[i]) * Pi / 180.00)))); //Roll
table->item(i, 4)->setText(
QString("%1").arg(
(int) (127.0 * (PitchConstant)
* cos((config.heli.CorrectionAngle + ThisAngle[i]) * Pi / 180.00)))); //Pitch
// Yaw
table->item(i, 5)->setText(QString("%1").arg(0));
} }
} } else {
else for (int j = 0; j < 6; j++) {
{ table->item(i, j)->setText(QString("-"));
for (j=0;j<6;j++) m_ccpm->ccpmAdvancedSettingsTable->item(i,j)->setText(QString("-")); }
} }
} }
} else {
// advanced settings
QTableWidget *table = m_aircraft->ccpmAdvancedSettingsTable;
for (int i = 0; i < 6; i++) {
Channel = table->item(i, 0)->text();
if (Channel == "-") {
Channel = QString("9");
}
MixerChannelData[i] = Channel.toInt();
}
} }
else
{//advanced settings
for (i=0;i<6;i++)
{
Channel =m_ccpm->ccpmAdvancedSettingsTable->item(i,0)->text();
if (Channel == "-") Channel = QString("9");
MixerChannelData[i]= Channel.toInt();
}
}
} }
QString ConfigCcpmWidget::updateConfigObjects() QString ConfigCcpmWidget::updateConfigObjects()
{ {
QString airframeType = "HeliCP"; QString airframeType = "HeliCP";
@ -719,145 +796,86 @@ QString ConfigCcpmWidget::updateConfigObjects()
bool useCCPM; bool useCCPM;
bool useCyclic; bool useCyclic;
if (updatingFromHardware == TRUE) return airframeType; if (updatingFromHardware == TRUE)
return airframeType;
updatingFromHardware = TRUE; updatingFromHardware = TRUE;
//get the user options //get the user options
GUIConfigDataUnion config = GetConfigData(); GUIConfigDataUnion config = getConfigData();
//swashplate config //swashplate config
config.heli.SwashplateType = m_ccpm->ccpmType->count() - m_ccpm->ccpmType->currentIndex()-1; config.heli.SwashplateType = m_aircraft->ccpmType->count() - m_aircraft->ccpmType->currentIndex() - 1;
config.heli.FirstServoIndex = m_ccpm->ccpmSingleServo->currentIndex(); config.heli.FirstServoIndex = m_aircraft->ccpmSingleServo->currentIndex();
//ccpm mixing options //ccpm mixing options
config.heli.ccpmCollectivePassthroughState = m_ccpm->ccpmCollectivePassthrough->isChecked(); config.heli.ccpmCollectivePassthroughState = m_aircraft->ccpmCollectivePassthrough->isChecked();
config.heli.ccpmLinkCyclicState = m_ccpm->ccpmLinkCyclic->isChecked(); config.heli.ccpmLinkCyclicState = m_aircraft->ccpmLinkCyclic->isChecked();
config.heli.ccpmLinkRollState = m_ccpm->ccpmLinkRoll->isChecked(); config.heli.ccpmLinkRollState = m_aircraft->ccpmLinkRoll->isChecked();
useCCPM = !(config.heli.ccpmCollectivePassthroughState || !config.heli.ccpmLinkCyclicState); useCCPM = !(config.heli.ccpmCollectivePassthroughState || !config.heli.ccpmLinkCyclicState);
useCyclic = config.heli.ccpmLinkRollState; useCyclic = config.heli.ccpmLinkRollState;
//correction angle //correction angle
config.heli.CorrectionAngle = m_ccpm->ccpmCorrectionAngle->value(); config.heli.CorrectionAngle = m_aircraft->ccpmCorrectionAngle->value();
//update sliders //update sliders
if (useCCPM) if (useCCPM) {
{ config.heli.SliderValue0 = m_aircraft->ccpmCollectiveSlider->value();
config.heli.SliderValue0 = m_ccpm->ccpmCollectiveSlider->value(); } else {
config.heli.SliderValue0 = m_aircraft->ccpmCollectiveScale->value();
} }
else if (useCyclic) {
{ config.heli.SliderValue1 = m_aircraft->ccpmCyclicScale->value();
config.heli.SliderValue0 = m_ccpm->ccpmCollectiveScale->value(); } else {
config.heli.SliderValue1 = m_aircraft->ccpmPitchScale->value();
} }
if (useCyclic) config.heli.SliderValue2 = m_aircraft->ccpmRollScale->value();
{
config.heli.SliderValue1 = m_ccpm->ccpmCyclicScale->value();
}
else
{
config.heli.SliderValue1 = m_ccpm->ccpmPitchScale->value();
}
config.heli.SliderValue2 = m_ccpm->ccpmRollScale->value();
//servo assignments //servo assignments
config.heli.ServoIndexW = m_ccpm->ccpmServoWChannel->currentIndex(); config.heli.ServoIndexW = m_aircraft->ccpmServoWChannel->currentIndex();
config.heli.ServoIndexX = m_ccpm->ccpmServoXChannel->currentIndex(); config.heli.ServoIndexX = m_aircraft->ccpmServoXChannel->currentIndex();
config.heli.ServoIndexY = m_ccpm->ccpmServoYChannel->currentIndex(); config.heli.ServoIndexY = m_aircraft->ccpmServoYChannel->currentIndex();
config.heli.ServoIndexZ = m_ccpm->ccpmServoZChannel->currentIndex(); config.heli.ServoIndexZ = m_aircraft->ccpmServoZChannel->currentIndex();
//throttle //throttle
config.heli.Throttle = m_ccpm->ccpmEngineChannel->currentIndex(); config.heli.Throttle = m_aircraft->ccpmEngineChannel->currentIndex();
//tail //tail
config.heli.Tail = m_ccpm->ccpmTailChannel->currentIndex(); config.heli.Tail = m_aircraft->ccpmTailChannel->currentIndex();
SetConfigData(config); setConfigData(config);
updatingFromHardware = FALSE; updatingFromHardware = FALSE;
return airframeType; return airframeType;
} }
QString ConfigCcpmWidget::updateConfigObjectsFromWidgets() //UpdateCCPMOptionsFromUI()
{
QString airframeType = updateConfigObjects();
setMixer();
return airframeType;
}
void ConfigCcpmWidget::refreshWidgetsValues(QString frameType) //UpdateCCPMUIFromOptions()
{
Q_UNUSED(frameType);
GUIConfigDataUnion config = GetConfigData();
//swashplate config
setComboCurrentIndex( m_ccpm->ccpmType, m_ccpm->ccpmType->count() - (config.heli.SwashplateType +1));
setComboCurrentIndex(m_ccpm->ccpmSingleServo, config.heli.FirstServoIndex);
//ccpm mixing options
m_ccpm->ccpmCollectivePassthrough->setChecked(config.heli.ccpmCollectivePassthroughState);
m_ccpm->ccpmLinkCyclic->setChecked(config.heli.ccpmLinkCyclicState);
m_ccpm->ccpmLinkRoll->setChecked(config.heli.ccpmLinkRollState);
//correction angle
m_ccpm->ccpmCorrectionAngle->setValue(config.heli.CorrectionAngle);
//update sliders
m_ccpm->ccpmCollectiveScale->setValue(config.heli.SliderValue0);
m_ccpm->ccpmCollectiveScaleBox->setValue(config.heli.SliderValue0);
m_ccpm->ccpmCyclicScale->setValue(config.heli.SliderValue1);
m_ccpm->ccpmCyclicScaleBox->setValue(config.heli.SliderValue1);
m_ccpm->ccpmPitchScale->setValue(config.heli.SliderValue1);
m_ccpm->ccpmPitchScaleBox->setValue(config.heli.SliderValue1);
m_ccpm->ccpmRollScale->setValue(config.heli.SliderValue2);
m_ccpm->ccpmRollScaleBox->setValue(config.heli.SliderValue2);
m_ccpm->ccpmCollectiveSlider->setValue(config.heli.SliderValue0);
m_ccpm->ccpmCollectivespinBox->setValue(config.heli.SliderValue0);
//servo assignments
setComboCurrentIndex(m_ccpm->ccpmServoWChannel, config.heli.ServoIndexW);
setComboCurrentIndex( m_ccpm->ccpmServoXChannel,config.heli.ServoIndexX);
setComboCurrentIndex( m_ccpm->ccpmServoYChannel,config.heli.ServoIndexY);
setComboCurrentIndex( m_ccpm->ccpmServoZChannel,config.heli.ServoIndexZ);
//throttle
setComboCurrentIndex( m_ccpm->ccpmEngineChannel, config.heli.Throttle);
//tail
setComboCurrentIndex( m_ccpm->ccpmTailChannel, config.heli.Tail);
getMixer();
}
void ConfigCcpmWidget::SetUIComponentVisibilities() void ConfigCcpmWidget::SetUIComponentVisibilities()
{ {
m_ccpm->ccpmRevoMixingBox->setVisible(0); m_aircraft->ccpmRevoMixingBox->setVisible(0);
m_ccpm->ccpmPitchMixingBox->setVisible(!m_ccpm->ccpmCollectivePassthrough->isChecked() && m_aircraft->ccpmPitchMixingBox->setVisible(
m_ccpm->ccpmLinkCyclic->isChecked()); !m_aircraft->ccpmCollectivePassthrough->isChecked() && m_aircraft->ccpmLinkCyclic->isChecked());
m_ccpm->ccpmCollectiveScalingBox->setVisible(m_ccpm->ccpmCollectivePassthrough->isChecked() || !m_ccpm->ccpmLinkCyclic->isChecked()); m_aircraft->ccpmCollectiveScalingBox->setVisible(
m_aircraft->ccpmCollectivePassthrough->isChecked() || !m_aircraft->ccpmLinkCyclic->isChecked());
m_ccpm->ccpmLinkCyclic->setVisible(!m_ccpm->ccpmCollectivePassthrough->isChecked()); m_aircraft->ccpmLinkCyclic->setVisible(!m_aircraft->ccpmCollectivePassthrough->isChecked());
m_ccpm->ccpmCyclicScalingBox->setVisible((m_ccpm->ccpmCollectivePassthrough->isChecked() || !m_ccpm->ccpmLinkCyclic->isChecked()) && m_aircraft->ccpmCyclicScalingBox->setVisible(
m_ccpm->ccpmLinkRoll->isChecked()); (m_aircraft->ccpmCollectivePassthrough->isChecked() || !m_aircraft->ccpmLinkCyclic->isChecked())
&& m_aircraft->ccpmLinkRoll->isChecked());
if (!m_ccpm->ccpmCollectivePassthrough->checkState() && m_ccpm->ccpmLinkCyclic->isChecked()) if (!m_aircraft->ccpmCollectivePassthrough->checkState() && m_aircraft->ccpmLinkCyclic->isChecked()) {
{ m_aircraft->ccpmPitchScalingBox->setVisible(0);
m_ccpm->ccpmPitchScalingBox->setVisible(0); m_aircraft->ccpmRollScalingBox->setVisible(0);
m_ccpm->ccpmRollScalingBox->setVisible(0); m_aircraft->ccpmLinkRoll->setVisible(0);
m_ccpm->ccpmLinkRoll->setVisible(0);
} } else {
else m_aircraft->ccpmPitchScalingBox->setVisible(!m_aircraft->ccpmLinkRoll->isChecked());
{ m_aircraft->ccpmRollScalingBox->setVisible(!m_aircraft->ccpmLinkRoll->isChecked());
m_ccpm->ccpmPitchScalingBox->setVisible(!m_ccpm->ccpmLinkRoll->isChecked()); m_aircraft->ccpmLinkRoll->setVisible(1);
m_ccpm->ccpmRollScalingBox->setVisible(!m_ccpm->ccpmLinkRoll->isChecked());
m_ccpm->ccpmLinkRoll->setVisible(1);
} }
} }
/** /**
Request the current value of the SystemSettings which holds the ccpm type Request the current value of the SystemSettings which holds the ccpm type
*/ */
@ -866,32 +884,29 @@ void ConfigCcpmWidget::getMixer()
if (SwashLvlConfigurationInProgress)return; if (SwashLvlConfigurationInProgress)return;
if (updatingToHardware)return; if (updatingToHardware)return;
updatingFromHardware=TRUE; updatingFromHardware = TRUE;
UAVDataObject* mixer = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings"))); UAVDataObject* mixer = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
Q_ASSERT(mixer); Q_ASSERT(mixer);
QPointer<VehicleConfig> vconfig = new VehicleConfig();
QList<double> curveValues; QList<double> curveValues;
vconfig->getThrottleCurve(mixer, VehicleConfig::MIXER_THROTTLECURVE1, &curveValues); getThrottleCurve(mixer, VehicleConfig::MIXER_THROTTLECURVE1, &curveValues);
// is at least one of the curve values != 0? // is at least one of the curve values != 0?
if (vconfig->isValidThrottleCurve(&curveValues)) { if (isValidThrottleCurve(&curveValues)) {
m_ccpm->ThrottleCurve->setCurve(&curveValues); m_aircraft->ThrottleCurve->setCurve(&curveValues);
} }
else { else {
m_ccpm->ThrottleCurve->ResetCurve(); m_aircraft->ThrottleCurve->ResetCurve();
} }
getThrottleCurve(mixer, VehicleConfig::MIXER_THROTTLECURVE2, &curveValues);
vconfig->getThrottleCurve(mixer, VehicleConfig::MIXER_THROTTLECURVE2, &curveValues);
// is at least one of the curve values != 0? // is at least one of the curve values != 0?
if (vconfig->isValidThrottleCurve(&curveValues)) { if (isValidThrottleCurve(&curveValues)) {
m_ccpm->PitchCurve->setCurve(&curveValues); m_aircraft->PitchCurve->setCurve(&curveValues);
} }
else { else {
m_ccpm->PitchCurve->ResetCurve(); m_aircraft->PitchCurve->ResetCurve();
} }
updatingFromHardware=FALSE; updatingFromHardware=FALSE;
@ -899,7 +914,6 @@ void ConfigCcpmWidget::getMixer()
ccpmSwashplateUpdate(); ccpmSwashplateUpdate();
} }
/** /**
Sends the config to the board (ccpm type) Sends the config to the board (ccpm type)
*/ */
@ -964,13 +978,13 @@ void ConfigCcpmWidget::setMixer()
//Configure the vector //Configure the vector
for (j=0;j<5;j++) for (j=0;j<5;j++)
mixers[MixerChannelData[i] - 1][j] = m_ccpm->ccpmAdvancedSettingsTable->item(i,j+1)->text().toInt(); mixers[MixerChannelData[i] - 1][j] = m_aircraft->ccpmAdvancedSettingsTable->item(i,j+1)->text().toInt();
} }
} }
//get the user data for the curve into the mixer settings //get the user data for the curve into the mixer settings
QList<double> curve1 = m_ccpm->ThrottleCurve->getCurve(); QList<double> curve1 = m_aircraft->ThrottleCurve->getCurve();
QList<double> curve2 = m_ccpm->PitchCurve->getCurve(); QList<double> curve2 = m_aircraft->PitchCurve->getCurve();
for (i=0;i<5;i++) { for (i=0;i<5;i++) {
mixerSettingsData.ThrottleCurve1[i] = curve1.at(i); mixerSettingsData.ThrottleCurve1[i] = curve1.at(i);
mixerSettingsData.ThrottleCurve2[i] = curve2.at(i); mixerSettingsData.ThrottleCurve2[i] = curve2.at(i);
@ -979,7 +993,7 @@ void ConfigCcpmWidget::setMixer()
//mapping of collective input to curve 2... //mapping of collective input to curve 2...
//MixerSettings.Curve2Source = Throttle,Roll,Pitch,Yaw,Accessory0,Accessory1,Accessory2,Accessory3,Accessory4,Accessory5 //MixerSettings.Curve2Source = Throttle,Roll,Pitch,Yaw,Accessory0,Accessory1,Accessory2,Accessory3,Accessory4,Accessory5
//check if we are using throttle or directly from a channel... //check if we are using throttle or directly from a channel...
if (m_ccpm->ccpmCollectivePassthrough->isChecked()) if (m_aircraft->ccpmCollectivePassthrough->isChecked())
mixerSettingsData.Curve2Source = MixerSettings::CURVE2SOURCE_COLLECTIVE; mixerSettingsData.Curve2Source = MixerSettings::CURVE2SOURCE_COLLECTIVE;
else else
mixerSettingsData.Curve2Source = MixerSettings::CURVE2SOURCE_THROTTLE; mixerSettingsData.Curve2Source = MixerSettings::CURVE2SOURCE_THROTTLE;
@ -1009,10 +1023,10 @@ void ConfigCcpmWidget::resizeEvent(QResizeEvent* event)
{ {
Q_UNUSED(event); Q_UNUSED(event);
// Make the custom table columns autostretch: // Make the custom table columns autostretch:
m_ccpm->ccpmAdvancedSettingsTable->resizeColumnsToContents(); m_aircraft->ccpmAdvancedSettingsTable->resizeColumnsToContents();
for (int i=0;i<6;i++) { for (int i=0;i<6;i++) {
m_ccpm->ccpmAdvancedSettingsTable->setColumnWidth(i,(m_ccpm->ccpmAdvancedSettingsTable->width()- m_aircraft->ccpmAdvancedSettingsTable->setColumnWidth(i,(m_aircraft->ccpmAdvancedSettingsTable->width()-
m_ccpm->ccpmAdvancedSettingsTable->verticalHeader()->width())/6); m_aircraft->ccpmAdvancedSettingsTable->verticalHeader()->width())/6);
} }
ccpmSwashplateRedraw(); ccpmSwashplateRedraw();
@ -1020,10 +1034,10 @@ void ConfigCcpmWidget::resizeEvent(QResizeEvent* event)
void ConfigCcpmWidget::showEvent(QShowEvent *event) void ConfigCcpmWidget::showEvent(QShowEvent *event)
{ {
Q_UNUSED(event) Q_UNUSED(event)
m_ccpm->ccpmAdvancedSettingsTable->resizeColumnsToContents(); m_aircraft->ccpmAdvancedSettingsTable->resizeColumnsToContents();
for (int i=0;i<6;i++) { for (int i=0;i<6;i++) {
m_ccpm->ccpmAdvancedSettingsTable->setColumnWidth(i,(m_ccpm->ccpmAdvancedSettingsTable->width()- m_aircraft->ccpmAdvancedSettingsTable->setColumnWidth(i,(m_aircraft->ccpmAdvancedSettingsTable->width()-
m_ccpm->ccpmAdvancedSettingsTable->verticalHeader()->width())/6); m_aircraft->ccpmAdvancedSettingsTable->verticalHeader()->width())/6);
} }
ccpmSwashplateRedraw(); ccpmSwashplateRedraw();
} }
@ -1054,15 +1068,15 @@ void ConfigCcpmWidget::SwashLvlStartButtonPressed()
//remove Flight control of ActuatorCommand //remove Flight control of ActuatorCommand
enableSwashplateLevellingControl(true); enableSwashplateLevellingControl(true);
m_ccpm->SwashLvlStartButton->setEnabled(false); m_aircraft->SwashLvlStartButton->setEnabled(false);
m_ccpm->SwashLvlNextButton->setEnabled(true); m_aircraft->SwashLvlNextButton->setEnabled(true);
m_ccpm->SwashLvlCancelButton->setEnabled(true); m_aircraft->SwashLvlCancelButton->setEnabled(true);
m_ccpm->SwashLvlFinishButton->setEnabled(false); m_aircraft->SwashLvlFinishButton->setEnabled(false);
//clear status check boxes //clear status check boxes
m_ccpm->SwashLvlStepList->item(0)->setCheckState(Qt::Unchecked); m_aircraft->SwashLvlStepList->item(0)->setCheckState(Qt::Unchecked);
m_ccpm->SwashLvlStepList->item(1)->setCheckState(Qt::Unchecked); m_aircraft->SwashLvlStepList->item(1)->setCheckState(Qt::Unchecked);
m_ccpm->SwashLvlStepList->item(2)->setCheckState(Qt::Unchecked); m_aircraft->SwashLvlStepList->item(2)->setCheckState(Qt::Unchecked);
m_ccpm->SwashLvlStepList->item(3)->setCheckState(Qt::Unchecked); m_aircraft->SwashLvlStepList->item(3)->setCheckState(Qt::Unchecked);
//download the current settings to the OP hw //download the current settings to the OP hw
@ -1087,15 +1101,15 @@ void ConfigCcpmWidget::SwashLvlStartButtonPressed()
MaxField = obj->getField(QString("ChannelMax")); MaxField = obj->getField(QString("ChannelMax"));
//channel assignments //channel assignments
oldSwashLvlConfiguration.ServoChannels[0]=m_ccpm->ccpmServoWChannel->currentIndex(); oldSwashLvlConfiguration.ServoChannels[0]=m_aircraft->ccpmServoWChannel->currentIndex();
oldSwashLvlConfiguration.ServoChannels[1]=m_ccpm->ccpmServoXChannel->currentIndex(); oldSwashLvlConfiguration.ServoChannels[1]=m_aircraft->ccpmServoXChannel->currentIndex();
oldSwashLvlConfiguration.ServoChannels[2]=m_ccpm->ccpmServoYChannel->currentIndex(); oldSwashLvlConfiguration.ServoChannels[2]=m_aircraft->ccpmServoYChannel->currentIndex();
oldSwashLvlConfiguration.ServoChannels[3]=m_ccpm->ccpmServoZChannel->currentIndex(); oldSwashLvlConfiguration.ServoChannels[3]=m_aircraft->ccpmServoZChannel->currentIndex();
//if servos are used //if servos are used
oldSwashLvlConfiguration.Used[0]=((m_ccpm->ccpmServoWChannel->currentIndex()>0)&&(m_ccpm->ccpmServoWChannel->isEnabled())); oldSwashLvlConfiguration.Used[0]=((m_aircraft->ccpmServoWChannel->currentIndex()>0)&&(m_aircraft->ccpmServoWChannel->isEnabled()));
oldSwashLvlConfiguration.Used[1]=((m_ccpm->ccpmServoXChannel->currentIndex()>0)&&(m_ccpm->ccpmServoXChannel->isEnabled())); oldSwashLvlConfiguration.Used[1]=((m_aircraft->ccpmServoXChannel->currentIndex()>0)&&(m_aircraft->ccpmServoXChannel->isEnabled()));
oldSwashLvlConfiguration.Used[2]=((m_ccpm->ccpmServoYChannel->currentIndex()>0)&&(m_ccpm->ccpmServoYChannel->isEnabled())); oldSwashLvlConfiguration.Used[2]=((m_aircraft->ccpmServoYChannel->currentIndex()>0)&&(m_aircraft->ccpmServoYChannel->isEnabled()));
oldSwashLvlConfiguration.Used[3]=((m_ccpm->ccpmServoZChannel->currentIndex()>0)&&(m_ccpm->ccpmServoZChannel->isEnabled())); oldSwashLvlConfiguration.Used[3]=((m_aircraft->ccpmServoZChannel->currentIndex()>0)&&(m_aircraft->ccpmServoZChannel->isEnabled()));
//min,neutral,max values for the servos //min,neutral,max values for the servos
for (i=0;i<CCPM_MAX_SWASH_SERVOS;i++) for (i=0;i<CCPM_MAX_SWASH_SERVOS;i++)
{ {
@ -1116,111 +1130,107 @@ void ConfigCcpmWidget::SwashLvlStartButtonPressed()
//restore Flight control of ActuatorCommand //restore Flight control of ActuatorCommand
enableSwashplateLevellingControl(false); enableSwashplateLevellingControl(false);
m_ccpm->SwashLvlStartButton->setEnabled(true); m_aircraft->SwashLvlStartButton->setEnabled(true);
m_ccpm->SwashLvlNextButton->setEnabled(false); m_aircraft->SwashLvlNextButton->setEnabled(false);
m_ccpm->SwashLvlCancelButton->setEnabled(false); m_aircraft->SwashLvlCancelButton->setEnabled(false);
m_ccpm->SwashLvlFinishButton->setEnabled(false); m_aircraft->SwashLvlFinishButton->setEnabled(false);
break; break;
default: default:
// should never be reached // should never be reached
break; break;
} }
} }
void ConfigCcpmWidget::SwashLvlNextButtonPressed() void ConfigCcpmWidget::SwashLvlNextButtonPressed()
{ {
//ShowDisclaimer(2); //ShowDisclaimer(2);
SwashLvlState++; SwashLvlState++;
int i;
switch (SwashLvlState) {
switch (SwashLvlState)
{
case 0: case 0:
break; break;
case 1: //Neutral levelling case 1: //Neutral levelling
m_ccpm->SwashLvlStepList->setCurrentRow(0); m_aircraft->SwashLvlStepList->setCurrentRow(0);
//set spin boxes and swashplate servos to Neutral values //set spin boxes and swashplate servos to Neutral values
setSwashplateLevel(50); setSwashplateLevel(50);
//disable position slider //disable position slider
m_ccpm->SwashLvlPositionSlider->setEnabled(false); m_aircraft->SwashLvlPositionSlider->setEnabled(false);
m_ccpm->SwashLvlPositionSpinBox->setEnabled(false); m_aircraft->SwashLvlPositionSpinBox->setEnabled(false);
//set position slider to 50% //set position slider to 50%
m_ccpm->SwashLvlPositionSlider->setValue(50); m_aircraft->SwashLvlPositionSlider->setValue(50);
m_ccpm->SwashLvlPositionSpinBox->setValue(50); m_aircraft->SwashLvlPositionSpinBox->setValue(50);
//connect spinbox signals to slots and ebnable them //connect spinbox signals to slots and ebnable them
for (i=0;i<CCPM_MAX_SWASH_SERVOS;i++) for (int i = 0; i < CCPM_MAX_SWASH_SERVOS; i++) {
{
connect(SwashLvlSpinBoxes[i], SIGNAL(valueChanged(int)), this, SLOT(SwashLvlSpinBoxChanged(int))); connect(SwashLvlSpinBoxes[i], SIGNAL(valueChanged(int)), this, SLOT(SwashLvlSpinBoxChanged(int)));
SwashLvlSpinBoxes[i]->setEnabled(true); SwashLvlSpinBoxes[i]->setEnabled(true);
} }
//issue user instructions //issue user instructions
m_ccpm->SwashLvlStepInstruction->setHtml("<h2>Neutral levelling</h2><p>Using adjustment of:<ul><li>servo horns<li>link lengths and<li>Neutral timing spinboxes to the right</ul><br>ensure that the swashplate is in the center of desired travel range and is level."); m_aircraft->SwashLvlStepInstruction->setHtml(
"<h2>Neutral levelling</h2><p>Using adjustment of:<ul><li>servo horns<li>link lengths and<li>Neutral timing spinboxes to the right</ul><br>ensure that the swashplate is in the center of desired travel range and is level.");
break; break;
case 2: //Max levelling case 2: //Max levelling
//check Neutral status as complete //check Neutral status as complete
m_ccpm->SwashLvlStepList->item(0)->setCheckState(Qt::Checked); m_aircraft->SwashLvlStepList->item(0)->setCheckState(Qt::Checked);
m_ccpm->SwashLvlStepList->setCurrentRow(1); m_aircraft->SwashLvlStepList->setCurrentRow(1);
//set spin boxes and swashplate servos to Max values //set spin boxes and swashplate servos to Max values
setSwashplateLevel(100); setSwashplateLevel(100);
//set position slider to 100% //set position slider to 100%
m_ccpm->SwashLvlPositionSlider->setValue(100); m_aircraft->SwashLvlPositionSlider->setValue(100);
m_ccpm->SwashLvlPositionSpinBox->setValue(100); m_aircraft->SwashLvlPositionSpinBox->setValue(100);
//issue user instructions //issue user instructions
m_ccpm->SwashLvlStepInstruction->setText("<h2>Max levelling</h2><p>Using adjustment of:<ul><li>Max timing spinboxes to the right ONLY</ul><br>ensure that the swashplate is at the top of desired travel range and is level."); m_aircraft->SwashLvlStepInstruction->setText(
"<h2>Max levelling</h2><p>Using adjustment of:<ul><li>Max timing spinboxes to the right ONLY</ul><br>ensure that the swashplate is at the top of desired travel range and is level.");
break; break;
case 3: //Min levelling case 3: //Min levelling
//check Max status as complete //check Max status as complete
m_ccpm->SwashLvlStepList->item(1)->setCheckState(Qt::Checked); m_aircraft->SwashLvlStepList->item(1)->setCheckState(Qt::Checked);
m_ccpm->SwashLvlStepList->setCurrentRow(2); m_aircraft->SwashLvlStepList->setCurrentRow(2);
//set spin boxes and swashplate servos to Min values //set spin boxes and swashplate servos to Min values
setSwashplateLevel(0); setSwashplateLevel(0);
//set position slider to 0% //set position slider to 0%
m_ccpm->SwashLvlPositionSlider->setValue(0); m_aircraft->SwashLvlPositionSlider->setValue(0);
m_ccpm->SwashLvlPositionSpinBox->setValue(0); m_aircraft->SwashLvlPositionSpinBox->setValue(0);
//issue user instructions //issue user instructions
m_ccpm->SwashLvlStepInstruction->setText("<h2>Min levelling</h2><p>Using adjustment of:<ul><li>Min timing spinboxes to the right ONLY</ul><br>ensure that the swashplate is at the bottom of desired travel range and is level."); m_aircraft->SwashLvlStepInstruction->setText(
break; "<h2>Min levelling</h2><p>Using adjustment of:<ul><li>Min timing spinboxes to the right ONLY</ul><br>ensure that the swashplate is at the bottom of desired travel range and is level.");
break;
case 4: //levelling verification case 4: //levelling verification
//check Min status as complete //check Min status as complete
m_ccpm->SwashLvlStepList->item(2)->setCheckState(Qt::Checked); m_aircraft->SwashLvlStepList->item(2)->setCheckState(Qt::Checked);
m_ccpm->SwashLvlStepList->setCurrentRow(3); m_aircraft->SwashLvlStepList->setCurrentRow(3);
//enable position slider //enable position slider
m_ccpm->SwashLvlPositionSlider->setEnabled(true); m_aircraft->SwashLvlPositionSlider->setEnabled(true);
m_ccpm->SwashLvlPositionSpinBox->setEnabled(true); m_aircraft->SwashLvlPositionSpinBox->setEnabled(true);
//make heli respond to slider movement //make heli respond to slider movement
connect(m_ccpm->SwashLvlPositionSlider, SIGNAL(valueChanged(int)), this, SLOT(setSwashplateLevel(int))); connect(m_aircraft->SwashLvlPositionSlider, SIGNAL(valueChanged(int)), this, SLOT(setSwashplateLevel(int)));
//disable spin boxes //disable spin boxes
for (i=0;i<CCPM_MAX_SWASH_SERVOS;i++) for (int i = 0; i < CCPM_MAX_SWASH_SERVOS; i++) {
{
SwashLvlSpinBoxes[i]->setEnabled(false); SwashLvlSpinBoxes[i]->setEnabled(false);
} }
//issue user instructions //issue user instructions
m_ccpm->SwashLvlStepInstruction->setText("<h2>levelling verification</h2><p>Adjust the slider to the right over it's full range and observe the swashplate motion. It should remain level over the entire range of travel."); m_aircraft->SwashLvlStepInstruction->setText(
break; "<h2>levelling verification</h2><p>Adjust the slider to the right over it's full range and observe the swashplate motion. It should remain level over the entire range of travel.");
break;
case 5: //levelling complete case 5: //levelling complete
//check verify status as complete //check verify status as complete
m_ccpm->SwashLvlStepList->item(3)->setCheckState(Qt::Checked); m_aircraft->SwashLvlStepList->item(3)->setCheckState(Qt::Checked);
//issue user instructions //issue user instructions
m_ccpm->SwashLvlStepInstruction->setText("<h2>levelling complete</h2><p>Press the Finish button to save these settings to the SD card<p>Press the cancel button to return to the pre-levelling settings"); m_aircraft->SwashLvlStepInstruction->setText(
"<h2>levelling complete</h2><p>Press the Finish button to save these settings to the SD card<p>Press the cancel button to return to the pre-levelling settings");
//disable position slider //disable position slider
m_ccpm->SwashLvlPositionSlider->setEnabled(false); m_aircraft->SwashLvlPositionSlider->setEnabled(false);
m_ccpm->SwashLvlPositionSpinBox->setEnabled(false); m_aircraft->SwashLvlPositionSpinBox->setEnabled(false);
//disconnect levelling slots from signals //disconnect levelling slots from signals
disconnect(m_ccpm->SwashLvlPositionSlider, SIGNAL(valueChanged(int)), this, SLOT(setSwashplateLevel(int))); disconnect(m_aircraft->SwashLvlPositionSlider, SIGNAL(valueChanged(int)), this, SLOT(setSwashplateLevel(int)));
for (i=0;i<CCPM_MAX_SWASH_SERVOS;i++) for (int i = 0; i < CCPM_MAX_SWASH_SERVOS; i++) {
{
disconnect(SwashLvlSpinBoxes[i], SIGNAL(valueChanged(int)), this, SLOT(SwashLvlSpinBoxChanged(int))); disconnect(SwashLvlSpinBoxes[i], SIGNAL(valueChanged(int)), this, SLOT(SwashLvlSpinBoxChanged(int)));
} }
m_ccpm->SwashLvlStartButton->setEnabled(false); m_aircraft->SwashLvlStartButton->setEnabled(false);
m_ccpm->SwashLvlNextButton->setEnabled(false); m_aircraft->SwashLvlNextButton->setEnabled(false);
m_ccpm->SwashLvlCancelButton->setEnabled(true); m_aircraft->SwashLvlCancelButton->setEnabled(true);
m_ccpm->SwashLvlFinishButton->setEnabled(true); m_aircraft->SwashLvlFinishButton->setEnabled(true);
default: default:
//restore collective/cyclic setting //restore collective/cyclic setting
@ -1231,24 +1241,24 @@ void ConfigCcpmWidget::SwashLvlNextButtonPressed()
break; break;
} }
} }
void ConfigCcpmWidget::SwashLvlCancelButtonPressed() void ConfigCcpmWidget::SwashLvlCancelButtonPressed()
{ {
int i; SwashLvlState = 0;
SwashLvlState=0;
UAVObjectField* MinField; UAVObjectField *MinField;
UAVObjectField* NeutralField; UAVObjectField *NeutralField;
UAVObjectField* MaxField; UAVObjectField *MaxField;
m_ccpm->SwashLvlStartButton->setEnabled(true); m_aircraft->SwashLvlStartButton->setEnabled(true);
m_ccpm->SwashLvlNextButton->setEnabled(false); m_aircraft->SwashLvlNextButton->setEnabled(false);
m_ccpm->SwashLvlCancelButton->setEnabled(false); m_aircraft->SwashLvlCancelButton->setEnabled(false);
m_ccpm->SwashLvlFinishButton->setEnabled(false); m_aircraft->SwashLvlFinishButton->setEnabled(false);
m_ccpm->SwashLvlStepList->item(0)->setCheckState(Qt::Unchecked); m_aircraft->SwashLvlStepList->item(0)->setCheckState(Qt::Unchecked);
m_ccpm->SwashLvlStepList->item(1)->setCheckState(Qt::Unchecked); m_aircraft->SwashLvlStepList->item(1)->setCheckState(Qt::Unchecked);
m_ccpm->SwashLvlStepList->item(2)->setCheckState(Qt::Unchecked); m_aircraft->SwashLvlStepList->item(2)->setCheckState(Qt::Unchecked);
m_ccpm->SwashLvlStepList->item(3)->setCheckState(Qt::Unchecked); m_aircraft->SwashLvlStepList->item(3)->setCheckState(Qt::Unchecked);
//restore old Actuator Settings //restore old Actuator Settings
ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance(); ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance();
@ -1260,110 +1270,110 @@ void ConfigCcpmWidget::SwashLvlCancelButtonPressed()
NeutralField = obj->getField(QString("ChannelNeutral")); NeutralField = obj->getField(QString("ChannelNeutral"));
MaxField = obj->getField(QString("ChannelMax")); MaxField = obj->getField(QString("ChannelMax"));
//min,neutral,max values for the servos // min,neutral,max values for the servos
for (i=0;i<CCPM_MAX_SWASH_SERVOS;i++) for (int i = 0; i < CCPM_MAX_SWASH_SERVOS; i++) {
{ MinField->setValue(oldSwashLvlConfiguration.Min[i], oldSwashLvlConfiguration.ServoChannels[i]);
MinField->setValue(oldSwashLvlConfiguration.Min[i],oldSwashLvlConfiguration.ServoChannels[i]); NeutralField->setValue(oldSwashLvlConfiguration.Neutral[i], oldSwashLvlConfiguration.ServoChannels[i]);
NeutralField->setValue(oldSwashLvlConfiguration.Neutral[i],oldSwashLvlConfiguration.ServoChannels[i]); MaxField->setValue(oldSwashLvlConfiguration.Max[i], oldSwashLvlConfiguration.ServoChannels[i]);
MaxField->setValue(oldSwashLvlConfiguration.Max[i],oldSwashLvlConfiguration.ServoChannels[i]);
} }
obj->updated(); obj->updated();
// restore Flight control of ActuatorCommand
//restore Flight control of ActuatorCommand
enableSwashplateLevellingControl(false); enableSwashplateLevellingControl(false);
m_ccpm->SwashLvlStepInstruction->setText("<h2>Levelling Cancelled</h2><p>Previous settings have been restored."); m_aircraft->SwashLvlStepInstruction->setText(
"<h2>Levelling Cancelled</h2><p>Previous settings have been restored.");
} }
void ConfigCcpmWidget::SwashLvlFinishButtonPressed() void ConfigCcpmWidget::SwashLvlFinishButtonPressed()
{ {
int i; UAVObjectField *MinField;
UAVObjectField *NeutralField;
UAVObjectField *MaxField;
UAVObjectField* MinField; m_aircraft->SwashLvlStartButton->setEnabled(true);
UAVObjectField* NeutralField; m_aircraft->SwashLvlNextButton->setEnabled(false);
UAVObjectField* MaxField; m_aircraft->SwashLvlCancelButton->setEnabled(false);
m_aircraft->SwashLvlFinishButton->setEnabled(false);
m_ccpm->SwashLvlStartButton->setEnabled(true); // save new Actuator Settings to memory and SD card
m_ccpm->SwashLvlNextButton->setEnabled(false);
m_ccpm->SwashLvlCancelButton->setEnabled(false);
m_ccpm->SwashLvlFinishButton->setEnabled(false);
//save new Actuator Settings to memory and SD card
ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance(); ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance();
UAVObjectManager *objManager = pm->getObject<UAVObjectManager>(); UAVObjectManager *objManager = pm->getObject<UAVObjectManager>();
UAVDataObject* obj = dynamic_cast<UAVDataObject*>(objManager->getObject(QString("ActuatorSettings"))); UAVDataObject* obj = dynamic_cast<UAVDataObject*>(objManager->getObject(QString("ActuatorSettings")));
Q_ASSERT(obj); Q_ASSERT(obj);
//update settings to match our changes.
// update settings to match our changes.
MinField = obj->getField(QString("ChannelMin")); MinField = obj->getField(QString("ChannelMin"));
NeutralField = obj->getField(QString("ChannelNeutral")); NeutralField = obj->getField(QString("ChannelNeutral"));
MaxField = obj->getField(QString("ChannelMax")); MaxField = obj->getField(QString("ChannelMax"));
//min,neutral,max values for the servos // min,neutral,max values for the servos
for (i=0;i<CCPM_MAX_SWASH_SERVOS;i++) for (int i = 0; i < CCPM_MAX_SWASH_SERVOS; i++) {
{ MinField->setValue(newSwashLvlConfiguration.Min[i], newSwashLvlConfiguration.ServoChannels[i]);
MinField->setValue(newSwashLvlConfiguration.Min[i],newSwashLvlConfiguration.ServoChannels[i]); NeutralField->setValue(newSwashLvlConfiguration.Neutral[i], newSwashLvlConfiguration.ServoChannels[i]);
NeutralField->setValue(newSwashLvlConfiguration.Neutral[i],newSwashLvlConfiguration.ServoChannels[i]); MaxField->setValue(newSwashLvlConfiguration.Max[i], newSwashLvlConfiguration.ServoChannels[i]);
MaxField->setValue(newSwashLvlConfiguration.Max[i],newSwashLvlConfiguration.ServoChannels[i]);
} }
obj->updated(); obj->updated();
saveObjectToSD(obj); saveObjectToSD(obj);
//restore Flight control of ActuatorCommand // restore Flight control of ActuatorCommand
enableSwashplateLevellingControl(false); enableSwashplateLevellingControl(false);
m_ccpm->SwashLvlStepInstruction->setText("<h2>Levelling Completed</h2><p>New settings have been saved to the SD card"); m_aircraft->SwashLvlStepInstruction->setText(
"<h2>Levelling Completed</h2><p>New settings have been saved to the SD card");
ShowDisclaimer(0); ShowDisclaimer(0);
//ShowDisclaimer(2); //ShowDisclaimer(2);
} }
int ConfigCcpmWidget::ShowDisclaimer(int messageID) int ConfigCcpmWidget::ShowDisclaimer(int messageID)
{ {
QMessageBox msgBox; QMessageBox msgBox;
msgBox.setText("<font color=red><h1>Warning!!!</h2></font>"); msgBox.setText("<font color=red><h1>Warning!!!</h2></font>");
int ret; int ret;
switch (messageID) { switch (messageID) {
case 0: case 0:
// Basic disclaimer // Basic disclaimer
msgBox.setInformativeText("<h2>This code has many configurations.</h2><p>Please double check all settings before attempting flight!"); msgBox.setInformativeText(
msgBox.setStandardButtons(QMessageBox::Ok); "<h2>This code has many configurations.</h2><p>Please double check all settings before attempting flight!");
msgBox.setDefaultButton(QMessageBox::Ok); msgBox.setStandardButtons(QMessageBox::Ok);
msgBox.setIcon(QMessageBox::Information); msgBox.setDefaultButton(QMessageBox::Ok);
ret = msgBox.exec(); msgBox.setIcon(QMessageBox::Information);
return 0; ret = msgBox.exec();
break; return 0;
case 1: break;
// Not Tested disclaimer case 1:
msgBox.setInformativeText("<h2>The CCPM mixer code needs more testing!</h2><p><font color=red>Use it at your own risk!</font><p>Do you wish to continue?"); // Not Tested disclaimer
msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::Cancel); msgBox.setInformativeText(
msgBox.setDefaultButton(QMessageBox::Cancel); "<h2>The CCPM mixer code needs more testing!</h2><p><font color=red>Use it at your own risk!</font><p>Do you wish to continue?");
msgBox.setIcon(QMessageBox::Warning); msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::Cancel);
ret = msgBox.exec(); msgBox.setDefaultButton(QMessageBox::Cancel);
switch (ret) msgBox.setIcon(QMessageBox::Warning);
{ ret = msgBox.exec();
case QMessageBox::Cancel: return -1; switch (ret) {
case QMessageBox::Yes: return 0; case QMessageBox::Cancel:
} return -1;
break; case QMessageBox::Yes:
case 2:
// DO NOT use
msgBox.setInformativeText("<h2>The CCPM swashplate levelling code is NOT complete!</h2><p><font color=red>DO NOT use it for flight!</font>");
msgBox.setStandardButtons(QMessageBox::Ok);
msgBox.setDefaultButton(QMessageBox::Ok);
msgBox.setIcon(QMessageBox::Critical);
ret = msgBox.exec();
return 0; return 0;
break;
default:
// should never be reached
break;
} }
break;
case 2:
// DO NOT use
msgBox.setInformativeText(
"<h2>The CCPM swashplate levelling code is NOT complete!</h2><p><font color=red>DO NOT use it for flight!</font>");
msgBox.setStandardButtons(QMessageBox::Ok);
msgBox.setDefaultButton(QMessageBox::Ok);
msgBox.setIcon(QMessageBox::Critical);
ret = msgBox.exec();
return 0;
break;
default:
// should never be reached
break;
}
return -1; return -1;
} }
@ -1379,33 +1389,30 @@ void ConfigCcpmWidget::enableSwashplateLevellingControl(bool state)
UAVDataObject* obj = dynamic_cast<UAVDataObject*>(objManager->getObject(QString("ActuatorCommand"))); UAVDataObject* obj = dynamic_cast<UAVDataObject*>(objManager->getObject(QString("ActuatorCommand")));
UAVObject::Metadata mdata = obj->getMetadata(); UAVObject::Metadata mdata = obj->getMetadata();
if (state) if (state) {
{
SwashLvlaccInitialData = mdata; SwashLvlaccInitialData = mdata;
UAVObject::SetFlightAccess(mdata, UAVObject::ACCESS_READONLY); UAVObject::SetFlightAccess(mdata, UAVObject::ACCESS_READONLY);
UAVObject::SetFlightTelemetryUpdateMode(mdata, UAVObject::UPDATEMODE_ONCHANGE); UAVObject::SetFlightTelemetryUpdateMode(mdata, UAVObject::UPDATEMODE_ONCHANGE);
UAVObject::SetGcsTelemetryAcked(mdata, false); UAVObject::SetGcsTelemetryAcked(mdata, false);
UAVObject::SetGcsTelemetryUpdateMode(mdata, UAVObject::UPDATEMODE_ONCHANGE); UAVObject::SetGcsTelemetryUpdateMode(mdata, UAVObject::UPDATEMODE_ONCHANGE);
mdata.gcsTelemetryUpdatePeriod = 100; mdata.gcsTelemetryUpdatePeriod = 100;
SwashLvlConfigurationInProgress=1; SwashLvlConfigurationInProgress = 1;
m_ccpm->TabObject->setTabEnabled(0,0); m_aircraft->TabObject->setTabEnabled(0, 0);
m_ccpm->TabObject->setTabEnabled(2,0); m_aircraft->TabObject->setTabEnabled(2, 0);
m_ccpm->TabObject->setTabEnabled(3,0); m_aircraft->TabObject->setTabEnabled(3, 0);
m_ccpm->ccpmType->setEnabled(0); m_aircraft->ccpmType->setEnabled(0);
} } else {
else // Restore metadata
{ mdata = SwashLvlaccInitialData;
mdata = SwashLvlaccInitialData; // Restore metadata SwashLvlConfigurationInProgress = 0;
SwashLvlConfigurationInProgress=0;
m_ccpm->TabObject->setTabEnabled(0,1); m_aircraft->TabObject->setTabEnabled(0, 1);
m_ccpm->TabObject->setTabEnabled(2,1); m_aircraft->TabObject->setTabEnabled(2, 1);
m_ccpm->TabObject->setTabEnabled(3,1); m_aircraft->TabObject->setTabEnabled(3, 1);
m_ccpm->ccpmType->setEnabled(1); m_aircraft->ccpmType->setEnabled(1);
} }
obj->setMetadata(mdata); obj->setMetadata(mdata);
} }
/** /**
@ -1414,26 +1421,34 @@ void ConfigCcpmWidget::enableSwashplateLevellingControl(bool state)
*/ */
void ConfigCcpmWidget::setSwashplateLevel(int percent) void ConfigCcpmWidget::setSwashplateLevel(int percent)
{ {
if (percent<0)return;// -1; if (percent < 0) {
if (percent>100)return;// -1; return; // -1;
if (SwashLvlConfigurationInProgress!=1)return;// -1; }
int i; if (percent > 100) {
double value; return; // -1;
double level = ((double)percent /50.00) - 1.00; }
if (SwashLvlConfigurationInProgress != 1) {
return; // -1;
}
SwashLvlServoInterlock=1; double level = ((double) percent / 50.00) - 1.00;
ActuatorCommand * actuatorCommand = ActuatorCommand::GetInstance(getObjectManager()); SwashLvlServoInterlock = 1;
ActuatorCommand *actuatorCommand = ActuatorCommand::GetInstance(getObjectManager());
ActuatorCommand::DataFields actuatorCommandData = actuatorCommand->getData(); ActuatorCommand::DataFields actuatorCommandData = actuatorCommand->getData();
for (i=0;i<CCPM_MAX_SWASH_SERVOS;i++) { for (int i = 0; i < CCPM_MAX_SWASH_SERVOS; i++) {
if (level==0) double value;
if (level == 0) {
value = newSwashLvlConfiguration.Neutral[i]; value = newSwashLvlConfiguration.Neutral[i];
else if (level > 0) } else if (level > 0) {
value = (newSwashLvlConfiguration.Max[i] - newSwashLvlConfiguration.Neutral[i])*level + newSwashLvlConfiguration.Neutral[i]; value = (newSwashLvlConfiguration.Max[i] - newSwashLvlConfiguration.Neutral[i]) * level
else if (level < 0) + newSwashLvlConfiguration.Neutral[i];
value = (newSwashLvlConfiguration.Neutral[i] - newSwashLvlConfiguration.Min[i])*level + newSwashLvlConfiguration.Neutral[i]; } else if (level < 0) {
value = (newSwashLvlConfiguration.Neutral[i] - newSwashLvlConfiguration.Min[i]) * level
+ newSwashLvlConfiguration.Neutral[i];
}
actuatorCommandData.Channel[newSwashLvlConfiguration.ServoChannels[i]] = value; actuatorCommandData.Channel[newSwashLvlConfiguration.ServoChannels[i]] = value;
SwashLvlSpinBoxes[i]->setValue(value); SwashLvlSpinBoxes[i]->setValue(value);
} }
@ -1441,38 +1456,42 @@ void ConfigCcpmWidget::setSwashplateLevel(int percent)
actuatorCommand->setData(actuatorCommandData); actuatorCommand->setData(actuatorCommandData);
actuatorCommand->updated(); actuatorCommand->updated();
SwashLvlServoInterlock=0; SwashLvlServoInterlock = 0;
return;
} }
void ConfigCcpmWidget::SwashLvlSpinBoxChanged(int value) void ConfigCcpmWidget::SwashLvlSpinBoxChanged(int value)
{ {
Q_UNUSED(value); Q_UNUSED(value);
int i;
if (SwashLvlServoInterlock==1)return;
ActuatorCommand * actuatorCommand = ActuatorCommand::GetInstance(getObjectManager()); if (SwashLvlServoInterlock == 1) {
return;
}
ActuatorCommand *actuatorCommand = ActuatorCommand::GetInstance(getObjectManager());
ActuatorCommand::DataFields actuatorCommandData = actuatorCommand->getData(); ActuatorCommand::DataFields actuatorCommandData = actuatorCommand->getData();
for (i = 0; i < CCPM_MAX_SWASH_SERVOS; i++) { for (int i = 0; i < CCPM_MAX_SWASH_SERVOS; i++) {
value = SwashLvlSpinBoxes[i]->value(); value = SwashLvlSpinBoxes[i]->value();
switch (SwashLvlState) switch (SwashLvlState) {
{ case 1:
case 1: //Neutral levelling // Neutral levelling
newSwashLvlConfiguration.Neutral[i]=value; newSwashLvlConfiguration.Neutral[i] = value;
break; break;
case 2: //Max levelling case 2:
// Max levelling
newSwashLvlConfiguration.Max[i] = value; newSwashLvlConfiguration.Max[i] = value;
break; break;
case 3: //Min levelling case 3:
newSwashLvlConfiguration.Min[i]= value; // Min levelling
newSwashLvlConfiguration.Min[i] = value;
break; break;
case 4: //levelling verification case 4:
// levelling verification
break; break;
case 5: //levelling complete case 5:
// levelling complete
break; break;
default: default:
break; break;
@ -1481,7 +1500,6 @@ void ConfigCcpmWidget::SwashLvlSpinBoxChanged(int value)
actuatorCommandData.Channel[newSwashLvlConfiguration.ServoChannels[i]] = value; actuatorCommandData.Channel[newSwashLvlConfiguration.ServoChannels[i]] = value;
} }
actuatorCommand->setData(actuatorCommandData); actuatorCommand->setData(actuatorCommandData);
actuatorCommand->updated(); actuatorCommand->updated();
@ -1497,63 +1515,45 @@ bool ConfigCcpmWidget::throwConfigError(QString airframeType)
bool error = false; bool error = false;
if((m_ccpm->ccpmServoWChannel->currentIndex()==0) && (m_ccpm->ccpmServoWChannel->isEnabled())) if ((m_aircraft->ccpmServoWChannel->currentIndex() == 0) && (m_aircraft->ccpmServoWChannel->isEnabled())) {
{ m_aircraft->ccpmServoWLabel->setText("<font color=red>" + m_aircraft->ccpmServoWLabel->text() + "</font>");
m_ccpm->ccpmServoWLabel->setText("<font color=red>" + m_ccpm->ccpmServoWLabel->text() + "</font>");
error = true; error = true;
} } else {
else m_aircraft->ccpmServoWLabel->setText(QTextEdit(m_aircraft->ccpmServoWLabel->text()).toPlainText());
{
m_ccpm->ccpmServoWLabel->setText(QTextEdit(m_ccpm->ccpmServoWLabel->text()).toPlainText());
} }
if((m_ccpm->ccpmServoXChannel->currentIndex()==0) && (m_ccpm->ccpmServoXChannel->isEnabled())) if ((m_aircraft->ccpmServoXChannel->currentIndex() == 0) && (m_aircraft->ccpmServoXChannel->isEnabled())) {
{ m_aircraft->ccpmServoXLabel->setText("<font color=red>" + m_aircraft->ccpmServoXLabel->text() + "</font>");
m_ccpm->ccpmServoXLabel->setText("<font color=red>" + m_ccpm->ccpmServoXLabel->text() + "</font>");
error = true; error = true;
} } else {
else m_aircraft->ccpmServoXLabel->setText(QTextEdit(m_aircraft->ccpmServoXLabel->text()).toPlainText());
{
m_ccpm->ccpmServoXLabel->setText(QTextEdit(m_ccpm->ccpmServoXLabel->text()).toPlainText());
} }
if((m_ccpm->ccpmServoYChannel->currentIndex()==0) && (m_ccpm->ccpmServoYChannel->isEnabled())) if ((m_aircraft->ccpmServoYChannel->currentIndex() == 0) && (m_aircraft->ccpmServoYChannel->isEnabled())) {
{ m_aircraft->ccpmServoYLabel->setText("<font color=red>" + m_aircraft->ccpmServoYLabel->text() + "</font>");
m_ccpm->ccpmServoYLabel->setText("<font color=red>" + m_ccpm->ccpmServoYLabel->text() + "</font>");
error = true; error = true;
} } else {
else m_aircraft->ccpmServoYLabel->setText(QTextEdit(m_aircraft->ccpmServoYLabel->text()).toPlainText());
{
m_ccpm->ccpmServoYLabel->setText(QTextEdit(m_ccpm->ccpmServoYLabel->text()).toPlainText());
} }
if((m_ccpm->ccpmServoZChannel->currentIndex()==0) && (m_ccpm->ccpmServoZChannel->isEnabled())) if ((m_aircraft->ccpmServoZChannel->currentIndex() == 0) && (m_aircraft->ccpmServoZChannel->isEnabled())) {
{ m_aircraft->ccpmServoZLabel->setText("<font color=red>" + m_aircraft->ccpmServoZLabel->text() + "</font>");
m_ccpm->ccpmServoZLabel->setText("<font color=red>" + m_ccpm->ccpmServoZLabel->text()+ "</font>");
error = true; error = true;
} } else {
else m_aircraft->ccpmServoZLabel->setText(QTextEdit(m_aircraft->ccpmServoZLabel->text()).toPlainText());
{
m_ccpm->ccpmServoZLabel->setText(QTextEdit(m_ccpm->ccpmServoZLabel->text()).toPlainText());
} }
if((m_ccpm->ccpmEngineChannel->currentIndex()==0) && (m_ccpm->ccpmEngineChannel->isEnabled())) if ((m_aircraft->ccpmEngineChannel->currentIndex() == 0) && (m_aircraft->ccpmEngineChannel->isEnabled())) {
{ m_aircraft->ccpmEngineLabel->setText("<font color=red>" + m_aircraft->ccpmEngineLabel->text() + "</font>");
m_ccpm->ccpmEngineLabel->setText("<font color=red>" + m_ccpm->ccpmEngineLabel->text() + "</font>"); } else {
} m_aircraft->ccpmEngineLabel->setText(QTextEdit(m_aircraft->ccpmEngineLabel->text()).toPlainText());
else
{
m_ccpm->ccpmEngineLabel->setText(QTextEdit(m_ccpm->ccpmEngineLabel->text()).toPlainText());
} }
if((m_ccpm->ccpmTailChannel->currentIndex()==0) && (m_ccpm->ccpmTailChannel->isEnabled())) if ((m_aircraft->ccpmTailChannel->currentIndex() == 0) && (m_aircraft->ccpmTailChannel->isEnabled())) {
{ m_aircraft->ccpmTailLabel->setText("<font color=red>" + m_aircraft->ccpmTailLabel->text() + "</font>");
m_ccpm->ccpmTailLabel->setText("<font color=red>" + m_ccpm->ccpmTailLabel->text() + "</font>");
error = true; error = true;
} } else {
else m_aircraft->ccpmTailLabel->setText(QTextEdit(m_aircraft->ccpmTailLabel->text()).toPlainText());
{
m_ccpm->ccpmTailLabel->setText(QTextEdit(m_ccpm->ccpmTailLabel->text()).toPlainText());
} }

View File

@ -27,12 +27,13 @@
#ifndef CONFIGccpmWIDGET_H #ifndef CONFIGccpmWIDGET_H
#define CONFIGccpmWIDGET_H #define CONFIGccpmWIDGET_H
#include "ui_ccpm.h"
#include "../uavobjectwidgetutils/configtaskwidget.h"
#include "cfg_vehicletypes/vehicleconfig.h" #include "cfg_vehicletypes/vehicleconfig.h"
#include "ui_airframe_ccpm.h"
#include "../uavobjectwidgetutils/configtaskwidget.h"
#include "extensionsystem/pluginmanager.h" #include "extensionsystem/pluginmanager.h"
#include "uavobjectmanager.h" #include "uavobjectmanager.h"
#include "uavobject.h" #include "uavobject.h"
#include <QtSvg/QSvgRenderer> #include <QtSvg/QSvgRenderer>
#include <QtSvg/QGraphicsSvgItem> #include <QtSvg/QGraphicsSvgItem>
#include <QGraphicsEllipseItem> #include <QGraphicsEllipseItem>
@ -51,83 +52,85 @@ typedef struct {
int Min[CCPM_MAX_SWASH_SERVOS]; int Min[CCPM_MAX_SWASH_SERVOS];
} SwashplateServoSettingsStruct; } SwashplateServoSettingsStruct;
class ConfigCcpmWidget: public VehicleConfig class ConfigCcpmWidget: public VehicleConfig
{ {
Q_OBJECT Q_OBJECT
public: public:
static QStringList getChannelDescriptions();
ConfigCcpmWidget(QWidget *parent = 0); ConfigCcpmWidget(QWidget *parent = 0);
~ConfigCcpmWidget(); ~ConfigCcpmWidget();
friend class ConfigVehicleTypeWidget; virtual void refreshWidgetsValues(QString frameType);
virtual QString updateConfigObjectsFromWidgets();
private: public slots:
Ui_ccpmWidget *m_ccpm; void getMixer();
QGraphicsSvgItem *SwashplateImg; void setMixer();
QGraphicsSvgItem *CurveImg; void saveccpmUpdate();
QGraphicsSvgItem *Servos[CCPM_MAX_SWASH_SERVOS];
QGraphicsTextItem *ServosText[CCPM_MAX_SWASH_SERVOS];
QGraphicsLineItem *ServoLines[CCPM_MAX_SWASH_SERVOS];
QGraphicsEllipseItem *ServosTextCircles[CCPM_MAX_SWASH_SERVOS];
QSpinBox *SwashLvlSpinBoxes[CCPM_MAX_SWASH_SERVOS];
QString TypeText;
bool SwashLvlConfigurationInProgress;
UAVObject::Metadata SwashLvlaccInitialData;
int SwashLvlState;
int SwashLvlServoInterlock;
SwashplateServoSettingsStruct oldSwashLvlConfiguration;
SwashplateServoSettingsStruct newSwashLvlConfiguration;
int MixerChannelData[6];
int ShowDisclaimer(int messageID);
virtual void enableControls(bool enable) { Q_UNUSED(enable)}; // Not used by this widget
bool updatingFromHardware;
bool updatingToHardware;
virtual void ResetActuators(GUIConfigDataUnion* configData);
static QStringList getChannelDescriptions();
QString updateConfigObjects();
private slots:
virtual void setupUI(QString airframeType);
virtual void refreshWidgetsValues(QString frameType);
virtual QString updateConfigObjectsFromWidgets();
virtual bool throwConfigError(QString airframeType);
void ccpmSwashplateUpdate();
void ccpmSwashplateRedraw();
void UpdateMixer();
void UpdateType();
void SwashLvlStartButtonPressed();
void SwashLvlNextButtonPressed();
void SwashLvlCancelButtonPressed();
void SwashLvlFinishButtonPressed();
//void UpdateCCPMOptionsFromUI();
//void UpdateCCPMUIFromOptions();
void SetUIComponentVisibilities();
void enableSwashplateLevellingControl(bool state);
void setSwashplateLevel(int percent);
void SwashLvlSpinBoxChanged(int value);
virtual void refreshValues() {}; // Not used
public slots:
void getMixer();
void setMixer();
void saveccpmUpdate();
protected: protected:
void showEvent(QShowEvent *event); void showEvent(QShowEvent *event);
void resizeEvent(QResizeEvent *event); void resizeEvent(QResizeEvent *event);
private:
Ui_CcpmConfigWidget *m_aircraft;
QGraphicsSvgItem *SwashplateImg;
QGraphicsSvgItem *CurveImg;
QGraphicsSvgItem *Servos[CCPM_MAX_SWASH_SERVOS];
QGraphicsTextItem *ServosText[CCPM_MAX_SWASH_SERVOS];
QGraphicsLineItem *ServoLines[CCPM_MAX_SWASH_SERVOS];
QGraphicsEllipseItem *ServosTextCircles[CCPM_MAX_SWASH_SERVOS];
QSpinBox *SwashLvlSpinBoxes[CCPM_MAX_SWASH_SERVOS];
QString TypeText;
bool SwashLvlConfigurationInProgress;
UAVObject::Metadata SwashLvlaccInitialData;
int SwashLvlState;
int SwashLvlServoInterlock;
SwashplateServoSettingsStruct oldSwashLvlConfiguration;
SwashplateServoSettingsStruct newSwashLvlConfiguration;
int MixerChannelData[6];
virtual void registerWidgets(ConfigTaskWidget &parent);
virtual void resetActuators(GUIConfigDataUnion *configData);
int ShowDisclaimer(int messageID);
virtual void enableControls(bool enable) { Q_UNUSED(enable) }; // Not used by this widget
bool updatingFromHardware;
bool updatingToHardware;
QString updateConfigObjects();
private slots:
virtual void setupUI(QString airframeType);
virtual bool throwConfigError(QString airframeType);
void ccpmSwashplateUpdate();
void ccpmSwashplateRedraw();
void UpdateMixer();
void UpdateType();
void SwashLvlStartButtonPressed();
void SwashLvlNextButtonPressed();
void SwashLvlCancelButtonPressed();
void SwashLvlFinishButtonPressed();
//void UpdateCCPMOptionsFromUI();
//void UpdateCCPMUIFromOptions();
void SetUIComponentVisibilities();
void enableSwashplateLevellingControl(bool state);
void setSwashplateLevel(int percent);
void SwashLvlSpinBoxChanged(int value);
virtual void refreshValues() {}; // Not used
}; };
#endif // CONFIGccpmWIDGET_H #endif // CONFIGccpmWIDGET_H

View File

@ -0,0 +1,296 @@
/**
******************************************************************************
*
* @file configmultirotorwidget.cpp
* @author E. Lafargue & The OpenPilot Team, http://www.openpilot.org Copyright (C) 2012.
* @addtogroup GCSPlugins GCS Plugins
* @{
* @addtogroup ConfigPlugin Config Plugin
* @{
* @brief ccpm 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 "configcustomwidget.h"
#include "mixersettings.h"
#include <QDebug>
#include <QStringList>
#include <QtGui/QWidget>
#include <QtGui/QTextEdit>
#include <QtGui/QVBoxLayout>
#include <QtGui/QPushButton>
#include <QtGui/QComboBox>
#include <QBrush>
#include <math.h>
#include <QMessageBox>
QStringList ConfigCustomWidget::getChannelDescriptions()
{
QStringList channelDesc;
for (int i = 0; i < (int) VehicleConfig::CHANNEL_NUMELEM; i++) {
channelDesc.append(QString("-"));
}
return channelDesc;
}
ConfigCustomWidget::ConfigCustomWidget(QWidget *parent) :
VehicleConfig(parent), m_aircraft(new Ui_CustomConfigWidget())
{
m_aircraft->setupUi(this);
// Put combo boxes in line one of the custom mixer table:
UAVDataObject *mixer = dynamic_cast<UAVDataObject *>(getObjectManager()->getObject(QString("MixerSettings")));
Q_ASSERT(mixer);
UAVObjectField* field = mixer->getField(QString("Mixer1Type"));
QStringList list = field->getOptions();
for (int i = 0; i < (int) VehicleConfig::CHANNEL_NUMELEM; 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 < (int) VehicleConfig::CHANNEL_NUMELEM; i++) {
m_aircraft->customMixerTable->setItemDelegateForRow(i, sbd);
}
}
ConfigCustomWidget::~ConfigCustomWidget()
{
delete m_aircraft;
}
void ConfigCustomWidget::setupUI(QString frameType)
{
Q_ASSERT(m_aircraft);
}
void ConfigCustomWidget::registerWidgets(ConfigTaskWidget &parent) {
parent.addWidget(m_aircraft->customMixerTable);
parent.addWidget(m_aircraft->customThrottle1Curve->getCurveWidget());
parent.addWidget(m_aircraft->customThrottle2Curve->getCurveWidget());
}
void ConfigCustomWidget::resetActuators(GUIConfigDataUnion *configData)
{
}
/**
Helper function to refresh the UI widget values
*/
void ConfigCustomWidget::refreshWidgetsValues(QString frameType)
{
Q_ASSERT(m_aircraft);
setupUI(frameType);
UAVDataObject *mixer = dynamic_cast<UAVDataObject *>(getObjectManager()->getObject(QString("MixerSettings")));
Q_ASSERT(mixer);
QList<double> curveValues;
getThrottleCurve(mixer, VehicleConfig::MIXER_THROTTLECURVE1, &curveValues);
// is at least one of the curve values != 0?
if (isValidThrottleCurve(&curveValues)) {
// yes, use the curve we just read from mixersettings
m_aircraft->customThrottle1Curve->initCurve(&curveValues);
}
else {
// no, init a straight curve
m_aircraft->customThrottle1Curve->initLinearCurve(curveValues.count(), 1.0);
}
if (MixerSettings *mxr = qobject_cast<MixerSettings *>(mixer)) {
MixerSettings::DataFields mixerSettingsData = mxr->getData();
if (mixerSettingsData.Curve2Source == MixerSettings::CURVE2SOURCE_THROTTLE)
m_aircraft->customThrottle2Curve->setMixerType(MixerCurve::MIXERCURVE_THROTTLE);
else {
m_aircraft->customThrottle2Curve->setMixerType(MixerCurve::MIXERCURVE_PITCH);
}
}
// Setup all Throttle2 curves for all types of airframes
getThrottleCurve(mixer, VehicleConfig::MIXER_THROTTLECURVE2, &curveValues);
if (isValidThrottleCurve(&curveValues)) {
m_aircraft->customThrottle2Curve->initCurve(&curveValues);
}
else {
m_aircraft->customThrottle2Curve->initLinearCurve(curveValues.count(), 1.0, m_aircraft->customThrottle2Curve->getMin());
}
// Update the mixer table:
for (int channel = 0; channel < m_aircraft->customMixerTable->columnCount(); channel++) {
UAVObjectField* field = mixer->getField(mixerTypes.at(channel));
if (field) {
QComboBox* q = (QComboBox*) m_aircraft->customMixerTable->cellWidget(0, channel);
if (q) {
QString s = field->getValue().toString();
setComboCurrentIndex(q, q->findText(s));
}
m_aircraft->customMixerTable->item(1, channel)->setText(
QString::number(getMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_THROTTLECURVE1)));
m_aircraft->customMixerTable->item(2, channel)->setText(
QString::number(getMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_THROTTLECURVE2)));
m_aircraft->customMixerTable->item(3, channel)->setText(
QString::number(getMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_ROLL)));
m_aircraft->customMixerTable->item(4, channel)->setText(
QString::number(getMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_PITCH)));
m_aircraft->customMixerTable->item(5, channel)->setText(
QString::number(getMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_YAW)));
}
}
}
/**
Helper function to
*/
QString ConfigCustomWidget::updateConfigObjectsFromWidgets()
{
UAVDataObject *mixer = dynamic_cast<UAVDataObject *>(getObjectManager()->getObject(QString("MixerSettings")));
Q_ASSERT(mixer);
setThrottleCurve(mixer, VehicleConfig::MIXER_THROTTLECURVE1, m_aircraft->customThrottle1Curve->getCurve());
setThrottleCurve(mixer, VehicleConfig::MIXER_THROTTLECURVE2, m_aircraft->customThrottle2Curve->getCurve());
// Update the table:
for (int channel = 0; channel < (int) VehicleConfig::CHANNEL_NUMELEM; channel++) {
QComboBox* q = (QComboBox*) m_aircraft->customMixerTable->cellWidget(0, channel);
if (q->currentText() == "Disabled") {
setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_DISABLED);
} else if (q->currentText() == "Motor") {
setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_MOTOR);
} else if (q->currentText() == "Servo") {
setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_SERVO);
} else if (q->currentText() == "CameraRoll") {
setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_CAMERAROLL);
} else if (q->currentText() == "CameraPitch") {
setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_CAMERAPITCH);
} else if (q->currentText() == "CameraYaw") {
setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_CAMERAYAW);
} else if (q->currentText() == "Accessory0") {
setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_ACCESSORY0);
} else if (q->currentText() == "Accessory1") {
setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_ACCESSORY1);
} else if (q->currentText() == "Accessory2") {
setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_ACCESSORY2);
} else if (q->currentText() == "Accessory3") {
setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_ACCESSORY3);
} else if (q->currentText() == "Accessory4") {
setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_ACCESSORY4);
} else if (q->currentText() == "Accessory5") {
setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_ACCESSORY5);
}
setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_THROTTLECURVE1,
m_aircraft->customMixerTable->item(1, channel)->text().toDouble());
setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_THROTTLECURVE2,
m_aircraft->customMixerTable->item(2, channel)->text().toDouble());
setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_ROLL,
m_aircraft->customMixerTable->item(3, channel)->text().toDouble());
setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_PITCH,
m_aircraft->customMixerTable->item(4, channel)->text().toDouble());
setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_YAW,
m_aircraft->customMixerTable->item(5, channel)->text().toDouble());
}
return "Custom";
}
/**
This function displays text and color formatting in order to help the user understand what channels have not yet been configured.
*/
bool ConfigCustomWidget::throwConfigError(int numMotors)
{
return false;
}
/**
WHAT DOES THIS DO???
*/
void ConfigCustomWidget::showEvent(QShowEvent *event)
{
Q_UNUSED(event);
// Make the custom table columns autostretch:
m_aircraft->customMixerTable->resizeColumnsToContents();
int channelCount = (int) VehicleConfig::CHANNEL_NUMELEM;
for (int i = 0; i < channelCount; i++) {
m_aircraft->customMixerTable->setColumnWidth(i,
(m_aircraft->customMixerTable->width() - m_aircraft->customMixerTable->verticalHeader()->width())
/ channelCount);
}
}
/**
Resize the GUI contents when the user changes the window size
*/
void ConfigCustomWidget::resizeEvent(QResizeEvent *event)
{
Q_UNUSED(event);
// Make the custom table columns autostretch:
m_aircraft->customMixerTable->resizeColumnsToContents();
int channelCount = (int) VehicleConfig::CHANNEL_NUMELEM;
for (int i = 0; i < channelCount; i++) {
m_aircraft->customMixerTable->setColumnWidth(i,
(m_aircraft->customMixerTable->width() - m_aircraft->customMixerTable->verticalHeader()->width())
/ channelCount);
}
}
/**
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);
}

View File

@ -0,0 +1,88 @@
/**
******************************************************************************
*
* @file configairframetwidget.h
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2012.
* @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
*/
#ifndef CONFIGCUSTOMWIDGET_H
#define CONFIGCUSTOMWIDGET_H
#include "cfg_vehicletypes/vehicleconfig.h"
#include "ui_airframe_custom.h"
#include "../uavobjectwidgetutils/configtaskwidget.h"
#include "extensionsystem/pluginmanager.h"
#include "uavobjectmanager.h"
#include "uavobject.h"
#include "uavtalk/telemetrymanager.h"
#include <QtGui/QWidget>
#include <QList>
#include <QItemDelegate>
class Ui_Widget;
class ConfigCustomWidget: public VehicleConfig
{
Q_OBJECT
public:
static QStringList getChannelDescriptions();
ConfigCustomWidget(QWidget *parent = 0);
~ConfigCustomWidget();
virtual void refreshWidgetsValues(QString frameType);
virtual QString updateConfigObjectsFromWidgets();
protected:
void showEvent(QShowEvent *event);
void resizeEvent(QResizeEvent *event);
private:
Ui_CustomConfigWidget *m_aircraft;
virtual void registerWidgets(ConfigTaskWidget &parent);
virtual void resetActuators(GUIConfigDataUnion *configData);
private slots:
virtual void setupUI(QString airframeType);
virtual bool throwConfigError(int numMotors);
};
class SpinBoxDelegate : public QItemDelegate
{
Q_OBJECT
public:
SpinBoxDelegate(QObject *parent = 0);
QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const;
void setEditorData(QWidget *editor, const QModelIndex &index) const;
void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const;
void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const;
};
#endif // CONFIGCUSTOMWIDGET_H

View File

@ -25,8 +25,10 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/ */
#include "configfixedwingwidget.h" #include "configfixedwingwidget.h"
#include "configvehicletypewidget.h"
#include "mixersettings.h" #include "mixersettings.h"
#include "systemsettings.h"
#include "actuatorsettings.h"
#include "actuatorcommand.h"
#include <QDebug> #include <QDebug>
#include <QStringList> #include <QStringList>
@ -38,29 +40,65 @@
#include <math.h> #include <math.h>
#include <QMessageBox> #include <QMessageBox>
#include "mixersettings.h" QStringList ConfigFixedWingWidget::getChannelDescriptions()
#include "systemsettings.h"
#include "actuatorsettings.h"
#include "actuatorcommand.h"
/**
Constructor
*/
ConfigFixedWingWidget::ConfigFixedWingWidget(Ui_AircraftWidget *aircraft, QWidget *parent) : VehicleConfig(parent)
{ {
m_aircraft = aircraft; // init a channel_numelem list of channel desc defaults
QStringList channelDesc;
for (int i = 0; i < (int) ConfigFixedWingWidget::CHANNEL_NUMELEM; i++) {
channelDesc.append(QString("-"));
}
// get the gui config data
GUIConfigDataUnion configData = getConfigData();
if (configData.fixedwing.FixedWingPitch1 > 0) {
channelDesc[configData.fixedwing.FixedWingPitch1 - 1] = QString("FixedWingPitch1");
}
if (configData.fixedwing.FixedWingPitch2 > 0) {
channelDesc[configData.fixedwing.FixedWingPitch2 - 1] = QString("FixedWingPitch2");
}
if (configData.fixedwing.FixedWingRoll1 > 0) {
channelDesc[configData.fixedwing.FixedWingRoll1 - 1] = QString("FixedWingRoll1");
}
if (configData.fixedwing.FixedWingRoll2 > 0) {
channelDesc[configData.fixedwing.FixedWingRoll2 - 1] = QString("FixedWingRoll2");
}
if (configData.fixedwing.FixedWingYaw1 > 0) {
channelDesc[configData.fixedwing.FixedWingYaw1 - 1] = QString("FixedWingYaw1");
}
if (configData.fixedwing.FixedWingYaw2 > 0) {
channelDesc[configData.fixedwing.FixedWingYaw2 - 1] = QString("FixedWingYaw2");
}
if (configData.fixedwing.FixedWingThrottle > 0) {
channelDesc[configData.fixedwing.FixedWingThrottle - 1] = QString("FixedWingThrottle");
}
return channelDesc;
}
ConfigFixedWingWidget::ConfigFixedWingWidget(QWidget *parent) :
VehicleConfig(parent), m_aircraft(new Ui_FixedWingConfigWidget())
{
m_aircraft->setupUi(this);
populateChannelComboBoxes();
QStringList fixedWingTypes;
fixedWingTypes << "Elevator aileron rudder" << "Elevon" << "Vtail";
m_aircraft->fixedWingType->addItems(fixedWingTypes);
// Set default model to "Elevator aileron rudder"
m_aircraft->fixedWingType->setCurrentIndex(m_aircraft->fixedWingType->findText("Elevator aileron rudder"));
//setupUI(m_aircraft->fixedWingType->currentText());
connect(m_aircraft->fixedWingType, SIGNAL(currentIndexChanged(QString)), this, SLOT(setupUI(QString)));
} }
/**
Destructor
*/
ConfigFixedWingWidget::~ConfigFixedWingWidget() ConfigFixedWingWidget::~ConfigFixedWingWidget()
{ {
// Do nothing delete m_aircraft;
} }
/** /**
Virtual function to setup the UI Virtual function to setup the UI
*/ */
@ -69,8 +107,6 @@ void ConfigFixedWingWidget::setupUI(QString frameType)
Q_ASSERT(m_aircraft); Q_ASSERT(m_aircraft);
if (frameType == "FixedWing" || frameType == "Elevator aileron rudder") { if (frameType == "FixedWing" || frameType == "Elevator aileron rudder") {
// Setup the UI
setComboCurrentIndex(m_aircraft->aircraftType, m_aircraft->aircraftType->findText("Fixed Wing"));
setComboCurrentIndex(m_aircraft->fixedWingType, m_aircraft->fixedWingType->findText("Elevator aileron rudder")); setComboCurrentIndex(m_aircraft->fixedWingType, m_aircraft->fixedWingType->findText("Elevator aileron rudder"));
m_aircraft->fwRudder1ChannelBox->setEnabled(true); m_aircraft->fwRudder1ChannelBox->setEnabled(true);
m_aircraft->fwRudder1Label->setEnabled(true); m_aircraft->fwRudder1Label->setEnabled(true);
@ -92,7 +128,6 @@ void ConfigFixedWingWidget::setupUI(QString frameType)
m_aircraft->elevonMixBox->setHidden(true); m_aircraft->elevonMixBox->setHidden(true);
} else if (frameType == "FixedWingElevon" || frameType == "Elevon") { } else if (frameType == "FixedWingElevon" || frameType == "Elevon") {
setComboCurrentIndex(m_aircraft->aircraftType, m_aircraft->aircraftType->findText("Fixed Wing"));
setComboCurrentIndex(m_aircraft->fixedWingType, m_aircraft->fixedWingType->findText("Elevon")); setComboCurrentIndex(m_aircraft->fixedWingType, m_aircraft->fixedWingType->findText("Elevon"));
m_aircraft->fwAileron1Label->setText("Elevon 1"); m_aircraft->fwAileron1Label->setText("Elevon 1");
m_aircraft->fwAileron2Label->setText("Elevon 2"); m_aircraft->fwAileron2Label->setText("Elevon 2");
@ -111,7 +146,6 @@ void ConfigFixedWingWidget::setupUI(QString frameType)
m_aircraft->elevonLabel2->setText("Pitch"); m_aircraft->elevonLabel2->setText("Pitch");
} else if (frameType == "FixedWingVtail" || frameType == "Vtail") { } else if (frameType == "FixedWingVtail" || frameType == "Vtail") {
setComboCurrentIndex(m_aircraft->aircraftType, m_aircraft->aircraftType->findText("Fixed Wing"));
setComboCurrentIndex(m_aircraft->fixedWingType, m_aircraft->fixedWingType->findText("Vtail")); setComboCurrentIndex(m_aircraft->fixedWingType, m_aircraft->fixedWingType->findText("Vtail"));
m_aircraft->fwRudder1ChannelBox->setEnabled(false); m_aircraft->fwRudder1ChannelBox->setEnabled(false);
m_aircraft->fwRudder1Label->setEnabled(false); m_aircraft->fwRudder1Label->setEnabled(false);
@ -131,7 +165,22 @@ void ConfigFixedWingWidget::setupUI(QString frameType)
} }
} }
void ConfigFixedWingWidget::ResetActuators(GUIConfigDataUnion* configData) void ConfigFixedWingWidget::registerWidgets(ConfigTaskWidget &parent) {
parent.addWidget(m_aircraft->fixedWingThrottle->getCurveWidget());
parent.addWidget(m_aircraft->fixedWingType);
parent.addWidget(m_aircraft->fwEngineChannelBox);
parent.addWidget(m_aircraft->fwAileron1ChannelBox);
parent.addWidget(m_aircraft->fwAileron2ChannelBox);
parent.addWidget(m_aircraft->fwElevator1ChannelBox);
parent.addWidget(m_aircraft->fwElevator2ChannelBox);
parent.addWidget(m_aircraft->fwRudder1ChannelBox);
parent.addWidget(m_aircraft->fwRudder2ChannelBox);
parent.addWidget(m_aircraft->elevonSlider1);
parent.addWidget(m_aircraft->elevonSlider2);
}
void ConfigFixedWingWidget::resetActuators(GUIConfigDataUnion *configData)
{ {
configData->fixedwing.FixedWingPitch1 = 0; configData->fixedwing.FixedWingPitch1 = 0;
configData->fixedwing.FixedWingPitch2 = 0; configData->fixedwing.FixedWingPitch2 = 0;
@ -142,36 +191,65 @@ void ConfigFixedWingWidget::ResetActuators(GUIConfigDataUnion* configData)
configData->fixedwing.FixedWingThrottle = 0; configData->fixedwing.FixedWingThrottle = 0;
} }
QStringList ConfigFixedWingWidget::getChannelDescriptions() /**
Virtual function to refresh the UI widget values
*/
void ConfigFixedWingWidget::refreshWidgetsValues(QString frameType)
{ {
int i; Q_ASSERT(m_aircraft);
QStringList channelDesc;
// init a channel_numelem list of channel desc defaults setupUI(frameType);
for (i=0; i < (int)(ConfigFixedWingWidget::CHANNEL_NUMELEM); i++)
{ UAVDataObject *mixer = dynamic_cast<UAVDataObject *>(getObjectManager()->getObject(QString("MixerSettings")));
channelDesc.append(QString("-")); Q_ASSERT(mixer);
QList<double> curveValues;
getThrottleCurve(mixer, VehicleConfig::MIXER_THROTTLECURVE1, &curveValues);
// is at least one of the curve values != 0?
if (isValidThrottleCurve(&curveValues)) {
// yes, use the curve we just read from mixersettings
m_aircraft->fixedWingThrottle->initCurve(&curveValues);
}
else {
// no, init a straight curve
m_aircraft->fixedWingThrottle->initLinearCurve(curveValues.count(), 1.0);
} }
// get the gui config data GUIConfigDataUnion config = getConfigData();
GUIConfigDataUnion configData = GetConfigData(); fixedGUISettingsStruct fixed = config.fixedwing;
if (configData.fixedwing.FixedWingPitch1 > 0) // Then retrieve how channels are setup
channelDesc[configData.fixedwing.FixedWingPitch1-1] = QString("FixedWingPitch1"); setComboCurrentIndex(m_aircraft->fwEngineChannelBox, fixed.FixedWingThrottle);
if (configData.fixedwing.FixedWingPitch2 > 0) setComboCurrentIndex(m_aircraft->fwAileron1ChannelBox, fixed.FixedWingRoll1);
channelDesc[configData.fixedwing.FixedWingPitch2-1] = QString("FixedWingPitch2"); setComboCurrentIndex(m_aircraft->fwAileron2ChannelBox, fixed.FixedWingRoll2);
if (configData.fixedwing.FixedWingRoll1 > 0) setComboCurrentIndex(m_aircraft->fwElevator1ChannelBox, fixed.FixedWingPitch1);
channelDesc[configData.fixedwing.FixedWingRoll1-1] = QString("FixedWingRoll1"); setComboCurrentIndex(m_aircraft->fwElevator2ChannelBox, fixed.FixedWingPitch2);
if (configData.fixedwing.FixedWingRoll2 > 0) setComboCurrentIndex(m_aircraft->fwRudder1ChannelBox, fixed.FixedWingYaw1);
channelDesc[configData.fixedwing.FixedWingRoll2-1] = QString("FixedWingRoll2"); setComboCurrentIndex(m_aircraft->fwRudder2ChannelBox, fixed.FixedWingYaw2);
if (configData.fixedwing.FixedWingYaw1 > 0)
channelDesc[configData.fixedwing.FixedWingYaw1-1] = QString("FixedWingYaw1");
if (configData.fixedwing.FixedWingYaw2 > 0)
channelDesc[configData.fixedwing.FixedWingYaw2-1] = QString("FixedWingYaw2");
if (configData.fixedwing.FixedWingThrottle > 0)
channelDesc[configData.fixedwing.FixedWingThrottle-1] = QString("FixedWingThrottle");
return channelDesc; if (frameType == "FixedWingElevon") {
// If the airframe is elevon, restore the slider setting
// Find the channel number for Elevon1 (FixedWingRoll1)
int channel = m_aircraft->fwAileron1ChannelBox->currentIndex() - 1;
if (channel > -1) {
// If for some reason the actuators were incoherent, we might fail here, hence the check.
m_aircraft->elevonSlider1->setValue(
getMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_ROLL) * 100);
m_aircraft->elevonSlider2->setValue(
getMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_PITCH) * 100);
}
}
else if (frameType == "FixedWingVtail") {
int channel = m_aircraft->fwElevator1ChannelBox->currentIndex() - 1;
if (channel > -1) {
// If for some reason the actuators were incoherent, we might fail here, hence the check.
m_aircraft->elevonSlider1->setValue(
getMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_YAW) * 100);
m_aircraft->elevonSlider2->setValue(
getMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_PITCH) * 100);
}
}
} }
/** /**
@ -191,7 +269,7 @@ QString ConfigFixedWingWidget::updateConfigObjectsFromWidgets()
// Set the throttle curve // Set the throttle curve
setThrottleCurve(mixer,VehicleConfig::MIXER_THROTTLECURVE1, m_aircraft->fixedWingThrottle->getCurve()); setThrottleCurve(mixer,VehicleConfig::MIXER_THROTTLECURVE1, m_aircraft->fixedWingThrottle->getCurve());
//All airframe types must start with "FixedWing" // All airframe types must start with "FixedWing"
if (m_aircraft->fixedWingType->currentText() == "Elevator aileron rudder" ) { if (m_aircraft->fixedWingType->currentText() == "Elevator aileron rudder" ) {
airframeType = "FixedWing"; airframeType = "FixedWing";
setupFrameFixedWing( airframeType ); setupFrameFixedWing( airframeType );
@ -206,50 +284,6 @@ QString ConfigFixedWingWidget::updateConfigObjectsFromWidgets()
return airframeType; return airframeType;
} }
/**
Virtual function to refresh the UI widget values
*/
void ConfigFixedWingWidget::refreshWidgetsValues(QString frameType)
{
Q_ASSERT(m_aircraft);
GUIConfigDataUnion config = GetConfigData();
fixedGUISettingsStruct fixed = config.fixedwing;
// Then retrieve how channels are setup
setComboCurrentIndex(m_aircraft->fwEngineChannelBox, fixed.FixedWingThrottle);
setComboCurrentIndex(m_aircraft->fwAileron1ChannelBox, fixed.FixedWingRoll1);
setComboCurrentIndex(m_aircraft->fwAileron2ChannelBox, fixed.FixedWingRoll2);
setComboCurrentIndex(m_aircraft->fwElevator1ChannelBox, fixed.FixedWingPitch1);
setComboCurrentIndex(m_aircraft->fwElevator2ChannelBox, fixed.FixedWingPitch2);
setComboCurrentIndex(m_aircraft->fwRudder1ChannelBox, fixed.FixedWingYaw1);
setComboCurrentIndex(m_aircraft->fwRudder2ChannelBox, fixed.FixedWingYaw2);
UAVDataObject* mixer= dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
Q_ASSERT(mixer);
int channel;
if (frameType == "FixedWingElevon") {
// If the airframe is elevon, restore the slider setting
// Find the channel number for Elevon1 (FixedWingRoll1)
channel = m_aircraft->fwAileron1ChannelBox->currentIndex()-1;
if (channel > -1) { // If for some reason the actuators were incoherent, we might fail here, hence the check.
m_aircraft->elevonSlider1->setValue(getMixerVectorValue(mixer,channel,VehicleConfig::MIXERVECTOR_ROLL)*100);
m_aircraft->elevonSlider2->setValue(getMixerVectorValue(mixer,channel,VehicleConfig::MIXERVECTOR_PITCH)*100);
}
}
if (frameType == "FixedWingVtail") {
channel = m_aircraft->fwElevator1ChannelBox->currentIndex()-1;
if (channel > -1) { // If for some reason the actuators were incoherent, we might fail here, hence the check.
m_aircraft->elevonSlider1->setValue(getMixerVectorValue(mixer,channel,VehicleConfig::MIXERVECTOR_YAW)*100);
m_aircraft->elevonSlider2->setValue(getMixerVectorValue(mixer,channel,VehicleConfig::MIXERVECTOR_PITCH)*100);
}
}
}
/** /**
Setup Elevator/Aileron/Rudder airframe. Setup Elevator/Aileron/Rudder airframe.
@ -260,15 +294,14 @@ void ConfigFixedWingWidget::refreshWidgetsValues(QString frameType)
bool ConfigFixedWingWidget::setupFrameFixedWing(QString airframeType) bool ConfigFixedWingWidget::setupFrameFixedWing(QString airframeType)
{ {
// Check coherence: // Check coherence:
//Show any config errors in GUI // Show any config errors in GUI
if (throwConfigError(airframeType)) { if (throwConfigError(airframeType)) {
return false; return false;
} }
// Now setup the channels: // Now setup the channels:
GUIConfigDataUnion config = getConfigData();
GUIConfigDataUnion config = GetConfigData(); resetActuators(&config);
ResetActuators(&config);
config.fixedwing.FixedWingPitch1 = m_aircraft->fwElevator1ChannelBox->currentIndex(); config.fixedwing.FixedWingPitch1 = m_aircraft->fwElevator1ChannelBox->currentIndex();
config.fixedwing.FixedWingPitch2 = m_aircraft->fwElevator2ChannelBox->currentIndex(); config.fixedwing.FixedWingPitch2 = m_aircraft->fwElevator2ChannelBox->currentIndex();
@ -277,7 +310,7 @@ bool ConfigFixedWingWidget::setupFrameFixedWing(QString airframeType)
config.fixedwing.FixedWingYaw1 = m_aircraft->fwRudder1ChannelBox->currentIndex(); config.fixedwing.FixedWingYaw1 = m_aircraft->fwRudder1ChannelBox->currentIndex();
config.fixedwing.FixedWingThrottle = m_aircraft->fwEngineChannelBox->currentIndex(); config.fixedwing.FixedWingThrottle = m_aircraft->fwEngineChannelBox->currentIndex();
SetConfigData(config); setConfigData(config);
UAVDataObject* mixer = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings"))); UAVDataObject* mixer = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
Q_ASSERT(mixer); Q_ASSERT(mixer);
@ -289,35 +322,35 @@ bool ConfigFixedWingWidget::setupFrameFixedWing(QString airframeType)
// 1. Assign the servo/motor/none for each channel // 1. Assign the servo/motor/none for each channel
//motor // motor
int channel = m_aircraft->fwEngineChannelBox->currentIndex()-1; int channel = m_aircraft->fwEngineChannelBox->currentIndex() - 1;
setMixerType(mixer,channel,VehicleConfig::MIXERTYPE_MOTOR); setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_MOTOR);
setMixerVectorValue(mixer,channel,VehicleConfig::MIXERVECTOR_THROTTLECURVE1, 127); setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_THROTTLECURVE1, 127);
//rudder // rudder
channel = m_aircraft->fwRudder1ChannelBox->currentIndex()-1; channel = m_aircraft->fwRudder1ChannelBox->currentIndex() - 1;
setMixerType(mixer,channel,VehicleConfig::MIXERTYPE_SERVO); setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_SERVO);
setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_YAW, 127); setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_YAW, 127);
//ailerons // ailerons
channel = m_aircraft->fwAileron1ChannelBox->currentIndex()-1; channel = m_aircraft->fwAileron1ChannelBox->currentIndex() - 1;
if (channel > -1) { if (channel > -1) {
setMixerType(mixer,channel,VehicleConfig::MIXERTYPE_SERVO); setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_SERVO);
setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_ROLL, 127); setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_ROLL, 127);
channel = m_aircraft->fwAileron2ChannelBox->currentIndex()-1; channel = m_aircraft->fwAileron2ChannelBox->currentIndex() - 1;
setMixerType(mixer,channel,VehicleConfig::MIXERTYPE_SERVO); setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_SERVO);
setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_ROLL, 127); setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_ROLL, 127);
} }
//elevators // elevators
channel = m_aircraft->fwElevator1ChannelBox->currentIndex()-1; channel = m_aircraft->fwElevator1ChannelBox->currentIndex() - 1;
if (channel > -1) { if (channel > -1) {
setMixerType(mixer,channel,VehicleConfig::MIXERTYPE_SERVO); setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_SERVO);
setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_PITCH, 127); setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_PITCH, 127);
channel = m_aircraft->fwElevator2ChannelBox->currentIndex()-1; channel = m_aircraft->fwElevator2ChannelBox->currentIndex() - 1;
setMixerType(mixer,channel,VehicleConfig::MIXERTYPE_SERVO); setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_SERVO);
setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_PITCH, 127); setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_PITCH, 127);
} }
@ -326,21 +359,19 @@ bool ConfigFixedWingWidget::setupFrameFixedWing(QString airframeType)
return true; return true;
} }
/** /**
Setup Elevon Setup Elevon
*/ */
bool ConfigFixedWingWidget::setupFrameElevon(QString airframeType) bool ConfigFixedWingWidget::setupFrameElevon(QString airframeType)
{ {
// Check coherence: // Check coherence:
//Show any config errors in GUI // Show any config errors in GUI
if (throwConfigError(airframeType)) { if (throwConfigError(airframeType)) {
return false; return false;
} }
GUIConfigDataUnion config = GetConfigData(); GUIConfigDataUnion config = getConfigData();
ResetActuators(&config); resetActuators(&config);
config.fixedwing.FixedWingRoll1 = m_aircraft->fwAileron1ChannelBox->currentIndex(); config.fixedwing.FixedWingRoll1 = m_aircraft->fwAileron1ChannelBox->currentIndex();
config.fixedwing.FixedWingRoll2 = m_aircraft->fwAileron2ChannelBox->currentIndex(); config.fixedwing.FixedWingRoll2 = m_aircraft->fwAileron2ChannelBox->currentIndex();
@ -348,7 +379,7 @@ bool ConfigFixedWingWidget::setupFrameElevon(QString airframeType)
config.fixedwing.FixedWingYaw2 = m_aircraft->fwRudder2ChannelBox->currentIndex(); config.fixedwing.FixedWingYaw2 = m_aircraft->fwRudder2ChannelBox->currentIndex();
config.fixedwing.FixedWingThrottle = m_aircraft->fwEngineChannelBox->currentIndex(); config.fixedwing.FixedWingThrottle = m_aircraft->fwEngineChannelBox->currentIndex();
SetConfigData(config); setConfigData(config);
UAVDataObject* mixer = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings"))); UAVDataObject* mixer = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
Q_ASSERT(mixer); Q_ASSERT(mixer);
@ -363,34 +394,34 @@ bool ConfigFixedWingWidget::setupFrameElevon(QString airframeType)
double value; double value;
//motor // motor
int channel = m_aircraft->fwEngineChannelBox->currentIndex()-1; int channel = m_aircraft->fwEngineChannelBox->currentIndex() - 1;
setMixerType(mixer,channel,VehicleConfig::MIXERTYPE_MOTOR); setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_MOTOR);
setMixerVectorValue(mixer,channel,VehicleConfig::MIXERVECTOR_THROTTLECURVE1, 127); setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_THROTTLECURVE1, 127);
//rudders // rudders
channel = m_aircraft->fwRudder1ChannelBox->currentIndex()-1; channel = m_aircraft->fwRudder1ChannelBox->currentIndex() - 1;
setMixerType(mixer,channel,VehicleConfig::MIXERTYPE_SERVO); setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_SERVO);
setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_YAW, 127); setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_YAW, 127);
channel = m_aircraft->fwRudder2ChannelBox->currentIndex()-1; channel = m_aircraft->fwRudder2ChannelBox->currentIndex() - 1;
setMixerType(mixer,channel,VehicleConfig::MIXERTYPE_SERVO); setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_SERVO);
setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_YAW, -127); setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_YAW, -127);
//ailerons // ailerons
channel = m_aircraft->fwAileron1ChannelBox->currentIndex()-1; channel = m_aircraft->fwAileron1ChannelBox->currentIndex() - 1;
if (channel > -1) { if (channel > -1) {
setMixerType(mixer,channel,VehicleConfig::MIXERTYPE_SERVO); setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_SERVO);
value = (double)(m_aircraft->elevonSlider2->value()*1.27); value = (double) (m_aircraft->elevonSlider2->value() * 1.27);
setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_PITCH, value); setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_PITCH, value);
value = (double)(m_aircraft->elevonSlider1->value()*1.27); value = (double) (m_aircraft->elevonSlider1->value() * 1.27);
setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_ROLL, value); setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_ROLL, value);
channel = m_aircraft->fwAileron2ChannelBox->currentIndex()-1; channel = m_aircraft->fwAileron2ChannelBox->currentIndex() - 1;
setMixerType(mixer,channel,VehicleConfig::MIXERTYPE_SERVO); setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_SERVO);
value = (double)(m_aircraft->elevonSlider2->value()*1.27); value = (double) (m_aircraft->elevonSlider2->value() * 1.27);
setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_PITCH, value); setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_PITCH, value);
value = (double)(m_aircraft->elevonSlider1->value()*1.27); value = (double) (m_aircraft->elevonSlider1->value() * 1.27);
setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_ROLL, -value); setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_ROLL, -value);
} }
@ -398,21 +429,19 @@ bool ConfigFixedWingWidget::setupFrameElevon(QString airframeType)
return true; return true;
} }
/** /**
Setup VTail Setup VTail
*/ */
bool ConfigFixedWingWidget::setupFrameVtail(QString airframeType) bool ConfigFixedWingWidget::setupFrameVtail(QString airframeType)
{ {
// Check coherence: // Check coherence:
//Show any config errors in GUI // Show any config errors in GUI
if (throwConfigError(airframeType)) { if (throwConfigError(airframeType)) {
return false; return false;
} }
GUIConfigDataUnion config = GetConfigData(); GUIConfigDataUnion config = getConfigData();
ResetActuators(&config); resetActuators(&config);
config.fixedwing.FixedWingPitch1 = m_aircraft->fwElevator1ChannelBox->currentIndex(); config.fixedwing.FixedWingPitch1 = m_aircraft->fwElevator1ChannelBox->currentIndex();
config.fixedwing.FixedWingPitch2 = m_aircraft->fwElevator2ChannelBox->currentIndex(); config.fixedwing.FixedWingPitch2 = m_aircraft->fwElevator2ChannelBox->currentIndex();
@ -420,7 +449,7 @@ bool ConfigFixedWingWidget::setupFrameVtail(QString airframeType)
config.fixedwing.FixedWingRoll2 = m_aircraft->fwAileron2ChannelBox->currentIndex(); config.fixedwing.FixedWingRoll2 = m_aircraft->fwAileron2ChannelBox->currentIndex();
config.fixedwing.FixedWingThrottle = m_aircraft->fwEngineChannelBox->currentIndex(); config.fixedwing.FixedWingThrottle = m_aircraft->fwEngineChannelBox->currentIndex();
SetConfigData(config); setConfigData(config);
UAVDataObject* mixer = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings"))); UAVDataObject* mixer = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
Q_ASSERT(mixer); Q_ASSERT(mixer);
@ -433,14 +462,12 @@ bool ConfigFixedWingWidget::setupFrameVtail(QString airframeType)
// 1. Assign the servo/motor/none for each channel // 1. Assign the servo/motor/none for each channel
double value; // motor
//motor
int channel = m_aircraft->fwEngineChannelBox->currentIndex()-1; int channel = m_aircraft->fwEngineChannelBox->currentIndex()-1;
setMixerType(mixer,channel,VehicleConfig::MIXERTYPE_MOTOR); setMixerType(mixer,channel,VehicleConfig::MIXERTYPE_MOTOR);
setMixerVectorValue(mixer,channel,VehicleConfig::MIXERVECTOR_THROTTLECURVE1, 127); setMixerVectorValue(mixer,channel,VehicleConfig::MIXERVECTOR_THROTTLECURVE1, 127);
//rudders // rudders
channel = m_aircraft->fwRudder1ChannelBox->currentIndex()-1; channel = m_aircraft->fwRudder1ChannelBox->currentIndex()-1;
setMixerType(mixer,channel,VehicleConfig::MIXERTYPE_SERVO); setMixerType(mixer,channel,VehicleConfig::MIXERTYPE_SERVO);
setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_YAW, 127); setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_YAW, 127);
@ -449,7 +476,7 @@ bool ConfigFixedWingWidget::setupFrameVtail(QString airframeType)
setMixerType(mixer,channel,VehicleConfig::MIXERTYPE_SERVO); setMixerType(mixer,channel,VehicleConfig::MIXERTYPE_SERVO);
setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_YAW, -127); setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_YAW, -127);
//ailerons // ailerons
channel = m_aircraft->fwAileron1ChannelBox->currentIndex()-1; channel = m_aircraft->fwAileron1ChannelBox->currentIndex()-1;
if (channel > -1) { if (channel > -1) {
setMixerType(mixer,channel,VehicleConfig::MIXERTYPE_SERVO); setMixerType(mixer,channel,VehicleConfig::MIXERTYPE_SERVO);
@ -460,11 +487,11 @@ bool ConfigFixedWingWidget::setupFrameVtail(QString airframeType)
setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_ROLL, -127); setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_ROLL, -127);
} }
//vtail // vtail
channel = m_aircraft->fwElevator1ChannelBox->currentIndex()-1; channel = m_aircraft->fwElevator1ChannelBox->currentIndex()-1;
if (channel > -1) { if (channel > -1) {
setMixerType(mixer,channel,VehicleConfig::MIXERTYPE_SERVO); setMixerType(mixer,channel,VehicleConfig::MIXERTYPE_SERVO);
value = (double)(m_aircraft->elevonSlider2->value()*1.27); double value = (double)(m_aircraft->elevonSlider2->value()*1.27);
setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_PITCH, value); setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_PITCH, value);
value = (double)(m_aircraft->elevonSlider1->value()*1.27); value = (double)(m_aircraft->elevonSlider1->value()*1.27);
setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_YAW, value); setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_YAW, value);
@ -486,96 +513,88 @@ bool ConfigFixedWingWidget::setupFrameVtail(QString airframeType)
*/ */
bool ConfigFixedWingWidget::throwConfigError(QString airframeType) bool ConfigFixedWingWidget::throwConfigError(QString airframeType)
{ {
//Initialize configuration error flag // Initialize configuration error flag
bool error=false; bool error = false;
//Create a red block. All combo boxes are the same size, so any one should do as a model // Create a red block. All combo boxes are the same size, so any one should do as a model
int size = m_aircraft->fwEngineChannelBox->style()->pixelMetric(QStyle::PM_SmallIconSize); int size = m_aircraft->fwEngineChannelBox->style()->pixelMetric(QStyle::PM_SmallIconSize);
QPixmap pixmap(size,size); QPixmap pixmap(size, size);
pixmap.fill(QColor("red")); pixmap.fill(QColor("red"));
if (airframeType == "FixedWing" ) { if (airframeType == "FixedWing") {
if (m_aircraft->fwEngineChannelBox->currentText() == "None"){ if (m_aircraft->fwEngineChannelBox->currentText() == "None") {
m_aircraft->fwEngineChannelBox->setItemData(0, pixmap, Qt::DecorationRole);//Set color palettes m_aircraft->fwEngineChannelBox->setItemData(0, pixmap, Qt::DecorationRole); //Set color palettes
error=true; error = true;
} } else {
else{ m_aircraft->fwEngineChannelBox->setItemData(0, 0, Qt::DecorationRole); //Reset color palettes
m_aircraft->fwEngineChannelBox->setItemData(0, 0, Qt::DecorationRole);//Reset color palettes }
}
if (m_aircraft->fwElevator1ChannelBox->currentText() == "None"){ if (m_aircraft->fwElevator1ChannelBox->currentText() == "None") {
m_aircraft->fwElevator1ChannelBox->setItemData(0, pixmap, Qt::DecorationRole);//Set color palettes m_aircraft->fwElevator1ChannelBox->setItemData(0, pixmap, Qt::DecorationRole); //Set color palettes
error=true; error = true;
} } else {
else{ m_aircraft->fwElevator1ChannelBox->setItemData(0, 0, Qt::DecorationRole); //Reset color palettes
m_aircraft->fwElevator1ChannelBox->setItemData(0, 0, Qt::DecorationRole);//Reset color palettes }
}
if ((m_aircraft->fwAileron1ChannelBox->currentText() == "None") && (m_aircraft->fwRudder1ChannelBox->currentText() == "None")) { if ((m_aircraft->fwAileron1ChannelBox->currentText() == "None")
pixmap.fill(QColor("green")); && (m_aircraft->fwRudder1ChannelBox->currentText() == "None")) {
m_aircraft->fwAileron1ChannelBox->setItemData(0, pixmap, Qt::DecorationRole);//Set color palettes pixmap.fill(QColor("green"));
m_aircraft->fwRudder1ChannelBox->setItemData(0, pixmap, Qt::DecorationRole);//Set color palettes m_aircraft->fwAileron1ChannelBox->setItemData(0, pixmap, Qt::DecorationRole); //Set color palettes
error=true; m_aircraft->fwRudder1ChannelBox->setItemData(0, pixmap, Qt::DecorationRole); //Set color palettes
} error = true;
else{ } else {
m_aircraft->fwAileron1ChannelBox->setItemData(0, 0, Qt::DecorationRole);//Reset color palettes m_aircraft->fwAileron1ChannelBox->setItemData(0, 0, Qt::DecorationRole); //Reset color palettes
m_aircraft->fwRudder1ChannelBox->setItemData(0, 0, Qt::DecorationRole);//Reset color palettes m_aircraft->fwRudder1ChannelBox->setItemData(0, 0, Qt::DecorationRole); //Reset color palettes
} }
} else if (airframeType == "FixedWingElevon"){ } else if (airframeType == "FixedWingElevon") {
if (m_aircraft->fwEngineChannelBox->currentText() == "None"){ if (m_aircraft->fwEngineChannelBox->currentText() == "None") {
m_aircraft->fwEngineChannelBox->setItemData(0, pixmap, Qt::DecorationRole);//Set color palettes m_aircraft->fwEngineChannelBox->setItemData(0, pixmap, Qt::DecorationRole); //Set color palettes
error=true; error = true;
} } else {
else{ m_aircraft->fwEngineChannelBox->setItemData(0, 0, Qt::DecorationRole); //Reset color palettes
m_aircraft->fwEngineChannelBox->setItemData(0, 0, Qt::DecorationRole);//Reset color palettes }
}
if(m_aircraft->fwAileron1ChannelBox->currentText() == "None"){ if (m_aircraft->fwAileron1ChannelBox->currentText() == "None") {
m_aircraft->fwAileron1ChannelBox->setItemData(0, pixmap, Qt::DecorationRole);//Set color palettes m_aircraft->fwAileron1ChannelBox->setItemData(0, pixmap, Qt::DecorationRole); //Set color palettes
error=true; error = true;
} } else {
else{ m_aircraft->fwAileron1ChannelBox->setItemData(0, 0, Qt::DecorationRole); //Reset color palettes
m_aircraft->fwAileron1ChannelBox->setItemData(0, 0, Qt::DecorationRole);//Reset color palettes }
}
if (m_aircraft->fwAileron2ChannelBox->currentText() == "None"){ if (m_aircraft->fwAileron2ChannelBox->currentText() == "None") {
m_aircraft->fwAileron2ChannelBox->setItemData(0, pixmap, Qt::DecorationRole);//Set color palettes m_aircraft->fwAileron2ChannelBox->setItemData(0, pixmap, Qt::DecorationRole); //Set color palettes
error=true; error = true;
} } else {
else{ m_aircraft->fwAileron2ChannelBox->setItemData(0, 0, Qt::DecorationRole); //Reset color palettes
m_aircraft->fwAileron2ChannelBox->setItemData(0, 0, Qt::DecorationRole);//Reset color palettes }
}
} else if ( airframeType == "FixedWingVtail"){ } else if (airframeType == "FixedWingVtail") {
if (m_aircraft->fwEngineChannelBox->currentText() == "None"){ if (m_aircraft->fwEngineChannelBox->currentText() == "None") {
m_aircraft->fwEngineChannelBox->setItemData(0, pixmap, Qt::DecorationRole);//Set color palettes m_aircraft->fwEngineChannelBox->setItemData(0, pixmap, Qt::DecorationRole); //Set color palettes
error=true; error = true;
} } else {
else{ m_aircraft->fwEngineChannelBox->setItemData(0, 0, Qt::DecorationRole); //Reset color palettes
m_aircraft->fwEngineChannelBox->setItemData(0, 0, Qt::DecorationRole);//Reset color palettes }
}
if(m_aircraft->fwElevator1ChannelBox->currentText() == "None"){ if (m_aircraft->fwElevator1ChannelBox->currentText() == "None") {
m_aircraft->fwElevator1ChannelBox->setItemData(0, pixmap, Qt::DecorationRole);//Set color palettes m_aircraft->fwElevator1ChannelBox->setItemData(0, pixmap, Qt::DecorationRole); //Set color palettes
error=true; error = true;
} } else {
else{ m_aircraft->fwElevator1ChannelBox->setItemData(0, 0, Qt::DecorationRole); //Reset color palettes
m_aircraft->fwElevator1ChannelBox->setItemData(0, 0, Qt::DecorationRole);//Reset color palettes }
}
if(m_aircraft->fwElevator2ChannelBox->currentText() == "None"){ if (m_aircraft->fwElevator2ChannelBox->currentText() == "None") {
m_aircraft->fwElevator2ChannelBox->setItemData(0, pixmap, Qt::DecorationRole);//Set color palettes m_aircraft->fwElevator2ChannelBox->setItemData(0, pixmap, Qt::DecorationRole); //Set color palettes
error=true; error = true;
} } else {
else{ m_aircraft->fwElevator2ChannelBox->setItemData(0, 0, Qt::DecorationRole); //Reset color palettes
m_aircraft->fwElevator2ChannelBox->setItemData(0, 0, Qt::DecorationRole);//Reset color palettes }
}
} }
if (error){ if (error) {
m_aircraft->fwStatusLabel->setText(QString("<font color='red'>ERROR: Assign all necessary channels</font>")); m_aircraft->fwStatusLabel->setText(QString("<font color='red'>ERROR: Assign all necessary channels</font>"));
} }
return error; return error;
} }

View File

@ -27,12 +27,14 @@
#ifndef CONFIGFIXEDWINGWIDGET_H #ifndef CONFIGFIXEDWINGWIDGET_H
#define CONFIGFIXEDWINGWIDGET_H #define CONFIGFIXEDWINGWIDGET_H
#include "ui_airframe.h" #include "cfg_vehicletypes/vehicleconfig.h"
#include "ui_airframe_fixedwing.h"
#include "../uavobjectwidgetutils/configtaskwidget.h" #include "../uavobjectwidgetutils/configtaskwidget.h"
#include "extensionsystem/pluginmanager.h" #include "extensionsystem/pluginmanager.h"
#include "uavobjectmanager.h" #include "uavobjectmanager.h"
#include "uavobject.h" #include "uavobject.h"
#include "uavtalk/telemetrymanager.h" #include "uavtalk/telemetrymanager.h"
#include <QtGui/QWidget> #include <QtGui/QWidget>
#include <QList> #include <QList>
#include <QItemDelegate> #include <QItemDelegate>
@ -44,31 +46,28 @@ class ConfigFixedWingWidget: public VehicleConfig
Q_OBJECT Q_OBJECT
public: public:
ConfigFixedWingWidget(Ui_AircraftWidget *aircraft = 0, QWidget *parent = 0); static QStringList getChannelDescriptions();
ConfigFixedWingWidget(QWidget *parent = 0);
~ConfigFixedWingWidget(); ~ConfigFixedWingWidget();
friend class ConfigVehicleTypeWidget; virtual void refreshWidgetsValues(QString frameType);
virtual QString updateConfigObjectsFromWidgets();
private: private:
Ui_AircraftWidget *m_aircraft; Ui_FixedWingConfigWidget *m_aircraft;
virtual void registerWidgets(ConfigTaskWidget &parent);
virtual void resetActuators(GUIConfigDataUnion *configData);
bool setupFrameFixedWing(QString airframeType); bool setupFrameFixedWing(QString airframeType);
bool setupFrameElevon(QString airframeType); bool setupFrameElevon(QString airframeType);
bool setupFrameVtail(QString airframeType); bool setupFrameVtail(QString airframeType);
virtual void ResetActuators(GUIConfigDataUnion* configData);
static QStringList getChannelDescriptions();
private slots: private slots:
virtual void setupUI(QString airframeType); virtual void setupUI(QString airframeType);
virtual void refreshWidgetsValues(QString frameType);
virtual QString updateConfigObjectsFromWidgets();
virtual bool throwConfigError(QString airframeType); virtual bool throwConfigError(QString airframeType);
protected:
}; };
#endif // CONFIGFIXEDWINGWIDGET_H #endif // CONFIGFIXEDWINGWIDGET_H

View File

@ -25,8 +25,10 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/ */
#include "configgroundvehiclewidget.h" #include "configgroundvehiclewidget.h"
#include "configvehicletypewidget.h"
#include "mixersettings.h" #include "mixersettings.h"
#include "systemsettings.h"
#include "actuatorsettings.h"
#include "actuatorcommand.h"
#include <QDebug> #include <QDebug>
#include <QStringList> #include <QStringList>
@ -35,29 +37,58 @@
#include <QtGui/QVBoxLayout> #include <QtGui/QVBoxLayout>
#include <QtGui/QPushButton> #include <QtGui/QPushButton>
#include <QBrush> #include <QBrush>
#include <math.h>
#include <QMessageBox> #include <QMessageBox>
#include "mixersettings.h" #include <math.h>
#include "systemsettings.h"
#include "actuatorsettings.h"
#include "actuatorcommand.h"
QStringList ConfigGroundVehicleWidget::getChannelDescriptions()
/**
Constructor
*/
ConfigGroundVehicleWidget::ConfigGroundVehicleWidget(Ui_AircraftWidget *aircraft, QWidget *parent) : VehicleConfig(parent)
{ {
m_aircraft = aircraft; // init a channel_numelem list of channel desc defaults
QStringList channelDesc;
for (int i = 0; i < (int) ConfigGroundVehicleWidget::CHANNEL_NUMELEM; i++) {
channelDesc.append(QString("-"));
}
// get the gui config data
GUIConfigDataUnion configData = getConfigData();
if (configData.ground.GroundVehicleSteering1 > 0) {
channelDesc[configData.ground.GroundVehicleSteering1 - 1] = QString("GroundSteering1");
}
if (configData.ground.GroundVehicleSteering2 > 0) {
channelDesc[configData.ground.GroundVehicleSteering2 - 1] = QString("GroundSteering2");
}
if (configData.ground.GroundVehicleThrottle1 > 0) {
channelDesc[configData.ground.GroundVehicleThrottle1 - 1] = QString("GroundThrottle1");
}
if (configData.ground.GroundVehicleThrottle2 > 0) {
channelDesc[configData.ground.GroundVehicleThrottle2 - 1] = QString("GroundThrottle2");
}
return channelDesc;
}
ConfigGroundVehicleWidget::ConfigGroundVehicleWidget(QWidget *parent) :
VehicleConfig(parent), m_aircraft(new Ui_GroundConfigWidget())
{
m_aircraft->setupUi(this);
populateChannelComboBoxes();
QStringList groundVehicleTypes;
groundVehicleTypes << "Turnable (car)" << "Differential (tank)" << "Motorcycle";
m_aircraft->groundVehicleType->addItems(groundVehicleTypes);
// Set default model to "Turnable (car)"
m_aircraft->groundVehicleType->setCurrentIndex(m_aircraft->groundVehicleType->findText("Turnable (car)"));
//setupUI(m_aircraft->groundVehicleType->currentText());
connect(m_aircraft->groundVehicleType, SIGNAL(currentIndexChanged(QString)), this, SLOT(setupUI(QString)));
} }
/**
Destructor
*/
ConfigGroundVehicleWidget::~ConfigGroundVehicleWidget() ConfigGroundVehicleWidget::~ConfigGroundVehicleWidget()
{ {
// Do nothing delete m_aircraft;
} }
/** /**
@ -65,96 +96,103 @@ ConfigGroundVehicleWidget::~ConfigGroundVehicleWidget()
*/ */
void ConfigGroundVehicleWidget::setupUI(QString frameType) void ConfigGroundVehicleWidget::setupUI(QString frameType)
{ {
m_aircraft->differentialSteeringMixBox->setHidden(true); m_aircraft->differentialSteeringMixBox->setHidden(true);
//STILL NEEDS WORK //STILL NEEDS WORK
// Setup the UI
setComboCurrentIndex(m_aircraft->aircraftType, m_aircraft->aircraftType->findText("Ground"));
m_aircraft->gvEngineChannelBox->setEnabled(false); // Setup the UI
m_aircraft->gvEngineLabel->setEnabled(false);
m_aircraft->gvEngineChannelBox->setEnabled(false);
m_aircraft->gvEngineLabel->setEnabled(false);
m_aircraft->gvAileron1ChannelBox->setEnabled(false); m_aircraft->gvAileron1ChannelBox->setEnabled(false);
m_aircraft->gvAileron1Label->setEnabled(false); m_aircraft->gvAileron1Label->setEnabled(false);
m_aircraft->gvAileron2ChannelBox->setEnabled(false); m_aircraft->gvAileron2ChannelBox->setEnabled(false);
m_aircraft->gvAileron2Label->setEnabled(false); m_aircraft->gvAileron2Label->setEnabled(false);
if (frameType == "GroundVehicleDifferential" || frameType == "Differential (tank)"){ //Tank if (frameType == "GroundVehicleDifferential" || frameType == "Differential (tank)") {
setComboCurrentIndex(m_aircraft->groundVehicleType, m_aircraft->groundVehicleType->findText("Differential (tank)")); // Tank
m_aircraft->gvMotor1ChannelBox->setEnabled(true); setComboCurrentIndex(m_aircraft->groundVehicleType,
m_aircraft->gvMotor1Label->setEnabled(true); m_aircraft->groundVehicleType->findText("Differential (tank)"));
m_aircraft->gvMotor1ChannelBox->setEnabled(true);
m_aircraft->gvMotor1Label->setEnabled(true);
m_aircraft->gvMotor2ChannelBox->setEnabled(true); m_aircraft->gvMotor2ChannelBox->setEnabled(true);
m_aircraft->gvMotor2Label->setEnabled(true); m_aircraft->gvMotor2Label->setEnabled(true);
m_aircraft->gvMotor1Label->setText("Left motor"); m_aircraft->gvMotor1Label->setText("Left motor");
m_aircraft->gvMotor2Label->setText("Right motor"); m_aircraft->gvMotor2Label->setText("Right motor");
m_aircraft->gvSteering1ChannelBox->setEnabled(false); m_aircraft->gvSteering1ChannelBox->setEnabled(false);
m_aircraft->gvSteering1Label->setEnabled(false); m_aircraft->gvSteering1Label->setEnabled(false);
m_aircraft->gvSteering2ChannelBox->setEnabled(false); m_aircraft->gvSteering2ChannelBox->setEnabled(false);
m_aircraft->gvSteering2Label->setEnabled(false); m_aircraft->gvSteering2Label->setEnabled(false);
m_aircraft->gvSteering2Label->setText("Rear steering"); m_aircraft->gvSteering2Label->setText("Rear steering");
m_aircraft->differentialSteeringMixBox->setHidden(false); m_aircraft->differentialSteeringMixBox->setHidden(false);
m_aircraft->gvThrottleCurve1GroupBox->setTitle("Left throttle curve"); m_aircraft->gvThrottleCurve1GroupBox->setTitle("Left throttle curve");
m_aircraft->gvThrottleCurve2GroupBox->setTitle("Right throttle curve"); m_aircraft->gvThrottleCurve2GroupBox->setTitle("Right throttle curve");
} } else if (frameType == "GroundVehicleMotorcycle" || frameType == "Motorcycle") {
else if (frameType == "GroundVehicleMotorcycle" || frameType == "Motorcycle"){ //Motorcycle // Motorcycle
setComboCurrentIndex(m_aircraft->groundVehicleType, m_aircraft->groundVehicleType->findText("Motorcycle")); setComboCurrentIndex(m_aircraft->groundVehicleType, m_aircraft->groundVehicleType->findText("Motorcycle"));
m_aircraft->gvMotor1ChannelBox->setEnabled(false); m_aircraft->gvMotor1ChannelBox->setEnabled(false);
m_aircraft->gvMotor1Label->setEnabled(false); m_aircraft->gvMotor1Label->setEnabled(false);
m_aircraft->gvMotor2ChannelBox->setEnabled(true); m_aircraft->gvMotor2ChannelBox->setEnabled(true);
m_aircraft->gvMotor2Label->setEnabled(true); m_aircraft->gvMotor2Label->setEnabled(true);
m_aircraft->gvMotor1Label->setText("Front motor"); m_aircraft->gvMotor1Label->setText("Front motor");
m_aircraft->gvMotor2Label->setText("Rear motor"); m_aircraft->gvMotor2Label->setText("Rear motor");
m_aircraft->gvSteering1ChannelBox->setEnabled(true); m_aircraft->gvSteering1ChannelBox->setEnabled(true);
m_aircraft->gvSteering1Label->setEnabled(true); m_aircraft->gvSteering1Label->setEnabled(true);
m_aircraft->gvSteering2ChannelBox->setEnabled(true); m_aircraft->gvSteering2ChannelBox->setEnabled(true);
m_aircraft->gvSteering2Label->setEnabled(true); m_aircraft->gvSteering2Label->setEnabled(true);
m_aircraft->gvSteering2Label->setText("Balancing"); m_aircraft->gvSteering2Label->setText("Balancing");
m_aircraft->differentialSteeringMixBox->setHidden(true); m_aircraft->differentialSteeringMixBox->setHidden(true);
m_aircraft->gvThrottleCurve1GroupBox->setTitle("Front throttle curve"); m_aircraft->gvThrottleCurve1GroupBox->setTitle("Front throttle curve");
m_aircraft->gvThrottleCurve2GroupBox->setTitle("Rear throttle curve"); m_aircraft->gvThrottleCurve2GroupBox->setTitle("Rear throttle curve");
} } else {
else {//Car // Car
setComboCurrentIndex(m_aircraft->groundVehicleType, m_aircraft->groundVehicleType->findText("Turnable (car)")); setComboCurrentIndex(m_aircraft->groundVehicleType, m_aircraft->groundVehicleType->findText("Turnable (car)"));
m_aircraft->gvMotor1ChannelBox->setEnabled(true); m_aircraft->gvMotor1ChannelBox->setEnabled(true);
m_aircraft->gvMotor1Label->setEnabled(true); m_aircraft->gvMotor1Label->setEnabled(true);
m_aircraft->gvMotor2ChannelBox->setEnabled(true); m_aircraft->gvMotor2ChannelBox->setEnabled(true);
m_aircraft->gvMotor2Label->setEnabled(true); m_aircraft->gvMotor2Label->setEnabled(true);
m_aircraft->gvMotor1Label->setText("Front motor"); m_aircraft->gvMotor1Label->setText("Front motor");
m_aircraft->gvMotor2Label->setText("Rear motor"); m_aircraft->gvMotor2Label->setText("Rear motor");
m_aircraft->gvSteering1ChannelBox->setEnabled(true); m_aircraft->gvSteering1ChannelBox->setEnabled(true);
m_aircraft->gvSteering1Label->setEnabled(true); m_aircraft->gvSteering1Label->setEnabled(true);
m_aircraft->gvSteering2ChannelBox->setEnabled(true); m_aircraft->gvSteering2ChannelBox->setEnabled(true);
m_aircraft->gvSteering2Label->setEnabled(true); m_aircraft->gvSteering2Label->setEnabled(true);
m_aircraft->differentialSteeringMixBox->setHidden(true); m_aircraft->differentialSteeringMixBox->setHidden(true);
m_aircraft->gvThrottleCurve1GroupBox->setTitle("Front throttle curve"); m_aircraft->gvThrottleCurve1GroupBox->setTitle("Front throttle curve");
m_aircraft->gvThrottleCurve2GroupBox->setTitle("Rear throttle curve"); m_aircraft->gvThrottleCurve2GroupBox->setTitle("Rear throttle curve");
} }
} }
void ConfigGroundVehicleWidget::ResetActuators(GUIConfigDataUnion* configData) void ConfigGroundVehicleWidget::registerWidgets(ConfigTaskWidget &parent) {
parent.addWidget(m_aircraft->groundVehicleThrottle1->getCurveWidget());
parent.addWidget(m_aircraft->groundVehicleThrottle2->getCurveWidget());
parent.addWidget(m_aircraft->groundVehicleType);
}
void ConfigGroundVehicleWidget::resetActuators(GUIConfigDataUnion *configData)
{ {
configData->ground.GroundVehicleSteering1 = 0; configData->ground.GroundVehicleSteering1 = 0;
configData->ground.GroundVehicleSteering2 = 0; configData->ground.GroundVehicleSteering2 = 0;
@ -162,213 +200,202 @@ void ConfigGroundVehicleWidget::ResetActuators(GUIConfigDataUnion* configData)
configData->ground.GroundVehicleThrottle2 = 0; configData->ground.GroundVehicleThrottle2 = 0;
} }
QStringList ConfigGroundVehicleWidget::getChannelDescriptions() /**
Virtual function to refresh the UI widget values
*/
void ConfigGroundVehicleWidget::refreshWidgetsValues(QString frameType)
{ {
int i; setupUI(frameType);
QStringList channelDesc;
// init a channel_numelem list of channel desc defaults UAVDataObject *mixer = dynamic_cast<UAVDataObject *>(getObjectManager()->getObject(QString("MixerSettings")));
for (i=0; i < (int)(ConfigGroundVehicleWidget::CHANNEL_NUMELEM); i++) Q_ASSERT(mixer);
{
channelDesc.append(QString("-")); QList<double> curveValues;
getThrottleCurve(mixer, VehicleConfig::MIXER_THROTTLECURVE1, &curveValues);
// is at least one of the curve values != 0?
if (isValidThrottleCurve(&curveValues)) {
// yes, use the curve we just read from mixersettings
m_aircraft->groundVehicleThrottle1->initCurve(&curveValues);
} else {
// no, init a straight curve
m_aircraft->groundVehicleThrottle1->initLinearCurve(curveValues.count(), 1.0);
} }
// get the gui config data // Setup all Throttle2 curves for all types of airframes
GUIConfigDataUnion configData = GetConfigData(); getThrottleCurve(mixer, VehicleConfig::MIXER_THROTTLECURVE2, &curveValues);
if (configData.ground.GroundVehicleSteering1 > 0) if (isValidThrottleCurve(&curveValues)) {
channelDesc[configData.ground.GroundVehicleSteering1-1] = QString("GroundSteering1"); m_aircraft->groundVehicleThrottle2->initCurve(&curveValues);
if (configData.ground.GroundVehicleSteering2 > 0) } else {
channelDesc[configData.ground.GroundVehicleSteering2-1] = QString("GroundSteering2"); m_aircraft->groundVehicleThrottle2->initLinearCurve(curveValues.count(), 1.0);
if (configData.ground.GroundVehicleThrottle1 > 0) }
channelDesc[configData.ground.GroundVehicleThrottle1-1] = QString("GroundThrottle1"); GUIConfigDataUnion config = getConfigData();
if (configData.ground.GroundVehicleThrottle2 > 0)
channelDesc[configData.ground.GroundVehicleThrottle2-1] = QString("GroundThrottle2");
return channelDesc; // THIS SECTION STILL NEEDS WORK. FOR THE MOMENT, USE THE FIXED-WING ONBOARD SETTING IN ORDER TO MINIMIZE CHANCES OF BOLLOXING REAL CODE
// Retrieve channel setup values
setComboCurrentIndex(m_aircraft->gvMotor1ChannelBox, config.ground.GroundVehicleThrottle1);
setComboCurrentIndex(m_aircraft->gvMotor2ChannelBox, config.ground.GroundVehicleThrottle2);
setComboCurrentIndex(m_aircraft->gvSteering1ChannelBox, config.ground.GroundVehicleSteering1);
setComboCurrentIndex(m_aircraft->gvSteering2ChannelBox, config.ground.GroundVehicleSteering2);
if (frameType == "GroundVehicleDifferential") {
//CURRENTLY BROKEN UNTIL WE DECIDE HOW DIFFERENTIAL SHOULD BEHAVE
// If the vehicle type is "differential", restore the slider setting
// Find the channel number for Motor1
//obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
//Q_ASSERT(obj);
int channel = m_aircraft->gvMotor1ChannelBox->currentIndex() - 1;
if (channel > -1) {
// If for some reason the actuators were incoherent, we might fail here, hence the check.
m_aircraft->differentialSteeringSlider1->setValue(
getMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_ROLL) * 100);
m_aircraft->differentialSteeringSlider2->setValue(
getMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_PITCH) * 100);
}
} else if (frameType == "GroundVehicleMotorcycle") {
// CURRENTLY BROKEN UNTIL WE DECIDE HOW MOTORCYCLE SHOULD BEHAVE
// obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
// Q_ASSERT(obj);
// int chMixerNumber = m_aircraft->gvMotor1ChannelBox->currentIndex()-1;
// if (chMixerNumber >=0) {
// field = obj->getField(mixerVectors.at(chMixerNumber));
// int ti = field->getElementNames().indexOf("Yaw");
// m_aircraft->differentialSteeringSlider1->setValue(field->getDouble(ti)*100);
//
// ti = field->getElementNames().indexOf("Pitch");
// m_aircraft->differentialSteeringSlider2->setValue(field->getDouble(ti)*100);
// }
}
} }
/** /**
Virtual function to update the UI widget objects Virtual function to update the UI widget objects
*/ */
QString ConfigGroundVehicleWidget::updateConfigObjectsFromWidgets() QString ConfigGroundVehicleWidget::updateConfigObjectsFromWidgets()
{ {
QString airframeType = "GroundVehicleCar"; QString airframeType = "GroundVehicleCar";
// Save the curve (common to all ground vehicle frames) // Save the curve (common to all ground vehicle frames)
UAVDataObject *mixer = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings"))); UAVDataObject *mixer = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
// Remove Feed Forward, it is pointless on a ground vehicle: // Remove Feed Forward, it is pointless on a ground vehicle:
setMixerValue(mixer, "FeedForward", 0.0); setMixerValue(mixer, "FeedForward", 0.0);
// set the throttle curves // set the throttle curves
setThrottleCurve(mixer, VehicleConfig::MIXER_THROTTLECURVE1, m_aircraft->groundVehicleThrottle1->getCurve() ); setThrottleCurve(mixer, VehicleConfig::MIXER_THROTTLECURVE1, m_aircraft->groundVehicleThrottle1->getCurve());
setThrottleCurve(mixer, VehicleConfig::MIXER_THROTTLECURVE2, m_aircraft->groundVehicleThrottle2->getCurve() ); setThrottleCurve(mixer, VehicleConfig::MIXER_THROTTLECURVE2, m_aircraft->groundVehicleThrottle2->getCurve());
//All airframe types must start with "GroundVehicle" // All airframe types must start with "GroundVehicle"
if (m_aircraft->groundVehicleType->currentText() == "Turnable (car)" ) { if (m_aircraft->groundVehicleType->currentText() == "Turnable (car)") {
airframeType = "GroundVehicleCar"; airframeType = "GroundVehicleCar";
setupGroundVehicleCar(airframeType); setupGroundVehicleCar(airframeType);
} else if (m_aircraft->groundVehicleType->currentText() == "Differential (tank)") { } else if (m_aircraft->groundVehicleType->currentText() == "Differential (tank)") {
airframeType = "GroundVehicleDifferential"; airframeType = "GroundVehicleDifferential";
setupGroundVehicleDifferential(airframeType); setupGroundVehicleDifferential(airframeType);
} else { // "Motorcycle" } else { // "Motorcycle"
airframeType = "GroundVehicleMotorcycle"; airframeType = "GroundVehicleMotorcycle";
setupGroundVehicleMotorcycle(airframeType); setupGroundVehicleMotorcycle(airframeType);
} }
return airframeType; return airframeType;
} }
/**
Virtual function to refresh the UI widget values
*/
void ConfigGroundVehicleWidget::refreshWidgetsValues(QString frameType)
{
UAVDataObject* obj;
// UAVObjectField *field;
GUIConfigDataUnion config = GetConfigData();
//THIS SECTION STILL NEEDS WORK. FOR THE MOMENT, USE THE FIXED-WING ONBOARD SETTING IN ORDER TO MINIMIZE CHANCES OF BOLLOXING REAL CODE
// Retrieve channel setup values
setComboCurrentIndex(m_aircraft->gvMotor1ChannelBox, config.ground.GroundVehicleThrottle1);
setComboCurrentIndex(m_aircraft->gvMotor2ChannelBox, config.ground.GroundVehicleThrottle2);
setComboCurrentIndex(m_aircraft->gvSteering1ChannelBox, config.ground.GroundVehicleSteering1);
setComboCurrentIndex(m_aircraft->gvSteering2ChannelBox, config.ground.GroundVehicleSteering2);
if (frameType == "GroundVehicleDifferential") {
//CURRENTLY BROKEN UNTIL WE DECIDE HOW DIFFERENTIAL SHOULD BEHAVE
// If the vehicle type is "differential", restore the slider setting
// Find the channel number for Motor1
obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
Q_ASSERT(obj);
int channel = m_aircraft->gvMotor1ChannelBox->currentIndex()-1;
if (channel > -1) { // If for some reason the actuators were incoherent, we might fail here, hence the check.
m_aircraft->differentialSteeringSlider1->setValue(getMixerVectorValue(obj,channel,VehicleConfig::MIXERVECTOR_ROLL)*100);
m_aircraft->differentialSteeringSlider2->setValue(getMixerVectorValue(obj,channel,VehicleConfig::MIXERVECTOR_PITCH)*100);
}
}
if (frameType == "GroundVehicleMotorcycle") {
//CURRENTLY BROKEN UNTIL WE DECIDE HOW MOTORCYCLE SHOULD BEHAVE
// obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
// Q_ASSERT(obj);
// int chMixerNumber = m_aircraft->gvMotor1ChannelBox->currentIndex()-1;
// if (chMixerNumber >=0) {
// field = obj->getField(mixerVectors.at(chMixerNumber));
// int ti = field->getElementNames().indexOf("Yaw");
// m_aircraft->differentialSteeringSlider1->setValue(field->getDouble(ti)*100);
//
// ti = field->getElementNames().indexOf("Pitch");
// m_aircraft->differentialSteeringSlider2->setValue(field->getDouble(ti)*100);
// }
}
}
/** /**
Setup balancing ground vehicle. Setup balancing ground vehicle.
Returns False if impossible to create the mixer. Returns False if impossible to create the mixer.
*/ */
bool ConfigGroundVehicleWidget::setupGroundVehicleMotorcycle(QString airframeType){ bool ConfigGroundVehicleWidget::setupGroundVehicleMotorcycle(QString airframeType)
// Check coherence: {
//Show any config errors in GUI // Check coherence:
// Show any config errors in GUI
if (throwConfigError(airframeType)) { if (throwConfigError(airframeType)) {
return false; return false;
} }
// Now setup the channels: // Now setup the channels:
GUIConfigDataUnion config = GetConfigData(); GUIConfigDataUnion config = getConfigData();
ResetActuators(&config); resetActuators(&config);
config.ground.GroundVehicleThrottle1 = m_aircraft->gvMotor1ChannelBox->currentIndex(); config.ground.GroundVehicleThrottle1 = m_aircraft->gvMotor1ChannelBox->currentIndex();
config.ground.GroundVehicleThrottle2 = m_aircraft->gvMotor2ChannelBox->currentIndex(); config.ground.GroundVehicleThrottle2 = m_aircraft->gvMotor2ChannelBox->currentIndex();
SetConfigData(config); setConfigData(config);
UAVDataObject* mixer = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings"))); UAVDataObject* mixer = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
Q_ASSERT(mixer); Q_ASSERT(mixer);
resetMotorAndServoMixers(mixer); resetMotorAndServoMixers(mixer);
//motor // motor
int channel = m_aircraft->gvMotor2ChannelBox->currentIndex()-1; int channel = m_aircraft->gvMotor2ChannelBox->currentIndex() - 1;
setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_SERVO); setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_SERVO);
setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_THROTTLECURVE1, 127); setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_THROTTLECURVE1, 127);
setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_YAW, 127); setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_YAW, 127);
//steering // steering
channel = m_aircraft->gvSteering1ChannelBox->currentIndex()-1; channel = m_aircraft->gvSteering1ChannelBox->currentIndex() - 1;
setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_SERVO); setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_SERVO);
setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_YAW, -127); setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_YAW, -127);
setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_ROLL, -127); setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_ROLL, -127);
//balance // balance
channel = m_aircraft->gvSteering2ChannelBox->currentIndex()-1; channel = m_aircraft->gvSteering2ChannelBox->currentIndex() - 1;
setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_SERVO); setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_SERVO);
setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_YAW, 127); setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_YAW, 127);
setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_ROLL, 127); setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_ROLL, 127);
m_aircraft->gvStatusLabel->setText("Mixer generated"); m_aircraft->gvStatusLabel->setText("Mixer generated");
return true; return true;
} }
/** /**
Setup differentially steered ground vehicle. Setup differentially steered ground vehicle.
Returns False if impossible to create the mixer. Returns False if impossible to create the mixer.
*/ */
bool ConfigGroundVehicleWidget::setupGroundVehicleDifferential(QString airframeType){ bool ConfigGroundVehicleWidget::setupGroundVehicleDifferential(QString airframeType)
// Check coherence: {
//Show any config errors in GUI // Check coherence:
// Show any config errors in GUI
if (throwConfigError(airframeType)) { if (throwConfigError(airframeType)) {
return false; return false;
} }
// Now setup the channels: // Now setup the channels:
GUIConfigDataUnion config = GetConfigData(); GUIConfigDataUnion config = getConfigData();
ResetActuators(&config); resetActuators(&config);
config.ground.GroundVehicleThrottle1 = m_aircraft->gvMotor1ChannelBox->currentIndex(); config.ground.GroundVehicleThrottle1 = m_aircraft->gvMotor1ChannelBox->currentIndex();
config.ground.GroundVehicleThrottle2 = m_aircraft->gvMotor2ChannelBox->currentIndex(); config.ground.GroundVehicleThrottle2 = m_aircraft->gvMotor2ChannelBox->currentIndex();
SetConfigData((config)); setConfigData(config);
UAVDataObject* mixer = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings"))); UAVDataObject *mixer = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
Q_ASSERT(mixer); Q_ASSERT(mixer);
resetMotorAndServoMixers(mixer); resetMotorAndServoMixers(mixer);
//left motor // left motor
int channel = m_aircraft->gvMotor1ChannelBox->currentIndex()-1; int channel = m_aircraft->gvMotor1ChannelBox->currentIndex() - 1;
setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_SERVO); setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_SERVO);
setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_THROTTLECURVE1, 127); setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_THROTTLECURVE1, 127);
setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_YAW, 127); setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_YAW, 127);
//right motor // right motor
channel = m_aircraft->gvMotor2ChannelBox->currentIndex()-1; channel = m_aircraft->gvMotor2ChannelBox->currentIndex() - 1;
setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_SERVO); setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_SERVO);
setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_THROTTLECURVE2, 127); setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_THROTTLECURVE2, 127);
setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_YAW, -127); setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_YAW, -127);
//Output success message // Output success message
m_aircraft->gvStatusLabel->setText("Mixer generated"); m_aircraft->gvStatusLabel->setText("Mixer generated");
return true; return true;
} }
/** /**
Setup steerable ground vehicle. Setup steerable ground vehicle.
@ -377,43 +404,43 @@ bool ConfigGroundVehicleWidget::setupGroundVehicleDifferential(QString airframeT
bool ConfigGroundVehicleWidget::setupGroundVehicleCar(QString airframeType) bool ConfigGroundVehicleWidget::setupGroundVehicleCar(QString airframeType)
{ {
// Check coherence: // Check coherence:
//Show any config errors in GUI // Show any config errors in GUI
if (throwConfigError(airframeType)) { if (throwConfigError(airframeType)) {
return false; return false;
} }
// Now setup the channels: // Now setup the channels:
GUIConfigDataUnion config = GetConfigData(); GUIConfigDataUnion config = getConfigData();
ResetActuators(&config); resetActuators(&config);
config.ground.GroundVehicleThrottle1 = m_aircraft->gvMotor1ChannelBox->currentIndex(); config.ground.GroundVehicleThrottle1 = m_aircraft->gvMotor1ChannelBox->currentIndex();
config.ground.GroundVehicleThrottle2 = m_aircraft->gvMotor2ChannelBox->currentIndex(); config.ground.GroundVehicleThrottle2 = m_aircraft->gvMotor2ChannelBox->currentIndex();
config.ground.GroundVehicleSteering1 = m_aircraft->gvSteering1ChannelBox->currentIndex(); config.ground.GroundVehicleSteering1 = m_aircraft->gvSteering1ChannelBox->currentIndex();
config.ground.GroundVehicleSteering2 = m_aircraft->gvSteering2ChannelBox->currentIndex(); config.ground.GroundVehicleSteering2 = m_aircraft->gvSteering2ChannelBox->currentIndex();
SetConfigData(config); setConfigData(config);
UAVDataObject* mixer = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings"))); UAVDataObject* mixer = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
Q_ASSERT(mixer); Q_ASSERT(mixer);
resetMotorAndServoMixers(mixer); resetMotorAndServoMixers(mixer);
int channel = m_aircraft->gvSteering1ChannelBox->currentIndex()-1; int channel = m_aircraft->gvSteering1ChannelBox->currentIndex() - 1;
setMixerType(mixer,channel, VehicleConfig::MIXERTYPE_SERVO); setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_SERVO);
setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_YAW, 127); setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_YAW, 127);
channel = m_aircraft->gvSteering2ChannelBox->currentIndex()-1; channel = m_aircraft->gvSteering2ChannelBox->currentIndex() - 1;
setMixerType(mixer,channel, VehicleConfig::MIXERTYPE_SERVO); setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_SERVO);
setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_YAW, -127); setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_YAW, -127);
channel = m_aircraft->gvMotor1ChannelBox->currentIndex()-1; channel = m_aircraft->gvMotor1ChannelBox->currentIndex() - 1;
setMixerType(mixer,channel, VehicleConfig::MIXERTYPE_SERVO); setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_SERVO);
setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_THROTTLECURVE1, 127); setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_THROTTLECURVE1, 127);
channel = m_aircraft->gvMotor2ChannelBox->currentIndex()-1; channel = m_aircraft->gvMotor2ChannelBox->currentIndex() - 1;
setMixerType(mixer,channel, VehicleConfig::MIXERTYPE_SERVO); setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_SERVO);
setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_THROTTLECURVE2, 127); setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_THROTTLECURVE2, 127);
//Output success message // Output success message
m_aircraft->gvStatusLabel->setText("Mixer generated"); m_aircraft->gvStatusLabel->setText("Mixer generated");
return true; return true;
@ -424,94 +451,91 @@ bool ConfigGroundVehicleWidget::setupGroundVehicleCar(QString airframeType)
*/ */
bool ConfigGroundVehicleWidget::throwConfigError(QString airframeType) bool ConfigGroundVehicleWidget::throwConfigError(QString airframeType)
{ {
//Initialize configuration error flag // Initialize configuration error flag
bool error=false; bool error = false;
// Create a red block. All combo boxes are the same size, so any one should do as a model
int size = m_aircraft->gvEngineChannelBox->style()->pixelMetric(QStyle::PM_SmallIconSize);
QPixmap pixmap(size, size);
pixmap.fill(QColor("red"));
//Create a red block. All combo boxes are the same size, so any one should do as a model if (airframeType == "GroundVehicleCar") { //Car
int size = m_aircraft->gvEngineChannelBox->style()->pixelMetric(QStyle::PM_SmallIconSize); if (m_aircraft->gvMotor1ChannelBox->currentText() == "None"
QPixmap pixmap(size,size); && m_aircraft->gvMotor2ChannelBox->currentText() == "None") {
pixmap.fill(QColor("red")); pixmap.fill(QColor("green"));
m_aircraft->gvMotor1ChannelBox->setItemData(0, pixmap, Qt::DecorationRole); //Set color palettes
m_aircraft->gvMotor2ChannelBox->setItemData(0, pixmap, Qt::DecorationRole); //Set color palettes
//m_aircraft->gvMotor1Label->setText("<font color='red'>" + m_aircraft->gvMotor1Label->text() + "</font>");
//m_aircraft->gvMotor2Label->setText("<font color='red'>" + m_aircraft->gvMotor2Label->text() + "</font>");
error = true;
if (airframeType == "GroundVehicleCar" ) { //Car } else {
if(m_aircraft->gvMotor1ChannelBox->currentText() == "None" && m_aircraft->gvMotor2ChannelBox->currentText() == "None"){ m_aircraft->gvMotor1ChannelBox->setItemData(0, 0, Qt::DecorationRole); //Reset color palettes
pixmap.fill(QColor("green")); m_aircraft->gvMotor2ChannelBox->setItemData(0, 0, Qt::DecorationRole); //Reset color palettes
m_aircraft->gvMotor1ChannelBox->setItemData(0, pixmap, Qt::DecorationRole);//Set color palettes //QTextEdit* htmlText=new QTextEdit(m_aircraft->gvMotor1Label->text()); // HtmlText is any QString with html tags.
m_aircraft->gvMotor2ChannelBox->setItemData(0, pixmap, Qt::DecorationRole);//Set color palettes //m_aircraft->gvMotor1Label->setText(htmlText->toPlainText());
// m_aircraft->gvMotor1Label->setText("<font color='red'>" + m_aircraft->gvMotor1Label->text() + "</font>"); //delete htmlText;
// m_aircraft->gvMotor2Label->setText("<font color='red'>" + m_aircraft->gvMotor2Label->text() + "</font>");
error=true;
} //htmlText=new QTextEdit(m_aircraft->gvMotor2Label->text()); // HtmlText is any QString with html tags.
else{ //m_aircraft->gvMotor2Label->setText(htmlText->toPlainText());
m_aircraft->gvMotor1ChannelBox->setItemData(0, 0, Qt::DecorationRole);//Reset color palettes }
m_aircraft->gvMotor2ChannelBox->setItemData(0, 0, Qt::DecorationRole);//Reset color palettes
// QTextEdit* htmlText=new QTextEdit(m_aircraft->gvMotor1Label->text()); // HtmlText is any QString with html tags.
// m_aircraft->gvMotor1Label->setText(htmlText->toPlainText());
// delete htmlText;
//
// htmlText=new QTextEdit(m_aircraft->gvMotor2Label->text()); // HtmlText is any QString with html tags.
// m_aircraft->gvMotor2Label->setText(htmlText->toPlainText());
}
if (m_aircraft->gvSteering1ChannelBox->currentText() == "None" && m_aircraft->gvSteering2ChannelBox->currentText() == "None") { if (m_aircraft->gvSteering1ChannelBox->currentText() == "None"
m_aircraft->gvSteering1ChannelBox->setItemData(0, pixmap, Qt::DecorationRole);//Set color palettes && m_aircraft->gvSteering2ChannelBox->currentText() == "None") {
m_aircraft->gvSteering2ChannelBox->setItemData(0, pixmap, Qt::DecorationRole);//Set color palettes m_aircraft->gvSteering1ChannelBox->setItemData(0, pixmap, Qt::DecorationRole); //Set color palettes
// m_aircraft->gvStatusLabel->setText("<font color='red'>ERROR: check steering channel assignment</font>"); m_aircraft->gvSteering2ChannelBox->setItemData(0, pixmap, Qt::DecorationRole); //Set color palettes
// m_aircraft->gvSteering1Label->setText("<font color='red'>" + m_aircraft->gvSteering1Label->text() + "</font>"); //m_aircraft->gvStatusLabel->setText("<font color='red'>ERROR: check steering channel assignment</font>");
// m_aircraft->gvSteering2Label->setText("<font color='red'>" + m_aircraft->gvSteering2Label->text() + "</font>"); //m_aircraft->gvSteering1Label->setText("<font color='red'>" + m_aircraft->gvSteering1Label->text() + "</font>");
error=true; //m_aircraft->gvSteering2Label->setText("<font color='red'>" + m_aircraft->gvSteering2Label->text() + "</font>");
} error = true;
else{ } else {
m_aircraft->gvSteering1ChannelBox->setItemData(0, 0, Qt::DecorationRole);//Reset color palettes m_aircraft->gvSteering1ChannelBox->setItemData(0, 0, Qt::DecorationRole); //Reset color palettes
m_aircraft->gvSteering2ChannelBox->setItemData(0, 0, Qt::DecorationRole);//Reset color palettes m_aircraft->gvSteering2ChannelBox->setItemData(0, 0, Qt::DecorationRole); //Reset color palettes
// QTextEdit* htmlText=new QTextEdit(m_aircraft->gvSteering1Label->text()); // HtmlText is any QString with html tags. //QTextEdit* htmlText=new QTextEdit(m_aircraft->gvSteering1Label->text()); // HtmlText is any QString with html tags.
// m_aircraft->gvSteering1Label->setText(htmlText->toPlainText()); //m_aircraft->gvSteering1Label->setText(htmlText->toPlainText());
// delete htmlText; //delete htmlText;
//
// htmlText=new QTextEdit(m_aircraft->gvSteering2Label->text()); // HtmlText is any QString with html tags.
// m_aircraft->gvSteering2Label->setText(htmlText->toPlainText());
}
} else if (airframeType == "GroundVehicleDifferential"){ //Tank //htmlText=new QTextEdit(m_aircraft->gvSteering2Label->text()); // HtmlText is any QString with html tags.
if(m_aircraft->gvMotor1ChannelBox->currentText() == "None" || m_aircraft->gvMotor2ChannelBox->currentText() == "None"){ //m_aircraft->gvSteering2Label->setText(htmlText->toPlainText());
m_aircraft->gvMotor1ChannelBox->setItemData(0, pixmap, Qt::DecorationRole);//Set color palettes }
m_aircraft->gvMotor2ChannelBox->setItemData(0, pixmap, Qt::DecorationRole);//Set color palettes } else if (airframeType == "GroundVehicleDifferential") { //Tank
error=true; if (m_aircraft->gvMotor1ChannelBox->currentText() == "None"
} || m_aircraft->gvMotor2ChannelBox->currentText() == "None") {
else{ m_aircraft->gvMotor1ChannelBox->setItemData(0, pixmap, Qt::DecorationRole); //Set color palettes
m_aircraft->gvMotor1ChannelBox->setItemData(0, 0, Qt::DecorationRole);//Reset color palettes m_aircraft->gvMotor2ChannelBox->setItemData(0, pixmap, Qt::DecorationRole); //Set color palettes
m_aircraft->gvMotor2ChannelBox->setItemData(0, 0, Qt::DecorationRole);//Reset color palettes error = true;
} } else {
m_aircraft->gvMotor1ChannelBox->setItemData(0, 0, Qt::DecorationRole); //Reset color palettes
m_aircraft->gvMotor2ChannelBox->setItemData(0, 0, Qt::DecorationRole); //Reset color palettes
}
//Always reset // Always reset
m_aircraft->gvSteering1ChannelBox->setItemData(0, 0, Qt::DecorationRole);//Reset color palettes m_aircraft->gvSteering1ChannelBox->setItemData(0, 0, Qt::DecorationRole); //Reset color palettes
m_aircraft->gvSteering2ChannelBox->setItemData(0, 0, Qt::DecorationRole);//Reset color palettes m_aircraft->gvSteering2ChannelBox->setItemData(0, 0, Qt::DecorationRole); //Reset color palettes
} else if ( airframeType == "GroundVehicleMotorcycle"){ //Motorcycle } else if (airframeType == "GroundVehicleMotorcycle") { //Motorcycle
if(m_aircraft->gvMotor1ChannelBox->currentText() == "None" && m_aircraft->gvMotor2ChannelBox->currentText() == "None"){ if (m_aircraft->gvMotor1ChannelBox->currentText() == "None"
m_aircraft->gvMotor2ChannelBox->setItemData(0, pixmap, Qt::DecorationRole);//Set color palettes && m_aircraft->gvMotor2ChannelBox->currentText() == "None") {
error=true; m_aircraft->gvMotor2ChannelBox->setItemData(0, pixmap, Qt::DecorationRole); //Set color palettes
} error = true;
else{ } else {
m_aircraft->gvMotor2ChannelBox->setItemData(0, 0, Qt::DecorationRole);//Reset color palettes m_aircraft->gvMotor2ChannelBox->setItemData(0, 0, Qt::DecorationRole); //Reset color palettes
} }
if (m_aircraft->gvSteering1ChannelBox->currentText() == "None" && m_aircraft->gvSteering2ChannelBox->currentText() == "None") { if (m_aircraft->gvSteering1ChannelBox->currentText() == "None"
m_aircraft->gvSteering1ChannelBox->setItemData(0, pixmap, Qt::DecorationRole);//Set color palettes && m_aircraft->gvSteering2ChannelBox->currentText() == "None") {
error=true; m_aircraft->gvSteering1ChannelBox->setItemData(0, pixmap, Qt::DecorationRole); //Set color palettes
} error = true;
else{ } else {
m_aircraft->gvSteering1ChannelBox->setItemData(0, 0, Qt::DecorationRole);//Reset color palettes m_aircraft->gvSteering1ChannelBox->setItemData(0, 0, Qt::DecorationRole); //Reset color palettes
} }
//Always reset // Always reset
m_aircraft->gvMotor1ChannelBox->setItemData(0, 0, Qt::DecorationRole);//Reset color palettes m_aircraft->gvMotor1ChannelBox->setItemData(0, 0, Qt::DecorationRole); //Reset color palettes
m_aircraft->gvSteering2ChannelBox->setItemData(0, 0, Qt::DecorationRole);//Reset color palettes m_aircraft->gvSteering2ChannelBox->setItemData(0, 0, Qt::DecorationRole); //Reset color palettes
} }
if (error){ if (error) {
m_aircraft->gvStatusLabel->setText(QString("<font color='red'>ERROR: Assign all necessary channels</font>")); m_aircraft->gvStatusLabel->setText(QString("<font color='red'>ERROR: Assign all necessary channels</font>"));
} }
return error; return error;
} }

View File

@ -27,12 +27,14 @@
#ifndef CONFIGGROUNDVEHICLEWIDGET_H #ifndef CONFIGGROUNDVEHICLEWIDGET_H
#define CONFIGGROUNDVEHICLEWIDGET_H #define CONFIGGROUNDVEHICLEWIDGET_H
#include "ui_airframe.h" #include "cfg_vehicletypes/vehicleconfig.h"
#include "ui_airframe_ground.h"
#include "../uavobjectwidgetutils/configtaskwidget.h" #include "../uavobjectwidgetutils/configtaskwidget.h"
#include "extensionsystem/pluginmanager.h" #include "extensionsystem/pluginmanager.h"
#include "uavobjectmanager.h" #include "uavobjectmanager.h"
#include "uavobject.h" #include "uavobject.h"
#include "uavtalk/telemetrymanager.h" #include "uavtalk/telemetrymanager.h"
#include <QtGui/QWidget> #include <QtGui/QWidget>
#include <QList> #include <QList>
#include <QItemDelegate> #include <QItemDelegate>
@ -44,31 +46,28 @@ class ConfigGroundVehicleWidget: public VehicleConfig
Q_OBJECT Q_OBJECT
public: public:
ConfigGroundVehicleWidget(Ui_AircraftWidget *aircraft = 0, QWidget *parent = 0); static QStringList getChannelDescriptions();
ConfigGroundVehicleWidget(QWidget *parent = 0);
~ConfigGroundVehicleWidget(); ~ConfigGroundVehicleWidget();
friend class ConfigVehicleTypeWidget; virtual void refreshWidgetsValues(QString frameType);
virtual QString updateConfigObjectsFromWidgets();
private: private:
Ui_AircraftWidget *m_aircraft; Ui_GroundConfigWidget *m_aircraft;
virtual void registerWidgets(ConfigTaskWidget &parent);
virtual void resetActuators(GUIConfigDataUnion *configData);
bool setupGroundVehicleCar(QString airframeType); bool setupGroundVehicleCar(QString airframeType);
bool setupGroundVehicleDifferential(QString airframeType); bool setupGroundVehicleDifferential(QString airframeType);
bool setupGroundVehicleMotorcycle(QString airframeType); bool setupGroundVehicleMotorcycle(QString airframeType);
virtual void ResetActuators(GUIConfigDataUnion* configData);
static QStringList getChannelDescriptions();
private slots: private slots:
virtual void setupUI(QString airframeType); virtual void setupUI(QString airframeType);
virtual void refreshWidgetsValues(QString frameType);
virtual QString updateConfigObjectsFromWidgets();
virtual bool throwConfigError(QString airframeType); virtual bool throwConfigError(QString airframeType);
protected:
}; };
#endif // CONFIGGROUNDVEHICLEWIDGET_H #endif // CONFIGGROUNDVEHICLEWIDGET_H

View File

@ -25,6 +25,10 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/ */
#include "configmultirotorwidget.h" #include "configmultirotorwidget.h"
#include "mixersettings.h"
#include "systemsettings.h"
#include "actuatorsettings.h"
#include "actuatorcommand.h"
#include <QDebug> #include <QDebug>
#include <QStringList> #include <QStringList>
@ -37,48 +41,106 @@
#include <math.h> #include <math.h>
#include <QMessageBox> #include <QMessageBox>
#include "mixersettings.h"
#include "systemsettings.h"
#include "actuatorsettings.h"
#include "actuatorcommand.h"
const QString ConfigMultiRotorWidget::CHANNELBOXNAME = QString("multiMotorChannelBox"); const QString ConfigMultiRotorWidget::CHANNELBOXNAME = QString("multiMotorChannelBox");
QStringList ConfigMultiRotorWidget::getChannelDescriptions()
/**
Constructor
*/
ConfigMultiRotorWidget::ConfigMultiRotorWidget(Ui_AircraftWidget *aircraft, QWidget *parent) : VehicleConfig(parent), invertMotors(1)
{ {
m_aircraft = aircraft; // init a channel_numelem list of channel desc defaults
QStringList channelDesc;
for (int i = 0; i < (int) ConfigMultiRotorWidget::CHANNEL_NUMELEM; i++) {
channelDesc.append(QString("-"));
}
// get the gui config data
GUIConfigDataUnion configData = getConfigData();
multiGUISettingsStruct multi = configData.multi;
if (multi.VTOLMotorN > 0 && multi.VTOLMotorN <= ConfigMultiRotorWidget::CHANNEL_NUMELEM) {
channelDesc[multi.VTOLMotorN - 1] = QString("VTOLMotorN");
}
if (multi.VTOLMotorNE > 0 && multi.VTOLMotorNE <= ConfigMultiRotorWidget::CHANNEL_NUMELEM) {
channelDesc[multi.VTOLMotorNE - 1] = QString("VTOLMotorNE");
}
if (multi.VTOLMotorNW > 0 && multi.VTOLMotorNW <= ConfigMultiRotorWidget::CHANNEL_NUMELEM) {
channelDesc[multi.VTOLMotorNW - 1] = QString("VTOLMotorNW");
}
if (multi.VTOLMotorS > 0 && multi.VTOLMotorS <= ConfigMultiRotorWidget::CHANNEL_NUMELEM) {
channelDesc[multi.VTOLMotorS - 1] = QString("VTOLMotorS");
}
if (multi.VTOLMotorSE > 0 && multi.VTOLMotorSE <= ConfigMultiRotorWidget::CHANNEL_NUMELEM) {
channelDesc[multi.VTOLMotorSE - 1] = QString("VTOLMotorSE");
}
if (multi.VTOLMotorSW > 0 && multi.VTOLMotorSW <= ConfigMultiRotorWidget::CHANNEL_NUMELEM) {
channelDesc[multi.VTOLMotorSW - 1] = QString("VTOLMotorSW");
}
if (multi.VTOLMotorW > 0 && multi.VTOLMotorW <= ConfigMultiRotorWidget::CHANNEL_NUMELEM) {
channelDesc[multi.VTOLMotorW - 1] = QString("VTOLMotorW");
}
if (multi.VTOLMotorE > 0 && multi.VTOLMotorE <= ConfigMultiRotorWidget::CHANNEL_NUMELEM) {
channelDesc[multi.VTOLMotorE - 1] = QString("VTOLMotorE");
}
if (multi.TRIYaw > 0 && multi.TRIYaw <= ConfigMultiRotorWidget::CHANNEL_NUMELEM) {
channelDesc[multi.TRIYaw - 1] = QString("Tri-Yaw");
}
return channelDesc;
}
ConfigMultiRotorWidget::ConfigMultiRotorWidget(QWidget *parent) :
VehicleConfig(parent), m_aircraft(new Ui_MultiRotorConfigWidget()), invertMotors(false)
{
m_aircraft->setupUi(this);
populateChannelComboBoxes();
// 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/multirotor-shapes.svg"));
quad = new QGraphicsSvgItem();
quad->setSharedRenderer(renderer);
quad->setElementId("quad-x");
QGraphicsScene *scene = new QGraphicsScene();
scene->addItem(quad);
scene->setSceneRect(quad->boundingRect());
m_aircraft->quadShape->setScene(scene);
QStringList multiRotorTypes;
multiRotorTypes << "Tricopter Y" << "Quad +" << "Quad X" << "Hexacopter" << "Hexacopter X" << "Hexacopter Y6"
<< "Octocopter" << "Octocopter V" << "Octo Coax +" << "Octo Coax X";
m_aircraft->multirotorFrameType->addItems(multiRotorTypes);
// Set default model to "Quad X"
m_aircraft->multirotorFrameType->setCurrentIndex(m_aircraft->multirotorFrameType->findText("Quad X"));
//setupUI(m_aircraft->multirotorFrameType->currentText());
connect(m_aircraft->multirotorFrameType, SIGNAL(currentIndexChanged(QString)), this, SLOT(setupUI(QString)));
// Connect the multirotor motor reverse checkbox
connect(m_aircraft->MultirotorRevMixerCheckBox, SIGNAL(clicked(bool)), this, SLOT(reverseMultirotorMotor()));
} }
/**
Destructor
*/
ConfigMultiRotorWidget::~ConfigMultiRotorWidget() ConfigMultiRotorWidget::~ConfigMultiRotorWidget()
{ {
// Do nothing delete m_aircraft;
} }
void ConfigMultiRotorWidget::setupUI(QString frameType) void ConfigMultiRotorWidget::setupUI(QString frameType)
{ {
Q_ASSERT(m_aircraft); Q_ASSERT(m_aircraft);
Q_ASSERT(uiowner);
Q_ASSERT(quad); Q_ASSERT(quad);
int i; // disable triyaw channel
// set aircraftType to Multirotor, disable triyaw channel
setComboCurrentIndex(m_aircraft->aircraftType, m_aircraft->aircraftType->findText("Multirotor"));
m_aircraft->triYawChannelBox->setEnabled(false); m_aircraft->triYawChannelBox->setEnabled(false);
// disable all motor channel boxes // disable all motor channel boxes
for (i=1; i <=8; i++) { for (int i = 1; i <= 8; i++) {
// do it manually so we can turn off any error decorations // do it manually so we can turn off any error decorations
QComboBox *combobox = qFindChild<QComboBox*>(uiowner, "multiMotorChannelBox" + QString::number(i)); QComboBox *combobox = qFindChild<QComboBox*>(this, "multiMotorChannelBox" + QString::number(i));
if (combobox) { if (combobox) {
combobox->setEnabled(false); combobox->setEnabled(false);
combobox->setItemData(0, 0, Qt::DecorationRole); combobox->setItemData(0, 0, Qt::DecorationRole);
@ -86,198 +148,125 @@ void ConfigMultiRotorWidget::setupUI(QString frameType)
} }
if (frameType == "Tri" || frameType == "Tricopter Y") { if (frameType == "Tri" || frameType == "Tricopter Y") {
setComboCurrentIndex( m_aircraft->multirotorFrameType, m_aircraft->multirotorFrameType->findText("Tricopter Y")); setComboCurrentIndex(m_aircraft->multirotorFrameType, m_aircraft->multirotorFrameType->findText("Tricopter Y"));
//Enable all necessary motor channel boxes... // Enable all necessary motor channel boxes...
enableComboBoxes(uiowner, CHANNELBOXNAME, 3, true); enableComboBoxes(this, CHANNELBOXNAME, 3, true);
m_aircraft->mrRollMixLevel->setValue(100); m_aircraft->mrRollMixLevel->setValue(100);
m_aircraft->mrPitchMixLevel->setValue(100); m_aircraft->mrPitchMixLevel->setValue(100);
setYawMixLevel(50); setYawMixLevel(50);
m_aircraft->triYawChannelBox->setEnabled(true); m_aircraft->triYawChannelBox->setEnabled(true);
} } else if (frameType == "QuadX" || frameType == "Quad X") {
else if (frameType == "QuadX" || frameType == "Quad X") { setComboCurrentIndex(m_aircraft->multirotorFrameType, m_aircraft->multirotorFrameType->findText("Quad X"));
setComboCurrentIndex( m_aircraft->multirotorFrameType, m_aircraft->multirotorFrameType->findText("Quad X"));
//Enable all necessary motor channel boxes... // Enable all necessary motor channel boxes...
enableComboBoxes(uiowner, CHANNELBOXNAME, 4, true); enableComboBoxes(this, CHANNELBOXNAME, 4, true);
// init mixer levels // init mixer levels
m_aircraft->mrRollMixLevel->setValue(50); m_aircraft->mrRollMixLevel->setValue(50);
m_aircraft->mrPitchMixLevel->setValue(50); m_aircraft->mrPitchMixLevel->setValue(50);
setYawMixLevel(50); setYawMixLevel(50);
} } else if (frameType == "QuadP" || frameType == "Quad +") {
else if (frameType == "QuadP" || frameType == "Quad +") { setComboCurrentIndex(m_aircraft->multirotorFrameType, m_aircraft->multirotorFrameType->findText("Quad +"));
setComboCurrentIndex( m_aircraft->multirotorFrameType, m_aircraft->multirotorFrameType->findText("Quad +"));
//Enable all necessary motor channel boxes... // Enable all necessary motor channel boxes...
enableComboBoxes(uiowner, CHANNELBOXNAME, 4, true); enableComboBoxes(this, CHANNELBOXNAME, 4, true);
m_aircraft->mrRollMixLevel->setValue(100); m_aircraft->mrRollMixLevel->setValue(100);
m_aircraft->mrPitchMixLevel->setValue(100); m_aircraft->mrPitchMixLevel->setValue(100);
setYawMixLevel(50); setYawMixLevel(50);
} } else if (frameType == "Hexa" || frameType == "Hexacopter") {
else if (frameType == "Hexa" || frameType == "Hexacopter") setComboCurrentIndex(m_aircraft->multirotorFrameType, m_aircraft->multirotorFrameType->findText("Hexacopter"));
{
setComboCurrentIndex( m_aircraft->multirotorFrameType, m_aircraft->multirotorFrameType->findText("Hexacopter"));
//Enable all necessary motor channel boxes... // Enable all necessary motor channel boxes...
enableComboBoxes(uiowner, CHANNELBOXNAME, 6, true); enableComboBoxes(this, CHANNELBOXNAME, 6, true);
m_aircraft->mrRollMixLevel->setValue(50); m_aircraft->mrRollMixLevel->setValue(50);
m_aircraft->mrPitchMixLevel->setValue(33); m_aircraft->mrPitchMixLevel->setValue(33);
setYawMixLevel(33); setYawMixLevel(33);
} } else if (frameType == "HexaX" || frameType == "Hexacopter X") {
else if (frameType == "HexaX" || frameType == "Hexacopter X" ) { setComboCurrentIndex(m_aircraft->multirotorFrameType,
setComboCurrentIndex( m_aircraft->multirotorFrameType, m_aircraft->multirotorFrameType->findText("Hexacopter X")); m_aircraft->multirotorFrameType->findText("Hexacopter X"));
//Enable all necessary motor channel boxes... // Enable all necessary motor channel boxes...
enableComboBoxes(uiowner, CHANNELBOXNAME, 6, true); enableComboBoxes(this, CHANNELBOXNAME, 6, true);
m_aircraft->mrRollMixLevel->setValue(33); m_aircraft->mrRollMixLevel->setValue(33);
m_aircraft->mrPitchMixLevel->setValue(50); m_aircraft->mrPitchMixLevel->setValue(50);
setYawMixLevel(33); setYawMixLevel(33);
} else if (frameType == "HexaCoax" || frameType == "Hexacopter Y6") {
setComboCurrentIndex(m_aircraft->multirotorFrameType,
m_aircraft->multirotorFrameType->findText("Hexacopter Y6"));
} // Enable all necessary motor channel boxes...
else if (frameType == "HexaCoax" || frameType == "Hexacopter Y6") enableComboBoxes(this, CHANNELBOXNAME, 6, true);
{
setComboCurrentIndex( m_aircraft->multirotorFrameType, m_aircraft->multirotorFrameType->findText("Hexacopter Y6"));
//Enable all necessary motor channel boxes...
enableComboBoxes(uiowner, CHANNELBOXNAME, 6, true);
m_aircraft->mrRollMixLevel->setValue(100); m_aircraft->mrRollMixLevel->setValue(100);
m_aircraft->mrPitchMixLevel->setValue(50); m_aircraft->mrPitchMixLevel->setValue(50);
setYawMixLevel(66); setYawMixLevel(66);
} else if (frameType == "Octo" || frameType == "Octocopter") {
setComboCurrentIndex(m_aircraft->multirotorFrameType, m_aircraft->multirotorFrameType->findText("Octocopter"));
} // Enable all necessary motor channel boxes
else if (frameType == "Octo" || frameType == "Octocopter") enableComboBoxes(this, CHANNELBOXNAME, 8, true);
{
setComboCurrentIndex( m_aircraft->multirotorFrameType, m_aircraft->multirotorFrameType->findText("Octocopter"));
//Enable all necessary motor channel boxes
enableComboBoxes(uiowner, CHANNELBOXNAME, 8, true);
m_aircraft->mrRollMixLevel->setValue(33); m_aircraft->mrRollMixLevel->setValue(33);
m_aircraft->mrPitchMixLevel->setValue(33); m_aircraft->mrPitchMixLevel->setValue(33);
setYawMixLevel(25); setYawMixLevel(25);
} } else if (frameType == "OctoV" || frameType == "Octocopter V") {
else if (frameType == "OctoV" || frameType == "Octocopter V") setComboCurrentIndex(m_aircraft->multirotorFrameType,
{ m_aircraft->multirotorFrameType->findText("Octocopter V"));
setComboCurrentIndex( m_aircraft->multirotorFrameType, m_aircraft->multirotorFrameType->findText("Octocopter V"));
//Enable all necessary motor channel boxes // Enable all necessary motor channel boxes
enableComboBoxes(uiowner, CHANNELBOXNAME, 8, true); enableComboBoxes(this, CHANNELBOXNAME, 8, true);
m_aircraft->mrRollMixLevel->setValue(25); m_aircraft->mrRollMixLevel->setValue(25);
m_aircraft->mrPitchMixLevel->setValue(25); m_aircraft->mrPitchMixLevel->setValue(25);
setYawMixLevel(25); setYawMixLevel(25);
} else if (frameType == "OctoCoaxP" || frameType == "Octo Coax +") {
setComboCurrentIndex(m_aircraft->multirotorFrameType, m_aircraft->multirotorFrameType->findText("Octo Coax +"));
} // Enable all necessary motor channel boxes
else if (frameType == "OctoCoaxP" || frameType == "Octo Coax +") enableComboBoxes(this, CHANNELBOXNAME, 8, true);
{
setComboCurrentIndex( m_aircraft->multirotorFrameType, m_aircraft->multirotorFrameType->findText("Octo Coax +"));
//Enable all necessary motor channel boxes
enableComboBoxes(uiowner, CHANNELBOXNAME, 8, true);
m_aircraft->mrRollMixLevel->setValue(100); m_aircraft->mrRollMixLevel->setValue(100);
m_aircraft->mrPitchMixLevel->setValue(100); m_aircraft->mrPitchMixLevel->setValue(100);
setYawMixLevel(50); setYawMixLevel(50);
} else if (frameType == "OctoCoaxX" || frameType == "Octo Coax X") {
setComboCurrentIndex(m_aircraft->multirotorFrameType, m_aircraft->multirotorFrameType->findText("Octo Coax X"));
} // Enable all necessary motor channel boxes
else if (frameType == "OctoCoaxX" || frameType == "Octo Coax X") enableComboBoxes(this, CHANNELBOXNAME, 8, true);
{
setComboCurrentIndex( m_aircraft->multirotorFrameType, m_aircraft->multirotorFrameType->findText("Octo Coax X"));
//Enable all necessary motor channel boxes
enableComboBoxes(uiowner, CHANNELBOXNAME, 8, true);
m_aircraft->mrRollMixLevel->setValue(50); m_aircraft->mrRollMixLevel->setValue(50);
m_aircraft->mrPitchMixLevel->setValue(50); m_aircraft->mrPitchMixLevel->setValue(50);
setYawMixLevel(50); setYawMixLevel(50);
} }
//Draw the appropriate airframe // Draw the appropriate airframe
drawAirframe(frameType); updateAirframe(frameType);
} }
void ConfigMultiRotorWidget::drawAirframe(QString frameType){ void ConfigMultiRotorWidget::registerWidgets(ConfigTaskWidget &parent) {
parent.addWidget(m_aircraft->multiThrottleCurve->getCurveWidget());
invertMotors = m_aircraft->MultirotorRevMixercheckBox->isChecked() ? -1:1; parent.addWidget(m_aircraft->multirotorFrameType);
parent.addWidget(m_aircraft->multiMotorChannelBox1);
if (frameType == "Tri" || frameType == "Tricopter Y") { parent.addWidget(m_aircraft->multiMotorChannelBox2);
if(invertMotors > 0) parent.addWidget(m_aircraft->multiMotorChannelBox3);
quad->setElementId("tri"); parent.addWidget(m_aircraft->multiMotorChannelBox4);
else parent.addWidget(m_aircraft->multiMotorChannelBox5);
quad->setElementId("tri_reverse"); parent.addWidget(m_aircraft->multiMotorChannelBox6);
} parent.addWidget(m_aircraft->multiMotorChannelBox7);
else if (frameType == "QuadX" || frameType == "Quad X") { parent.addWidget(m_aircraft->multiMotorChannelBox8);
if(invertMotors > 0) parent.addWidget(m_aircraft->mrPitchMixLevel);
quad->setElementId("quad-x"); parent.addWidget(m_aircraft->mrRollMixLevel);
else parent.addWidget(m_aircraft->mrYawMixLevel);
quad->setElementId("quad-x_reverse"); parent.addWidget(m_aircraft->triYawChannelBox);
}
else if (frameType == "QuadP" || frameType == "Quad +") {
if(invertMotors > 0)
quad->setElementId("quad-plus");
else
quad->setElementId("quad-plus_reverse");
}
else if (frameType == "Hexa" || frameType == "Hexacopter")
{
if(invertMotors > 0)
quad->setElementId("quad-hexa");
else
quad->setElementId("quad-hexa_reverse");
}
else if (frameType == "HexaX" || frameType == "Hexacopter X" ) {
if(invertMotors > 0)
quad->setElementId("quad-hexa-H");
else
quad->setElementId("quad-hexa-H_reverse");
}
else if (frameType == "HexaCoax" || frameType == "Hexacopter Y6")
{
if(invertMotors > 0)
quad->setElementId("hexa-coax");
else
quad->setElementId("hexa-coax_reverse");
}
else if (frameType == "Octo" || frameType == "Octocopter")
{
if(invertMotors > 0)
quad->setElementId("quad-octo");
else
quad->setElementId("quad-octo_reverse");
}
else if (frameType == "OctoV" || frameType == "Octocopter V")
{
if(invertMotors > 0)
quad->setElementId("quad-octo-v");
else
quad->setElementId("quad-octo-v_reverse");
}
else if (frameType == "OctoCoaxP" || frameType == "Octo Coax +")
{
if(invertMotors > 0)
quad->setElementId("octo-coax-P");
else
quad->setElementId("octo-coax-P_reverse");
}
else if (frameType == "OctoCoaxX" || frameType == "Octo Coax X")
{
if(invertMotors > 0)
quad->setElementId("octo-coax-X");
else
quad->setElementId("octo-coax-X_reverse");
}
} }
void ConfigMultiRotorWidget::ResetActuators(GUIConfigDataUnion* configData) void ConfigMultiRotorWidget::resetActuators(GUIConfigDataUnion *configData)
{ {
configData->multi.VTOLMotorN = 0; configData->multi.VTOLMotorN = 0;
configData->multi.VTOLMotorNE = 0; configData->multi.VTOLMotorNE = 0;
@ -290,74 +279,262 @@ void ConfigMultiRotorWidget::ResetActuators(GUIConfigDataUnion* configData)
configData->multi.TRIYaw = 0; configData->multi.TRIYaw = 0;
} }
QStringList ConfigMultiRotorWidget::getChannelDescriptions() /**
Helper function to refresh the UI widget values
*/
void ConfigMultiRotorWidget::refreshWidgetsValues(QString frameType)
{ {
QStringList channelDesc; Q_ASSERT(m_aircraft);
// init a channel_numelem list of channel desc defaults setupUI(frameType);
for (int i=0; i < (int)(ConfigMultiRotorWidget::CHANNEL_NUMELEM); i++)
{ UAVDataObject *mixer = dynamic_cast<UAVDataObject *>(getObjectManager()->getObject(QString("MixerSettings")));
channelDesc.append(QString("-")); Q_ASSERT(mixer);
QList<double> curveValues;
getThrottleCurve(mixer, VehicleConfig::MIXER_THROTTLECURVE1, &curveValues);
// is at least one of the curve values != 0?
if (isValidThrottleCurve(&curveValues)) {
// yes, use the curve we just read from mixersettings
m_aircraft->multiThrottleCurve->initCurve(&curveValues);
} else {
// no, init a straight curve
m_aircraft->multiThrottleCurve->initLinearCurve(curveValues.count(), 0.9);
} }
// get the gui config data GUIConfigDataUnion config = getConfigData();
GUIConfigDataUnion configData = GetConfigData(); multiGUISettingsStruct multi = config.multi;
multiGUISettingsStruct multi = configData.multi;
if (multi.VTOLMotorN > 0 && multi.VTOLMotorN <= ConfigMultiRotorWidget::CHANNEL_NUMELEM) if (frameType == "QuadP") {
channelDesc[multi.VTOLMotorN-1] = QString("VTOLMotorN"); // Motors 1/2/3/4 are: N / E / S / W
if (multi.VTOLMotorNE > 0 && multi.VTOLMotorNE <= ConfigMultiRotorWidget::CHANNEL_NUMELEM) setComboCurrentIndex(m_aircraft->multiMotorChannelBox1, multi.VTOLMotorN);
channelDesc[multi.VTOLMotorNE-1] = QString("VTOLMotorNE"); setComboCurrentIndex(m_aircraft->multiMotorChannelBox2, multi.VTOLMotorE);
if (multi.VTOLMotorNW > 0 && multi.VTOLMotorNW <= ConfigMultiRotorWidget::CHANNEL_NUMELEM) setComboCurrentIndex(m_aircraft->multiMotorChannelBox3, multi.VTOLMotorS);
channelDesc[multi.VTOLMotorNW-1] = QString("VTOLMotorNW"); setComboCurrentIndex(m_aircraft->multiMotorChannelBox4, multi.VTOLMotorW);
if (multi.VTOLMotorS > 0 && multi.VTOLMotorS <= ConfigMultiRotorWidget::CHANNEL_NUMELEM)
channelDesc[multi.VTOLMotorS-1] = QString("VTOLMotorS");
if (multi.VTOLMotorSE > 0 && multi.VTOLMotorSE <= ConfigMultiRotorWidget::CHANNEL_NUMELEM)
channelDesc[multi.VTOLMotorSE-1] = QString("VTOLMotorSE");
if (multi.VTOLMotorSW > 0 && multi.VTOLMotorSW <= ConfigMultiRotorWidget::CHANNEL_NUMELEM)
channelDesc[multi.VTOLMotorSW-1] = QString("VTOLMotorSW");
if (multi.VTOLMotorW > 0 && multi.VTOLMotorW <= ConfigMultiRotorWidget::CHANNEL_NUMELEM)
channelDesc[multi.VTOLMotorW-1] = QString("VTOLMotorW");
if (multi.VTOLMotorE > 0 && multi.VTOLMotorE <= ConfigMultiRotorWidget::CHANNEL_NUMELEM)
channelDesc[multi.VTOLMotorE-1] = QString("VTOLMotorE");
if (multi.TRIYaw > 0 && multi.TRIYaw <= ConfigMultiRotorWidget::CHANNEL_NUMELEM)
channelDesc[multi.TRIYaw-1] = QString("Tri-Yaw");
return channelDesc; // 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.
int channel = m_aircraft->multiMotorChannelBox1->currentIndex() - 1;
if (channel > -1) {
double value = getMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_PITCH);
m_aircraft->mrPitchMixLevel->setValue(qRound(value / 1.27));
value = getMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_YAW);
setYawMixLevel(-qRound(value / 1.27));
channel = m_aircraft->multiMotorChannelBox2->currentIndex() - 1;
value = getMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_ROLL);
m_aircraft->mrRollMixLevel->setValue(-qRound(value / 1.27));
}
} else if (frameType == "QuadX") {
// Motors 1/2/3/4 are: NW / NE / SE / SW
setComboCurrentIndex(m_aircraft->multiMotorChannelBox1, multi.VTOLMotorNW);
setComboCurrentIndex(m_aircraft->multiMotorChannelBox2, multi.VTOLMotorNE);
setComboCurrentIndex(m_aircraft->multiMotorChannelBox3, multi.VTOLMotorSE);
setComboCurrentIndex(m_aircraft->multiMotorChannelBox4, multi.VTOLMotorSW);
// 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.
int channel = m_aircraft->multiMotorChannelBox1->currentIndex() - 1;
if (channel > -1) {
double value = getMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_PITCH);
m_aircraft->mrPitchMixLevel->setValue(qRound(value / 1.27));
value = getMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_YAW);
setYawMixLevel(-qRound(value / 1.27));
value = getMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_ROLL);
m_aircraft->mrRollMixLevel->setValue(qRound(value / 1.27));
}
} else if (frameType == "Hexa") {
// Motors 1/2/3 4/5/6 are: N / NE / SE / S / SW / NW
setComboCurrentIndex(m_aircraft->multiMotorChannelBox1, multi.VTOLMotorN);
setComboCurrentIndex(m_aircraft->multiMotorChannelBox2, multi.VTOLMotorNE);
setComboCurrentIndex(m_aircraft->multiMotorChannelBox3, multi.VTOLMotorSE);
setComboCurrentIndex(m_aircraft->multiMotorChannelBox4, multi.VTOLMotorS);
setComboCurrentIndex(m_aircraft->multiMotorChannelBox5, multi.VTOLMotorSW);
setComboCurrentIndex(m_aircraft->multiMotorChannelBox6, multi.VTOLMotorNW);
// 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.
int channel = m_aircraft->multiMotorChannelBox1->currentIndex() - 1;
if (channel > -1) {
double value = getMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_PITCH);
m_aircraft->mrPitchMixLevel->setValue(qRound(value / 1.27));
value = getMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_YAW);
setYawMixLevel(-qRound(value / 1.27));
//change channels
channel = m_aircraft->multiMotorChannelBox2->currentIndex() - 1;
value = getMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_ROLL);
m_aircraft->mrRollMixLevel->setValue(-qRound(value / 1.27));
}
} else if (frameType == "HexaX") {
// Motors 1/2/3 4/5/6 are: NE / E / SE / SW / W / NW
setComboCurrentIndex(m_aircraft->multiMotorChannelBox1, multi.VTOLMotorNE);
setComboCurrentIndex(m_aircraft->multiMotorChannelBox2, multi.VTOLMotorE);
setComboCurrentIndex(m_aircraft->multiMotorChannelBox3, multi.VTOLMotorSE);
setComboCurrentIndex(m_aircraft->multiMotorChannelBox4, multi.VTOLMotorSW);
setComboCurrentIndex(m_aircraft->multiMotorChannelBox5, multi.VTOLMotorW);
setComboCurrentIndex(m_aircraft->multiMotorChannelBox6, multi.VTOLMotorNW);
// 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.
int channel = m_aircraft->multiMotorChannelBox1->currentIndex() - 1;
if (channel > -1) {
double value = getMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_PITCH);
m_aircraft->mrPitchMixLevel->setValue(qRound(value / 1.27));
value = getMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_YAW);
setYawMixLevel(-qRound(value / 1.27));
channel = m_aircraft->multiMotorChannelBox2->currentIndex() - 1;
value = getMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_ROLL);
m_aircraft->mrRollMixLevel->setValue(-qRound(value / 1.27));
}
} else if (frameType == "HexaCoax") {
// Motors 1/2/3 4/5/6 are: NW/W NE/E S/SE
setComboCurrentIndex(m_aircraft->multiMotorChannelBox1, multi.VTOLMotorNW);
setComboCurrentIndex(m_aircraft->multiMotorChannelBox2, multi.VTOLMotorW);
setComboCurrentIndex(m_aircraft->multiMotorChannelBox3, multi.VTOLMotorNE);
setComboCurrentIndex(m_aircraft->multiMotorChannelBox4, multi.VTOLMotorE);
setComboCurrentIndex(m_aircraft->multiMotorChannelBox5, multi.VTOLMotorS);
setComboCurrentIndex(m_aircraft->multiMotorChannelBox6, multi.VTOLMotorSE);
// 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.
int channel = m_aircraft->multiMotorChannelBox1->currentIndex() - 1;
if (channel > -1) {
double value = getMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_PITCH);
m_aircraft->mrPitchMixLevel->setValue(qRound(2 * value / 1.27));
channel = m_aircraft->multiMotorChannelBox2->currentIndex() - 1;
value = getMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_YAW);
setYawMixLevel(qRound(value / 1.27));
value = getMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_ROLL);
m_aircraft->mrRollMixLevel->setValue(qRound(value / 1.27));
}
} else if (frameType == "Octo" || frameType == "OctoV" || frameType == "OctoCoaxP") {
// Motors 1 to 8 are N / NE / E / etc
setComboCurrentIndex(m_aircraft->multiMotorChannelBox1, multi.VTOLMotorN);
setComboCurrentIndex(m_aircraft->multiMotorChannelBox2, multi.VTOLMotorNE);
setComboCurrentIndex(m_aircraft->multiMotorChannelBox3, multi.VTOLMotorE);
setComboCurrentIndex(m_aircraft->multiMotorChannelBox4, multi.VTOLMotorSE);
setComboCurrentIndex(m_aircraft->multiMotorChannelBox5, multi.VTOLMotorS);
setComboCurrentIndex(m_aircraft->multiMotorChannelBox6, multi.VTOLMotorSW);
setComboCurrentIndex(m_aircraft->multiMotorChannelBox7, multi.VTOLMotorW);
setComboCurrentIndex(m_aircraft->multiMotorChannelBox8, multi.VTOLMotorNW);
// 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.
int channel = m_aircraft->multiMotorChannelBox1->currentIndex() - 1;
if (channel > -1) {
if (frameType == "Octo") {
double value = getMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_PITCH);
m_aircraft->mrPitchMixLevel->setValue(qRound(value / 1.27));
value = getMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_YAW);
setYawMixLevel(-qRound(value / 1.27));
//change channels
channel = m_aircraft->multiMotorChannelBox2->currentIndex() - 1;
value = getMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_ROLL);
m_aircraft->mrRollMixLevel->setValue(-qRound(value / 1.27));
} else if (frameType == "OctoV") {
double value = getMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_PITCH);
m_aircraft->mrPitchMixLevel->setValue(qRound(value / 1.27));
value = getMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_YAW);
setYawMixLevel(-qRound(value / 1.27));
//change channels
channel = m_aircraft->multiMotorChannelBox2->currentIndex() - 1;
value = getMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_ROLL);
m_aircraft->mrRollMixLevel->setValue(-qRound(value / 1.27));
} else if (frameType == "OctoCoaxP") {
double value = getMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_PITCH);
m_aircraft->mrPitchMixLevel->setValue(qRound(value / 1.27));
value = getMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_YAW);
setYawMixLevel(-qRound(value / 1.27));
//change channels
channel = m_aircraft->multiMotorChannelBox3->currentIndex() - 1;
value = getMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_ROLL);
m_aircraft->mrRollMixLevel->setValue(-qRound(value / 1.27));
}
}
} else if (frameType == "OctoCoaxX") {
// Motors 1 to 8 are N / NE / E / etc
setComboCurrentIndex(m_aircraft->multiMotorChannelBox1, multi.VTOLMotorNW);
setComboCurrentIndex(m_aircraft->multiMotorChannelBox2, multi.VTOLMotorN);
setComboCurrentIndex(m_aircraft->multiMotorChannelBox3, multi.VTOLMotorNE);
setComboCurrentIndex(m_aircraft->multiMotorChannelBox4, multi.VTOLMotorE);
setComboCurrentIndex(m_aircraft->multiMotorChannelBox5, multi.VTOLMotorSE);
setComboCurrentIndex(m_aircraft->multiMotorChannelBox6, multi.VTOLMotorS);
setComboCurrentIndex(m_aircraft->multiMotorChannelBox7, multi.VTOLMotorSW);
setComboCurrentIndex(m_aircraft->multiMotorChannelBox8, multi.VTOLMotorW);
// 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.
int channel = m_aircraft->multiMotorChannelBox1->currentIndex() - 1;
if (channel > -1) {
double value = getMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_PITCH);
m_aircraft->mrPitchMixLevel->setValue(qRound(value / 1.27));
value = getMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_YAW);
setYawMixLevel(-qRound(value / 1.27));
value = getMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_ROLL);
m_aircraft->mrRollMixLevel->setValue(qRound(value / 1.27));
}
} else if (frameType == "Tri") {
// Motors 1 to 8 are N / NE / E / etc
setComboCurrentIndex(m_aircraft->multiMotorChannelBox1, multi.VTOLMotorNW);
setComboCurrentIndex(m_aircraft->multiMotorChannelBox2, multi.VTOLMotorNE);
setComboCurrentIndex(m_aircraft->multiMotorChannelBox3, multi.VTOLMotorS);
setComboCurrentIndex(m_aircraft->multiMotorChannelBox4, multi.VTOLMotorS);
setComboCurrentIndex(m_aircraft->triYawChannelBox, multi.TRIYaw);
int channel = m_aircraft->multiMotorChannelBox1->currentIndex() - 1;
if (channel > -1) {
double value = getMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_PITCH);
m_aircraft->mrPitchMixLevel->setValue(qRound(2 * value / 1.27));
value = getMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_ROLL);
m_aircraft->mrRollMixLevel->setValue(qRound(value / 1.27));
}
}
updateAirframe(frameType);
} }
void ConfigMultiRotorWidget::setYawMixLevel(int value)
{
if(value<0)
{
m_aircraft->mrYawMixLevel->setValue((-1)*value);
m_aircraft->MultirotorRevMixercheckBox->setChecked(true);
}
else
{
m_aircraft->mrYawMixLevel->setValue(value);
m_aircraft->MultirotorRevMixercheckBox->setChecked(false);
}
}
/** /**
Helper function to update the UI widget objects Helper function to update the UI widget objects
*/ */
QString ConfigMultiRotorWidget::updateConfigObjectsFromWidgets() QString ConfigMultiRotorWidget::updateConfigObjectsFromWidgets()
{ {
QString airframeType; UAVDataObject *mixer = dynamic_cast<UAVDataObject *>(getObjectManager()->getObject(QString("MixerSettings")));
QList<QString> motorList; Q_ASSERT(mixer);
UAVDataObject* mixerObj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
Q_ASSERT(mixerObj);
// Curve is also common to all quads: // Curve is also common to all quads:
setThrottleCurve(mixerObj, VehicleConfig::MIXER_THROTTLECURVE1, m_aircraft->multiThrottleCurve->getCurve() ); setThrottleCurve(mixer, VehicleConfig::MIXER_THROTTLECURVE1, m_aircraft->multiThrottleCurve->getCurve() );
QString airframeType;
QList<QString> motorList;
if (m_aircraft->multirotorFrameType->currentText() == "Quad +") { if (m_aircraft->multirotorFrameType->currentText() == "Quad +") {
airframeType = "QuadP"; airframeType = "QuadP";
setupQuad(true); setupQuad(true);
@ -373,135 +550,134 @@ QString ConfigMultiRotorWidget::updateConfigObjectsFromWidgets()
} else if (m_aircraft->multirotorFrameType->currentText() == "Hexacopter Y6") { } else if (m_aircraft->multirotorFrameType->currentText() == "Hexacopter Y6") {
airframeType = "HexaCoax"; airframeType = "HexaCoax";
//Show any config errors in GUI // Show any config errors in GUI
if (throwConfigError(6)) { if (throwConfigError(6)) {
return airframeType; return airframeType;
} }
motorList << "VTOLMotorNW" << "VTOLMotorW" << "VTOLMotorNE" << "VTOLMotorE" motorList << "VTOLMotorNW" << "VTOLMotorW" << "VTOLMotorNE" << "VTOLMotorE" << "VTOLMotorS" << "VTOLMotorSE";
<< "VTOLMotorS" << "VTOLMotorSE";
setupMotors(motorList); setupMotors(motorList);
// Motor 1 to 6, Y6 Layout: // Motor 1 to 6, Y6 Layout:
// pitch roll yaw // pitch roll yaw
double mixer [8][3] = { double mixerMatrix[8][3] = {
{ 0.5, 1, -1}, { 0.5, 1, -1 },
{ 0.5, 1, 1}, { 0.5, 1, 1 },
{ 0.5, -1, -1}, { 0.5, -1, -1 },
{ 0.5, -1, 1}, { 0.5, -1, 1 },
{ -1, 0, -1}, { -1, 0, -1 },
{ -1, 0, 1}, { -1, 0, 1 },
{ 0, 0, 0}, { 0, 0, 0 },
{ 0, 0, 0} { 0, 0, 0 }
}; };
setupMultiRotorMixer(mixer); setupMultiRotorMixer(mixerMatrix);
m_aircraft->mrStatusLabel->setText("Configuration OK"); m_aircraft->mrStatusLabel->setText("Configuration OK");
} else if (m_aircraft->multirotorFrameType->currentText() == "Octocopter") { } else if (m_aircraft->multirotorFrameType->currentText() == "Octocopter") {
airframeType = "Octo"; airframeType = "Octo";
//Show any config errors in GUI // Show any config errors in GUI
if (throwConfigError(8)) { if (throwConfigError(8)) {
return airframeType; return airframeType;
} }
motorList << "VTOLMotorN" << "VTOLMotorNE" << "VTOLMotorE" << "VTOLMotorSE" motorList << "VTOLMotorN" << "VTOLMotorNE" << "VTOLMotorE" << "VTOLMotorSE" << "VTOLMotorS" << "VTOLMotorSW"
<< "VTOLMotorS" << "VTOLMotorSW" << "VTOLMotorW" << "VTOLMotorNW"; << "VTOLMotorW" << "VTOLMotorNW";
setupMotors(motorList); setupMotors(motorList);
// Motor 1 to 8: // Motor 1 to 8:
// pitch roll yaw // pitch roll yaw
double mixer [8][3] = { double mixerMatrix[8][3] = {
{ 1, 0, -1}, { 1, 0, -1 },
{ 1, -1, 1}, { 1, -1, 1 },
{ 0, -1, -1}, { 0, -1, -1 },
{ -1, -1, 1}, { -1, -1, 1 },
{ -1, 0, -1}, { -1, 0, -1 },
{ -1, 1, 1}, { -1, 1, 1 },
{ 0, 1, -1}, { 0, 1, -1 },
{ 1, 1, 1} { 1, 1, 1 }
}; };
setupMultiRotorMixer(mixer); setupMultiRotorMixer(mixerMatrix);
m_aircraft->mrStatusLabel->setText("Configuration OK"); m_aircraft->mrStatusLabel->setText("Configuration OK");
} else if (m_aircraft->multirotorFrameType->currentText() == "Octocopter V") { } else if (m_aircraft->multirotorFrameType->currentText() == "Octocopter V") {
airframeType = "OctoV"; airframeType = "OctoV";
//Show any config errors in GUI // Show any config errors in GUI
if (throwConfigError(8)) { if (throwConfigError(8)) {
return airframeType; return airframeType;
} }
motorList << "VTOLMotorN" << "VTOLMotorNE" << "VTOLMotorE" << "VTOLMotorSE" motorList << "VTOLMotorN" << "VTOLMotorNE" << "VTOLMotorE" << "VTOLMotorSE" << "VTOLMotorS" << "VTOLMotorSW"
<< "VTOLMotorS" << "VTOLMotorSW" << "VTOLMotorW" << "VTOLMotorNW"; << "VTOLMotorW" << "VTOLMotorNW";
setupMotors(motorList); setupMotors(motorList);
// Motor 1 to 8: // Motor 1 to 8:
// IMPORTANT: Assumes evenly spaced engines // IMPORTANT: Assumes evenly spaced engines
// pitch roll yaw // pitch roll yaw
double mixer [8][3] = { double mixerMatrix[8][3] = {
{ 0.33, -1, -1}, { 0.33, -1, -1 },
{ 1 , -1, 1}, { 1 , -1, 1 },
{ -1 , -1, -1}, { -1 , -1, -1 },
{ -0.33, -1, 1}, { -0.33, -1, 1 },
{ -0.33, 1, -1}, { -0.33, 1, -1 },
{ -1 , 1, 1}, { -1 , 1, 1 },
{ 1 , 1, -1}, { 1 , 1, -1 },
{ 0.33, 1, 1} { 0.33, 1, 1 }
}; };
setupMultiRotorMixer(mixer); setupMultiRotorMixer(mixerMatrix);
m_aircraft->mrStatusLabel->setText("Configuration OK"); m_aircraft->mrStatusLabel->setText("Configuration OK");
} else if (m_aircraft->multirotorFrameType->currentText() == "Octo Coax +") { } else if (m_aircraft->multirotorFrameType->currentText() == "Octo Coax +") {
airframeType = "OctoCoaxP"; airframeType = "OctoCoaxP";
//Show any config errors in GUI // Show any config errors in GUI
if (throwConfigError(8)) { if (throwConfigError(8)) {
return airframeType; return airframeType;
} }
motorList << "VTOLMotorN" << "VTOLMotorNE" << "VTOLMotorE" << "VTOLMotorSE" motorList << "VTOLMotorN" << "VTOLMotorNE" << "VTOLMotorE" << "VTOLMotorSE" << "VTOLMotorS" << "VTOLMotorSW"
<< "VTOLMotorS" << "VTOLMotorSW" << "VTOLMotorW" << "VTOLMotorNW"; << "VTOLMotorW" << "VTOLMotorNW";
setupMotors(motorList); setupMotors(motorList);
// Motor 1 to 8: // Motor 1 to 8:
// pitch roll yaw // pitch roll yaw
double mixer [8][3] = { double mixerMatrix[8][3] = {
{ 1, 0, -1}, { 1, 0, -1 },
{ 1, 0, 1}, { 1, 0, 1 },
{ 0, -1, -1}, { 0, -1, -1 },
{ 0, -1, 1}, { 0, -1, 1 },
{ -1, 0, -1}, { -1, 0, -1 },
{ -1, 0, 1}, { -1, 0, 1 },
{ 0, 1, -1}, { 0, 1, -1 },
{ 0, 1, 1} { 0, 1, 1 }
}; };
setupMultiRotorMixer(mixer); setupMultiRotorMixer(mixerMatrix);
m_aircraft->mrStatusLabel->setText("Configuration OK"); m_aircraft->mrStatusLabel->setText("Configuration OK");
} else if (m_aircraft->multirotorFrameType->currentText() == "Octo Coax X") { } else if (m_aircraft->multirotorFrameType->currentText() == "Octo Coax X") {
airframeType = "OctoCoaxX"; airframeType = "OctoCoaxX";
//Show any config errors in GUI // Show any config errors in GUI
if (throwConfigError(8)) { if (throwConfigError(8)) {
return airframeType; return airframeType;
} }
motorList << "VTOLMotorNW" << "VTOLMotorN" << "VTOLMotorNE" << "VTOLMotorE" motorList << "VTOLMotorNW" << "VTOLMotorN" << "VTOLMotorNE" << "VTOLMotorE" << "VTOLMotorSE" << "VTOLMotorS"
<< "VTOLMotorSE" << "VTOLMotorS" << "VTOLMotorSW" << "VTOLMotorW"; << "VTOLMotorSW" << "VTOLMotorW";
setupMotors(motorList); setupMotors(motorList);
// Motor 1 to 8: // Motor 1 to 8:
// pitch roll yaw // pitch roll yaw
double mixer [8][3] = { double mixerMatrix[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 },
{ -1, -1, -1}, { -1, -1, -1 },
{ -1, -1, 1}, { -1, -1, 1 },
{ -1, 1, -1}, { -1, 1, -1 },
{ -1, 1, 1} { -1, 1, 1 }
}; };
setupMultiRotorMixer(mixer); setupMultiRotorMixer(mixerMatrix);
m_aircraft->mrStatusLabel->setText("Configuration OK"); m_aircraft->mrStatusLabel->setText("Configuration OK");
} else if (m_aircraft->multirotorFrameType->currentText() == "Tricopter Y") { } else if (m_aircraft->multirotorFrameType->currentText() == "Tricopter Y") {
airframeType = "Tri"; airframeType = "Tri";
//Show any config errors in GUI // Show any config errors in GUI
if (throwConfigError(3)) { if (throwConfigError(3)) {
return airframeType; return airframeType;
@ -513,31 +689,30 @@ QString ConfigMultiRotorWidget::updateConfigObjectsFromWidgets()
motorList << "VTOLMotorNW" << "VTOLMotorNE" << "VTOLMotorS"; motorList << "VTOLMotorNW" << "VTOLMotorNE" << "VTOLMotorS";
setupMotors(motorList); setupMotors(motorList);
GUIConfigDataUnion config = GetConfigData(); GUIConfigDataUnion config = getConfigData();
config.multi.TRIYaw = m_aircraft->triYawChannelBox->currentIndex(); config.multi.TRIYaw = m_aircraft->triYawChannelBox->currentIndex();
SetConfigData(config); setConfigData(config);
// Motor 1 to 6, Y6 Layout: // Motor 1 to 6, Y6 Layout:
// pitch roll yaw // pitch roll yaw
double mixer [8][3] = { double mixerMatrix[8][3] = {
{ 0.5, 1, 0}, { 0.5, 1, 0 },
{ 0.5, -1, 0}, { 0.5, -1, 0 },
{ -1, 0, 0}, { -1, 0, 0 },
{ 0, 0, 0}, { 0, 0, 0 },
{ 0, 0, 0}, { 0, 0, 0 },
{ 0, 0, 0}, { 0, 0, 0 },
{ 0, 0, 0}, { 0, 0, 0 },
{ 0, 0, 0} { 0, 0, 0 }
}; };
setupMultiRotorMixer(mixer); setupMultiRotorMixer(mixerMatrix);
//tell the mixer about tricopter yaw channel // tell the mixer about tricopter yaw channel
int channel = m_aircraft->triYawChannelBox->currentIndex()-1; int channel = m_aircraft->triYawChannelBox->currentIndex() - 1;
if (channel > -1){ if (channel > -1) {
setMixerType(mixerObj, channel, VehicleConfig::MIXERTYPE_SERVO); setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_SERVO);
setMixerVectorValue(mixerObj, channel, VehicleConfig::MIXERVECTOR_YAW, 127); setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_YAW, 127);
} }
m_aircraft->mrStatusLabel->setText(tr("Configuration OK")); m_aircraft->mrStatusLabel->setText(tr("Configuration OK"));
@ -547,278 +722,61 @@ QString ConfigMultiRotorWidget::updateConfigObjectsFromWidgets()
return airframeType; return airframeType;
} }
void ConfigMultiRotorWidget::setYawMixLevel(int value)
/**
Helper function to refresh the UI widget values
*/
void ConfigMultiRotorWidget::refreshWidgetsValues(QString frameType)
{ {
int channel; if (value < 0) {
double value; m_aircraft->mrYawMixLevel->setValue(-value);
m_aircraft->MultirotorRevMixerCheckBox->setChecked(true);
GUIConfigDataUnion config = GetConfigData(); } else {
multiGUISettingsStruct multi = config.multi; m_aircraft->mrYawMixLevel->setValue(value);
m_aircraft->MultirotorRevMixerCheckBox->setChecked(false);
UAVDataObject* mixer = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
Q_ASSERT(mixer);
if (frameType == "QuadP")
{
// Motors 1/2/3/4 are: N / E / S / W
setComboCurrentIndex(m_aircraft->multiMotorChannelBox1,multi.VTOLMotorN);
setComboCurrentIndex(m_aircraft->multiMotorChannelBox2,multi.VTOLMotorE);
setComboCurrentIndex(m_aircraft->multiMotorChannelBox3,multi.VTOLMotorS);
setComboCurrentIndex(m_aircraft->multiMotorChannelBox4,multi.VTOLMotorW);
// 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.
channel = m_aircraft->multiMotorChannelBox1->currentIndex() - 1;
if (channel > -1)
{
value = getMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_PITCH);
m_aircraft->mrPitchMixLevel->setValue( qRound(value/1.27) );
value = getMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_YAW);
setYawMixLevel( -qRound(value/1.27) );
channel = m_aircraft->multiMotorChannelBox2->currentIndex() - 1;
value = getMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_ROLL);
m_aircraft->mrRollMixLevel->setValue( -qRound(value/1.27));
}
}
else if (frameType == "QuadX")
{
// Motors 1/2/3/4 are: NW / NE / SE / SW
setComboCurrentIndex(m_aircraft->multiMotorChannelBox1,multi.VTOLMotorNW);
setComboCurrentIndex(m_aircraft->multiMotorChannelBox2,multi.VTOLMotorNE);
setComboCurrentIndex(m_aircraft->multiMotorChannelBox3,multi.VTOLMotorSE);
setComboCurrentIndex(m_aircraft->multiMotorChannelBox4,multi.VTOLMotorSW);
// 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.
channel = m_aircraft->multiMotorChannelBox1->currentIndex() - 1;
if (channel > -1)
{
value = getMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_PITCH);
m_aircraft->mrPitchMixLevel->setValue( qRound(value/1.27) );
value = getMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_YAW);
setYawMixLevel( -qRound(value/1.27) );
value = getMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_ROLL);
m_aircraft->mrRollMixLevel->setValue( qRound(value/1.27));
}
}
else if (frameType == "Hexa")
{
// Motors 1/2/3 4/5/6 are: N / NE / SE / S / SW / NW
setComboCurrentIndex(m_aircraft->multiMotorChannelBox1,multi.VTOLMotorN);
setComboCurrentIndex(m_aircraft->multiMotorChannelBox2,multi.VTOLMotorNE);
setComboCurrentIndex(m_aircraft->multiMotorChannelBox3,multi.VTOLMotorSE);
setComboCurrentIndex(m_aircraft->multiMotorChannelBox4,multi.VTOLMotorS);
setComboCurrentIndex(m_aircraft->multiMotorChannelBox5,multi.VTOLMotorSW);
setComboCurrentIndex(m_aircraft->multiMotorChannelBox6,multi.VTOLMotorNW);
// 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.
channel = m_aircraft->multiMotorChannelBox1->currentIndex() - 1;
if (channel > -1)
{
value = getMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_PITCH);
m_aircraft->mrPitchMixLevel->setValue( qRound(value/1.27) );
value = getMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_YAW);
setYawMixLevel( -qRound(value/1.27) );
//change channels
channel = m_aircraft->multiMotorChannelBox2->currentIndex() - 1;
value = getMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_ROLL);
m_aircraft->mrRollMixLevel->setValue( -qRound(value/1.27) );
}
}
else if (frameType == "HexaX")
{
// Motors 1/2/3 4/5/6 are: NE / E / SE / SW / W / NW
setComboCurrentIndex(m_aircraft->multiMotorChannelBox1,multi.VTOLMotorNE);
setComboCurrentIndex(m_aircraft->multiMotorChannelBox2,multi.VTOLMotorE);
setComboCurrentIndex(m_aircraft->multiMotorChannelBox3,multi.VTOLMotorSE);
setComboCurrentIndex(m_aircraft->multiMotorChannelBox4,multi.VTOLMotorSW);
setComboCurrentIndex(m_aircraft->multiMotorChannelBox5,multi.VTOLMotorW);
setComboCurrentIndex(m_aircraft->multiMotorChannelBox6,multi.VTOLMotorNW);
// 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.
channel = m_aircraft->multiMotorChannelBox1->currentIndex() - 1;
if (channel > -1)
{
value = getMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_PITCH);
m_aircraft->mrPitchMixLevel->setValue( qRound(value/1.27) );
value = getMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_YAW);
setYawMixLevel( -qRound(value/1.27) );
channel = m_aircraft->multiMotorChannelBox2->currentIndex() - 1;
value = getMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_ROLL);
m_aircraft->mrRollMixLevel->setValue( -qRound(value/1.27) );
}
}
else if (frameType == "HexaCoax")
{
// Motors 1/2/3 4/5/6 are: NW/W NE/E S/SE
setComboCurrentIndex(m_aircraft->multiMotorChannelBox1,multi.VTOLMotorNW);
setComboCurrentIndex(m_aircraft->multiMotorChannelBox2,multi.VTOLMotorW);
setComboCurrentIndex(m_aircraft->multiMotorChannelBox3,multi.VTOLMotorNE);
setComboCurrentIndex(m_aircraft->multiMotorChannelBox4,multi.VTOLMotorE);
setComboCurrentIndex(m_aircraft->multiMotorChannelBox5,multi.VTOLMotorS);
setComboCurrentIndex(m_aircraft->multiMotorChannelBox6,multi.VTOLMotorSE);
// 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.
channel = m_aircraft->multiMotorChannelBox1->currentIndex() - 1;
if (channel > -1)
{
value = getMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_PITCH);
m_aircraft->mrPitchMixLevel->setValue( qRound(2*value/1.27) );
channel = m_aircraft->multiMotorChannelBox2->currentIndex() - 1;
value = getMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_YAW);
setYawMixLevel( qRound(value/1.27) );
value = getMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_ROLL);
m_aircraft->mrRollMixLevel->setValue( qRound(value/1.27) );
}
}
else if (frameType == "Octo" || frameType == "OctoV" || frameType == "OctoCoaxP")
{
// Motors 1 to 8 are N / NE / E / etc
setComboCurrentIndex(m_aircraft->multiMotorChannelBox1,multi.VTOLMotorN);
setComboCurrentIndex(m_aircraft->multiMotorChannelBox2,multi.VTOLMotorNE);
setComboCurrentIndex(m_aircraft->multiMotorChannelBox3,multi.VTOLMotorE);
setComboCurrentIndex(m_aircraft->multiMotorChannelBox4,multi.VTOLMotorSE);
setComboCurrentIndex(m_aircraft->multiMotorChannelBox5,multi.VTOLMotorS);
setComboCurrentIndex(m_aircraft->multiMotorChannelBox6,multi.VTOLMotorSW);
setComboCurrentIndex(m_aircraft->multiMotorChannelBox7,multi.VTOLMotorW);
setComboCurrentIndex(m_aircraft->multiMotorChannelBox8,multi.VTOLMotorNW);
// 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.
channel = m_aircraft->multiMotorChannelBox1->currentIndex() - 1;
if (channel > -1)
{
if (frameType == "Octo") {
value = getMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_PITCH);
m_aircraft->mrPitchMixLevel->setValue( qRound(value/1.27) );
value = getMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_YAW);
setYawMixLevel( -qRound(value/1.27) );
//change channels
channel = m_aircraft->multiMotorChannelBox2->currentIndex() - 1;
value = getMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_ROLL);
m_aircraft->mrRollMixLevel->setValue( -qRound(value/1.27) );
}
else if (frameType == "OctoV") {
value = getMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_PITCH);
m_aircraft->mrPitchMixLevel->setValue( qRound(value/1.27) );
value = getMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_YAW);
setYawMixLevel( -qRound(value/1.27) );
//change channels
channel = m_aircraft->multiMotorChannelBox2->currentIndex() - 1;
value = getMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_ROLL);
m_aircraft->mrRollMixLevel->setValue( -qRound(value/1.27) );
}
else if (frameType == "OctoCoaxP") {
value = getMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_PITCH);
m_aircraft->mrPitchMixLevel->setValue( qRound(value/1.27) );
value = getMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_YAW);
setYawMixLevel( -qRound(value/1.27) );
//change channels
channel = m_aircraft->multiMotorChannelBox3->currentIndex() - 1;
value = getMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_ROLL);
m_aircraft->mrRollMixLevel->setValue( -qRound(value/1.27) );
}
}
}
else if (frameType == "OctoCoaxX")
{
// Motors 1 to 8 are N / NE / E / etc
setComboCurrentIndex(m_aircraft->multiMotorChannelBox1,multi.VTOLMotorNW);
setComboCurrentIndex(m_aircraft->multiMotorChannelBox2,multi.VTOLMotorN);
setComboCurrentIndex(m_aircraft->multiMotorChannelBox3,multi.VTOLMotorNE);
setComboCurrentIndex(m_aircraft->multiMotorChannelBox4,multi.VTOLMotorE);
setComboCurrentIndex(m_aircraft->multiMotorChannelBox5,multi.VTOLMotorSE);
setComboCurrentIndex(m_aircraft->multiMotorChannelBox6,multi.VTOLMotorS);
setComboCurrentIndex(m_aircraft->multiMotorChannelBox7,multi.VTOLMotorSW);
setComboCurrentIndex(m_aircraft->multiMotorChannelBox8,multi.VTOLMotorW);
// 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.
channel = m_aircraft->multiMotorChannelBox1->currentIndex() - 1;
if (channel > -1)
{
value = getMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_PITCH);
m_aircraft->mrPitchMixLevel->setValue( qRound(value/1.27) );
value = getMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_YAW);
setYawMixLevel( -qRound(value/1.27) );
value = getMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_ROLL);
m_aircraft->mrRollMixLevel->setValue( qRound(value/1.27) );
}
}
else if (frameType == "Tri")
{
// Motors 1 to 8 are N / NE / E / etc
setComboCurrentIndex(m_aircraft->multiMotorChannelBox1,multi.VTOLMotorNW);
setComboCurrentIndex(m_aircraft->multiMotorChannelBox2,multi.VTOLMotorNE);
setComboCurrentIndex(m_aircraft->multiMotorChannelBox3,multi.VTOLMotorS);
setComboCurrentIndex(m_aircraft->multiMotorChannelBox4,multi.VTOLMotorS);
setComboCurrentIndex(m_aircraft->triYawChannelBox,multi.TRIYaw);
channel = m_aircraft->multiMotorChannelBox1->currentIndex() - 1;
if (channel > -1)
{
value = getMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_PITCH);
m_aircraft->mrPitchMixLevel->setValue( qRound(2*value/1.27) );
value = getMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_ROLL);
m_aircraft->mrRollMixLevel->setValue( qRound(value/1.27) );
}
} }
drawAirframe(frameType);
} }
void ConfigMultiRotorWidget::reverseMultirotorMotor(){
QString frameType = m_aircraft->multirotorFrameType->currentText();
updateAirframe(frameType);
}
void ConfigMultiRotorWidget::updateAirframe(QString frameType)
{
qDebug() << "ConfigMultiRotorWidget::updateAirframe - frame type" << frameType;
QString elementId;
if (frameType == "Tri" || frameType == "Tricopter Y") {
elementId = "tri";
} else if (frameType == "QuadX" || frameType == "Quad X") {
elementId = "quad-x";
} else if (frameType == "QuadP" || frameType == "Quad +") {
elementId = "quad-plus";
} else if (frameType == "Hexa" || frameType == "Hexacopter") {
elementId = "quad-hexa";
} else if (frameType == "HexaX" || frameType == "Hexacopter X") {
elementId = "quad-hexa-H";
} else if (frameType == "HexaCoax" || frameType == "Hexacopter Y6") {
elementId = "hexa-coax";
} else if (frameType == "Octo" || frameType == "Octocopter") {
elementId = "quad-octo";
} else if (frameType == "OctoV" || frameType == "Octocopter V") {
elementId = "quad-octo-v";
} else if (frameType == "OctoCoaxP" || frameType == "Octo Coax +") {
elementId = "octo-coax-P";
} else if (frameType == "OctoCoaxX" || frameType == "Octo Coax X") {
elementId = "octo-coax-X";
}
invertMotors = m_aircraft->MultirotorRevMixerCheckBox->isChecked();
if (invertMotors) {
elementId += "_reverse";
}
if (elementId != "" && elementId != quad->elementId()) {
quad->setElementId(elementId);
m_aircraft->quadShape->setSceneRect(quad->boundingRect());
m_aircraft->quadShape->fitInView(quad, Qt::KeepAspectRatio);
}
}
/** /**
Helper function: setupQuadMotor Helper function: setupQuadMotor
@ -832,54 +790,48 @@ void ConfigMultiRotorWidget::setupQuadMotor(int channel, double pitch, double ro
setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_THROTTLECURVE1, 127); setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_THROTTLECURVE1, 127);
setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_THROTTLECURVE2, 0); setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_THROTTLECURVE2, 0);
setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_ROLL, roll*127); setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_ROLL, roll * 127);
setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_PITCH, pitch*127); setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_PITCH, pitch * 127);
setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_YAW, yaw*127); setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_YAW, yaw * 127);
} }
/** /**
Helper function: setup motors. Takes a list of channel names in input. Helper function: setup motors. Takes a list of channel names in input.
*/ */
void ConfigMultiRotorWidget::setupMotors(QList<QString> motorList) void ConfigMultiRotorWidget::setupMotors(QList<QString> motorList)
{ {
QList<QComboBox*> mmList; QList<QComboBox*> mmList;
mmList << m_aircraft->multiMotorChannelBox1 << m_aircraft->multiMotorChannelBox2 << m_aircraft->multiMotorChannelBox3 mmList << m_aircraft->multiMotorChannelBox1 << m_aircraft->multiMotorChannelBox2
<< m_aircraft->multiMotorChannelBox4 << m_aircraft->multiMotorChannelBox5 << m_aircraft->multiMotorChannelBox6 << m_aircraft->multiMotorChannelBox3 << m_aircraft->multiMotorChannelBox4
<< m_aircraft->multiMotorChannelBox7 << m_aircraft->multiMotorChannelBox8; << m_aircraft->multiMotorChannelBox5 << m_aircraft->multiMotorChannelBox6
<< m_aircraft->multiMotorChannelBox7 << m_aircraft->multiMotorChannelBox8;
GUIConfigDataUnion configData = GetConfigData(); GUIConfigDataUnion configData = getConfigData();
ResetActuators(&configData); resetActuators(&configData);
int index;
foreach (QString motor, motorList) { foreach (QString motor, motorList) {
int index = mmList.takeFirst()->currentIndex();
index = mmList.takeFirst()->currentIndex(); if (motor == QString("VTOLMotorN")) {
if (motor == QString("VTOLMotorN"))
configData.multi.VTOLMotorN = index; configData.multi.VTOLMotorN = index;
else if (motor == QString("VTOLMotorNE")) } else if (motor == QString("VTOLMotorNE")) {
configData.multi.VTOLMotorNE = index; configData.multi.VTOLMotorNE = index;
else if (motor == QString("VTOLMotorE")) } else if (motor == QString("VTOLMotorE")) {
configData.multi.VTOLMotorE = index; configData.multi.VTOLMotorE = index;
else if (motor == QString("VTOLMotorSE")) } else if (motor == QString("VTOLMotorSE")) {
configData.multi.VTOLMotorSE = index; configData.multi.VTOLMotorSE = index;
else if (motor == QString( "VTOLMotorS")) } else if (motor == QString("VTOLMotorS")) {
configData.multi.VTOLMotorS = index; configData.multi.VTOLMotorS = index;
else if (motor == QString( "VTOLMotorSW")) } else if (motor == QString("VTOLMotorSW")) {
configData.multi.VTOLMotorSW = index; configData.multi.VTOLMotorSW = index;
else if (motor == QString( "VTOLMotorW")) } else if (motor == QString("VTOLMotorW")) {
configData.multi.VTOLMotorW = index; configData.multi.VTOLMotorW = index;
else if (motor == QString( "VTOLMotorNW")) } else if (motor == QString("VTOLMotorNW")) {
configData.multi.VTOLMotorNW = index; configData.multi.VTOLMotorNW = index;
}
} }
SetConfigData(configData); setConfigData(configData);
} }
/** /**
Set up a Quad-X or Quad-P mixer Set up a Quad-X or Quad-P mixer
*/ */
@ -887,19 +839,16 @@ bool ConfigMultiRotorWidget::setupQuad(bool pLayout)
{ {
// Check coherence: // Check coherence:
//Show any config errors in GUI // Show any config errors in GUI
if (throwConfigError(4)) { if (throwConfigError(4)) {
return false; return false;
} }
QList<QString> motorList; QList<QString> motorList;
if (pLayout) { if (pLayout) {
motorList << "VTOLMotorN" << "VTOLMotorE" << "VTOLMotorS" motorList << "VTOLMotorN" << "VTOLMotorE" << "VTOLMotorS" << "VTOLMotorW";
<< "VTOLMotorW";
} else { } else {
motorList << "VTOLMotorNW" << "VTOLMotorNE" << "VTOLMotorSE" motorList << "VTOLMotorNW" << "VTOLMotorNE" << "VTOLMotorSE" << "VTOLMotorSW";
<< "VTOLMotorSW";
} }
setupMotors(motorList); setupMotors(motorList);
@ -920,7 +869,7 @@ bool ConfigMultiRotorWidget::setupQuad(bool pLayout)
{ 0, 0, 0}, { 0, 0, 0},
{ 0, 0, 0} { 0, 0, 0}
}; };
//
// Motor 1 to 4, P Layout: // Motor 1 to 4, P Layout:
// pitch roll yaw // pitch roll yaw
// {1 ,0 ,-0.5 //Front motor (CW) // {1 ,0 ,-0.5 //Front motor (CW)
@ -947,25 +896,22 @@ bool ConfigMultiRotorWidget::setupQuad(bool pLayout)
return true; return true;
} }
/** /**
Set up a Hexa-X or Hexa-P mixer Set up a Hexa-X or Hexa-P mixer
*/ */
bool ConfigMultiRotorWidget::setupHexa(bool pLayout) bool ConfigMultiRotorWidget::setupHexa(bool pLayout)
{ {
// Check coherence: // Check coherence:
//Show any config errors in GUI // Show any config errors in GUI
if (throwConfigError(6)) if (throwConfigError(6)) {
return false; return false;
}
QList<QString> motorList; QList<QString> motorList;
if (pLayout) { if (pLayout) {
motorList << "VTOLMotorN" << "VTOLMotorNE" << "VTOLMotorSE" motorList << "VTOLMotorN" << "VTOLMotorNE" << "VTOLMotorSE" << "VTOLMotorS" << "VTOLMotorSW" << "VTOLMotorNW";
<< "VTOLMotorS" << "VTOLMotorSW" << "VTOLMotorNW";
} else { } else {
motorList << "VTOLMotorNE" << "VTOLMotorE" << "VTOLMotorSE" motorList << "VTOLMotorNE" << "VTOLMotorE" << "VTOLMotorSE" << "VTOLMotorSW" << "VTOLMotorW" << "VTOLMotorNW";
<< "VTOLMotorSW" << "VTOLMotorW" << "VTOLMotorNW";
} }
setupMotors(motorList); setupMotors(motorList);
@ -979,7 +925,6 @@ bool ConfigMultiRotorWidget::setupHexa(bool pLayout)
// 4 {-0.3 , 0 , 0.3 // S CCW // 4 {-0.3 , 0 , 0.3 // S CCW
// 5 {-0.3 , 0.5 ,-0.3 // SW CW // 5 {-0.3 , 0.5 ,-0.3 // SW CW
// 6 { 0.3 , 0.5 , 0.3 // NW CCW // 6 { 0.3 , 0.5 , 0.3 // NW CCW
double pMixer [8][3] = { double pMixer [8][3] = {
{ 1, 0, -1}, { 1, 0, -1},
{ 1, -1, 1}, { 1, -1, 1},
@ -991,7 +936,6 @@ bool ConfigMultiRotorWidget::setupHexa(bool pLayout)
{ 0, 0, 0} { 0, 0, 0}
}; };
//
// Motor 1 to 6, X Layout: // Motor 1 to 6, X Layout:
// 1 [ 0.5, -0.3, -0.3 ] NE // 1 [ 0.5, -0.3, -0.3 ] NE
// 2 [ 0 , -0.3, 0.3 ] E // 2 [ 0 , -0.3, 0.3 ] E
@ -1025,64 +969,82 @@ bool ConfigMultiRotorWidget::setupHexa(bool pLayout)
*/ */
bool ConfigMultiRotorWidget::setupMultiRotorMixer(double mixerFactors[8][3]) bool ConfigMultiRotorWidget::setupMultiRotorMixer(double mixerFactors[8][3])
{ {
QList<QComboBox*> mmList;
mmList << m_aircraft->multiMotorChannelBox1 << m_aircraft->multiMotorChannelBox2 << m_aircraft->multiMotorChannelBox3
<< m_aircraft->multiMotorChannelBox4 << m_aircraft->multiMotorChannelBox5 << m_aircraft->multiMotorChannelBox6
<< m_aircraft->multiMotorChannelBox7 << m_aircraft->multiMotorChannelBox8;
UAVDataObject* mixer = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings"))); UAVDataObject* mixer = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
Q_ASSERT(mixer); Q_ASSERT(mixer);
resetMotorAndServoMixers(mixer); resetMotorAndServoMixers(mixer);
// and enable only the relevant channels: // and enable only the relevant channels:
double pFactor = (double)m_aircraft->mrPitchMixLevel->value()/100; double pFactor = (double) m_aircraft->mrPitchMixLevel->value() / 100.0;
double rFactor = (double)m_aircraft->mrRollMixLevel->value()/100; double rFactor = (double) m_aircraft->mrRollMixLevel->value() / 100.0;
invertMotors = m_aircraft->MultirotorRevMixercheckBox->isChecked() ? -1:1; invertMotors = m_aircraft->MultirotorRevMixerCheckBox->isChecked();
double yFactor =invertMotors * (double)m_aircraft->mrYawMixLevel->value()/100; double yFactor = (invertMotors ? -1.0 : 1.0) * (double) m_aircraft->mrYawMixLevel->value() / 100.0;
for (int i=0 ; i<8; i++) {
if(mmList.at(i)->isEnabled()) QList<QComboBox*> mmList;
{ mmList << m_aircraft->multiMotorChannelBox1 << m_aircraft->multiMotorChannelBox2
int channel = mmList.at(i)->currentIndex()-1; << m_aircraft->multiMotorChannelBox3 << m_aircraft->multiMotorChannelBox4
if (channel > -1) << m_aircraft->multiMotorChannelBox5 << m_aircraft->multiMotorChannelBox6
setupQuadMotor(channel, mixerFactors[i][0]*pFactor, << m_aircraft->multiMotorChannelBox7 << m_aircraft->multiMotorChannelBox8;
rFactor*mixerFactors[i][1], yFactor*mixerFactors[i][2]); for (int i = 0; i < 8; i++) {
if (mmList.at(i)->isEnabled()) {
int channel = mmList.at(i)->currentIndex() - 1;
if (channel > -1) {
setupQuadMotor(channel, mixerFactors[i][0] * pFactor, rFactor * mixerFactors[i][1],
yFactor * mixerFactors[i][2]);
}
} }
} }
return true; return true;
} }
/** /**
This function displays text and color formatting in order to help the user understand what channels have not yet been configured. This function displays text and color formatting in order to help the user understand what channels have not yet been configured.
*/ */
bool ConfigMultiRotorWidget::throwConfigError(int numMotors) bool ConfigMultiRotorWidget::throwConfigError(int numMotors)
{ {
//Initialize configuration error flag // Initialize configuration error flag
bool error=false; bool error = false;
//Iterate through all instances of multiMotorChannelBox // Iterate through all instances of multiMotorChannelBox
for (int i=0; i<numMotors; i++) { for (int i = 0; i < numMotors; i++) {
//Fine widgets with text "multiMotorChannelBox.x", where x is an integer //Fine widgets with text "multiMotorChannelBox.x", where x is an integer
QComboBox *combobox = qFindChild<QComboBox*>(uiowner, "multiMotorChannelBox" + QString::number(i+1)); QComboBox *combobox = qFindChild<QComboBox*>(this, "multiMotorChannelBox" + QString::number(i + 1));
if (combobox){ if (combobox) {
if (combobox->currentText() == "None") { if (combobox->currentText() == "None") {
int size = combobox->style()->pixelMetric(QStyle::PM_SmallIconSize); int size = combobox->style()->pixelMetric(QStyle::PM_SmallIconSize);
QPixmap pixmap(size,size); QPixmap pixmap(size, size);
pixmap.fill(QColor("red")); pixmap.fill(QColor("red"));
combobox->setItemData(0, pixmap, Qt::DecorationRole);//Set color palettes combobox->setItemData(0, pixmap, Qt::DecorationRole); //Set color palettes
error=true; error = true;
} } else {
else { combobox->setItemData(0, 0, Qt::DecorationRole); //Reset color palettes
combobox->setItemData(0, 0, Qt::DecorationRole);//Reset color palettes
} }
} }
} }
if (error) {
if (error){ m_aircraft->mrStatusLabel->setText(
m_aircraft->mrStatusLabel->setText(QString("<font color='red'>ERROR: Assign all %1 motor channels</font>").arg(numMotors)); QString("<font color='red'>ERROR: Assign all %1 motor channels</font>").arg(numMotors));
} }
return error; return error;
} }
/**
WHAT DOES THIS DO???
*/
void ConfigMultiRotorWidget::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);
}
/**
Resize the GUI contents when the user changes the window size
*/
void ConfigMultiRotorWidget::resizeEvent(QResizeEvent *event)
{
Q_UNUSED(event);
m_aircraft->quadShape->fitInView(quad, Qt::KeepAspectRatio);
}

View File

@ -27,17 +27,17 @@
#ifndef CONFIGMULTIROTORWIDGET_H #ifndef CONFIGMULTIROTORWIDGET_H
#define CONFIGMULTIROTORWIDGET_H #define CONFIGMULTIROTORWIDGET_H
#include "ui_airframe.h"
#include "../uavobjectwidgetutils/configtaskwidget.h"
#include "cfg_vehicletypes/vehicleconfig.h" #include "cfg_vehicletypes/vehicleconfig.h"
#include "ui_airframe_multirotor.h"
#include "../uavobjectwidgetutils/configtaskwidget.h"
#include "extensionsystem/pluginmanager.h" #include "extensionsystem/pluginmanager.h"
#include "uavobjectmanager.h" #include "uavobjectmanager.h"
#include "uavobject.h" #include "uavobject.h"
#include "uavtalk/telemetrymanager.h" #include "uavtalk/telemetrymanager.h"
#include <QtCore/QList>
#include <QtGui/QWidget> #include <QtGui/QWidget>
#include <QList> #include <QtGui/QItemDelegate>
#include <QItemDelegate>
class Ui_Widget; class Ui_Widget;
@ -46,16 +46,26 @@ class ConfigMultiRotorWidget: public VehicleConfig
Q_OBJECT Q_OBJECT
public: public:
ConfigMultiRotorWidget(Ui_AircraftWidget *aircraft = 0, QWidget *parent = 0); static const QString CHANNELBOXNAME;
static QStringList getChannelDescriptions();
ConfigMultiRotorWidget(QWidget *parent = 0);
~ConfigMultiRotorWidget(); ~ConfigMultiRotorWidget();
friend class ConfigVehicleTypeWidget; virtual void refreshWidgetsValues(QString frameType);
virtual QString updateConfigObjectsFromWidgets();
protected:
void showEvent(QShowEvent *event);
void resizeEvent(QResizeEvent *event);
private: private:
Ui_AircraftWidget *m_aircraft; Ui_MultiRotorConfigWidget *m_aircraft;
QWidget *uiowner;
QGraphicsSvgItem *quad; QGraphicsSvgItem *quad;
bool invertMotors;
virtual void registerWidgets(ConfigTaskWidget &parent);
virtual void resetActuators(GUIConfigDataUnion *configData);
bool setupQuad(bool pLayout); bool setupQuad(bool pLayout);
bool setupHexa(bool pLayout); bool setupHexa(bool pLayout);
@ -64,28 +74,15 @@ private:
void setupMotors(QList<QString> motorList); void setupMotors(QList<QString> motorList);
void setupQuadMotor(int channel, double roll, double pitch, double yaw); void setupQuadMotor(int channel, double roll, double pitch, double yaw);
float invertMotors;
virtual void ResetActuators(GUIConfigDataUnion* configData);
static QStringList getChannelDescriptions();
static const QString CHANNELBOXNAME;
void setYawMixLevel(int); void setYawMixLevel(int);
void drawAirframe(QString multiRotorType); void updateAirframe(QString multiRotorType);
private slots: private slots:
virtual void setupUI(QString airframeType); virtual void setupUI(QString airframeType);
virtual void refreshWidgetsValues(QString frameType);
virtual QString updateConfigObjectsFromWidgets();
virtual bool throwConfigError(int numMotors); virtual bool throwConfigError(int numMotors);
void reverseMultirotorMotor();
protected:
signals:
void configurationChanged();
}; };
#endif // CONFIGMULTIROTORWIDGET_H #endif // CONFIGMULTIROTORWIDGET_H

View File

@ -29,29 +29,27 @@
#include "extensionsystem/pluginmanager.h" #include "extensionsystem/pluginmanager.h"
#include "uavobjectmanager.h" #include "uavobjectmanager.h"
#include "uavobject.h" #include "uavobject.h"
#include "systemsettings.h" #include "systemsettings.h"
#include <QDebug> #include <QDebug>
VehicleConfig::VehicleConfig(QWidget *parent) : ConfigTaskWidget(parent) VehicleConfig::VehicleConfig(QWidget *parent) : ConfigTaskWidget(parent)
{ {
//Generate lists of mixerTypeNames, mixerVectorNames, channelNames // Generate lists of mixerTypeNames, mixerVectorNames, channelNames
channelNames << "None"; channelNames << "None";
for (int i = 0; i < (int)(VehicleConfig::CHANNEL_NUMELEM); i++) { for (int i = 0; i < (int) VehicleConfig::CHANNEL_NUMELEM; i++) {
mixerTypes << QString("Mixer%1Type").arg(i+1); mixerTypes << QString("Mixer%1Type").arg(i + 1);
mixerVectors << QString("Mixer%1Vector").arg(i+1); mixerVectors << QString("Mixer%1Vector").arg(i + 1);
channelNames << QString("Channel%1").arg(i+1); channelNames << QString("Channel%1").arg(i + 1);
} }
mixerTypeDescriptions << "Disabled" << "Motor" << "Servo" << "CameraRoll" << "CameraPitch" mixerTypeDescriptions << "Disabled" << "Motor" << "Servo" << "CameraRoll" << "CameraPitch" << "CameraYaw"
<< "CameraYaw" << "Accessory0" << "Accessory1" << "Accessory2" << "Accessory0" << "Accessory1" << "Accessory2" << "Accessory3" << "Accessory4" << "Accessory5";
<< "Accessory3" << "Accessory4" << "Accessory5";
// This is needed because new style tries to compact things as much as possible in grid // This is needed because new style tries to compact things as much as possible in grid
// and on OSX the widget sizes of PushButtons is reported incorrectly: // and on OSX the widget sizes of PushButtons is reported incorrectly:
// https://bugreports.qt-project.org/browse/QTBUG-14591 // https://bugreports.qt-project.org/browse/QTBUG-14591
foreach( QPushButton * btn, findChildren<QPushButton*>() ) { foreach(QPushButton *btn, findChildren<QPushButton*>()) {
btn->setAttribute(Qt::WA_LayoutUsesWidgetRect); btn->setAttribute(Qt::WA_LayoutUsesWidgetRect);
} }
} }
@ -61,52 +59,91 @@ VehicleConfig::~VehicleConfig()
// Do nothing // Do nothing
} }
GUIConfigDataUnion VehicleConfig::GetConfigData() { GUIConfigDataUnion VehicleConfig::getConfigData()
{
int i;
GUIConfigDataUnion configData;
// get an instance of systemsettings // get an instance of systemsettings
SystemSettings * systemSettings = SystemSettings::GetInstance(getUAVObjectManager()); SystemSettings *systemSettings = SystemSettings::GetInstance(getUAVObjectManager());
Q_ASSERT(systemSettings); Q_ASSERT(systemSettings);
SystemSettings::DataFields systemSettingsData = systemSettings->getData(); SystemSettings::DataFields systemSettingsData = systemSettings->getData();
// copy systemsettings -> local configData // copy systemsettings -> local configData
for(i = 0; i < (int)(SystemSettings::GUICONFIGDATA_NUMELEM); i++) GUIConfigDataUnion configData;
configData.UAVObject[i]=systemSettingsData.GUIConfigData[i]; for (int i = 0; i < (int) SystemSettings::GUICONFIGDATA_NUMELEM; i++) {
configData.UAVObject[i] = systemSettingsData.GUIConfigData[i];
}
// sanity check // sanity check
Q_ASSERT(SystemSettings::GUICONFIGDATA_NUMELEM == Q_ASSERT(SystemSettings::GUICONFIGDATA_NUMELEM == (sizeof(configData.UAVObject) / sizeof(configData.UAVObject[0])));
(sizeof(configData.UAVObject) / sizeof(configData.UAVObject[0])));
return configData; return configData;
} }
void VehicleConfig::SetConfigData(GUIConfigDataUnion configData) { void VehicleConfig::setConfigData(GUIConfigDataUnion configData)
{
int i;
// sanity check // sanity check
Q_ASSERT(SystemSettings::GUICONFIGDATA_NUMELEM == Q_ASSERT(SystemSettings::GUICONFIGDATA_NUMELEM == (sizeof(configData.UAVObject) / sizeof(configData.UAVObject[0])));
(sizeof(configData.UAVObject) / sizeof(configData.UAVObject[0])));
// get an instance of systemsettings // get an instance of systemsettings
SystemSettings * systemSettings = SystemSettings::GetInstance(getUAVObjectManager()); SystemSettings *systemSettings = SystemSettings::GetInstance(getUAVObjectManager());
Q_ASSERT(systemSettings); Q_ASSERT(systemSettings);
SystemSettings::DataFields systemSettingsData = systemSettings->getData(); SystemSettings::DataFields systemSettingsData = systemSettings->getData();
UAVObjectField* guiConfig = systemSettings->getField("GUIConfigData"); UAVObjectField *guiConfig = systemSettings->getField("GUIConfigData");
Q_ASSERT(guiConfig); Q_ASSERT(guiConfig);
if(!guiConfig) if (!guiConfig) {
return; return;
}
// copy parameter configData -> systemsettings // copy parameter configData -> systemsettings
for (i = 0; i < (int)(SystemSettings::GUICONFIGDATA_NUMELEM); i++) for (int i = 0; i < (int) SystemSettings::GUICONFIGDATA_NUMELEM; i++) {
guiConfig->setValue(configData.UAVObject[i], i); guiConfig->setValue(configData.UAVObject[i], i);
}
} }
void VehicleConfig::ResetActuators(GUIConfigDataUnion* configData) void VehicleConfig::setupUI(QString frameType)
{ {
Q_UNUSED(frameType);
}
void VehicleConfig::refreshWidgetsValues(QString frameType)
{
Q_UNUSED(frameType);
}
QString VehicleConfig::updateConfigObjectsFromWidgets()
{
return NULL;
}
void VehicleConfig::refreshWidgetsValues(UAVObject *o)
{
Q_UNUSED(o);
}
void VehicleConfig::updateObjectsFromWidgets()
{
}
void VehicleConfig::resetActuators(GUIConfigDataUnion *configData)
{
Q_UNUSED(configData);
}
void VehicleConfig::registerWidgets(ConfigTaskWidget &parent) {
Q_UNUSED(parent);
}
// NEW STYLE: Loop through the widgets looking for all widgets that have "ChannelBox" in their name
// The upshot of this is that ALL new ComboBox widgets for selecting the output channel must have "ChannelBox" in their name
// FOR WHATEVER REASON, THIS DOES NOT WORK WITH ChannelBox. ChannelBo is sufficiently accurate
void VehicleConfig::populateChannelComboBoxes()
{
QList<QComboBox *> l = findChildren<QComboBox *>(QRegExp("\\S+ChannelBo\\S+"));
foreach(QComboBox *combobox, l) {
combobox->addItems(channelNames);
}
} }
/** /**
@ -114,44 +151,48 @@ void VehicleConfig::ResetActuators(GUIConfigDataUnion* configData)
Sets the current index on supplied combobox to index Sets the current index on supplied combobox to index
if it is within bounds 0 <= index < combobox.count() if it is within bounds 0 <= index < combobox.count()
*/ */
void VehicleConfig::setComboCurrentIndex(QComboBox* box, int index) void VehicleConfig::setComboCurrentIndex(QComboBox *box, int index)
{ {
Q_ASSERT(box); Q_ASSERT(box);
if (index >= 0 && index < box->count()) {
if (index >= 0 && index < box->count())
box->setCurrentIndex(index); box->setCurrentIndex(index);
}
} }
/** /**
Helper function: Helper function:
enables/disables the named comboboxes within supplied uiowner enables/disables the named comboboxes within supplied owner
*/ */
void VehicleConfig::enableComboBoxes(QWidget* owner, QString boxName, int boxCount, bool enable) void VehicleConfig::enableComboBoxes(QWidget *owner, QString boxName, int boxCount, bool enable)
{ {
for (int i = 1; i <= boxCount; i++) { for (int i = 1; i <= boxCount; i++) {
QComboBox* box = qFindChild<QComboBox*>(owner, QString("%0%1").arg(boxName).arg(i)); QComboBox* box = qFindChild<QComboBox*>(owner, QString("%0%1").arg(boxName).arg(i));
if (box) if (box) {
box->setEnabled(enable); box->setEnabled(enable);
}
} }
} }
QString VehicleConfig::getMixerType(UAVDataObject* mixer, int channel)
QString VehicleConfig::getMixerType(UAVDataObject *mixer, int channel)
{ {
Q_ASSERT(mixer); Q_ASSERT(mixer);
QString mixerType = mixerTypeDescriptions[0]; //default to disabled // default to disabled
QString mixerType = mixerTypeDescriptions[0];
if (channel >= 0 && channel < mixerTypes.count()) { if (channel >= 0 && channel < mixerTypes.count()) {
UAVObjectField *field = mixer->getField(mixerTypes.at(channel)); UAVObjectField *field = mixer->getField(mixerTypes.at(channel));
Q_ASSERT(field); Q_ASSERT(field);
if (field) if (field) {
mixerType = field->getValue().toString(); mixerType = field->getValue().toString();
}
} }
return mixerType; return mixerType;
} }
void VehicleConfig::setMixerType(UAVDataObject* mixer, int channel, MixerTypeElem mixerType) void VehicleConfig::setMixerType(UAVDataObject *mixer, int channel, MixerTypeElem mixerType)
{ {
Q_ASSERT(mixer); Q_ASSERT(mixer);
@ -160,15 +201,14 @@ void VehicleConfig::setMixerType(UAVDataObject* mixer, int channel, MixerTypeEle
Q_ASSERT(field); Q_ASSERT(field);
if (field) { if (field) {
if (mixerType >= 0 && mixerType < mixerTypeDescriptions.count()) if (mixerType >= 0 && mixerType < mixerTypeDescriptions.count()) {
{
field->setValue(mixerTypeDescriptions[mixerType]); field->setValue(mixerTypeDescriptions[mixerType]);
} }
} }
} }
} }
void VehicleConfig::resetMixerVector(UAVDataObject* mixer, int channel) void VehicleConfig::resetMixerVector(UAVDataObject *mixer, int channel)
{ {
Q_ASSERT(mixer); Q_ASSERT(mixer);
@ -184,7 +224,7 @@ void VehicleConfig::resetMixerVector(UAVDataObject* mixer, int channel)
// Disable all servo/motor mixers (but keep camera and accessory ones) // Disable all servo/motor mixers (but keep camera and accessory ones)
void VehicleConfig::resetMotorAndServoMixers(UAVDataObject *mixer) void VehicleConfig::resetMotorAndServoMixers(UAVDataObject *mixer)
{ {
for (int channel = 0; channel < (int)VehicleConfig::CHANNEL_NUMELEM; channel++) { for (int channel = 0; channel < (int) VehicleConfig::CHANNEL_NUMELEM; channel++) {
QString type = getMixerType(mixer, channel); QString type = getMixerType(mixer, channel);
if ((type == "Disabled") || (type == "Motor") || (type == "Servo")) { if ((type == "Disabled") || (type == "Motor") || (type == "Servo")) {
setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_DISABLED); setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_DISABLED);
@ -193,12 +233,10 @@ void VehicleConfig::resetMotorAndServoMixers(UAVDataObject *mixer)
} }
} }
double VehicleConfig::getMixerVectorValue(UAVDataObject* mixer, int channel, MixerVectorElem elementName) double VehicleConfig::getMixerVectorValue(UAVDataObject *mixer, int channel, MixerVectorElem elementName)
{ {
Q_ASSERT(mixer); Q_ASSERT(mixer);
double value = 0; double value = 0;
if (channel >= 0 && channel < mixerVectors.count()) { if (channel >= 0 && channel < mixerVectors.count()) {
UAVObjectField *field = mixer->getField(mixerVectors.at(channel)); UAVObjectField *field = mixer->getField(mixerVectors.at(channel));
Q_ASSERT(field); Q_ASSERT(field);
@ -210,7 +248,7 @@ double VehicleConfig::getMixerVectorValue(UAVDataObject* mixer, int channel, Mix
return value; return value;
} }
void VehicleConfig::setMixerVectorValue(UAVDataObject* mixer, int channel, MixerVectorElem elementName, double value) void VehicleConfig::setMixerVectorValue(UAVDataObject *mixer, int channel, MixerVectorElem elementName, double value)
{ {
Q_ASSERT(mixer); Q_ASSERT(mixer);
@ -224,7 +262,7 @@ void VehicleConfig::setMixerVectorValue(UAVDataObject* mixer, int channel, Mixer
} }
} }
double VehicleConfig::getMixerValue(UAVDataObject* mixer, QString elementName) double VehicleConfig::getMixerValue(UAVDataObject *mixer, QString elementName)
{ {
Q_ASSERT(mixer); Q_ASSERT(mixer);
@ -237,7 +275,7 @@ double VehicleConfig::getMixerValue(UAVDataObject* mixer, QString elementName)
return value; return value;
} }
void VehicleConfig::setMixerValue(UAVDataObject* mixer, QString elementName, double value) void VehicleConfig::setMixerValue(UAVDataObject *mixer, QString elementName, double value)
{ {
Q_ASSERT(mixer); Q_ASSERT(mixer);
@ -247,67 +285,56 @@ void VehicleConfig::setMixerValue(UAVDataObject* mixer, QString elementName, dou
} }
} }
void VehicleConfig::setThrottleCurve(UAVDataObject *mixer, MixerThrottleCurveElem curveType, QList<double> curve)
void VehicleConfig::setThrottleCurve(UAVDataObject* mixer, MixerThrottleCurveElem curveType, QList<double> curve)
{ {
QPointer<UAVObjectField> field; QPointer<UAVObjectField> field;
switch (curveType) switch (curveType) {
{ case MIXER_THROTTLECURVE1:
case MIXER_THROTTLECURVE1: field = mixer->getField("ThrottleCurve1");
{ break;
field = mixer->getField("ThrottleCurve1"); case MIXER_THROTTLECURVE2:
break; field = mixer->getField("ThrottleCurve2");
} break;
case MIXER_THROTTLECURVE2:
{
field = mixer->getField("ThrottleCurve2");
break;
}
} }
if (field && field->getNumElements() == curve.length()) { if (field && (field->getNumElements() == (unsigned int) curve.length())) {
for (int i=0;i<curve.length();i++) { for (int i = 0; i < curve.length(); i++) {
field->setValue(curve.at(i),i); field->setValue(curve.at(i), i);
} }
} }
} }
void VehicleConfig::getThrottleCurve(UAVDataObject* mixer, MixerThrottleCurveElem curveType, QList<double>* curve) void VehicleConfig::getThrottleCurve(UAVDataObject *mixer, MixerThrottleCurveElem curveType, QList<double> *curve)
{ {
Q_ASSERT(mixer); Q_ASSERT(mixer);
Q_ASSERT(curve); Q_ASSERT(curve);
QPointer<UAVObjectField> field; QPointer<UAVObjectField> field;
switch (curveType) switch (curveType) {
{ case MIXER_THROTTLECURVE1:
case MIXER_THROTTLECURVE1: field = mixer->getField("ThrottleCurve1");
{ break;
field = mixer->getField("ThrottleCurve1"); case MIXER_THROTTLECURVE2:
break; field = mixer->getField("ThrottleCurve2");
} break;
case MIXER_THROTTLECURVE2:
{
field = mixer->getField("ThrottleCurve2");
break;
}
} }
if (field) { if (field) {
curve->clear(); curve->clear();
for (unsigned int i=0; i < field->getNumElements(); i++) { for (unsigned int i = 0; i < field->getNumElements(); i++) {
curve->append(field->getValue(i).toDouble()); curve->append(field->getValue(i).toDouble());
} }
} }
} }
bool VehicleConfig::isValidThrottleCurve(QList<double>* curve) bool VehicleConfig::isValidThrottleCurve(QList<double> *curve)
{ {
Q_ASSERT(curve); Q_ASSERT(curve);
if (curve) { if (curve) {
for (int i=0; i < curve->count(); i++) { for (int i = 0; i < curve->count(); i++) {
if (curve->at(i) != 0) if (curve->at(i) != 0)
return true; return true;
} }
@ -315,41 +342,44 @@ bool VehicleConfig::isValidThrottleCurve(QList<double>* curve)
return false; return false;
} }
double VehicleConfig::getCurveMin(QList<double>* curve) double VehicleConfig::getCurveMin(QList<double> *curve)
{ {
// TODO initialize to max double
double min = 0; double min = 0;
for (int i=0; i<curve->count(); i++) for (int i = 0; i < curve->count(); i++) {
min = std::min(min, curve->at(i)); min = std::min(min, curve->at(i));
}
return min; return min;
} }
double VehicleConfig::getCurveMax(QList<double>* curve) double VehicleConfig::getCurveMax(QList<double> *curve)
{ {
// TODO initialize to min double
double max = 0; double max = 0;
for (int i=0; i<curve->count(); i++) for (int i = 0; i < curve->count(); i++) {
max = std::max(max, curve->at(i)); max = std::max(max, curve->at(i));
}
return max; return max;
} }
/** /**
Reset the contents of a field Reset the contents of a field
*/ */
void VehicleConfig::resetField(UAVObjectField * field) void VehicleConfig::resetField(UAVObjectField * field)
{ {
for (unsigned int i=0;i<field->getNumElements();i++) { for (unsigned int i = 0; i < field->getNumElements(); i++) {
field->setValue(0,i); field->setValue(0, i);
} }
} }
/** /**
* Util function to get a pointer to the object manager * Util function to get a pointer to the object manager
* @return pointer to the UAVObjectManager * @return pointer to the UAVObjectManager
*/ */
UAVObjectManager* VehicleConfig::getUAVObjectManager() { UAVObjectManager *VehicleConfig::getUAVObjectManager()
{
ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance(); ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance();
UAVObjectManager * objMngr = pm->getObject<UAVObjectManager>(); UAVObjectManager *objMngr = pm->getObject<UAVObjectManager>();
Q_ASSERT(objMngr); Q_ASSERT(objMngr);
return objMngr; return objMngr;
} }

View File

@ -24,8 +24,8 @@
* with this program; if not, write to the Free Software Foundation, Inc., * with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/ */
#ifndef GUIVEHICLECONFIG_H #ifndef VEHICLECONFIG_H
#define GUIVEHICLECONFIG_H #define VEHICLECONFIG_H
#include "../uavobjectwidgetutils/configtaskwidget.h" #include "../uavobjectwidgetutils/configtaskwidget.h"
#include "extensionsystem/pluginmanager.h" #include "extensionsystem/pluginmanager.h"
@ -33,7 +33,6 @@
#include "uavobject.h" #include "uavobject.h"
#include "actuatorcommand.h" #include "actuatorcommand.h"
typedef struct { typedef struct {
uint VTOLMotorN:4; uint VTOLMotorN:4;
uint VTOLMotorS:4; uint VTOLMotorS:4;
@ -42,11 +41,11 @@ typedef struct {
uint VTOLMotorNW:4; uint VTOLMotorNW:4;
uint VTOLMotorNE:4; uint VTOLMotorNE:4;
uint VTOLMotorSW:4; uint VTOLMotorSW:4;
uint VTOLMotorSE:4; //32bits uint VTOLMotorSE:4; // 32 bits
uint TRIYaw:4; uint TRIYaw:4;
quint32 padding:28; //64bits quint32 padding:28; // 64 bits
quint32 padding1; quint32 padding1;
quint32 padding2; //128bits quint32 padding2; // 128 bits
} __attribute__((packed)) multiGUISettingsStruct; } __attribute__((packed)) multiGUISettingsStruct;
typedef struct { typedef struct {
@ -58,15 +57,15 @@ typedef struct {
uint ccpmLinkRollState:1; uint ccpmLinkRollState:1;
uint SliderValue0:7; uint SliderValue0:7;
uint SliderValue1:7; uint SliderValue1:7;
uint SliderValue2:7;//41bits uint SliderValue2:7; // 41 bits
uint ServoIndexW:4; uint ServoIndexW:4;
uint ServoIndexX:4; uint ServoIndexX:4;
uint ServoIndexY:4; uint ServoIndexY:4;
uint ServoIndexZ:4;//57bits uint ServoIndexZ:4; // 57 bits
uint Throttle:4; uint Throttle:4;
uint Tail:4; //65bits uint Tail:4; // 65bits
quint32 padding:31; //96bits quint32 padding:31; // 96 bits
quint32 padding1; //128bits quint32 padding1; // 128 bits
} __attribute__((packed)) heliGUISettingsStruct; } __attribute__((packed)) heliGUISettingsStruct;
typedef struct { typedef struct {
@ -77,10 +76,10 @@ typedef struct {
uint FixedWingPitch2:4; uint FixedWingPitch2:4;
uint FixedWingYaw1:4; uint FixedWingYaw1:4;
uint FixedWingYaw2:4; uint FixedWingYaw2:4;
uint padding:4; //32bits uint padding:4; // 32 bits
quint32 padding1; quint32 padding1;
quint32 padding2; quint32 padding2;
quint32 padding3; //128bits quint32 padding3; // 128 bits
} __attribute__((packed)) fixedGUISettingsStruct; } __attribute__((packed)) fixedGUISettingsStruct;
typedef struct { typedef struct {
@ -88,78 +87,119 @@ typedef struct {
uint GroundVehicleThrottle2:4; uint GroundVehicleThrottle2:4;
uint GroundVehicleSteering1:4; uint GroundVehicleSteering1:4;
uint GroundVehicleSteering2:4; uint GroundVehicleSteering2:4;
uint padding:16; //32bits uint padding:16; // 32 bits
quint32 padding1; quint32 padding1;
quint32 padding2; quint32 padding2;
quint32 padding3; //128bits quint32 padding3; // 128 bits
} __attribute__((packed)) groundGUISettingsStruct; } __attribute__((packed)) groundGUISettingsStruct;
typedef union typedef union
{ {
uint UAVObject[4]; //32bits * 4 uint UAVObject[4]; // 32 bits * 4
heliGUISettingsStruct heli; //128bits heliGUISettingsStruct heli; // 128 bits
fixedGUISettingsStruct fixedwing; fixedGUISettingsStruct fixedwing;
multiGUISettingsStruct multi; multiGUISettingsStruct multi;
groundGUISettingsStruct ground; groundGUISettingsStruct ground;
} GUIConfigDataUnion; } GUIConfigDataUnion;
class ConfigTaskWidget;
/*
* This class handles vehicle specific configuration UI and associated logic.
*
* This class derives from ConfigTaskWidget and overrides its the default "binding" mechanism.
* It does not use the "dirty" state management directlyand registers its relevant widgets with ConfigTaskWidget to do so.
*/
class VehicleConfig: public ConfigTaskWidget class VehicleConfig: public ConfigTaskWidget
{ {
Q_OBJECT Q_OBJECT
public: public:
VehicleConfig(QWidget *parent = 0);
~VehicleConfig();
/* Enumeration options for ThrottleCurves */ /* Enumeration options for ThrottleCurves */
typedef enum { MIXER_THROTTLECURVE1=0, MIXER_THROTTLECURVE2=1 } MixerThrottleCurveElem; typedef enum {
MIXER_THROTTLECURVE1 = 0, MIXER_THROTTLECURVE2 = 1
} MixerThrottleCurveElem;
/* Enumeration options for field MixerType */ /* Enumeration options for field MixerType */
typedef enum { MIXERTYPE_DISABLED=0, MIXERTYPE_MOTOR=1, MIXERTYPE_SERVO=2, MIXERTYPE_CAMERAROLL=3, MIXERTYPE_CAMERAPITCH=4, MIXERTYPE_CAMERAYAW=5, MIXERTYPE_ACCESSORY0=6, MIXERTYPE_ACCESSORY1=7, MIXERTYPE_ACCESSORY2=8, MIXERTYPE_ACCESSORY3=9, MIXERTYPE_ACCESSORY4=10, MIXERTYPE_ACCESSORY5=11 } MixerTypeElem; typedef enum {
/* Array element names for field MixerVector */ MIXERTYPE_DISABLED = 0,
typedef enum { MIXERVECTOR_THROTTLECURVE1=0, MIXERVECTOR_THROTTLECURVE2=1, MIXERVECTOR_ROLL=2, MIXERVECTOR_PITCH=3, MIXERVECTOR_YAW=4 } MixerVectorElem; MIXERTYPE_MOTOR = 1,
MIXERTYPE_SERVO = 2,
MIXERTYPE_CAMERAROLL = 3,
MIXERTYPE_CAMERAPITCH = 4,
MIXERTYPE_CAMERAYAW = 5,
MIXERTYPE_ACCESSORY0 = 6,
MIXERTYPE_ACCESSORY1 = 7,
MIXERTYPE_ACCESSORY2 = 8,
MIXERTYPE_ACCESSORY3 = 9,
MIXERTYPE_ACCESSORY4 = 10,
MIXERTYPE_ACCESSORY5 = 11
} MixerTypeElem;
static GUIConfigDataUnion GetConfigData(); /* Array element names for field MixerVector */
static void SetConfigData(GUIConfigDataUnion configData); typedef enum {
static void resetField(UAVObjectField * field); MIXERVECTOR_THROTTLECURVE1 = 0,
static void setComboCurrentIndex(QComboBox* box, int index); MIXERVECTOR_THROTTLECURVE2 = 1,
static void enableComboBoxes(QWidget* owner, QString boxName, int boxCount, bool enable); MIXERVECTOR_ROLL = 2,
double getMixerVectorValue(UAVDataObject* mixer, int channel, MixerVectorElem elementName); MIXERVECTOR_PITCH = 3,
void setMixerVectorValue(UAVDataObject* mixer, int channel, MixerVectorElem elementName, double value); MIXERVECTOR_YAW = 4
void resetMixerVector(UAVDataObject* mixer, int channel); } MixerVectorElem;
void resetMotorAndServoMixers(UAVDataObject* mixer);
QString getMixerType(UAVDataObject* mixer, int channel);
void setMixerType(UAVDataObject* mixer, int channel, MixerTypeElem mixerType);
double getMixerValue(UAVDataObject* mixer, QString elementName);
void setMixerValue(UAVDataObject* mixer, QString elementName, double value);
void setThrottleCurve(UAVDataObject* mixer, MixerThrottleCurveElem curveType, QList<double> curve);
void getThrottleCurve(UAVDataObject* mixer, MixerThrottleCurveElem curveType, QList<double>* curve);
bool isValidThrottleCurve(QList<double>* curve);
double getCurveMin(QList<double>* curve);
double getCurveMax(QList<double>* curve);
virtual void ResetActuators(GUIConfigDataUnion* configData);
QStringList channelNames; static const quint32 CHANNEL_NUMELEM = ActuatorCommand::CHANNEL_NUMELEM;;
QStringList mixerTypes;
QStringList mixerVectors;
QStringList mixerTypeDescriptions;
static const quint32 CHANNEL_NUMELEM = ActuatorCommand::CHANNEL_NUMELEM; static GUIConfigDataUnion getConfigData();
static void setConfigData(GUIConfigDataUnion configData);
private: static void resetField(UAVObjectField *field);
static UAVObjectManager* getUAVObjectManager(); static void setComboCurrentIndex(QComboBox *box, int index);
static void enableComboBoxes(QWidget *owner, QString boxName, int boxCount, bool enable);
private slots: // VehicleConfig class
VehicleConfig(QWidget *parent = 0);
~VehicleConfig();
public slots: virtual void registerWidgets(ConfigTaskWidget &parent);
signals: virtual void refreshWidgetsValues(QString frameType);
//void ConfigurationChanged(); virtual QString updateConfigObjectsFromWidgets();
double getMixerValue(UAVDataObject *mixer, QString elementName);
void setMixerValue(UAVDataObject *mixer, QString elementName, double value);
protected: protected:
QStringList channelNames;
QStringList mixerTypes;
QStringList mixerVectors;
QStringList mixerTypeDescriptions;
void populateChannelComboBoxes();
double getMixerVectorValue(UAVDataObject *mixer, int channel, MixerVectorElem elementName);
void setMixerVectorValue(UAVDataObject *mixer, int channel, MixerVectorElem elementName, double value);
void resetMixerVector(UAVDataObject *mixer, int channel);
void resetMotorAndServoMixers(UAVDataObject *mixer);
QString getMixerType(UAVDataObject *mixer, int channel);
void setMixerType(UAVDataObject *mixer, int channel, MixerTypeElem mixerType);
void setThrottleCurve(UAVDataObject *mixer, MixerThrottleCurveElem curveType, QList<double> curve);
void getThrottleCurve(UAVDataObject *mixer, MixerThrottleCurveElem curveType, QList<double>* curve);
bool isValidThrottleCurve(QList<double> *curve);
double getCurveMin(QList<double> *curve);
double getCurveMax(QList<double> *curve);
protected slots:
virtual void refreshWidgetsValues(UAVObject *o = NULL);
virtual void updateObjectsFromWidgets();
private:
static UAVObjectManager *getUAVObjectManager();
virtual void resetActuators(GUIConfigDataUnion *configData);
private slots:
virtual void setupUI(QString airframeType);
}; };
#endif // GUIVEHICLECONFIG_H #endif // VEHICLECONFIG_H

View File

@ -18,7 +18,6 @@ HEADERS += configplugin.h \
config_cc_hw_widget.h \ config_cc_hw_widget.h \
configccattitudewidget.h \ configccattitudewidget.h \
configpipxtremewidget.h \ configpipxtremewidget.h \
cfg_vehicletypes/configccpmwidget.h \
configstabilizationwidget.h \ configstabilizationwidget.h \
assertions.h \ assertions.h \
calibration.h \ calibration.h \
@ -28,10 +27,12 @@ HEADERS += configplugin.h \
configcamerastabilizationwidget.h \ configcamerastabilizationwidget.h \
configtxpidwidget.h \ configtxpidwidget.h \
outputchannelform.h \ outputchannelform.h \
cfg_vehicletypes/configmultirotorwidget.h \
cfg_vehicletypes/configgroundvehiclewidget.h \
cfg_vehicletypes/configfixedwingwidget.h \
cfg_vehicletypes/vehicleconfig.h \ cfg_vehicletypes/vehicleconfig.h \
cfg_vehicletypes/configccpmwidget.h \
cfg_vehicletypes/configmultirotorwidget.h \
cfg_vehicletypes/configfixedwingwidget.h \
cfg_vehicletypes/configgroundvehiclewidget.h \
cfg_vehicletypes/configcustomwidget.h \
configrevowidget.h \ configrevowidget.h \
config_global.h \ config_global.h \
mixercurve.h \ mixercurve.h \
@ -60,19 +61,24 @@ SOURCES += configplugin.cpp \
configcamerastabilizationwidget.cpp \ configcamerastabilizationwidget.cpp \
configrevowidget.cpp \ configrevowidget.cpp \
configtxpidwidget.cpp \ configtxpidwidget.cpp \
cfg_vehicletypes/configmultirotorwidget.cpp \
cfg_vehicletypes/configgroundvehiclewidget.cpp \
cfg_vehicletypes/configfixedwingwidget.cpp \
cfg_vehicletypes/configccpmwidget.cpp \
outputchannelform.cpp \
cfg_vehicletypes/vehicleconfig.cpp \ cfg_vehicletypes/vehicleconfig.cpp \
cfg_vehicletypes/configccpmwidget.cpp \
cfg_vehicletypes/configmultirotorwidget.cpp \
cfg_vehicletypes/configfixedwingwidget.cpp \
cfg_vehicletypes/configgroundvehiclewidget.cpp \
cfg_vehicletypes/configcustomwidget.cpp \
outputchannelform.cpp \
mixercurve.cpp \ mixercurve.cpp \
dblspindelegate.cpp \ dblspindelegate.cpp \
configrevohwwidget.cpp configrevohwwidget.cpp
FORMS += airframe.ui \ FORMS += airframe.ui \
airframe_ccpm.ui \
airframe_fixedwing.ui \
airframe_ground.ui \
airframe_multirotor.ui \
airframe_custom.ui \
cc_hw_settings.ui \ cc_hw_settings.ui \
ccpm.ui \
stabilization.ui \ stabilization.ui \
input.ui \ input.ui \
output.ui \ output.ui \

View File

@ -3,7 +3,6 @@
<file>images/help2.png</file> <file>images/help2.png</file>
<file>images/ahrs-calib.svg</file> <file>images/ahrs-calib.svg</file>
<file>images/paper-plane.svg</file> <file>images/paper-plane.svg</file>
<file>images/curve-bg.svg</file>
<file>images/multirotor-shapes.svg</file> <file>images/multirotor-shapes.svg</file>
<file>images/ccpm_setup.svg</file> <file>images/ccpm_setup.svg</file>
<file>images/PipXtreme.png</file> <file>images/PipXtreme.png</file>

View File

@ -25,77 +25,81 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/ */
#include "configvehicletypewidget.h" #include "configvehicletypewidget.h"
#include "systemsettings.h"
#include "actuatorsettings.h"
#include "cfg_vehicletypes/configccpmwidget.h"
#include "cfg_vehicletypes/configfixedwingwidget.h"
#include "cfg_vehicletypes/configgroundvehiclewidget.h"
#include "cfg_vehicletypes/configmultirotorwidget.h"
#include "cfg_vehicletypes/configcustomwidget.h"
#include <QDebug> #include <QDebug>
#include <QStringList> #include <QStringList>
#include <QTimer> #include <QTimer>
#include <QtGui/QWidget> #include <QtGui/QWidget>
#include <QtGui/QTextEdit>
#include <QtGui/QVBoxLayout>
#include <QtGui/QPushButton>
#include <math.h>
#include <QDesktopServices> #include <QDesktopServices>
#include <QUrl> #include <QUrl>
#include <QEventLoop>
#include "systemsettings.h"
#include "mixersettings.h"
#include "actuatorsettings.h"
#include <extensionsystem/pluginmanager.h> #include <extensionsystem/pluginmanager.h>
#include <coreplugin/generalsettings.h> #include <coreplugin/generalsettings.h>
/** /**
Helper delegate for the custom mixer editor table. Static function to get currently assigned channelDescriptions
Taken straight from Qt examples, thanks! for all known vehicle types; instantiates the appropriate object
then asks it to supply channel descs
*/ */
SpinBoxDelegate::SpinBoxDelegate(QObject *parent) QStringList ConfigVehicleTypeWidget::getChannelDescriptions()
: QItemDelegate(parent)
{
}
QWidget *SpinBoxDelegate::createEditor(QWidget *parent,
const QStyleOptionViewItem &/* option */,
const QModelIndex &/* index */) const
{ {
QSpinBox *editor = new QSpinBox(parent); ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance();
editor->setMinimum(-127); UAVObjectManager *objMngr = pm->getObject<UAVObjectManager>();
editor->setMaximum(127); Q_ASSERT(objMngr);
return editor; // get an instance of systemsettings
SystemSettings *systemSettings = SystemSettings::GetInstance(objMngr);
Q_ASSERT(systemSettings);
SystemSettings::DataFields systemSettingsData = systemSettings->getData();
QStringList channelDesc;
switch (systemSettingsData.AirframeType) {
case SystemSettings::AIRFRAMETYPE_FIXEDWING:
case SystemSettings::AIRFRAMETYPE_FIXEDWINGELEVON:
case SystemSettings::AIRFRAMETYPE_FIXEDWINGVTAIL:
// fixed wing
channelDesc = ConfigFixedWingWidget::getChannelDescriptions();
break;
case SystemSettings::AIRFRAMETYPE_HELICP:
// helicp
channelDesc = ConfigCcpmWidget::getChannelDescriptions();
break;
case SystemSettings::AIRFRAMETYPE_VTOL:
case SystemSettings::AIRFRAMETYPE_TRI:
case SystemSettings::AIRFRAMETYPE_QUADX:
case SystemSettings::AIRFRAMETYPE_QUADP:
case SystemSettings::AIRFRAMETYPE_OCTOV:
case SystemSettings::AIRFRAMETYPE_OCTOCOAXX:
case SystemSettings::AIRFRAMETYPE_OCTOCOAXP:
case SystemSettings::AIRFRAMETYPE_OCTO:
case SystemSettings::AIRFRAMETYPE_HEXAX:
case SystemSettings::AIRFRAMETYPE_HEXACOAX:
case SystemSettings::AIRFRAMETYPE_HEXA:
// multirotor
channelDesc = ConfigMultiRotorWidget::getChannelDescriptions();
break;
case SystemSettings::AIRFRAMETYPE_GROUNDVEHICLECAR:
case SystemSettings::AIRFRAMETYPE_GROUNDVEHICLEDIFFERENTIAL:
case SystemSettings::AIRFRAMETYPE_GROUNDVEHICLEMOTORCYCLE:
// ground
channelDesc = ConfigGroundVehicleWidget::getChannelDescriptions();
break;
default:
channelDesc = ConfigCustomWidget::getChannelDescriptions();
break;
}
return channelDesc;
} }
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);
}
/**********************************************************************************/
/**
Constructor
*/
ConfigVehicleTypeWidget::ConfigVehicleTypeWidget(QWidget *parent) : ConfigTaskWidget(parent) ConfigVehicleTypeWidget::ConfigVehicleTypeWidget(QWidget *parent) : ConfigTaskWidget(parent)
{ {
m_aircraft = new Ui_AircraftWidget(); m_aircraft = new Ui_AircraftWidget();
@ -103,10 +107,11 @@ ConfigVehicleTypeWidget::ConfigVehicleTypeWidget(QWidget *parent) : ConfigTaskWi
ExtensionSystem::PluginManager *pm=ExtensionSystem::PluginManager::instance(); ExtensionSystem::PluginManager *pm=ExtensionSystem::PluginManager::instance();
Core::Internal::GeneralSettings * settings=pm->getObject<Core::Internal::GeneralSettings>(); Core::Internal::GeneralSettings * settings=pm->getObject<Core::Internal::GeneralSettings>();
if(!settings->useExpertMode()) if (!settings->useExpertMode()) {
m_aircraft->saveAircraftToRAM->setVisible(false); m_aircraft->saveAircraftToRAM->setVisible(false);
}
addApplySaveButtons(m_aircraft->saveAircraftToRAM,m_aircraft->saveAircraftToSD); addApplySaveButtons(m_aircraft->saveAircraftToRAM, m_aircraft->saveAircraftToSD);
addUAVObject("SystemSettings"); addUAVObject("SystemSettings");
addUAVObject("MixerSettings"); addUAVObject("MixerSettings");
@ -115,120 +120,40 @@ ConfigVehicleTypeWidget::ConfigVehicleTypeWidget(QWidget *parent) : ConfigTaskWi
ffTuningInProgress = false; ffTuningInProgress = false;
ffTuningPhase = false; ffTuningPhase = false;
//Generate lists of mixerTypeNames, mixerVectorNames, channelNames
channelNames << "None";
for (int i = 0; i < (int)ActuatorSettings::CHANNELADDR_NUMELEM; i++) {
mixerTypes << QString("Mixer%1Type").arg(i+1);
mixerVectors << QString("Mixer%1Vector").arg(i+1);
channelNames << QString("Channel%1").arg(i+1);
}
QStringList airframeTypes; QStringList airframeTypes;
airframeTypes << "Fixed Wing" << "Multirotor" << "Helicopter" << "Ground" << "Custom"; airframeTypes << "Fixed Wing" << "Multirotor" << "Helicopter" << "Ground" << "Custom";
m_aircraft->aircraftType->addItems(airframeTypes); m_aircraft->aircraftType->addItems(airframeTypes);
m_aircraft->aircraftType->setCurrentIndex(1); //Set default vehicle to MultiRotor
m_aircraft->airframesWidget->setCurrentIndex(1); // Force the tab index to match
QStringList fixedWingTypes; // Set default vehicle to MultiRotor
fixedWingTypes << "Elevator aileron rudder" << "Elevon" << "Vtail"; //m_aircraft->aircraftType->setCurrentIndex(3);
m_aircraft->fixedWingType->addItems(fixedWingTypes);
m_aircraft->fixedWingType->setCurrentIndex(0); //Set default model to "Elevator aileron rudder"
QStringList groundVehicleTypes; // Connect aircraft type selection dropbox to callback function
groundVehicleTypes << "Turnable (car)" << "Differential (tank)" << "Motorcycle";
m_aircraft->groundVehicleType->addItems(groundVehicleTypes);
m_aircraft->groundVehicleType->setCurrentIndex(0); //Set default model to "Turnable (car)"
QStringList multiRotorTypes;
multiRotorTypes << "Tricopter Y"<< "Quad +" << "Quad X" <<
"Hexacopter" << "Hexacopter X" << "Hexacopter Y6" <<
"Octocopter" << "Octocopter V" << "Octo Coax +" << "Octo Coax X" ;
m_aircraft->multirotorFrameType->addItems(multiRotorTypes);
m_aircraft->multirotorFrameType->setCurrentIndex(2); //Set default model to "Quad X"
//NEW STYLE: Loop through the widgets looking for all widgets that have "ChannelBox" in their name
// The upshot of this is that ALL new ComboBox widgets for selecting the output channel must have "ChannelBox" in their name
foreach(QComboBox *combobox, this->findChildren<QComboBox*>(QRegExp("\\S+ChannelBo\\S+")))//FOR WHATEVER REASON, THIS DOES NOT WORK WITH ChannelBox. ChannelBo is sufficiently accurate
{
combobox->addItems(channelNames);
}
// 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/multirotor-shapes.svg"));
quad = new QGraphicsSvgItem();
quad->setSharedRenderer(renderer);
quad->setElementId("quad-x");
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<(int)(VehicleConfig::CHANNEL_NUMELEM); 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<(int)(VehicleConfig::CHANNEL_NUMELEM); i++) {
m_aircraft->customMixerTable->setItemDelegateForRow(i, sbd);
}
// create and setup a MultiRotor config widget
m_multirotor = new ConfigMultiRotorWidget(m_aircraft);
m_multirotor->quad = quad;
m_multirotor->uiowner = this;
m_multirotor->setupUI(m_aircraft->multirotorFrameType->currentText());
// create and setup a GroundVehicle config widget
m_groundvehicle = new ConfigGroundVehicleWidget(m_aircraft);
m_groundvehicle->setupUI(m_aircraft->groundVehicleType->currentText() );
// create and setup a FixedWing config widget
m_fixedwing = new ConfigFixedWingWidget(m_aircraft);
m_fixedwing->setupUI(m_aircraft->fixedWingType->currentText() );
// create and setup a Helicopter config widget
m_heli = m_aircraft->widget_3;
m_heli->setupUI(QString("HeliCP"));
//Connect aircraft type selection dropbox to callback function
connect(m_aircraft->aircraftType, SIGNAL(currentIndexChanged(int)), this, SLOT(switchAirframeType(int))); connect(m_aircraft->aircraftType, SIGNAL(currentIndexChanged(int)), this, SLOT(switchAirframeType(int)));
//Connect airframe selection dropbox to callback functions // Connect the three feed forward test checkboxes
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->groundVehicleType, SIGNAL(currentIndexChanged(QString)), this, SLOT(setupAirframeUI(QString)));
//mdl connect(m_heli->m_ccpm->ccpmType, SIGNAL(currentIndexChanged(QString)), this, SLOT(setupAirframeUI(QString)));
//Connect the three feed forward test checkboxes
connect(m_aircraft->ffTestBox1, SIGNAL(clicked(bool)), this, SLOT(enableFFTest())); connect(m_aircraft->ffTestBox1, SIGNAL(clicked(bool)), this, SLOT(enableFFTest()));
connect(m_aircraft->ffTestBox2, 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(m_aircraft->ffTestBox3, SIGNAL(clicked(bool)), this, SLOT(enableFFTest()));
//Connect the multirotor motor reverse checkbox
connect(m_aircraft->MultirotorRevMixercheckBox, SIGNAL(clicked(bool)), this, SLOT(reverseMultirotorMotor()));
// Connect the help pushbutton // Connect the help pushbutton
connect(m_aircraft->airframeHelp, SIGNAL(clicked()), this, SLOT(openHelp())); connect(m_aircraft->airframeHelp, SIGNAL(clicked()), this, SLOT(openHelp()));
enableControls(false); enableControls(false);
refreshWidgetsValues(); refreshWidgetsValues();
addToDirtyMonitor();
// register widgets for dirty state management
addWidget(m_aircraft->aircraftType);
// register FF widgets for dirty state management
addWidget(m_aircraft->feedForwardSlider);
addWidget(m_aircraft->accelTime);
addWidget(m_aircraft->decelTime);
addWidget(m_aircraft->maxAccelSlider);
disableMouseWheelEvents(); disableMouseWheelEvents();
m_aircraft->quadShape->fitInView(quad, Qt::KeepAspectRatio);
} }
/** /**
Destructor Destructor
*/ */
@ -237,174 +162,159 @@ ConfigVehicleTypeWidget::~ConfigVehicleTypeWidget()
// Do nothing // Do nothing
} }
/**
Static function to get currently assigned channelDescriptions
for all known vehicle types; instantiates the appropriate object
then asks it to supply channel descs
*/
QStringList ConfigVehicleTypeWidget::getChannelDescriptions()
{
int i;
QStringList channelDesc;
ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance();
UAVObjectManager * objMngr = pm->getObject<UAVObjectManager>();
Q_ASSERT(objMngr);
// get an instance of systemsettings
SystemSettings * systemSettings = SystemSettings::GetInstance(objMngr);
Q_ASSERT(systemSettings);
SystemSettings::DataFields systemSettingsData = systemSettings->getData();
switch (systemSettingsData.AirframeType)
{
// fixed wing
case SystemSettings::AIRFRAMETYPE_FIXEDWING:
case SystemSettings::AIRFRAMETYPE_FIXEDWINGELEVON:
case SystemSettings::AIRFRAMETYPE_FIXEDWINGVTAIL:
{
channelDesc = ConfigFixedWingWidget::getChannelDescriptions();
}
break;
// helicp
case SystemSettings::AIRFRAMETYPE_HELICP:
{
channelDesc = ConfigCcpmWidget::getChannelDescriptions();
}
break;
//multirotor
case SystemSettings::AIRFRAMETYPE_VTOL:
case SystemSettings::AIRFRAMETYPE_TRI:
case SystemSettings::AIRFRAMETYPE_QUADX:
case SystemSettings::AIRFRAMETYPE_QUADP:
case SystemSettings::AIRFRAMETYPE_OCTOV:
case SystemSettings::AIRFRAMETYPE_OCTOCOAXX:
case SystemSettings::AIRFRAMETYPE_OCTOCOAXP:
case SystemSettings::AIRFRAMETYPE_OCTO:
case SystemSettings::AIRFRAMETYPE_HEXAX:
case SystemSettings::AIRFRAMETYPE_HEXACOAX:
case SystemSettings::AIRFRAMETYPE_HEXA:
{
channelDesc = ConfigMultiRotorWidget::getChannelDescriptions();
}
break;
// ground
case SystemSettings::AIRFRAMETYPE_GROUNDVEHICLECAR:
case SystemSettings::AIRFRAMETYPE_GROUNDVEHICLEDIFFERENTIAL:
case SystemSettings::AIRFRAMETYPE_GROUNDVEHICLEMOTORCYCLE:
{
channelDesc = ConfigGroundVehicleWidget::getChannelDescriptions();
}
break;
default:
{
for (i=0; i < (int)(VehicleConfig::CHANNEL_NUMELEM); i++)
channelDesc.append(QString("-"));
}
break;
}
// for (i=0; i < channelDesc.count(); i++)
// qDebug() << QString("Channel %0 = %1").arg(i).arg(channelDesc[i]);
return channelDesc;
}
/**
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 ConfigVehicleTypeWidget::switchAirframeType(int index) void ConfigVehicleTypeWidget::switchAirframeType(int index)
{ {
m_aircraft->airframesWidget->setCurrentIndex(index); // TODO not safe w/r to translation!!!
m_aircraft->quadShape->setSceneRect(quad->boundingRect()); QString frameCategory = m_aircraft->aircraftType->currentText();
m_aircraft->quadShape->fitInView(quad, Qt::KeepAspectRatio); m_aircraft->airframesWidget->setCurrentWidget(getVehicleConfigWidget(frameCategory));
if (m_aircraft->aircraftType->findText("Custom")) {
m_aircraft->customMixerTable->resizeColumnsToContents();
for (int i=0;i<(int)(VehicleConfig::CHANNEL_NUMELEM);i++) {
m_aircraft->customMixerTable->setColumnWidth(i,(m_aircraft->customMixerTable->width()-
m_aircraft->customMixerTable->verticalHeader()->width())/10);
}
}
}
/**
WHAT DOES THIS DO???
*/
void ConfigVehicleTypeWidget::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<(int)(VehicleConfig::CHANNEL_NUMELEM);i++) {
m_aircraft->customMixerTable->setColumnWidth(i,(m_aircraft->customMixerTable->width()-
m_aircraft->customMixerTable->verticalHeader()->width())/ 10);
}
} }
/** /**
Resize the GUI contents when the user changes the window size Refreshes the current value of the SystemSettings which holds the aircraft type
*/ Note: The default behavior of ConfigTaskWidget is bypassed.
void ConfigVehicleTypeWidget::resizeEvent(QResizeEvent* event) Therefore no automatic synchronization of UAV Objects to UI is done.
*/
void ConfigVehicleTypeWidget::refreshWidgetsValues(UAVObject *o)
{ {
Q_UNUSED(event); Q_UNUSED(o);
m_aircraft->quadShape->fitInView(quad, Qt::KeepAspectRatio);
// Make the custom table columns autostretch: if (!allObjectsUpdated()) {
m_aircraft->customMixerTable->resizeColumnsToContents(); return;
for (int i=0;i<(int)(VehicleConfig::CHANNEL_NUMELEM);i++) {
m_aircraft->customMixerTable->setColumnWidth(i,(m_aircraft->customMixerTable->width()-
m_aircraft->customMixerTable->verticalHeader()->width())/ 10);
} }
bool dirty = isDirty();
// Get the Airframe type from the system settings:
UAVDataObject *system = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("SystemSettings")));
Q_ASSERT(system);
UAVObjectField *field = system->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 there you go.
QString frameType = field->getValue().toString();
qDebug() << "ConfigVehicleTypeWidget::refreshWidgetsValues - frame type:" << frameType;
QString category = frameCategory(frameType);
setComboCurrentIndex(m_aircraft->aircraftType, m_aircraft->aircraftType->findText(category));
VehicleConfig *vehicleConfig = getVehicleConfigWidget(category);
if (vehicleConfig) {
vehicleConfig->refreshWidgetsValues(frameType);
}
updateFeedForwardUI();
setDirty(dirty);
qDebug() << "ConfigVehicleTypeWidget::refreshWidgetsValues - end";
} }
/**
Sends the config to the board (airframe type)
void ConfigVehicleTypeWidget::toggleAileron2(int index) 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.
Note: The default behavior of ConfigTaskWidget is bypassed.
Therefore no automatic synchronization of UI to UAV Objects is done.
*/
void ConfigVehicleTypeWidget::updateObjectsFromWidgets()
{ {
if (index) { // Airframe type defaults to Custom
m_aircraft->fwAileron2ChannelBox->setEnabled(true); QString airframeType = "Custom";
m_aircraft->fwAileron2Label->setEnabled(true);
VehicleConfig *vehicleConfig = (VehicleConfig *) m_aircraft->airframesWidget->currentWidget();
if (vehicleConfig) {
airframeType = vehicleConfig->updateConfigObjectsFromWidgets();
}
// set the airframe type
UAVDataObject *system = dynamic_cast<UAVDataObject *>(getObjectManager()->getObject(QString("SystemSettings")));
Q_ASSERT(system);
QPointer<UAVObjectField> field = system->getField(QString("AirframeType"));
if (field) {
field->setValue(airframeType);
}
// Update feed forward settings
UAVDataObject *mixer = dynamic_cast<UAVDataObject *>(getObjectManager()->getObject(QString("MixerSettings")));
Q_ASSERT(mixer);
QPointer<VehicleConfig> vconfig = new VehicleConfig();
vconfig->setMixerValue(mixer, "FeedForward", m_aircraft->feedForwardSlider->value() / 100.0);
vconfig->setMixerValue(mixer, "AccelTime", m_aircraft->accelTime->value());
vconfig->setMixerValue(mixer, "DecelTime", m_aircraft->decelTime->value());
vconfig->setMixerValue(mixer, "MaxAccel", m_aircraft->maxAccelSlider->value());
// TODO call refreshWidgetsValues() to reflect actual saved values ?
updateFeedForwardUI();
}
QString ConfigVehicleTypeWidget::frameCategory(QString frameType)
{
QString category;
if (frameType == "FixedWing" || frameType == "Elevator aileron rudder" || frameType == "FixedWingElevon"
|| frameType == "Elevon" || frameType == "FixedWingVtail" || frameType == "Vtail") {
category = "Fixed Wing";
} else if (frameType == "Tri" || frameType == "Tricopter Y" || frameType == "QuadX" || frameType == "Quad X"
|| frameType == "QuadP" || frameType == "Quad +" || frameType == "Hexa" || frameType == "Hexacopter"
|| frameType == "HexaX" || frameType == "Hexacopter X" || frameType == "HexaCoax"
|| frameType == "Hexacopter Y6" || frameType == "Octo" || frameType == "Octocopter" || frameType == "OctoV"
|| frameType == "Octocopter V" || frameType == "OctoCoaxP" || frameType == "Octo Coax +"
|| frameType == "OctoCoaxX" || frameType == "Octo Coax X") {
category = "Multirotor";
} else if (frameType == "HeliCP") {
category = "Helicopter";
} else if (frameType == "GroundVehicleCar" || frameType == "Turnable (car)"
|| frameType == "GroundVehicleDifferential" || frameType == "Differential (tank)"
|| frameType == "GroundVehicleMotorcyle" || frameType == "Motorcycle") {
category = "Ground";
} else { } else {
m_aircraft->fwAileron2ChannelBox->setEnabled(false); category = "Custom";
m_aircraft->fwAileron2Label->setEnabled(false);
} }
return category;
} }
void ConfigVehicleTypeWidget::toggleElevator2(int index) VehicleConfig *ConfigVehicleTypeWidget::getVehicleConfigWidget(QString frameCategory)
{ {
if (index) { VehicleConfig *vehiculeConfig;
m_aircraft->fwElevator2ChannelBox->setEnabled(true); if (!vehicleIndexMap.contains(frameCategory)) {
m_aircraft->fwElevator2Label->setEnabled(true); // create config widget
} else { vehiculeConfig = createVehicleConfigWidget(frameCategory);
m_aircraft->fwElevator2ChannelBox->setEnabled(false); // bind config widget "field" to this ConfigTaskWodget
m_aircraft->fwElevator2Label->setEnabled(false); // this is necessary to get "dirty" state management
vehiculeConfig->registerWidgets(*this);
// add config widget to UI
int index = m_aircraft->airframesWidget->insertWidget(m_aircraft->airframesWidget->count(), vehiculeConfig);
vehicleIndexMap[frameCategory] = index;
} }
int index = vehicleIndexMap.value(frameCategory);
vehiculeConfig = (VehicleConfig *) m_aircraft->airframesWidget->widget(index);
return vehiculeConfig;
} }
void ConfigVehicleTypeWidget::toggleRudder2(int index) VehicleConfig *ConfigVehicleTypeWidget::createVehicleConfigWidget(QString frameCategory)
{ {
if (index) { qDebug() << "ConfigVehicleTypeWidget::createVehicleConfigWidget - creating" << frameCategory;
m_aircraft->fwRudder2ChannelBox->setEnabled(true); if (frameCategory == "Fixed Wing") {
m_aircraft->fwRudder2Label->setEnabled(true); return new ConfigFixedWingWidget();
} else { } else if (frameCategory == "Multirotor") {
m_aircraft->fwRudder2ChannelBox->setEnabled(false); return new ConfigMultiRotorWidget();
m_aircraft->fwRudder2Label->setEnabled(false); } else if (frameCategory == "Helicopter") {
return new ConfigCcpmWidget();
} else if (frameCategory == "Ground") {
return new ConfigGroundVehicleWidget();
} else if (frameCategory == "Custom") {
return new ConfigCustomWidget();
} }
return NULL;
} }
/////////////////////////////////////////////////////////
/// Feed Forward Testing
/////////////////////////////////////////////////////////
/** /**
Enables and runs feed forward testing Enables and runs feed forward testing
*/ */
@ -414,13 +324,12 @@ void ConfigVehicleTypeWidget::enableFFTest()
// - Check if all three checkboxes are checked // - Check if all three checkboxes are checked
// - Every other timer event: toggle engine from 45% to 55% // - Every other timer event: toggle engine from 45% to 55%
// - Every other time event: send FF settings to flight FW // - Every other time event: send FF settings to flight FW
if (m_aircraft->ffTestBox1->isChecked() && if (m_aircraft->ffTestBox1->isChecked() && m_aircraft->ffTestBox2->isChecked()
m_aircraft->ffTestBox2->isChecked() && && m_aircraft->ffTestBox3->isChecked()) {
m_aircraft->ffTestBox3->isChecked()) { if (!ffTuningInProgress) {
if (!ffTuningInProgress)
{
// Initiate tuning: // Initiate tuning:
UAVDataObject* obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("ManualControlCommand"))); UAVDataObject *obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(
QString("ManualControlCommand")));
UAVObject::Metadata mdata = obj->getMetadata(); UAVObject::Metadata mdata = obj->getMetadata();
accInitialData = mdata; accInitialData = mdata;
UAVObject::SetFlightAccess(mdata, UAVObject::ACCESS_READONLY); UAVObject::SetFlightAccess(mdata, UAVObject::ACCESS_READONLY);
@ -440,9 +349,10 @@ void ConfigVehicleTypeWidget::enableFFTest()
vconfig->setMixerValue(mixer, "DecelTime", m_aircraft->decelTime->value()); vconfig->setMixerValue(mixer, "DecelTime", m_aircraft->decelTime->value());
vconfig->setMixerValue(mixer, "MaxAccel", m_aircraft->maxAccelSlider->value()); vconfig->setMixerValue(mixer, "MaxAccel", m_aircraft->maxAccelSlider->value());
mixer->updated(); mixer->updated();
} else { } else {
// Toggle motor state // Toggle motor state
UAVDataObject* obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("ManualControlCommand"))); UAVDataObject* obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(
QString("ManualControlCommand")));
double value = obj->getField("Throttle")->getDouble(); double value = obj->getField("Throttle")->getDouble();
double target = (value < 0.5) ? 0.55 : 0.45; double target = (value < 0.5) ? 0.55 : 0.45;
obj->getField("Throttle")->setValue(target); obj->getField("Throttle")->setValue(target);
@ -456,7 +366,8 @@ void ConfigVehicleTypeWidget::enableFFTest()
// Disarm! // Disarm!
if (ffTuningInProgress) { if (ffTuningInProgress) {
ffTuningInProgress = false; ffTuningInProgress = false;
UAVDataObject* obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("ManualControlCommand"))); UAVDataObject *obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(
QString("ManualControlCommand")));
UAVObject::Metadata mdata = obj->getMetadata(); UAVObject::Metadata mdata = obj->getMetadata();
mdata = accInitialData; // Restore metadata mdata = accInitialData; // Restore metadata
obj->setMetadata(mdata); obj->setMetadata(mdata);
@ -464,310 +375,23 @@ void ConfigVehicleTypeWidget::enableFFTest()
} }
} }
/**************************
* Aircraft settings
**************************/
/**
Refreshes the current value of the SystemSettings which holds the aircraft type
*/
void ConfigVehicleTypeWidget::refreshWidgetsValues(UAVObject * o)
{
Q_UNUSED(o);
if(!allObjectsUpdated())
return;
bool dirty=isDirty();
// Get the Airframe type from the system settings:
UAVDataObject* system = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("SystemSettings")));
Q_ASSERT(system);
UAVObjectField *field = system->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 there you go.
QString frameType = field->getValue().toString();
setupAirframeUI(frameType);
UAVDataObject* mixer = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
Q_ASSERT(mixer);
QPointer<VehicleConfig> vconfig = new VehicleConfig();
QList<double> curveValues;
vconfig->getThrottleCurve(mixer, VehicleConfig::MIXER_THROTTLECURVE1, &curveValues);
// is at least one of the curve values != 0?
if (vconfig->isValidThrottleCurve(&curveValues)) {
// yes, use the curve we just read from mixersettings
m_aircraft->multiThrottleCurve->initCurve(&curveValues);
m_aircraft->fixedWingThrottle->initCurve(&curveValues);
m_aircraft->groundVehicleThrottle1->initCurve(&curveValues);
}
else {
// no, init a straight curve
m_aircraft->multiThrottleCurve->initLinearCurve(curveValues.count(), 0.9);
m_aircraft->fixedWingThrottle->initLinearCurve(curveValues.count(), 1.0);
m_aircraft->groundVehicleThrottle1->initLinearCurve(curveValues.count(), 1.0);
}
// Setup all Throttle2 curves for all types of airframes //AT THIS MOMENT, THAT MEANS ONLY GROUND VEHICLES
vconfig->getThrottleCurve(mixer, VehicleConfig::MIXER_THROTTLECURVE2, &curveValues);
if (vconfig->isValidThrottleCurve(&curveValues)) {
m_aircraft->groundVehicleThrottle2->initCurve(&curveValues);
}
else {
m_aircraft->groundVehicleThrottle2->initLinearCurve(curveValues.count(), 1.0);
}
// Load the Settings for fixed wing frames:
if (frameType.startsWith("FixedWing")) {
// Retrieve fixed wing settings
m_fixedwing->refreshWidgetsValues(frameType);
} else if (frameType == "Tri" ||
frameType == "QuadX" || frameType == "QuadP" ||
frameType == "Hexa" || frameType == "HexaCoax" || frameType == "HexaX" ||
frameType == "Octo" || frameType == "OctoV" || frameType == "OctoCoaxP" || frameType == "OctoCoaxX" ) {
// Retrieve multirotor settings
m_multirotor->refreshWidgetsValues(frameType);
} else if (frameType == "HeliCP") {
setComboCurrentIndex(m_aircraft->aircraftType, m_aircraft->aircraftType->findText("Helicopter"));
m_heli->refreshWidgetsValues(frameType);
} else if (frameType.startsWith("GroundVehicle")) {
// Retrieve ground vehicle settings
m_groundvehicle->refreshWidgetsValues(frameType);
} else if (frameType == "Custom") {
setComboCurrentIndex(m_aircraft->aircraftType, m_aircraft->aircraftType->findText("Custom"));
}
updateCustomAirframeUI();
setDirty(dirty);
}
/**
\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 ConfigVehicleTypeWidget::setupAirframeUI(QString frameType)
{
bool dirty=isDirty();
if(frameType == "FixedWing" || frameType == "Elevator aileron rudder" ||
frameType == "FixedWingElevon" || frameType == "Elevon" ||
frameType == "FixedWingVtail" || frameType == "Vtail"){
m_fixedwing->setupUI(frameType);
}
else if (frameType == "Tri" || frameType == "Tricopter Y" ||
frameType == "QuadX" || frameType == "Quad X" ||
frameType == "QuadP" || frameType == "Quad +" ||
frameType == "Hexa" || frameType == "Hexacopter" ||
frameType == "HexaX" || frameType == "Hexacopter X" ||
frameType == "HexaCoax" || frameType == "Hexacopter Y6" ||
frameType == "Octo" || frameType == "Octocopter" ||
frameType == "OctoV" || frameType == "Octocopter V" ||
frameType == "OctoCoaxP" || frameType == "Octo Coax +" ||
frameType == "OctoCoaxX" || frameType == "Octo Coax X" ) {
//Call multi-rotor setup UI
m_multirotor->setupUI(frameType);
}
else if (frameType == "HeliCP") {
m_heli->setupUI(frameType);
}
else if (frameType == "GroundVehicleCar" || frameType == "Turnable (car)" ||
frameType == "GroundVehicleDifferential" || frameType == "Differential (tank)" ||
frameType == "GroundVehicleMotorcyle" || frameType == "Motorcycle") {
m_groundvehicle->setupUI(frameType);
}
//SHOULDN'T THIS BE DONE ONLY IN QUAD SETUP, AND NOT ALL THE REST???
m_aircraft->quadShape->setSceneRect(quad->boundingRect());
m_aircraft->quadShape->fitInView(quad, Qt::KeepAspectRatio);
setDirty(dirty);
}
/**
Reset the contents of a field
*/
void ConfigVehicleTypeWidget::resetField(UAVObjectField * field)
{
for (unsigned int i=0;i<field->getNumElements();i++) {
field->setValue(0,i);
}
}
/** /**
Updates the custom airframe settings based on the current airframe. Updates the custom airframe settings based on the current airframe.
Note: does NOT ask for an object refresh itself! Note: does NOT ask for an object refresh itself!
*/ */
void ConfigVehicleTypeWidget::updateCustomAirframeUI() void ConfigVehicleTypeWidget::updateFeedForwardUI()
{ {
UAVDataObject* mixer = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings"))); UAVDataObject *mixer = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
Q_ASSERT(mixer);
QPointer<VehicleConfig> vconfig = new VehicleConfig();
QList<double> curveValues;
vconfig->getThrottleCurve(mixer, VehicleConfig::MIXER_THROTTLECURVE1, &curveValues);
// is at least one of the curve values != 0?
if (vconfig->isValidThrottleCurve(&curveValues)) {
m_aircraft->customThrottle1Curve->initCurve(&curveValues);
}
else {
// no, init a straight curve
m_aircraft->customThrottle1Curve->initLinearCurve(curveValues.count(), 1.0);
}
if (MixerSettings* mxr = qobject_cast<MixerSettings *>(mixer)) {
MixerSettings::DataFields mixerSettingsData = mxr->getData();
if (mixerSettingsData.Curve2Source == MixerSettings::CURVE2SOURCE_THROTTLE)
m_aircraft->customThrottle2Curve->setMixerType(MixerCurve::MIXERCURVE_THROTTLE);
else {
m_aircraft->customThrottle2Curve->setMixerType(MixerCurve::MIXERCURVE_PITCH);
}
}
// Setup all Throttle2 curves for all types of airframes
vconfig->getThrottleCurve(mixer, VehicleConfig::MIXER_THROTTLECURVE2, &curveValues);
if (vconfig->isValidThrottleCurve(&curveValues)) {
m_aircraft->customThrottle2Curve->initCurve(&curveValues);
}
else {
m_aircraft->customThrottle2Curve->initLinearCurve(curveValues.count(), 1.0, m_aircraft->customThrottle2Curve->getMin());
}
// Update the mixer table:
for (int channel=0; channel < m_aircraft->customMixerTable->columnCount(); channel++) {
UAVObjectField* field = mixer->getField(mixerTypes.at(channel));
if (field)
{
QComboBox* q = (QComboBox*)m_aircraft->customMixerTable->cellWidget(0,channel);
if (q)
{
QString s = field->getValue().toString();
setComboCurrentIndex(q, q->findText(s));
}
m_aircraft->customMixerTable->item(1,channel)->setText(
QString::number(vconfig->getMixerVectorValue(mixer,channel,VehicleConfig::MIXERVECTOR_THROTTLECURVE1)));
m_aircraft->customMixerTable->item(2,channel)->setText(
QString::number(vconfig->getMixerVectorValue(mixer,channel,VehicleConfig::MIXERVECTOR_THROTTLECURVE2)));
m_aircraft->customMixerTable->item(3,channel)->setText(
QString::number(vconfig->getMixerVectorValue(mixer,channel,VehicleConfig::MIXERVECTOR_ROLL)));
m_aircraft->customMixerTable->item(4,channel)->setText(
QString::number(vconfig->getMixerVectorValue(mixer,channel,VehicleConfig::MIXERVECTOR_PITCH)));
m_aircraft->customMixerTable->item(5,channel)->setText(
QString::number(vconfig->getMixerVectorValue(mixer,channel,VehicleConfig::MIXERVECTOR_YAW)));
}
}
// Update feed forward settings
m_aircraft->feedForwardSlider->setValue(vconfig->getMixerValue(mixer,"FeedForward") * 100);
m_aircraft->accelTime->setValue(vconfig->getMixerValue(mixer,"AccelTime"));
m_aircraft->decelTime->setValue(vconfig->getMixerValue(mixer,"DecelTime"));
m_aircraft->maxAccelSlider->setValue(vconfig->getMixerValue(mixer,"MaxAccel"));
}
/**
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 ConfigVehicleTypeWidget::updateObjectsFromWidgets()
{
UAVDataObject* mixer = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
Q_ASSERT(mixer); Q_ASSERT(mixer);
QPointer<VehicleConfig> vconfig = new VehicleConfig(); QPointer<VehicleConfig> vconfig = new VehicleConfig();
// Update feed forward settings // Update feed forward settings
vconfig->setMixerValue(mixer, "FeedForward", m_aircraft->feedForwardSlider->value() / 100.0); m_aircraft->feedForwardSlider->setValue(vconfig->getMixerValue(mixer, "FeedForward") * 100);
vconfig->setMixerValue(mixer, "AccelTime", m_aircraft->accelTime->value()); m_aircraft->accelTime->setValue(vconfig->getMixerValue(mixer, "AccelTime"));
vconfig->setMixerValue(mixer, "DecelTime", m_aircraft->decelTime->value()); m_aircraft->decelTime->setValue(vconfig->getMixerValue(mixer, "DecelTime"));
vconfig->setMixerValue(mixer, "MaxAccel", m_aircraft->maxAccelSlider->value()); m_aircraft->maxAccelSlider->setValue(vconfig->getMixerValue(mixer, "MaxAccel"));
QString airframeType = "Custom"; //Sets airframe type default to "Custom"
if (m_aircraft->aircraftType->currentText() == "Fixed Wing") {
airframeType = m_fixedwing->updateConfigObjectsFromWidgets();
}
else if (m_aircraft->aircraftType->currentText() == "Multirotor") {
airframeType = m_multirotor->updateConfigObjectsFromWidgets();
}
else if (m_aircraft->aircraftType->currentText() == "Helicopter") {
airframeType = m_heli->updateConfigObjectsFromWidgets();
}
else if (m_aircraft->aircraftType->currentText() == "Ground") {
airframeType = m_groundvehicle->updateConfigObjectsFromWidgets();
}
else {
vconfig->setThrottleCurve(mixer, VehicleConfig::MIXER_THROTTLECURVE1, m_aircraft->customThrottle1Curve->getCurve());
vconfig->setThrottleCurve(mixer, VehicleConfig::MIXER_THROTTLECURVE2, m_aircraft->customThrottle2Curve->getCurve());
// Update the table:
for (int channel=0; channel<(int)(VehicleConfig::CHANNEL_NUMELEM); channel++) {
QComboBox* q = (QComboBox*)m_aircraft->customMixerTable->cellWidget(0,channel);
if(q->currentText()=="Disabled")
vconfig->setMixerType(mixer,channel,VehicleConfig::MIXERTYPE_DISABLED);
else if(q->currentText()=="Motor")
vconfig->setMixerType(mixer,channel,VehicleConfig::MIXERTYPE_MOTOR);
else if(q->currentText()=="Servo")
vconfig->setMixerType(mixer,channel,VehicleConfig::MIXERTYPE_SERVO);
else if(q->currentText()=="CameraRoll")
vconfig->setMixerType(mixer,channel,VehicleConfig::MIXERTYPE_CAMERAROLL);
else if(q->currentText()=="CameraPitch")
vconfig->setMixerType(mixer,channel,VehicleConfig::MIXERTYPE_CAMERAPITCH);
else if(q->currentText()=="CameraYaw")
vconfig->setMixerType(mixer,channel,VehicleConfig::MIXERTYPE_CAMERAYAW);
else if(q->currentText()=="Accessory0")
vconfig->setMixerType(mixer,channel,VehicleConfig::MIXERTYPE_ACCESSORY0);
else if(q->currentText()=="Accessory1")
vconfig->setMixerType(mixer,channel,VehicleConfig::MIXERTYPE_ACCESSORY1);
else if(q->currentText()=="Accessory2")
vconfig->setMixerType(mixer,channel,VehicleConfig::MIXERTYPE_ACCESSORY2);
else if(q->currentText()=="Accessory3")
vconfig->setMixerType(mixer,channel,VehicleConfig::MIXERTYPE_ACCESSORY3);
else if(q->currentText()=="Accessory4")
vconfig->setMixerType(mixer,channel,VehicleConfig::MIXERTYPE_ACCESSORY4);
else if(q->currentText()=="Accessory5")
vconfig->setMixerType(mixer,channel,VehicleConfig::MIXERTYPE_ACCESSORY5);
vconfig->setMixerVectorValue(mixer,channel,VehicleConfig::MIXERVECTOR_THROTTLECURVE1,
m_aircraft->customMixerTable->item(1,channel)->text().toDouble());
vconfig->setMixerVectorValue(mixer,channel,VehicleConfig::MIXERVECTOR_THROTTLECURVE2,
m_aircraft->customMixerTable->item(2,channel)->text().toDouble());
vconfig->setMixerVectorValue(mixer,channel,VehicleConfig::MIXERVECTOR_ROLL,
m_aircraft->customMixerTable->item(3,channel)->text().toDouble());
vconfig->setMixerVectorValue(mixer,channel,VehicleConfig::MIXERVECTOR_PITCH,
m_aircraft->customMixerTable->item(4,channel)->text().toDouble());
vconfig->setMixerVectorValue(mixer,channel,VehicleConfig::MIXERVECTOR_YAW,
m_aircraft->customMixerTable->item(5,channel)->text().toDouble());
}
}
// set the airframe type
UAVDataObject* system = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("SystemSettings")));
Q_ASSERT(system);
QPointer<UAVObjectField> field = system->getField(QString("AirframeType"));
if (field)
field->setValue(airframeType);
updateCustomAirframeUI();
} }
/** /**
@ -775,7 +399,6 @@ void ConfigVehicleTypeWidget::updateObjectsFromWidgets()
*/ */
void ConfigVehicleTypeWidget::openHelp() void ConfigVehicleTypeWidget::openHelp()
{ {
QDesktopServices::openUrl( QUrl("http://wiki.openpilot.org/x/44Cf", QUrl::StrictMode) ); QDesktopServices::openUrl( QUrl("http://wiki.openpilot.org/x/44Cf", QUrl::StrictMode) );
} }
@ -786,88 +409,7 @@ void ConfigVehicleTypeWidget::openHelp()
*/ */
void ConfigVehicleTypeWidget::setComboCurrentIndex(QComboBox* box, int index) void ConfigVehicleTypeWidget::setComboCurrentIndex(QComboBox* box, int index)
{ {
if (index >= 0 && index < box->count()) if (index >= 0 && index < box->count()) {
box->setCurrentIndex(index); box->setCurrentIndex(index);
}
} }
void ConfigVehicleTypeWidget::reverseMultirotorMotor(){
QString frameType = m_aircraft->multirotorFrameType->currentText();
m_multirotor->drawAirframe(frameType);
}
/**
WHAT DOES THIS DO???
*/
void ConfigVehicleTypeWidget::addToDirtyMonitor()
{
addWidget(m_aircraft->customMixerTable);
addWidget(m_aircraft->customThrottle1Curve->getCurveWidget());
addWidget(m_aircraft->customThrottle2Curve->getCurveWidget());
addWidget(m_aircraft->multiThrottleCurve->getCurveWidget());
addWidget(m_aircraft->fixedWingThrottle->getCurveWidget());
addWidget(m_aircraft->fixedWingType);
addWidget(m_aircraft->groundVehicleThrottle1->getCurveWidget());
addWidget(m_aircraft->groundVehicleThrottle2->getCurveWidget());
addWidget(m_aircraft->groundVehicleType);
addWidget(m_aircraft->feedForwardSlider);
addWidget(m_aircraft->accelTime);
addWidget(m_aircraft->decelTime);
addWidget(m_aircraft->maxAccelSlider);
addWidget(m_aircraft->multirotorFrameType);
addWidget(m_aircraft->multiMotorChannelBox1);
addWidget(m_aircraft->multiMotorChannelBox2);
addWidget(m_aircraft->multiMotorChannelBox3);
addWidget(m_aircraft->multiMotorChannelBox4);
addWidget(m_aircraft->multiMotorChannelBox5);
addWidget(m_aircraft->multiMotorChannelBox6);
addWidget(m_aircraft->multiMotorChannelBox7);
addWidget(m_aircraft->multiMotorChannelBox8);
addWidget(m_aircraft->mrPitchMixLevel);
addWidget(m_aircraft->mrRollMixLevel);
addWidget(m_aircraft->mrYawMixLevel);
addWidget(m_aircraft->triYawChannelBox);
addWidget(m_aircraft->aircraftType);
addWidget(m_aircraft->fwEngineChannelBox);
addWidget(m_aircraft->fwAileron1ChannelBox);
addWidget(m_aircraft->fwAileron2ChannelBox);
addWidget(m_aircraft->fwElevator1ChannelBox);
addWidget(m_aircraft->fwElevator2ChannelBox);
addWidget(m_aircraft->fwRudder1ChannelBox);
addWidget(m_aircraft->fwRudder2ChannelBox);
addWidget(m_aircraft->elevonSlider1);
addWidget(m_aircraft->elevonSlider2);
addWidget(m_heli->m_ccpm->ccpmType);
addWidget(m_heli->m_ccpm->ccpmTailChannel);
addWidget(m_heli->m_ccpm->ccpmEngineChannel);
addWidget(m_heli->m_ccpm->ccpmServoWChannel);
addWidget(m_heli->m_ccpm->ccpmServoXChannel);
addWidget(m_heli->m_ccpm->ccpmServoYChannel);
addWidget(m_heli->m_ccpm->ccpmSingleServo);
addWidget(m_heli->m_ccpm->ccpmServoZChannel);
addWidget(m_heli->m_ccpm->ccpmAngleW);
addWidget(m_heli->m_ccpm->ccpmAngleX);
addWidget(m_heli->m_ccpm->ccpmCorrectionAngle);
addWidget(m_heli->m_ccpm->ccpmAngleZ);
addWidget(m_heli->m_ccpm->ccpmAngleY);
addWidget(m_heli->m_ccpm->ccpmCollectivePassthrough);
addWidget(m_heli->m_ccpm->ccpmLinkRoll);
addWidget(m_heli->m_ccpm->ccpmLinkCyclic);
addWidget(m_heli->m_ccpm->ccpmRevoSlider);
addWidget(m_heli->m_ccpm->ccpmREVOspinBox);
addWidget(m_heli->m_ccpm->ccpmCollectiveSlider);
addWidget(m_heli->m_ccpm->ccpmCollectivespinBox);
addWidget(m_heli->m_ccpm->ccpmCollectiveScale);
addWidget(m_heli->m_ccpm->ccpmCollectiveScaleBox);
addWidget(m_heli->m_ccpm->ccpmCyclicScale);
addWidget(m_heli->m_ccpm->ccpmPitchScale);
addWidget(m_heli->m_ccpm->ccpmPitchScaleBox);
addWidget(m_heli->m_ccpm->ccpmRollScale);
addWidget(m_heli->m_ccpm->ccpmRollScaleBox);
addWidget(m_heli->m_ccpm->SwashLvlPositionSlider);
addWidget(m_heli->m_ccpm->SwashLvlPositionSpinBox);
addWidget(m_heli->m_ccpm->ThrottleCurve->getCurveWidget());
addWidget(m_heli->m_ccpm->PitchCurve->getCurveWidget());
addWidget(m_heli->m_ccpm->ccpmAdvancedSettingsTable);
}

View File

@ -28,98 +28,69 @@
#define CONFIGVEHICLETYPEWIDGET_H #define CONFIGVEHICLETYPEWIDGET_H
#include "ui_airframe.h" #include "ui_airframe.h"
#include "../uavobjectwidgetutils/configtaskwidget.h"
#include "extensionsystem/pluginmanager.h"
#include "uavobjectmanager.h"
#include "uavobject.h"
#include "uavtalk/telemetrymanager.h"
#include "cfg_vehicletypes/configccpmwidget.h"
#include "cfg_vehicletypes/configfixedwingwidget.h"
#include "cfg_vehicletypes/configmultirotorwidget.h"
#include "cfg_vehicletypes/configgroundvehiclewidget.h"
#include "cfg_vehicletypes/vehicleconfig.h" #include "cfg_vehicletypes/vehicleconfig.h"
#include "uavobject.h"
#include "../uavobjectwidgetutils/configtaskwidget.h"
#include <QtGui/QWidget> #include <QComboBox>
#include <QList> #include <QMap>
#include <QItemDelegate> #include <QString>
#include <QStringList>
class Ui_Widget; #include <QWidget>
/*
* This class derives from ConfigTaskWidget and overrides its default "binding" mechanism.
* This widget bypasses automatic synchronization of UAVObjects and UI by providing its own implementations of
* virtual void refreshWidgetsValues(UAVObject *obj = NULL);
* virtual void updateObjectsFromWidgets();
*
* It does use the "dirty" state management and registers its relevant widgets with ConfigTaskWidget to do so.
*
* This class also manages child ConfigTaskWidget : see VehicleConfig class and its derived classes.
* Note: for "dirty" state management it is important to register the fields of child widgets with the parent
* ConfigVehicleTypeWidget class.
*
* TODO consider to call "super" to benefit from default logic...
* TODO improve handling of relationship with VehicleConfig derived classes (i.e. ConfigTaskWidget within ConfigTaskWidget)
*/
class ConfigVehicleTypeWidget: public ConfigTaskWidget class ConfigVehicleTypeWidget: public ConfigTaskWidget
{ {
Q_OBJECT Q_OBJECT
public: public:
static QStringList getChannelDescriptions();
static void setComboCurrentIndex(QComboBox *box, int index);
ConfigVehicleTypeWidget(QWidget *parent = 0); ConfigVehicleTypeWidget(QWidget *parent = 0);
~ConfigVehicleTypeWidget(); ~ConfigVehicleTypeWidget();
static QStringList getChannelDescriptions(); protected slots:
virtual void refreshWidgetsValues(UAVObject *o = NULL);
virtual void updateObjectsFromWidgets();
private: private:
Ui_AircraftWidget *m_aircraft; Ui_AircraftWidget *m_aircraft;
ConfigCcpmWidget *m_heli; // Maps a frame category to its index in the m_aircraft->airframesWidget QStackedWidget
ConfigFixedWingWidget *m_fixedwing; QMap<QString, int> vehicleIndexMap;
ConfigMultiRotorWidget *m_multirotor;
ConfigGroundVehicleWidget *m_groundvehicle;
void updateCustomAirframeUI(); QString frameCategory(QString frameType);
void addToDirtyMonitor();
void resetField(UAVObjectField * field);
//void setMixerChannel(int channelNumber, bool channelIsMotor, QList<double> vector); VehicleConfig *getVehicleConfigWidget(QString frameCategory);
VehicleConfig *createVehicleConfigWidget(QString frameCategory);
QStringList channelNames; // Feed Forward
QStringList mixerTypes; void updateFeedForwardUI();
QStringList mixerVectors;
QGraphicsSvgItem *quad;
bool ffTuningInProgress; bool ffTuningInProgress;
bool ffTuningPhase; bool ffTuningPhase;
UAVObject::Metadata accInitialData; UAVObject::Metadata accInitialData;
private slots: private slots:
virtual void refreshWidgetsValues(UAVObject * o=NULL);
virtual void updateObjectsFromWidgets();
void setComboCurrentIndex(QComboBox* box, int index);
void setupAirframeUI(QString type);
void toggleAileron2(int index);
void toggleElevator2(int index);
void toggleRudder2(int index);
void switchAirframeType(int index); void switchAirframeType(int index);
void enableFFTest();
void openHelp(); void openHelp();
void reverseMultirotorMotor(); void enableFFTest();
protected:
void showEvent(QShowEvent *event);
void resizeEvent(QResizeEvent *event);
};
class SpinBoxDelegate : public QItemDelegate
{
Q_OBJECT
public:
SpinBoxDelegate(QObject *parent = 0);
QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option,
const QModelIndex &index) const;
void setEditorData(QWidget *editor, const QModelIndex &index) const;
void setModelData(QWidget *editor, QAbstractItemModel *model,
const QModelIndex &index) const;
void updateEditorGeometry(QWidget *editor,
const QStyleOptionViewItem &option, const QModelIndex &index) const;
}; };
#endif // CONFIGVEHICLETYPEWIDGET_H #endif // CONFIGVEHICLETYPEWIDGET_H

View File

@ -39,74 +39,74 @@
****************************************************************************/ ****************************************************************************/
import QtQuick 1.1 import QtQuick 1.1
import QtWebKit 1.0
// This is a tabbed pane element. Add a nested Rectangle to add a tab. // This is a tabbed pane element. Add a nested Rectangle to add a tab.
TabWidget { TabWidget {
// Define AuthorsModel as type // Define AuthorsModel as type
property AuthorsModel authors: AuthorsModel {} property AuthorsModel authors: AuthorsModel {}
id: tabs id: tabs
width: 640; height: 480 width: 640; height: 480
// This tab is for the GCS version information // This tab is for the GCS version information
Rectangle { Rectangle {
property string title: "OpenPilot GCS" property string title: "OpenPilot GCS"
anchors.fill: parent anchors.fill: parent
color: "#e3e3e3" color: "#e3e3e3"
Rectangle { Rectangle {
anchors.fill: parent; anchors.margins: 20 anchors.fill: parent; anchors.margins: 20
color: "#e3e3e3" color: "#e3e3e3"
Image { Image {
source: "../images/openpilot_logo_128.png" source: "../images/openpilot_logo_128.png"
x: 0; y: 0; z: 100 x: 0; y: 0; z: 100
fillMode: Image.PreserveAspectFit fillMode: Image.PreserveAspectFit
} }
Flickable { Flickable {
anchors.fill: parent anchors.fill: parent
anchors.centerIn: parent anchors.centerIn: parent
Text { Text {
id: versionLabel id: versionLabel
x: 156; y: 0 x: 156; y: 0
width: 430; height: 379 width: 430; height: 379
horizontalAlignment: Qt.AlignLeft horizontalAlignment: Qt.AlignLeft
font.pixelSize: 12 font.pixelSize: 12
wrapMode: Text.WordWrap wrapMode: Text.WordWrap
// @var version exposed in authorsdialog.cpp // @var version exposed in authorsdialog.cpp
text: version text: version
} }
}
}
}
// This tab is for the authors/contributors/credits
Rectangle {
property string title: "Authors"
anchors.fill: parent; color: "#e3e3e3"
Rectangle {
anchors.fill: parent; anchors.margins: 20
color: "#e3e3e3"
Text {
id: description
text: "<h4>These people have been key contributors to the OpenPilot project. Without the work of the people in this list, OpenPilot would not be what it is today.</h4><p>This list is sorted alphabetically by name</p>"
width: 600
wrapMode: Text.WordWrap
}
ListView {
id: authorsView
y: description.y + description.height + 20
width: parent.width; height: parent.height - description.height - 20
spacing: 3
model: authors
delegate: Text {
text: name
} }
clip: true
}
ScrollDecorator {
flickableItem: authorsView
} }
} }
} // This tab is for the authors/contributors/credits
Rectangle {
property string title: "Authors"
anchors.fill: parent; color: "#e3e3e3"
Rectangle {
anchors.fill: parent; anchors.margins: 20
color: "#e3e3e3"
Text {
id: description
text: "<h4>These people have been key contributors to the OpenPilot project. Without the work of the people in this list, OpenPilot would not be what it is today.</h4><p>This list is sorted alphabetically by name</p>"
width: 600
wrapMode: Text.WordWrap
}
ListView {
id: authorsView
y: description.y + description.height + 20
width: parent.width; height: parent.height - description.height - 20
spacing: 3
model: authors
delegate: Text {
text: name
}
clip: true
}
ScrollDecorator {
flickableItem: authorsView
}
}
}
} }

View File

@ -14,7 +14,7 @@
height="253" height="253"
id="svg2" id="svg2"
version="1.1" version="1.1"
inkscape:version="0.48.2 r9819" inkscape:version="0.48.4 r9939"
sodipodi:docname="curve-bg.svg"> sodipodi:docname="curve-bg.svg">
<defs <defs
id="defs4"> id="defs4">
@ -55,15 +55,15 @@
inkscape:pageopacity="0.0" inkscape:pageopacity="0.0"
inkscape:pageshadow="2" inkscape:pageshadow="2"
inkscape:zoom="1.9966906" inkscape:zoom="1.9966906"
inkscape:cx="181.06787" inkscape:cx="102.93859"
inkscape:cy="89.329853" inkscape:cy="89.329853"
inkscape:document-units="px" inkscape:document-units="px"
inkscape:current-layer="layer1" inkscape:current-layer="layer1"
showgrid="false" showgrid="false"
inkscape:window-width="1440" inkscape:window-width="1440"
inkscape:window-height="878" inkscape:window-height="878"
inkscape:window-x="1695" inkscape:window-x="148"
inkscape:window-y="97" inkscape:window-y="40"
inkscape:window-maximized="0" /> inkscape:window-maximized="0" />
<metadata <metadata
id="metadata7"> id="metadata7">
@ -101,49 +101,49 @@
<path <path
id="path3594" id="path3594"
d="m 175.95412,348.09206 248.91774,0" d="m 175.95412,348.09206 248.91774,0"
style="fill:none;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:5.30000019;stroke-opacity:0.28888890000000000;stroke-dasharray:0.5,0.5;stroke-dashoffset:3.7" /> style="fill:none;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:5.30000019;stroke-opacity:0.28888890000000000;stroke-dasharray:none;stroke-dashoffset:3.70000000000000020" />
<path <path
style="fill:none;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:5.30000019;stroke-opacity:0.28888890000000000;stroke-dasharray:0.5,0.5;stroke-dashoffset:3.7" style="fill:none;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:5.30000019;stroke-opacity:0.28888890000000000;stroke-dasharray:none;stroke-dashoffset:3.70000000000000020"
d="m 175.95412,317.09206 248.91774,0" d="m 175.95412,317.09206 248.91774,0"
id="path3596" /> id="path3596" />
<path <path
id="path3598" id="path3598"
d="m 175.95412,286.09206 248.91774,0" d="m 175.95412,286.09206 248.91774,0"
style="fill:none;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:5.30000019;stroke-opacity:0.28888890000000000;stroke-dasharray:0.5,0.5;stroke-dashoffset:3.7" /> style="fill:none;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:5.30000019;stroke-opacity:0.28888890000000000;stroke-dasharray:none;stroke-dashoffset:3.70000000000000020" />
<path <path
style="fill:none;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:5.30000019;stroke-opacity:0.28888890000000000;stroke-dasharray:0.5,0.5;stroke-dashoffset:3.7;marker-start:none" style="fill:none;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:5.30000019;stroke-opacity:0.28888890000000000;stroke-dasharray:none;stroke-dashoffset:3.70000000000000020;marker-start:none"
d="m 175.95412,410.09206 248.91774,0" d="m 175.95412,410.09206 248.91774,0"
id="path3600" /> id="path3600" />
<path <path
id="path3602" id="path3602"
d="m 175.95412,441.09206 248.91774,0" d="m 175.95412,441.09206 248.91774,0"
style="fill:none;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:5.30000019;stroke-opacity:0.28888890000000000;stroke-dasharray:0.5,0.5;stroke-dashoffset:3.7;marker-start:none" /> style="fill:none;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:5.30000019;stroke-opacity:0.28888890000000000;stroke-dasharray:none;stroke-dashoffset:3.70000000000000020;marker-start:none" />
<path <path
style="fill:none;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:5.30000019;stroke-opacity:0.28888890000000000;stroke-dasharray:0.5,0.5;stroke-dashoffset:3.7;marker-start:none" style="fill:none;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:5.30000019;stroke-opacity:0.28888890000000000;stroke-dasharray:none;stroke-dashoffset:3.70000000000000020;marker-start:none"
d="m 175.95412,472.09206 248.91774,0" d="m 175.95412,472.09206 248.91774,0"
id="path3604" /> id="path3604" />
<path <path
style="fill:none;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:0.28888890000000000;stroke-miterlimit:5.30000019;stroke-dasharray:0.5,0.5;stroke-dashoffset:3.7" style="fill:none;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:0.28888890000000000;stroke-miterlimit:5.30000019;stroke-dasharray:none;stroke-dashoffset:3.70000000000000020"
d="m 269.41299,254.63319 0,248.91774" d="m 269.41299,254.63319 0,248.91774"
id="path3792" /> id="path3792" />
<path <path
id="path3794" id="path3794"
d="m 238.41299,254.63319 0,248.91774" d="m 238.41299,254.63319 0,248.91774"
style="fill:none;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:0.28888890000000000;stroke-miterlimit:5.30000019;stroke-dasharray:0.5,0.5;stroke-dashoffset:3.7" /> style="fill:none;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:0.28888890000000000;stroke-miterlimit:5.30000019;stroke-dasharray:none;stroke-dashoffset:3.70000000000000020" />
<path <path
style="fill:none;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:0.28888890000000000;stroke-miterlimit:5.30000019;stroke-dasharray:0.5,0.5;stroke-dashoffset:3.7" style="fill:none;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:0.28888890000000000;stroke-miterlimit:5.30000019;stroke-dasharray:none;stroke-dashoffset:3.70000000000000020"
d="m 207.41299,254.63319 0,248.91774" d="m 207.41299,254.63319 0,248.91774"
id="path3796" /> id="path3796" />
<path <path
style="fill:none;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:0.28888890000000000;stroke-miterlimit:5.30000019;stroke-dasharray:0.5,0.5;stroke-dashoffset:3.7" style="fill:none;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:0.28888890000000000;stroke-miterlimit:5.30000019;stroke-dasharray:none;stroke-dashoffset:3.70000000000000020"
d="m 331.41299,254.63319 0,248.91774" d="m 331.41299,254.63319 0,248.91774"
id="path3800" /> id="path3800" />
<path <path
id="path3802" id="path3802"
d="m 362.41299,254.63319 0,248.91774" d="m 362.41299,254.63319 0,248.91774"
style="fill:none;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:0.28888890000000000;stroke-miterlimit:5.30000019;stroke-dasharray:0.5,0.5;stroke-dashoffset:3.7" /> style="fill:none;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:0.28888890000000000;stroke-miterlimit:5.30000019;stroke-dasharray:none;stroke-dashoffset:3.70000000000000020" />
<path <path
style="fill:none;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:0.28888890000000000;stroke-miterlimit:5.30000019;stroke-dasharray:0.5,0.5;stroke-dashoffset:3.7" style="fill:none;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:0.28888890000000000;stroke-miterlimit:5.30000019;stroke-dasharray:none;stroke-dashoffset:3.70000000000000020"
d="m 393.41299,254.63319 0,248.91774" d="m 393.41299,254.63319 0,248.91774"
id="path3804" /> id="path3804" />
</g> </g>

Before

Width:  |  Height:  |  Size: 6.7 KiB

After

Width:  |  Height:  |  Size: 6.9 KiB

View File

@ -64,7 +64,7 @@ MixerCurveWidget::MixerCurveWidget(QWidget *parent) : QGraphicsView(parent)
QGraphicsScene *scene = new QGraphicsScene(this); QGraphicsScene *scene = new QGraphicsScene(this);
QSvgRenderer *renderer = new QSvgRenderer(); QSvgRenderer *renderer = new QSvgRenderer();
plot = new QGraphicsSvgItem(); plot = new QGraphicsSvgItem();
renderer->load(QString(":/configgadget/images/curve-bg.svg")); renderer->load(QString(":/uavobjectwidgetutils/images/curve-bg.svg"));
plot->setSharedRenderer(renderer); plot->setSharedRenderer(renderer);
//plot->setElementId("map"); //plot->setElementId("map");
scene->addItem(plot); scene->addItem(plot);

View File

@ -2,16 +2,19 @@ TEMPLATE = lib
TARGET = UAVObjectWidgetUtils TARGET = UAVObjectWidgetUtils
DEFINES += UAVOBJECTWIDGETUTILS_LIBRARY DEFINES += UAVOBJECTWIDGETUTILS_LIBRARY
QT += svg QT += svg
include(../../openpilotgcsplugin.pri) include(../../openpilotgcsplugin.pri)
include(uavobjectwidgetutils_dependencies.pri) include(uavobjectwidgetutils_dependencies.pri)
HEADERS += uavobjectwidgetutils_global.h \ HEADERS += uavobjectwidgetutils_global.h \
uavobjectwidgetutilsplugin.h \ uavobjectwidgetutilsplugin.h \
configtaskwidget.h \ configtaskwidget.h \
mixercurvewidget.h \ mixercurvewidget.h \
mixercurvepoint.h \ mixercurvepoint.h \
mixercurveline.h \ mixercurveline.h \
smartsavebutton.h \ smartsavebutton.h \
popupwidget.h popupwidget.h
SOURCES += uavobjectwidgetutilsplugin.cpp \ SOURCES += uavobjectwidgetutilsplugin.cpp \
configtaskwidget.cpp \ configtaskwidget.cpp \
mixercurvewidget.cpp \ mixercurvewidget.cpp \
@ -20,6 +23,7 @@ SOURCES += uavobjectwidgetutilsplugin.cpp \
smartsavebutton.cpp \ smartsavebutton.cpp \
popupwidget.cpp popupwidget.cpp
RESOURCES += uavobjectwidgetutils.qrc
OTHER_FILES += UAVObjectWidgetUtils.pluginspec OTHER_FILES += UAVObjectWidgetUtils.pluginspec

View File

@ -0,0 +1,5 @@
<RCC>
<qresource prefix="/uavobjectwidgetutils">
<file>images/curve-bg.svg</file>
</qresource>
</RCC>