1
0
mirror of https://bitbucket.org/librepilot/librepilot.git synced 2024-11-29 07:24:13 +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">
<number>12</number>
</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>
<widget class="QTabWidget" name="tabWidget">
<property name="currentIndex">
<number>0</number>
</property>
<widget class="QWidget" name="tabWidgetPage1">
<widget class="QWidget" name="mixerSettingsPage">
<property name="autoFillBackground">
<bool>true</bool>
</property>
<attribute name="title">
<string>Mixer Settings</string>
</attribute>
<layout class="QGridLayout" name="gridLayout_9">
<property name="horizontalSpacing">
<number>0</number>
</property>
<layout class="QVBoxLayout" name="verticalLayout_3">
<property name="margin">
<number>0</number>
<number>9</number>
</property>
<item row="0" column="0">
<widget class="QScrollArea" name="scrollArea">
<item>
<widget class="QScrollArea" name="airframesScrollArea">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
@ -128,75 +197,14 @@
<rect>
<x>0</x>
<y>0</y>
<width>852</width>
<height>518</height>
<width>832</width>
<height>461</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<property name="margin">
<number>12</number>
<number>0</number>
</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>
<widget class="QStackedWidget" name="airframesWidget">
<property name="sizePolicy">
@ -215,2639 +223,8 @@
<enum>QFrame::NoFrame</enum>
</property>
<property name="currentIndex">
<number>4</number>
<number>-1</number>
</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>
</item>
</layout>
@ -2856,7 +233,7 @@ margin:1px;</string>
</item>
</layout>
</widget>
<widget class="QWidget" name="tab">
<widget class="QWidget" name="feedForwardPage">
<property name="autoFillBackground">
<bool>true</bool>
</property>
@ -2950,8 +327,8 @@ margin:1px;</string>
<rect>
<x>0</x>
<y>0</y>
<width>852</width>
<height>518</height>
<width>223</width>
<height>269</height>
</rect>
</property>
<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;
&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; }
&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;tr&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 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; 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 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-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-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: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>
@ -3355,7 +733,7 @@ p, li { white-space: pre-wrap; }
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<layout class="QHBoxLayout" name="bottomLayout">
<property name="spacing">
<number>4</number>
</property>
@ -3431,20 +809,6 @@ p, li { white-space: pre-wrap; }
</item>
</layout>
</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>
<include location="../coreplugin/core.qrc"/>
</resources>
@ -3481,117 +845,5 @@ p, li { white-space: pre-wrap; }
</hint>
</hints>
</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>
</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
*/
#include "configccpmwidget.h"
#include "mixersettings.h"
#include "systemsettings.h"
#include "actuatorcommand.h"
#include <QDebug>
#include <QStringList>
@ -33,52 +36,122 @@
#include <QtGui/QVBoxLayout>
#include <QtGui/QPushButton>
#include <QBrush>
#include <math.h>
#include <QMessageBox>
#include "mixersettings.h"
#include "systemsettings.h"
#include "actuatorcommand.h"
#include <math.h>
#define Pi 3.14159265358979323846
#define Pi 3.14159265358979323846
ConfigCcpmWidget::ConfigCcpmWidget(QWidget *parent) : VehicleConfig(parent)
QStringList ConfigCcpmWidget::getChannelDescriptions()
{
int i;
SwashLvlConfigurationInProgress=0;
SwashLvlState=0;
SwashLvlServoInterlock=0;
updatingFromHardware=FALSE;
updatingToHardware=FALSE;
// init a channel_numelem list of channel desc defaults
QStringList channelDesc;
for (int i = 0; i < (int) ConfigCcpmWidget::CHANNEL_NUMELEM; i++) {
channelDesc.append(QString("-"));
}
m_ccpm = new Ui_ccpmWidget();
m_ccpm->setupUi(this);
// get the gui config data
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
m_ccpm->SwashplateImage->setScene(new QGraphicsScene(this));
m_aircraft->SwashplateImage->setScene(new QGraphicsScene(this));
m_ccpm->SwashLvlSwashplateImage->setScene(m_ccpm->SwashplateImage->scene());
m_ccpm->SwashLvlSwashplateImage->setSceneRect(-50,-50,500,500);
//m_ccpm->SwashLvlSwashplateImage->scale(.85,.85);
m_aircraft->SwashLvlSwashplateImage->setScene(m_aircraft->SwashplateImage->scene());
m_aircraft->SwashLvlSwashplateImage->setSceneRect(-50, -50, 500, 500);
//m_aircraft->SwashLvlSwashplateImage->scale(.85,.85);
//m_ccpm->SwashplateImage->setSceneRect(SwashplateImg->boundingRect());
m_ccpm->SwashplateImage->setSceneRect(-50,-30,500,500);
//m_ccpm->SwashplateImage->scale(.85,.85);
//m_aircraft->SwashplateImage->setSceneRect(SwashplateImg->boundingRect());
m_aircraft->SwashplateImage->setSceneRect(-50, -30, 500, 500);
//m_aircraft->SwashplateImage->scale(.85,.85);
QSvgRenderer *renderer = new QSvgRenderer();
renderer->load(QString(":/configgadget/images/ccpm_setup.svg"));
SwashplateImg = new QGraphicsSvgItem();
SwashplateImg->setSharedRenderer(renderer);
SwashplateImg->setElementId("Swashplate");
SwashplateImg->setObjectName("Swashplate");
//SwashplateImg->setScale(0.75);
m_ccpm->SwashplateImage->scene()->addItem(SwashplateImg);
m_aircraft->SwashplateImage->scene()->addItem(SwashplateImg);
QFont serifFont("Times", 24, QFont::Bold);
QPen pen; // creates a default pen
// creates a default pen
QPen pen;
pen.setStyle(Qt::DotLine);
pen.setWidth(2);
@ -86,123 +159,117 @@ ConfigCcpmWidget::ConfigCcpmWidget(QWidget *parent) : VehicleConfig(parent)
pen.setCapStyle(Qt::RoundCap);
pen.setJoinStyle(Qt::RoundJoin);
QBrush brush(Qt::darkBlue);
QPen pen2; // creates a default pen
// creates a default pen
QPen pen2;
//pen2.setStyle(Qt::DotLine);
pen2.setWidth(1);
pen2.setBrush(Qt::blue);
//pen2.setCapStyle(Qt::RoundCap);
//pen2.setJoinStyle(Qt::RoundJoin);
//brush.setStyle(Qt::RadialGradientPattern);
QList<QString> ServoNames;
ServoNames << "ServoW" << "ServoX" << "ServoY" << "ServoZ" ;
for (i=0;i<CCPM_MAX_SWASH_SERVOS;i++)
{
ServoLines[i] = m_ccpm->SwashLvlSwashplateImage->scene()->addLine(0,0,100*i,i*i*100,pen);
//brush.setStyle(Qt::RadialGradientPattern);
QList<QString> ServoNames;
ServoNames << "ServoW" << "ServoX" << "ServoY" << "ServoZ";
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);
Servos[i] = new QGraphicsSvgItem();
Servos[i]->setSharedRenderer(renderer);
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]->setDefaultTextColor(Qt::yellow);
ServosText[i]->setPlainText(QString("-"));
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]->setPen(pen2);
m_ccpm->SwashplateImage->scene()->addItem(ServosTextCircles[i]);
m_ccpm->SwashplateImage->scene()->addItem(ServosText[i]);
m_aircraft->SwashplateImage->scene()->addItem(ServosTextCircles[i]);
m_aircraft->SwashplateImage->scene()->addItem(ServosText[i]);
SwashLvlSpinBoxes[i] = new QSpinBox(m_ccpm->SwashLvlSwashplateImage); // use QGraphicsView
m_ccpm->SwashLvlSwashplateImage->scene()->addWidget(SwashLvlSpinBoxes[i]);
SwashLvlSpinBoxes[i] = new QSpinBox(m_aircraft->SwashLvlSwashplateImage); // use QGraphicsView
m_aircraft->SwashLvlSwashplateImage->scene()->addWidget(SwashLvlSpinBoxes[i]);
SwashLvlSpinBoxes[i]->setMaximum(10000);
SwashLvlSpinBoxes[i]->setMinimum(0);
SwashLvlSpinBoxes[i]->setValue(0);
}
//initialize our two mixer curves
// initialize our two mixer curves
// 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
m_ccpm->PitchCurve->setMixerType(MixerCurve::MIXERCURVE_PITCH);
m_ccpm->PitchCurve->initLinearCurve(5, 1.0, -1.0);
m_aircraft->PitchCurve->setMixerType(MixerCurve::MIXERCURVE_PITCH);
m_aircraft->PitchCurve->initLinearCurve(5, 1.0, -1.0);
//initialize channel names
m_ccpm->ccpmEngineChannel->addItems(channelNames);
m_ccpm->ccpmEngineChannel->setCurrentIndex(0);
m_ccpm->ccpmTailChannel->addItems(channelNames);
m_ccpm->ccpmTailChannel->setCurrentIndex(0);
m_ccpm->ccpmServoWChannel->addItems(channelNames);
m_ccpm->ccpmServoWChannel->setCurrentIndex(0);
m_ccpm->ccpmServoXChannel->addItems(channelNames);
m_ccpm->ccpmServoXChannel->setCurrentIndex(0);
m_ccpm->ccpmServoYChannel->addItems(channelNames);
m_ccpm->ccpmServoYChannel->setCurrentIndex(0);
m_ccpm->ccpmServoZChannel->addItems(channelNames);
m_ccpm->ccpmServoZChannel->setCurrentIndex(0);
// initialize channel names
m_aircraft->ccpmEngineChannel->addItems(channelNames);
m_aircraft->ccpmEngineChannel->setCurrentIndex(0);
m_aircraft->ccpmTailChannel->addItems(channelNames);
m_aircraft->ccpmTailChannel->setCurrentIndex(0);
m_aircraft->ccpmServoWChannel->addItems(channelNames);
m_aircraft->ccpmServoWChannel->setCurrentIndex(0);
m_aircraft->ccpmServoXChannel->addItems(channelNames);
m_aircraft->ccpmServoXChannel->setCurrentIndex(0);
m_aircraft->ccpmServoYChannel->addItems(channelNames);
m_aircraft->ccpmServoYChannel->setCurrentIndex(0);
m_aircraft->ccpmServoZChannel->addItems(channelNames);
m_aircraft->ccpmServoZChannel->setCurrentIndex(0);
QStringList Types;
Types << QString::fromUtf8("CCPM 2 Servo 90º") << QString::fromUtf8("CCPM 3 Servo 90º") << QString::fromUtf8("CCPM 4 Servo 90º") <<
QString::fromUtf8("CCPM 3 Servo 120º") << QString::fromUtf8("CCPM 3 Servo 140º") <<
QString::fromUtf8("FP 2 Servo 90º") <<
QString::fromUtf8("Coax 2 Servo 90º") <<
QString::fromUtf8("Custom - User Angles") << QString::fromUtf8("Custom - Advanced Settings");
m_ccpm->ccpmType->addItems(Types);
m_ccpm->ccpmType->setCurrentIndex(m_ccpm->ccpmType->count() - 1);
Types << QString::fromUtf8("CCPM 2 Servo 90º") << QString::fromUtf8("CCPM 3 Servo 90º")
<< QString::fromUtf8("CCPM 4 Servo 90º") << QString::fromUtf8("CCPM 3 Servo 120º")
<< QString::fromUtf8("CCPM 3 Servo 140º") << QString::fromUtf8("FP 2 Servo 90º")
<< QString::fromUtf8("Coax 2 Servo 90º") << QString::fromUtf8("Custom - User Angles")
<< QString::fromUtf8("Custom - Advanced Settings");
m_aircraft->ccpmType->addItems(Types);
m_aircraft->ccpmType->setCurrentIndex(m_aircraft->ccpmType->count() - 1);
refreshWidgetsValues(QString("HeliCP"));
//refreshWidgetsValues(QString("HeliCP"));
UpdateType();
connect(m_ccpm->ccpmAngleW, SIGNAL(valueChanged(double)), this, SLOT(ccpmSwashplateUpdate()));
connect(m_ccpm->ccpmAngleX, SIGNAL(valueChanged(double)), this, SLOT(ccpmSwashplateUpdate()));
connect(m_ccpm->ccpmAngleY, SIGNAL(valueChanged(double)), this, SLOT(ccpmSwashplateUpdate()));
connect(m_ccpm->ccpmAngleZ, SIGNAL(valueChanged(double)), this, SLOT(ccpmSwashplateUpdate()));
connect(m_ccpm->ccpmCorrectionAngle, SIGNAL(valueChanged(double)), this, SLOT(ccpmSwashplateUpdate()));
connect(m_ccpm->ccpmServoWChannel, SIGNAL(currentIndexChanged(int)), this, SLOT(ccpmSwashplateUpdate()));
connect(m_ccpm->ccpmServoXChannel, SIGNAL(currentIndexChanged(int)), this, SLOT(ccpmSwashplateUpdate()));
connect(m_ccpm->ccpmServoYChannel, SIGNAL(currentIndexChanged(int)), this, SLOT(ccpmSwashplateUpdate()));
connect(m_ccpm->ccpmServoZChannel, SIGNAL(currentIndexChanged(int)), this, SLOT(ccpmSwashplateUpdate()));
connect(m_ccpm->ccpmEngineChannel, SIGNAL(currentIndexChanged(int)), this, SLOT(UpdateMixer()));
connect(m_ccpm->ccpmTailChannel, SIGNAL(currentIndexChanged(int)), this, SLOT(UpdateMixer()));
connect(m_ccpm->ccpmRevoSlider, SIGNAL(valueChanged(int)), this, SLOT(UpdateMixer()));
connect(m_ccpm->ccpmREVOspinBox, SIGNAL(valueChanged(int)), this, SLOT(UpdateMixer()));
connect(m_ccpm->ccpmCollectiveSlider, SIGNAL(valueChanged(int)), this, SLOT(UpdateMixer()));
connect(m_ccpm->ccpmCollectivespinBox, SIGNAL(valueChanged(int)), this, SLOT(UpdateMixer()));
connect(m_ccpm->ccpmType, SIGNAL(currentIndexChanged(int)), this, SLOT(UpdateType()));
connect(m_ccpm->ccpmSingleServo, SIGNAL(currentIndexChanged(int)), this, SLOT(UpdateType()));
connect(m_ccpm->TabObject, SIGNAL(currentChanged ( QWidget * )), this, SLOT(UpdateType()));
connect(m_aircraft->ccpmAngleW, SIGNAL(valueChanged(double)), this, SLOT(ccpmSwashplateUpdate()));
connect(m_aircraft->ccpmAngleX, SIGNAL(valueChanged(double)), this, SLOT(ccpmSwashplateUpdate()));
connect(m_aircraft->ccpmAngleY, SIGNAL(valueChanged(double)), this, SLOT(ccpmSwashplateUpdate()));
connect(m_aircraft->ccpmAngleZ, SIGNAL(valueChanged(double)), this, SLOT(ccpmSwashplateUpdate()));
connect(m_aircraft->ccpmCorrectionAngle, SIGNAL(valueChanged(double)), this, SLOT(ccpmSwashplateUpdate()));
connect(m_aircraft->ccpmServoWChannel, SIGNAL(currentIndexChanged(int)), this, SLOT(ccpmSwashplateUpdate()));
connect(m_aircraft->ccpmServoXChannel, SIGNAL(currentIndexChanged(int)), this, SLOT(ccpmSwashplateUpdate()));
connect(m_aircraft->ccpmServoYChannel, SIGNAL(currentIndexChanged(int)), this, SLOT(ccpmSwashplateUpdate()));
connect(m_aircraft->ccpmServoZChannel, SIGNAL(currentIndexChanged(int)), this, SLOT(ccpmSwashplateUpdate()));
connect(m_aircraft->ccpmEngineChannel, SIGNAL(currentIndexChanged(int)), this, SLOT(UpdateMixer()));
connect(m_aircraft->ccpmTailChannel, SIGNAL(currentIndexChanged(int)), this, SLOT(UpdateMixer()));
connect(m_aircraft->ccpmRevoSlider, SIGNAL(valueChanged(int)), this, SLOT(UpdateMixer()));
connect(m_aircraft->ccpmREVOspinBox, SIGNAL(valueChanged(int)), this, SLOT(UpdateMixer()));
connect(m_aircraft->ccpmCollectiveSlider, SIGNAL(valueChanged(int)), this, SLOT(UpdateMixer()));
connect(m_aircraft->ccpmCollectivespinBox, SIGNAL(valueChanged(int)), this, SLOT(UpdateMixer()));
connect(m_aircraft->ccpmType, SIGNAL(currentIndexChanged(int)), this, SLOT(UpdateType()));
connect(m_aircraft->ccpmSingleServo, SIGNAL(currentIndexChanged(int)), this, SLOT(UpdateType()));
connect(m_aircraft->TabObject, SIGNAL(currentChanged ( QWidget * )), this, SLOT(UpdateType()));
connect(m_ccpm->SwashLvlStartButton, SIGNAL(clicked()), this, SLOT(SwashLvlStartButtonPressed()));
connect(m_ccpm->SwashLvlNextButton, SIGNAL(clicked()), this, SLOT(SwashLvlNextButtonPressed()));
connect(m_ccpm->SwashLvlCancelButton, SIGNAL(clicked()), this, SLOT(SwashLvlCancelButtonPressed()));
connect(m_ccpm->SwashLvlFinishButton, SIGNAL(clicked()), this, SLOT(SwashLvlFinishButtonPressed()));
connect(m_aircraft->SwashLvlStartButton, SIGNAL(clicked()), this, SLOT(SwashLvlStartButtonPressed()));
connect(m_aircraft->SwashLvlNextButton, SIGNAL(clicked()), this, SLOT(SwashLvlNextButtonPressed()));
connect(m_aircraft->SwashLvlCancelButton, SIGNAL(clicked()), this, SLOT(SwashLvlCancelButtonPressed()));
connect(m_aircraft->SwashLvlFinishButton, SIGNAL(clicked()), this, SLOT(SwashLvlFinishButtonPressed()));
connect(m_ccpm->ccpmCollectivePassthrough, SIGNAL(clicked()),this, SLOT(SetUIComponentVisibilities()));
connect(m_ccpm->ccpmLinkCyclic, SIGNAL(clicked()), this, SLOT(SetUIComponentVisibilities()));
connect(m_ccpm->ccpmLinkRoll, SIGNAL(clicked()), this, SLOT(SetUIComponentVisibilities()));
connect(m_aircraft->ccpmCollectivePassthrough, SIGNAL(clicked()), this, SLOT(SetUIComponentVisibilities()));
connect(m_aircraft->ccpmLinkCyclic, SIGNAL(clicked()), this, SLOT(SetUIComponentVisibilities()));
connect(m_aircraft->ccpmLinkRoll, SIGNAL(clicked()), this, SLOT(SetUIComponentVisibilities()));
ccpmSwashplateRedraw();
ccpmSwashplateRedraw();
}
ConfigCcpmWidget::~ConfigCcpmWidget()
{
// Do nothing
delete m_aircraft;
}
void ConfigCcpmWidget::setupUI(QString frameType)
@ -210,7 +277,42 @@ void ConfigCcpmWidget::setupUI(QString 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.Tail = 0;
@ -220,260 +322,225 @@ void ConfigCcpmWidget::ResetActuators(GUIConfigDataUnion* configData)
configData->heli.ServoIndexZ = 0;
}
QStringList ConfigCcpmWidget::getChannelDescriptions()
void ConfigCcpmWidget::refreshWidgetsValues(QString frameType)
{
int i;
QStringList channelDesc;
Q_UNUSED(frameType);
// init a channel_numelem list of channel desc defaults
for (i=0; i < (int)(ConfigCcpmWidget::CHANNEL_NUMELEM); i++)
{
channelDesc.append(QString("-"));
}
setupUI(frameType);
// get the gui config data
GUIConfigDataUnion configData = GetConfigData();
heliGUISettingsStruct heli = configData.heli;
GUIConfigDataUnion config = getConfigData();
if (heli.Throttle > 0)
channelDesc[heli.Throttle - 1] = QString("Throttle");
if (heli.Tail > 0)
channelDesc[heli.Tail - 1] = QString("Tail");
// swashplate config
setComboCurrentIndex(m_aircraft->ccpmType, m_aircraft->ccpmType->count() - (config.heli.SwashplateType + 1));
setComboCurrentIndex(m_aircraft->ccpmSingleServo, config.heli.FirstServoIndex);
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;
// ccpm mixing options
m_aircraft->ccpmCollectivePassthrough->setChecked(config.heli.ccpmCollectivePassthroughState);
m_aircraft->ccpmLinkCyclic->setChecked(config.heli.ccpmLinkCyclicState);
m_aircraft->ccpmLinkRoll->setChecked(config.heli.ccpmLinkRollState);
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;
// correction angle
m_aircraft->ccpmCorrectionAngle->setValue(config.heli.CorrectionAngle);
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;
// update sliders
m_aircraft->ccpmCollectiveScale->setValue(config.heli.SliderValue0);
m_aircraft->ccpmCollectiveScaleBox->setValue(config.heli.SliderValue0);
m_aircraft->ccpmCyclicScale->setValue(config.heli.SliderValue1);
m_aircraft->ccpmCyclicScaleBox->setValue(config.heli.SliderValue1);
m_aircraft->ccpmPitchScale->setValue(config.heli.SliderValue1);
m_aircraft->ccpmPitchScaleBox->setValue(config.heli.SliderValue1);
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
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;
// servo assignments
setComboCurrentIndex(m_aircraft->ccpmServoWChannel, config.heli.ServoIndexW);
setComboCurrentIndex( m_aircraft->ccpmServoXChannel,config.heli.ServoIndexX);
setComboCurrentIndex( m_aircraft->ccpmServoYChannel,config.heli.ServoIndexY);
setComboCurrentIndex( m_aircraft->ccpmServoZChannel,config.heli.ServoIndexZ);
}
if (heli.ServoIndexZ > 0)
channelDesc[heli.ServoIndexZ - 1] = QString("ServoZ");
// throttle
setComboCurrentIndex( m_aircraft->ccpmEngineChannel, config.heli.Throttle);
// tail
setComboCurrentIndex( m_aircraft->ccpmTailChannel, config.heli.Tail);
return channelDesc;
getMixer();
}
QString ConfigCcpmWidget::updateConfigObjectsFromWidgets()
{
QString airframeType = updateConfigObjects();
setMixer();
return airframeType;
}
void ConfigCcpmWidget::UpdateType()
{
int TypeInt,SingleServoIndex,NumServosDefined;
double AdjustmentAngle=0;
int TypeInt, SingleServoIndex, NumServosDefined;
double AdjustmentAngle = 0;
SetUIComponentVisibilities();
TypeInt = m_ccpm->ccpmType->count() - m_ccpm->ccpmType->currentIndex()-1;
TypeText = m_ccpm->ccpmType->currentText();
SingleServoIndex = m_ccpm->ccpmSingleServo->currentIndex();
TypeInt = m_aircraft->ccpmType->count() - m_aircraft->ccpmType->currentIndex() - 1;
TypeText = m_aircraft->ccpmType->currentText();
SingleServoIndex = m_aircraft->ccpmSingleServo->currentIndex();
//set visibility of user settings
m_ccpm->ccpmAdvancedSettingsTable->setEnabled(TypeInt==0);
m_ccpm->ccpmAdvancedSettingsTable->clearFocus();;
m_aircraft->ccpmAdvancedSettingsTable->setEnabled(TypeInt == 0);
m_aircraft->ccpmAdvancedSettingsTable->clearFocus();
m_ccpm->ccpmAngleW->setEnabled(TypeInt==1);
m_ccpm->ccpmAngleX->setEnabled(TypeInt==1);
m_ccpm->ccpmAngleY->setEnabled(TypeInt==1);
m_ccpm->ccpmAngleZ->setEnabled(TypeInt==1);
m_ccpm->ccpmCorrectionAngle->setEnabled(TypeInt!=0);
m_aircraft->ccpmAngleW->setEnabled(TypeInt == 1);
m_aircraft->ccpmAngleX->setEnabled(TypeInt == 1);
m_aircraft->ccpmAngleY->setEnabled(TypeInt == 1);
m_aircraft->ccpmAngleZ->setEnabled(TypeInt == 1);
m_aircraft->ccpmCorrectionAngle->setEnabled(TypeInt != 0);
m_ccpm->ccpmServoWChannel->setEnabled(TypeInt>0);
m_ccpm->ccpmServoXChannel->setEnabled(TypeInt>0);
m_ccpm->ccpmServoYChannel->setEnabled(TypeInt>0);
m_ccpm->ccpmServoZChannel->setEnabled(TypeInt>0);
m_ccpm->ccpmSingleServo->setEnabled(TypeInt>1);
m_aircraft->ccpmServoWChannel->setEnabled(TypeInt > 0);
m_aircraft->ccpmServoXChannel->setEnabled(TypeInt > 0);
m_aircraft->ccpmServoYChannel->setEnabled(TypeInt > 0);
m_aircraft->ccpmServoZChannel->setEnabled(TypeInt > 0);
m_aircraft->ccpmSingleServo->setEnabled(TypeInt > 1);
m_ccpm->ccpmEngineChannel->setEnabled(TypeInt>0);
m_ccpm->ccpmTailChannel->setEnabled(TypeInt>0);
m_ccpm->ccpmCollectiveSlider->setEnabled(TypeInt>0);
m_ccpm->ccpmCollectivespinBox->setEnabled(TypeInt>0);
m_ccpm->ccpmRevoSlider->setEnabled(TypeInt>0);
m_ccpm->ccpmREVOspinBox->setEnabled(TypeInt>0);
m_aircraft->ccpmEngineChannel->setEnabled(TypeInt > 0);
m_aircraft->ccpmTailChannel->setEnabled(TypeInt > 0);
m_aircraft->ccpmCollectiveSlider->setEnabled(TypeInt > 0);
m_aircraft->ccpmCollectivespinBox->setEnabled(TypeInt > 0);
m_aircraft->ccpmRevoSlider->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
if (TypeText.compare(QString::fromUtf8("CCPM 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);
NumServosDefined=2;
if (TypeText.compare(QString::fromUtf8("CCPM 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);
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);
}
else if (TypeText.compare(QString::fromUtf8("CCPM 3 Servo 90º"), Qt::CaseInsensitive)==0)
{
m_ccpm->ccpmAngleW->setValue(AdjustmentAngle + 0);
m_ccpm->ccpmAngleX->setValue(fmod(AdjustmentAngle + 90,360));
m_ccpm->ccpmAngleY->setValue(fmod(AdjustmentAngle + 180,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 4 Servo 90º"), Qt::CaseInsensitive)==0)
{
m_ccpm->ccpmAngleW->setValue(AdjustmentAngle + 0);
m_ccpm->ccpmAngleX->setValue(fmod(AdjustmentAngle + 90,360));
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;
} else if (TypeText.compare(QString::fromUtf8("Coax 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);
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
if (TypeText.compare(QString::fromUtf8("Coax 2 Servo 90º"), Qt::CaseInsensitive)==0)
{
m_ccpm->ccpmEngineLabel->setText("CW motor");
m_ccpm->ccpmTailLabel->setText("CCW motor");
}
else{
m_ccpm->ccpmEngineLabel->setText("Engine");
m_ccpm->ccpmTailLabel->setText("Tail rotor");
if (TypeText.compare(QString::fromUtf8("Coax 2 Servo 90º"), Qt::CaseInsensitive) == 0) {
m_aircraft->ccpmEngineLabel->setText("CW motor");
m_aircraft->ccpmTailLabel->setText("CCW motor");
} else {
m_aircraft->ccpmEngineLabel->setText("Engine");
m_aircraft->ccpmTailLabel->setText("Tail rotor");
}
//set the visibility of the swashplate servo selection boxes
m_ccpm->ccpmServoWLabel->setVisible(NumServosDefined>=1);
m_ccpm->ccpmServoXLabel->setVisible(NumServosDefined>=2);
m_ccpm->ccpmServoYLabel->setVisible(NumServosDefined>=3);
m_ccpm->ccpmServoZLabel->setVisible(NumServosDefined>=4);
m_ccpm->ccpmServoWChannel->setVisible(NumServosDefined>=1);
m_ccpm->ccpmServoXChannel->setVisible(NumServosDefined>=2);
m_ccpm->ccpmServoYChannel->setVisible(NumServosDefined>=3);
m_ccpm->ccpmServoZChannel->setVisible(NumServosDefined>=4);
//set the visibility of the swashplate angle selection boxes
m_ccpm->ccpmServoWLabel_2->setVisible(NumServosDefined>=1);
m_ccpm->ccpmServoXLabel_2->setVisible(NumServosDefined>=2);
m_ccpm->ccpmServoYLabel_2->setVisible(NumServosDefined>=3);
m_ccpm->ccpmServoZLabel_2->setVisible(NumServosDefined>=4);
m_ccpm->ccpmAngleW->setVisible(NumServosDefined>=1);
m_ccpm->ccpmAngleX->setVisible(NumServosDefined>=2);
m_ccpm->ccpmAngleY->setVisible(NumServosDefined>=3);
m_ccpm->ccpmAngleZ->setVisible(NumServosDefined>=4);
m_aircraft->ccpmServoWLabel->setVisible(NumServosDefined >= 1);
m_aircraft->ccpmServoXLabel->setVisible(NumServosDefined >= 2);
m_aircraft->ccpmServoYLabel->setVisible(NumServosDefined >= 3);
m_aircraft->ccpmServoZLabel->setVisible(NumServosDefined >= 4);
m_aircraft->ccpmServoWChannel->setVisible(NumServosDefined >= 1);
m_aircraft->ccpmServoXChannel->setVisible(NumServosDefined >= 2);
m_aircraft->ccpmServoYChannel->setVisible(NumServosDefined >= 3);
m_aircraft->ccpmServoZChannel->setVisible(NumServosDefined >= 4);
m_ccpm->ccpmAdvancedSettingsTable->resizeColumnsToContents();
for (int i=0;i<6;i++) {
m_ccpm->ccpmAdvancedSettingsTable->setColumnWidth(i,(m_ccpm->ccpmAdvancedSettingsTable->width()-
m_ccpm->ccpmAdvancedSettingsTable->verticalHeader()->width())/6);
//set the visibility of the swashplate angle selection boxes
m_aircraft->ccpmServoWLabel_2->setVisible(NumServosDefined >= 1);
m_aircraft->ccpmServoXLabel_2->setVisible(NumServosDefined >= 2);
m_aircraft->ccpmServoYLabel_2->setVisible(NumServosDefined >= 3);
m_aircraft->ccpmServoZLabel_2->setVisible(NumServosDefined >= 4);
m_aircraft->ccpmAngleW->setVisible(NumServosDefined >= 1);
m_aircraft->ccpmAngleX->setVisible(NumServosDefined >= 2);
m_aircraft->ccpmAngleY->setVisible(NumServosDefined >= 3);
m_aircraft->ccpmAngleZ->setVisible(NumServosDefined >= 4);
QTableWidget *table = m_aircraft->ccpmAdvancedSettingsTable;
table->resizeColumnsToContents();
for (int i = 0; i < 6; i++) {
table->setColumnWidth(i, (table->width() - table->verticalHeader()->width()) / 6);
}
//update UI
ccpmSwashplateUpdate();
}
void ConfigCcpmWidget::ccpmSwashplateRedraw()
{
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;
size = m_ccpm->SwashplateImage->rect();
size = m_aircraft->SwashplateImage->rect();
xscale=size.width();
yscale=size.height();
scale=xscale;
if (yscale<scale)scale=yscale;
scale/=460.00;
m_ccpm->SwashplateImage->resetTransform ();
m_ccpm->SwashplateImage->scale(scale,scale);
m_aircraft->SwashplateImage->resetTransform ();
m_aircraft->SwashplateImage->scale(scale,scale);
size = m_ccpm->SwashLvlSwashplateImage->rect();
size = m_aircraft->SwashLvlSwashplateImage->rect();
xscale=size.width();
yscale=size.height();
scale=xscale;
if (yscale<scale)scale=yscale;
scale/=590.00;
m_ccpm->SwashLvlSwashplateImage->resetTransform ();
m_ccpm->SwashLvlSwashplateImage->scale(scale,scale);
m_aircraft->SwashLvlSwashplateImage->resetTransform ();
m_aircraft->SwashLvlSwashplateImage->scale(scale,scale);
CorrectionAngle=m_ccpm->ccpmCorrectionAngle->value();
CorrectionAngle=m_aircraft->ccpmCorrectionAngle->value();
CenterX=200;
CenterY=200;
@ -510,18 +577,18 @@ void ConfigCcpmWidget::ccpmSwashplateRedraw()
SwashplateImg->setPos(CenterX-bounds.width()/2,CenterY-bounds.height()/2);
defined[0]=(m_ccpm->ccpmServoWChannel->isEnabled());
defined[1]=(m_ccpm->ccpmServoXChannel->isEnabled());
defined[2]=(m_ccpm->ccpmServoYChannel->isEnabled());
defined[3]=(m_ccpm->ccpmServoZChannel->isEnabled());
used[0]=((m_ccpm->ccpmServoWChannel->currentIndex()>0)&&(m_ccpm->ccpmServoWChannel->isEnabled()));
used[1]=((m_ccpm->ccpmServoXChannel->currentIndex()>0)&&(m_ccpm->ccpmServoXChannel->isEnabled()));
used[2]=((m_ccpm->ccpmServoYChannel->currentIndex()>0)&&(m_ccpm->ccpmServoYChannel->isEnabled()));
used[3]=((m_ccpm->ccpmServoZChannel->currentIndex()>0)&&(m_ccpm->ccpmServoZChannel->isEnabled()));
angle[0]=(CorrectionAngle+180+m_ccpm->ccpmAngleW->value())*Pi/180.00;
angle[1]=(CorrectionAngle+180+m_ccpm->ccpmAngleX->value())*Pi/180.00;
angle[2]=(CorrectionAngle+180+m_ccpm->ccpmAngleY->value())*Pi/180.00;
angle[3]=(CorrectionAngle+180+m_ccpm->ccpmAngleZ->value())*Pi/180.00;
defined[0]=(m_aircraft->ccpmServoWChannel->isEnabled());
defined[1]=(m_aircraft->ccpmServoXChannel->isEnabled());
defined[2]=(m_aircraft->ccpmServoYChannel->isEnabled());
defined[3]=(m_aircraft->ccpmServoZChannel->isEnabled());
used[0]=((m_aircraft->ccpmServoWChannel->currentIndex()>0)&&(m_aircraft->ccpmServoWChannel->isEnabled()));
used[1]=((m_aircraft->ccpmServoXChannel->currentIndex()>0)&&(m_aircraft->ccpmServoXChannel->isEnabled()));
used[2]=((m_aircraft->ccpmServoYChannel->currentIndex()>0)&&(m_aircraft->ccpmServoYChannel->isEnabled()));
used[3]=((m_aircraft->ccpmServoZChannel->currentIndex()>0)&&(m_aircraft->ccpmServoZChannel->isEnabled()));
angle[0]=(CorrectionAngle+180+m_aircraft->ccpmAngleW->value())*Pi/180.00;
angle[1]=(CorrectionAngle+180+m_aircraft->ccpmAngleX->value())*Pi/180.00;
angle[2]=(CorrectionAngle+180+m_aircraft->ccpmAngleY->value())*Pi/180.00;
angle[3]=(CorrectionAngle+180+m_aircraft->ccpmAngleZ->value())*Pi/180.00;
for (i=0;i<CCPM_MAX_SWASH_SERVOS;i++)
@ -560,7 +627,7 @@ void ConfigCcpmWidget::ccpmSwashplateRedraw()
radius = (215.00+w+h);
x=CenterX-(radius*sin(angle[i]))-w;
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);
radius=220;
@ -570,9 +637,9 @@ void ConfigCcpmWidget::ccpmSwashplateRedraw()
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()
@ -586,132 +653,142 @@ void ConfigCcpmWidget::UpdateMixer()
{
bool useCCPM;
bool useCyclic;
int i,j,ThisEnable[6];
float CollectiveConstant,PitchConstant,RollConstant,ThisAngle[6];
int ThisEnable[6];
float CollectiveConstant, PitchConstant, RollConstant;
float ThisAngle[6];
QString Channel;
if (throwConfigError(QString("HeliCP")))
return;
GUIConfigDataUnion config = GetConfigData();
GUIConfigDataUnion config = getConfigData();
useCCPM = !(config.heli.ccpmCollectivePassthroughState || !config.heli.ccpmLinkCyclicState);
useCyclic = config.heli.ccpmLinkRollState;
CollectiveConstant = (float)config.heli.SliderValue0 / 100.00;
CollectiveConstant = (float) config.heli.SliderValue0 / 100.00;
if (useCCPM)
{//cyclic = 1 - collective
PitchConstant = 1-CollectiveConstant;
if (useCCPM) { //cyclic = 1 - collective
PitchConstant = 1 - CollectiveConstant;
RollConstant = PitchConstant;
}
else
{
PitchConstant = (float)config.heli.SliderValue1 / 100.00;;
if (useCyclic)
{
} else {
PitchConstant = (float) config.heli.SliderValue1 / 100.00;
;
if (useCyclic) {
RollConstant = PitchConstant;
}
else
{
RollConstant = (float)config.heli.SliderValue2 / 100.00;;
}
} else {
RollConstant = (float) config.heli.SliderValue2 / 100.00;
;
}
}
if (config.heli.SwashplateType>0)
{//not advanced settings
//get the channel data from the ui
MixerChannelData[0] = m_ccpm->ccpmEngineChannel->currentIndex();
MixerChannelData[1] = m_ccpm->ccpmTailChannel->currentIndex();
MixerChannelData[2] = m_ccpm->ccpmServoWChannel->currentIndex();
MixerChannelData[3] = m_ccpm->ccpmServoXChannel->currentIndex();
MixerChannelData[4] = m_ccpm->ccpmServoYChannel->currentIndex();
MixerChannelData[5] = m_ccpm->ccpmServoZChannel->currentIndex();
if (config.heli.SwashplateType > 0) { //not advanced settings
//get the channel data from the ui
MixerChannelData[0] = m_aircraft->ccpmEngineChannel->currentIndex();
MixerChannelData[1] = m_aircraft->ccpmTailChannel->currentIndex();
MixerChannelData[2] = m_aircraft->ccpmServoWChannel->currentIndex();
MixerChannelData[3] = m_aircraft->ccpmServoXChannel->currentIndex();
MixerChannelData[4] = m_aircraft->ccpmServoYChannel->currentIndex();
MixerChannelData[5] = m_aircraft->ccpmServoZChannel->currentIndex();
//get the angle data from the ui
ThisAngle[2] = m_ccpm->ccpmAngleW->value();
ThisAngle[3] = m_ccpm->ccpmAngleX->value();
ThisAngle[4] = m_ccpm->ccpmAngleY->value();
ThisAngle[5] = m_ccpm->ccpmAngleZ->value();
ThisAngle[2] = m_aircraft->ccpmAngleW->value();
ThisAngle[3] = m_aircraft->ccpmAngleX->value();
ThisAngle[4] = m_aircraft->ccpmAngleY->value();
ThisAngle[5] = m_aircraft->ccpmAngleZ->value();
//get the angle data from the ui
ThisEnable[2] = m_ccpm->ccpmServoWChannel->isEnabled();
ThisEnable[3] = m_ccpm->ccpmServoXChannel->isEnabled();
ThisEnable[4] = m_ccpm->ccpmServoYChannel->isEnabled();
ThisEnable[5] = m_ccpm->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] ));
ThisEnable[2] = m_aircraft->ccpmServoWChannel->isEnabled();
ThisEnable[3] = m_aircraft->ccpmServoXChannel->isEnabled();
ThisEnable[4] = m_aircraft->ccpmServoYChannel->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]));
//go through the user data and update the mixer matrix
for (i=0;i<6;i++)
{
if ((MixerChannelData[i]>0) && ((ThisEnable[i])||(i<2)))
{
m_ccpm->ccpmAdvancedSettingsTable->item(i,0)->setText(QString("%1").arg( MixerChannelData[i] ));
QTableWidget *table = m_aircraft->ccpmAdvancedSettingsTable;
for (int i = 0; i < 6; i++) {
if ((MixerChannelData[i] > 0) && ((ThisEnable[i]) || (i < 2))) {
table->item(i, 0)->setText(QString("%1").arg(MixerChannelData[i]));
//Generate the mixer vector
if (i==0)
{//main motor-engine
m_ccpm->ccpmAdvancedSettingsTable->item(i,1)->setText(QString("%1").arg(127));//ThrottleCurve1
m_ccpm->ccpmAdvancedSettingsTable->item(i,2)->setText(QString("%1").arg(0));//ThrottleCurve2
m_ccpm->ccpmAdvancedSettingsTable->item(i,3)->setText(QString("%1").arg(0));//Roll
m_ccpm->ccpmAdvancedSettingsTable->item(i,4)->setText(QString("%1").arg(0));//Pitch
if (i == 0) { //main motor-engine
table->item(i, 1)->setText(QString("%1").arg(127)); //ThrottleCurve1
table->item(i, 2)->setText(QString("%1").arg(0)); //ThrottleCurve2
table->item(i, 3)->setText(QString("%1").arg(0)); //Roll
table->item(i, 4)->setText(QString("%1").arg(0)); //Pitch
if (TypeText.compare(QString::fromUtf8("Coax 2 Servo 90º"), Qt::CaseInsensitive)==0)
m_ccpm->ccpmAdvancedSettingsTable->item(i,5)->setText(QString("%1").arg(-127));//Yaw
else
m_ccpm->ccpmAdvancedSettingsTable->item(i,5)->setText(QString("%1").arg(0));//Yaw
}
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
if (TypeText.compare(QString::fromUtf8("Coax 2 Servo 90º"), Qt::CaseInsensitive) == 0) {
// Yaw
table->item(i, 5)->setText(QString("%1").arg(-127));
} else {
// Yaw
table->item(i, 5)->setText(QString("%1").arg(0));
}
m_ccpm->ccpmAdvancedSettingsTable->item(i,2)->setText(QString("%1").arg(0));//ThrottleCurve2
m_ccpm->ccpmAdvancedSettingsTable->item(i,3)->setText(QString("%1").arg(0));//Roll
m_ccpm->ccpmAdvancedSettingsTable->item(i,4)->setText(QString("%1").arg(0));//Pitch
}
if (i == 1) {
// 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)
{//Swashplate
m_ccpm->ccpmAdvancedSettingsTable->item(i,1)->setText(QString("%1").arg(0));//ThrottleCurve1
m_ccpm->ccpmAdvancedSettingsTable->item(i,2)->setText(QString("%1").arg((int)(127.0*CollectiveConstant)));//ThrottleCurve2
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
m_ccpm->ccpmAdvancedSettingsTable->item(i,4)->setText(QString("%1").arg((int)(127.0*(PitchConstant)*cos((config.heli.CorrectionAngle + ThisAngle[i])*Pi/180.00))));//Pitch
m_ccpm->ccpmAdvancedSettingsTable->item(i,5)->setText(QString("%1").arg(0));//Yaw
if (i > 1) {
// Swashplate
//ThrottleCurve1
table->item(i, 1)->setText(QString("%1").arg(0));
//ThrottleCurve2
table->item(i, 2)->setText(QString("%1").arg((int) (127.0 * CollectiveConstant)));
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
{
for (j=0;j<6;j++) m_ccpm->ccpmAdvancedSettingsTable->item(i,j)->setText(QString("-"));
} else {
for (int j = 0; j < 6; j++) {
table->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 airframeType = "HeliCP";
@ -719,145 +796,86 @@ QString ConfigCcpmWidget::updateConfigObjects()
bool useCCPM;
bool useCyclic;
if (updatingFromHardware == TRUE) return airframeType;
if (updatingFromHardware == TRUE)
return airframeType;
updatingFromHardware = TRUE;
//get the user options
GUIConfigDataUnion config = GetConfigData();
GUIConfigDataUnion config = getConfigData();
//swashplate config
config.heli.SwashplateType = m_ccpm->ccpmType->count() - m_ccpm->ccpmType->currentIndex()-1;
config.heli.FirstServoIndex = m_ccpm->ccpmSingleServo->currentIndex();
config.heli.SwashplateType = m_aircraft->ccpmType->count() - m_aircraft->ccpmType->currentIndex() - 1;
config.heli.FirstServoIndex = m_aircraft->ccpmSingleServo->currentIndex();
//ccpm mixing options
config.heli.ccpmCollectivePassthroughState = m_ccpm->ccpmCollectivePassthrough->isChecked();
config.heli.ccpmLinkCyclicState = m_ccpm->ccpmLinkCyclic->isChecked();
config.heli.ccpmLinkRollState = m_ccpm->ccpmLinkRoll->isChecked();
config.heli.ccpmCollectivePassthroughState = m_aircraft->ccpmCollectivePassthrough->isChecked();
config.heli.ccpmLinkCyclicState = m_aircraft->ccpmLinkCyclic->isChecked();
config.heli.ccpmLinkRollState = m_aircraft->ccpmLinkRoll->isChecked();
useCCPM = !(config.heli.ccpmCollectivePassthroughState || !config.heli.ccpmLinkCyclicState);
useCyclic = config.heli.ccpmLinkRollState;
//correction angle
config.heli.CorrectionAngle = m_ccpm->ccpmCorrectionAngle->value();
config.heli.CorrectionAngle = m_aircraft->ccpmCorrectionAngle->value();
//update sliders
if (useCCPM)
{
config.heli.SliderValue0 = m_ccpm->ccpmCollectiveSlider->value();
if (useCCPM) {
config.heli.SliderValue0 = m_aircraft->ccpmCollectiveSlider->value();
} else {
config.heli.SliderValue0 = m_aircraft->ccpmCollectiveScale->value();
}
else
{
config.heli.SliderValue0 = m_ccpm->ccpmCollectiveScale->value();
if (useCyclic) {
config.heli.SliderValue1 = m_aircraft->ccpmCyclicScale->value();
} else {
config.heli.SliderValue1 = m_aircraft->ccpmPitchScale->value();
}
if (useCyclic)
{
config.heli.SliderValue1 = m_ccpm->ccpmCyclicScale->value();
}
else
{
config.heli.SliderValue1 = m_ccpm->ccpmPitchScale->value();
}
config.heli.SliderValue2 = m_ccpm->ccpmRollScale->value();
config.heli.SliderValue2 = m_aircraft->ccpmRollScale->value();
//servo assignments
config.heli.ServoIndexW = m_ccpm->ccpmServoWChannel->currentIndex();
config.heli.ServoIndexX = m_ccpm->ccpmServoXChannel->currentIndex();
config.heli.ServoIndexY = m_ccpm->ccpmServoYChannel->currentIndex();
config.heli.ServoIndexZ = m_ccpm->ccpmServoZChannel->currentIndex();
config.heli.ServoIndexW = m_aircraft->ccpmServoWChannel->currentIndex();
config.heli.ServoIndexX = m_aircraft->ccpmServoXChannel->currentIndex();
config.heli.ServoIndexY = m_aircraft->ccpmServoYChannel->currentIndex();
config.heli.ServoIndexZ = m_aircraft->ccpmServoZChannel->currentIndex();
//throttle
config.heli.Throttle = m_ccpm->ccpmEngineChannel->currentIndex();
config.heli.Throttle = m_aircraft->ccpmEngineChannel->currentIndex();
//tail
config.heli.Tail = m_ccpm->ccpmTailChannel->currentIndex();
config.heli.Tail = m_aircraft->ccpmTailChannel->currentIndex();
SetConfigData(config);
setConfigData(config);
updatingFromHardware = FALSE;
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()
{
m_ccpm->ccpmRevoMixingBox->setVisible(0);
m_ccpm->ccpmPitchMixingBox->setVisible(!m_ccpm->ccpmCollectivePassthrough->isChecked() &&
m_ccpm->ccpmLinkCyclic->isChecked());
m_aircraft->ccpmRevoMixingBox->setVisible(0);
m_ccpm->ccpmCollectiveScalingBox->setVisible(m_ccpm->ccpmCollectivePassthrough->isChecked() || !m_ccpm->ccpmLinkCyclic->isChecked());
m_aircraft->ccpmPitchMixingBox->setVisible(
!m_aircraft->ccpmCollectivePassthrough->isChecked() && m_aircraft->ccpmLinkCyclic->isChecked());
m_ccpm->ccpmLinkCyclic->setVisible(!m_ccpm->ccpmCollectivePassthrough->isChecked());
m_aircraft->ccpmCollectiveScalingBox->setVisible(
m_aircraft->ccpmCollectivePassthrough->isChecked() || !m_aircraft->ccpmLinkCyclic->isChecked());
m_ccpm->ccpmCyclicScalingBox->setVisible((m_ccpm->ccpmCollectivePassthrough->isChecked() || !m_ccpm->ccpmLinkCyclic->isChecked()) &&
m_ccpm->ccpmLinkRoll->isChecked());
m_aircraft->ccpmLinkCyclic->setVisible(!m_aircraft->ccpmCollectivePassthrough->isChecked());
if (!m_ccpm->ccpmCollectivePassthrough->checkState() && m_ccpm->ccpmLinkCyclic->isChecked())
{
m_ccpm->ccpmPitchScalingBox->setVisible(0);
m_ccpm->ccpmRollScalingBox->setVisible(0);
m_ccpm->ccpmLinkRoll->setVisible(0);
m_aircraft->ccpmCyclicScalingBox->setVisible(
(m_aircraft->ccpmCollectivePassthrough->isChecked() || !m_aircraft->ccpmLinkCyclic->isChecked())
&& m_aircraft->ccpmLinkRoll->isChecked());
}
else
{
m_ccpm->ccpmPitchScalingBox->setVisible(!m_ccpm->ccpmLinkRoll->isChecked());
m_ccpm->ccpmRollScalingBox->setVisible(!m_ccpm->ccpmLinkRoll->isChecked());
m_ccpm->ccpmLinkRoll->setVisible(1);
if (!m_aircraft->ccpmCollectivePassthrough->checkState() && m_aircraft->ccpmLinkCyclic->isChecked()) {
m_aircraft->ccpmPitchScalingBox->setVisible(0);
m_aircraft->ccpmRollScalingBox->setVisible(0);
m_aircraft->ccpmLinkRoll->setVisible(0);
} else {
m_aircraft->ccpmPitchScalingBox->setVisible(!m_aircraft->ccpmLinkRoll->isChecked());
m_aircraft->ccpmRollScalingBox->setVisible(!m_aircraft->ccpmLinkRoll->isChecked());
m_aircraft->ccpmLinkRoll->setVisible(1);
}
}
/**
Request the current value of the SystemSettings which holds the ccpm type
*/
@ -866,32 +884,29 @@ void ConfigCcpmWidget::getMixer()
if (SwashLvlConfigurationInProgress)return;
if (updatingToHardware)return;
updatingFromHardware=TRUE;
updatingFromHardware = TRUE;
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);
getThrottleCurve(mixer, VehicleConfig::MIXER_THROTTLECURVE1, &curveValues);
// is at least one of the curve values != 0?
if (vconfig->isValidThrottleCurve(&curveValues)) {
m_ccpm->ThrottleCurve->setCurve(&curveValues);
if (isValidThrottleCurve(&curveValues)) {
m_aircraft->ThrottleCurve->setCurve(&curveValues);
}
else {
m_ccpm->ThrottleCurve->ResetCurve();
m_aircraft->ThrottleCurve->ResetCurve();
}
vconfig->getThrottleCurve(mixer, VehicleConfig::MIXER_THROTTLECURVE2, &curveValues);
getThrottleCurve(mixer, VehicleConfig::MIXER_THROTTLECURVE2, &curveValues);
// is at least one of the curve values != 0?
if (vconfig->isValidThrottleCurve(&curveValues)) {
m_ccpm->PitchCurve->setCurve(&curveValues);
if (isValidThrottleCurve(&curveValues)) {
m_aircraft->PitchCurve->setCurve(&curveValues);
}
else {
m_ccpm->PitchCurve->ResetCurve();
m_aircraft->PitchCurve->ResetCurve();
}
updatingFromHardware=FALSE;
@ -899,7 +914,6 @@ void ConfigCcpmWidget::getMixer()
ccpmSwashplateUpdate();
}
/**
Sends the config to the board (ccpm type)
*/
@ -964,13 +978,13 @@ void ConfigCcpmWidget::setMixer()
//Configure the vector
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
QList<double> curve1 = m_ccpm->ThrottleCurve->getCurve();
QList<double> curve2 = m_ccpm->PitchCurve->getCurve();
QList<double> curve1 = m_aircraft->ThrottleCurve->getCurve();
QList<double> curve2 = m_aircraft->PitchCurve->getCurve();
for (i=0;i<5;i++) {
mixerSettingsData.ThrottleCurve1[i] = curve1.at(i);
mixerSettingsData.ThrottleCurve2[i] = curve2.at(i);
@ -979,7 +993,7 @@ void ConfigCcpmWidget::setMixer()
//mapping of collective input to curve 2...
//MixerSettings.Curve2Source = Throttle,Roll,Pitch,Yaw,Accessory0,Accessory1,Accessory2,Accessory3,Accessory4,Accessory5
//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;
else
mixerSettingsData.Curve2Source = MixerSettings::CURVE2SOURCE_THROTTLE;
@ -1009,10 +1023,10 @@ void ConfigCcpmWidget::resizeEvent(QResizeEvent* event)
{
Q_UNUSED(event);
// Make the custom table columns autostretch:
m_ccpm->ccpmAdvancedSettingsTable->resizeColumnsToContents();
m_aircraft->ccpmAdvancedSettingsTable->resizeColumnsToContents();
for (int i=0;i<6;i++) {
m_ccpm->ccpmAdvancedSettingsTable->setColumnWidth(i,(m_ccpm->ccpmAdvancedSettingsTable->width()-
m_ccpm->ccpmAdvancedSettingsTable->verticalHeader()->width())/6);
m_aircraft->ccpmAdvancedSettingsTable->setColumnWidth(i,(m_aircraft->ccpmAdvancedSettingsTable->width()-
m_aircraft->ccpmAdvancedSettingsTable->verticalHeader()->width())/6);
}
ccpmSwashplateRedraw();
@ -1020,10 +1034,10 @@ void ConfigCcpmWidget::resizeEvent(QResizeEvent* event)
void ConfigCcpmWidget::showEvent(QShowEvent *event)
{
Q_UNUSED(event)
m_ccpm->ccpmAdvancedSettingsTable->resizeColumnsToContents();
m_aircraft->ccpmAdvancedSettingsTable->resizeColumnsToContents();
for (int i=0;i<6;i++) {
m_ccpm->ccpmAdvancedSettingsTable->setColumnWidth(i,(m_ccpm->ccpmAdvancedSettingsTable->width()-
m_ccpm->ccpmAdvancedSettingsTable->verticalHeader()->width())/6);
m_aircraft->ccpmAdvancedSettingsTable->setColumnWidth(i,(m_aircraft->ccpmAdvancedSettingsTable->width()-
m_aircraft->ccpmAdvancedSettingsTable->verticalHeader()->width())/6);
}
ccpmSwashplateRedraw();
}
@ -1054,15 +1068,15 @@ void ConfigCcpmWidget::SwashLvlStartButtonPressed()
//remove Flight control of ActuatorCommand
enableSwashplateLevellingControl(true);
m_ccpm->SwashLvlStartButton->setEnabled(false);
m_ccpm->SwashLvlNextButton->setEnabled(true);
m_ccpm->SwashLvlCancelButton->setEnabled(true);
m_ccpm->SwashLvlFinishButton->setEnabled(false);
m_aircraft->SwashLvlStartButton->setEnabled(false);
m_aircraft->SwashLvlNextButton->setEnabled(true);
m_aircraft->SwashLvlCancelButton->setEnabled(true);
m_aircraft->SwashLvlFinishButton->setEnabled(false);
//clear status check boxes
m_ccpm->SwashLvlStepList->item(0)->setCheckState(Qt::Unchecked);
m_ccpm->SwashLvlStepList->item(1)->setCheckState(Qt::Unchecked);
m_ccpm->SwashLvlStepList->item(2)->setCheckState(Qt::Unchecked);
m_ccpm->SwashLvlStepList->item(3)->setCheckState(Qt::Unchecked);
m_aircraft->SwashLvlStepList->item(0)->setCheckState(Qt::Unchecked);
m_aircraft->SwashLvlStepList->item(1)->setCheckState(Qt::Unchecked);
m_aircraft->SwashLvlStepList->item(2)->setCheckState(Qt::Unchecked);
m_aircraft->SwashLvlStepList->item(3)->setCheckState(Qt::Unchecked);
//download the current settings to the OP hw
@ -1087,15 +1101,15 @@ void ConfigCcpmWidget::SwashLvlStartButtonPressed()
MaxField = obj->getField(QString("ChannelMax"));
//channel assignments
oldSwashLvlConfiguration.ServoChannels[0]=m_ccpm->ccpmServoWChannel->currentIndex();
oldSwashLvlConfiguration.ServoChannels[1]=m_ccpm->ccpmServoXChannel->currentIndex();
oldSwashLvlConfiguration.ServoChannels[2]=m_ccpm->ccpmServoYChannel->currentIndex();
oldSwashLvlConfiguration.ServoChannels[3]=m_ccpm->ccpmServoZChannel->currentIndex();
oldSwashLvlConfiguration.ServoChannels[0]=m_aircraft->ccpmServoWChannel->currentIndex();
oldSwashLvlConfiguration.ServoChannels[1]=m_aircraft->ccpmServoXChannel->currentIndex();
oldSwashLvlConfiguration.ServoChannels[2]=m_aircraft->ccpmServoYChannel->currentIndex();
oldSwashLvlConfiguration.ServoChannels[3]=m_aircraft->ccpmServoZChannel->currentIndex();
//if servos are used
oldSwashLvlConfiguration.Used[0]=((m_ccpm->ccpmServoWChannel->currentIndex()>0)&&(m_ccpm->ccpmServoWChannel->isEnabled()));
oldSwashLvlConfiguration.Used[1]=((m_ccpm->ccpmServoXChannel->currentIndex()>0)&&(m_ccpm->ccpmServoXChannel->isEnabled()));
oldSwashLvlConfiguration.Used[2]=((m_ccpm->ccpmServoYChannel->currentIndex()>0)&&(m_ccpm->ccpmServoYChannel->isEnabled()));
oldSwashLvlConfiguration.Used[3]=((m_ccpm->ccpmServoZChannel->currentIndex()>0)&&(m_ccpm->ccpmServoZChannel->isEnabled()));
oldSwashLvlConfiguration.Used[0]=((m_aircraft->ccpmServoWChannel->currentIndex()>0)&&(m_aircraft->ccpmServoWChannel->isEnabled()));
oldSwashLvlConfiguration.Used[1]=((m_aircraft->ccpmServoXChannel->currentIndex()>0)&&(m_aircraft->ccpmServoXChannel->isEnabled()));
oldSwashLvlConfiguration.Used[2]=((m_aircraft->ccpmServoYChannel->currentIndex()>0)&&(m_aircraft->ccpmServoYChannel->isEnabled()));
oldSwashLvlConfiguration.Used[3]=((m_aircraft->ccpmServoZChannel->currentIndex()>0)&&(m_aircraft->ccpmServoZChannel->isEnabled()));
//min,neutral,max values for the servos
for (i=0;i<CCPM_MAX_SWASH_SERVOS;i++)
{
@ -1116,111 +1130,107 @@ void ConfigCcpmWidget::SwashLvlStartButtonPressed()
//restore Flight control of ActuatorCommand
enableSwashplateLevellingControl(false);
m_ccpm->SwashLvlStartButton->setEnabled(true);
m_ccpm->SwashLvlNextButton->setEnabled(false);
m_ccpm->SwashLvlCancelButton->setEnabled(false);
m_ccpm->SwashLvlFinishButton->setEnabled(false);
m_aircraft->SwashLvlStartButton->setEnabled(true);
m_aircraft->SwashLvlNextButton->setEnabled(false);
m_aircraft->SwashLvlCancelButton->setEnabled(false);
m_aircraft->SwashLvlFinishButton->setEnabled(false);
break;
default:
// should never be reached
break;
}
}
void ConfigCcpmWidget::SwashLvlNextButtonPressed()
{
//ShowDisclaimer(2);
SwashLvlState++;
int i;
switch (SwashLvlState)
{
switch (SwashLvlState) {
case 0:
break;
case 1: //Neutral levelling
m_ccpm->SwashLvlStepList->setCurrentRow(0);
m_aircraft->SwashLvlStepList->setCurrentRow(0);
//set spin boxes and swashplate servos to Neutral values
setSwashplateLevel(50);
//disable position slider
m_ccpm->SwashLvlPositionSlider->setEnabled(false);
m_ccpm->SwashLvlPositionSpinBox->setEnabled(false);
m_aircraft->SwashLvlPositionSlider->setEnabled(false);
m_aircraft->SwashLvlPositionSpinBox->setEnabled(false);
//set position slider to 50%
m_ccpm->SwashLvlPositionSlider->setValue(50);
m_ccpm->SwashLvlPositionSpinBox->setValue(50);
m_aircraft->SwashLvlPositionSlider->setValue(50);
m_aircraft->SwashLvlPositionSpinBox->setValue(50);
//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)));
SwashLvlSpinBoxes[i]->setEnabled(true);
}
//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;
case 2: //Max levelling
//check Neutral status as complete
m_ccpm->SwashLvlStepList->item(0)->setCheckState(Qt::Checked);
m_ccpm->SwashLvlStepList->setCurrentRow(1);
m_aircraft->SwashLvlStepList->item(0)->setCheckState(Qt::Checked);
m_aircraft->SwashLvlStepList->setCurrentRow(1);
//set spin boxes and swashplate servos to Max values
setSwashplateLevel(100);
//set position slider to 100%
m_ccpm->SwashLvlPositionSlider->setValue(100);
m_ccpm->SwashLvlPositionSpinBox->setValue(100);
m_aircraft->SwashLvlPositionSlider->setValue(100);
m_aircraft->SwashLvlPositionSpinBox->setValue(100);
//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;
case 3: //Min levelling
//check Max status as complete
m_ccpm->SwashLvlStepList->item(1)->setCheckState(Qt::Checked);
m_ccpm->SwashLvlStepList->setCurrentRow(2);
m_aircraft->SwashLvlStepList->item(1)->setCheckState(Qt::Checked);
m_aircraft->SwashLvlStepList->setCurrentRow(2);
//set spin boxes and swashplate servos to Min values
setSwashplateLevel(0);
//set position slider to 0%
m_ccpm->SwashLvlPositionSlider->setValue(0);
m_ccpm->SwashLvlPositionSpinBox->setValue(0);
m_aircraft->SwashLvlPositionSlider->setValue(0);
m_aircraft->SwashLvlPositionSpinBox->setValue(0);
//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.");
break;
m_aircraft->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.");
break;
case 4: //levelling verification
//check Min status as complete
m_ccpm->SwashLvlStepList->item(2)->setCheckState(Qt::Checked);
m_ccpm->SwashLvlStepList->setCurrentRow(3);
m_aircraft->SwashLvlStepList->item(2)->setCheckState(Qt::Checked);
m_aircraft->SwashLvlStepList->setCurrentRow(3);
//enable position slider
m_ccpm->SwashLvlPositionSlider->setEnabled(true);
m_ccpm->SwashLvlPositionSpinBox->setEnabled(true);
m_aircraft->SwashLvlPositionSlider->setEnabled(true);
m_aircraft->SwashLvlPositionSpinBox->setEnabled(true);
//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
for (i=0;i<CCPM_MAX_SWASH_SERVOS;i++)
{
for (int i = 0; i < CCPM_MAX_SWASH_SERVOS; i++) {
SwashLvlSpinBoxes[i]->setEnabled(false);
}
//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.");
break;
m_aircraft->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.");
break;
case 5: //levelling 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
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
m_ccpm->SwashLvlPositionSlider->setEnabled(false);
m_ccpm->SwashLvlPositionSpinBox->setEnabled(false);
m_aircraft->SwashLvlPositionSlider->setEnabled(false);
m_aircraft->SwashLvlPositionSpinBox->setEnabled(false);
//disconnect levelling slots from signals
disconnect(m_ccpm->SwashLvlPositionSlider, SIGNAL(valueChanged(int)), this, SLOT(setSwashplateLevel(int)));
for (i=0;i<CCPM_MAX_SWASH_SERVOS;i++)
{
disconnect(m_aircraft->SwashLvlPositionSlider, SIGNAL(valueChanged(int)), this, SLOT(setSwashplateLevel(int)));
for (int i = 0; i < CCPM_MAX_SWASH_SERVOS; i++) {
disconnect(SwashLvlSpinBoxes[i], SIGNAL(valueChanged(int)), this, SLOT(SwashLvlSpinBoxChanged(int)));
}
m_ccpm->SwashLvlStartButton->setEnabled(false);
m_ccpm->SwashLvlNextButton->setEnabled(false);
m_ccpm->SwashLvlCancelButton->setEnabled(true);
m_ccpm->SwashLvlFinishButton->setEnabled(true);
m_aircraft->SwashLvlStartButton->setEnabled(false);
m_aircraft->SwashLvlNextButton->setEnabled(false);
m_aircraft->SwashLvlCancelButton->setEnabled(true);
m_aircraft->SwashLvlFinishButton->setEnabled(true);
default:
//restore collective/cyclic setting
@ -1231,24 +1241,24 @@ void ConfigCcpmWidget::SwashLvlNextButtonPressed()
break;
}
}
void ConfigCcpmWidget::SwashLvlCancelButtonPressed()
{
int i;
SwashLvlState=0;
SwashLvlState = 0;
UAVObjectField* MinField;
UAVObjectField* NeutralField;
UAVObjectField* MaxField;
UAVObjectField *MinField;
UAVObjectField *NeutralField;
UAVObjectField *MaxField;
m_ccpm->SwashLvlStartButton->setEnabled(true);
m_ccpm->SwashLvlNextButton->setEnabled(false);
m_ccpm->SwashLvlCancelButton->setEnabled(false);
m_ccpm->SwashLvlFinishButton->setEnabled(false);
m_aircraft->SwashLvlStartButton->setEnabled(true);
m_aircraft->SwashLvlNextButton->setEnabled(false);
m_aircraft->SwashLvlCancelButton->setEnabled(false);
m_aircraft->SwashLvlFinishButton->setEnabled(false);
m_ccpm->SwashLvlStepList->item(0)->setCheckState(Qt::Unchecked);
m_ccpm->SwashLvlStepList->item(1)->setCheckState(Qt::Unchecked);
m_ccpm->SwashLvlStepList->item(2)->setCheckState(Qt::Unchecked);
m_ccpm->SwashLvlStepList->item(3)->setCheckState(Qt::Unchecked);
m_aircraft->SwashLvlStepList->item(0)->setCheckState(Qt::Unchecked);
m_aircraft->SwashLvlStepList->item(1)->setCheckState(Qt::Unchecked);
m_aircraft->SwashLvlStepList->item(2)->setCheckState(Qt::Unchecked);
m_aircraft->SwashLvlStepList->item(3)->setCheckState(Qt::Unchecked);
//restore old Actuator Settings
ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance();
@ -1260,110 +1270,110 @@ void ConfigCcpmWidget::SwashLvlCancelButtonPressed()
NeutralField = obj->getField(QString("ChannelNeutral"));
MaxField = obj->getField(QString("ChannelMax"));
//min,neutral,max values for the servos
for (i=0;i<CCPM_MAX_SWASH_SERVOS;i++)
{
MinField->setValue(oldSwashLvlConfiguration.Min[i],oldSwashLvlConfiguration.ServoChannels[i]);
NeutralField->setValue(oldSwashLvlConfiguration.Neutral[i],oldSwashLvlConfiguration.ServoChannels[i]);
MaxField->setValue(oldSwashLvlConfiguration.Max[i],oldSwashLvlConfiguration.ServoChannels[i]);
// min,neutral,max values for the servos
for (int i = 0; i < CCPM_MAX_SWASH_SERVOS; i++) {
MinField->setValue(oldSwashLvlConfiguration.Min[i], oldSwashLvlConfiguration.ServoChannels[i]);
NeutralField->setValue(oldSwashLvlConfiguration.Neutral[i], oldSwashLvlConfiguration.ServoChannels[i]);
MaxField->setValue(oldSwashLvlConfiguration.Max[i], oldSwashLvlConfiguration.ServoChannels[i]);
}
obj->updated();
//restore Flight control of ActuatorCommand
// restore Flight control of ActuatorCommand
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()
{
int i;
UAVObjectField *MinField;
UAVObjectField *NeutralField;
UAVObjectField *MaxField;
UAVObjectField* MinField;
UAVObjectField* NeutralField;
UAVObjectField* MaxField;
m_aircraft->SwashLvlStartButton->setEnabled(true);
m_aircraft->SwashLvlNextButton->setEnabled(false);
m_aircraft->SwashLvlCancelButton->setEnabled(false);
m_aircraft->SwashLvlFinishButton->setEnabled(false);
m_ccpm->SwashLvlStartButton->setEnabled(true);
m_ccpm->SwashLvlNextButton->setEnabled(false);
m_ccpm->SwashLvlCancelButton->setEnabled(false);
m_ccpm->SwashLvlFinishButton->setEnabled(false);
//save new Actuator Settings to memory and SD card
// save new Actuator Settings to memory and SD card
ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance();
UAVObjectManager *objManager = pm->getObject<UAVObjectManager>();
UAVDataObject* obj = dynamic_cast<UAVDataObject*>(objManager->getObject(QString("ActuatorSettings")));
Q_ASSERT(obj);
//update settings to match our changes.
// update settings to match our changes.
MinField = obj->getField(QString("ChannelMin"));
NeutralField = obj->getField(QString("ChannelNeutral"));
MaxField = obj->getField(QString("ChannelMax"));
//min,neutral,max values for the servos
for (i=0;i<CCPM_MAX_SWASH_SERVOS;i++)
{
MinField->setValue(newSwashLvlConfiguration.Min[i],newSwashLvlConfiguration.ServoChannels[i]);
NeutralField->setValue(newSwashLvlConfiguration.Neutral[i],newSwashLvlConfiguration.ServoChannels[i]);
MaxField->setValue(newSwashLvlConfiguration.Max[i],newSwashLvlConfiguration.ServoChannels[i]);
// min,neutral,max values for the servos
for (int i = 0; i < CCPM_MAX_SWASH_SERVOS; i++) {
MinField->setValue(newSwashLvlConfiguration.Min[i], newSwashLvlConfiguration.ServoChannels[i]);
NeutralField->setValue(newSwashLvlConfiguration.Neutral[i], newSwashLvlConfiguration.ServoChannels[i]);
MaxField->setValue(newSwashLvlConfiguration.Max[i], newSwashLvlConfiguration.ServoChannels[i]);
}
obj->updated();
saveObjectToSD(obj);
//restore Flight control of ActuatorCommand
// restore Flight control of ActuatorCommand
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(2);
}
int ConfigCcpmWidget::ShowDisclaimer(int messageID)
{
QMessageBox msgBox;
msgBox.setText("<font color=red><h1>Warning!!!</h2></font>");
int ret;
switch (messageID) {
case 0:
// Basic disclaimer
msgBox.setInformativeText("<h2>This code has many configurations.</h2><p>Please double check all settings before attempting flight!");
msgBox.setStandardButtons(QMessageBox::Ok);
msgBox.setDefaultButton(QMessageBox::Ok);
msgBox.setIcon(QMessageBox::Information);
ret = msgBox.exec();
return 0;
break;
case 1:
// Not Tested disclaimer
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?");
msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::Cancel);
msgBox.setDefaultButton(QMessageBox::Cancel);
msgBox.setIcon(QMessageBox::Warning);
ret = msgBox.exec();
switch (ret)
{
case QMessageBox::Cancel: return -1;
case QMessageBox::Yes: return 0;
}
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();
QMessageBox msgBox;
msgBox.setText("<font color=red><h1>Warning!!!</h2></font>");
int ret;
switch (messageID) {
case 0:
// Basic disclaimer
msgBox.setInformativeText(
"<h2>This code has many configurations.</h2><p>Please double check all settings before attempting flight!");
msgBox.setStandardButtons(QMessageBox::Ok);
msgBox.setDefaultButton(QMessageBox::Ok);
msgBox.setIcon(QMessageBox::Information);
ret = msgBox.exec();
return 0;
break;
case 1:
// Not Tested disclaimer
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?");
msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::Cancel);
msgBox.setDefaultButton(QMessageBox::Cancel);
msgBox.setIcon(QMessageBox::Warning);
ret = msgBox.exec();
switch (ret) {
case QMessageBox::Cancel:
return -1;
case QMessageBox::Yes:
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;
}
@ -1379,33 +1389,30 @@ void ConfigCcpmWidget::enableSwashplateLevellingControl(bool state)
UAVDataObject* obj = dynamic_cast<UAVDataObject*>(objManager->getObject(QString("ActuatorCommand")));
UAVObject::Metadata mdata = obj->getMetadata();
if (state)
{
if (state) {
SwashLvlaccInitialData = mdata;
UAVObject::SetFlightAccess(mdata, UAVObject::ACCESS_READONLY);
UAVObject::SetFlightTelemetryUpdateMode(mdata, UAVObject::UPDATEMODE_ONCHANGE);
UAVObject::SetGcsTelemetryAcked(mdata, false);
UAVObject::SetGcsTelemetryUpdateMode(mdata, UAVObject::UPDATEMODE_ONCHANGE);
mdata.gcsTelemetryUpdatePeriod = 100;
SwashLvlConfigurationInProgress=1;
m_ccpm->TabObject->setTabEnabled(0,0);
m_ccpm->TabObject->setTabEnabled(2,0);
m_ccpm->TabObject->setTabEnabled(3,0);
m_ccpm->ccpmType->setEnabled(0);
}
else
{
mdata = SwashLvlaccInitialData; // Restore metadata
SwashLvlConfigurationInProgress=0;
SwashLvlConfigurationInProgress = 1;
m_aircraft->TabObject->setTabEnabled(0, 0);
m_aircraft->TabObject->setTabEnabled(2, 0);
m_aircraft->TabObject->setTabEnabled(3, 0);
m_aircraft->ccpmType->setEnabled(0);
} else {
// Restore metadata
mdata = SwashLvlaccInitialData;
SwashLvlConfigurationInProgress = 0;
m_ccpm->TabObject->setTabEnabled(0,1);
m_ccpm->TabObject->setTabEnabled(2,1);
m_ccpm->TabObject->setTabEnabled(3,1);
m_ccpm->ccpmType->setEnabled(1);
m_aircraft->TabObject->setTabEnabled(0, 1);
m_aircraft->TabObject->setTabEnabled(2, 1);
m_aircraft->TabObject->setTabEnabled(3, 1);
m_aircraft->ccpmType->setEnabled(1);
}
obj->setMetadata(mdata);
}
/**
@ -1414,26 +1421,34 @@ void ConfigCcpmWidget::enableSwashplateLevellingControl(bool state)
*/
void ConfigCcpmWidget::setSwashplateLevel(int percent)
{
if (percent<0)return;// -1;
if (percent>100)return;// -1;
if (SwashLvlConfigurationInProgress!=1)return;// -1;
int i;
double value;
double level = ((double)percent /50.00) - 1.00;
if (percent < 0) {
return; // -1;
}
if (percent > 100) {
return; // -1;
}
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();
for (i=0;i<CCPM_MAX_SWASH_SERVOS;i++) {
if (level==0)
for (int i = 0; i < CCPM_MAX_SWASH_SERVOS; i++) {
double value;
if (level == 0) {
value = newSwashLvlConfiguration.Neutral[i];
else if (level > 0)
value = (newSwashLvlConfiguration.Max[i] - newSwashLvlConfiguration.Neutral[i])*level + newSwashLvlConfiguration.Neutral[i];
else if (level < 0)
value = (newSwashLvlConfiguration.Neutral[i] - newSwashLvlConfiguration.Min[i])*level + newSwashLvlConfiguration.Neutral[i];
} else if (level > 0) {
value = (newSwashLvlConfiguration.Max[i] - newSwashLvlConfiguration.Neutral[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;
SwashLvlSpinBoxes[i]->setValue(value);
}
@ -1441,38 +1456,42 @@ void ConfigCcpmWidget::setSwashplateLevel(int percent)
actuatorCommand->setData(actuatorCommandData);
actuatorCommand->updated();
SwashLvlServoInterlock=0;
return;
SwashLvlServoInterlock = 0;
}
void ConfigCcpmWidget::SwashLvlSpinBoxChanged(int 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();
for (i = 0; i < CCPM_MAX_SWASH_SERVOS; i++) {
for (int i = 0; i < CCPM_MAX_SWASH_SERVOS; i++) {
value = SwashLvlSpinBoxes[i]->value();
switch (SwashLvlState)
{
case 1: //Neutral levelling
newSwashLvlConfiguration.Neutral[i]=value;
switch (SwashLvlState) {
case 1:
// Neutral levelling
newSwashLvlConfiguration.Neutral[i] = value;
break;
case 2: //Max levelling
case 2:
// Max levelling
newSwashLvlConfiguration.Max[i] = value;
break;
case 3: //Min levelling
newSwashLvlConfiguration.Min[i]= value;
case 3:
// Min levelling
newSwashLvlConfiguration.Min[i] = value;
break;
case 4: //levelling verification
case 4:
// levelling verification
break;
case 5: //levelling complete
case 5:
// levelling complete
break;
default:
break;
@ -1481,7 +1500,6 @@ void ConfigCcpmWidget::SwashLvlSpinBoxChanged(int value)
actuatorCommandData.Channel[newSwashLvlConfiguration.ServoChannels[i]] = value;
}
actuatorCommand->setData(actuatorCommandData);
actuatorCommand->updated();
@ -1497,63 +1515,45 @@ bool ConfigCcpmWidget::throwConfigError(QString airframeType)
bool error = false;
if((m_ccpm->ccpmServoWChannel->currentIndex()==0) && (m_ccpm->ccpmServoWChannel->isEnabled()))
{
m_ccpm->ccpmServoWLabel->setText("<font color=red>" + m_ccpm->ccpmServoWLabel->text() + "</font>");
if ((m_aircraft->ccpmServoWChannel->currentIndex() == 0) && (m_aircraft->ccpmServoWChannel->isEnabled())) {
m_aircraft->ccpmServoWLabel->setText("<font color=red>" + m_aircraft->ccpmServoWLabel->text() + "</font>");
error = true;
}
else
{
m_ccpm->ccpmServoWLabel->setText(QTextEdit(m_ccpm->ccpmServoWLabel->text()).toPlainText());
} else {
m_aircraft->ccpmServoWLabel->setText(QTextEdit(m_aircraft->ccpmServoWLabel->text()).toPlainText());
}
if((m_ccpm->ccpmServoXChannel->currentIndex()==0) && (m_ccpm->ccpmServoXChannel->isEnabled()))
{
m_ccpm->ccpmServoXLabel->setText("<font color=red>" + m_ccpm->ccpmServoXLabel->text() + "</font>");
if ((m_aircraft->ccpmServoXChannel->currentIndex() == 0) && (m_aircraft->ccpmServoXChannel->isEnabled())) {
m_aircraft->ccpmServoXLabel->setText("<font color=red>" + m_aircraft->ccpmServoXLabel->text() + "</font>");
error = true;
}
else
{
m_ccpm->ccpmServoXLabel->setText(QTextEdit(m_ccpm->ccpmServoXLabel->text()).toPlainText());
} else {
m_aircraft->ccpmServoXLabel->setText(QTextEdit(m_aircraft->ccpmServoXLabel->text()).toPlainText());
}
if((m_ccpm->ccpmServoYChannel->currentIndex()==0) && (m_ccpm->ccpmServoYChannel->isEnabled()))
{
m_ccpm->ccpmServoYLabel->setText("<font color=red>" + m_ccpm->ccpmServoYLabel->text() + "</font>");
if ((m_aircraft->ccpmServoYChannel->currentIndex() == 0) && (m_aircraft->ccpmServoYChannel->isEnabled())) {
m_aircraft->ccpmServoYLabel->setText("<font color=red>" + m_aircraft->ccpmServoYLabel->text() + "</font>");
error = true;
}
else
{
m_ccpm->ccpmServoYLabel->setText(QTextEdit(m_ccpm->ccpmServoYLabel->text()).toPlainText());
} else {
m_aircraft->ccpmServoYLabel->setText(QTextEdit(m_aircraft->ccpmServoYLabel->text()).toPlainText());
}
if((m_ccpm->ccpmServoZChannel->currentIndex()==0) && (m_ccpm->ccpmServoZChannel->isEnabled()))
{
m_ccpm->ccpmServoZLabel->setText("<font color=red>" + m_ccpm->ccpmServoZLabel->text()+ "</font>");
if ((m_aircraft->ccpmServoZChannel->currentIndex() == 0) && (m_aircraft->ccpmServoZChannel->isEnabled())) {
m_aircraft->ccpmServoZLabel->setText("<font color=red>" + m_aircraft->ccpmServoZLabel->text() + "</font>");
error = true;
}
else
{
m_ccpm->ccpmServoZLabel->setText(QTextEdit(m_ccpm->ccpmServoZLabel->text()).toPlainText());
} else {
m_aircraft->ccpmServoZLabel->setText(QTextEdit(m_aircraft->ccpmServoZLabel->text()).toPlainText());
}
if((m_ccpm->ccpmEngineChannel->currentIndex()==0) && (m_ccpm->ccpmEngineChannel->isEnabled()))
{
m_ccpm->ccpmEngineLabel->setText("<font color=red>" + m_ccpm->ccpmEngineLabel->text() + "</font>");
}
else
{
m_ccpm->ccpmEngineLabel->setText(QTextEdit(m_ccpm->ccpmEngineLabel->text()).toPlainText());
if ((m_aircraft->ccpmEngineChannel->currentIndex() == 0) && (m_aircraft->ccpmEngineChannel->isEnabled())) {
m_aircraft->ccpmEngineLabel->setText("<font color=red>" + m_aircraft->ccpmEngineLabel->text() + "</font>");
} else {
m_aircraft->ccpmEngineLabel->setText(QTextEdit(m_aircraft->ccpmEngineLabel->text()).toPlainText());
}
if((m_ccpm->ccpmTailChannel->currentIndex()==0) && (m_ccpm->ccpmTailChannel->isEnabled()))
{
m_ccpm->ccpmTailLabel->setText("<font color=red>" + m_ccpm->ccpmTailLabel->text() + "</font>");
if ((m_aircraft->ccpmTailChannel->currentIndex() == 0) && (m_aircraft->ccpmTailChannel->isEnabled())) {
m_aircraft->ccpmTailLabel->setText("<font color=red>" + m_aircraft->ccpmTailLabel->text() + "</font>");
error = true;
}
else
{
m_ccpm->ccpmTailLabel->setText(QTextEdit(m_ccpm->ccpmTailLabel->text()).toPlainText());
} else {
m_aircraft->ccpmTailLabel->setText(QTextEdit(m_aircraft->ccpmTailLabel->text()).toPlainText());
}

View File

@ -27,12 +27,13 @@
#ifndef CONFIGccpmWIDGET_H
#define CONFIGccpmWIDGET_H
#include "ui_ccpm.h"
#include "../uavobjectwidgetutils/configtaskwidget.h"
#include "cfg_vehicletypes/vehicleconfig.h"
#include "ui_airframe_ccpm.h"
#include "../uavobjectwidgetutils/configtaskwidget.h"
#include "extensionsystem/pluginmanager.h"
#include "uavobjectmanager.h"
#include "uavobject.h"
#include <QtSvg/QSvgRenderer>
#include <QtSvg/QGraphicsSvgItem>
#include <QGraphicsEllipseItem>
@ -51,83 +52,85 @@ typedef struct {
int Min[CCPM_MAX_SWASH_SERVOS];
} SwashplateServoSettingsStruct;
class ConfigCcpmWidget: public VehicleConfig
{
Q_OBJECT
public:
static QStringList getChannelDescriptions();
ConfigCcpmWidget(QWidget *parent = 0);
~ConfigCcpmWidget();
friend class ConfigVehicleTypeWidget;
virtual void refreshWidgetsValues(QString frameType);
virtual QString updateConfigObjectsFromWidgets();
private:
Ui_ccpmWidget *m_ccpm;
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];
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();
public slots:
void getMixer();
void setMixer();
void saveccpmUpdate();
protected:
void showEvent(QShowEvent *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

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
*/
#include "configfixedwingwidget.h"
#include "configvehicletypewidget.h"
#include "mixersettings.h"
#include "systemsettings.h"
#include "actuatorsettings.h"
#include "actuatorcommand.h"
#include <QDebug>
#include <QStringList>
@ -38,29 +40,65 @@
#include <math.h>
#include <QMessageBox>
#include "mixersettings.h"
#include "systemsettings.h"
#include "actuatorsettings.h"
#include "actuatorcommand.h"
/**
Constructor
*/
ConfigFixedWingWidget::ConfigFixedWingWidget(Ui_AircraftWidget *aircraft, QWidget *parent) : VehicleConfig(parent)
QStringList ConfigFixedWingWidget::getChannelDescriptions()
{
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()
{
// Do nothing
delete m_aircraft;
}
/**
Virtual function to setup the UI
*/
@ -69,8 +107,6 @@ void ConfigFixedWingWidget::setupUI(QString frameType)
Q_ASSERT(m_aircraft);
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"));
m_aircraft->fwRudder1ChannelBox->setEnabled(true);
m_aircraft->fwRudder1Label->setEnabled(true);
@ -92,7 +128,6 @@ void ConfigFixedWingWidget::setupUI(QString frameType)
m_aircraft->elevonMixBox->setHidden(true);
} 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"));
m_aircraft->fwAileron1Label->setText("Elevon 1");
m_aircraft->fwAileron2Label->setText("Elevon 2");
@ -111,7 +146,6 @@ void ConfigFixedWingWidget::setupUI(QString frameType)
m_aircraft->elevonLabel2->setText("Pitch");
} 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"));
m_aircraft->fwRudder1ChannelBox->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.FixedWingPitch2 = 0;
@ -142,36 +191,65 @@ void ConfigFixedWingWidget::ResetActuators(GUIConfigDataUnion* configData)
configData->fixedwing.FixedWingThrottle = 0;
}
QStringList ConfigFixedWingWidget::getChannelDescriptions()
/**
Virtual function to refresh the UI widget values
*/
void ConfigFixedWingWidget::refreshWidgetsValues(QString frameType)
{
int i;
QStringList channelDesc;
Q_ASSERT(m_aircraft);
// init a channel_numelem list of channel desc defaults
for (i=0; i < (int)(ConfigFixedWingWidget::CHANNEL_NUMELEM); i++)
{
channelDesc.append(QString("-"));
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->fixedWingThrottle->initCurve(&curveValues);
}
else {
// no, init a straight curve
m_aircraft->fixedWingThrottle->initLinearCurve(curveValues.count(), 1.0);
}
// get the gui config data
GUIConfigDataUnion configData = GetConfigData();
GUIConfigDataUnion config = getConfigData();
fixedGUISettingsStruct fixed = config.fixedwing;
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");
// 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);
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);
}
}
}
/**
@ -180,18 +258,18 @@ QStringList ConfigFixedWingWidget::getChannelDescriptions()
QString ConfigFixedWingWidget::updateConfigObjectsFromWidgets()
{
QString airframeType = "FixedWing";
// Save the curve (common to all Fixed wing frames)
UAVDataObject* mixer = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
Q_ASSERT(mixer);
// Remove Feed Forward, it is pointless on a plane:
setMixerValue(mixer, "FeedForward", 0.0);
// Set the throttle curve
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" ) {
airframeType = "FixedWing";
setupFrameFixedWing( airframeType );
@ -206,50 +284,6 @@ QString ConfigFixedWingWidget::updateConfigObjectsFromWidgets()
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.
@ -260,15 +294,14 @@ void ConfigFixedWingWidget::refreshWidgetsValues(QString frameType)
bool ConfigFixedWingWidget::setupFrameFixedWing(QString airframeType)
{
// Check coherence:
//Show any config errors in GUI
// Show any config errors in GUI
if (throwConfigError(airframeType)) {
return false;
}
return false;
}
// Now setup the channels:
GUIConfigDataUnion config = GetConfigData();
ResetActuators(&config);
GUIConfigDataUnion config = getConfigData();
resetActuators(&config);
config.fixedwing.FixedWingPitch1 = m_aircraft->fwElevator1ChannelBox->currentIndex();
config.fixedwing.FixedWingPitch2 = m_aircraft->fwElevator2ChannelBox->currentIndex();
@ -277,8 +310,8 @@ bool ConfigFixedWingWidget::setupFrameFixedWing(QString airframeType)
config.fixedwing.FixedWingYaw1 = m_aircraft->fwRudder1ChannelBox->currentIndex();
config.fixedwing.FixedWingThrottle = m_aircraft->fwEngineChannelBox->currentIndex();
SetConfigData(config);
setConfigData(config);
UAVDataObject* mixer = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
Q_ASSERT(mixer);
resetMotorAndServoMixers(mixer);
@ -289,58 +322,56 @@ bool ConfigFixedWingWidget::setupFrameFixedWing(QString airframeType)
// 1. Assign the servo/motor/none for each channel
//motor
int channel = m_aircraft->fwEngineChannelBox->currentIndex()-1;
setMixerType(mixer,channel,VehicleConfig::MIXERTYPE_MOTOR);
setMixerVectorValue(mixer,channel,VehicleConfig::MIXERVECTOR_THROTTLECURVE1, 127);
// motor
int channel = m_aircraft->fwEngineChannelBox->currentIndex() - 1;
setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_MOTOR);
setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_THROTTLECURVE1, 127);
//rudder
channel = m_aircraft->fwRudder1ChannelBox->currentIndex()-1;
setMixerType(mixer,channel,VehicleConfig::MIXERTYPE_SERVO);
// rudder
channel = m_aircraft->fwRudder1ChannelBox->currentIndex() - 1;
setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_SERVO);
setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_YAW, 127);
//ailerons
channel = m_aircraft->fwAileron1ChannelBox->currentIndex()-1;
// ailerons
channel = m_aircraft->fwAileron1ChannelBox->currentIndex() - 1;
if (channel > -1) {
setMixerType(mixer,channel,VehicleConfig::MIXERTYPE_SERVO);
setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_SERVO);
setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_ROLL, 127);
channel = m_aircraft->fwAileron2ChannelBox->currentIndex()-1;
setMixerType(mixer,channel,VehicleConfig::MIXERTYPE_SERVO);
channel = m_aircraft->fwAileron2ChannelBox->currentIndex() - 1;
setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_SERVO);
setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_ROLL, 127);
}
//elevators
channel = m_aircraft->fwElevator1ChannelBox->currentIndex()-1;
// elevators
channel = m_aircraft->fwElevator1ChannelBox->currentIndex() - 1;
if (channel > -1) {
setMixerType(mixer,channel,VehicleConfig::MIXERTYPE_SERVO);
setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_SERVO);
setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_PITCH, 127);
channel = m_aircraft->fwElevator2ChannelBox->currentIndex()-1;
setMixerType(mixer,channel,VehicleConfig::MIXERTYPE_SERVO);
channel = m_aircraft->fwElevator2ChannelBox->currentIndex() - 1;
setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_SERVO);
setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_PITCH, 127);
}
m_aircraft->fwStatusLabel->setText("Mixer generated");
return true;
}
/**
Setup Elevon
*/
bool ConfigFixedWingWidget::setupFrameElevon(QString airframeType)
{
// Check coherence:
//Show any config errors in GUI
// Show any config errors in GUI
if (throwConfigError(airframeType)) {
return false;
}
GUIConfigDataUnion config = GetConfigData();
ResetActuators(&config);
GUIConfigDataUnion config = getConfigData();
resetActuators(&config);
config.fixedwing.FixedWingRoll1 = m_aircraft->fwAileron1ChannelBox->currentIndex();
config.fixedwing.FixedWingRoll2 = m_aircraft->fwAileron2ChannelBox->currentIndex();
@ -348,8 +379,8 @@ bool ConfigFixedWingWidget::setupFrameElevon(QString airframeType)
config.fixedwing.FixedWingYaw2 = m_aircraft->fwRudder2ChannelBox->currentIndex();
config.fixedwing.FixedWingThrottle = m_aircraft->fwEngineChannelBox->currentIndex();
SetConfigData(config);
setConfigData(config);
UAVDataObject* mixer = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
Q_ASSERT(mixer);
resetMotorAndServoMixers(mixer);
@ -363,34 +394,34 @@ bool ConfigFixedWingWidget::setupFrameElevon(QString airframeType)
double value;
//motor
int channel = m_aircraft->fwEngineChannelBox->currentIndex()-1;
setMixerType(mixer,channel,VehicleConfig::MIXERTYPE_MOTOR);
setMixerVectorValue(mixer,channel,VehicleConfig::MIXERVECTOR_THROTTLECURVE1, 127);
// motor
int channel = m_aircraft->fwEngineChannelBox->currentIndex() - 1;
setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_MOTOR);
setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_THROTTLECURVE1, 127);
//rudders
channel = m_aircraft->fwRudder1ChannelBox->currentIndex()-1;
setMixerType(mixer,channel,VehicleConfig::MIXERTYPE_SERVO);
// rudders
channel = m_aircraft->fwRudder1ChannelBox->currentIndex() - 1;
setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_SERVO);
setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_YAW, 127);
channel = m_aircraft->fwRudder2ChannelBox->currentIndex()-1;
setMixerType(mixer,channel,VehicleConfig::MIXERTYPE_SERVO);
channel = m_aircraft->fwRudder2ChannelBox->currentIndex() - 1;
setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_SERVO);
setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_YAW, -127);
//ailerons
channel = m_aircraft->fwAileron1ChannelBox->currentIndex()-1;
// ailerons
channel = m_aircraft->fwAileron1ChannelBox->currentIndex() - 1;
if (channel > -1) {
setMixerType(mixer,channel,VehicleConfig::MIXERTYPE_SERVO);
value = (double)(m_aircraft->elevonSlider2->value()*1.27);
setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_SERVO);
value = (double) (m_aircraft->elevonSlider2->value() * 1.27);
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);
channel = m_aircraft->fwAileron2ChannelBox->currentIndex()-1;
setMixerType(mixer,channel,VehicleConfig::MIXERTYPE_SERVO);
value = (double)(m_aircraft->elevonSlider2->value()*1.27);
channel = m_aircraft->fwAileron2ChannelBox->currentIndex() - 1;
setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_SERVO);
value = (double) (m_aircraft->elevonSlider2->value() * 1.27);
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);
}
@ -398,21 +429,19 @@ bool ConfigFixedWingWidget::setupFrameElevon(QString airframeType)
return true;
}
/**
Setup VTail
*/
bool ConfigFixedWingWidget::setupFrameVtail(QString airframeType)
{
// Check coherence:
//Show any config errors in GUI
// Show any config errors in GUI
if (throwConfigError(airframeType)) {
return false;
}
GUIConfigDataUnion config = GetConfigData();
ResetActuators(&config);
GUIConfigDataUnion config = getConfigData();
resetActuators(&config);
config.fixedwing.FixedWingPitch1 = m_aircraft->fwElevator1ChannelBox->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.FixedWingThrottle = m_aircraft->fwEngineChannelBox->currentIndex();
SetConfigData(config);
setConfigData(config);
UAVDataObject* mixer = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
Q_ASSERT(mixer);
@ -433,14 +462,12 @@ bool ConfigFixedWingWidget::setupFrameVtail(QString airframeType)
// 1. Assign the servo/motor/none for each channel
double value;
//motor
// motor
int channel = m_aircraft->fwEngineChannelBox->currentIndex()-1;
setMixerType(mixer,channel,VehicleConfig::MIXERTYPE_MOTOR);
setMixerVectorValue(mixer,channel,VehicleConfig::MIXERVECTOR_THROTTLECURVE1, 127);
//rudders
// rudders
channel = m_aircraft->fwRudder1ChannelBox->currentIndex()-1;
setMixerType(mixer,channel,VehicleConfig::MIXERTYPE_SERVO);
setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_YAW, 127);
@ -449,7 +476,7 @@ bool ConfigFixedWingWidget::setupFrameVtail(QString airframeType)
setMixerType(mixer,channel,VehicleConfig::MIXERTYPE_SERVO);
setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_YAW, -127);
//ailerons
// ailerons
channel = m_aircraft->fwAileron1ChannelBox->currentIndex()-1;
if (channel > -1) {
setMixerType(mixer,channel,VehicleConfig::MIXERTYPE_SERVO);
@ -460,11 +487,11 @@ bool ConfigFixedWingWidget::setupFrameVtail(QString airframeType)
setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_ROLL, -127);
}
//vtail
// vtail
channel = m_aircraft->fwElevator1ChannelBox->currentIndex()-1;
if (channel > -1) {
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);
value = (double)(m_aircraft->elevonSlider1->value()*1.27);
setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_YAW, value);
@ -486,96 +513,88 @@ bool ConfigFixedWingWidget::setupFrameVtail(QString airframeType)
*/
bool ConfigFixedWingWidget::throwConfigError(QString airframeType)
{
//Initialize configuration error flag
bool error=false;
//Create a red block. All combo boxes are the same size, so any one should do as a model
int size = m_aircraft->fwEngineChannelBox->style()->pixelMetric(QStyle::PM_SmallIconSize);
QPixmap pixmap(size,size);
pixmap.fill(QColor("red"));
if (airframeType == "FixedWing" ) {
if (m_aircraft->fwEngineChannelBox->currentText() == "None"){
m_aircraft->fwEngineChannelBox->setItemData(0, pixmap, Qt::DecorationRole);//Set color palettes
error=true;
}
else{
m_aircraft->fwEngineChannelBox->setItemData(0, 0, Qt::DecorationRole);//Reset color palettes
}
if (m_aircraft->fwElevator1ChannelBox->currentText() == "None"){
m_aircraft->fwElevator1ChannelBox->setItemData(0, pixmap, Qt::DecorationRole);//Set color palettes
error=true;
}
else{
m_aircraft->fwElevator1ChannelBox->setItemData(0, 0, Qt::DecorationRole);//Reset color palettes
}
if ((m_aircraft->fwAileron1ChannelBox->currentText() == "None") && (m_aircraft->fwRudder1ChannelBox->currentText() == "None")) {
pixmap.fill(QColor("green"));
m_aircraft->fwAileron1ChannelBox->setItemData(0, pixmap, Qt::DecorationRole);//Set color palettes
m_aircraft->fwRudder1ChannelBox->setItemData(0, pixmap, Qt::DecorationRole);//Set color palettes
error=true;
}
else{
m_aircraft->fwAileron1ChannelBox->setItemData(0, 0, Qt::DecorationRole);//Reset color palettes
m_aircraft->fwRudder1ChannelBox->setItemData(0, 0, Qt::DecorationRole);//Reset color palettes
}
} else if (airframeType == "FixedWingElevon"){
if (m_aircraft->fwEngineChannelBox->currentText() == "None"){
m_aircraft->fwEngineChannelBox->setItemData(0, pixmap, Qt::DecorationRole);//Set color palettes
error=true;
}
else{
m_aircraft->fwEngineChannelBox->setItemData(0, 0, Qt::DecorationRole);//Reset color palettes
}
if(m_aircraft->fwAileron1ChannelBox->currentText() == "None"){
m_aircraft->fwAileron1ChannelBox->setItemData(0, pixmap, Qt::DecorationRole);//Set color palettes
error=true;
}
else{
m_aircraft->fwAileron1ChannelBox->setItemData(0, 0, Qt::DecorationRole);//Reset color palettes
}
if (m_aircraft->fwAileron2ChannelBox->currentText() == "None"){
m_aircraft->fwAileron2ChannelBox->setItemData(0, pixmap, Qt::DecorationRole);//Set color palettes
error=true;
}
else{
m_aircraft->fwAileron2ChannelBox->setItemData(0, 0, Qt::DecorationRole);//Reset color palettes
}
} else if ( airframeType == "FixedWingVtail"){
if (m_aircraft->fwEngineChannelBox->currentText() == "None"){
m_aircraft->fwEngineChannelBox->setItemData(0, pixmap, Qt::DecorationRole);//Set color palettes
error=true;
}
else{
m_aircraft->fwEngineChannelBox->setItemData(0, 0, Qt::DecorationRole);//Reset color palettes
}
if(m_aircraft->fwElevator1ChannelBox->currentText() == "None"){
m_aircraft->fwElevator1ChannelBox->setItemData(0, pixmap, Qt::DecorationRole);//Set color palettes
error=true;
}
else{
m_aircraft->fwElevator1ChannelBox->setItemData(0, 0, Qt::DecorationRole);//Reset color palettes
}
if(m_aircraft->fwElevator2ChannelBox->currentText() == "None"){
m_aircraft->fwElevator2ChannelBox->setItemData(0, pixmap, Qt::DecorationRole);//Set color palettes
error=true;
}
else{
m_aircraft->fwElevator2ChannelBox->setItemData(0, 0, Qt::DecorationRole);//Reset color palettes
}
}
if (error){
m_aircraft->fwStatusLabel->setText(QString("<font color='red'>ERROR: Assign all necessary channels</font>"));
}
// Initialize configuration error flag
bool error = false;
// Create a red block. All combo boxes are the same size, so any one should do as a model
int size = m_aircraft->fwEngineChannelBox->style()->pixelMetric(QStyle::PM_SmallIconSize);
QPixmap pixmap(size, size);
pixmap.fill(QColor("red"));
if (airframeType == "FixedWing") {
if (m_aircraft->fwEngineChannelBox->currentText() == "None") {
m_aircraft->fwEngineChannelBox->setItemData(0, pixmap, Qt::DecorationRole); //Set color palettes
error = true;
} else {
m_aircraft->fwEngineChannelBox->setItemData(0, 0, Qt::DecorationRole); //Reset color palettes
}
if (m_aircraft->fwElevator1ChannelBox->currentText() == "None") {
m_aircraft->fwElevator1ChannelBox->setItemData(0, pixmap, Qt::DecorationRole); //Set color palettes
error = true;
} else {
m_aircraft->fwElevator1ChannelBox->setItemData(0, 0, Qt::DecorationRole); //Reset color palettes
}
if ((m_aircraft->fwAileron1ChannelBox->currentText() == "None")
&& (m_aircraft->fwRudder1ChannelBox->currentText() == "None")) {
pixmap.fill(QColor("green"));
m_aircraft->fwAileron1ChannelBox->setItemData(0, pixmap, Qt::DecorationRole); //Set color palettes
m_aircraft->fwRudder1ChannelBox->setItemData(0, pixmap, Qt::DecorationRole); //Set color palettes
error = true;
} else {
m_aircraft->fwAileron1ChannelBox->setItemData(0, 0, Qt::DecorationRole); //Reset color palettes
m_aircraft->fwRudder1ChannelBox->setItemData(0, 0, Qt::DecorationRole); //Reset color palettes
}
} else if (airframeType == "FixedWingElevon") {
if (m_aircraft->fwEngineChannelBox->currentText() == "None") {
m_aircraft->fwEngineChannelBox->setItemData(0, pixmap, Qt::DecorationRole); //Set color palettes
error = true;
} else {
m_aircraft->fwEngineChannelBox->setItemData(0, 0, Qt::DecorationRole); //Reset color palettes
}
if (m_aircraft->fwAileron1ChannelBox->currentText() == "None") {
m_aircraft->fwAileron1ChannelBox->setItemData(0, pixmap, Qt::DecorationRole); //Set color palettes
error = true;
} else {
m_aircraft->fwAileron1ChannelBox->setItemData(0, 0, Qt::DecorationRole); //Reset color palettes
}
if (m_aircraft->fwAileron2ChannelBox->currentText() == "None") {
m_aircraft->fwAileron2ChannelBox->setItemData(0, pixmap, Qt::DecorationRole); //Set color palettes
error = true;
} else {
m_aircraft->fwAileron2ChannelBox->setItemData(0, 0, Qt::DecorationRole); //Reset color palettes
}
} else if (airframeType == "FixedWingVtail") {
if (m_aircraft->fwEngineChannelBox->currentText() == "None") {
m_aircraft->fwEngineChannelBox->setItemData(0, pixmap, Qt::DecorationRole); //Set color palettes
error = true;
} else {
m_aircraft->fwEngineChannelBox->setItemData(0, 0, Qt::DecorationRole); //Reset color palettes
}
if (m_aircraft->fwElevator1ChannelBox->currentText() == "None") {
m_aircraft->fwElevator1ChannelBox->setItemData(0, pixmap, Qt::DecorationRole); //Set color palettes
error = true;
} else {
m_aircraft->fwElevator1ChannelBox->setItemData(0, 0, Qt::DecorationRole); //Reset color palettes
}
if (m_aircraft->fwElevator2ChannelBox->currentText() == "None") {
m_aircraft->fwElevator2ChannelBox->setItemData(0, pixmap, Qt::DecorationRole); //Set color palettes
error = true;
} else {
m_aircraft->fwElevator2ChannelBox->setItemData(0, 0, Qt::DecorationRole); //Reset color palettes
}
}
if (error) {
m_aircraft->fwStatusLabel->setText(QString("<font color='red'>ERROR: Assign all necessary channels</font>"));
}
return error;
}

View File

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

View File

@ -25,8 +25,10 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "configgroundvehiclewidget.h"
#include "configvehicletypewidget.h"
#include "mixersettings.h"
#include "systemsettings.h"
#include "actuatorsettings.h"
#include "actuatorcommand.h"
#include <QDebug>
#include <QStringList>
@ -35,29 +37,58 @@
#include <QtGui/QVBoxLayout>
#include <QtGui/QPushButton>
#include <QBrush>
#include <math.h>
#include <QMessageBox>
#include "mixersettings.h"
#include "systemsettings.h"
#include "actuatorsettings.h"
#include "actuatorcommand.h"
#include <math.h>
/**
Constructor
*/
ConfigGroundVehicleWidget::ConfigGroundVehicleWidget(Ui_AircraftWidget *aircraft, QWidget *parent) : VehicleConfig(parent)
QStringList ConfigGroundVehicleWidget::getChannelDescriptions()
{
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()
{
// Do nothing
delete m_aircraft;
}
/**
@ -65,96 +96,103 @@ ConfigGroundVehicleWidget::~ConfigGroundVehicleWidget()
*/
void ConfigGroundVehicleWidget::setupUI(QString frameType)
{
m_aircraft->differentialSteeringMixBox->setHidden(true);
//STILL NEEDS WORK
// Setup the UI
setComboCurrentIndex(m_aircraft->aircraftType, m_aircraft->aircraftType->findText("Ground"));
m_aircraft->gvEngineChannelBox->setEnabled(false);
m_aircraft->gvEngineLabel->setEnabled(false);
m_aircraft->differentialSteeringMixBox->setHidden(true);
//STILL NEEDS WORK
m_aircraft->gvAileron1ChannelBox->setEnabled(false);
m_aircraft->gvAileron1Label->setEnabled(false);
m_aircraft->gvAileron2ChannelBox->setEnabled(false);
m_aircraft->gvAileron2Label->setEnabled(false);
if (frameType == "GroundVehicleDifferential" || frameType == "Differential (tank)"){ //Tank
setComboCurrentIndex(m_aircraft->groundVehicleType, m_aircraft->groundVehicleType->findText("Differential (tank)"));
m_aircraft->gvMotor1ChannelBox->setEnabled(true);
m_aircraft->gvMotor1Label->setEnabled(true);
m_aircraft->gvMotor2ChannelBox->setEnabled(true);
m_aircraft->gvMotor2Label->setEnabled(true);
// Setup the UI
m_aircraft->gvMotor1Label->setText("Left motor");
m_aircraft->gvMotor2Label->setText("Right motor");
m_aircraft->gvEngineChannelBox->setEnabled(false);
m_aircraft->gvEngineLabel->setEnabled(false);
m_aircraft->gvSteering1ChannelBox->setEnabled(false);
m_aircraft->gvSteering1Label->setEnabled(false);
m_aircraft->gvSteering2ChannelBox->setEnabled(false);
m_aircraft->gvSteering2Label->setEnabled(false);
m_aircraft->gvAileron1ChannelBox->setEnabled(false);
m_aircraft->gvAileron1Label->setEnabled(false);
m_aircraft->gvSteering2Label->setText("Rear steering");
m_aircraft->gvAileron2ChannelBox->setEnabled(false);
m_aircraft->gvAileron2Label->setEnabled(false);
m_aircraft->differentialSteeringMixBox->setHidden(false);
if (frameType == "GroundVehicleDifferential" || frameType == "Differential (tank)") {
// Tank
setComboCurrentIndex(m_aircraft->groundVehicleType,
m_aircraft->groundVehicleType->findText("Differential (tank)"));
m_aircraft->gvMotor1ChannelBox->setEnabled(true);
m_aircraft->gvMotor1Label->setEnabled(true);
m_aircraft->gvThrottleCurve1GroupBox->setTitle("Left throttle curve");
m_aircraft->gvThrottleCurve2GroupBox->setTitle("Right throttle curve");
m_aircraft->gvMotor2ChannelBox->setEnabled(true);
m_aircraft->gvMotor2Label->setEnabled(true);
}
else if (frameType == "GroundVehicleMotorcycle" || frameType == "Motorcycle"){ //Motorcycle
m_aircraft->gvMotor1Label->setText("Left motor");
m_aircraft->gvMotor2Label->setText("Right motor");
m_aircraft->gvSteering1ChannelBox->setEnabled(false);
m_aircraft->gvSteering1Label->setEnabled(false);
m_aircraft->gvSteering2ChannelBox->setEnabled(false);
m_aircraft->gvSteering2Label->setEnabled(false);
m_aircraft->gvSteering2Label->setText("Rear steering");
m_aircraft->differentialSteeringMixBox->setHidden(false);
m_aircraft->gvThrottleCurve1GroupBox->setTitle("Left throttle curve");
m_aircraft->gvThrottleCurve2GroupBox->setTitle("Right throttle curve");
} else if (frameType == "GroundVehicleMotorcycle" || frameType == "Motorcycle") {
// Motorcycle
setComboCurrentIndex(m_aircraft->groundVehicleType, m_aircraft->groundVehicleType->findText("Motorcycle"));
m_aircraft->gvMotor1ChannelBox->setEnabled(false);
m_aircraft->gvMotor1Label->setEnabled(false);
m_aircraft->gvMotor1ChannelBox->setEnabled(false);
m_aircraft->gvMotor1Label->setEnabled(false);
m_aircraft->gvMotor2ChannelBox->setEnabled(true);
m_aircraft->gvMotor2Label->setEnabled(true);
m_aircraft->gvMotor2ChannelBox->setEnabled(true);
m_aircraft->gvMotor2Label->setEnabled(true);
m_aircraft->gvMotor1Label->setText("Front motor");
m_aircraft->gvMotor2Label->setText("Rear motor");
m_aircraft->gvMotor1Label->setText("Front motor");
m_aircraft->gvMotor2Label->setText("Rear motor");
m_aircraft->gvSteering1ChannelBox->setEnabled(true);
m_aircraft->gvSteering1Label->setEnabled(true);
m_aircraft->gvSteering2ChannelBox->setEnabled(true);
m_aircraft->gvSteering2Label->setEnabled(true);
m_aircraft->gvSteering1ChannelBox->setEnabled(true);
m_aircraft->gvSteering1Label->setEnabled(true);
m_aircraft->gvSteering2Label->setText("Balancing");
m_aircraft->gvSteering2ChannelBox->setEnabled(true);
m_aircraft->gvSteering2Label->setEnabled(true);
m_aircraft->differentialSteeringMixBox->setHidden(true);
m_aircraft->gvThrottleCurve1GroupBox->setTitle("Front throttle curve");
m_aircraft->gvThrottleCurve2GroupBox->setTitle("Rear throttle curve");
}
else {//Car
m_aircraft->gvSteering2Label->setText("Balancing");
m_aircraft->differentialSteeringMixBox->setHidden(true);
m_aircraft->gvThrottleCurve1GroupBox->setTitle("Front throttle curve");
m_aircraft->gvThrottleCurve2GroupBox->setTitle("Rear throttle curve");
} else {
// Car
setComboCurrentIndex(m_aircraft->groundVehicleType, m_aircraft->groundVehicleType->findText("Turnable (car)"));
m_aircraft->gvMotor1ChannelBox->setEnabled(true);
m_aircraft->gvMotor1Label->setEnabled(true);
m_aircraft->gvMotor2ChannelBox->setEnabled(true);
m_aircraft->gvMotor2Label->setEnabled(true);
m_aircraft->gvMotor1Label->setText("Front motor");
m_aircraft->gvMotor2Label->setText("Rear motor");
m_aircraft->gvSteering1ChannelBox->setEnabled(true);
m_aircraft->gvSteering1Label->setEnabled(true);
m_aircraft->gvSteering2ChannelBox->setEnabled(true);
m_aircraft->gvSteering2Label->setEnabled(true);
m_aircraft->differentialSteeringMixBox->setHidden(true);
m_aircraft->gvThrottleCurve1GroupBox->setTitle("Front throttle curve");
m_aircraft->gvThrottleCurve2GroupBox->setTitle("Rear throttle curve");
}
m_aircraft->gvMotor1ChannelBox->setEnabled(true);
m_aircraft->gvMotor1Label->setEnabled(true);
m_aircraft->gvMotor2ChannelBox->setEnabled(true);
m_aircraft->gvMotor2Label->setEnabled(true);
m_aircraft->gvMotor1Label->setText("Front motor");
m_aircraft->gvMotor2Label->setText("Rear motor");
m_aircraft->gvSteering1ChannelBox->setEnabled(true);
m_aircraft->gvSteering1Label->setEnabled(true);
m_aircraft->gvSteering2ChannelBox->setEnabled(true);
m_aircraft->gvSteering2Label->setEnabled(true);
m_aircraft->differentialSteeringMixBox->setHidden(true);
m_aircraft->gvThrottleCurve1GroupBox->setTitle("Front 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.GroundVehicleSteering2 = 0;
@ -162,213 +200,202 @@ void ConfigGroundVehicleWidget::ResetActuators(GUIConfigDataUnion* configData)
configData->ground.GroundVehicleThrottle2 = 0;
}
QStringList ConfigGroundVehicleWidget::getChannelDescriptions()
/**
Virtual function to refresh the UI widget values
*/
void ConfigGroundVehicleWidget::refreshWidgetsValues(QString frameType)
{
int i;
QStringList channelDesc;
setupUI(frameType);
// init a channel_numelem list of channel desc defaults
for (i=0; i < (int)(ConfigGroundVehicleWidget::CHANNEL_NUMELEM); i++)
{
channelDesc.append(QString("-"));
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->groundVehicleThrottle1->initCurve(&curveValues);
} else {
// no, init a straight curve
m_aircraft->groundVehicleThrottle1->initLinearCurve(curveValues.count(), 1.0);
}
// get the gui config data
GUIConfigDataUnion configData = GetConfigData();
// Setup all Throttle2 curves for all types of airframes
getThrottleCurve(mixer, VehicleConfig::MIXER_THROTTLECURVE2, &curveValues);
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");
if (isValidThrottleCurve(&curveValues)) {
m_aircraft->groundVehicleThrottle2->initCurve(&curveValues);
} else {
m_aircraft->groundVehicleThrottle2->initLinearCurve(curveValues.count(), 1.0);
}
GUIConfigDataUnion config = getConfigData();
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
*/
QString ConfigGroundVehicleWidget::updateConfigObjectsFromWidgets()
{
QString airframeType = "GroundVehicleCar";
// Save the curve (common to all ground vehicle frames)
QString airframeType = "GroundVehicleCar";
// Save the curve (common to all ground vehicle frames)
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);
// set the throttle curves
setThrottleCurve(mixer, VehicleConfig::MIXER_THROTTLECURVE1, m_aircraft->groundVehicleThrottle1->getCurve() );
setThrottleCurve(mixer, VehicleConfig::MIXER_THROTTLECURVE2, m_aircraft->groundVehicleThrottle2->getCurve() );
setThrottleCurve(mixer, VehicleConfig::MIXER_THROTTLECURVE1, m_aircraft->groundVehicleThrottle1->getCurve());
setThrottleCurve(mixer, VehicleConfig::MIXER_THROTTLECURVE2, m_aircraft->groundVehicleThrottle2->getCurve());
//All airframe types must start with "GroundVehicle"
if (m_aircraft->groundVehicleType->currentText() == "Turnable (car)" ) {
airframeType = "GroundVehicleCar";
setupGroundVehicleCar(airframeType);
} else if (m_aircraft->groundVehicleType->currentText() == "Differential (tank)") {
airframeType = "GroundVehicleDifferential";
setupGroundVehicleDifferential(airframeType);
} else { // "Motorcycle"
airframeType = "GroundVehicleMotorcycle";
setupGroundVehicleMotorcycle(airframeType);
}
// All airframe types must start with "GroundVehicle"
if (m_aircraft->groundVehicleType->currentText() == "Turnable (car)") {
airframeType = "GroundVehicleCar";
setupGroundVehicleCar(airframeType);
} else if (m_aircraft->groundVehicleType->currentText() == "Differential (tank)") {
airframeType = "GroundVehicleDifferential";
setupGroundVehicleDifferential(airframeType);
} else { // "Motorcycle"
airframeType = "GroundVehicleMotorcycle";
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.
Returns False if impossible to create the mixer.
*/
bool ConfigGroundVehicleWidget::setupGroundVehicleMotorcycle(QString airframeType){
// Check coherence:
//Show any config errors in GUI
bool ConfigGroundVehicleWidget::setupGroundVehicleMotorcycle(QString airframeType)
{
// Check coherence:
// Show any config errors in GUI
if (throwConfigError(airframeType)) {
return false;
}
return false;
}
// Now setup the channels:
GUIConfigDataUnion config = GetConfigData();
ResetActuators(&config);
// Now setup the channels:
GUIConfigDataUnion config = getConfigData();
resetActuators(&config);
config.ground.GroundVehicleThrottle1 = m_aircraft->gvMotor1ChannelBox->currentIndex();
config.ground.GroundVehicleThrottle2 = m_aircraft->gvMotor2ChannelBox->currentIndex();
SetConfigData(config);
setConfigData(config);
UAVDataObject* mixer = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
Q_ASSERT(mixer);
resetMotorAndServoMixers(mixer);
//motor
int channel = m_aircraft->gvMotor2ChannelBox->currentIndex()-1;
// motor
int channel = m_aircraft->gvMotor2ChannelBox->currentIndex() - 1;
setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_SERVO);
setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_THROTTLECURVE1, 127);
setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_YAW, 127);
//steering
channel = m_aircraft->gvSteering1ChannelBox->currentIndex()-1;
// steering
channel = m_aircraft->gvSteering1ChannelBox->currentIndex() - 1;
setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_SERVO);
setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_YAW, -127);
setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_ROLL, -127);
//balance
channel = m_aircraft->gvSteering2ChannelBox->currentIndex()-1;
// balance
channel = m_aircraft->gvSteering2ChannelBox->currentIndex() - 1;
setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_SERVO);
setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_YAW, 127);
setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_ROLL, 127);
m_aircraft->gvStatusLabel->setText("Mixer generated");
m_aircraft->gvStatusLabel->setText("Mixer generated");
return true;
}
/**
Setup differentially steered ground vehicle.
Returns False if impossible to create the mixer.
*/
bool ConfigGroundVehicleWidget::setupGroundVehicleDifferential(QString airframeType){
// Check coherence:
//Show any config errors in GUI
bool ConfigGroundVehicleWidget::setupGroundVehicleDifferential(QString airframeType)
{
// Check coherence:
// Show any config errors in GUI
if (throwConfigError(airframeType)) {
return false;
}
return false;
}
// Now setup the channels:
GUIConfigDataUnion config = GetConfigData();
ResetActuators(&config);
GUIConfigDataUnion config = getConfigData();
resetActuators(&config);
config.ground.GroundVehicleThrottle1 = m_aircraft->gvMotor1ChannelBox->currentIndex();
config.ground.GroundVehicleThrottle2 = m_aircraft->gvMotor2ChannelBox->currentIndex();
SetConfigData((config));
UAVDataObject* mixer = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
setConfigData(config);
UAVDataObject *mixer = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
Q_ASSERT(mixer);
resetMotorAndServoMixers(mixer);
//left motor
int channel = m_aircraft->gvMotor1ChannelBox->currentIndex()-1;
// left motor
int channel = m_aircraft->gvMotor1ChannelBox->currentIndex() - 1;
setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_SERVO);
setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_THROTTLECURVE1, 127);
setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_YAW, 127);
//right motor
channel = m_aircraft->gvMotor2ChannelBox->currentIndex()-1;
// right motor
channel = m_aircraft->gvMotor2ChannelBox->currentIndex() - 1;
setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_SERVO);
setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_THROTTLECURVE2, 127);
setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_YAW, -127);
//Output success message
m_aircraft->gvStatusLabel->setText("Mixer generated");
// Output success message
m_aircraft->gvStatusLabel->setText("Mixer generated");
return true;
}
/**
Setup steerable ground vehicle.
@ -377,45 +404,45 @@ bool ConfigGroundVehicleWidget::setupGroundVehicleDifferential(QString airframeT
bool ConfigGroundVehicleWidget::setupGroundVehicleCar(QString airframeType)
{
// Check coherence:
//Show any config errors in GUI
// Show any config errors in GUI
if (throwConfigError(airframeType)) {
return false;
}
return false;
}
// Now setup the channels:
GUIConfigDataUnion config = GetConfigData();
ResetActuators(&config);
GUIConfigDataUnion config = getConfigData();
resetActuators(&config);
config.ground.GroundVehicleThrottle1 = m_aircraft->gvMotor1ChannelBox->currentIndex();
config.ground.GroundVehicleThrottle2 = m_aircraft->gvMotor2ChannelBox->currentIndex();
config.ground.GroundVehicleSteering1 = m_aircraft->gvSteering1ChannelBox->currentIndex();
config.ground.GroundVehicleSteering2 = m_aircraft->gvSteering2ChannelBox->currentIndex();
SetConfigData(config);
setConfigData(config);
UAVDataObject* mixer = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
Q_ASSERT(mixer);
resetMotorAndServoMixers(mixer);
int channel = m_aircraft->gvSteering1ChannelBox->currentIndex()-1;
setMixerType(mixer,channel, VehicleConfig::MIXERTYPE_SERVO);
int channel = m_aircraft->gvSteering1ChannelBox->currentIndex() - 1;
setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_SERVO);
setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_YAW, 127);
channel = m_aircraft->gvSteering2ChannelBox->currentIndex()-1;
setMixerType(mixer,channel, VehicleConfig::MIXERTYPE_SERVO);
channel = m_aircraft->gvSteering2ChannelBox->currentIndex() - 1;
setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_SERVO);
setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_YAW, -127);
channel = m_aircraft->gvMotor1ChannelBox->currentIndex()-1;
setMixerType(mixer,channel, VehicleConfig::MIXERTYPE_SERVO);
channel = m_aircraft->gvMotor1ChannelBox->currentIndex() - 1;
setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_SERVO);
setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_THROTTLECURVE1, 127);
channel = m_aircraft->gvMotor2ChannelBox->currentIndex()-1;
setMixerType(mixer,channel, VehicleConfig::MIXERTYPE_SERVO);
channel = m_aircraft->gvMotor2ChannelBox->currentIndex() - 1;
setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_SERVO);
setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_THROTTLECURVE2, 127);
//Output success message
// Output success message
m_aircraft->gvStatusLabel->setText("Mixer generated");
return true;
}
@ -424,94 +451,91 @@ bool ConfigGroundVehicleWidget::setupGroundVehicleCar(QString airframeType)
*/
bool ConfigGroundVehicleWidget::throwConfigError(QString airframeType)
{
//Initialize configuration error flag
bool error=false;
// Initialize configuration error flag
bool error = false;
//Create a red block. All combo boxes are the same size, so any one should do as a model
int size = m_aircraft->gvEngineChannelBox->style()->pixelMetric(QStyle::PM_SmallIconSize);
QPixmap pixmap(size,size);
pixmap.fill(QColor("red"));
if (airframeType == "GroundVehicleCar" ) { //Car
if(m_aircraft->gvMotor1ChannelBox->currentText() == "None" && m_aircraft->gvMotor2ChannelBox->currentText() == "None"){
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;
// 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"));
}
else{
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") {
m_aircraft->gvSteering1ChannelBox->setItemData(0, pixmap, Qt::DecorationRole);//Set color palettes
m_aircraft->gvSteering2ChannelBox->setItemData(0, pixmap, Qt::DecorationRole);//Set color palettes
// m_aircraft->gvStatusLabel->setText("<font color='red'>ERROR: check steering channel assignment</font>");
// m_aircraft->gvSteering1Label->setText("<font color='red'>" + m_aircraft->gvSteering1Label->text() + "</font>");
// m_aircraft->gvSteering2Label->setText("<font color='red'>" + m_aircraft->gvSteering2Label->text() + "</font>");
error=true;
}
else{
m_aircraft->gvSteering1ChannelBox->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.
// m_aircraft->gvSteering1Label->setText(htmlText->toPlainText());
// 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
if(m_aircraft->gvMotor1ChannelBox->currentText() == "None" || m_aircraft->gvMotor2ChannelBox->currentText() == "None"){
m_aircraft->gvMotor1ChannelBox->setItemData(0, pixmap, Qt::DecorationRole);//Set color palettes
m_aircraft->gvMotor2ChannelBox->setItemData(0, pixmap, Qt::DecorationRole);//Set 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
m_aircraft->gvSteering1ChannelBox->setItemData(0, 0, Qt::DecorationRole);//Reset color palettes
m_aircraft->gvSteering2ChannelBox->setItemData(0, 0, Qt::DecorationRole);//Reset color palettes
} else if ( airframeType == "GroundVehicleMotorcycle"){ //Motorcycle
if(m_aircraft->gvMotor1ChannelBox->currentText() == "None" && m_aircraft->gvMotor2ChannelBox->currentText() == "None"){
m_aircraft->gvMotor2ChannelBox->setItemData(0, pixmap, Qt::DecorationRole);//Set color palettes
error=true;
}
else{
m_aircraft->gvMotor2ChannelBox->setItemData(0, 0, Qt::DecorationRole);//Reset color palettes
}
if (m_aircraft->gvSteering1ChannelBox->currentText() == "None" && m_aircraft->gvSteering2ChannelBox->currentText() == "None") {
m_aircraft->gvSteering1ChannelBox->setItemData(0, pixmap, Qt::DecorationRole);//Set color palettes
error=true;
}
else{
m_aircraft->gvSteering1ChannelBox->setItemData(0, 0, Qt::DecorationRole);//Reset color palettes
}
//Always reset
m_aircraft->gvMotor1ChannelBox->setItemData(0, 0, Qt::DecorationRole);//Reset color palettes
m_aircraft->gvSteering2ChannelBox->setItemData(0, 0, Qt::DecorationRole);//Reset color palettes
}
if (error){
m_aircraft->gvStatusLabel->setText(QString("<font color='red'>ERROR: Assign all necessary channels</font>"));
}
if (airframeType == "GroundVehicleCar") { //Car
if (m_aircraft->gvMotor1ChannelBox->currentText() == "None"
&& m_aircraft->gvMotor2ChannelBox->currentText() == "None") {
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;
} else {
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") {
m_aircraft->gvSteering1ChannelBox->setItemData(0, pixmap, Qt::DecorationRole); //Set color palettes
m_aircraft->gvSteering2ChannelBox->setItemData(0, pixmap, Qt::DecorationRole); //Set color palettes
//m_aircraft->gvStatusLabel->setText("<font color='red'>ERROR: check steering channel assignment</font>");
//m_aircraft->gvSteering1Label->setText("<font color='red'>" + m_aircraft->gvSteering1Label->text() + "</font>");
//m_aircraft->gvSteering2Label->setText("<font color='red'>" + m_aircraft->gvSteering2Label->text() + "</font>");
error = true;
} else {
m_aircraft->gvSteering1ChannelBox->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.
//m_aircraft->gvSteering1Label->setText(htmlText->toPlainText());
//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
if (m_aircraft->gvMotor1ChannelBox->currentText() == "None"
|| m_aircraft->gvMotor2ChannelBox->currentText() == "None") {
m_aircraft->gvMotor1ChannelBox->setItemData(0, pixmap, Qt::DecorationRole); //Set color palettes
m_aircraft->gvMotor2ChannelBox->setItemData(0, pixmap, Qt::DecorationRole); //Set 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
m_aircraft->gvSteering1ChannelBox->setItemData(0, 0, Qt::DecorationRole); //Reset color palettes
m_aircraft->gvSteering2ChannelBox->setItemData(0, 0, Qt::DecorationRole); //Reset color palettes
} else if (airframeType == "GroundVehicleMotorcycle") { //Motorcycle
if (m_aircraft->gvMotor1ChannelBox->currentText() == "None"
&& m_aircraft->gvMotor2ChannelBox->currentText() == "None") {
m_aircraft->gvMotor2ChannelBox->setItemData(0, pixmap, Qt::DecorationRole); //Set color palettes
error = true;
} else {
m_aircraft->gvMotor2ChannelBox->setItemData(0, 0, Qt::DecorationRole); //Reset color palettes
}
if (m_aircraft->gvSteering1ChannelBox->currentText() == "None"
&& m_aircraft->gvSteering2ChannelBox->currentText() == "None") {
m_aircraft->gvSteering1ChannelBox->setItemData(0, pixmap, Qt::DecorationRole); //Set color palettes
error = true;
} else {
m_aircraft->gvSteering1ChannelBox->setItemData(0, 0, Qt::DecorationRole); //Reset color palettes
}
// Always reset
m_aircraft->gvMotor1ChannelBox->setItemData(0, 0, Qt::DecorationRole); //Reset color palettes
m_aircraft->gvSteering2ChannelBox->setItemData(0, 0, Qt::DecorationRole); //Reset color palettes
}
if (error) {
m_aircraft->gvStatusLabel->setText(QString("<font color='red'>ERROR: Assign all necessary channels</font>"));
}
return error;
}

View File

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

View File

@ -25,6 +25,10 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "configmultirotorwidget.h"
#include "mixersettings.h"
#include "systemsettings.h"
#include "actuatorsettings.h"
#include "actuatorcommand.h"
#include <QDebug>
#include <QStringList>
@ -37,48 +41,106 @@
#include <math.h>
#include <QMessageBox>
#include "mixersettings.h"
#include "systemsettings.h"
#include "actuatorsettings.h"
#include "actuatorcommand.h"
const QString ConfigMultiRotorWidget::CHANNELBOXNAME = QString("multiMotorChannelBox");
/**
Constructor
*/
ConfigMultiRotorWidget::ConfigMultiRotorWidget(Ui_AircraftWidget *aircraft, QWidget *parent) : VehicleConfig(parent), invertMotors(1)
QStringList ConfigMultiRotorWidget::getChannelDescriptions()
{
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()
{
// Do nothing
delete m_aircraft;
}
void ConfigMultiRotorWidget::setupUI(QString frameType)
{
Q_ASSERT(m_aircraft);
Q_ASSERT(uiowner);
Q_ASSERT(quad);
int i;
// set aircraftType to Multirotor, disable triyaw channel
setComboCurrentIndex(m_aircraft->aircraftType, m_aircraft->aircraftType->findText("Multirotor"));
// disable triyaw channel
m_aircraft->triYawChannelBox->setEnabled(false);
// 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
QComboBox *combobox = qFindChild<QComboBox*>(uiowner, "multiMotorChannelBox" + QString::number(i));
QComboBox *combobox = qFindChild<QComboBox*>(this, "multiMotorChannelBox" + QString::number(i));
if (combobox) {
combobox->setEnabled(false);
combobox->setItemData(0, 0, Qt::DecorationRole);
@ -86,198 +148,125 @@ void ConfigMultiRotorWidget::setupUI(QString frameType)
}
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...
enableComboBoxes(uiowner, CHANNELBOXNAME, 3, true);
// Enable all necessary motor channel boxes...
enableComboBoxes(this, CHANNELBOXNAME, 3, true);
m_aircraft->mrRollMixLevel->setValue(100);
m_aircraft->mrPitchMixLevel->setValue(100);
setYawMixLevel(50);
m_aircraft->triYawChannelBox->setEnabled(true);
}
else if (frameType == "QuadX" || frameType == "Quad X") {
setComboCurrentIndex( m_aircraft->multirotorFrameType, m_aircraft->multirotorFrameType->findText("Quad X"));
} else if (frameType == "QuadX" || frameType == "Quad X") {
setComboCurrentIndex(m_aircraft->multirotorFrameType, m_aircraft->multirotorFrameType->findText("Quad X"));
//Enable all necessary motor channel boxes...
enableComboBoxes(uiowner, CHANNELBOXNAME, 4, true);
// Enable all necessary motor channel boxes...
enableComboBoxes(this, CHANNELBOXNAME, 4, true);
// init mixer levels
m_aircraft->mrRollMixLevel->setValue(50);
m_aircraft->mrPitchMixLevel->setValue(50);
setYawMixLevel(50);
}
else if (frameType == "QuadP" || frameType == "Quad +") {
setComboCurrentIndex( m_aircraft->multirotorFrameType, m_aircraft->multirotorFrameType->findText("Quad +"));
} else if (frameType == "QuadP" || frameType == "Quad +") {
setComboCurrentIndex(m_aircraft->multirotorFrameType, m_aircraft->multirotorFrameType->findText("Quad +"));
//Enable all necessary motor channel boxes...
enableComboBoxes(uiowner, CHANNELBOXNAME, 4, true);
// Enable all necessary motor channel boxes...
enableComboBoxes(this, CHANNELBOXNAME, 4, true);
m_aircraft->mrRollMixLevel->setValue(100);
m_aircraft->mrPitchMixLevel->setValue(100);
setYawMixLevel(50);
}
else if (frameType == "Hexa" || frameType == "Hexacopter")
{
setComboCurrentIndex( m_aircraft->multirotorFrameType, m_aircraft->multirotorFrameType->findText("Hexacopter"));
} else if (frameType == "Hexa" || frameType == "Hexacopter") {
setComboCurrentIndex(m_aircraft->multirotorFrameType, m_aircraft->multirotorFrameType->findText("Hexacopter"));
//Enable all necessary motor channel boxes...
enableComboBoxes(uiowner, CHANNELBOXNAME, 6, true);
// Enable all necessary motor channel boxes...
enableComboBoxes(this, CHANNELBOXNAME, 6, true);
m_aircraft->mrRollMixLevel->setValue(50);
m_aircraft->mrPitchMixLevel->setValue(33);
setYawMixLevel(33);
}
else if (frameType == "HexaX" || frameType == "Hexacopter X" ) {
setComboCurrentIndex( m_aircraft->multirotorFrameType, m_aircraft->multirotorFrameType->findText("Hexacopter X"));
} else if (frameType == "HexaX" || frameType == "Hexacopter X") {
setComboCurrentIndex(m_aircraft->multirotorFrameType,
m_aircraft->multirotorFrameType->findText("Hexacopter X"));
//Enable all necessary motor channel boxes...
enableComboBoxes(uiowner, CHANNELBOXNAME, 6, true);
// Enable all necessary motor channel boxes...
enableComboBoxes(this, CHANNELBOXNAME, 6, true);
m_aircraft->mrRollMixLevel->setValue(33);
m_aircraft->mrPitchMixLevel->setValue(50);
setYawMixLevel(33);
} else if (frameType == "HexaCoax" || frameType == "Hexacopter Y6") {
setComboCurrentIndex(m_aircraft->multirotorFrameType,
m_aircraft->multirotorFrameType->findText("Hexacopter Y6"));
}
else if (frameType == "HexaCoax" || frameType == "Hexacopter Y6")
{
setComboCurrentIndex( m_aircraft->multirotorFrameType, m_aircraft->multirotorFrameType->findText("Hexacopter Y6"));
//Enable all necessary motor channel boxes...
enableComboBoxes(uiowner, CHANNELBOXNAME, 6, true);
// Enable all necessary motor channel boxes...
enableComboBoxes(this, CHANNELBOXNAME, 6, true);
m_aircraft->mrRollMixLevel->setValue(100);
m_aircraft->mrPitchMixLevel->setValue(50);
setYawMixLevel(66);
} else if (frameType == "Octo" || frameType == "Octocopter") {
setComboCurrentIndex(m_aircraft->multirotorFrameType, m_aircraft->multirotorFrameType->findText("Octocopter"));
}
else if (frameType == "Octo" || frameType == "Octocopter")
{
setComboCurrentIndex( m_aircraft->multirotorFrameType, m_aircraft->multirotorFrameType->findText("Octocopter"));
//Enable all necessary motor channel boxes
enableComboBoxes(uiowner, CHANNELBOXNAME, 8, true);
// Enable all necessary motor channel boxes
enableComboBoxes(this, CHANNELBOXNAME, 8, true);
m_aircraft->mrRollMixLevel->setValue(33);
m_aircraft->mrPitchMixLevel->setValue(33);
setYawMixLevel(25);
}
else if (frameType == "OctoV" || frameType == "Octocopter V")
{
setComboCurrentIndex( m_aircraft->multirotorFrameType, m_aircraft->multirotorFrameType->findText("Octocopter V"));
} else if (frameType == "OctoV" || frameType == "Octocopter V") {
setComboCurrentIndex(m_aircraft->multirotorFrameType,
m_aircraft->multirotorFrameType->findText("Octocopter V"));
//Enable all necessary motor channel boxes
enableComboBoxes(uiowner, CHANNELBOXNAME, 8, true);
// Enable all necessary motor channel boxes
enableComboBoxes(this, CHANNELBOXNAME, 8, true);
m_aircraft->mrRollMixLevel->setValue(25);
m_aircraft->mrPitchMixLevel->setValue(25);
setYawMixLevel(25);
} else if (frameType == "OctoCoaxP" || frameType == "Octo Coax +") {
setComboCurrentIndex(m_aircraft->multirotorFrameType, m_aircraft->multirotorFrameType->findText("Octo Coax +"));
}
else if (frameType == "OctoCoaxP" || frameType == "Octo Coax +")
{
setComboCurrentIndex( m_aircraft->multirotorFrameType, m_aircraft->multirotorFrameType->findText("Octo Coax +"));
//Enable all necessary motor channel boxes
enableComboBoxes(uiowner, CHANNELBOXNAME, 8, true);
// Enable all necessary motor channel boxes
enableComboBoxes(this, CHANNELBOXNAME, 8, true);
m_aircraft->mrRollMixLevel->setValue(100);
m_aircraft->mrPitchMixLevel->setValue(100);
setYawMixLevel(50);
} else if (frameType == "OctoCoaxX" || frameType == "Octo Coax X") {
setComboCurrentIndex(m_aircraft->multirotorFrameType, m_aircraft->multirotorFrameType->findText("Octo Coax X"));
}
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
enableComboBoxes(uiowner, CHANNELBOXNAME, 8, true);
// Enable all necessary motor channel boxes
enableComboBoxes(this, CHANNELBOXNAME, 8, true);
m_aircraft->mrRollMixLevel->setValue(50);
m_aircraft->mrPitchMixLevel->setValue(50);
setYawMixLevel(50);
}
//Draw the appropriate airframe
drawAirframe(frameType);
// Draw the appropriate airframe
updateAirframe(frameType);
}
void ConfigMultiRotorWidget::drawAirframe(QString frameType){
invertMotors = m_aircraft->MultirotorRevMixercheckBox->isChecked() ? -1:1;
if (frameType == "Tri" || frameType == "Tricopter Y") {
if(invertMotors > 0)
quad->setElementId("tri");
else
quad->setElementId("tri_reverse");
}
else if (frameType == "QuadX" || frameType == "Quad X") {
if(invertMotors > 0)
quad->setElementId("quad-x");
else
quad->setElementId("quad-x_reverse");
}
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::registerWidgets(ConfigTaskWidget &parent) {
parent.addWidget(m_aircraft->multiThrottleCurve->getCurveWidget());
parent.addWidget(m_aircraft->multirotorFrameType);
parent.addWidget(m_aircraft->multiMotorChannelBox1);
parent.addWidget(m_aircraft->multiMotorChannelBox2);
parent.addWidget(m_aircraft->multiMotorChannelBox3);
parent.addWidget(m_aircraft->multiMotorChannelBox4);
parent.addWidget(m_aircraft->multiMotorChannelBox5);
parent.addWidget(m_aircraft->multiMotorChannelBox6);
parent.addWidget(m_aircraft->multiMotorChannelBox7);
parent.addWidget(m_aircraft->multiMotorChannelBox8);
parent.addWidget(m_aircraft->mrPitchMixLevel);
parent.addWidget(m_aircraft->mrRollMixLevel);
parent.addWidget(m_aircraft->mrYawMixLevel);
parent.addWidget(m_aircraft->triYawChannelBox);
}
void ConfigMultiRotorWidget::ResetActuators(GUIConfigDataUnion* configData)
void ConfigMultiRotorWidget::resetActuators(GUIConfigDataUnion *configData)
{
configData->multi.VTOLMotorN = 0;
configData->multi.VTOLMotorNE = 0;
@ -290,74 +279,262 @@ void ConfigMultiRotorWidget::ResetActuators(GUIConfigDataUnion* configData)
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
for (int i=0; i < (int)(ConfigMultiRotorWidget::CHANNEL_NUMELEM); i++)
{
channelDesc.append(QString("-"));
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->multiThrottleCurve->initCurve(&curveValues);
} else {
// no, init a straight curve
m_aircraft->multiThrottleCurve->initLinearCurve(curveValues.count(), 0.9);
}
// get the gui config data
GUIConfigDataUnion configData = GetConfigData();
multiGUISettingsStruct multi = configData.multi;
GUIConfigDataUnion config = getConfigData();
multiGUISettingsStruct multi = config.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");
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);
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
*/
QString ConfigMultiRotorWidget::updateConfigObjectsFromWidgets()
{
QString airframeType;
QList<QString> motorList;
UAVDataObject* mixerObj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
Q_ASSERT(mixerObj);
UAVDataObject *mixer = dynamic_cast<UAVDataObject *>(getObjectManager()->getObject(QString("MixerSettings")));
Q_ASSERT(mixer);
// 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 +") {
airframeType = "QuadP";
setupQuad(true);
@ -373,135 +550,134 @@ QString ConfigMultiRotorWidget::updateConfigObjectsFromWidgets()
} else if (m_aircraft->multirotorFrameType->currentText() == "Hexacopter Y6") {
airframeType = "HexaCoax";
//Show any config errors in GUI
// Show any config errors in GUI
if (throwConfigError(6)) {
return airframeType;
}
motorList << "VTOLMotorNW" << "VTOLMotorW" << "VTOLMotorNE" << "VTOLMotorE"
<< "VTOLMotorS" << "VTOLMotorSE";
motorList << "VTOLMotorNW" << "VTOLMotorW" << "VTOLMotorNE" << "VTOLMotorE" << "VTOLMotorS" << "VTOLMotorSE";
setupMotors(motorList);
// Motor 1 to 6, Y6 Layout:
// pitch roll yaw
double mixer [8][3] = {
{ 0.5, 1, -1},
{ 0.5, 1, 1},
{ 0.5, -1, -1},
{ 0.5, -1, 1},
{ -1, 0, -1},
{ -1, 0, 1},
{ 0, 0, 0},
{ 0, 0, 0}
double mixerMatrix[8][3] = {
{ 0.5, 1, -1 },
{ 0.5, 1, 1 },
{ 0.5, -1, -1 },
{ 0.5, -1, 1 },
{ -1, 0, -1 },
{ -1, 0, 1 },
{ 0, 0, 0 },
{ 0, 0, 0 }
};
setupMultiRotorMixer(mixer);
setupMultiRotorMixer(mixerMatrix);
m_aircraft->mrStatusLabel->setText("Configuration OK");
} else if (m_aircraft->multirotorFrameType->currentText() == "Octocopter") {
airframeType = "Octo";
//Show any config errors in GUI
// Show any config errors in GUI
if (throwConfigError(8)) {
return airframeType;
}
motorList << "VTOLMotorN" << "VTOLMotorNE" << "VTOLMotorE" << "VTOLMotorSE"
<< "VTOLMotorS" << "VTOLMotorSW" << "VTOLMotorW" << "VTOLMotorNW";
motorList << "VTOLMotorN" << "VTOLMotorNE" << "VTOLMotorE" << "VTOLMotorSE" << "VTOLMotorS" << "VTOLMotorSW"
<< "VTOLMotorW" << "VTOLMotorNW";
setupMotors(motorList);
// Motor 1 to 8:
// pitch roll yaw
double mixer [8][3] = {
{ 1, 0, -1},
{ 1, -1, 1},
{ 0, -1, -1},
{ -1, -1, 1},
{ -1, 0, -1},
{ -1, 1, 1},
{ 0, 1, -1},
{ 1, 1, 1}
double mixerMatrix[8][3] = {
{ 1, 0, -1 },
{ 1, -1, 1 },
{ 0, -1, -1 },
{ -1, -1, 1 },
{ -1, 0, -1 },
{ -1, 1, 1 },
{ 0, 1, -1 },
{ 1, 1, 1 }
};
setupMultiRotorMixer(mixer);
setupMultiRotorMixer(mixerMatrix);
m_aircraft->mrStatusLabel->setText("Configuration OK");
} else if (m_aircraft->multirotorFrameType->currentText() == "Octocopter V") {
airframeType = "OctoV";
//Show any config errors in GUI
// Show any config errors in GUI
if (throwConfigError(8)) {
return airframeType;
}
motorList << "VTOLMotorN" << "VTOLMotorNE" << "VTOLMotorE" << "VTOLMotorSE"
<< "VTOLMotorS" << "VTOLMotorSW" << "VTOLMotorW" << "VTOLMotorNW";
motorList << "VTOLMotorN" << "VTOLMotorNE" << "VTOLMotorE" << "VTOLMotorSE" << "VTOLMotorS" << "VTOLMotorSW"
<< "VTOLMotorW" << "VTOLMotorNW";
setupMotors(motorList);
// Motor 1 to 8:
// IMPORTANT: Assumes evenly spaced engines
// pitch roll yaw
double mixer [8][3] = {
{ 0.33, -1, -1},
{ 1 , -1, 1},
{ -1 , -1, -1},
{ -0.33, -1, 1},
{ -0.33, 1, -1},
{ -1 , 1, 1},
{ 1 , 1, -1},
{ 0.33, 1, 1}
double mixerMatrix[8][3] = {
{ 0.33, -1, -1 },
{ 1 , -1, 1 },
{ -1 , -1, -1 },
{ -0.33, -1, 1 },
{ -0.33, 1, -1 },
{ -1 , 1, 1 },
{ 1 , 1, -1 },
{ 0.33, 1, 1 }
};
setupMultiRotorMixer(mixer);
setupMultiRotorMixer(mixerMatrix);
m_aircraft->mrStatusLabel->setText("Configuration OK");
} else if (m_aircraft->multirotorFrameType->currentText() == "Octo Coax +") {
airframeType = "OctoCoaxP";
//Show any config errors in GUI
// Show any config errors in GUI
if (throwConfigError(8)) {
return airframeType;
}
motorList << "VTOLMotorN" << "VTOLMotorNE" << "VTOLMotorE" << "VTOLMotorSE"
<< "VTOLMotorS" << "VTOLMotorSW" << "VTOLMotorW" << "VTOLMotorNW";
motorList << "VTOLMotorN" << "VTOLMotorNE" << "VTOLMotorE" << "VTOLMotorSE" << "VTOLMotorS" << "VTOLMotorSW"
<< "VTOLMotorW" << "VTOLMotorNW";
setupMotors(motorList);
// Motor 1 to 8:
// pitch roll yaw
double mixer [8][3] = {
{ 1, 0, -1},
{ 1, 0, 1},
{ 0, -1, -1},
{ 0, -1, 1},
{ -1, 0, -1},
{ -1, 0, 1},
{ 0, 1, -1},
{ 0, 1, 1}
double mixerMatrix[8][3] = {
{ 1, 0, -1 },
{ 1, 0, 1 },
{ 0, -1, -1 },
{ 0, -1, 1 },
{ -1, 0, -1 },
{ -1, 0, 1 },
{ 0, 1, -1 },
{ 0, 1, 1 }
};
setupMultiRotorMixer(mixer);
setupMultiRotorMixer(mixerMatrix);
m_aircraft->mrStatusLabel->setText("Configuration OK");
} else if (m_aircraft->multirotorFrameType->currentText() == "Octo Coax X") {
airframeType = "OctoCoaxX";
//Show any config errors in GUI
// Show any config errors in GUI
if (throwConfigError(8)) {
return airframeType;
}
motorList << "VTOLMotorNW" << "VTOLMotorN" << "VTOLMotorNE" << "VTOLMotorE"
<< "VTOLMotorSE" << "VTOLMotorS" << "VTOLMotorSW" << "VTOLMotorW";
motorList << "VTOLMotorNW" << "VTOLMotorN" << "VTOLMotorNE" << "VTOLMotorE" << "VTOLMotorSE" << "VTOLMotorS"
<< "VTOLMotorSW" << "VTOLMotorW";
setupMotors(motorList);
// Motor 1 to 8:
// pitch roll yaw
double mixer [8][3] = {
{ 1, 1, -1},
{ 1, 1, 1},
{ 1, -1, -1},
{ 1, -1, 1},
{ -1, -1, -1},
{ -1, -1, 1},
{ -1, 1, -1},
{ -1, 1, 1}
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 }
};
setupMultiRotorMixer(mixer);
setupMultiRotorMixer(mixerMatrix);
m_aircraft->mrStatusLabel->setText("Configuration OK");
} else if (m_aircraft->multirotorFrameType->currentText() == "Tricopter Y") {
airframeType = "Tri";
//Show any config errors in GUI
// Show any config errors in GUI
if (throwConfigError(3)) {
return airframeType;
@ -513,31 +689,30 @@ QString ConfigMultiRotorWidget::updateConfigObjectsFromWidgets()
motorList << "VTOLMotorNW" << "VTOLMotorNE" << "VTOLMotorS";
setupMotors(motorList);
GUIConfigDataUnion config = GetConfigData();
GUIConfigDataUnion config = getConfigData();
config.multi.TRIYaw = m_aircraft->triYawChannelBox->currentIndex();
SetConfigData(config);
setConfigData(config);
// Motor 1 to 6, Y6 Layout:
// pitch roll yaw
double mixer [8][3] = {
{ 0.5, 1, 0},
{ 0.5, -1, 0},
{ -1, 0, 0},
{ 0, 0, 0},
{ 0, 0, 0},
{ 0, 0, 0},
{ 0, 0, 0},
{ 0, 0, 0}
double mixerMatrix[8][3] = {
{ 0.5, 1, 0 },
{ 0.5, -1, 0 },
{ -1, 0, 0 },
{ 0, 0, 0 },
{ 0, 0, 0 },
{ 0, 0, 0 },
{ 0, 0, 0 },
{ 0, 0, 0 }
};
setupMultiRotorMixer(mixer);
setupMultiRotorMixer(mixerMatrix);
//tell the mixer about tricopter yaw channel
// tell the mixer about tricopter yaw channel
int channel = m_aircraft->triYawChannelBox->currentIndex()-1;
if (channel > -1){
setMixerType(mixerObj, channel, VehicleConfig::MIXERTYPE_SERVO);
setMixerVectorValue(mixerObj, channel, VehicleConfig::MIXERVECTOR_YAW, 127);
int channel = m_aircraft->triYawChannelBox->currentIndex() - 1;
if (channel > -1) {
setMixerType(mixer, channel, VehicleConfig::MIXERTYPE_SERVO);
setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_YAW, 127);
}
m_aircraft->mrStatusLabel->setText(tr("Configuration OK"));
@ -547,278 +722,61 @@ QString ConfigMultiRotorWidget::updateConfigObjectsFromWidgets()
return airframeType;
}
/**
Helper function to refresh the UI widget values
*/
void ConfigMultiRotorWidget::refreshWidgetsValues(QString frameType)
void ConfigMultiRotorWidget::setYawMixLevel(int value)
{
int channel;
double value;
GUIConfigDataUnion config = GetConfigData();
multiGUISettingsStruct multi = config.multi;
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) );
}
if (value < 0) {
m_aircraft->mrYawMixLevel->setValue(-value);
m_aircraft->MultirotorRevMixerCheckBox->setChecked(true);
} else {
m_aircraft->mrYawMixLevel->setValue(value);
m_aircraft->MultirotorRevMixerCheckBox->setChecked(false);
}
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
@ -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_THROTTLECURVE2, 0);
setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_ROLL, roll*127);
setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_PITCH, pitch*127);
setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_YAW, yaw*127);
setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_ROLL, roll * 127);
setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_PITCH, pitch * 127);
setMixerVectorValue(mixer, channel, VehicleConfig::MIXERVECTOR_YAW, yaw * 127);
}
/**
Helper function: setup motors. Takes a list of channel names in input.
*/
void ConfigMultiRotorWidget::setupMotors(QList<QString> motorList)
{
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;
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;
GUIConfigDataUnion configData = GetConfigData();
ResetActuators(&configData);
GUIConfigDataUnion configData = getConfigData();
resetActuators(&configData);
int index;
foreach (QString motor, motorList) {
index = mmList.takeFirst()->currentIndex();
if (motor == QString("VTOLMotorN"))
int index = mmList.takeFirst()->currentIndex();
if (motor == QString("VTOLMotorN")) {
configData.multi.VTOLMotorN = index;
else if (motor == QString("VTOLMotorNE"))
} else if (motor == QString("VTOLMotorNE")) {
configData.multi.VTOLMotorNE = index;
else if (motor == QString("VTOLMotorE"))
} else if (motor == QString("VTOLMotorE")) {
configData.multi.VTOLMotorE = index;
else if (motor == QString("VTOLMotorSE"))
} else if (motor == QString("VTOLMotorSE")) {
configData.multi.VTOLMotorSE = index;
else if (motor == QString( "VTOLMotorS"))
} else if (motor == QString("VTOLMotorS")) {
configData.multi.VTOLMotorS = index;
else if (motor == QString( "VTOLMotorSW"))
} else if (motor == QString("VTOLMotorSW")) {
configData.multi.VTOLMotorSW = index;
else if (motor == QString( "VTOLMotorW"))
} else if (motor == QString("VTOLMotorW")) {
configData.multi.VTOLMotorW = index;
else if (motor == QString( "VTOLMotorNW"))
} else if (motor == QString("VTOLMotorNW")) {
configData.multi.VTOLMotorNW = index;
}
}
SetConfigData(configData);
setConfigData(configData);
}
/**
Set up a Quad-X or Quad-P mixer
*/
@ -887,19 +839,16 @@ bool ConfigMultiRotorWidget::setupQuad(bool pLayout)
{
// Check coherence:
//Show any config errors in GUI
// Show any config errors in GUI
if (throwConfigError(4)) {
return false;
}
QList<QString> motorList;
if (pLayout) {
motorList << "VTOLMotorN" << "VTOLMotorE" << "VTOLMotorS"
<< "VTOLMotorW";
motorList << "VTOLMotorN" << "VTOLMotorE" << "VTOLMotorS" << "VTOLMotorW";
} else {
motorList << "VTOLMotorNW" << "VTOLMotorNE" << "VTOLMotorSE"
<< "VTOLMotorSW";
motorList << "VTOLMotorNW" << "VTOLMotorNE" << "VTOLMotorSE" << "VTOLMotorSW";
}
setupMotors(motorList);
@ -920,7 +869,7 @@ bool ConfigMultiRotorWidget::setupQuad(bool pLayout)
{ 0, 0, 0},
{ 0, 0, 0}
};
//
// Motor 1 to 4, P Layout:
// pitch roll yaw
// {1 ,0 ,-0.5 //Front motor (CW)
@ -947,25 +896,22 @@ bool ConfigMultiRotorWidget::setupQuad(bool pLayout)
return true;
}
/**
Set up a Hexa-X or Hexa-P mixer
*/
bool ConfigMultiRotorWidget::setupHexa(bool pLayout)
{
// Check coherence:
//Show any config errors in GUI
if (throwConfigError(6))
// Show any config errors in GUI
if (throwConfigError(6)) {
return false;
}
QList<QString> motorList;
if (pLayout) {
motorList << "VTOLMotorN" << "VTOLMotorNE" << "VTOLMotorSE"
<< "VTOLMotorS" << "VTOLMotorSW" << "VTOLMotorNW";
motorList << "VTOLMotorN" << "VTOLMotorNE" << "VTOLMotorSE" << "VTOLMotorS" << "VTOLMotorSW" << "VTOLMotorNW";
} else {
motorList << "VTOLMotorNE" << "VTOLMotorE" << "VTOLMotorSE"
<< "VTOLMotorSW" << "VTOLMotorW" << "VTOLMotorNW";
motorList << "VTOLMotorNE" << "VTOLMotorE" << "VTOLMotorSE" << "VTOLMotorSW" << "VTOLMotorW" << "VTOLMotorNW";
}
setupMotors(motorList);
@ -979,7 +925,6 @@ bool ConfigMultiRotorWidget::setupHexa(bool pLayout)
// 4 {-0.3 , 0 , 0.3 // S CCW
// 5 {-0.3 , 0.5 ,-0.3 // SW CW
// 6 { 0.3 , 0.5 , 0.3 // NW CCW
double pMixer [8][3] = {
{ 1, 0, -1},
{ 1, -1, 1},
@ -991,7 +936,6 @@ bool ConfigMultiRotorWidget::setupHexa(bool pLayout)
{ 0, 0, 0}
};
//
// Motor 1 to 6, X Layout:
// 1 [ 0.5, -0.3, -0.3 ] NE
// 2 [ 0 , -0.3, 0.3 ] E
@ -1025,64 +969,82 @@ bool ConfigMultiRotorWidget::setupHexa(bool pLayout)
*/
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")));
Q_ASSERT(mixer);
resetMotorAndServoMixers(mixer);
// and enable only the relevant channels:
double pFactor = (double)m_aircraft->mrPitchMixLevel->value()/100;
double rFactor = (double)m_aircraft->mrRollMixLevel->value()/100;
invertMotors = m_aircraft->MultirotorRevMixercheckBox->isChecked() ? -1:1;
double yFactor =invertMotors * (double)m_aircraft->mrYawMixLevel->value()/100;
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]);
double pFactor = (double) m_aircraft->mrPitchMixLevel->value() / 100.0;
double rFactor = (double) m_aircraft->mrRollMixLevel->value() / 100.0;
invertMotors = m_aircraft->MultirotorRevMixerCheckBox->isChecked();
double yFactor = (invertMotors ? -1.0 : 1.0) * (double) m_aircraft->mrYawMixLevel->value() / 100.0;
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;
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;
}
/**
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)
{
//Initialize configuration error flag
bool error=false;
{
// Initialize configuration error flag
bool error = false;
//Iterate through all instances of multiMotorChannelBox
for (int i=0; i<numMotors; i++) {
// Iterate through all instances of multiMotorChannelBox
for (int i = 0; i < numMotors; i++) {
//Fine widgets with text "multiMotorChannelBox.x", where x is an integer
QComboBox *combobox = qFindChild<QComboBox*>(uiowner, "multiMotorChannelBox" + QString::number(i+1));
if (combobox){
QComboBox *combobox = qFindChild<QComboBox*>(this, "multiMotorChannelBox" + QString::number(i + 1));
if (combobox) {
if (combobox->currentText() == "None") {
int size = combobox->style()->pixelMetric(QStyle::PM_SmallIconSize);
QPixmap pixmap(size,size);
QPixmap pixmap(size, size);
pixmap.fill(QColor("red"));
combobox->setItemData(0, pixmap, Qt::DecorationRole);//Set color palettes
error=true;
}
else {
combobox->setItemData(0, 0, Qt::DecorationRole);//Reset color palettes
combobox->setItemData(0, pixmap, Qt::DecorationRole); //Set color palettes
error = true;
} else {
combobox->setItemData(0, 0, Qt::DecorationRole); //Reset color palettes
}
}
}
if (error){
m_aircraft->mrStatusLabel->setText(QString("<font color='red'>ERROR: Assign all %1 motor channels</font>").arg(numMotors));
if (error) {
m_aircraft->mrStatusLabel->setText(
QString("<font color='red'>ERROR: Assign all %1 motor channels</font>").arg(numMotors));
}
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
#define CONFIGMULTIROTORWIDGET_H
#include "ui_airframe.h"
#include "../uavobjectwidgetutils/configtaskwidget.h"
#include "cfg_vehicletypes/vehicleconfig.h"
#include "ui_airframe_multirotor.h"
#include "../uavobjectwidgetutils/configtaskwidget.h"
#include "extensionsystem/pluginmanager.h"
#include "uavobjectmanager.h"
#include "uavobject.h"
#include "uavtalk/telemetrymanager.h"
#include <QtCore/QList>
#include <QtGui/QWidget>
#include <QList>
#include <QItemDelegate>
#include <QtGui/QItemDelegate>
class Ui_Widget;
@ -46,16 +46,26 @@ class ConfigMultiRotorWidget: public VehicleConfig
Q_OBJECT
public:
ConfigMultiRotorWidget(Ui_AircraftWidget *aircraft = 0, QWidget *parent = 0);
static const QString CHANNELBOXNAME;
static QStringList getChannelDescriptions();
ConfigMultiRotorWidget(QWidget *parent = 0);
~ConfigMultiRotorWidget();
friend class ConfigVehicleTypeWidget;
virtual void refreshWidgetsValues(QString frameType);
virtual QString updateConfigObjectsFromWidgets();
protected:
void showEvent(QShowEvent *event);
void resizeEvent(QResizeEvent *event);
private:
Ui_AircraftWidget *m_aircraft;
QWidget *uiowner;
Ui_MultiRotorConfigWidget *m_aircraft;
QGraphicsSvgItem *quad;
bool invertMotors;
virtual void registerWidgets(ConfigTaskWidget &parent);
virtual void resetActuators(GUIConfigDataUnion *configData);
bool setupQuad(bool pLayout);
bool setupHexa(bool pLayout);
@ -64,28 +74,15 @@ private:
void setupMotors(QList<QString> motorList);
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 drawAirframe(QString multiRotorType);
void updateAirframe(QString multiRotorType);
private slots:
virtual void setupUI(QString airframeType);
virtual void refreshWidgetsValues(QString frameType);
virtual QString updateConfigObjectsFromWidgets();
virtual bool throwConfigError(int numMotors);
protected:
signals:
void configurationChanged();
void reverseMultirotorMotor();
};
#endif // CONFIGMULTIROTORWIDGET_H

View File

@ -29,29 +29,27 @@
#include "extensionsystem/pluginmanager.h"
#include "uavobjectmanager.h"
#include "uavobject.h"
#include "systemsettings.h"
#include <QDebug>
VehicleConfig::VehicleConfig(QWidget *parent) : ConfigTaskWidget(parent)
{
//Generate lists of mixerTypeNames, mixerVectorNames, channelNames
// Generate lists of mixerTypeNames, mixerVectorNames, channelNames
channelNames << "None";
for (int i = 0; i < (int)(VehicleConfig::CHANNEL_NUMELEM); i++) {
mixerTypes << QString("Mixer%1Type").arg(i+1);
mixerVectors << QString("Mixer%1Vector").arg(i+1);
channelNames << QString("Channel%1").arg(i+1);
for (int i = 0; i < (int) VehicleConfig::CHANNEL_NUMELEM; i++) {
mixerTypes << QString("Mixer%1Type").arg(i + 1);
mixerVectors << QString("Mixer%1Vector").arg(i + 1);
channelNames << QString("Channel%1").arg(i + 1);
}
mixerTypeDescriptions << "Disabled" << "Motor" << "Servo" << "CameraRoll" << "CameraPitch"
<< "CameraYaw" << "Accessory0" << "Accessory1" << "Accessory2"
<< "Accessory3" << "Accessory4" << "Accessory5";
mixerTypeDescriptions << "Disabled" << "Motor" << "Servo" << "CameraRoll" << "CameraPitch" << "CameraYaw"
<< "Accessory0" << "Accessory1" << "Accessory2" << "Accessory3" << "Accessory4" << "Accessory5";
// 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:
// https://bugreports.qt-project.org/browse/QTBUG-14591
foreach( QPushButton * btn, findChildren<QPushButton*>() ) {
foreach(QPushButton *btn, findChildren<QPushButton*>()) {
btn->setAttribute(Qt::WA_LayoutUsesWidgetRect);
}
}
@ -61,52 +59,91 @@ VehicleConfig::~VehicleConfig()
// Do nothing
}
GUIConfigDataUnion VehicleConfig::GetConfigData() {
int i;
GUIConfigDataUnion configData;
GUIConfigDataUnion VehicleConfig::getConfigData()
{
// get an instance of systemsettings
SystemSettings * systemSettings = SystemSettings::GetInstance(getUAVObjectManager());
SystemSettings *systemSettings = SystemSettings::GetInstance(getUAVObjectManager());
Q_ASSERT(systemSettings);
SystemSettings::DataFields systemSettingsData = systemSettings->getData();
// copy systemsettings -> local configData
for(i = 0; i < (int)(SystemSettings::GUICONFIGDATA_NUMELEM); i++)
configData.UAVObject[i]=systemSettingsData.GUIConfigData[i];
GUIConfigDataUnion configData;
for (int i = 0; i < (int) SystemSettings::GUICONFIGDATA_NUMELEM; i++) {
configData.UAVObject[i] = systemSettingsData.GUIConfigData[i];
}
// sanity check
Q_ASSERT(SystemSettings::GUICONFIGDATA_NUMELEM ==
(sizeof(configData.UAVObject) / sizeof(configData.UAVObject[0])));
Q_ASSERT(SystemSettings::GUICONFIGDATA_NUMELEM == (sizeof(configData.UAVObject) / sizeof(configData.UAVObject[0])));
return configData;
}
void VehicleConfig::SetConfigData(GUIConfigDataUnion configData) {
int i;
void VehicleConfig::setConfigData(GUIConfigDataUnion configData)
{
// sanity check
Q_ASSERT(SystemSettings::GUICONFIGDATA_NUMELEM ==
(sizeof(configData.UAVObject) / sizeof(configData.UAVObject[0])));
Q_ASSERT(SystemSettings::GUICONFIGDATA_NUMELEM == (sizeof(configData.UAVObject) / sizeof(configData.UAVObject[0])));
// get an instance of systemsettings
SystemSettings * systemSettings = SystemSettings::GetInstance(getUAVObjectManager());
SystemSettings *systemSettings = SystemSettings::GetInstance(getUAVObjectManager());
Q_ASSERT(systemSettings);
SystemSettings::DataFields systemSettingsData = systemSettings->getData();
UAVObjectField* guiConfig = systemSettings->getField("GUIConfigData");
UAVObjectField *guiConfig = systemSettings->getField("GUIConfigData");
Q_ASSERT(guiConfig);
if(!guiConfig)
if (!guiConfig) {
return;
}
// 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);
}
}
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
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);
if (index >= 0 && index < box->count())
if (index >= 0 && index < box->count()) {
box->setCurrentIndex(index);
}
}
/**
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++) {
QComboBox* box = qFindChild<QComboBox*>(owner, QString("%0%1").arg(boxName).arg(i));
if (box)
if (box) {
box->setEnabled(enable);
}
}
}
QString VehicleConfig::getMixerType(UAVDataObject* mixer, int channel)
QString VehicleConfig::getMixerType(UAVDataObject *mixer, int channel)
{
Q_ASSERT(mixer);
QString mixerType = mixerTypeDescriptions[0]; //default to disabled
// default to disabled
QString mixerType = mixerTypeDescriptions[0];
if (channel >= 0 && channel < mixerTypes.count()) {
UAVObjectField *field = mixer->getField(mixerTypes.at(channel));
Q_ASSERT(field);
if (field)
mixerType = field->getValue().toString();
if (field) {
mixerType = field->getValue().toString();
}
}
return mixerType;
}
void VehicleConfig::setMixerType(UAVDataObject* mixer, int channel, MixerTypeElem mixerType)
void VehicleConfig::setMixerType(UAVDataObject *mixer, int channel, MixerTypeElem mixerType)
{
Q_ASSERT(mixer);
@ -160,15 +201,14 @@ void VehicleConfig::setMixerType(UAVDataObject* mixer, int channel, MixerTypeEle
Q_ASSERT(field);
if (field) {
if (mixerType >= 0 && mixerType < mixerTypeDescriptions.count())
{
if (mixerType >= 0 && mixerType < mixerTypeDescriptions.count()) {
field->setValue(mixerTypeDescriptions[mixerType]);
}
}
}
}
void VehicleConfig::resetMixerVector(UAVDataObject* mixer, int channel)
void VehicleConfig::resetMixerVector(UAVDataObject *mixer, int channel)
{
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)
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);
if ((type == "Disabled") || (type == "Motor") || (type == "Servo")) {
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);
double value = 0;
if (channel >= 0 && channel < mixerVectors.count()) {
UAVObjectField *field = mixer->getField(mixerVectors.at(channel));
Q_ASSERT(field);
@ -210,7 +248,7 @@ double VehicleConfig::getMixerVectorValue(UAVDataObject* mixer, int channel, Mix
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);
@ -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);
@ -237,7 +275,7 @@ double VehicleConfig::getMixerValue(UAVDataObject* mixer, QString elementName)
return value;
}
void VehicleConfig::setMixerValue(UAVDataObject* mixer, QString elementName, double value)
void VehicleConfig::setMixerValue(UAVDataObject *mixer, QString elementName, double value)
{
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;
switch (curveType)
{
case MIXER_THROTTLECURVE1:
{
field = mixer->getField("ThrottleCurve1");
break;
}
case MIXER_THROTTLECURVE2:
{
field = mixer->getField("ThrottleCurve2");
break;
}
switch (curveType) {
case MIXER_THROTTLECURVE1:
field = mixer->getField("ThrottleCurve1");
break;
case MIXER_THROTTLECURVE2:
field = mixer->getField("ThrottleCurve2");
break;
}
if (field && field->getNumElements() == curve.length()) {
for (int i=0;i<curve.length();i++) {
field->setValue(curve.at(i),i);
if (field && (field->getNumElements() == (unsigned int) curve.length())) {
for (int i = 0; i < curve.length(); 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(curve);
QPointer<UAVObjectField> field;
switch (curveType)
{
case MIXER_THROTTLECURVE1:
{
field = mixer->getField("ThrottleCurve1");
break;
}
case MIXER_THROTTLECURVE2:
{
field = mixer->getField("ThrottleCurve2");
break;
}
switch (curveType) {
case MIXER_THROTTLECURVE1:
field = mixer->getField("ThrottleCurve1");
break;
case MIXER_THROTTLECURVE2:
field = mixer->getField("ThrottleCurve2");
break;
}
if (field) {
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());
}
}
}
bool VehicleConfig::isValidThrottleCurve(QList<double>* curve)
bool VehicleConfig::isValidThrottleCurve(QList<double> *curve)
{
Q_ASSERT(curve);
if (curve) {
for (int i=0; i < curve->count(); i++) {
for (int i = 0; i < curve->count(); i++) {
if (curve->at(i) != 0)
return true;
}
@ -315,41 +342,44 @@ bool VehicleConfig::isValidThrottleCurve(QList<double>* curve)
return false;
}
double VehicleConfig::getCurveMin(QList<double>* curve)
double VehicleConfig::getCurveMin(QList<double> *curve)
{
// TODO initialize to max double
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));
}
return min;
}
double VehicleConfig::getCurveMax(QList<double>* curve)
double VehicleConfig::getCurveMax(QList<double> *curve)
{
// TODO initialize to min double
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));
}
return max;
}
/**
Reset the contents of a field
*/
void VehicleConfig::resetField(UAVObjectField * field)
{
for (unsigned int i=0;i<field->getNumElements();i++) {
field->setValue(0,i);
for (unsigned int i = 0; i < field->getNumElements(); i++) {
field->setValue(0, i);
}
}
/**
* Util function to get a pointer to the object manager
* @return pointer to the UAVObjectManager
*/
UAVObjectManager* VehicleConfig::getUAVObjectManager() {
UAVObjectManager *VehicleConfig::getUAVObjectManager()
{
ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance();
UAVObjectManager * objMngr = pm->getObject<UAVObjectManager>();
UAVObjectManager *objMngr = pm->getObject<UAVObjectManager>();
Q_ASSERT(objMngr);
return objMngr;
}

View File

@ -24,8 +24,8 @@
* with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef GUIVEHICLECONFIG_H
#define GUIVEHICLECONFIG_H
#ifndef VEHICLECONFIG_H
#define VEHICLECONFIG_H
#include "../uavobjectwidgetutils/configtaskwidget.h"
#include "extensionsystem/pluginmanager.h"
@ -33,7 +33,6 @@
#include "uavobject.h"
#include "actuatorcommand.h"
typedef struct {
uint VTOLMotorN:4;
uint VTOLMotorS:4;
@ -42,11 +41,11 @@ typedef struct {
uint VTOLMotorNW:4;
uint VTOLMotorNE:4;
uint VTOLMotorSW:4;
uint VTOLMotorSE:4; //32bits
uint VTOLMotorSE:4; // 32 bits
uint TRIYaw:4;
quint32 padding:28; //64bits
quint32 padding:28; // 64 bits
quint32 padding1;
quint32 padding2; //128bits
quint32 padding2; // 128 bits
} __attribute__((packed)) multiGUISettingsStruct;
typedef struct {
@ -58,15 +57,15 @@ typedef struct {
uint ccpmLinkRollState:1;
uint SliderValue0:7;
uint SliderValue1:7;
uint SliderValue2:7;//41bits
uint SliderValue2:7; // 41 bits
uint ServoIndexW:4;
uint ServoIndexX:4;
uint ServoIndexY:4;
uint ServoIndexZ:4;//57bits
uint ServoIndexZ:4; // 57 bits
uint Throttle:4;
uint Tail:4; //65bits
quint32 padding:31; //96bits
quint32 padding1; //128bits
uint Tail:4; // 65bits
quint32 padding:31; // 96 bits
quint32 padding1; // 128 bits
} __attribute__((packed)) heliGUISettingsStruct;
typedef struct {
@ -77,10 +76,10 @@ typedef struct {
uint FixedWingPitch2:4;
uint FixedWingYaw1:4;
uint FixedWingYaw2:4;
uint padding:4; //32bits
uint padding:4; // 32 bits
quint32 padding1;
quint32 padding2;
quint32 padding3; //128bits
quint32 padding3; // 128 bits
} __attribute__((packed)) fixedGUISettingsStruct;
typedef struct {
@ -88,78 +87,119 @@ typedef struct {
uint GroundVehicleThrottle2:4;
uint GroundVehicleSteering1:4;
uint GroundVehicleSteering2:4;
uint padding:16; //32bits
uint padding:16; // 32 bits
quint32 padding1;
quint32 padding2;
quint32 padding3; //128bits
quint32 padding3; // 128 bits
} __attribute__((packed)) groundGUISettingsStruct;
typedef union
{
uint UAVObject[4]; //32bits * 4
heliGUISettingsStruct heli; //128bits
fixedGUISettingsStruct fixedwing;
multiGUISettingsStruct multi;
uint UAVObject[4]; // 32 bits * 4
heliGUISettingsStruct heli; // 128 bits
fixedGUISettingsStruct fixedwing;
multiGUISettingsStruct multi;
groundGUISettingsStruct ground;
} 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
{
Q_OBJECT
Q_OBJECT
public:
VehicleConfig(QWidget *parent = 0);
~VehicleConfig();
public:
/* Enumeration options for ThrottleCurves */
typedef enum { MIXER_THROTTLECURVE1=0, MIXER_THROTTLECURVE2=1 } MixerThrottleCurveElem;
/* Enumeration options for ThrottleCurves */
typedef enum {
MIXER_THROTTLECURVE1 = 0, MIXER_THROTTLECURVE2 = 1
} MixerThrottleCurveElem;
/* 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;
/* Array element names for field MixerVector */
typedef enum { MIXERVECTOR_THROTTLECURVE1=0, MIXERVECTOR_THROTTLECURVE2=1, MIXERVECTOR_ROLL=2, MIXERVECTOR_PITCH=3, MIXERVECTOR_YAW=4 } MixerVectorElem;
/* 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;
static GUIConfigDataUnion GetConfigData();
static void SetConfigData(GUIConfigDataUnion configData);
static void resetField(UAVObjectField * field);
static void setComboCurrentIndex(QComboBox* box, int index);
static void enableComboBoxes(QWidget* owner, QString boxName, int boxCount, bool enable);
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);
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);
/* Array element names for field MixerVector */
typedef enum {
MIXERVECTOR_THROTTLECURVE1 = 0,
MIXERVECTOR_THROTTLECURVE2 = 1,
MIXERVECTOR_ROLL = 2,
MIXERVECTOR_PITCH = 3,
MIXERVECTOR_YAW = 4
} MixerVectorElem;
QStringList channelNames;
QStringList mixerTypes;
QStringList mixerVectors;
QStringList mixerTypeDescriptions;
static const quint32 CHANNEL_NUMELEM = ActuatorCommand::CHANNEL_NUMELEM;;
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:
//void ConfigurationChanged();
virtual void refreshWidgetsValues(QString frameType);
virtual QString updateConfigObjectsFromWidgets();
double getMixerValue(UAVDataObject *mixer, QString elementName);
void setMixerValue(UAVDataObject *mixer, QString elementName, double value);
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 \
configccattitudewidget.h \
configpipxtremewidget.h \
cfg_vehicletypes/configccpmwidget.h \
configstabilizationwidget.h \
assertions.h \
calibration.h \
@ -28,10 +27,12 @@ HEADERS += configplugin.h \
configcamerastabilizationwidget.h \
configtxpidwidget.h \
outputchannelform.h \
cfg_vehicletypes/configmultirotorwidget.h \
cfg_vehicletypes/configgroundvehiclewidget.h \
cfg_vehicletypes/configfixedwingwidget.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 \
config_global.h \
mixercurve.h \
@ -60,19 +61,24 @@ SOURCES += configplugin.cpp \
configcamerastabilizationwidget.cpp \
configrevowidget.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/configccpmwidget.cpp \
cfg_vehicletypes/configmultirotorwidget.cpp \
cfg_vehicletypes/configfixedwingwidget.cpp \
cfg_vehicletypes/configgroundvehiclewidget.cpp \
cfg_vehicletypes/configcustomwidget.cpp \
outputchannelform.cpp \
mixercurve.cpp \
dblspindelegate.cpp \
configrevohwwidget.cpp
FORMS += airframe.ui \
airframe_ccpm.ui \
airframe_fixedwing.ui \
airframe_ground.ui \
airframe_multirotor.ui \
airframe_custom.ui \
cc_hw_settings.ui \
ccpm.ui \
stabilization.ui \
input.ui \
output.ui \

View File

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

View File

@ -25,77 +25,81 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#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 <QStringList>
#include <QTimer>
#include <QtGui/QWidget>
#include <QtGui/QTextEdit>
#include <QtGui/QVBoxLayout>
#include <QtGui/QPushButton>
#include <math.h>
#include <QDesktopServices>
#include <QUrl>
#include <QEventLoop>
#include "systemsettings.h"
#include "mixersettings.h"
#include "actuatorsettings.h"
#include <extensionsystem/pluginmanager.h>
#include <coreplugin/generalsettings.h>
/**
Helper delegate for the custom mixer editor table.
Taken straight from Qt examples, thanks!
Static function to get currently assigned channelDescriptions
for all known vehicle types; instantiates the appropriate object
then asks it to supply channel descs
*/
SpinBoxDelegate::SpinBoxDelegate(QObject *parent)
: QItemDelegate(parent)
{
}
QWidget *SpinBoxDelegate::createEditor(QWidget *parent,
const QStyleOptionViewItem &/* option */,
const QModelIndex &/* index */) const
QStringList ConfigVehicleTypeWidget::getChannelDescriptions()
{
QSpinBox *editor = new QSpinBox(parent);
editor->setMinimum(-127);
editor->setMaximum(127);
ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance();
UAVObjectManager *objMngr = pm->getObject<UAVObjectManager>();
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)
{
m_aircraft = new Ui_AircraftWidget();
@ -103,10 +107,11 @@ ConfigVehicleTypeWidget::ConfigVehicleTypeWidget(QWidget *parent) : ConfigTaskWi
ExtensionSystem::PluginManager *pm=ExtensionSystem::PluginManager::instance();
Core::Internal::GeneralSettings * settings=pm->getObject<Core::Internal::GeneralSettings>();
if(!settings->useExpertMode())
if (!settings->useExpertMode()) {
m_aircraft->saveAircraftToRAM->setVisible(false);
}
addApplySaveButtons(m_aircraft->saveAircraftToRAM,m_aircraft->saveAircraftToSD);
addApplySaveButtons(m_aircraft->saveAircraftToRAM, m_aircraft->saveAircraftToSD);
addUAVObject("SystemSettings");
addUAVObject("MixerSettings");
@ -115,120 +120,40 @@ ConfigVehicleTypeWidget::ConfigVehicleTypeWidget(QWidget *parent) : ConfigTaskWi
ffTuningInProgress = 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;
airframeTypes << "Fixed Wing" << "Multirotor" << "Helicopter" << "Ground" << "Custom";
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;
fixedWingTypes << "Elevator aileron rudder" << "Elevon" << "Vtail";
m_aircraft->fixedWingType->addItems(fixedWingTypes);
m_aircraft->fixedWingType->setCurrentIndex(0); //Set default model to "Elevator aileron rudder"
// Set default vehicle to MultiRotor
//m_aircraft->aircraftType->setCurrentIndex(3);
QStringList groundVehicleTypes;
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 aircraft type selection dropbox to callback function
connect(m_aircraft->aircraftType, SIGNAL(currentIndexChanged(int)), this, SLOT(switchAirframeType(int)));
//Connect airframe selection dropbox to callback functions
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 the three feed forward test checkboxes
connect(m_aircraft->ffTestBox1, SIGNAL(clicked(bool)), this, SLOT(enableFFTest()));
connect(m_aircraft->ffTestBox2, SIGNAL(clicked(bool)), this, SLOT(enableFFTest()));
connect(m_aircraft->ffTestBox3, SIGNAL(clicked(bool)), this, SLOT(enableFFTest()));
//Connect the multirotor motor reverse checkbox
connect(m_aircraft->MultirotorRevMixercheckBox, SIGNAL(clicked(bool)), this, SLOT(reverseMultirotorMotor()));
// Connect the help pushbutton
connect(m_aircraft->airframeHelp, SIGNAL(clicked()), this, SLOT(openHelp()));
enableControls(false);
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();
m_aircraft->quadShape->fitInView(quad, Qt::KeepAspectRatio);
}
/**
Destructor
*/
@ -237,174 +162,159 @@ ConfigVehicleTypeWidget::~ConfigVehicleTypeWidget()
// 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)
{
m_aircraft->airframesWidget->setCurrentIndex(index);
m_aircraft->quadShape->setSceneRect(quad->boundingRect());
m_aircraft->quadShape->fitInView(quad, Qt::KeepAspectRatio);
if (m_aircraft->aircraftType->findText("Custom")) {
m_aircraft->customMixerTable->resizeColumnsToContents();
for (int i=0;i<(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);
}
// TODO not safe w/r to translation!!!
QString frameCategory = m_aircraft->aircraftType->currentText();
m_aircraft->airframesWidget->setCurrentWidget(getVehicleConfigWidget(frameCategory));
}
/**
Resize the GUI contents when the user changes the window size
*/
void ConfigVehicleTypeWidget::resizeEvent(QResizeEvent* event)
Refreshes the current value of the SystemSettings which holds the aircraft type
Note: The default behavior of ConfigTaskWidget is bypassed.
Therefore no automatic synchronization of UAV Objects to UI is done.
*/
void ConfigVehicleTypeWidget::refreshWidgetsValues(UAVObject *o)
{
Q_UNUSED(event);
m_aircraft->quadShape->fitInView(quad, Qt::KeepAspectRatio);
// Make the custom table columns autostretch:
m_aircraft->customMixerTable->resizeColumnsToContents();
for (int i=0;i<(int)(VehicleConfig::CHANNEL_NUMELEM);i++) {
m_aircraft->customMixerTable->setColumnWidth(i,(m_aircraft->customMixerTable->width()-
m_aircraft->customMixerTable->verticalHeader()->width())/ 10);
}
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();
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) {
m_aircraft->fwAileron2ChannelBox->setEnabled(true);
m_aircraft->fwAileron2Label->setEnabled(true);
// Airframe type defaults to Custom
QString airframeType = "Custom";
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 {
m_aircraft->fwAileron2ChannelBox->setEnabled(false);
m_aircraft->fwAileron2Label->setEnabled(false);
category = "Custom";
}
return category;
}
void ConfigVehicleTypeWidget::toggleElevator2(int index)
VehicleConfig *ConfigVehicleTypeWidget::getVehicleConfigWidget(QString frameCategory)
{
if (index) {
m_aircraft->fwElevator2ChannelBox->setEnabled(true);
m_aircraft->fwElevator2Label->setEnabled(true);
} else {
m_aircraft->fwElevator2ChannelBox->setEnabled(false);
m_aircraft->fwElevator2Label->setEnabled(false);
VehicleConfig *vehiculeConfig;
if (!vehicleIndexMap.contains(frameCategory)) {
// create config widget
vehiculeConfig = createVehicleConfigWidget(frameCategory);
// bind config widget "field" to this ConfigTaskWodget
// 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) {
m_aircraft->fwRudder2ChannelBox->setEnabled(true);
m_aircraft->fwRudder2Label->setEnabled(true);
} else {
m_aircraft->fwRudder2ChannelBox->setEnabled(false);
m_aircraft->fwRudder2Label->setEnabled(false);
qDebug() << "ConfigVehicleTypeWidget::createVehicleConfigWidget - creating" << frameCategory;
if (frameCategory == "Fixed Wing") {
return new ConfigFixedWingWidget();
} else if (frameCategory == "Multirotor") {
return new ConfigMultiRotorWidget();
} 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
*/
@ -414,13 +324,12 @@ void ConfigVehicleTypeWidget::enableFFTest()
// - Check if all three checkboxes are checked
// - Every other timer event: toggle engine from 45% to 55%
// - Every other time event: send FF settings to flight FW
if (m_aircraft->ffTestBox1->isChecked() &&
m_aircraft->ffTestBox2->isChecked() &&
m_aircraft->ffTestBox3->isChecked()) {
if (!ffTuningInProgress)
{
if (m_aircraft->ffTestBox1->isChecked() && m_aircraft->ffTestBox2->isChecked()
&& m_aircraft->ffTestBox3->isChecked()) {
if (!ffTuningInProgress) {
// Initiate tuning:
UAVDataObject* obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("ManualControlCommand")));
UAVDataObject *obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(
QString("ManualControlCommand")));
UAVObject::Metadata mdata = obj->getMetadata();
accInitialData = mdata;
UAVObject::SetFlightAccess(mdata, UAVObject::ACCESS_READONLY);
@ -440,9 +349,10 @@ void ConfigVehicleTypeWidget::enableFFTest()
vconfig->setMixerValue(mixer, "DecelTime", m_aircraft->decelTime->value());
vconfig->setMixerValue(mixer, "MaxAccel", m_aircraft->maxAccelSlider->value());
mixer->updated();
} else {
} else {
// 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 target = (value < 0.5) ? 0.55 : 0.45;
obj->getField("Throttle")->setValue(target);
@ -456,7 +366,8 @@ void ConfigVehicleTypeWidget::enableFFTest()
// Disarm!
if (ffTuningInProgress) {
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();
mdata = accInitialData; // Restore metadata
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.
Note: does NOT ask for an object refresh itself!
*/
void ConfigVehicleTypeWidget::updateCustomAirframeUI()
{
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()
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();
// Update feed forward settings
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());
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();
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"));
}
/**
@ -775,7 +399,6 @@ void ConfigVehicleTypeWidget::updateObjectsFromWidgets()
*/
void ConfigVehicleTypeWidget::openHelp()
{
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)
{
if (index >= 0 && index < box->count())
if (index >= 0 && index < box->count()) {
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
#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 "uavobject.h"
#include "../uavobjectwidgetutils/configtaskwidget.h"
#include <QtGui/QWidget>
#include <QList>
#include <QItemDelegate>
class Ui_Widget;
#include <QComboBox>
#include <QMap>
#include <QString>
#include <QStringList>
#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
{
Q_OBJECT
public:
static QStringList getChannelDescriptions();
static void setComboCurrentIndex(QComboBox *box, int index);
ConfigVehicleTypeWidget(QWidget *parent = 0);
~ConfigVehicleTypeWidget();
static QStringList getChannelDescriptions();
protected slots:
virtual void refreshWidgetsValues(UAVObject *o = NULL);
virtual void updateObjectsFromWidgets();
private:
Ui_AircraftWidget *m_aircraft;
ConfigCcpmWidget *m_heli;
ConfigFixedWingWidget *m_fixedwing;
ConfigMultiRotorWidget *m_multirotor;
ConfigGroundVehicleWidget *m_groundvehicle;
// Maps a frame category to its index in the m_aircraft->airframesWidget QStackedWidget
QMap<QString, int> vehicleIndexMap;
void updateCustomAirframeUI();
void addToDirtyMonitor();
void resetField(UAVObjectField * field);
QString frameCategory(QString frameType);
//void setMixerChannel(int channelNumber, bool channelIsMotor, QList<double> vector);
VehicleConfig *getVehicleConfigWidget(QString frameCategory);
VehicleConfig *createVehicleConfigWidget(QString frameCategory);
QStringList channelNames;
QStringList mixerTypes;
QStringList mixerVectors;
// Feed Forward
void updateFeedForwardUI();
QGraphicsSvgItem *quad;
bool ffTuningInProgress;
bool ffTuningPhase;
UAVObject::Metadata accInitialData;
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 enableFFTest();
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

View File

@ -39,74 +39,74 @@
****************************************************************************/
import QtQuick 1.1
import QtWebKit 1.0
// This is a tabbed pane element. Add a nested Rectangle to add a tab.
TabWidget {
// Define AuthorsModel as type
property AuthorsModel authors: AuthorsModel {}
id: tabs
width: 640; height: 480
// This tab is for the GCS version information
Rectangle {
property string title: "OpenPilot GCS"
anchors.fill: parent
color: "#e3e3e3"
Rectangle {
anchors.fill: parent; anchors.margins: 20
color: "#e3e3e3"
Image {
source: "../images/openpilot_logo_128.png"
x: 0; y: 0; z: 100
fillMode: Image.PreserveAspectFit
}
Flickable {
anchors.fill: parent
anchors.centerIn: parent
Text {
id: versionLabel
x: 156; y: 0
width: 430; height: 379
horizontalAlignment: Qt.AlignLeft
font.pixelSize: 12
wrapMode: Text.WordWrap
// @var version exposed in authorsdialog.cpp
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
// Define AuthorsModel as type
property AuthorsModel authors: AuthorsModel {}
id: tabs
width: 640; height: 480
// This tab is for the GCS version information
Rectangle {
property string title: "OpenPilot GCS"
anchors.fill: parent
color: "#e3e3e3"
Rectangle {
anchors.fill: parent; anchors.margins: 20
color: "#e3e3e3"
Image {
source: "../images/openpilot_logo_128.png"
x: 0; y: 0; z: 100
fillMode: Image.PreserveAspectFit
}
Flickable {
anchors.fill: parent
anchors.centerIn: parent
Text {
id: versionLabel
x: 156; y: 0
width: 430; height: 379
horizontalAlignment: Qt.AlignLeft
font.pixelSize: 12
wrapMode: Text.WordWrap
// @var version exposed in authorsdialog.cpp
text: version
}
}
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"
id="svg2"
version="1.1"
inkscape:version="0.48.2 r9819"
inkscape:version="0.48.4 r9939"
sodipodi:docname="curve-bg.svg">
<defs
id="defs4">
@ -55,15 +55,15 @@
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="1.9966906"
inkscape:cx="181.06787"
inkscape:cx="102.93859"
inkscape:cy="89.329853"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
inkscape:window-width="1440"
inkscape:window-height="878"
inkscape:window-x="1695"
inkscape:window-y="97"
inkscape:window-x="148"
inkscape:window-y="40"
inkscape:window-maximized="0" />
<metadata
id="metadata7">
@ -101,49 +101,49 @@
<path
id="path3594"
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
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"
id="path3596" />
<path
id="path3598"
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
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"
id="path3600" />
<path
id="path3602"
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
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"
id="path3604" />
<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"
id="path3792" />
<path
id="path3794"
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
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"
id="path3796" />
<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"
id="path3800" />
<path
id="path3802"
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
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"
id="path3804" />
</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);
QSvgRenderer *renderer = new QSvgRenderer();
plot = new QGraphicsSvgItem();
renderer->load(QString(":/configgadget/images/curve-bg.svg"));
renderer->load(QString(":/uavobjectwidgetutils/images/curve-bg.svg"));
plot->setSharedRenderer(renderer);
//plot->setElementId("map");
scene->addItem(plot);

View File

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

View File

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