mirror of
https://bitbucket.org/librepilot/librepilot.git
synced 2025-01-29 14:52:12 +01:00
Merge GroundVehicle into latest next
This commit is contained in:
parent
f3de06bd0f
commit
88a46f9062
@ -173,7 +173,7 @@ QGroupBox::title {
|
|||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="1" column="1">
|
<item row="1" column="1">
|
||||||
<widget class="QComboBox" name="fwEngineChannel">
|
<widget class="QComboBox" name="fwEngineChannelBox">
|
||||||
<property name="toolTip">
|
<property name="toolTip">
|
||||||
<string>Select output channel for the engine</string>
|
<string>Select output channel for the engine</string>
|
||||||
</property>
|
</property>
|
||||||
@ -193,7 +193,7 @@ QGroupBox::title {
|
|||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="2" column="1">
|
<item row="2" column="1">
|
||||||
<widget class="QComboBox" name="fwAileron1Channel">
|
<widget class="QComboBox" name="fwAileron1ChannelBox">
|
||||||
<property name="toolTip">
|
<property name="toolTip">
|
||||||
<string>Select output channel for the first aileron (or elevon)</string>
|
<string>Select output channel for the first aileron (or elevon)</string>
|
||||||
</property>
|
</property>
|
||||||
@ -216,7 +216,7 @@ QGroupBox::title {
|
|||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="3" column="1">
|
<item row="3" column="1">
|
||||||
<widget class="QComboBox" name="fwAileron2Channel">
|
<widget class="QComboBox" name="fwAileron2ChannelBox">
|
||||||
<property name="enabled">
|
<property name="enabled">
|
||||||
<bool>false</bool>
|
<bool>false</bool>
|
||||||
</property>
|
</property>
|
||||||
@ -239,7 +239,7 @@ QGroupBox::title {
|
|||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="4" column="1">
|
<item row="4" column="1">
|
||||||
<widget class="QComboBox" name="fwElevator1Channel">
|
<widget class="QComboBox" name="fwElevator1ChannelBox">
|
||||||
<property name="toolTip">
|
<property name="toolTip">
|
||||||
<string>Select output channel for the first elevator</string>
|
<string>Select output channel for the first elevator</string>
|
||||||
</property>
|
</property>
|
||||||
@ -262,12 +262,12 @@ QGroupBox::title {
|
|||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="5" column="1">
|
<item row="5" column="1">
|
||||||
<widget class="QComboBox" name="fwElevator2Channel">
|
<widget class="QComboBox" name="fwElevator2ChannelBox">
|
||||||
<property name="enabled">
|
<property name="enabled">
|
||||||
<bool>false</bool>
|
<bool>false</bool>
|
||||||
</property>
|
</property>
|
||||||
<property name="toolTip">
|
<property name="toolTip">
|
||||||
<string>Select output channel for a secondry elevator</string>
|
<string>Select output channel for a secondary elevator</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
@ -279,7 +279,7 @@ QGroupBox::title {
|
|||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="6" column="1">
|
<item row="6" column="1">
|
||||||
<widget class="QComboBox" name="fwRudder1Channel">
|
<widget class="QComboBox" name="fwRudder1ChannelBox">
|
||||||
<property name="toolTip">
|
<property name="toolTip">
|
||||||
<string>Select output channel for the first rudder</string>
|
<string>Select output channel for the first rudder</string>
|
||||||
</property>
|
</property>
|
||||||
@ -293,7 +293,7 @@ QGroupBox::title {
|
|||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="7" column="1">
|
<item row="7" column="1">
|
||||||
<widget class="QComboBox" name="fwRudder2Channel">
|
<widget class="QComboBox" name="fwRudder2ChannelBox">
|
||||||
<property name="toolTip">
|
<property name="toolTip">
|
||||||
<string>Select output channel for a secondary rudder</string>
|
<string>Select output channel for a secondary rudder</string>
|
||||||
</property>
|
</property>
|
||||||
@ -390,7 +390,7 @@ margin:1px;</string>
|
|||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QLabel" name="label_18">
|
<widget class="QLabel" name="elevonSliderLabel1">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>50</string>
|
<string>50</string>
|
||||||
</property>
|
</property>
|
||||||
@ -446,7 +446,7 @@ margin:1px;</string>
|
|||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QLabel" name="label_25">
|
<widget class="QLabel" name="elevonSliderLabel2">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>50</string>
|
<string>50</string>
|
||||||
</property>
|
</property>
|
||||||
@ -533,6 +533,12 @@ margin:1px;</string>
|
|||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QPushButton" name="fwThrottleReset">
|
<widget class="QPushButton" name="fwThrottleReset">
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>200</width>
|
||||||
|
<height>16777215</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Reset</string>
|
<string>Reset</string>
|
||||||
</property>
|
</property>
|
||||||
@ -681,7 +687,13 @@ margin:1px;</string>
|
|||||||
<item>
|
<item>
|
||||||
<layout class="QVBoxLayout" name="verticalLayout_22">
|
<layout class="QVBoxLayout" name="verticalLayout_22">
|
||||||
<item>
|
<item>
|
||||||
<widget class="QLabel" name="label_43">
|
<widget class="QLabel" name="mrRollMixValue">
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>30</width>
|
||||||
|
<height>0</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>100</string>
|
<string>100</string>
|
||||||
</property>
|
</property>
|
||||||
@ -692,6 +704,12 @@ margin:1px;</string>
|
|||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QSlider" name="mrRollMixLevel">
|
<widget class="QSlider" name="mrRollMixLevel">
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>35</width>
|
||||||
|
<height>0</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
<property name="toolTip">
|
<property name="toolTip">
|
||||||
<string>Weight of Roll mixing in percent.
|
<string>Weight of Roll mixing in percent.
|
||||||
Typical values are 100% for + configuration and 50% for X configuration on quads.</string>
|
Typical values are 100% for + configuration and 50% for X configuration on quads.</string>
|
||||||
@ -729,7 +747,13 @@ margin:1px;</string>
|
|||||||
<item>
|
<item>
|
||||||
<layout class="QVBoxLayout" name="verticalLayout_23">
|
<layout class="QVBoxLayout" name="verticalLayout_23">
|
||||||
<item>
|
<item>
|
||||||
<widget class="QLabel" name="label_44">
|
<widget class="QLabel" name="mrYawPitchValue">
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>0</width>
|
||||||
|
<height>0</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>100</string>
|
<string>100</string>
|
||||||
</property>
|
</property>
|
||||||
@ -740,6 +764,12 @@ margin:1px;</string>
|
|||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QSlider" name="mrPitchMixLevel">
|
<widget class="QSlider" name="mrPitchMixLevel">
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>35</width>
|
||||||
|
<height>0</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
<property name="toolTip">
|
<property name="toolTip">
|
||||||
<string>Weight of Pitch mixing in percent.
|
<string>Weight of Pitch mixing in percent.
|
||||||
Typical values are 100% for + configuration and 50% for X configuration on quads.</string>
|
Typical values are 100% for + configuration and 50% for X configuration on quads.</string>
|
||||||
@ -777,7 +807,13 @@ margin:1px;</string>
|
|||||||
<item>
|
<item>
|
||||||
<layout class="QVBoxLayout" name="verticalLayout_21">
|
<layout class="QVBoxLayout" name="verticalLayout_21">
|
||||||
<item>
|
<item>
|
||||||
<widget class="QLabel" name="label_45">
|
<widget class="QLabel" name="mrYawMixValue">
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>0</width>
|
||||||
|
<height>0</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>50</string>
|
<string>50</string>
|
||||||
</property>
|
</property>
|
||||||
@ -788,6 +824,12 @@ margin:1px;</string>
|
|||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QSlider" name="mrYawMixLevel">
|
<widget class="QSlider" name="mrYawMixLevel">
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>40</width>
|
||||||
|
<height>0</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
<property name="toolTip">
|
<property name="toolTip">
|
||||||
<string>Weight of Yaw mixing in percent.
|
<string>Weight of Yaw mixing in percent.
|
||||||
Typical value is 50% for + or X configuration on quads.</string>
|
Typical value is 50% for + or X configuration on quads.</string>
|
||||||
@ -923,6 +965,12 @@ margin:1px;</string>
|
|||||||
<verstretch>0</verstretch>
|
<verstretch>0</verstretch>
|
||||||
</sizepolicy>
|
</sizepolicy>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>200</width>
|
||||||
|
<height>16777215</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Reset</string>
|
<string>Reset</string>
|
||||||
</property>
|
</property>
|
||||||
@ -992,7 +1040,7 @@ margin:1px;</string>
|
|||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QComboBox" name="triYawChannel">
|
<widget class="QComboBox" name="triYawChannelBox">
|
||||||
<property name="enabled">
|
<property name="enabled">
|
||||||
<bool>false</bool>
|
<bool>false</bool>
|
||||||
</property>
|
</property>
|
||||||
@ -1046,7 +1094,7 @@ margin:1px;</string>
|
|||||||
<number>3</number>
|
<number>3</number>
|
||||||
</property>
|
</property>
|
||||||
<item row="1" column="0">
|
<item row="1" column="0">
|
||||||
<widget class="QLabel" name="label_3">
|
<widget class="QLabel" name="MotorOutputLabel1">
|
||||||
<property name="styleSheet">
|
<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));
|
<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);
|
color: rgb(255, 255, 255);
|
||||||
@ -1060,7 +1108,7 @@ margin:1px;</string>
|
|||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="1" column="1">
|
<item row="1" column="1">
|
||||||
<widget class="QComboBox" name="multiMotor1">
|
<widget class="QComboBox" name="multiMotorChannelBox1">
|
||||||
<property name="toolTip">
|
<property name="toolTip">
|
||||||
<string>Assign your motor output channels using the drawing above as a reference. Respect propeller rotation.</string>
|
<string>Assign your motor output channels using the drawing above as a reference. Respect propeller rotation.</string>
|
||||||
</property>
|
</property>
|
||||||
@ -1081,7 +1129,7 @@ margin:1px;</string>
|
|||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="2" column="1">
|
<item row="2" column="1">
|
||||||
<widget class="QComboBox" name="multiMotor2">
|
<widget class="QComboBox" name="multiMotorChannelBox2">
|
||||||
<property name="toolTip">
|
<property name="toolTip">
|
||||||
<string>Assign your motor output channels using the drawing above as a reference. Respect propeller rotation.</string>
|
<string>Assign your motor output channels using the drawing above as a reference. Respect propeller rotation.</string>
|
||||||
</property>
|
</property>
|
||||||
@ -1102,7 +1150,7 @@ margin:1px;</string>
|
|||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="3" column="1">
|
<item row="3" column="1">
|
||||||
<widget class="QComboBox" name="multiMotor3">
|
<widget class="QComboBox" name="multiMotorChannelBox3">
|
||||||
<property name="toolTip">
|
<property name="toolTip">
|
||||||
<string>Assign your motor output channels using the drawing above as a reference. Respect propeller rotation.</string>
|
<string>Assign your motor output channels using the drawing above as a reference. Respect propeller rotation.</string>
|
||||||
</property>
|
</property>
|
||||||
@ -1123,7 +1171,7 @@ margin:1px;</string>
|
|||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="4" column="1">
|
<item row="4" column="1">
|
||||||
<widget class="QComboBox" name="multiMotor4">
|
<widget class="QComboBox" name="multiMotorChannelBox4">
|
||||||
<property name="toolTip">
|
<property name="toolTip">
|
||||||
<string>Assign your motor output channels using the drawing above as a reference. Respect propeller rotation.</string>
|
<string>Assign your motor output channels using the drawing above as a reference. Respect propeller rotation.</string>
|
||||||
</property>
|
</property>
|
||||||
@ -1170,7 +1218,7 @@ margin:1px;</string>
|
|||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="1" column="1">
|
<item row="1" column="1">
|
||||||
<widget class="QComboBox" name="multiMotor5">
|
<widget class="QComboBox" name="multiMotorChannelBox5">
|
||||||
<property name="enabled">
|
<property name="enabled">
|
||||||
<bool>false</bool>
|
<bool>false</bool>
|
||||||
</property>
|
</property>
|
||||||
@ -1200,7 +1248,7 @@ margin:1px;</string>
|
|||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="2" column="1">
|
<item row="2" column="1">
|
||||||
<widget class="QComboBox" name="multiMotor6">
|
<widget class="QComboBox" name="multiMotorChannelBox6">
|
||||||
<property name="enabled">
|
<property name="enabled">
|
||||||
<bool>false</bool>
|
<bool>false</bool>
|
||||||
</property>
|
</property>
|
||||||
@ -1224,7 +1272,7 @@ margin:1px;</string>
|
|||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="3" column="1">
|
<item row="3" column="1">
|
||||||
<widget class="QComboBox" name="multiMotor7">
|
<widget class="QComboBox" name="multiMotorChannelBox7">
|
||||||
<property name="enabled">
|
<property name="enabled">
|
||||||
<bool>false</bool>
|
<bool>false</bool>
|
||||||
</property>
|
</property>
|
||||||
@ -1248,7 +1296,7 @@ margin:1px;</string>
|
|||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="4" column="1">
|
<item row="4" column="1">
|
||||||
<widget class="QComboBox" name="multiMotor8">
|
<widget class="QComboBox" name="multiMotorChannelBox8">
|
||||||
<property name="enabled">
|
<property name="enabled">
|
||||||
<bool>false</bool>
|
<bool>false</bool>
|
||||||
</property>
|
</property>
|
||||||
@ -1334,6 +1382,520 @@ margin:1px;</string>
|
|||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</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_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="groundVehicleType"/>
|
||||||
|
</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>
|
||||||
|
<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_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>0</width>
|
||||||
|
<height>100</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="title">
|
||||||
|
<string>Output channel asignmets</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QFormLayout" name="formLayout_3">
|
||||||
|
<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_13">
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout_8">
|
||||||
|
<item>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_14">
|
||||||
|
<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_15">
|
||||||
|
<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>
|
||||||
|
<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="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_16">
|
||||||
|
<item>
|
||||||
|
<widget class="MixerCurveWidget" 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>100</width>
|
||||||
|
<height>100</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>200</width>
|
||||||
|
<height>200</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="sizeIncrement">
|
||||||
|
<size>
|
||||||
|
<width>10</width>
|
||||||
|
<height>10</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="gvThrottleCurve1Reset">
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>200</width>
|
||||||
|
<height>16777215</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Reset</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="gvThrottleCurve1ItemValue">
|
||||||
|
<property name="text">
|
||||||
|
<string>Val: 0.00</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QGroupBox" name="gvThrottleCurve2GroupBox">
|
||||||
|
<property name="title">
|
||||||
|
<string>Rear throttle curve</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_17">
|
||||||
|
<item>
|
||||||
|
<widget class="MixerCurveWidget" 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>100</width>
|
||||||
|
<height>100</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>200</width>
|
||||||
|
<height>200</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="gvThrottleCurve2Reset">
|
||||||
|
<property name="text">
|
||||||
|
<string>Reset</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="gvThrottleCurve2ItemValue">
|
||||||
|
<property name="text">
|
||||||
|
<string>Val: 0.00</string>
|
||||||
|
</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="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 class="QWidget" name="custom">
|
<widget class="QWidget" name="custom">
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout_15">
|
<layout class="QHBoxLayout" name="horizontalLayout_15">
|
||||||
<item>
|
<item>
|
||||||
@ -1990,7 +2552,7 @@ margin:1px;</string>
|
|||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QLabel" name="feedForwardValue">
|
<widget class="QLabel" name="feedForwardSliderValue">
|
||||||
<property name="minimumSize">
|
<property name="minimumSize">
|
||||||
<size>
|
<size>
|
||||||
<width>30</width>
|
<width>30</width>
|
||||||
@ -2095,7 +2657,7 @@ Do it after accel time is setup.</string>
|
|||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QLabel" name="label_33">
|
<widget class="QLabel" name="maxAccelSliderValue">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>1000</string>
|
<string>1000</string>
|
||||||
</property>
|
</property>
|
||||||
@ -2329,7 +2891,7 @@ p, li { white-space: pre-wrap; }
|
|||||||
<customwidget>
|
<customwidget>
|
||||||
<class>ConfigccpmWidget</class>
|
<class>ConfigccpmWidget</class>
|
||||||
<extends>QWidget</extends>
|
<extends>QWidget</extends>
|
||||||
<header>configccpmwidget.h</header>
|
<header>cfg_vehicletypes/configccpmwidget.h</header>
|
||||||
<container>1</container>
|
<container>1</container>
|
||||||
</customwidget>
|
</customwidget>
|
||||||
</customwidgets>
|
</customwidgets>
|
||||||
@ -2340,7 +2902,7 @@ p, li { white-space: pre-wrap; }
|
|||||||
<connection>
|
<connection>
|
||||||
<sender>feedForwardSlider</sender>
|
<sender>feedForwardSlider</sender>
|
||||||
<signal>valueChanged(int)</signal>
|
<signal>valueChanged(int)</signal>
|
||||||
<receiver>feedForwardValue</receiver>
|
<receiver>feedForwardSliderValue</receiver>
|
||||||
<slot>setNum(int)</slot>
|
<slot>setNum(int)</slot>
|
||||||
<hints>
|
<hints>
|
||||||
<hint type="sourcelabel">
|
<hint type="sourcelabel">
|
||||||
@ -2356,7 +2918,7 @@ p, li { white-space: pre-wrap; }
|
|||||||
<connection>
|
<connection>
|
||||||
<sender>maxAccelSlider</sender>
|
<sender>maxAccelSlider</sender>
|
||||||
<signal>valueChanged(int)</signal>
|
<signal>valueChanged(int)</signal>
|
||||||
<receiver>label_33</receiver>
|
<receiver>maxAccelSliderValue</receiver>
|
||||||
<slot>setNum(int)</slot>
|
<slot>setNum(int)</slot>
|
||||||
<hints>
|
<hints>
|
||||||
<hint type="sourcelabel">
|
<hint type="sourcelabel">
|
||||||
@ -2372,7 +2934,7 @@ p, li { white-space: pre-wrap; }
|
|||||||
<connection>
|
<connection>
|
||||||
<sender>elevonSlider1</sender>
|
<sender>elevonSlider1</sender>
|
||||||
<signal>valueChanged(int)</signal>
|
<signal>valueChanged(int)</signal>
|
||||||
<receiver>label_18</receiver>
|
<receiver>elevonSliderLabel1</receiver>
|
||||||
<slot>setNum(int)</slot>
|
<slot>setNum(int)</slot>
|
||||||
<hints>
|
<hints>
|
||||||
<hint type="sourcelabel">
|
<hint type="sourcelabel">
|
||||||
@ -2388,12 +2950,12 @@ p, li { white-space: pre-wrap; }
|
|||||||
<connection>
|
<connection>
|
||||||
<sender>elevonSlider2</sender>
|
<sender>elevonSlider2</sender>
|
||||||
<signal>valueChanged(int)</signal>
|
<signal>valueChanged(int)</signal>
|
||||||
<receiver>label_25</receiver>
|
<receiver>elevonSliderLabel2</receiver>
|
||||||
<slot>setNum(int)</slot>
|
<slot>setNum(int)</slot>
|
||||||
<hints>
|
<hints>
|
||||||
<hint type="sourcelabel">
|
<hint type="sourcelabel">
|
||||||
<x>124</x>
|
<x>362</x>
|
||||||
<y>126</y>
|
<y>299</y>
|
||||||
</hint>
|
</hint>
|
||||||
<hint type="destinationlabel">
|
<hint type="destinationlabel">
|
||||||
<x>124</x>
|
<x>124</x>
|
||||||
@ -2401,10 +2963,42 @@ p, li { white-space: pre-wrap; }
|
|||||||
</hint>
|
</hint>
|
||||||
</hints>
|
</hints>
|
||||||
</connection>
|
</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>
|
<connection>
|
||||||
<sender>mrPitchMixLevel</sender>
|
<sender>mrPitchMixLevel</sender>
|
||||||
<signal>valueChanged(int)</signal>
|
<signal>valueChanged(int)</signal>
|
||||||
<receiver>label_44</receiver>
|
<receiver>mrPitchMixValue</receiver>
|
||||||
<slot>setNum(int)</slot>
|
<slot>setNum(int)</slot>
|
||||||
<hints>
|
<hints>
|
||||||
<hint type="sourcelabel">
|
<hint type="sourcelabel">
|
||||||
@ -2420,7 +3014,7 @@ p, li { white-space: pre-wrap; }
|
|||||||
<connection>
|
<connection>
|
||||||
<sender>mrRollMixLevel</sender>
|
<sender>mrRollMixLevel</sender>
|
||||||
<signal>valueChanged(int)</signal>
|
<signal>valueChanged(int)</signal>
|
||||||
<receiver>label_43</receiver>
|
<receiver>mrRollMixValue</receiver>
|
||||||
<slot>setNum(int)</slot>
|
<slot>setNum(int)</slot>
|
||||||
<hints>
|
<hints>
|
||||||
<hint type="sourcelabel">
|
<hint type="sourcelabel">
|
||||||
@ -2436,7 +3030,7 @@ p, li { white-space: pre-wrap; }
|
|||||||
<connection>
|
<connection>
|
||||||
<sender>mrYawMixLevel</sender>
|
<sender>mrYawMixLevel</sender>
|
||||||
<signal>valueChanged(int)</signal>
|
<signal>valueChanged(int)</signal>
|
||||||
<receiver>label_45</receiver>
|
<receiver>mrYawMixValue</receiver>
|
||||||
<slot>setNum(int)</slot>
|
<slot>setNum(int)</slot>
|
||||||
<hints>
|
<hints>
|
||||||
<hint type="sourcelabel">
|
<hint type="sourcelabel">
|
||||||
|
@ -0,0 +1,1810 @@
|
|||||||
|
/**
|
||||||
|
******************************************************************************
|
||||||
|
*
|
||||||
|
* @file configccpmwidget.cpp
|
||||||
|
* @author E. Lafargue & The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
|
||||||
|
* @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 "configccpmwidget.h"
|
||||||
|
#include "mixersettings.h"
|
||||||
|
|
||||||
|
#include <QDebug>
|
||||||
|
#include <QStringList>
|
||||||
|
#include <QtGui/QWidget>
|
||||||
|
#include <QtGui/QTextEdit>
|
||||||
|
#include <QtGui/QVBoxLayout>
|
||||||
|
#include <QtGui/QPushButton>
|
||||||
|
#include <QBrush>
|
||||||
|
#include <math.h>
|
||||||
|
#include <QMessageBox>
|
||||||
|
|
||||||
|
#include "mixersettings.h"
|
||||||
|
#include "systemsettings.h"
|
||||||
|
#include "actuatorcommand.h"
|
||||||
|
|
||||||
|
#define Pi 3.14159265358979323846
|
||||||
|
|
||||||
|
|
||||||
|
ConfigccpmWidget::ConfigccpmWidget(QWidget *parent) : ConfigTaskWidget(parent)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
m_ccpm = new Ui_ccpmWidget();
|
||||||
|
m_ccpm->setupUi(this);
|
||||||
|
SwashLvlConfigurationInProgress=0;
|
||||||
|
SwashLvlState=0;
|
||||||
|
SwashLvlServoInterlock=0;
|
||||||
|
updatingFromHardware=FALSE;
|
||||||
|
updatingToHardware=FALSE;
|
||||||
|
|
||||||
|
// Now connect the widget to the ManualControlCommand / Channel UAVObject
|
||||||
|
//ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance();
|
||||||
|
//UAVObjectManager *objManager = pm->getObject<UAVObjectManager>();
|
||||||
|
|
||||||
|
// Initialization of the swashplaye widget
|
||||||
|
m_ccpm->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_ccpm->SwashplateImage->setSceneRect(SwashplateImg->boundingRect());
|
||||||
|
m_ccpm->SwashplateImage->setSceneRect(-50,-30,500,500);
|
||||||
|
//m_ccpm->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);
|
||||||
|
|
||||||
|
QFont serifFont("Times", 24, QFont::Bold);
|
||||||
|
QPen pen; // creates a default pen
|
||||||
|
|
||||||
|
pen.setStyle(Qt::DotLine);
|
||||||
|
pen.setWidth(2);
|
||||||
|
pen.setBrush(Qt::gray);
|
||||||
|
pen.setCapStyle(Qt::RoundCap);
|
||||||
|
pen.setJoinStyle(Qt::RoundJoin);
|
||||||
|
|
||||||
|
|
||||||
|
QBrush brush(Qt::darkBlue);
|
||||||
|
QPen pen2; // creates a default pen
|
||||||
|
|
||||||
|
//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);
|
||||||
|
|
||||||
|
Servos[i] = new QGraphicsSvgItem();
|
||||||
|
Servos[i]->setSharedRenderer(renderer);
|
||||||
|
Servos[i]->setElementId(ServoNames.at(i));
|
||||||
|
m_ccpm->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]->setBrush(brush);
|
||||||
|
ServosTextCircles[i]->setPen(pen2);
|
||||||
|
m_ccpm->SwashplateImage->scene()->addItem(ServosTextCircles[i]);
|
||||||
|
m_ccpm->SwashplateImage->scene()->addItem(ServosText[i]);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
SwashLvlSpinBoxes[i] = new QSpinBox(m_ccpm->SwashLvlSwashplateImage); // use QGraphicsView
|
||||||
|
m_ccpm->SwashLvlSwashplateImage->scene()->addWidget(SwashLvlSpinBoxes[i]);
|
||||||
|
SwashLvlSpinBoxes[i]->setMaximum(10000);
|
||||||
|
SwashLvlSpinBoxes[i]->setMinimum(0);
|
||||||
|
SwashLvlSpinBoxes[i]->setValue(0);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
m_ccpm->PitchCurve->setMin(-1);
|
||||||
|
|
||||||
|
resetMixer(m_ccpm->PitchCurve, 5);
|
||||||
|
resetMixer(m_ccpm->ThrottleCurve, 5);
|
||||||
|
|
||||||
|
MixerSettings * mixerSettings = MixerSettings::GetInstance(getObjectManager());
|
||||||
|
Q_ASSERT(mixerSettings);
|
||||||
|
UAVObjectField * curve2source = mixerSettings->getField("Curve2Source");
|
||||||
|
Q_ASSERT(curve2source);
|
||||||
|
|
||||||
|
QStringList channels;
|
||||||
|
channels << "Channel1" << "Channel2" << "Channel3" << "Channel4" <<
|
||||||
|
"Channel5" << "Channel6" << "Channel7" << "Channel8" << "None";
|
||||||
|
m_ccpm->ccpmEngineChannel->addItems(channels);
|
||||||
|
m_ccpm->ccpmEngineChannel->setCurrentIndex(8);
|
||||||
|
m_ccpm->ccpmTailChannel->addItems(channels);
|
||||||
|
m_ccpm->ccpmTailChannel->setCurrentIndex(8);
|
||||||
|
m_ccpm->ccpmServoWChannel->addItems(channels);
|
||||||
|
m_ccpm->ccpmServoWChannel->setCurrentIndex(8);
|
||||||
|
m_ccpm->ccpmServoXChannel->addItems(channels);
|
||||||
|
m_ccpm->ccpmServoXChannel->setCurrentIndex(8);
|
||||||
|
m_ccpm->ccpmServoYChannel->addItems(channels);
|
||||||
|
m_ccpm->ccpmServoYChannel->setCurrentIndex(8);
|
||||||
|
m_ccpm->ccpmServoZChannel->addItems(channels);
|
||||||
|
m_ccpm->ccpmServoZChannel->setCurrentIndex(8);
|
||||||
|
|
||||||
|
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("Custom - User Angles") << QString::fromUtf8("Custom - Advanced Settings");
|
||||||
|
m_ccpm->ccpmType->addItems(Types);
|
||||||
|
m_ccpm->ccpmType->setCurrentIndex(m_ccpm->ccpmType->count() - 1);
|
||||||
|
requestccpmUpdate();
|
||||||
|
UpdateCurveSettings();
|
||||||
|
|
||||||
|
//disable changing number of points in curves until UAVObjects have more than 5
|
||||||
|
m_ccpm->NumCurvePoints->setEnabled(0);
|
||||||
|
|
||||||
|
UpdateType();
|
||||||
|
|
||||||
|
//connect(m_ccpm->saveccpmToSD, SIGNAL(clicked()), this, SLOT(saveccpmUpdate()));
|
||||||
|
//connect(m_ccpm->saveccpmToRAM, SIGNAL(clicked()), this, SLOT(sendccpmUpdate()));
|
||||||
|
//connect(m_ccpm->getccpmCurrent, SIGNAL(clicked()), this, SLOT(requestccpmUpdate()));
|
||||||
|
connect(m_ccpm->ccpmGenerateCurve, SIGNAL(clicked()), this, SLOT(GenerateCurve()));
|
||||||
|
connect(m_ccpm->NumCurvePoints, SIGNAL(valueChanged(int)), this, SLOT(UpdateCurveSettings()));
|
||||||
|
connect(m_ccpm->CurveToGenerate, SIGNAL(currentIndexChanged(int)), this, SLOT(UpdateCurveSettings()));
|
||||||
|
connect(m_ccpm->CurveType, SIGNAL(currentIndexChanged(int)), this, SLOT(UpdateCurveSettings()));
|
||||||
|
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->CurveSettings, SIGNAL(cellChanged (int, int)), this, SLOT(UpdateCurveWidgets()));
|
||||||
|
connect(m_ccpm->TabObject, SIGNAL(currentChanged ( QWidget * )), this, SLOT(UpdateType()));
|
||||||
|
|
||||||
|
// connect(m_ccpm->SwashLvlSwashplateImage, SIGNAL(valueChanged(double)), this, SLOT(ccpmSwashplateRedraw()));
|
||||||
|
|
||||||
|
|
||||||
|
connect(m_ccpm->PitchCurve, SIGNAL(curveUpdated(QList<double>,double)), this, SLOT(updatePitchCurveValue(QList<double>,double)));
|
||||||
|
connect(m_ccpm->ThrottleCurve, SIGNAL(curveUpdated(QList<double>,double)), this, SLOT(updateThrottleCurveValue(QList<double>,double)));
|
||||||
|
|
||||||
|
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_ccpm->ccpmLinkCyclic, SIGNAL(clicked()), this, SLOT(SetUIComponentVisibilities()));
|
||||||
|
connect(m_ccpm->ccpmLinkRoll, SIGNAL(clicked()), this, SLOT(SetUIComponentVisibilities()));
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
ccpmSwashplateRedraw();
|
||||||
|
}
|
||||||
|
|
||||||
|
ConfigccpmWidget::~ConfigccpmWidget()
|
||||||
|
{
|
||||||
|
// Do nothing
|
||||||
|
}
|
||||||
|
|
||||||
|
void ConfigccpmWidget::UpdateType()
|
||||||
|
{
|
||||||
|
int TypeInt,SingleServoIndex,NumServosDefined;
|
||||||
|
QString TypeText;
|
||||||
|
double AdjustmentAngle=0;
|
||||||
|
|
||||||
|
UpdateCCPMOptionsFromUI();
|
||||||
|
SetUIComponentVisibilities();
|
||||||
|
|
||||||
|
TypeInt = m_ccpm->ccpmType->count() - m_ccpm->ccpmType->currentIndex()-1;
|
||||||
|
TypeText = m_ccpm->ccpmType->currentText();
|
||||||
|
SingleServoIndex = m_ccpm->ccpmSingleServo->currentIndex();
|
||||||
|
|
||||||
|
//set visibility of user settings
|
||||||
|
m_ccpm->ccpmAdvancedSettingsTable->setEnabled(TypeInt==0);
|
||||||
|
m_ccpm->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_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_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);
|
||||||
|
|
||||||
|
AdjustmentAngle=SingleServoIndex*90;
|
||||||
|
|
||||||
|
m_ccpm->CurveToGenerate->setEnabled(1);
|
||||||
|
m_ccpm->CurveSettings->setColumnHidden(1,0);
|
||||||
|
m_ccpm->PitchCurve->setVisible(1);
|
||||||
|
//m_ccpm->customThrottleCurve2Value->setVisible(1);
|
||||||
|
//m_ccpm->label_41->setVisible(1);
|
||||||
|
|
||||||
|
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(8);
|
||||||
|
m_ccpm->ccpmServoZChannel->setCurrentIndex(8);
|
||||||
|
m_ccpm->ccpmServoYChannel->setEnabled(0);
|
||||||
|
m_ccpm->ccpmServoZChannel->setEnabled(0);
|
||||||
|
//m_ccpm->ccpmCorrectionAngle->setValue(0);
|
||||||
|
NumServosDefined=2;
|
||||||
|
|
||||||
|
}
|
||||||
|
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(8);
|
||||||
|
m_ccpm->ccpmServoZChannel->setEnabled(0);
|
||||||
|
//m_ccpm->ccpmCorrectionAngle->setValue(0);
|
||||||
|
NumServosDefined=3;
|
||||||
|
|
||||||
|
}
|
||||||
|
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->ccpmCorrectionAngle->setValue(0);
|
||||||
|
m_ccpm->ccpmSingleServo->setEnabled(0);
|
||||||
|
m_ccpm->ccpmSingleServo->setCurrentIndex(0);
|
||||||
|
NumServosDefined=4;
|
||||||
|
|
||||||
|
}
|
||||||
|
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(8);
|
||||||
|
m_ccpm->ccpmServoZChannel->setEnabled(0);
|
||||||
|
//m_ccpm->ccpmCorrectionAngle->setValue(0);
|
||||||
|
NumServosDefined=3;
|
||||||
|
|
||||||
|
}
|
||||||
|
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(8);
|
||||||
|
m_ccpm->ccpmServoZChannel->setEnabled(0);
|
||||||
|
//m_ccpm->ccpmCorrectionAngle->setValue(0);
|
||||||
|
NumServosDefined=3;
|
||||||
|
|
||||||
|
}
|
||||||
|
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(8);
|
||||||
|
m_ccpm->ccpmServoZChannel->setCurrentIndex(8);
|
||||||
|
m_ccpm->ccpmServoYChannel->setEnabled(0);
|
||||||
|
m_ccpm->ccpmServoZChannel->setEnabled(0);
|
||||||
|
//m_ccpm->ccpmCorrectionAngle->setValue(0);
|
||||||
|
|
||||||
|
m_ccpm->ccpmCollectivespinBox->setEnabled(0);
|
||||||
|
m_ccpm->ccpmCollectiveSlider->setEnabled(0);
|
||||||
|
m_ccpm->ccpmCollectivespinBox->setValue(0);
|
||||||
|
m_ccpm->ccpmCollectiveSlider->setValue(0);
|
||||||
|
m_ccpm->CurveToGenerate->setCurrentIndex(0);
|
||||||
|
m_ccpm->CurveToGenerate->setEnabled(0);
|
||||||
|
m_ccpm->CurveSettings->setColumnHidden(1,1);
|
||||||
|
m_ccpm->PitchCurve->setVisible(0);
|
||||||
|
//m_ccpm->customThrottleCurve2Value->setVisible(0);
|
||||||
|
//m_ccpm->label_41->setVisible(0);
|
||||||
|
NumServosDefined=2;
|
||||||
|
}
|
||||||
|
|
||||||
|
//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_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);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//update UI
|
||||||
|
ccpmSwashplateUpdate();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Resets a mixer curve
|
||||||
|
*/
|
||||||
|
void ConfigccpmWidget::resetMixer(MixerCurveWidget *mixer, int numElements)
|
||||||
|
{
|
||||||
|
mixer->initLinearCurve(numElements,(double)1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ConfigccpmWidget::UpdateCurveWidgets()
|
||||||
|
{
|
||||||
|
int NumCurvePoints,i,Changed;
|
||||||
|
QList<double> curveValues;
|
||||||
|
QList<double> OldCurveValues;
|
||||||
|
double ThisValue;
|
||||||
|
//get the user settings
|
||||||
|
NumCurvePoints=m_ccpm->NumCurvePoints->value();
|
||||||
|
|
||||||
|
curveValues.clear();
|
||||||
|
Changed=0;
|
||||||
|
OldCurveValues=m_ccpm->ThrottleCurve->getCurve();
|
||||||
|
for (i=0; i<NumCurvePoints; i++)
|
||||||
|
{
|
||||||
|
ThisValue=m_ccpm->CurveSettings->item(i, 0 )->text().toDouble();
|
||||||
|
curveValues.append(ThisValue);
|
||||||
|
if (ThisValue!=OldCurveValues.at(i))Changed=1;
|
||||||
|
}
|
||||||
|
// Setup all Throttle1 curves for all types of airframes
|
||||||
|
if (Changed==1)m_ccpm->ThrottleCurve->setCurve(curveValues);
|
||||||
|
|
||||||
|
curveValues.clear();
|
||||||
|
Changed=0;
|
||||||
|
OldCurveValues=m_ccpm->PitchCurve->getCurve();
|
||||||
|
for (i=0; i<NumCurvePoints; i++)
|
||||||
|
{
|
||||||
|
ThisValue=m_ccpm->CurveSettings->item(i, 1 )->text().toDouble();
|
||||||
|
curveValues.append(ThisValue);
|
||||||
|
if (ThisValue!=OldCurveValues.at(i))Changed=1;
|
||||||
|
}
|
||||||
|
// Setup all Throttle1 curves for all types of airframes
|
||||||
|
if (Changed==1)m_ccpm->PitchCurve->setCurve(curveValues);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ConfigccpmWidget::updatePitchCurveValue(QList<double> curveValues0,double Value0)
|
||||||
|
{
|
||||||
|
Q_UNUSED(curveValues0);
|
||||||
|
Q_UNUSED(Value0);
|
||||||
|
|
||||||
|
int NumCurvePoints,i;
|
||||||
|
double CurrentValue;
|
||||||
|
QList<double> internalCurveValues;
|
||||||
|
//get the user settings
|
||||||
|
NumCurvePoints=m_ccpm->NumCurvePoints->value();
|
||||||
|
internalCurveValues=m_ccpm->PitchCurve->getCurve();
|
||||||
|
|
||||||
|
for (i=0; i<internalCurveValues.length(); i++)
|
||||||
|
{
|
||||||
|
CurrentValue=m_ccpm->CurveSettings->item(i, 1 )->text().toDouble();
|
||||||
|
if (CurrentValue!=internalCurveValues[i])
|
||||||
|
{
|
||||||
|
m_ccpm->CurveSettings->item(i, 1)->setText(QString().sprintf("%.3f",internalCurveValues.at(i)));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void ConfigccpmWidget::updateThrottleCurveValue(QList<double> curveValues0,double Value0)
|
||||||
|
{
|
||||||
|
Q_UNUSED(curveValues0);
|
||||||
|
Q_UNUSED(Value0);
|
||||||
|
|
||||||
|
int NumCurvePoints,i;
|
||||||
|
double CurrentValue;
|
||||||
|
QList<double> internalCurveValues;
|
||||||
|
//get the user settings
|
||||||
|
NumCurvePoints=m_ccpm->NumCurvePoints->value();
|
||||||
|
internalCurveValues=m_ccpm->ThrottleCurve->getCurve();
|
||||||
|
|
||||||
|
for (i=0; i<internalCurveValues.length(); i++)
|
||||||
|
{
|
||||||
|
CurrentValue=m_ccpm->CurveSettings->item(i, 1 )->text().toDouble();
|
||||||
|
if (CurrentValue!=internalCurveValues[i])
|
||||||
|
{
|
||||||
|
m_ccpm->CurveSettings->item(i, 0)->setText(QString().sprintf("%.3f",internalCurveValues.at(i)));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void ConfigccpmWidget::UpdateCurveSettings()
|
||||||
|
{
|
||||||
|
int NumCurvePoints,i;
|
||||||
|
double scale;
|
||||||
|
QString CurveType;
|
||||||
|
QStringList vertHeaders;
|
||||||
|
|
||||||
|
//get the user settings
|
||||||
|
NumCurvePoints=m_ccpm->NumCurvePoints->value();
|
||||||
|
CurveType=m_ccpm->CurveType->currentText();
|
||||||
|
|
||||||
|
vertHeaders << "-" << "-" << "-" << "-" << "-" << "-" << "-" << "-" << "-" << "-" ;
|
||||||
|
for (i=0;i<NumCurvePoints;i++)
|
||||||
|
{
|
||||||
|
scale =((double)i/(double)(NumCurvePoints-1));
|
||||||
|
vertHeaders[i] = tr( "%1%" ).arg(100.00*scale, 0, 'f', 1);
|
||||||
|
}
|
||||||
|
m_ccpm->CurveSettings->setVerticalHeaderLabels( vertHeaders );
|
||||||
|
|
||||||
|
if (m_ccpm->CurveToGenerate->currentIndex()==0)
|
||||||
|
{
|
||||||
|
m_ccpm->CurveValue1->setMinimum(0.0);
|
||||||
|
m_ccpm->CurveValue2->setMinimum(0.0);
|
||||||
|
m_ccpm->CurveValue3->setMinimum(0.0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_ccpm->CurveValue1->setMinimum(-1.0);
|
||||||
|
m_ccpm->CurveValue2->setMinimum(-1.0);
|
||||||
|
m_ccpm->CurveValue3->setMinimum(0.0);
|
||||||
|
}
|
||||||
|
m_ccpm->CurveValue1->setMaximum(1.0);
|
||||||
|
m_ccpm->CurveValue2->setMaximum(1.0);
|
||||||
|
m_ccpm->CurveValue3->setMaximum(100.0);
|
||||||
|
m_ccpm->CurveValue1->setSingleStep(0.1);
|
||||||
|
m_ccpm->CurveValue2->setSingleStep(0.1);
|
||||||
|
m_ccpm->CurveValue3->setSingleStep(1.0);
|
||||||
|
m_ccpm->CurveValue1->setCorrectionMode(QAbstractSpinBox::CorrectToNearestValue);;
|
||||||
|
m_ccpm->CurveValue2->setCorrectionMode(QAbstractSpinBox::CorrectToNearestValue);
|
||||||
|
m_ccpm->CurveValue3->setCorrectionMode(QAbstractSpinBox::CorrectToNearestValue);
|
||||||
|
|
||||||
|
if ( CurveType.compare("Flat")==0)
|
||||||
|
{
|
||||||
|
m_ccpm->CurveLabel1->setText("Value");
|
||||||
|
m_ccpm->CurveLabel1->setVisible(true);
|
||||||
|
m_ccpm->CurveValue1->setVisible(true);
|
||||||
|
m_ccpm->CurveLabel2->setVisible(false);
|
||||||
|
m_ccpm->CurveValue2->setVisible(false);
|
||||||
|
m_ccpm->CurveLabel3->setVisible(false);
|
||||||
|
m_ccpm->CurveValue3->setVisible(false);
|
||||||
|
m_ccpm->ccpmGenerateCurve->setVisible(true);
|
||||||
|
m_ccpm->CurveToGenerate->setVisible(true);
|
||||||
|
}
|
||||||
|
if ( CurveType.compare("Linear")==0)
|
||||||
|
{
|
||||||
|
m_ccpm->CurveLabel1->setText("Min");
|
||||||
|
m_ccpm->CurveLabel1->setVisible(true);
|
||||||
|
m_ccpm->CurveValue1->setVisible(true);
|
||||||
|
m_ccpm->CurveLabel2->setText("Max");
|
||||||
|
m_ccpm->CurveLabel2->setVisible(true);
|
||||||
|
m_ccpm->CurveValue2->setVisible(true);
|
||||||
|
m_ccpm->CurveLabel3->setVisible(false);
|
||||||
|
m_ccpm->CurveValue3->setVisible(false);
|
||||||
|
m_ccpm->ccpmGenerateCurve->setVisible(true);
|
||||||
|
m_ccpm->CurveToGenerate->setVisible(true);
|
||||||
|
}
|
||||||
|
if ( CurveType.compare("Step")==0)
|
||||||
|
{
|
||||||
|
m_ccpm->CurveLabel1->setText("Min");
|
||||||
|
m_ccpm->CurveLabel1->setVisible(true);
|
||||||
|
m_ccpm->CurveValue1->setVisible(true);
|
||||||
|
m_ccpm->CurveLabel2->setText("Max");
|
||||||
|
m_ccpm->CurveLabel2->setVisible(true);
|
||||||
|
m_ccpm->CurveValue2->setVisible(true);
|
||||||
|
m_ccpm->CurveLabel3->setText("Step at");
|
||||||
|
m_ccpm->CurveLabel3->setVisible(true);
|
||||||
|
m_ccpm->CurveValue3->setVisible(true);
|
||||||
|
m_ccpm->ccpmGenerateCurve->setVisible(true);
|
||||||
|
m_ccpm->CurveToGenerate->setVisible(true);
|
||||||
|
}
|
||||||
|
if ( CurveType.compare("Exp")==0)
|
||||||
|
{
|
||||||
|
m_ccpm->CurveLabel1->setText("Min");
|
||||||
|
m_ccpm->CurveLabel1->setVisible(true);
|
||||||
|
m_ccpm->CurveValue1->setVisible(true);
|
||||||
|
m_ccpm->CurveLabel2->setText("Max");
|
||||||
|
m_ccpm->CurveLabel2->setVisible(true);
|
||||||
|
m_ccpm->CurveValue2->setVisible(true);
|
||||||
|
m_ccpm->CurveLabel3->setText("Strength");
|
||||||
|
m_ccpm->CurveLabel3->setVisible(true);
|
||||||
|
m_ccpm->CurveValue3->setVisible(true);
|
||||||
|
m_ccpm->CurveValue3->setMinimum(1.0);
|
||||||
|
m_ccpm->CurveValue3->setMaximum(100.0);
|
||||||
|
m_ccpm->CurveValue3->setSingleStep(1.0);
|
||||||
|
m_ccpm->CurveValue3->setCorrectionMode(QAbstractSpinBox::CorrectToNearestValue);;
|
||||||
|
m_ccpm->ccpmGenerateCurve->setVisible(true);
|
||||||
|
m_ccpm->CurveToGenerate->setVisible(true);
|
||||||
|
}
|
||||||
|
if ( CurveType.compare("Log")==0)
|
||||||
|
{
|
||||||
|
m_ccpm->CurveLabel1->setText("Min");
|
||||||
|
m_ccpm->CurveLabel1->setVisible(true);
|
||||||
|
m_ccpm->CurveValue1->setVisible(true);
|
||||||
|
m_ccpm->CurveLabel2->setText("Max");
|
||||||
|
m_ccpm->CurveLabel2->setVisible(true);
|
||||||
|
m_ccpm->CurveValue2->setVisible(true);
|
||||||
|
m_ccpm->CurveLabel3->setText("Strength");
|
||||||
|
m_ccpm->CurveLabel3->setVisible(true);
|
||||||
|
m_ccpm->CurveValue3->setVisible(true);
|
||||||
|
m_ccpm->CurveValue3->setMinimum(1.0);
|
||||||
|
m_ccpm->CurveValue3->setMaximum(100.0);
|
||||||
|
m_ccpm->CurveValue3->setSingleStep(1.0);
|
||||||
|
m_ccpm->CurveValue3->setCorrectionMode(QAbstractSpinBox::CorrectToNearestValue);;
|
||||||
|
m_ccpm->ccpmGenerateCurve->setVisible(true);
|
||||||
|
m_ccpm->CurveToGenerate->setVisible(true);
|
||||||
|
}
|
||||||
|
if ( CurveType.compare("Custom")==0)
|
||||||
|
{
|
||||||
|
m_ccpm->CurveLabel1->setVisible(false);
|
||||||
|
m_ccpm->CurveValue1->setVisible(false);
|
||||||
|
m_ccpm->CurveLabel2->setVisible(false);
|
||||||
|
m_ccpm->CurveValue2->setVisible(false);
|
||||||
|
m_ccpm->CurveLabel3->setVisible(false);
|
||||||
|
m_ccpm->CurveValue3->setVisible(false);
|
||||||
|
m_ccpm->ccpmGenerateCurve->setVisible(false);
|
||||||
|
m_ccpm->CurveToGenerate->setVisible(false);
|
||||||
|
}
|
||||||
|
UpdateCurveWidgets();
|
||||||
|
|
||||||
|
}
|
||||||
|
void ConfigccpmWidget::GenerateCurve()
|
||||||
|
{
|
||||||
|
int NumCurvePoints,CurveToGenerate,i;
|
||||||
|
double value1, value2, value3, scale;
|
||||||
|
QString CurveType;
|
||||||
|
QTableWidgetItem *item;
|
||||||
|
double newValue;
|
||||||
|
|
||||||
|
|
||||||
|
//get the user settings
|
||||||
|
NumCurvePoints=m_ccpm->NumCurvePoints->value();
|
||||||
|
value1=m_ccpm->CurveValue1->value();
|
||||||
|
value2=m_ccpm->CurveValue2->value();
|
||||||
|
value3=m_ccpm->CurveValue3->value();
|
||||||
|
CurveToGenerate=m_ccpm->CurveToGenerate->currentIndex();
|
||||||
|
CurveType=m_ccpm->CurveType->currentText();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
for (i=0;i<NumCurvePoints;i++)
|
||||||
|
{
|
||||||
|
scale =((double)i/(double)(NumCurvePoints-1));
|
||||||
|
item =m_ccpm->CurveSettings->item(i, CurveToGenerate );
|
||||||
|
|
||||||
|
if ( CurveType.compare("Flat")==0)
|
||||||
|
{
|
||||||
|
//item->setText( tr( "%1" ).arg( value1 ) );
|
||||||
|
item->setText(QString().sprintf("%.3f",value1));
|
||||||
|
}
|
||||||
|
if ( CurveType.compare("Linear")==0)
|
||||||
|
{
|
||||||
|
newValue =value1 +(scale*(value2-value1));
|
||||||
|
//item->setText( tr( "%1" ).arg(value1 +(scale*(value2-value1))) );
|
||||||
|
item->setText(QString().sprintf("%.3f",newValue));
|
||||||
|
}
|
||||||
|
if ( CurveType.compare("Step")==0)
|
||||||
|
{
|
||||||
|
if (scale*100<value3)
|
||||||
|
{
|
||||||
|
//item->setText( tr( "%1" ).arg(value1) );
|
||||||
|
item->setText(QString().sprintf("%.3f",value1));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//item->setText( tr( "%1" ).arg(value2) );
|
||||||
|
item->setText(QString().sprintf("%.3f",value2));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ( CurveType.compare("Exp")==0)
|
||||||
|
{
|
||||||
|
newValue =value1 +(((exp(scale*(value3/10))-1))/(exp((value3/10))-1)*(value2-value1));
|
||||||
|
//item->setText( tr( "%1" ).arg(value1 +(((exp(scale*(value3/10))-1))/(exp((value3/10))-1)*(value2-value1))) );
|
||||||
|
item->setText(QString().sprintf("%.3f",newValue));
|
||||||
|
}
|
||||||
|
if ( CurveType.compare("Log")==0)
|
||||||
|
{
|
||||||
|
newValue = value1 +(((log(scale*(value3*2)+1))/(log(1+(value3*2))))*(value2-value1));
|
||||||
|
//item->setText( tr( "%1" ).arg(value1 +(((log(scale*(value3*2)+1))/(log(1+(value3*2))))*(value2-value1))) );
|
||||||
|
item->setText(QString().sprintf("%.3f",newValue));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (i=NumCurvePoints;i<10;i++)
|
||||||
|
{
|
||||||
|
item =m_ccpm->CurveSettings->item(i, CurveToGenerate );
|
||||||
|
item->setText( tr( "" ) );
|
||||||
|
}
|
||||||
|
UpdateCurveWidgets();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void ConfigccpmWidget::ccpmSwashplateRedraw()
|
||||||
|
{
|
||||||
|
double angle[CCPM_MAX_SWASH_SERVOS],CorrectionAngle,x,y,w,h,radius,CenterX,CenterY;
|
||||||
|
int used[CCPM_MAX_SWASH_SERVOS],defined[CCPM_MAX_SWASH_SERVOS],i;
|
||||||
|
QRectF bounds;
|
||||||
|
QRect size;
|
||||||
|
double scale,xscale,yscale;
|
||||||
|
|
||||||
|
|
||||||
|
size = m_ccpm->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);
|
||||||
|
|
||||||
|
size = m_ccpm->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);
|
||||||
|
|
||||||
|
CorrectionAngle=m_ccpm->ccpmCorrectionAngle->value();
|
||||||
|
|
||||||
|
CenterX=200;
|
||||||
|
CenterY=200;
|
||||||
|
|
||||||
|
bounds=SwashplateImg->boundingRect();
|
||||||
|
|
||||||
|
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()<8)&&(m_ccpm->ccpmServoWChannel->isEnabled()));
|
||||||
|
used[1]=((m_ccpm->ccpmServoXChannel->currentIndex()<8)&&(m_ccpm->ccpmServoXChannel->isEnabled()));
|
||||||
|
used[2]=((m_ccpm->ccpmServoYChannel->currentIndex()<8)&&(m_ccpm->ccpmServoYChannel->isEnabled()));
|
||||||
|
used[3]=((m_ccpm->ccpmServoZChannel->currentIndex()<8)&&(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;
|
||||||
|
|
||||||
|
|
||||||
|
for (i=0;i<CCPM_MAX_SWASH_SERVOS;i++)
|
||||||
|
{
|
||||||
|
radius=210;
|
||||||
|
x=CenterX-(radius*sin(angle[i]))-10.00;
|
||||||
|
y=CenterY+(radius*cos(angle[i]))-10.00;
|
||||||
|
Servos[i]->setPos(x, y);
|
||||||
|
Servos[i]->setVisible(used[i]!=0);
|
||||||
|
|
||||||
|
radius=150;
|
||||||
|
bounds=ServosText[i]->boundingRect();
|
||||||
|
x=CenterX-(radius*sin(angle[i]))-bounds.width()/2;
|
||||||
|
y=CenterY+(radius*cos(angle[i]))-bounds.height()/2;
|
||||||
|
|
||||||
|
ServosText[i]->setPos(x, y);
|
||||||
|
ServosText[i]->setVisible(used[i]!=0);
|
||||||
|
|
||||||
|
if (bounds.width()>bounds.height())
|
||||||
|
{
|
||||||
|
bounds.setHeight(bounds.width());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
bounds.setWidth(bounds.height());
|
||||||
|
}
|
||||||
|
x=CenterX-(radius*sin(angle[i]))-bounds.width()/2;
|
||||||
|
y=CenterY+(radius*cos(angle[i]))-bounds.height()/2;
|
||||||
|
|
||||||
|
ServosTextCircles[i]->setRect(bounds);
|
||||||
|
ServosTextCircles[i]->setPos(x, y);
|
||||||
|
ServosTextCircles[i]->setVisible(used[i]!=0);
|
||||||
|
|
||||||
|
w=SwashLvlSpinBoxes[i]->width()/2;
|
||||||
|
h=SwashLvlSpinBoxes[i]->height()/2;
|
||||||
|
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]->setVisible(used[i]!=0);
|
||||||
|
|
||||||
|
radius=220;
|
||||||
|
x=CenterX-(radius*sin(angle[i]));
|
||||||
|
y=CenterY+(radius*cos(angle[i]));
|
||||||
|
ServoLines[i]->setLine(CenterX,CenterY,x,y);
|
||||||
|
ServoLines[i]->setVisible(defined[i]!=0);
|
||||||
|
}
|
||||||
|
|
||||||
|
//m_ccpm->SwashplateImage->centerOn (CenterX, CenterY);
|
||||||
|
|
||||||
|
//m_ccpm->SwashplateImage->fitInView(SwashplateImg, Qt::KeepAspectRatio);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ConfigccpmWidget::ccpmSwashplateUpdate()
|
||||||
|
{
|
||||||
|
ccpmSwashplateRedraw();
|
||||||
|
SetUIComponentVisibilities();
|
||||||
|
UpdateMixer();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ConfigccpmWidget::ccpmChannelCheck()
|
||||||
|
{
|
||||||
|
if((m_ccpm->ccpmServoWChannel->currentIndex()==8)&&(m_ccpm->ccpmServoWChannel->isEnabled()))
|
||||||
|
{
|
||||||
|
m_ccpm->ccpmServoWLabel->setText("<font color=red>Servo W</font>");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_ccpm->ccpmServoWLabel->setText("<font color=black>Servo W</font>");
|
||||||
|
}
|
||||||
|
if((m_ccpm->ccpmServoXChannel->currentIndex()==8)&&(m_ccpm->ccpmServoXChannel->isEnabled()))
|
||||||
|
{
|
||||||
|
m_ccpm->ccpmServoXLabel->setText("<font color=red>Servo X</font>");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_ccpm->ccpmServoXLabel->setText("<font color=black>Servo X</font>");
|
||||||
|
}
|
||||||
|
if((m_ccpm->ccpmServoYChannel->currentIndex()==8)&&(m_ccpm->ccpmServoYChannel->isEnabled()))
|
||||||
|
{
|
||||||
|
m_ccpm->ccpmServoYLabel->setText("<font color=red>Servo Y</font>");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_ccpm->ccpmServoYLabel->setText("<font color=black>Servo Y</font>");
|
||||||
|
}
|
||||||
|
if((m_ccpm->ccpmServoZChannel->currentIndex()==8)&&(m_ccpm->ccpmServoZChannel->isEnabled()))
|
||||||
|
{
|
||||||
|
m_ccpm->ccpmServoZLabel->setText("<font color=red>Servo Z</font>");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_ccpm->ccpmServoZLabel->setText("<font color=black>Servo Z</font>");
|
||||||
|
}
|
||||||
|
|
||||||
|
if((m_ccpm->ccpmEngineChannel->currentIndex()==8)&&(m_ccpm->ccpmEngineChannel->isEnabled()))
|
||||||
|
{
|
||||||
|
m_ccpm->ccpmEngineLabel->setText("<font color=red>Engine</font>");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_ccpm->ccpmEngineLabel->setText("<font color=black>Engine</font>");
|
||||||
|
}
|
||||||
|
|
||||||
|
if((m_ccpm->ccpmTailChannel->currentIndex()==8)&&(m_ccpm->ccpmTailChannel->isEnabled()))
|
||||||
|
{
|
||||||
|
m_ccpm->ccpmTailLabel->setText("<font color=red>Tail Rotor</font>");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_ccpm->ccpmTailLabel->setText("<font color=black>Tail Rotor</font>");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void ConfigccpmWidget::UpdateMixer()
|
||||||
|
{
|
||||||
|
bool useCCPM;
|
||||||
|
bool useCyclic;
|
||||||
|
int i,j,ThisEnable[6];
|
||||||
|
float CollectiveConstant,PitchConstant,RollConstant,ThisAngle[6];
|
||||||
|
QString Channel;
|
||||||
|
|
||||||
|
ccpmChannelCheck();
|
||||||
|
UpdateCCPMOptionsFromUI();
|
||||||
|
|
||||||
|
useCCPM = !(GUIConfigData.heli.ccpmCollectivePassthroughState || !GUIConfigData.heli.ccpmLinkCyclicState);
|
||||||
|
useCyclic = GUIConfigData.heli.ccpmLinkRollState;
|
||||||
|
|
||||||
|
CollectiveConstant = (float)GUIConfigData.heli.SliderValue0 / 100.00;
|
||||||
|
|
||||||
|
if (useCCPM)
|
||||||
|
{//cyclic = 1 - collective
|
||||||
|
PitchConstant = 1-CollectiveConstant;
|
||||||
|
RollConstant = PitchConstant;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
PitchConstant = (float)GUIConfigData.heli.SliderValue1 / 100.00;;
|
||||||
|
if (useCyclic)
|
||||||
|
{
|
||||||
|
RollConstant = PitchConstant;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
RollConstant = (float)GUIConfigData.heli.SliderValue2 / 100.00;;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (GUIConfigData.heli.SwasplateType>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();
|
||||||
|
|
||||||
|
//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();
|
||||||
|
|
||||||
|
//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]+1 ));
|
||||||
|
ServosText[1]->setPlainText(QString("%1").arg( MixerChannelData[3]+1 ));
|
||||||
|
ServosText[2]->setPlainText(QString("%1").arg( MixerChannelData[4]+1 ));
|
||||||
|
ServosText[3]->setPlainText(QString("%1").arg( MixerChannelData[5]+1 ));
|
||||||
|
|
||||||
|
|
||||||
|
//go through the user data and update the mixer matrix
|
||||||
|
for (i=0;i<6;i++)
|
||||||
|
{
|
||||||
|
if ((MixerChannelData[i]<8)&&((ThisEnable[i])||(i<2)))
|
||||||
|
{
|
||||||
|
m_ccpm->ccpmAdvancedSettingsTable->item(i,0)->setText(QString("%1").arg( MixerChannelData[i]+1 ));
|
||||||
|
//config the vector
|
||||||
|
if (i==0)
|
||||||
|
{//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
|
||||||
|
m_ccpm->ccpmAdvancedSettingsTable->item(i,5)->setText(QString("%1").arg(0));//Yaw
|
||||||
|
}
|
||||||
|
if (i==1)
|
||||||
|
{//tailrotor
|
||||||
|
m_ccpm->ccpmAdvancedSettingsTable->item(i,1)->setText(QString("%1").arg(0));//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
|
||||||
|
m_ccpm->ccpmAdvancedSettingsTable->item(i,5)->setText(QString("%1").arg(127));//Yaw
|
||||||
|
}
|
||||||
|
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+GUIConfigData.heli.CorrectionAngle + ThisAngle[i])*Pi/180.00))));//Roll
|
||||||
|
m_ccpm->ccpmAdvancedSettingsTable->item(i,4)->setText(QString("%1").arg((int)(127.0*(PitchConstant)*cos((GUIConfigData.heli.CorrectionAngle + ThisAngle[i])*Pi/180.00))));//Pitch
|
||||||
|
m_ccpm->ccpmAdvancedSettingsTable->item(i,5)->setText(QString("%1").arg(0));//Yaw
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (j=0;j<6;j++) m_ccpm->ccpmAdvancedSettingsTable->item(i,j)->setText(QString("-"));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**************************
|
||||||
|
* ccpm settings
|
||||||
|
**************************/
|
||||||
|
/*
|
||||||
|
Get the state of the UI check boxes and change the visibility of sliders
|
||||||
|
typedef struct {
|
||||||
|
uint SwasplateType:3;
|
||||||
|
uint FirstServoIndex:2;
|
||||||
|
uint CorrectionAngle:9;
|
||||||
|
uint ccpmCollectivePassthroughState:1;
|
||||||
|
uint ccpmLinkCyclicState:1;
|
||||||
|
uint ccpmLinkRollState:1;
|
||||||
|
uint CollectiveChannel:3;
|
||||||
|
uint padding:12;
|
||||||
|
} __attribute__((packed)) heliGUISettingsStruct;
|
||||||
|
|
||||||
|
*/
|
||||||
|
void ConfigccpmWidget::UpdateCCPMOptionsFromUI()
|
||||||
|
{
|
||||||
|
bool useCCPM;
|
||||||
|
bool useCyclic;
|
||||||
|
|
||||||
|
if (updatingFromHardware) return;
|
||||||
|
//get the user options
|
||||||
|
//swashplate config
|
||||||
|
GUIConfigData.heli.SwasplateType = m_ccpm->ccpmType->count() - m_ccpm->ccpmType->currentIndex()-1;
|
||||||
|
GUIConfigData.heli.FirstServoIndex = m_ccpm->ccpmSingleServo->currentIndex();
|
||||||
|
|
||||||
|
//ccpm mixing options
|
||||||
|
GUIConfigData.heli.ccpmCollectivePassthroughState = m_ccpm->ccpmCollectivePassthrough->isChecked();
|
||||||
|
GUIConfigData.heli.ccpmLinkCyclicState = m_ccpm->ccpmLinkCyclic->isChecked();
|
||||||
|
GUIConfigData.heli.ccpmLinkRollState = m_ccpm->ccpmLinkRoll->isChecked();
|
||||||
|
useCCPM = !(GUIConfigData.heli.ccpmCollectivePassthroughState || !GUIConfigData.heli.ccpmLinkCyclicState);
|
||||||
|
useCyclic = GUIConfigData.heli.ccpmLinkRollState;
|
||||||
|
|
||||||
|
//correction angle
|
||||||
|
GUIConfigData.heli.CorrectionAngle = m_ccpm->ccpmCorrectionAngle->value();
|
||||||
|
|
||||||
|
//update sliders
|
||||||
|
if (useCCPM)
|
||||||
|
{
|
||||||
|
GUIConfigData.heli.SliderValue0 = m_ccpm->ccpmCollectiveSlider->value();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
GUIConfigData.heli.SliderValue0 = m_ccpm->ccpmCollectiveScale->value();
|
||||||
|
}
|
||||||
|
if (useCyclic)
|
||||||
|
{
|
||||||
|
GUIConfigData.heli.SliderValue1 = m_ccpm->ccpmCyclicScale->value();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
GUIConfigData.heli.SliderValue1 = m_ccpm->ccpmPitchScale->value();
|
||||||
|
}
|
||||||
|
GUIConfigData.heli.SliderValue2 = m_ccpm->ccpmRollScale->value();
|
||||||
|
|
||||||
|
//servo assignments
|
||||||
|
GUIConfigData.heli.ServoIndexW = m_ccpm->ccpmServoWChannel->currentIndex();
|
||||||
|
GUIConfigData.heli.ServoIndexX = m_ccpm->ccpmServoXChannel->currentIndex();
|
||||||
|
GUIConfigData.heli.ServoIndexY = m_ccpm->ccpmServoYChannel->currentIndex();
|
||||||
|
GUIConfigData.heli.ServoIndexZ = m_ccpm->ccpmServoZChannel->currentIndex();
|
||||||
|
|
||||||
|
}
|
||||||
|
void ConfigccpmWidget::UpdateCCPMUIFromOptions()
|
||||||
|
{
|
||||||
|
//swashplate config
|
||||||
|
m_ccpm->ccpmType->setCurrentIndex(m_ccpm->ccpmType->count() - (GUIConfigData.heli.SwasplateType +1));
|
||||||
|
m_ccpm->ccpmSingleServo->setCurrentIndex(GUIConfigData.heli.FirstServoIndex);
|
||||||
|
|
||||||
|
//ccpm mixing options
|
||||||
|
m_ccpm->ccpmCollectivePassthrough->setChecked(GUIConfigData.heli.ccpmCollectivePassthroughState);
|
||||||
|
m_ccpm->ccpmLinkCyclic->setChecked(GUIConfigData.heli.ccpmLinkCyclicState);
|
||||||
|
m_ccpm->ccpmLinkRoll->setChecked(GUIConfigData.heli.ccpmLinkRollState);
|
||||||
|
|
||||||
|
//correction angle
|
||||||
|
m_ccpm->ccpmCorrectionAngle->setValue(GUIConfigData.heli.CorrectionAngle);
|
||||||
|
|
||||||
|
//update sliders
|
||||||
|
m_ccpm->ccpmCollectiveScale->setValue(GUIConfigData.heli.SliderValue0);
|
||||||
|
m_ccpm->ccpmCollectiveScaleBox->setValue(GUIConfigData.heli.SliderValue0);
|
||||||
|
m_ccpm->ccpmCyclicScale->setValue(GUIConfigData.heli.SliderValue1);
|
||||||
|
m_ccpm->ccpmCyclicScaleBox->setValue(GUIConfigData.heli.SliderValue1);
|
||||||
|
m_ccpm->ccpmPitchScale->setValue(GUIConfigData.heli.SliderValue1);
|
||||||
|
m_ccpm->ccpmPitchScaleBox->setValue(GUIConfigData.heli.SliderValue1);
|
||||||
|
m_ccpm->ccpmRollScale->setValue(GUIConfigData.heli.SliderValue2);
|
||||||
|
m_ccpm->ccpmRollScaleBox->setValue(GUIConfigData.heli.SliderValue2);
|
||||||
|
m_ccpm->ccpmCollectiveSlider->setValue(GUIConfigData.heli.SliderValue0);
|
||||||
|
m_ccpm->ccpmCollectivespinBox->setValue(GUIConfigData.heli.SliderValue0);
|
||||||
|
|
||||||
|
//servo assignments
|
||||||
|
m_ccpm->ccpmServoWChannel->setCurrentIndex(GUIConfigData.heli.ServoIndexW);
|
||||||
|
m_ccpm->ccpmServoXChannel->setCurrentIndex(GUIConfigData.heli.ServoIndexX);
|
||||||
|
m_ccpm->ccpmServoYChannel->setCurrentIndex(GUIConfigData.heli.ServoIndexY);
|
||||||
|
m_ccpm->ccpmServoZChannel->setCurrentIndex(GUIConfigData.heli.ServoIndexZ);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void ConfigccpmWidget::SetUIComponentVisibilities()
|
||||||
|
{
|
||||||
|
UpdateCCPMOptionsFromUI();
|
||||||
|
//set which sliders are user...
|
||||||
|
m_ccpm->ccpmRevoMixingBox->setVisible(0);
|
||||||
|
|
||||||
|
m_ccpm->ccpmPitchMixingBox->setVisible(!GUIConfigData.heli.ccpmCollectivePassthroughState && GUIConfigData.heli.ccpmLinkCyclicState);
|
||||||
|
m_ccpm->ccpmCollectiveScalingBox->setVisible(GUIConfigData.heli.ccpmCollectivePassthroughState || !GUIConfigData.heli.ccpmLinkCyclicState);
|
||||||
|
|
||||||
|
m_ccpm->ccpmLinkCyclic->setVisible(!GUIConfigData.heli.ccpmCollectivePassthroughState);
|
||||||
|
|
||||||
|
m_ccpm->ccpmCyclicScalingBox->setVisible((GUIConfigData.heli.ccpmCollectivePassthroughState || !GUIConfigData.heli.ccpmLinkCyclicState) && GUIConfigData.heli.ccpmLinkRollState);
|
||||||
|
if (!GUIConfigData.heli.ccpmCollectivePassthroughState && GUIConfigData.heli.ccpmLinkCyclicState)
|
||||||
|
{
|
||||||
|
m_ccpm->ccpmPitchScalingBox->setVisible(0);
|
||||||
|
m_ccpm->ccpmRollScalingBox->setVisible(0);
|
||||||
|
m_ccpm->ccpmLinkRoll->setVisible(0);
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_ccpm->ccpmPitchScalingBox->setVisible(!GUIConfigData.heli.ccpmLinkRollState);
|
||||||
|
m_ccpm->ccpmRollScalingBox->setVisible(!GUIConfigData.heli.ccpmLinkRollState);
|
||||||
|
m_ccpm->ccpmLinkRoll->setVisible(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
Request the current value of the SystemSettings which holds the ccpm type
|
||||||
|
*/
|
||||||
|
void ConfigccpmWidget::requestccpmUpdate()
|
||||||
|
{
|
||||||
|
#define MaxAngleError 2
|
||||||
|
int MixerDataFromHeli[8][5];
|
||||||
|
quint8 MixerOutputType[8];
|
||||||
|
int EngineChannel,TailRotorChannel,ServoChannels[4],ServoAngles[4],SortAngles[4],ServoCurve2[4];
|
||||||
|
int NumServos=0;
|
||||||
|
|
||||||
|
if (SwashLvlConfigurationInProgress)return;
|
||||||
|
if (updatingToHardware)return;
|
||||||
|
updatingFromHardware=TRUE;
|
||||||
|
|
||||||
|
unsigned int i,j;
|
||||||
|
|
||||||
|
SystemSettings * systemSettings = SystemSettings::GetInstance(getObjectManager());
|
||||||
|
Q_ASSERT(systemSettings);
|
||||||
|
SystemSettings::DataFields systemSettingsData = systemSettings->getData();
|
||||||
|
|
||||||
|
Q_ASSERT(SystemSettings::GUICONFIGDATA_NUMELEM ==
|
||||||
|
(sizeof(GUIConfigData.UAVObject) / sizeof(GUIConfigData.UAVObject[0])));
|
||||||
|
|
||||||
|
for(i = 0; i < SystemSettings::GUICONFIGDATA_NUMELEM; i++)
|
||||||
|
GUIConfigData.UAVObject[i]=systemSettingsData.GUIConfigData[i];
|
||||||
|
|
||||||
|
UpdateCCPMUIFromOptions();
|
||||||
|
|
||||||
|
// Get existing mixer settings
|
||||||
|
MixerSettings * mixerSettings = MixerSettings::GetInstance(getObjectManager());
|
||||||
|
MixerSettings::DataFields mixerSettingsData = mixerSettings->getData();
|
||||||
|
|
||||||
|
//go through the user data and update the mixer matrix
|
||||||
|
for (j=0;j<5;j++)
|
||||||
|
{
|
||||||
|
MixerDataFromHeli[0][j] = mixerSettingsData.Mixer1Vector[j];
|
||||||
|
MixerDataFromHeli[1][j] = mixerSettingsData.Mixer2Vector[j];
|
||||||
|
MixerDataFromHeli[2][j] = mixerSettingsData.Mixer3Vector[j];
|
||||||
|
MixerDataFromHeli[3][j] = mixerSettingsData.Mixer4Vector[j];
|
||||||
|
MixerDataFromHeli[4][j] = mixerSettingsData.Mixer5Vector[j];
|
||||||
|
MixerDataFromHeli[5][j] = mixerSettingsData.Mixer6Vector[j];
|
||||||
|
MixerDataFromHeli[6][j] = mixerSettingsData.Mixer7Vector[j];
|
||||||
|
MixerDataFromHeli[7][j] = mixerSettingsData.Mixer8Vector[j];
|
||||||
|
}
|
||||||
|
|
||||||
|
MixerOutputType[0] = mixerSettingsData.Mixer1Type;
|
||||||
|
MixerOutputType[1] = mixerSettingsData.Mixer2Type;
|
||||||
|
MixerOutputType[2] = mixerSettingsData.Mixer3Type;
|
||||||
|
MixerOutputType[3] = mixerSettingsData.Mixer4Type;
|
||||||
|
MixerOutputType[4] = mixerSettingsData.Mixer5Type;
|
||||||
|
MixerOutputType[5] = mixerSettingsData.Mixer6Type;
|
||||||
|
MixerOutputType[6] = mixerSettingsData.Mixer7Type;
|
||||||
|
MixerOutputType[7] = mixerSettingsData.Mixer8Type;
|
||||||
|
|
||||||
|
EngineChannel =-1;
|
||||||
|
TailRotorChannel =-1;
|
||||||
|
for (j=0;j<5;j++)
|
||||||
|
{
|
||||||
|
ServoChannels[j]=8;
|
||||||
|
ServoCurve2[j]=0;
|
||||||
|
ServoAngles[j]=0;
|
||||||
|
SortAngles[j]=j;
|
||||||
|
}
|
||||||
|
|
||||||
|
NumServos=0;
|
||||||
|
//process the data from Heli and try to figure out the settings...
|
||||||
|
for (i=0;i<8;i++)
|
||||||
|
{
|
||||||
|
//check if this is the engine... Throttle only
|
||||||
|
if ((MixerOutputType[i] == MixerSettings::MIXER1TYPE_MOTOR)&&
|
||||||
|
(MixerDataFromHeli[i][0]>0)&&//ThrottleCurve1
|
||||||
|
(MixerDataFromHeli[i][1]==0)&&//ThrottleCurve2
|
||||||
|
(MixerDataFromHeli[i][2]==0)&&//Roll
|
||||||
|
(MixerDataFromHeli[i][3]==0)&&//Pitch
|
||||||
|
(MixerDataFromHeli[i][4]==0))//Yaw
|
||||||
|
{
|
||||||
|
EngineChannel = i;
|
||||||
|
m_ccpm->ccpmEngineChannel->setCurrentIndex(i);
|
||||||
|
|
||||||
|
}
|
||||||
|
//check if this is the tail rotor... REVO and YAW
|
||||||
|
if ((MixerOutputType[i] == MixerSettings::MIXER1TYPE_SERVO)&&
|
||||||
|
//(MixerDataFromHeli[i][0]!=0)&&//ThrottleCurve1
|
||||||
|
(MixerDataFromHeli[i][1]==0)&&//ThrottleCurve2
|
||||||
|
(MixerDataFromHeli[i][2]==0)&&//Roll
|
||||||
|
(MixerDataFromHeli[i][3]==0)&&//Pitch
|
||||||
|
(MixerDataFromHeli[i][4]!=0))//Yaw
|
||||||
|
{
|
||||||
|
TailRotorChannel = i;
|
||||||
|
m_ccpm->ccpmTailChannel->setCurrentIndex(i);
|
||||||
|
m_ccpm->ccpmRevoSlider->setValue((MixerDataFromHeli[i][0]*100)/127);
|
||||||
|
m_ccpm->ccpmREVOspinBox->setValue((MixerDataFromHeli[i][0]*100)/127);
|
||||||
|
}
|
||||||
|
//check if this is a swashplate servo... Throttle is zero
|
||||||
|
if ((MixerOutputType[i] == MixerSettings::MIXER1TYPE_SERVO)&&
|
||||||
|
(MixerDataFromHeli[i][0]==0)&&//ThrottleCurve1
|
||||||
|
//(MixerDataFromHeli[i][1]==0)&&//ThrottleCurve2
|
||||||
|
//(MixerDataFromHeli[i][2]==0)&&//Roll
|
||||||
|
//(MixerDataFromHeli[i][3]==0)&&//Pitch
|
||||||
|
(MixerDataFromHeli[i][4]==0))//Yaw
|
||||||
|
{
|
||||||
|
ServoChannels[NumServos] = i;//record the channel for this servo
|
||||||
|
ServoCurve2[NumServos]=MixerDataFromHeli[i][1];//record the ThrottleCurve2 contribution to this servo
|
||||||
|
ServoAngles[NumServos]=NumServos*45;//make this 0 for the final version
|
||||||
|
|
||||||
|
NumServos++;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//get the settings for the curve from the mixer settings
|
||||||
|
for (i=0;i<5;i++)
|
||||||
|
{
|
||||||
|
m_ccpm->CurveSettings->item(i, 0)->setText(QString().sprintf("%.3f",
|
||||||
|
mixerSettingsData.ThrottleCurve1[i]));
|
||||||
|
m_ccpm->CurveSettings->item(i, 1)->setText(QString().sprintf("%.3f",
|
||||||
|
mixerSettingsData.ThrottleCurve2[i]));
|
||||||
|
}
|
||||||
|
|
||||||
|
updatingFromHardware=FALSE;
|
||||||
|
UpdateCCPMUIFromOptions();
|
||||||
|
ccpmSwashplateUpdate();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Sends the config to the board (ccpm type)
|
||||||
|
*/
|
||||||
|
void ConfigccpmWidget::sendccpmUpdate()
|
||||||
|
{
|
||||||
|
int i,j;
|
||||||
|
|
||||||
|
if (SwashLvlConfigurationInProgress)return;
|
||||||
|
updatingToHardware=TRUE;
|
||||||
|
//ShowDisclaimer(1);
|
||||||
|
|
||||||
|
UpdateCCPMOptionsFromUI();
|
||||||
|
|
||||||
|
// Store the data required to reconstruct
|
||||||
|
SystemSettings * systemSettings = SystemSettings::GetInstance(getObjectManager());
|
||||||
|
Q_ASSERT(systemSettings);
|
||||||
|
SystemSettings::DataFields systemSettingsData = systemSettings->getData();
|
||||||
|
systemSettingsData.GUIConfigData[0] = GUIConfigData.UAVObject[0];
|
||||||
|
systemSettingsData.GUIConfigData[1] = GUIConfigData.UAVObject[1];
|
||||||
|
systemSettings->setData(systemSettingsData);
|
||||||
|
systemSettings->updated();
|
||||||
|
|
||||||
|
MixerSettings * mixerSettings = MixerSettings::GetInstance(getObjectManager());
|
||||||
|
Q_ASSERT(mixerSettings);
|
||||||
|
MixerSettings::DataFields mixerSettingsData = mixerSettings->getData();
|
||||||
|
|
||||||
|
UpdateMixer();
|
||||||
|
|
||||||
|
// Set up some helper pointers
|
||||||
|
qint8 * mixers[8] = {mixerSettingsData.Mixer1Vector,
|
||||||
|
mixerSettingsData.Mixer2Vector,
|
||||||
|
mixerSettingsData.Mixer3Vector,
|
||||||
|
mixerSettingsData.Mixer4Vector,
|
||||||
|
mixerSettingsData.Mixer5Vector,
|
||||||
|
mixerSettingsData.Mixer6Vector,
|
||||||
|
mixerSettingsData.Mixer7Vector,
|
||||||
|
mixerSettingsData.Mixer8Vector
|
||||||
|
};
|
||||||
|
|
||||||
|
quint8 * mixerTypes[8] = {
|
||||||
|
&mixerSettingsData.Mixer1Type,
|
||||||
|
&mixerSettingsData.Mixer2Type,
|
||||||
|
&mixerSettingsData.Mixer3Type,
|
||||||
|
&mixerSettingsData.Mixer4Type,
|
||||||
|
&mixerSettingsData.Mixer5Type,
|
||||||
|
&mixerSettingsData.Mixer6Type,
|
||||||
|
&mixerSettingsData.Mixer7Type,
|
||||||
|
&mixerSettingsData.Mixer8Type
|
||||||
|
};
|
||||||
|
|
||||||
|
//go through the user data and update the mixer matrix
|
||||||
|
for (i=0;i<6;i++)
|
||||||
|
{
|
||||||
|
if (MixerChannelData[i]<8)
|
||||||
|
{
|
||||||
|
//set the mixer type
|
||||||
|
*(mixerTypes[MixerChannelData[i]]) = i==0 ?
|
||||||
|
MixerSettings::MIXER1TYPE_MOTOR :
|
||||||
|
MixerSettings::MIXER1TYPE_SERVO;
|
||||||
|
|
||||||
|
//config the vector
|
||||||
|
for (j=0;j<5;j++)
|
||||||
|
mixers[MixerChannelData[i]][j] = m_ccpm->ccpmAdvancedSettingsTable->item(i,j+1)->text().toInt();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//get the user data for the curve into the mixer settings
|
||||||
|
for (i=0;i<5;i++)
|
||||||
|
mixerSettingsData.ThrottleCurve1[i] = m_ccpm->CurveSettings->item(i, 0)->text().toDouble();
|
||||||
|
|
||||||
|
for (i=0;i<5;i++)
|
||||||
|
mixerSettingsData.ThrottleCurve2[i] = m_ccpm->CurveSettings->item(i, 1)->text().toDouble();
|
||||||
|
|
||||||
|
//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 (GUIConfigData.heli.ccpmCollectivePassthroughState)
|
||||||
|
mixerSettingsData.Curve2Source = MixerSettings::CURVE2SOURCE_COLLECTIVE;
|
||||||
|
else
|
||||||
|
mixerSettingsData.Curve2Source = MixerSettings::CURVE2SOURCE_THROTTLE;
|
||||||
|
|
||||||
|
mixerSettings->setData(mixerSettingsData);
|
||||||
|
mixerSettings->updated();
|
||||||
|
updatingToHardware=FALSE;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Send ccpm type to the board and request saving to SD card
|
||||||
|
*/
|
||||||
|
void ConfigccpmWidget::saveccpmUpdate()
|
||||||
|
{
|
||||||
|
if (SwashLvlConfigurationInProgress)return;
|
||||||
|
ShowDisclaimer(0);
|
||||||
|
// Send update so that the latest value is saved
|
||||||
|
sendccpmUpdate();
|
||||||
|
UAVDataObject* obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
|
||||||
|
Q_ASSERT(obj);
|
||||||
|
saveObjectToSD(obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ConfigccpmWidget::resizeEvent(QResizeEvent* event)
|
||||||
|
{
|
||||||
|
Q_UNUSED(event);
|
||||||
|
// Make the custom table columns autostretch:
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
ccpmSwashplateRedraw();
|
||||||
|
|
||||||
|
}
|
||||||
|
void ConfigccpmWidget::showEvent(QShowEvent *event)
|
||||||
|
{
|
||||||
|
Q_UNUSED(event)
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
ccpmSwashplateRedraw();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void ConfigccpmWidget::SwashLvlStartButtonPressed()
|
||||||
|
{
|
||||||
|
QMessageBox msgBox;
|
||||||
|
int i;
|
||||||
|
msgBox.setText("<h1>Swashplate Leveling Routine</h1>");
|
||||||
|
msgBox.setInformativeText("<b>You are about to start the Swashplate levelling routine.</b><p>This process will start by downloading the current configuration from the GCS to the OP hardware and will adjust your configuration at various stages.<p>The final state of your system should match the current configuration in the GCS config gadget.<p>Please ensure all ccpm settings in the GCS are correct before continuing.<p>If this process is interrupted, then the state of your OP board may not match the GCS configuration.<p><i>After completing this process, please check all settings before attempting to fly.</i><p><font color=red><b>Please disconnect your motor to ensure it will not spin up.</b></font><p><hr><i>Do you wish to proceed?</i>");
|
||||||
|
msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::Cancel);
|
||||||
|
msgBox.setDefaultButton(QMessageBox::Cancel);
|
||||||
|
msgBox.setIcon(QMessageBox::Information);
|
||||||
|
int ret = msgBox.exec();
|
||||||
|
|
||||||
|
UAVObjectField* MinField;
|
||||||
|
UAVObjectField* NeutralField;
|
||||||
|
UAVObjectField* MaxField;
|
||||||
|
UAVDataObject* obj;
|
||||||
|
ExtensionSystem::PluginManager *pm;
|
||||||
|
UAVObjectManager *objManager;
|
||||||
|
|
||||||
|
switch (ret) {
|
||||||
|
case QMessageBox::Yes:
|
||||||
|
// Yes was clicked
|
||||||
|
SwashLvlState=0;
|
||||||
|
//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);
|
||||||
|
//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);
|
||||||
|
|
||||||
|
|
||||||
|
//download the current settings to the OP hw
|
||||||
|
sendccpmUpdate();
|
||||||
|
|
||||||
|
//change control mode to gcs control / disarmed
|
||||||
|
//set throttle to 0
|
||||||
|
|
||||||
|
|
||||||
|
//save off the old ActuatorSettings for the swashplate servos
|
||||||
|
pm = ExtensionSystem::PluginManager::instance();
|
||||||
|
objManager = pm->getObject<UAVObjectManager>();
|
||||||
|
|
||||||
|
|
||||||
|
// Get the channel assignements:
|
||||||
|
obj = dynamic_cast<UAVDataObject*>(objManager->getObject(QString("ActuatorSettings")));
|
||||||
|
Q_ASSERT(obj);
|
||||||
|
// obj->requestUpdate();
|
||||||
|
MinField = obj->getField(QString("ChannelMin"));
|
||||||
|
NeutralField = obj->getField(QString("ChannelNeutral"));
|
||||||
|
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();
|
||||||
|
//if servos are used
|
||||||
|
oldSwashLvlConfiguration.Used[0]=((m_ccpm->ccpmServoWChannel->currentIndex()<8)&&(m_ccpm->ccpmServoWChannel->isEnabled()));
|
||||||
|
oldSwashLvlConfiguration.Used[1]=((m_ccpm->ccpmServoXChannel->currentIndex()<8)&&(m_ccpm->ccpmServoXChannel->isEnabled()));
|
||||||
|
oldSwashLvlConfiguration.Used[2]=((m_ccpm->ccpmServoYChannel->currentIndex()<8)&&(m_ccpm->ccpmServoYChannel->isEnabled()));
|
||||||
|
oldSwashLvlConfiguration.Used[3]=((m_ccpm->ccpmServoZChannel->currentIndex()<8)&&(m_ccpm->ccpmServoZChannel->isEnabled()));
|
||||||
|
//min,neutral,max values for the servos
|
||||||
|
for (i=0;i<CCPM_MAX_SWASH_SERVOS;i++)
|
||||||
|
{
|
||||||
|
oldSwashLvlConfiguration.Min[i]=MinField->getValue(oldSwashLvlConfiguration.ServoChannels[i]).toInt();
|
||||||
|
oldSwashLvlConfiguration.Neutral[i]=NeutralField->getValue(oldSwashLvlConfiguration.ServoChannels[i]).toInt();
|
||||||
|
oldSwashLvlConfiguration.Max[i]=MaxField->getValue(oldSwashLvlConfiguration.ServoChannels[i]).toInt();
|
||||||
|
}
|
||||||
|
|
||||||
|
//copy to new Actuator settings.
|
||||||
|
memcpy((void*)&newSwashLvlConfiguration,(void*)&oldSwashLvlConfiguration,sizeof(SwashplateServoSettingsStruct));
|
||||||
|
|
||||||
|
//goto the first step
|
||||||
|
SwashLvlNextButtonPressed();
|
||||||
|
break;
|
||||||
|
case QMessageBox::Cancel:
|
||||||
|
// Cancel was clicked
|
||||||
|
SwashLvlState=0;
|
||||||
|
//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);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
// should never be reached
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
void ConfigccpmWidget::SwashLvlNextButtonPressed()
|
||||||
|
{
|
||||||
|
//ShowDisclaimer(2);
|
||||||
|
SwashLvlState++;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
switch (SwashLvlState)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
break;
|
||||||
|
case 1: //Neutral levelling
|
||||||
|
m_ccpm->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);
|
||||||
|
//set position slider to 50%
|
||||||
|
m_ccpm->SwashLvlPositionSlider->setValue(50);
|
||||||
|
m_ccpm->SwashLvlPositionSpinBox->setValue(50);
|
||||||
|
//connect spinbox signals to slots and ebnable them
|
||||||
|
for (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.");
|
||||||
|
break;
|
||||||
|
case 2: //Max levelling
|
||||||
|
//check Neutral status as complete
|
||||||
|
m_ccpm->SwashLvlStepList->item(0)->setCheckState(Qt::Checked);
|
||||||
|
m_ccpm->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);
|
||||||
|
//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.");
|
||||||
|
break;
|
||||||
|
case 3: //Min levelling
|
||||||
|
//check Max status as complete
|
||||||
|
m_ccpm->SwashLvlStepList->item(1)->setCheckState(Qt::Checked);
|
||||||
|
m_ccpm->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);
|
||||||
|
//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;
|
||||||
|
case 4: //levelling verification
|
||||||
|
//check Min status as complete
|
||||||
|
m_ccpm->SwashLvlStepList->item(2)->setCheckState(Qt::Checked);
|
||||||
|
m_ccpm->SwashLvlStepList->setCurrentRow(3);
|
||||||
|
//enable position slider
|
||||||
|
m_ccpm->SwashLvlPositionSlider->setEnabled(true);
|
||||||
|
m_ccpm->SwashLvlPositionSpinBox->setEnabled(true);
|
||||||
|
//make heli respond to slider movement
|
||||||
|
connect(m_ccpm->SwashLvlPositionSlider, SIGNAL(valueChanged(int)), this, SLOT(setSwashplateLevel(int)));
|
||||||
|
//disable spin boxes
|
||||||
|
for (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;
|
||||||
|
case 5: //levelling complete
|
||||||
|
//check verify status as complete
|
||||||
|
m_ccpm->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");
|
||||||
|
//disable position slider
|
||||||
|
m_ccpm->SwashLvlPositionSlider->setEnabled(false);
|
||||||
|
m_ccpm->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(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);
|
||||||
|
|
||||||
|
default:
|
||||||
|
//restore collective/cyclic setting
|
||||||
|
//restore pitch curve
|
||||||
|
//clear spin boxes
|
||||||
|
//change control mode to gcs control (OFF) / disarmed
|
||||||
|
//issue user confirmation
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void ConfigccpmWidget::SwashLvlCancelButtonPressed()
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
SwashLvlState=0;
|
||||||
|
|
||||||
|
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_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);
|
||||||
|
|
||||||
|
//restore old Actuator Settings
|
||||||
|
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.
|
||||||
|
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(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
|
||||||
|
enableSwashplateLevellingControl(false);
|
||||||
|
|
||||||
|
m_ccpm->SwashLvlStepInstruction->setText("<h2>Levelling Cancelled</h2><p>Previous settings have been restored.");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void ConfigccpmWidget::SwashLvlFinishButtonPressed()
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
//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.
|
||||||
|
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]);
|
||||||
|
}
|
||||||
|
|
||||||
|
obj->updated();
|
||||||
|
saveObjectToSD(obj);
|
||||||
|
|
||||||
|
//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");
|
||||||
|
|
||||||
|
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();
|
||||||
|
return 0;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
// should never be reached
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Toggles the channel testing mode by making the GCS take over
|
||||||
|
the ActuatorCommand objects
|
||||||
|
*/
|
||||||
|
void ConfigccpmWidget::enableSwashplateLevellingControl(bool state)
|
||||||
|
{
|
||||||
|
ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance();
|
||||||
|
UAVObjectManager *objManager = pm->getObject<UAVObjectManager>();
|
||||||
|
|
||||||
|
UAVDataObject* obj = dynamic_cast<UAVDataObject*>(objManager->getObject(QString("ActuatorCommand")));
|
||||||
|
UAVObject::Metadata mdata = obj->getMetadata();
|
||||||
|
if (state)
|
||||||
|
{
|
||||||
|
SwashLvlaccInitialData = mdata;
|
||||||
|
mdata.flightAccess = UAVObject::ACCESS_READONLY;
|
||||||
|
mdata.flightTelemetryUpdateMode = UAVObject::UPDATEMODE_ONCHANGE;
|
||||||
|
mdata.gcsTelemetryAcked = false;
|
||||||
|
mdata.gcsTelemetryUpdateMode = 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;
|
||||||
|
|
||||||
|
m_ccpm->TabObject->setTabEnabled(0,1);
|
||||||
|
m_ccpm->TabObject->setTabEnabled(2,1);
|
||||||
|
m_ccpm->TabObject->setTabEnabled(3,1);
|
||||||
|
m_ccpm->ccpmType->setEnabled(1);
|
||||||
|
|
||||||
|
}
|
||||||
|
obj->setMetadata(mdata);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Sets the swashplate level to a given value based on current settings for Max, Neutral and Min values.
|
||||||
|
level ranges -1 to +1
|
||||||
|
*/
|
||||||
|
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;
|
||||||
|
|
||||||
|
SwashLvlServoInterlock=1;
|
||||||
|
|
||||||
|
ActuatorCommand * actuatorCommand = ActuatorCommand::GetInstance(getObjectManager());
|
||||||
|
ActuatorCommand::DataFields actuatorCommandData = actuatorCommand->getData();
|
||||||
|
|
||||||
|
for (i=0;i<CCPM_MAX_SWASH_SERVOS;i++) {
|
||||||
|
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];
|
||||||
|
|
||||||
|
actuatorCommandData.Channel[newSwashLvlConfiguration.ServoChannels[i]] = value;
|
||||||
|
SwashLvlSpinBoxes[i]->setValue(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
actuatorCommand->setData(actuatorCommandData);
|
||||||
|
actuatorCommand->updated();
|
||||||
|
|
||||||
|
SwashLvlServoInterlock=0;
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void ConfigccpmWidget::SwashLvlSpinBoxChanged(int value)
|
||||||
|
{
|
||||||
|
Q_UNUSED(value);
|
||||||
|
int i;
|
||||||
|
if (SwashLvlServoInterlock==1)return;
|
||||||
|
|
||||||
|
ActuatorCommand * actuatorCommand = ActuatorCommand::GetInstance(getObjectManager());
|
||||||
|
ActuatorCommand::DataFields actuatorCommandData = actuatorCommand->getData();
|
||||||
|
|
||||||
|
for (i = 0; i < CCPM_MAX_SWASH_SERVOS; i++) {
|
||||||
|
value = SwashLvlSpinBoxes[i]->value();
|
||||||
|
|
||||||
|
switch (SwashLvlState)
|
||||||
|
{
|
||||||
|
case 1: //Neutral levelling
|
||||||
|
newSwashLvlConfiguration.Neutral[i]=value;
|
||||||
|
break;
|
||||||
|
case 2: //Max levelling
|
||||||
|
newSwashLvlConfiguration.Max[i] = value;
|
||||||
|
break;
|
||||||
|
case 3: //Min levelling
|
||||||
|
newSwashLvlConfiguration.Min[i]= value;
|
||||||
|
break;
|
||||||
|
case 4: //levelling verification
|
||||||
|
break;
|
||||||
|
case 5: //levelling complete
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
actuatorCommandData.Channel[newSwashLvlConfiguration.ServoChannels[i]] = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
actuatorCommand->setData(actuatorCommandData);
|
||||||
|
actuatorCommand->updated();
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
@ -0,0 +1,160 @@
|
|||||||
|
/**
|
||||||
|
******************************************************************************
|
||||||
|
*
|
||||||
|
* @file configccpmtwidget.h
|
||||||
|
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
|
||||||
|
* @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
|
||||||
|
*/
|
||||||
|
#ifndef CONFIGccpmWIDGET_H
|
||||||
|
#define CONFIGccpmWIDGET_H
|
||||||
|
|
||||||
|
#include "ui_ccpm.h"
|
||||||
|
#include "../uavobjectwidgetutils/configtaskwidget.h"
|
||||||
|
#include "extensionsystem/pluginmanager.h"
|
||||||
|
#include "uavobjectmanager.h"
|
||||||
|
#include "uavobject.h"
|
||||||
|
#include <QtSvg/QSvgRenderer>
|
||||||
|
#include <QtSvg/QGraphicsSvgItem>
|
||||||
|
#include <QGraphicsEllipseItem>
|
||||||
|
#include <QtGui/QWidget>
|
||||||
|
#include <QList>
|
||||||
|
|
||||||
|
#define CCPM_MAX_SWASH_SERVOS 4
|
||||||
|
|
||||||
|
class Ui_Widget;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int ServoChannels[CCPM_MAX_SWASH_SERVOS];
|
||||||
|
int Used[CCPM_MAX_SWASH_SERVOS];
|
||||||
|
int Max[CCPM_MAX_SWASH_SERVOS];
|
||||||
|
int Neutral[CCPM_MAX_SWASH_SERVOS];
|
||||||
|
int Min[CCPM_MAX_SWASH_SERVOS];
|
||||||
|
} SwashplateServoSettingsStruct;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint SwasplateType:3;
|
||||||
|
uint FirstServoIndex:2;
|
||||||
|
uint CorrectionAngle:9;
|
||||||
|
uint ccpmCollectivePassthroughState:1;
|
||||||
|
uint ccpmLinkCyclicState:1;
|
||||||
|
uint ccpmLinkRollState:1;
|
||||||
|
uint SliderValue0:7;
|
||||||
|
uint SliderValue1:7;
|
||||||
|
uint SliderValue2:7;//41bits
|
||||||
|
uint ServoIndexW:4;
|
||||||
|
uint ServoIndexX:4;
|
||||||
|
uint ServoIndexY:4;
|
||||||
|
uint ServoIndexZ:4;//57bits
|
||||||
|
uint padding:7;
|
||||||
|
} __attribute__((packed)) heliGUISettingsStruct;
|
||||||
|
|
||||||
|
typedef union
|
||||||
|
{
|
||||||
|
uint UAVObject[2];//32bits * 2
|
||||||
|
heliGUISettingsStruct heli;//64bits
|
||||||
|
} GUIConfigDataUnion;
|
||||||
|
|
||||||
|
class ConfigccpmWidget: public ConfigTaskWidget
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
ConfigccpmWidget(QWidget *parent = 0);
|
||||||
|
~ConfigccpmWidget();
|
||||||
|
|
||||||
|
friend class ConfigVehicleTypeWidget;
|
||||||
|
|
||||||
|
private:
|
||||||
|
Ui_ccpmWidget *m_ccpm;
|
||||||
|
QGraphicsSvgItem *SwashplateImg;
|
||||||
|
QGraphicsSvgItem *CurveImg;
|
||||||
|
//QGraphicsSvgItem *ServoW;
|
||||||
|
//QGraphicsSvgItem *ServoX;
|
||||||
|
//QGraphicsSvgItem *ServoY;
|
||||||
|
//QGraphicsSvgItem *ServoZ;
|
||||||
|
//QGraphicsTextItem *ServoWText;
|
||||||
|
//QGraphicsTextItem *ServoXText;
|
||||||
|
//QGraphicsTextItem *ServoYText;
|
||||||
|
//QGraphicsTextItem *ServoZText;
|
||||||
|
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];
|
||||||
|
|
||||||
|
bool SwashLvlConfigurationInProgress;
|
||||||
|
UAVObject::Metadata SwashLvlaccInitialData;
|
||||||
|
int SwashLvlState;
|
||||||
|
int SwashLvlServoInterlock;
|
||||||
|
|
||||||
|
SwashplateServoSettingsStruct oldSwashLvlConfiguration;
|
||||||
|
SwashplateServoSettingsStruct newSwashLvlConfiguration;
|
||||||
|
|
||||||
|
GUIConfigDataUnion GUIConfigData;
|
||||||
|
|
||||||
|
int MixerChannelData[6];
|
||||||
|
int ShowDisclaimer(int messageID);
|
||||||
|
virtual void enableControls(bool enable) { Q_UNUSED(enable)}; // Not used by this widget
|
||||||
|
|
||||||
|
bool updatingFromHardware;
|
||||||
|
bool updatingToHardware;
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void ccpmSwashplateUpdate();
|
||||||
|
void ccpmSwashplateRedraw();
|
||||||
|
void UpdateCurveSettings();
|
||||||
|
void GenerateCurve();
|
||||||
|
void UpdateMixer();
|
||||||
|
void UpdateType();
|
||||||
|
void resetMixer(MixerCurveWidget *mixer, int numElements);
|
||||||
|
void UpdateCurveWidgets();
|
||||||
|
void updatePitchCurveValue(QList<double>,double);
|
||||||
|
void updateThrottleCurveValue(QList<double>,double);
|
||||||
|
|
||||||
|
void SwashLvlStartButtonPressed();
|
||||||
|
void SwashLvlNextButtonPressed();
|
||||||
|
void SwashLvlCancelButtonPressed();
|
||||||
|
void SwashLvlFinishButtonPressed();
|
||||||
|
|
||||||
|
void UpdateCCPMOptionsFromUI();
|
||||||
|
void UpdateCCPMUIFromOptions();
|
||||||
|
|
||||||
|
void SetUIComponentVisibilities();
|
||||||
|
void ccpmChannelCheck();
|
||||||
|
|
||||||
|
void enableSwashplateLevellingControl(bool state);
|
||||||
|
void setSwashplateLevel(int percent);
|
||||||
|
void SwashLvlSpinBoxChanged(int value);
|
||||||
|
virtual void refreshValues() {}; // Not used
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
void requestccpmUpdate();
|
||||||
|
void sendccpmUpdate();
|
||||||
|
void saveccpmUpdate();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void showEvent(QShowEvent *event);
|
||||||
|
void resizeEvent(QResizeEvent *event);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // CONFIGccpmWIDGET_H
|
@ -0,0 +1,699 @@
|
|||||||
|
/**
|
||||||
|
******************************************************************************
|
||||||
|
*
|
||||||
|
* @file configccpmwidget.cpp
|
||||||
|
* @author E. Lafargue & The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
|
||||||
|
* @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 "configfixedwingwidget.h"
|
||||||
|
#include "configvehicletypewidget.h"
|
||||||
|
#include "mixersettings.h"
|
||||||
|
|
||||||
|
#include <QDebug>
|
||||||
|
#include <QStringList>
|
||||||
|
#include <QtGui/QWidget>
|
||||||
|
#include <QtGui/QTextEdit>
|
||||||
|
#include <QtGui/QVBoxLayout>
|
||||||
|
#include <QtGui/QPushButton>
|
||||||
|
#include <QBrush>
|
||||||
|
#include <math.h>
|
||||||
|
#include <QMessageBox>
|
||||||
|
|
||||||
|
#include "mixersettings.h"
|
||||||
|
#include "systemsettings.h"
|
||||||
|
#include "actuatorcommand.h"
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Helper function to setup the UI
|
||||||
|
*/
|
||||||
|
void ConfigVehicleTypeWidget::setupFixedWingUI(QString frameType)
|
||||||
|
{
|
||||||
|
if (frameType == "FixedWing" || frameType == "Elevator aileron rudder") {
|
||||||
|
// Setup the UI
|
||||||
|
m_aircraft->aircraftType->setCurrentIndex(m_aircraft->aircraftType->findText("Fixed Wing"));
|
||||||
|
m_aircraft->fixedWingType->setCurrentIndex(m_aircraft->fixedWingType->findText("Elevator aileron rudder"));
|
||||||
|
m_aircraft->fwRudder1ChannelBox->setEnabled(true);
|
||||||
|
m_aircraft->fwRudder1Label->setEnabled(true);
|
||||||
|
m_aircraft->fwRudder2ChannelBox->setEnabled(true);
|
||||||
|
m_aircraft->fwRudder2Label->setEnabled(true);
|
||||||
|
m_aircraft->fwElevator1ChannelBox->setEnabled(true);
|
||||||
|
m_aircraft->fwElevator1Label->setEnabled(true);
|
||||||
|
m_aircraft->fwElevator2ChannelBox->setEnabled(true);
|
||||||
|
m_aircraft->fwElevator2Label->setEnabled(true);
|
||||||
|
m_aircraft->fwAileron1ChannelBox->setEnabled(true);
|
||||||
|
m_aircraft->fwAileron1Label->setEnabled(true);
|
||||||
|
m_aircraft->fwAileron2ChannelBox->setEnabled(true);
|
||||||
|
m_aircraft->fwAileron2Label->setEnabled(true);
|
||||||
|
|
||||||
|
m_aircraft->fwAileron1Label->setText("Aileron 1");
|
||||||
|
m_aircraft->fwAileron2Label->setText("Aileron 2");
|
||||||
|
m_aircraft->fwElevator1Label->setText("Elevator 1");
|
||||||
|
m_aircraft->fwElevator2Label->setText("Elevator 2");
|
||||||
|
m_aircraft->elevonMixBox->setHidden(true);
|
||||||
|
|
||||||
|
} else if (frameType == "FixedWingElevon" || frameType == "Elevon") {
|
||||||
|
m_aircraft->aircraftType->setCurrentIndex(m_aircraft->aircraftType->findText("Fixed Wing"));
|
||||||
|
m_aircraft->fixedWingType->setCurrentIndex(m_aircraft->fixedWingType->findText("Elevon"));
|
||||||
|
m_aircraft->fwAileron1Label->setText("Elevon 1");
|
||||||
|
m_aircraft->fwAileron2Label->setText("Elevon 2");
|
||||||
|
m_aircraft->fwElevator1ChannelBox->setEnabled(false);
|
||||||
|
m_aircraft->fwElevator1Label->setEnabled(false);
|
||||||
|
m_aircraft->fwElevator2ChannelBox->setEnabled(false);
|
||||||
|
m_aircraft->fwElevator2Label->setEnabled(false);
|
||||||
|
m_aircraft->fwRudder1ChannelBox->setEnabled(true);
|
||||||
|
m_aircraft->fwRudder1Label->setEnabled(true);
|
||||||
|
m_aircraft->fwRudder2ChannelBox->setEnabled(true);
|
||||||
|
m_aircraft->fwRudder2Label->setEnabled(true);
|
||||||
|
m_aircraft->fwElevator1Label->setText("Elevator 1");
|
||||||
|
m_aircraft->fwElevator2Label->setText("Elevator 2");
|
||||||
|
m_aircraft->elevonMixBox->setHidden(false);
|
||||||
|
m_aircraft->elevonLabel1->setText("Roll");
|
||||||
|
m_aircraft->elevonLabel2->setText("Pitch");
|
||||||
|
|
||||||
|
} else if (frameType == "FixedWingVtail" || frameType == "Vtail") {
|
||||||
|
m_aircraft->aircraftType->setCurrentIndex(m_aircraft->aircraftType->findText("Fixed Wing"));
|
||||||
|
m_aircraft->fixedWingType->setCurrentIndex(m_aircraft->fixedWingType->findText("Vtail"));
|
||||||
|
m_aircraft->fwRudder1ChannelBox->setEnabled(false);
|
||||||
|
m_aircraft->fwRudder1Label->setEnabled(false);
|
||||||
|
m_aircraft->fwRudder2ChannelBox->setEnabled(false);
|
||||||
|
m_aircraft->fwRudder2Label->setEnabled(false);
|
||||||
|
m_aircraft->fwElevator1ChannelBox->setEnabled(true);
|
||||||
|
m_aircraft->fwElevator1Label->setEnabled(true);
|
||||||
|
m_aircraft->fwElevator1Label->setText("Vtail 1");
|
||||||
|
m_aircraft->fwElevator2Label->setText("Vtail 2");
|
||||||
|
m_aircraft->elevonMixBox->setHidden(false);
|
||||||
|
m_aircraft->fwElevator2ChannelBox->setEnabled(true);
|
||||||
|
m_aircraft->fwElevator2Label->setEnabled(true);
|
||||||
|
m_aircraft->fwAileron1Label->setText("Aileron 1");
|
||||||
|
m_aircraft->fwAileron2Label->setText("Aileron 2");
|
||||||
|
m_aircraft->elevonLabel1->setText("Rudder");
|
||||||
|
m_aircraft->elevonLabel2->setText("Pitch");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Helper function to update the UI widget objects
|
||||||
|
*/
|
||||||
|
QString ConfigVehicleTypeWidget::updateFixedWingObjectsFromWidgets()
|
||||||
|
{
|
||||||
|
QString airframeType = "FixedWing";
|
||||||
|
|
||||||
|
// Save the curve (common to all Fixed wing frames)
|
||||||
|
UAVDataObject *obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
|
||||||
|
|
||||||
|
// Remove Feed Forward, it is pointless on a plane:
|
||||||
|
UAVObjectField* field = obj->getField(QString("FeedForward"));
|
||||||
|
field->setDouble(0);
|
||||||
|
|
||||||
|
field = obj->getField("ThrottleCurve1");
|
||||||
|
QList<double> curve = m_aircraft->fixedWingThrottle->getCurve();
|
||||||
|
for (int i=0;i<curve.length();i++) {
|
||||||
|
field->setValue(curve.at(i),i);
|
||||||
|
}
|
||||||
|
|
||||||
|
//All airframe types must start with "FixedWing"
|
||||||
|
if (m_aircraft->fixedWingType->currentText() == "Elevator aileron rudder" ) {
|
||||||
|
airframeType = "FixedWing";
|
||||||
|
setupFrameFixedWing( airframeType );
|
||||||
|
} else if (m_aircraft->fixedWingType->currentText() == "Elevon") {
|
||||||
|
airframeType = "FixedWingElevon";
|
||||||
|
setupFrameElevon( airframeType );
|
||||||
|
} else { // "Vtail"
|
||||||
|
airframeType = "FixedWingVtail";
|
||||||
|
setupFrameVtail( airframeType );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now reflect those settings in the "Custom" panel as well
|
||||||
|
updateCustomAirframeUI();
|
||||||
|
|
||||||
|
return airframeType;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Helper function to refresh the UI widget values
|
||||||
|
*/
|
||||||
|
void ConfigVehicleTypeWidget::refreshFixedWingWidgetsValues(QString frameType)
|
||||||
|
{
|
||||||
|
|
||||||
|
UAVDataObject* obj;
|
||||||
|
UAVObjectField *field;
|
||||||
|
|
||||||
|
// Then retrieve how channels are setup
|
||||||
|
obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("ActuatorSettings")));
|
||||||
|
Q_ASSERT(obj);
|
||||||
|
field = obj->getField(QString("FixedWingThrottle"));
|
||||||
|
Q_ASSERT(field);
|
||||||
|
m_aircraft->fwEngineChannelBox->setCurrentIndex(m_aircraft->fwEngineChannelBox->findText(field->getValue().toString()));
|
||||||
|
|
||||||
|
field = obj->getField(QString("FixedWingRoll1"));
|
||||||
|
Q_ASSERT(field);
|
||||||
|
m_aircraft->fwAileron1ChannelBox->setCurrentIndex(m_aircraft->fwAileron1ChannelBox->findText(field->getValue().toString()));
|
||||||
|
|
||||||
|
field = obj->getField(QString("FixedWingRoll2"));
|
||||||
|
Q_ASSERT(field);
|
||||||
|
m_aircraft->fwAileron2ChannelBox->setCurrentIndex(m_aircraft->fwAileron2ChannelBox->findText(field->getValue().toString()));
|
||||||
|
|
||||||
|
field = obj->getField(QString("FixedWingPitch1"));
|
||||||
|
Q_ASSERT(field);
|
||||||
|
m_aircraft->fwElevator1ChannelBox->setCurrentIndex(m_aircraft->fwElevator1ChannelBox->findText(field->getValue().toString()));
|
||||||
|
|
||||||
|
field = obj->getField(QString("FixedWingPitch2"));
|
||||||
|
Q_ASSERT(field);
|
||||||
|
m_aircraft->fwElevator2ChannelBox->setCurrentIndex(m_aircraft->fwElevator2ChannelBox->findText(field->getValue().toString()));
|
||||||
|
|
||||||
|
field = obj->getField(QString("FixedWingYaw1"));
|
||||||
|
Q_ASSERT(field);
|
||||||
|
m_aircraft->fwRudder1ChannelBox->setCurrentIndex(m_aircraft->fwRudder1ChannelBox->findText(field->getValue().toString()));
|
||||||
|
|
||||||
|
field = obj->getField(QString("FixedWingYaw2"));
|
||||||
|
Q_ASSERT(field);
|
||||||
|
m_aircraft->fwRudder2ChannelBox->setCurrentIndex(m_aircraft->fwRudder2ChannelBox->findText(field->getValue().toString()));
|
||||||
|
|
||||||
|
if (frameType == "FixedWingElevon") {
|
||||||
|
// If the airframe is elevon, restore the slider setting
|
||||||
|
// Find the channel number for Elevon1 (FixedWingRoll1)
|
||||||
|
obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
|
||||||
|
Q_ASSERT(obj);
|
||||||
|
int chMixerNumber = m_aircraft->fwAileron1ChannelBox->currentIndex()-1;
|
||||||
|
if (chMixerNumber >= 0) { // If for some reason the actuators were incoherent, we might fail here, hence the check.
|
||||||
|
field = obj->getField(mixerVectors.at(chMixerNumber));
|
||||||
|
int ti = field->getElementNames().indexOf("Roll");
|
||||||
|
m_aircraft->elevonSlider1->setValue(field->getDouble(ti)*100);
|
||||||
|
ti = field->getElementNames().indexOf("Pitch");
|
||||||
|
m_aircraft->elevonSlider2->setValue(field->getDouble(ti)*100);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (frameType == "FixedWingVtail") {
|
||||||
|
obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
|
||||||
|
Q_ASSERT(obj);
|
||||||
|
int chMixerNumber = m_aircraft->fwElevator1ChannelBox->currentIndex()-1;
|
||||||
|
if (chMixerNumber >=0) {
|
||||||
|
field = obj->getField(mixerVectors.at(chMixerNumber));
|
||||||
|
int ti = field->getElementNames().indexOf("Yaw");
|
||||||
|
m_aircraft->elevonSlider1->setValue(field->getDouble(ti)*100);
|
||||||
|
ti = field->getElementNames().indexOf("Pitch");
|
||||||
|
m_aircraft->elevonSlider2->setValue(field->getDouble(ti)*100);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Setup Elevator/Aileron/Rudder airframe.
|
||||||
|
|
||||||
|
If both Aileron channels are set to 'None' (EasyStar), do Pitch/Rudder mixing
|
||||||
|
|
||||||
|
Returns False if impossible to create the mixer.
|
||||||
|
*/
|
||||||
|
bool ConfigVehicleTypeWidget::setupFrameFixedWing(QString airframeType)
|
||||||
|
{
|
||||||
|
// Check coherence:
|
||||||
|
//Show any config errors in GUI
|
||||||
|
throwFixedWingChannelConfigError(airframeType);
|
||||||
|
|
||||||
|
// - At least Pitch and either Roll or Yaw
|
||||||
|
if (m_aircraft->fwEngineChannelBox->currentText() == "None" ||
|
||||||
|
m_aircraft->fwElevator1ChannelBox->currentText() == "None" ||
|
||||||
|
((m_aircraft->fwAileron1ChannelBox->currentText() == "None") &&
|
||||||
|
(m_aircraft->fwRudder1ChannelBox->currentText() == "None"))) {
|
||||||
|
// TODO: explain the problem in the UI
|
||||||
|
// m_aircraft->fwStatusLabel->setText("ERROR: check channel assignment");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// Now setup the channels:
|
||||||
|
resetActuators();
|
||||||
|
|
||||||
|
UAVDataObject* obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("ActuatorSettings")));
|
||||||
|
Q_ASSERT(obj);
|
||||||
|
|
||||||
|
// Elevator
|
||||||
|
UAVObjectField *field = obj->getField("FixedWingPitch1");
|
||||||
|
Q_ASSERT(field);
|
||||||
|
field->setValue(m_aircraft->fwElevator1ChannelBox->currentText());
|
||||||
|
field = obj->getField("FixedWingPitch2");
|
||||||
|
Q_ASSERT(field);
|
||||||
|
field->setValue(m_aircraft->fwElevator2ChannelBox->currentText());
|
||||||
|
|
||||||
|
// Aileron
|
||||||
|
field = obj->getField("FixedWingRoll1");
|
||||||
|
Q_ASSERT(field);
|
||||||
|
field->setValue(m_aircraft->fwAileron1ChannelBox->currentText());
|
||||||
|
field = obj->getField("FixedWingRoll2");
|
||||||
|
Q_ASSERT(field);
|
||||||
|
field->setValue(m_aircraft->fwAileron2ChannelBox->currentText());
|
||||||
|
|
||||||
|
// Rudder
|
||||||
|
field = obj->getField("FixedWingYaw1");
|
||||||
|
Q_ASSERT(field);
|
||||||
|
field->setValue(m_aircraft->fwRudder1ChannelBox->currentText());
|
||||||
|
|
||||||
|
// Throttle
|
||||||
|
field = obj->getField("FixedWingThrottle");
|
||||||
|
Q_ASSERT(field);
|
||||||
|
field->setValue(m_aircraft->fwEngineChannelBox->currentText());
|
||||||
|
|
||||||
|
obj->updated();
|
||||||
|
|
||||||
|
obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
|
||||||
|
Q_ASSERT(obj);
|
||||||
|
// ... and compute the matrix:
|
||||||
|
// In order to make code a bit nicer, we assume:
|
||||||
|
// - Channel dropdowns start with 'None', then 0 to 7
|
||||||
|
|
||||||
|
// 1. Assign the servo/motor/none for each channel
|
||||||
|
// Disable all
|
||||||
|
foreach(QString mixer, mixerTypes) {
|
||||||
|
field = obj->getField(mixer);
|
||||||
|
Q_ASSERT(field);
|
||||||
|
field->setValue("Disabled");
|
||||||
|
}
|
||||||
|
// and set only the relevant channels:
|
||||||
|
// Engine
|
||||||
|
int tmpVal = m_aircraft->fwEngineChannelBox->currentIndex()-1;
|
||||||
|
field = obj->getField(mixerTypes.at(tmpVal));
|
||||||
|
field->setValue("Motor");
|
||||||
|
field = obj->getField(mixerVectors.at(tmpVal));
|
||||||
|
// First of all reset the vector
|
||||||
|
resetField(field);
|
||||||
|
int ti = field->getElementNames().indexOf("ThrottleCurve1");
|
||||||
|
field->setValue(127, ti);
|
||||||
|
|
||||||
|
// Rudder
|
||||||
|
tmpVal = m_aircraft->fwRudder1ChannelBox->currentIndex()-1;
|
||||||
|
// tmpVal will be -1 if rudder is set to "None"
|
||||||
|
if (tmpVal > -1) {
|
||||||
|
field = obj->getField(mixerTypes.at(tmpVal));
|
||||||
|
field->setValue("Servo");
|
||||||
|
field = obj->getField(mixerVectors.at(tmpVal));
|
||||||
|
resetField(field);
|
||||||
|
ti = field->getElementNames().indexOf("Yaw");
|
||||||
|
field->setValue(127, ti);
|
||||||
|
} // Else: we have no rudder, only ailerons, we're fine with it.
|
||||||
|
|
||||||
|
// Ailerons
|
||||||
|
tmpVal = m_aircraft->fwAileron1ChannelBox->currentIndex()-1;
|
||||||
|
if (tmpVal > -1) {
|
||||||
|
field = obj->getField(mixerTypes.at(tmpVal));
|
||||||
|
field->setValue("Servo");
|
||||||
|
field = obj->getField(mixerVectors.at(tmpVal));
|
||||||
|
resetField(field);
|
||||||
|
ti = field->getElementNames().indexOf("Roll");
|
||||||
|
field->setValue(127, ti);
|
||||||
|
// Only set Aileron 2 if Aileron 1 is defined
|
||||||
|
tmpVal = m_aircraft->fwAileron2ChannelBox->currentIndex()-1;
|
||||||
|
if (tmpVal > -1) {
|
||||||
|
field = obj->getField(mixerTypes.at(tmpVal));
|
||||||
|
field->setValue("Servo");
|
||||||
|
field = obj->getField(mixerVectors.at(tmpVal));
|
||||||
|
resetField(field);
|
||||||
|
ti = field->getElementNames().indexOf("Roll");
|
||||||
|
field->setValue(127, ti);
|
||||||
|
}
|
||||||
|
} // Else we have no ailerons. Our consistency check guarantees we have
|
||||||
|
// rudder in this case, so we're fine with it too.
|
||||||
|
|
||||||
|
// Elevator
|
||||||
|
tmpVal = m_aircraft->fwElevator1ChannelBox->currentIndex()-1;
|
||||||
|
field = obj->getField(mixerTypes.at(tmpVal));
|
||||||
|
field->setValue("Servo");
|
||||||
|
field = obj->getField(mixerVectors.at(tmpVal));
|
||||||
|
resetField(field);
|
||||||
|
ti = field->getElementNames().indexOf("Pitch");
|
||||||
|
field->setValue(127, ti);
|
||||||
|
// Only set Elevator 2 if it is defined
|
||||||
|
tmpVal = m_aircraft->fwElevator2ChannelBox->currentIndex()-1;
|
||||||
|
if (tmpVal > -1) {
|
||||||
|
field = obj->getField(mixerTypes.at(tmpVal));
|
||||||
|
field->setValue("Servo");
|
||||||
|
field = obj->getField(mixerVectors.at(tmpVal));
|
||||||
|
resetField(field);
|
||||||
|
ti = field->getElementNames().indexOf("Pitch");
|
||||||
|
field->setValue(127, ti);
|
||||||
|
}
|
||||||
|
|
||||||
|
obj->updated();
|
||||||
|
m_aircraft->fwStatusLabel->setText("Mixer generated");
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Setup Elevon
|
||||||
|
*/
|
||||||
|
bool ConfigVehicleTypeWidget::setupFrameElevon(QString airframeType)
|
||||||
|
{
|
||||||
|
// Check coherence:
|
||||||
|
//Show any config errors in GUI
|
||||||
|
throwFixedWingChannelConfigError(airframeType);
|
||||||
|
|
||||||
|
// - At least Aileron1 and Aileron 2, and engine
|
||||||
|
if (m_aircraft->fwEngineChannelBox->currentText() == "None" ||
|
||||||
|
m_aircraft->fwAileron1ChannelBox->currentText() == "None" ||
|
||||||
|
m_aircraft->fwAileron2ChannelBox->currentText() == "None") {
|
||||||
|
// TODO: explain the problem in the UI
|
||||||
|
// m_aircraft->fwStatusLabel->setText("ERROR: check channel assignment");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
resetActuators();
|
||||||
|
UAVDataObject* obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("ActuatorSettings")));
|
||||||
|
Q_ASSERT(obj);
|
||||||
|
|
||||||
|
// Elevons
|
||||||
|
UAVObjectField *field = obj->getField("FixedWingRoll1");
|
||||||
|
Q_ASSERT(field);
|
||||||
|
field->setValue(m_aircraft->fwAileron1ChannelBox->currentText());
|
||||||
|
field = obj->getField("FixedWingRoll2");
|
||||||
|
Q_ASSERT(field);
|
||||||
|
field->setValue(m_aircraft->fwAileron2ChannelBox->currentText());
|
||||||
|
// Rudder 1 (can be None)
|
||||||
|
field = obj->getField("FixedWingYaw1");
|
||||||
|
Q_ASSERT(field);
|
||||||
|
field->setValue(m_aircraft->fwRudder1ChannelBox->currentText());
|
||||||
|
// Rudder 2 (can be None)
|
||||||
|
field = obj->getField("FixedWingYaw2");
|
||||||
|
Q_ASSERT(field);
|
||||||
|
field->setValue(m_aircraft->fwRudder2ChannelBox->currentText());
|
||||||
|
// Throttle
|
||||||
|
field = obj->getField("FixedWingThrottle");
|
||||||
|
Q_ASSERT(field);
|
||||||
|
field->setValue(m_aircraft->fwEngineChannelBox->currentText());
|
||||||
|
|
||||||
|
obj->updated();
|
||||||
|
|
||||||
|
// Save the curve:
|
||||||
|
obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
|
||||||
|
Q_ASSERT(obj);
|
||||||
|
// ... and compute the matrix:
|
||||||
|
// In order to make code a bit nicer, we assume:
|
||||||
|
// - Channel dropdowns start with 'None', then 0 to 7
|
||||||
|
|
||||||
|
// 1. Assign the servo/motor/none for each channel
|
||||||
|
// Disable all
|
||||||
|
foreach(QString mixer, mixerTypes) {
|
||||||
|
field = obj->getField(mixer);
|
||||||
|
Q_ASSERT(field);
|
||||||
|
field->setValue("Disabled");
|
||||||
|
}
|
||||||
|
// and set only the relevant channels:
|
||||||
|
// Engine
|
||||||
|
int tmpVal = m_aircraft->fwEngineChannelBox->currentIndex()-1;
|
||||||
|
field = obj->getField(mixerTypes.at(tmpVal));
|
||||||
|
field->setValue("Motor");
|
||||||
|
field = obj->getField(mixerVectors.at(tmpVal));
|
||||||
|
// First of all reset the vector
|
||||||
|
resetField(field);
|
||||||
|
int ti = field->getElementNames().indexOf("ThrottleCurve1");
|
||||||
|
field->setValue(127, ti);
|
||||||
|
|
||||||
|
// Rudder 1
|
||||||
|
tmpVal = m_aircraft->fwRudder1ChannelBox->currentIndex()-1;
|
||||||
|
// tmpVal will be -1 if rudder 1 is set to "None"
|
||||||
|
if (tmpVal > -1) {
|
||||||
|
field = obj->getField(mixerTypes.at(tmpVal));
|
||||||
|
field->setValue("Servo");
|
||||||
|
field = obj->getField(mixerVectors.at(tmpVal));
|
||||||
|
resetField(field);
|
||||||
|
ti = field->getElementNames().indexOf("Yaw");
|
||||||
|
field->setValue(127, ti);
|
||||||
|
} // Else: we have no rudder, only elevons, we're fine with it.
|
||||||
|
|
||||||
|
// Rudder 2
|
||||||
|
tmpVal = m_aircraft->fwRudder2ChannelBox->currentIndex()-1;
|
||||||
|
// tmpVal will be -1 if rudder 2 is set to "None"
|
||||||
|
if (tmpVal > -1) {
|
||||||
|
field = obj->getField(mixerTypes.at(tmpVal));
|
||||||
|
field->setValue("Servo");
|
||||||
|
field = obj->getField(mixerVectors.at(tmpVal));
|
||||||
|
resetField(field);
|
||||||
|
ti = field->getElementNames().indexOf("Yaw");
|
||||||
|
field->setValue(-127, ti);
|
||||||
|
} // Else: we have no rudder, only elevons, we're fine with it.
|
||||||
|
|
||||||
|
tmpVal = m_aircraft->fwAileron1ChannelBox->currentIndex()-1;
|
||||||
|
if (tmpVal > -1) {
|
||||||
|
field = obj->getField(mixerTypes.at(tmpVal));
|
||||||
|
field->setValue("Servo");
|
||||||
|
field = obj->getField(mixerVectors.at(tmpVal));
|
||||||
|
resetField(field);
|
||||||
|
ti = field->getElementNames().indexOf("Pitch");
|
||||||
|
field->setValue((double)m_aircraft->elevonSlider2->value()*1.27, ti);
|
||||||
|
ti = field->getElementNames().indexOf("Roll");
|
||||||
|
field->setValue((double)m_aircraft->elevonSlider1->value()*1.27,ti);
|
||||||
|
}
|
||||||
|
|
||||||
|
tmpVal = m_aircraft->fwAileron2ChannelBox->currentIndex()-1;
|
||||||
|
if (tmpVal > -1) {
|
||||||
|
field = obj->getField(mixerTypes.at(tmpVal));
|
||||||
|
field->setValue("Servo");
|
||||||
|
field = obj->getField(mixerVectors.at(tmpVal));
|
||||||
|
resetField(field);
|
||||||
|
ti = field->getElementNames().indexOf("Pitch");
|
||||||
|
field->setValue((double)m_aircraft->elevonSlider2->value()*1.27, ti);
|
||||||
|
ti = field->getElementNames().indexOf("Roll");
|
||||||
|
field->setValue(-(double)m_aircraft->elevonSlider1->value()*1.27,ti);
|
||||||
|
}
|
||||||
|
|
||||||
|
obj->updated();
|
||||||
|
m_aircraft->fwStatusLabel->setText("Mixer generated");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Setup VTail
|
||||||
|
*/
|
||||||
|
bool ConfigVehicleTypeWidget::setupFrameVtail(QString airframeType)
|
||||||
|
{
|
||||||
|
// Check coherence:
|
||||||
|
//Show any config errors in GUI
|
||||||
|
throwFixedWingChannelConfigError(airframeType);
|
||||||
|
|
||||||
|
// - At least Pitch1 and Pitch2, and engine
|
||||||
|
if (m_aircraft->fwEngineChannelBox->currentText() == "None" ||
|
||||||
|
m_aircraft->fwElevator1ChannelBox->currentText() == "None" ||
|
||||||
|
m_aircraft->fwElevator2ChannelBox->currentText() == "None") {
|
||||||
|
// TODO: explain the problem in the UI
|
||||||
|
// m_aircraft->fwStatusLabel->setText("WARNING: check channel assignment");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
resetActuators();
|
||||||
|
UAVDataObject* obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("ActuatorSettings")));
|
||||||
|
Q_ASSERT(obj);
|
||||||
|
|
||||||
|
// Elevons
|
||||||
|
UAVObjectField *field = obj->getField("FixedWingPitch1");
|
||||||
|
Q_ASSERT(field);
|
||||||
|
field->setValue(m_aircraft->fwElevator1ChannelBox->currentText());
|
||||||
|
field = obj->getField("FixedWingPitch2");
|
||||||
|
Q_ASSERT(field);
|
||||||
|
field->setValue(m_aircraft->fwElevator2ChannelBox->currentText());
|
||||||
|
field = obj->getField("FixedWingRoll1");
|
||||||
|
Q_ASSERT(field);
|
||||||
|
field->setValue(m_aircraft->fwAileron1ChannelBox->currentText());
|
||||||
|
field = obj->getField("FixedWingRoll2");
|
||||||
|
Q_ASSERT(field);
|
||||||
|
field->setValue(m_aircraft->fwAileron2ChannelBox->currentText());
|
||||||
|
|
||||||
|
// Throttle
|
||||||
|
field = obj->getField("FixedWingThrottle");
|
||||||
|
Q_ASSERT(field);
|
||||||
|
field->setValue(m_aircraft->fwEngineChannelBox->currentText());
|
||||||
|
|
||||||
|
obj->updated();
|
||||||
|
|
||||||
|
obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
|
||||||
|
Q_ASSERT(obj);
|
||||||
|
// ... and compute the matrix:
|
||||||
|
// In order to make code a bit nicer, we assume:
|
||||||
|
// - Channel dropdowns start with 'None', then 0 to 7
|
||||||
|
|
||||||
|
// 1. Assign the servo/motor/none for each channel
|
||||||
|
// Disable all
|
||||||
|
foreach(QString mixer, mixerTypes) {
|
||||||
|
field = obj->getField(mixer);
|
||||||
|
Q_ASSERT(field);
|
||||||
|
field->setValue("Disabled");
|
||||||
|
}
|
||||||
|
// and set only the relevant channels:
|
||||||
|
// Engine
|
||||||
|
int tmpVal = m_aircraft->fwEngineChannelBox->currentIndex()-1;
|
||||||
|
field = obj->getField(mixerTypes.at(tmpVal));
|
||||||
|
field->setValue("Motor");
|
||||||
|
field = obj->getField(mixerVectors.at(tmpVal));
|
||||||
|
// First of all reset the vector
|
||||||
|
resetField(field);
|
||||||
|
int ti = field->getElementNames().indexOf("ThrottleCurve1");
|
||||||
|
field->setValue(127, ti);
|
||||||
|
|
||||||
|
tmpVal = m_aircraft->fwAileron1ChannelBox->currentIndex()-1;
|
||||||
|
if (tmpVal > -1) {
|
||||||
|
field = obj->getField(mixerTypes.at(tmpVal));
|
||||||
|
field->setValue("Servo");
|
||||||
|
field = obj->getField(mixerVectors.at(tmpVal));
|
||||||
|
resetField(field);
|
||||||
|
ti = field->getElementNames().indexOf("Roll");
|
||||||
|
field->setValue(127,ti);
|
||||||
|
}
|
||||||
|
|
||||||
|
tmpVal = m_aircraft->fwAileron2ChannelBox->currentIndex()-1;
|
||||||
|
if (tmpVal > -1) {
|
||||||
|
field = obj->getField(mixerTypes.at(tmpVal));
|
||||||
|
field->setValue("Servo");
|
||||||
|
field = obj->getField(mixerVectors.at(tmpVal));
|
||||||
|
resetField(field);
|
||||||
|
ti = field->getElementNames().indexOf("Roll");
|
||||||
|
field->setValue(-127,ti);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now compute the VTail
|
||||||
|
tmpVal = m_aircraft->fwElevator1ChannelBox->currentIndex()-1;
|
||||||
|
field = obj->getField(mixerTypes.at(tmpVal));
|
||||||
|
field->setValue("Servo");
|
||||||
|
field = obj->getField(mixerVectors.at(tmpVal));
|
||||||
|
resetField(field);
|
||||||
|
ti = field->getElementNames().indexOf("Pitch");
|
||||||
|
field->setValue((double)m_aircraft->elevonSlider2->value()*1.27, ti);
|
||||||
|
ti = field->getElementNames().indexOf("Yaw");
|
||||||
|
field->setValue((double)m_aircraft->elevonSlider1->value()*1.27,ti);
|
||||||
|
|
||||||
|
tmpVal = m_aircraft->fwElevator2ChannelBox->currentIndex()-1;
|
||||||
|
field = obj->getField(mixerTypes.at(tmpVal));
|
||||||
|
field->setValue("Servo");
|
||||||
|
field = obj->getField(mixerVectors.at(tmpVal));
|
||||||
|
resetField(field);
|
||||||
|
ti = field->getElementNames().indexOf("Pitch");
|
||||||
|
field->setValue((double)m_aircraft->elevonSlider2->value()*1.27, ti);
|
||||||
|
ti = field->getElementNames().indexOf("Yaw");
|
||||||
|
field->setValue(-(double)m_aircraft->elevonSlider1->value()*1.27,ti);
|
||||||
|
|
||||||
|
obj->updated();
|
||||||
|
m_aircraft->fwStatusLabel->setText("Mixer generated");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
This function displays text and color formatting in order to help the user understand what channels have not yet been configured.
|
||||||
|
*/
|
||||||
|
void ConfigVehicleTypeWidget::throwFixedWingChannelConfigError(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>"));
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,751 @@
|
|||||||
|
/**
|
||||||
|
******************************************************************************
|
||||||
|
*
|
||||||
|
* @file configccpmwidget.cpp
|
||||||
|
* @author E. Lafargue & The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
|
||||||
|
* @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 "configgroundvehiclewidget.h"
|
||||||
|
#include "configvehicletypewidget.h"
|
||||||
|
#include "mixersettings.h"
|
||||||
|
|
||||||
|
#include <QDebug>
|
||||||
|
#include <QStringList>
|
||||||
|
#include <QtGui/QWidget>
|
||||||
|
#include <QtGui/QTextEdit>
|
||||||
|
#include <QtGui/QVBoxLayout>
|
||||||
|
#include <QtGui/QPushButton>
|
||||||
|
#include <QBrush>
|
||||||
|
#include <math.h>
|
||||||
|
#include <QMessageBox>
|
||||||
|
|
||||||
|
#include "mixersettings.h"
|
||||||
|
#include "systemsettings.h"
|
||||||
|
#include "actuatorcommand.h"
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Helper function to setup the UI
|
||||||
|
*/
|
||||||
|
void ConfigVehicleTypeWidget::setupGroundVehicleUI(QString frameType)
|
||||||
|
{
|
||||||
|
m_aircraft->differentialSteeringMixBox->setHidden(true);
|
||||||
|
//STILL NEEDS WORK
|
||||||
|
// Setup the UI
|
||||||
|
m_aircraft->aircraftType->setCurrentIndex(m_aircraft->aircraftType->findText("Ground"));
|
||||||
|
|
||||||
|
m_aircraft->gvEngineChannelBox->setEnabled(false);
|
||||||
|
m_aircraft->gvEngineLabel->setEnabled(false);
|
||||||
|
|
||||||
|
|
||||||
|
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
|
||||||
|
m_aircraft->groundVehicleType->setCurrentIndex(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);
|
||||||
|
|
||||||
|
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
|
||||||
|
m_aircraft->groundVehicleType->setCurrentIndex(m_aircraft->groundVehicleType->findText("Motorcycle"));
|
||||||
|
m_aircraft->gvMotor1ChannelBox->setEnabled(false);
|
||||||
|
m_aircraft->gvMotor1Label->setEnabled(false);
|
||||||
|
|
||||||
|
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->gvSteering2Label->setText("Balancing");
|
||||||
|
|
||||||
|
m_aircraft->differentialSteeringMixBox->setHidden(true);
|
||||||
|
|
||||||
|
m_aircraft->gvThrottleCurve1GroupBox->setTitle("Front throttle curve");
|
||||||
|
m_aircraft->gvThrottleCurve2GroupBox->setTitle("Rear throttle curve");
|
||||||
|
}
|
||||||
|
else {//Car
|
||||||
|
m_aircraft->groundVehicleType->setCurrentIndex(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");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Helper function to update the UI widget objects
|
||||||
|
*/
|
||||||
|
QString ConfigVehicleTypeWidget::updateGroundVehicleObjectsFromWidgets()
|
||||||
|
{
|
||||||
|
QString airframeType = "GroundVehicleCar";
|
||||||
|
|
||||||
|
// Save the curve (common to all ground vehicle frames)
|
||||||
|
UAVDataObject *obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
|
||||||
|
|
||||||
|
// Remove Feed Forward, it is pointless on a ground vehicle:
|
||||||
|
UAVObjectField* field = obj->getField(QString("FeedForward"));
|
||||||
|
field->setDouble(0);
|
||||||
|
|
||||||
|
field = obj->getField("ThrottleCurve1");
|
||||||
|
QList<double> curve = m_aircraft->groundVehicleThrottle1->getCurve();
|
||||||
|
for (int i=0;i<curve.length();i++) {
|
||||||
|
field->setValue(curve.at(i),i);
|
||||||
|
}
|
||||||
|
|
||||||
|
field = obj->getField("ThrottleCurve2");
|
||||||
|
curve = m_aircraft->groundVehicleThrottle2->getCurve();
|
||||||
|
for (int i=0;i<curve.length();i++) {
|
||||||
|
field->setValue(curve.at(i),i);
|
||||||
|
}
|
||||||
|
|
||||||
|
//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);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now reflect those settings in the "Custom" panel as well
|
||||||
|
updateCustomAirframeUI();
|
||||||
|
|
||||||
|
return airframeType;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Helper function to refresh the UI widget values
|
||||||
|
*/
|
||||||
|
void ConfigVehicleTypeWidget::refreshGroundVehicleWidgetsValues(QString frameType)
|
||||||
|
{
|
||||||
|
|
||||||
|
UAVDataObject* obj;
|
||||||
|
UAVObjectField *field;
|
||||||
|
|
||||||
|
//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
|
||||||
|
obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("ActuatorSettings")));
|
||||||
|
Q_ASSERT(obj);
|
||||||
|
field = obj->getField(QString("FixedWingThrottle"));
|
||||||
|
Q_ASSERT(field);
|
||||||
|
m_aircraft->gvEngineChannelBox->setCurrentIndex(m_aircraft->gvEngineChannelBox->findText(field->getValue().toString()));
|
||||||
|
|
||||||
|
field = obj->getField(QString("FixedWingRoll1"));
|
||||||
|
Q_ASSERT(field);
|
||||||
|
m_aircraft->gvAileron1ChannelBox->setCurrentIndex(m_aircraft->gvAileron1ChannelBox->findText(field->getValue().toString()));
|
||||||
|
|
||||||
|
field = obj->getField(QString("FixedWingRoll2"));
|
||||||
|
Q_ASSERT(field);
|
||||||
|
m_aircraft->gvAileron2ChannelBox->setCurrentIndex(m_aircraft->gvAileron2ChannelBox->findText(field->getValue().toString()));
|
||||||
|
|
||||||
|
field = obj->getField(QString("GroundVehicleThrottle1"));
|
||||||
|
Q_ASSERT(field);
|
||||||
|
m_aircraft->gvMotor1ChannelBox->setCurrentIndex(m_aircraft->gvMotor1ChannelBox->findText(field->getValue().toString()));
|
||||||
|
|
||||||
|
field = obj->getField(QString("GroundVehicleThrottle2"));
|
||||||
|
Q_ASSERT(field);
|
||||||
|
m_aircraft->gvMotor2ChannelBox->setCurrentIndex(m_aircraft->gvMotor2ChannelBox->findText(field->getValue().toString()));
|
||||||
|
|
||||||
|
field = obj->getField(QString("GroundVehicleSteering1"));
|
||||||
|
Q_ASSERT(field);
|
||||||
|
m_aircraft->gvSteering1ChannelBox->setCurrentIndex(m_aircraft->gvSteering1ChannelBox->findText(field->getValue().toString()));
|
||||||
|
|
||||||
|
field = obj->getField(QString("GroundVehicleSteering2"));
|
||||||
|
Q_ASSERT(field);
|
||||||
|
m_aircraft->gvSteering2ChannelBox->setCurrentIndex(m_aircraft->gvSteering2ChannelBox->findText(field->getValue().toString()));
|
||||||
|
|
||||||
|
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 chMixerNumber = m_aircraft->gvMotor1ChannelBox->currentIndex()-1;
|
||||||
|
if (chMixerNumber >= 0) { // If for some reason the actuators were incoherent, we might fail here, hence the check.
|
||||||
|
field = obj->getField(mixerVectors.at(chMixerNumber));
|
||||||
|
int ti = field->getElementNames().indexOf("Roll");
|
||||||
|
m_aircraft->differentialSteeringSlider1->setValue(field->getDouble(ti)*100);
|
||||||
|
|
||||||
|
ti = field->getElementNames().indexOf("Pitch");
|
||||||
|
m_aircraft->differentialSteeringSlider2->setValue(field->getDouble(ti)*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 ConfigVehicleTypeWidget::setupGroundVehicleMotorcycle(QString airframeType){
|
||||||
|
// Check coherence:
|
||||||
|
//Show any config errors in GUI
|
||||||
|
throwGroundVehicleChannelConfigError(airframeType);
|
||||||
|
|
||||||
|
// - Motor, steering, and balance
|
||||||
|
if (m_aircraft->gvMotor1ChannelBox->currentText() == "None" ||
|
||||||
|
(m_aircraft->gvSteering1ChannelBox->currentText() == "None" ||
|
||||||
|
m_aircraft->gvSteering2ChannelBox->currentText() == "None") )
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Now setup the channels:
|
||||||
|
resetActuators();
|
||||||
|
|
||||||
|
UAVDataObject* obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("ActuatorSettings")));
|
||||||
|
Q_ASSERT(obj);
|
||||||
|
|
||||||
|
// Left motor
|
||||||
|
UAVObjectField *field = obj->getField("GroundVehicleThrottle1");
|
||||||
|
Q_ASSERT(field);
|
||||||
|
field->setValue(m_aircraft->gvMotor1ChannelBox->currentText());
|
||||||
|
|
||||||
|
// Right motor
|
||||||
|
field = obj->getField("GroundVehicleThrottle2");
|
||||||
|
Q_ASSERT(field);
|
||||||
|
field->setValue(m_aircraft->gvMotor2ChannelBox->currentText());
|
||||||
|
|
||||||
|
obj->updated();
|
||||||
|
|
||||||
|
obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
|
||||||
|
Q_ASSERT(obj);
|
||||||
|
// ... and compute the matrix:
|
||||||
|
// In order to make code a bit nicer, we assume:
|
||||||
|
// - Channel dropdowns start with 'None', then 0 to 7
|
||||||
|
|
||||||
|
// 1. Assign the servo/motor/none for each channel
|
||||||
|
|
||||||
|
int tmpVal, ti;
|
||||||
|
|
||||||
|
// Disable all output channels
|
||||||
|
foreach(QString mixer, mixerTypes) {
|
||||||
|
field = obj->getField(mixer);
|
||||||
|
Q_ASSERT(field);
|
||||||
|
|
||||||
|
//Disable output channel
|
||||||
|
field->setValue("Disabled");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set all mixer values to zero
|
||||||
|
foreach(QString mixer, mixerVectors) {
|
||||||
|
field = obj->getField(mixer);
|
||||||
|
resetField(field);
|
||||||
|
|
||||||
|
ti = field->getElementNames().indexOf("ThrottleCurve1");
|
||||||
|
field->setValue(0, ti);
|
||||||
|
ti = field->getElementNames().indexOf("ThrottleCurve2");
|
||||||
|
field->setValue(0, ti);
|
||||||
|
ti = field->getElementNames().indexOf("Yaw");
|
||||||
|
field->setValue(0, ti);
|
||||||
|
ti = field->getElementNames().indexOf("Pitch");
|
||||||
|
field->setValue(0, ti);
|
||||||
|
ti = field->getElementNames().indexOf("Roll");
|
||||||
|
field->setValue(0, ti);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Motor
|
||||||
|
// Setup motor
|
||||||
|
tmpVal = m_aircraft->gvMotor2ChannelBox->currentIndex()-1;
|
||||||
|
field = obj->getField(mixerTypes.at(tmpVal));
|
||||||
|
field->setValue("Servo"); //Set motor mixer type to Servo
|
||||||
|
field = obj->getField(mixerVectors.at(tmpVal));
|
||||||
|
resetField(field);
|
||||||
|
ti = field->getElementNames().indexOf("ThrottleCurve1"); //Set motor to full forward
|
||||||
|
field->setValue(127, ti);
|
||||||
|
|
||||||
|
//Steering
|
||||||
|
// Setup steering
|
||||||
|
tmpVal = m_aircraft->gvSteering1ChannelBox->currentIndex()-1;
|
||||||
|
field = obj->getField(mixerTypes.at(tmpVal));
|
||||||
|
field->setValue("Servo"); //Set motor mixer type to Servo
|
||||||
|
field = obj->getField(mixerVectors.at(tmpVal));
|
||||||
|
resetField(field);
|
||||||
|
ti = field->getElementNames().indexOf("Yaw"); //Set steering response to roll
|
||||||
|
field->setValue(-127, ti);
|
||||||
|
ti = field->getElementNames().indexOf("Roll"); //Set steering response to roll
|
||||||
|
field->setValue(-127, ti);
|
||||||
|
|
||||||
|
//Balancing
|
||||||
|
// Setup balancing servo
|
||||||
|
tmpVal = m_aircraft->gvSteering2ChannelBox->currentIndex()-1;
|
||||||
|
field = obj->getField(mixerTypes.at(tmpVal));
|
||||||
|
field->setValue("Servo"); //Set motor mixer type to Servo
|
||||||
|
field = obj->getField(mixerVectors.at(tmpVal));
|
||||||
|
resetField(field);
|
||||||
|
ti = field->getElementNames().indexOf("Yaw"); //Set balance response to yaw
|
||||||
|
field->setValue(127, ti);
|
||||||
|
ti = field->getElementNames().indexOf("Roll"); //Set balance response to roll
|
||||||
|
field->setValue(127, ti);
|
||||||
|
|
||||||
|
obj->updated();
|
||||||
|
|
||||||
|
//Output success message
|
||||||
|
m_aircraft->gvStatusLabel->setText("Mixer generated");
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Setup differentially steered ground vehicle.
|
||||||
|
|
||||||
|
Returns False if impossible to create the mixer.
|
||||||
|
*/
|
||||||
|
bool ConfigVehicleTypeWidget::setupGroundVehicleDifferential(QString airframeType){
|
||||||
|
// Check coherence:
|
||||||
|
//Show any config errors in GUI
|
||||||
|
throwGroundVehicleChannelConfigError(airframeType);
|
||||||
|
|
||||||
|
// - Left and right steering
|
||||||
|
if ( m_aircraft->gvMotor2ChannelBox->currentText() == "None" ||
|
||||||
|
m_aircraft->gvSteering1ChannelBox->currentText() == "None")
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Now setup the channels:
|
||||||
|
resetActuators();
|
||||||
|
|
||||||
|
UAVDataObject* obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("ActuatorSettings")));
|
||||||
|
Q_ASSERT(obj);
|
||||||
|
|
||||||
|
// Left motor
|
||||||
|
UAVObjectField *field = obj->getField("GroundVehicleThrottle1");
|
||||||
|
Q_ASSERT(field);
|
||||||
|
field->setValue(m_aircraft->gvMotor1ChannelBox->currentText());
|
||||||
|
|
||||||
|
// Right motor
|
||||||
|
field = obj->getField("GroundVehicleThrottle2");
|
||||||
|
Q_ASSERT(field);
|
||||||
|
field->setValue(m_aircraft->gvMotor2ChannelBox->currentText());
|
||||||
|
|
||||||
|
obj->updated();
|
||||||
|
|
||||||
|
obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
|
||||||
|
Q_ASSERT(obj);
|
||||||
|
// ... and compute the matrix:
|
||||||
|
// In order to make code a bit nicer, we assume:
|
||||||
|
// - Channel dropdowns start with 'None', then 0 to 7
|
||||||
|
|
||||||
|
// 1. Assign the servo/motor/none for each channel
|
||||||
|
|
||||||
|
int tmpVal, ti;
|
||||||
|
|
||||||
|
// Disable all output channels
|
||||||
|
foreach(QString mixer, mixerTypes) {
|
||||||
|
field = obj->getField(mixer);
|
||||||
|
Q_ASSERT(field);
|
||||||
|
|
||||||
|
//Disable output channel
|
||||||
|
field->setValue("Disabled");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set all mixer values to zero
|
||||||
|
foreach(QString mixer, mixerVectors) {
|
||||||
|
field = obj->getField(mixer);
|
||||||
|
resetField(field);
|
||||||
|
|
||||||
|
ti = field->getElementNames().indexOf("ThrottleCurve1");
|
||||||
|
field->setValue(0, ti);
|
||||||
|
ti = field->getElementNames().indexOf("ThrottleCurve2");
|
||||||
|
field->setValue(0, ti);
|
||||||
|
ti = field->getElementNames().indexOf("Yaw");
|
||||||
|
field->setValue(0, ti);
|
||||||
|
ti = field->getElementNames().indexOf("Pitch");
|
||||||
|
field->setValue(0, ti);
|
||||||
|
ti = field->getElementNames().indexOf("Roll");
|
||||||
|
field->setValue(0, ti);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Motor
|
||||||
|
// Setup left motor
|
||||||
|
tmpVal = m_aircraft->gvMotor1ChannelBox->currentIndex()-1;
|
||||||
|
field = obj->getField(mixerTypes.at(tmpVal));
|
||||||
|
field->setValue("Servo"); //Set motor mixer type to Servo
|
||||||
|
field = obj->getField(mixerVectors.at(tmpVal));
|
||||||
|
resetField(field);
|
||||||
|
ti = field->getElementNames().indexOf("ThrottleCurve1"); //Set motor to full forward
|
||||||
|
field->setValue(127, ti);
|
||||||
|
ti = field->getElementNames().indexOf("Yaw"); //Set motor to turn right with increasing throttle
|
||||||
|
field->setValue(127, ti);
|
||||||
|
|
||||||
|
// Setup right motor
|
||||||
|
tmpVal = m_aircraft->gvMotor2ChannelBox->currentIndex()-1;
|
||||||
|
field = obj->getField(mixerTypes.at(tmpVal));
|
||||||
|
field->setValue("Servo"); //Set motor mixer type to Servo
|
||||||
|
field = obj->getField(mixerVectors.at(tmpVal));
|
||||||
|
resetField(field);
|
||||||
|
ti = field->getElementNames().indexOf("ThrottleCurve2"); //Set motor to full forward
|
||||||
|
field->setValue(127, ti);
|
||||||
|
ti = field->getElementNames().indexOf("Yaw"); //Set motor to turn left with increasing throttle
|
||||||
|
field->setValue(-127, ti);
|
||||||
|
|
||||||
|
obj->updated();
|
||||||
|
|
||||||
|
//Output success message
|
||||||
|
m_aircraft->gvStatusLabel->setText("Mixer generated");
|
||||||
|
|
||||||
|
return true;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Setup steerable ground vehicle.
|
||||||
|
|
||||||
|
Returns False if impossible to create the mixer.
|
||||||
|
*/
|
||||||
|
bool ConfigVehicleTypeWidget::setupGroundVehicleCar(QString airframeType)
|
||||||
|
{
|
||||||
|
// Check coherence:
|
||||||
|
//Show any config errors in GUI
|
||||||
|
throwGroundVehicleChannelConfigError(airframeType);
|
||||||
|
|
||||||
|
// - At least one motor and one steering servo
|
||||||
|
if ((m_aircraft->gvMotor1ChannelBox->currentText() == "None" &&
|
||||||
|
m_aircraft->gvMotor2ChannelBox->currentText() == "None") ||
|
||||||
|
(m_aircraft->gvSteering1ChannelBox->currentText() == "None" &&
|
||||||
|
m_aircraft->gvSteering2ChannelBox->currentText() == "None"))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// else{
|
||||||
|
// // m_aircraft->gvStatusLabel->setText("Mixer generated");
|
||||||
|
// 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());
|
||||||
|
// delete htmlText;
|
||||||
|
//
|
||||||
|
// 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());
|
||||||
|
// }
|
||||||
|
|
||||||
|
// Now setup the channels:
|
||||||
|
resetActuators();
|
||||||
|
|
||||||
|
UAVDataObject* obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("ActuatorSettings")));
|
||||||
|
Q_ASSERT(obj);
|
||||||
|
|
||||||
|
// Front motor
|
||||||
|
UAVObjectField *field = obj->getField("GroundVehicleThrottle1");
|
||||||
|
Q_ASSERT(field);
|
||||||
|
field->setValue(m_aircraft->gvMotor1ChannelBox->currentText());
|
||||||
|
|
||||||
|
// Rear motor
|
||||||
|
field = obj->getField("GroundVehicleThrottle2");
|
||||||
|
Q_ASSERT(field);
|
||||||
|
field->setValue(m_aircraft->gvMotor2ChannelBox->currentText());
|
||||||
|
|
||||||
|
// // Aileron
|
||||||
|
// field = obj->getField("FixedWingRoll1");
|
||||||
|
// Q_ASSERT(field);
|
||||||
|
// field->setValue(m_aircraft->fwAileron1ChannelBox->currentText());
|
||||||
|
//
|
||||||
|
// field = obj->getField("FixedWingRoll2");
|
||||||
|
// Q_ASSERT(field);
|
||||||
|
// field->setValue(m_aircraft->fwAileron2ChannelBox->currentText());
|
||||||
|
|
||||||
|
// Front steering
|
||||||
|
field = obj->getField("GroundVehicleSteering1");
|
||||||
|
Q_ASSERT(field);
|
||||||
|
field->setValue(m_aircraft->gvSteering1ChannelBox->currentText());
|
||||||
|
|
||||||
|
// Rear steering
|
||||||
|
field = obj->getField("GroundVehicleSteering2");
|
||||||
|
Q_ASSERT(field);
|
||||||
|
field->setValue(m_aircraft->gvSteering2ChannelBox->currentText());
|
||||||
|
|
||||||
|
obj->updated();
|
||||||
|
|
||||||
|
obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
|
||||||
|
Q_ASSERT(obj);
|
||||||
|
// ... and compute the matrix:
|
||||||
|
// In order to make code a bit nicer, we assume:
|
||||||
|
// - Channel dropdowns start with 'None', then 0 to 7
|
||||||
|
|
||||||
|
// 1. Assign the servo/motor/none for each channel
|
||||||
|
|
||||||
|
int tmpVal, ti;
|
||||||
|
|
||||||
|
// Disable all output channels
|
||||||
|
foreach(QString mixer, mixerTypes) {
|
||||||
|
field = obj->getField(mixer);
|
||||||
|
Q_ASSERT(field);
|
||||||
|
|
||||||
|
//Disable output channel
|
||||||
|
field->setValue("Disabled");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set all mixer values to zero
|
||||||
|
foreach(QString mixer, mixerVectors) {
|
||||||
|
field = obj->getField(mixer);
|
||||||
|
resetField(field);
|
||||||
|
|
||||||
|
ti = field->getElementNames().indexOf("ThrottleCurve1");
|
||||||
|
field->setValue(0, ti);
|
||||||
|
ti = field->getElementNames().indexOf("ThrottleCurve2");
|
||||||
|
field->setValue(0, ti);
|
||||||
|
ti = field->getElementNames().indexOf("Yaw");
|
||||||
|
field->setValue(0, ti);
|
||||||
|
ti = field->getElementNames().indexOf("Pitch");
|
||||||
|
field->setValue(0, ti);
|
||||||
|
ti = field->getElementNames().indexOf("Roll");
|
||||||
|
field->setValue(0, ti);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Steering
|
||||||
|
// Only set front steering if it is defined
|
||||||
|
tmpVal = m_aircraft->gvSteering1ChannelBox->currentIndex()-1;
|
||||||
|
// tmpVal will be -1 if steering is set to "None"
|
||||||
|
if (tmpVal > -1) {
|
||||||
|
field = obj->getField(mixerTypes.at(tmpVal));
|
||||||
|
field->setValue("Servo");
|
||||||
|
field = obj->getField(mixerVectors.at(tmpVal));
|
||||||
|
resetField(field);
|
||||||
|
ti = field->getElementNames().indexOf("Yaw");
|
||||||
|
field->setValue(127, ti);
|
||||||
|
} // Else: we have no front steering. We're fine with it as long as we have rear steering
|
||||||
|
|
||||||
|
// Only set rear steering if it is defined
|
||||||
|
tmpVal = m_aircraft->gvSteering2ChannelBox->currentIndex()-1;
|
||||||
|
// tmpVal will be -1 if steering is set to "None"
|
||||||
|
if (tmpVal > -1) {
|
||||||
|
field = obj->getField(mixerTypes.at(tmpVal));
|
||||||
|
field->setValue("Servo");
|
||||||
|
field = obj->getField(mixerVectors.at(tmpVal));
|
||||||
|
resetField(field);
|
||||||
|
ti = field->getElementNames().indexOf("Yaw");
|
||||||
|
field->setValue(-127, ti);
|
||||||
|
} // Else: we have no rear steering. We're fine with it as long as we have front steering
|
||||||
|
|
||||||
|
// Motor
|
||||||
|
// Only set front motor if it is defined
|
||||||
|
tmpVal = m_aircraft->gvMotor1ChannelBox->currentIndex()-1;
|
||||||
|
if (tmpVal > -1) {
|
||||||
|
field = obj->getField(mixerTypes.at(tmpVal));
|
||||||
|
field->setValue("Servo");
|
||||||
|
field = obj->getField(mixerVectors.at(tmpVal));
|
||||||
|
resetField(field);
|
||||||
|
ti = field->getElementNames().indexOf("ThrottleCurve1");
|
||||||
|
field->setValue(127, ti);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Only set rear motor if it is defined
|
||||||
|
tmpVal = m_aircraft->gvMotor2ChannelBox->currentIndex()-1;
|
||||||
|
if (tmpVal > -1) {
|
||||||
|
field = obj->getField(mixerTypes.at(tmpVal));
|
||||||
|
field->setValue("Servo");
|
||||||
|
field = obj->getField(mixerVectors.at(tmpVal));
|
||||||
|
resetField(field);
|
||||||
|
ti = field->getElementNames().indexOf("ThrottleCurve2");
|
||||||
|
field->setValue(127, ti);
|
||||||
|
}
|
||||||
|
|
||||||
|
obj->updated();
|
||||||
|
|
||||||
|
//Output success message
|
||||||
|
m_aircraft->gvStatusLabel->setText("Mixer generated");
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
This function displays text and color formatting in order to help the user understand what channels have not yet been configured.
|
||||||
|
*/
|
||||||
|
void ConfigVehicleTypeWidget::throwGroundVehicleChannelConfigError(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->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;
|
||||||
|
|
||||||
|
}
|
||||||
|
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>"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,1195 @@
|
|||||||
|
/**
|
||||||
|
******************************************************************************
|
||||||
|
*
|
||||||
|
* @file configccpmwidget.cpp
|
||||||
|
* @author E. Lafargue & The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
|
||||||
|
* @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 "configmultirotorwidget.h"
|
||||||
|
#include "configvehicletypewidget.h"
|
||||||
|
#include "mixersettings.h"
|
||||||
|
|
||||||
|
#include <QDebug>
|
||||||
|
#include <QStringList>
|
||||||
|
#include <QtGui/QWidget>
|
||||||
|
#include <QtGui/QTextEdit>
|
||||||
|
#include <QtGui/QVBoxLayout>
|
||||||
|
#include <QtGui/QPushButton>
|
||||||
|
#include <QBrush>
|
||||||
|
#include <math.h>
|
||||||
|
#include <QMessageBox>
|
||||||
|
|
||||||
|
#include "mixersettings.h"
|
||||||
|
#include "systemsettings.h"
|
||||||
|
#include "actuatorcommand.h"
|
||||||
|
|
||||||
|
//#define Pi 3.14159265358979323846
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Helper function to setup the UI
|
||||||
|
*/
|
||||||
|
void ConfigVehicleTypeWidget::setupMultiRotorUI(QString frameType)
|
||||||
|
{
|
||||||
|
if (frameType == "Tri" || frameType == "Tricopter Y") {
|
||||||
|
m_aircraft->aircraftType->setCurrentIndex(m_aircraft->aircraftType->findText("Multirotor"));
|
||||||
|
m_aircraft->multirotorFrameType->setCurrentIndex(m_aircraft->multirotorFrameType->findText("Tricopter Y"));
|
||||||
|
quad->setElementId("tri");
|
||||||
|
|
||||||
|
//Enable all necessary motor channel boxes...
|
||||||
|
for (int i=1; i <=3; i++) {
|
||||||
|
QComboBox *combobox = qFindChild<QComboBox*>(this, "multiMotorChannelBox" + QString::number(i));
|
||||||
|
combobox->setEnabled(true);
|
||||||
|
}
|
||||||
|
//and grey out all unused motor channel boxes
|
||||||
|
for (int i=4; i <=8; i++) {
|
||||||
|
QComboBox *combobox = qFindChild<QComboBox*>(this, "multiMotorChannelBox" + QString::number(i));
|
||||||
|
combobox->setEnabled(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
// m_aircraft->multiMotorChannelBox4->setEnabled(false);
|
||||||
|
// m_aircraft->multiMotorChannelBox5->setEnabled(false);
|
||||||
|
// m_aircraft->multiMotorChannelBox6->setEnabled(false);
|
||||||
|
// m_aircraft->multiMotorChannelBox7->setEnabled(false);
|
||||||
|
// m_aircraft->multiMotorChannelBox8->setEnabled(false);
|
||||||
|
m_aircraft->triYawChannelBox->setEnabled(true);
|
||||||
|
} else if (frameType == "QuadX" || frameType == "Quad X") {
|
||||||
|
m_aircraft->aircraftType->setCurrentIndex(m_aircraft->aircraftType->findText("Multirotor"));
|
||||||
|
m_aircraft->multirotorFrameType->setCurrentIndex(m_aircraft->multirotorFrameType->findText("Quad X"));
|
||||||
|
quad->setElementId("quad-X");
|
||||||
|
|
||||||
|
//Enable all necessary motor channel boxes...
|
||||||
|
for (int i=1; i <=4; i++) {
|
||||||
|
QComboBox *combobox = qFindChild<QComboBox*>(this, "multiMotorChannelBox" + QString::number(i));
|
||||||
|
combobox->setEnabled(true);
|
||||||
|
}
|
||||||
|
//and grey out all unused motor channel boxes
|
||||||
|
for (int i=5; i <=8; i++) {
|
||||||
|
QComboBox *combobox = qFindChild<QComboBox*>(this, "multiMotorChannelBox" + QString::number(i));
|
||||||
|
combobox->setEnabled(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
// m_aircraft->multiMotorChannelBox4->setEnabled(true);
|
||||||
|
// m_aircraft->multiMotorChannelBox5->setEnabled(false);
|
||||||
|
// m_aircraft->multiMotorChannelBox6->setEnabled(false);
|
||||||
|
// m_aircraft->multiMotorChannelBox7->setEnabled(false);
|
||||||
|
// m_aircraft->multiMotorChannelBox8->setEnabled(false);
|
||||||
|
m_aircraft->triYawChannelBox->setEnabled(false);
|
||||||
|
m_aircraft->mrRollMixLevel->setValue(50);
|
||||||
|
m_aircraft->mrPitchMixLevel->setValue(50);
|
||||||
|
m_aircraft->mrYawMixLevel->setValue(50);
|
||||||
|
} else if (frameType == "QuadP" || frameType == "Quad +") {
|
||||||
|
m_aircraft->aircraftType->setCurrentIndex(m_aircraft->aircraftType->findText("Multirotor"));
|
||||||
|
m_aircraft->multirotorFrameType->setCurrentIndex(m_aircraft->multirotorFrameType->findText("Quad +"));
|
||||||
|
quad->setElementId("quad-plus");
|
||||||
|
|
||||||
|
//Enable all necessary motor channel boxes...
|
||||||
|
for (int i=1; i <=4; i++) {
|
||||||
|
QComboBox *combobox = qFindChild<QComboBox*>(this, "multiMotorChannelBox" + QString::number(i));
|
||||||
|
combobox->setEnabled(true);
|
||||||
|
}
|
||||||
|
//and grey out all unused motor channel boxes
|
||||||
|
for (int i=5; i <=8; i++) {
|
||||||
|
QComboBox *combobox = qFindChild<QComboBox*>(this, "multiMotorChannelBox" + QString::number(i));
|
||||||
|
combobox->setEnabled(false);
|
||||||
|
}
|
||||||
|
// m_aircraft->multiMotorChannelBox4->setEnabled(true);
|
||||||
|
// m_aircraft->multiMotorChannelBox5->setEnabled(false);
|
||||||
|
// m_aircraft->multiMotorChannelBox6->setEnabled(false);
|
||||||
|
// m_aircraft->multiMotorChannelBox7->setEnabled(false);
|
||||||
|
// m_aircraft->multiMotorChannelBox8->setEnabled(false);
|
||||||
|
m_aircraft->triYawChannelBox->setEnabled(false);
|
||||||
|
m_aircraft->mrRollMixLevel->setValue(100);
|
||||||
|
m_aircraft->mrPitchMixLevel->setValue(100);
|
||||||
|
m_aircraft->mrYawMixLevel->setValue(50);
|
||||||
|
} else if (frameType == "Hexa" || frameType == "Hexacopter") {
|
||||||
|
m_aircraft->aircraftType->setCurrentIndex(m_aircraft->aircraftType->findText("Multirotor"));
|
||||||
|
m_aircraft->multirotorFrameType->setCurrentIndex(m_aircraft->multirotorFrameType->findText("Hexacopter"));
|
||||||
|
quad->setElementId("quad-hexa");
|
||||||
|
|
||||||
|
//Enable all necessary motor channel boxes...
|
||||||
|
for (int i=1; i <=6; i++) {
|
||||||
|
QComboBox *combobox = qFindChild<QComboBox*>(this, "multiMotorChannelBox" + QString::number(i));
|
||||||
|
combobox->setEnabled(true);
|
||||||
|
}
|
||||||
|
//and grey out all unused motor channel boxes
|
||||||
|
for (int i=7; i <=8; i++) {
|
||||||
|
QComboBox *combobox = qFindChild<QComboBox*>(this, "multiMotorChannelBox" + QString::number(i));
|
||||||
|
combobox->setEnabled(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
// m_aircraft->multiMotorChannelBox4->setEnabled(true);
|
||||||
|
// m_aircraft->multiMotorChannelBox5->setEnabled(true);
|
||||||
|
// m_aircraft->multiMotorChannelBox6->setEnabled(true);
|
||||||
|
// m_aircraft->multiMotorChannelBox7->setEnabled(false);
|
||||||
|
// m_aircraft->multiMotorChannelBox8->setEnabled(false);
|
||||||
|
m_aircraft->triYawChannelBox->setEnabled(false);
|
||||||
|
m_aircraft->mrRollMixLevel->setValue(50);
|
||||||
|
m_aircraft->mrPitchMixLevel->setValue(33);
|
||||||
|
m_aircraft->mrYawMixLevel->setValue(33);
|
||||||
|
} else if (frameType == "HexaX" || frameType == "Hexacopter X" ) {
|
||||||
|
m_aircraft->aircraftType->setCurrentIndex(m_aircraft->aircraftType->findText("Multirotor"));
|
||||||
|
m_aircraft->multirotorFrameType->setCurrentIndex(m_aircraft->multirotorFrameType->findText("Hexacopter X"));
|
||||||
|
quad->setElementId("quad-hexa-H");
|
||||||
|
|
||||||
|
//Enable all necessary motor channel boxes...
|
||||||
|
for (int i=1; i <=6; i++) {
|
||||||
|
QComboBox *combobox = qFindChild<QComboBox*>(this, "multiMotorChannelBox" + QString::number(i));
|
||||||
|
combobox->setEnabled(true);
|
||||||
|
}
|
||||||
|
//and grey out all unused motor channel boxes
|
||||||
|
for (int i=7; i <=8; i++) {
|
||||||
|
QComboBox *combobox = qFindChild<QComboBox*>(this, "multiMotorChannelBox" + QString::number(i));
|
||||||
|
combobox->setEnabled(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
// m_aircraft->multiMotorChannelBox4->setEnabled(true);
|
||||||
|
// m_aircraft->multiMotorChannelBox5->setEnabled(true);
|
||||||
|
// m_aircraft->multiMotorChannelBox6->setEnabled(true);
|
||||||
|
// m_aircraft->multiMotorChannelBox7->setEnabled(false);
|
||||||
|
// m_aircraft->multiMotorChannelBox8->setEnabled(false);
|
||||||
|
m_aircraft->triYawChannelBox->setEnabled(false);
|
||||||
|
m_aircraft->mrRollMixLevel->setValue(33);
|
||||||
|
m_aircraft->mrPitchMixLevel->setValue(50);
|
||||||
|
m_aircraft->mrYawMixLevel->setValue(33);
|
||||||
|
|
||||||
|
} else if (frameType == "HexaCoax" || frameType == "Hexacopter Y6") {
|
||||||
|
m_aircraft->aircraftType->setCurrentIndex(m_aircraft->aircraftType->findText("Multirotor"));
|
||||||
|
m_aircraft->multirotorFrameType->setCurrentIndex(m_aircraft->multirotorFrameType->findText("Hexacopter Y6"));
|
||||||
|
quad->setElementId("hexa-coax");
|
||||||
|
|
||||||
|
//Enable all necessary motor channel boxes...
|
||||||
|
for (int i=1; i <=6; i++) {
|
||||||
|
QComboBox *combobox = qFindChild<QComboBox*>(this, "multiMotorChannelBox" + QString::number(i));
|
||||||
|
combobox->setEnabled(true);
|
||||||
|
}
|
||||||
|
//and grey out all unused motor channel boxes
|
||||||
|
for (int i=7; i <=8; i++) {
|
||||||
|
QComboBox *combobox = qFindChild<QComboBox*>(this, "multiMotorChannelBox" + QString::number(i));
|
||||||
|
combobox->setEnabled(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
// m_aircraft->multiMotorChannelBox4->setEnabled(true);
|
||||||
|
// m_aircraft->multiMotorChannelBox5->setEnabled(true);
|
||||||
|
// m_aircraft->multiMotorChannelBox6->setEnabled(true);
|
||||||
|
// m_aircraft->multiMotorChannelBox7->setEnabled(false);
|
||||||
|
// m_aircraft->multiMotorChannelBox8->setEnabled(false);
|
||||||
|
m_aircraft->triYawChannelBox->setEnabled(false);
|
||||||
|
m_aircraft->mrRollMixLevel->setValue(100);
|
||||||
|
m_aircraft->mrPitchMixLevel->setValue(50);
|
||||||
|
m_aircraft->mrYawMixLevel->setValue(66);
|
||||||
|
|
||||||
|
} else if (frameType == "Octo" || frameType == "Octocopter") {
|
||||||
|
m_aircraft->aircraftType->setCurrentIndex(m_aircraft->aircraftType->findText("Multirotor"));
|
||||||
|
m_aircraft->multirotorFrameType->setCurrentIndex(m_aircraft->multirotorFrameType->findText("Octocopter"));
|
||||||
|
quad->setElementId("quad-octo");
|
||||||
|
|
||||||
|
//Enable all necessary motor channel boxes
|
||||||
|
for (int i=1; i <=8; i++) {
|
||||||
|
QComboBox *combobox = qFindChild<QComboBox*>(this, "multiMotorChannelBox" + QString::number(i));
|
||||||
|
combobox->setEnabled(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// m_aircraft->multiMotorChannelBox4->setEnabled(true);
|
||||||
|
// m_aircraft->multiMotorChannelBox5->setEnabled(true);
|
||||||
|
// m_aircraft->multiMotorChannelBox6->setEnabled(true);
|
||||||
|
// m_aircraft->multiMotorChannelBox7->setEnabled(true);
|
||||||
|
// m_aircraft->multiMotorChannelBox8->setEnabled(true);
|
||||||
|
m_aircraft->triYawChannelBox->setEnabled(false);
|
||||||
|
m_aircraft->mrRollMixLevel->setValue(33);
|
||||||
|
m_aircraft->mrPitchMixLevel->setValue(33);
|
||||||
|
m_aircraft->mrYawMixLevel->setValue(25);
|
||||||
|
} else if (frameType == "OctoV" || frameType == "Octocopter V") {
|
||||||
|
m_aircraft->aircraftType->setCurrentIndex(m_aircraft->aircraftType->findText("Multirotor"));
|
||||||
|
m_aircraft->multirotorFrameType->setCurrentIndex(m_aircraft->multirotorFrameType->findText("Octocopter V"));
|
||||||
|
quad->setElementId("quad-octo-v");
|
||||||
|
|
||||||
|
//Enable all necessary motor channel boxes
|
||||||
|
for (int i=1; i <=8; i++) {
|
||||||
|
QComboBox *combobox = qFindChild<QComboBox*>(this, "multiMotorChannelBox" + QString::number(i));
|
||||||
|
combobox->setEnabled(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// m_aircraft->multiMotorChannelBox4->setEnabled(true);
|
||||||
|
// m_aircraft->multiMotorChannelBox5->setEnabled(true);
|
||||||
|
// m_aircraft->multiMotorChannelBox6->setEnabled(true);
|
||||||
|
// m_aircraft->multiMotorChannelBox7->setEnabled(true);
|
||||||
|
// m_aircraft->multiMotorChannelBox8->setEnabled(true);
|
||||||
|
m_aircraft->triYawChannelBox->setEnabled(false);
|
||||||
|
m_aircraft->mrRollMixLevel->setValue(25);
|
||||||
|
m_aircraft->mrPitchMixLevel->setValue(25);
|
||||||
|
m_aircraft->mrYawMixLevel->setValue(25);
|
||||||
|
|
||||||
|
} else if (frameType == "OctoCoaxP" || frameType == "Octo Coax +") {
|
||||||
|
m_aircraft->aircraftType->setCurrentIndex(m_aircraft->aircraftType->findText("Multirotor"));
|
||||||
|
m_aircraft->multirotorFrameType->setCurrentIndex(m_aircraft->multirotorFrameType->findText("Octo Coax +"));
|
||||||
|
quad->setElementId("octo-coax-P");
|
||||||
|
|
||||||
|
//Enable all necessary motor channel boxes
|
||||||
|
for (int i=1; i <=8; i++) {
|
||||||
|
QComboBox *combobox = qFindChild<QComboBox*>(this, "multiMotorChannelBox" + QString::number(i));
|
||||||
|
combobox->setEnabled(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// m_aircraft->multiMotorChannelBox4->setEnabled(true);
|
||||||
|
// m_aircraft->multiMotorChannelBox5->setEnabled(true);
|
||||||
|
// m_aircraft->multiMotorChannelBox6->setEnabled(true);
|
||||||
|
// m_aircraft->multiMotorChannelBox7->setEnabled(true);
|
||||||
|
// m_aircraft->multiMotorChannelBox8->setEnabled(true);
|
||||||
|
m_aircraft->triYawChannelBox->setEnabled(false);
|
||||||
|
m_aircraft->mrRollMixLevel->setValue(100);
|
||||||
|
m_aircraft->mrPitchMixLevel->setValue(100);
|
||||||
|
m_aircraft->mrYawMixLevel->setValue(50);
|
||||||
|
|
||||||
|
} else if (frameType == "OctoCoaxX" || frameType == "Octo Coax X") {
|
||||||
|
m_aircraft->aircraftType->setCurrentIndex(m_aircraft->aircraftType->findText("Multirotor"));
|
||||||
|
m_aircraft->multirotorFrameType->setCurrentIndex(m_aircraft->multirotorFrameType->findText("Octo Coax X"));
|
||||||
|
quad->setElementId("octo-coax-X");
|
||||||
|
|
||||||
|
//Enable all necessary motor channel boxes
|
||||||
|
for (int i=1; i <=8; i++) {
|
||||||
|
QComboBox *combobox = qFindChild<QComboBox*>(this, "multiMotorChannelBox" + QString::number(i));
|
||||||
|
combobox->setEnabled(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// m_aircraft->multiMotorChannelBox4->setEnabled(true);
|
||||||
|
// m_aircraft->multiMotorChannelBox5->setEnabled(true);
|
||||||
|
// m_aircraft->multiMotorChannelBox6->setEnabled(true);
|
||||||
|
// m_aircraft->multiMotorChannelBox7->setEnabled(true);
|
||||||
|
// m_aircraft->multiMotorChannelBox8->setEnabled(true);
|
||||||
|
m_aircraft->triYawChannelBox->setEnabled(false);
|
||||||
|
m_aircraft->mrRollMixLevel->setValue(50);
|
||||||
|
m_aircraft->mrPitchMixLevel->setValue(50);
|
||||||
|
m_aircraft->mrYawMixLevel->setValue(50);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Helper function to update the UI widget objects
|
||||||
|
*/
|
||||||
|
QString ConfigVehicleTypeWidget::updateMultiRotorObjectsFromWidgets()
|
||||||
|
{
|
||||||
|
QString airframeType;
|
||||||
|
QList<QString> motorList;
|
||||||
|
|
||||||
|
// We can already setup the feedforward here, as it is common to all platforms
|
||||||
|
UAVDataObject* obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
|
||||||
|
UAVObjectField* field = obj->getField(QString("FeedForward"));
|
||||||
|
field->setDouble((double)m_aircraft->feedForwardSlider->value()/100);
|
||||||
|
field = obj->getField(QString("AccelTime"));
|
||||||
|
field->setDouble(m_aircraft->accelTime->value());
|
||||||
|
field = obj->getField(QString("DecelTime"));
|
||||||
|
field->setDouble(m_aircraft->decelTime->value());
|
||||||
|
field = obj->getField(QString("MaxAccel"));
|
||||||
|
field->setDouble(m_aircraft->maxAccelSlider->value());
|
||||||
|
|
||||||
|
// Curve is also common to all quads:
|
||||||
|
field = obj->getField("ThrottleCurve1");
|
||||||
|
QList<double> curve = m_aircraft->multiThrottleCurve->getCurve();
|
||||||
|
for (int i=0;i<curve.length();i++) {
|
||||||
|
field->setValue(curve.at(i),i);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_aircraft->multirotorFrameType->currentText() == "Quad +") {
|
||||||
|
airframeType = "QuadP";
|
||||||
|
setupQuad(true);
|
||||||
|
} else if (m_aircraft->multirotorFrameType->currentText() == "Quad X") {
|
||||||
|
airframeType = "QuadX";
|
||||||
|
setupQuad(false);
|
||||||
|
} else if (m_aircraft->multirotorFrameType->currentText() == "Hexacopter") {
|
||||||
|
airframeType = "Hexa";
|
||||||
|
setupHexa(true);
|
||||||
|
} else if (m_aircraft->multirotorFrameType->currentText() == "Hexacopter X") {
|
||||||
|
airframeType = "HexaX";
|
||||||
|
setupHexa(false);
|
||||||
|
} else if (m_aircraft->multirotorFrameType->currentText() == "Hexacopter Y6") {
|
||||||
|
airframeType = "HexaCoax";
|
||||||
|
|
||||||
|
//Show any config errors in GUI
|
||||||
|
throwMultiRotorChannelConfigError(6);
|
||||||
|
|
||||||
|
if (m_aircraft->multiMotorChannelBox1->currentText() == "None" ||
|
||||||
|
m_aircraft->multiMotorChannelBox2->currentText() == "None" ||
|
||||||
|
m_aircraft->multiMotorChannelBox3->currentText() == "None" ||
|
||||||
|
m_aircraft->multiMotorChannelBox4->currentText() == "None" ||
|
||||||
|
m_aircraft->multiMotorChannelBox5->currentText() == "None" ||
|
||||||
|
m_aircraft->multiMotorChannelBox6->currentText() == "None" ) {
|
||||||
|
|
||||||
|
return airframeType;
|
||||||
|
}
|
||||||
|
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}
|
||||||
|
};
|
||||||
|
setupMultiRotorMixer(mixer);
|
||||||
|
m_aircraft->mrStatusLabel->setText("SUCCESS: Mixer Saved OK");
|
||||||
|
|
||||||
|
} else if (m_aircraft->multirotorFrameType->currentText() == "Octocopter") {
|
||||||
|
airframeType = "Octo";
|
||||||
|
|
||||||
|
//Show any config errors in GUI
|
||||||
|
throwMultiRotorChannelConfigError(8);
|
||||||
|
|
||||||
|
if (m_aircraft->multiMotorChannelBox1->currentText() == "None" ||
|
||||||
|
m_aircraft->multiMotorChannelBox2->currentText() == "None" ||
|
||||||
|
m_aircraft->multiMotorChannelBox3->currentText() == "None" ||
|
||||||
|
m_aircraft->multiMotorChannelBox4->currentText() == "None" ||
|
||||||
|
m_aircraft->multiMotorChannelBox5->currentText() == "None" ||
|
||||||
|
m_aircraft->multiMotorChannelBox6->currentText() == "None" ||
|
||||||
|
m_aircraft->multiMotorChannelBox7->currentText() == "None" ||
|
||||||
|
m_aircraft->multiMotorChannelBox8->currentText() == "None") {
|
||||||
|
|
||||||
|
return airframeType;
|
||||||
|
}
|
||||||
|
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}
|
||||||
|
};
|
||||||
|
setupMultiRotorMixer(mixer);
|
||||||
|
m_aircraft->mrStatusLabel->setText("SUCCESS: Mixer Saved OK");
|
||||||
|
|
||||||
|
} else if (m_aircraft->multirotorFrameType->currentText() == "Octocopter V") {
|
||||||
|
airframeType = "OctoV";
|
||||||
|
|
||||||
|
//Show any config errors in GUI
|
||||||
|
throwMultiRotorChannelConfigError(8);
|
||||||
|
|
||||||
|
if (m_aircraft->multiMotorChannelBox1->currentText() == "None" ||
|
||||||
|
m_aircraft->multiMotorChannelBox2->currentText() == "None" ||
|
||||||
|
m_aircraft->multiMotorChannelBox3->currentText() == "None" ||
|
||||||
|
m_aircraft->multiMotorChannelBox4->currentText() == "None" ||
|
||||||
|
m_aircraft->multiMotorChannelBox5->currentText() == "None" ||
|
||||||
|
m_aircraft->multiMotorChannelBox6->currentText() == "None" ||
|
||||||
|
m_aircraft->multiMotorChannelBox7->currentText() == "None" ||
|
||||||
|
m_aircraft->multiMotorChannelBox8->currentText() == "None") {
|
||||||
|
|
||||||
|
return airframeType;
|
||||||
|
}
|
||||||
|
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}
|
||||||
|
};
|
||||||
|
setupMultiRotorMixer(mixer);
|
||||||
|
m_aircraft->mrStatusLabel->setText("SUCCESS: Mixer Saved OK");
|
||||||
|
|
||||||
|
} else if (m_aircraft->multirotorFrameType->currentText() == "Octo Coax +") {
|
||||||
|
airframeType = "OctoCoaxP";
|
||||||
|
|
||||||
|
//Show any config errors in GUI
|
||||||
|
throwMultiRotorChannelConfigError(8);
|
||||||
|
|
||||||
|
if (m_aircraft->multiMotorChannelBox1->currentText() == "None" ||
|
||||||
|
m_aircraft->multiMotorChannelBox2->currentText() == "None" ||
|
||||||
|
m_aircraft->multiMotorChannelBox3->currentText() == "None" ||
|
||||||
|
m_aircraft->multiMotorChannelBox4->currentText() == "None" ||
|
||||||
|
m_aircraft->multiMotorChannelBox5->currentText() == "None" ||
|
||||||
|
m_aircraft->multiMotorChannelBox6->currentText() == "None" ||
|
||||||
|
m_aircraft->multiMotorChannelBox7->currentText() == "None" ||
|
||||||
|
m_aircraft->multiMotorChannelBox8->currentText() == "None") {
|
||||||
|
|
||||||
|
return airframeType;
|
||||||
|
}
|
||||||
|
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}
|
||||||
|
};
|
||||||
|
setupMultiRotorMixer(mixer);
|
||||||
|
m_aircraft->mrStatusLabel->setText("SUCCESS: Mixer Saved OK");
|
||||||
|
|
||||||
|
} else if (m_aircraft->multirotorFrameType->currentText() == "Octo Coax X") {
|
||||||
|
airframeType = "OctoCoaxX";
|
||||||
|
|
||||||
|
//Show any config errors in GUI
|
||||||
|
throwMultiRotorChannelConfigError(8);
|
||||||
|
|
||||||
|
if (m_aircraft->multiMotorChannelBox1->currentText() == "None" ||
|
||||||
|
m_aircraft->multiMotorChannelBox2->currentText() == "None" ||
|
||||||
|
m_aircraft->multiMotorChannelBox3->currentText() == "None" ||
|
||||||
|
m_aircraft->multiMotorChannelBox4->currentText() == "None" ||
|
||||||
|
m_aircraft->multiMotorChannelBox5->currentText() == "None" ||
|
||||||
|
m_aircraft->multiMotorChannelBox6->currentText() == "None" ||
|
||||||
|
m_aircraft->multiMotorChannelBox7->currentText() == "None" ||
|
||||||
|
m_aircraft->multiMotorChannelBox8->currentText() == "None") {
|
||||||
|
|
||||||
|
return airframeType;
|
||||||
|
}
|
||||||
|
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}
|
||||||
|
};
|
||||||
|
setupMultiRotorMixer(mixer);
|
||||||
|
m_aircraft->mrStatusLabel->setText("SUCCESS: Mixer Saved OK");
|
||||||
|
|
||||||
|
} else if (m_aircraft->multirotorFrameType->currentText() == "Tricopter Y") {
|
||||||
|
airframeType = "Tri";
|
||||||
|
|
||||||
|
//Show any config errors in GUI
|
||||||
|
throwMultiRotorChannelConfigError(3);
|
||||||
|
if (m_aircraft->multiMotorChannelBox1->currentText() == "None" ||
|
||||||
|
m_aircraft->multiMotorChannelBox2->currentText() == "None" ||
|
||||||
|
m_aircraft->multiMotorChannelBox3->currentText() == "None" ) {
|
||||||
|
|
||||||
|
return airframeType;
|
||||||
|
}
|
||||||
|
if (m_aircraft->triYawChannelBox->currentText() == "None") {
|
||||||
|
m_aircraft->mrStatusLabel->setText("<font color='red'>Error: Assign a Yaw channel</font>");
|
||||||
|
return airframeType;
|
||||||
|
}
|
||||||
|
motorList << "VTOLMotorNW" << "VTOLMotorNE" << "VTOLMotorS";
|
||||||
|
setupMotors(motorList);
|
||||||
|
obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("ActuatorSettings")));
|
||||||
|
Q_ASSERT(obj);
|
||||||
|
field = obj->getField("FixedWingYaw1");
|
||||||
|
field->setValue(m_aircraft->triYawChannelBox->currentText());
|
||||||
|
|
||||||
|
// Motor 1 to 6, Y6 Layout:
|
||||||
|
// pitch roll yaw
|
||||||
|
double mixer [8][3] = {
|
||||||
|
{ 0.5, 1, 0},
|
||||||
|
{ 0.5, -1, 0},
|
||||||
|
{ -1, 0, 0},
|
||||||
|
{ 0, 0, 0},
|
||||||
|
{ 0, 0, 0},
|
||||||
|
{ 0, 0, 0},
|
||||||
|
{ 0, 0, 0},
|
||||||
|
{ 0, 0, 0}
|
||||||
|
};
|
||||||
|
setupMultiRotorMixer(mixer);
|
||||||
|
|
||||||
|
int tmpVal = m_aircraft->triYawChannelBox->currentIndex()-1;
|
||||||
|
obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
|
||||||
|
field = obj->getField(mixerTypes.at(tmpVal));
|
||||||
|
field->setValue("Servo");
|
||||||
|
field = obj->getField(mixerVectors.at(tmpVal));
|
||||||
|
resetField(field);
|
||||||
|
int ti = field->getElementNames().indexOf("Yaw");
|
||||||
|
field->setValue(127,ti);
|
||||||
|
|
||||||
|
m_aircraft->mrStatusLabel->setText("SUCCESS: Mixer Saved OK");
|
||||||
|
|
||||||
|
}
|
||||||
|
// Now reflect those settings in the "Custom" panel as well
|
||||||
|
updateCustomAirframeUI();
|
||||||
|
|
||||||
|
return airframeType;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Helper function to refresh the UI widget values
|
||||||
|
*/
|
||||||
|
void ConfigVehicleTypeWidget::refreshMultiRotorWidgetsValues(QString frameType)
|
||||||
|
{
|
||||||
|
//////////////////////////////////////////////////////////////////
|
||||||
|
// Retrieve settings
|
||||||
|
//////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
UAVDataObject* obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("ActuatorSettings")));
|
||||||
|
Q_ASSERT(obj);
|
||||||
|
UAVObjectField *field;
|
||||||
|
|
||||||
|
if (frameType == "QuadP") {
|
||||||
|
// Motors 1/2/3/4 are: N / E / S / W
|
||||||
|
field = obj->getField(QString("VTOLMotorN"));
|
||||||
|
Q_ASSERT(field);
|
||||||
|
m_aircraft->multiMotorChannelBox1->setCurrentIndex(m_aircraft->multiMotorChannelBox1->findText(field->getValue().toString()));
|
||||||
|
field = obj->getField(QString("VTOLMotorE"));
|
||||||
|
Q_ASSERT(field);
|
||||||
|
m_aircraft->multiMotorChannelBox2->setCurrentIndex(m_aircraft->multiMotorChannelBox2->findText(field->getValue().toString()));
|
||||||
|
field = obj->getField(QString("VTOLMotorS"));
|
||||||
|
Q_ASSERT(field);
|
||||||
|
m_aircraft->multiMotorChannelBox3->setCurrentIndex(m_aircraft->multiMotorChannelBox3->findText(field->getValue().toString()));
|
||||||
|
field = obj->getField(QString("VTOLMotorW"));
|
||||||
|
Q_ASSERT(field);
|
||||||
|
m_aircraft->multiMotorChannelBox4->setCurrentIndex(m_aircraft->multiMotorChannelBox4->findText(field->getValue().toString()));
|
||||||
|
|
||||||
|
// Now, read the 1st mixer R/P/Y levels and initialize the mix sliders.
|
||||||
|
// This assumes that all vectors are identical - if not, the user should use the
|
||||||
|
// "custom" setting.
|
||||||
|
obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
|
||||||
|
Q_ASSERT(obj);
|
||||||
|
int tmpVal= m_aircraft->multiMotorChannelBox1->currentIndex()-1;
|
||||||
|
// tmpVal will be -1 if value is set to "None"
|
||||||
|
if (tmpVal > -1) {
|
||||||
|
field = obj->getField(mixerVectors.at(tmpVal));
|
||||||
|
int i = field->getElementNames().indexOf("Pitch");
|
||||||
|
double val = field->getDouble(i)/1.27;
|
||||||
|
m_aircraft->mrPitchMixLevel->setValue(val);
|
||||||
|
i = field->getElementNames().indexOf("Yaw");
|
||||||
|
val = (1-field->getDouble(i)/1.27);
|
||||||
|
m_aircraft->mrYawMixLevel->setValue(val);
|
||||||
|
tmpVal = m_aircraft->multiMotorChannelBox2->currentIndex()-1;
|
||||||
|
field = obj->getField(mixerVectors.at(tmpVal));
|
||||||
|
i = field->getElementNames().indexOf("Roll");
|
||||||
|
val = -field->getDouble(i)/1.27;
|
||||||
|
m_aircraft->mrRollMixLevel->setValue(val);
|
||||||
|
}
|
||||||
|
} else if (frameType == "QuadX") {
|
||||||
|
// Motors 1/2/3/4 are: NW / NE / SE / SW
|
||||||
|
field = obj->getField(QString("VTOLMotorNW"));
|
||||||
|
Q_ASSERT(field);
|
||||||
|
m_aircraft->multiMotorChannelBox1->setCurrentIndex(m_aircraft->multiMotorChannelBox1->findText(field->getValue().toString()));
|
||||||
|
field = obj->getField(QString("VTOLMotorNE"));
|
||||||
|
Q_ASSERT(field);
|
||||||
|
m_aircraft->multiMotorChannelBox2->setCurrentIndex(m_aircraft->multiMotorChannelBox2->findText(field->getValue().toString()));
|
||||||
|
field = obj->getField(QString("VTOLMotorSE"));
|
||||||
|
Q_ASSERT(field);
|
||||||
|
m_aircraft->multiMotorChannelBox3->setCurrentIndex(m_aircraft->multiMotorChannelBox3->findText(field->getValue().toString()));
|
||||||
|
field = obj->getField(QString("VTOLMotorSW"));
|
||||||
|
Q_ASSERT(field);
|
||||||
|
m_aircraft->multiMotorChannelBox4->setCurrentIndex(m_aircraft->multiMotorChannelBox4->findText(field->getValue().toString()));
|
||||||
|
|
||||||
|
// Now, read the 1st mixer R/P/Y levels and initialize the mix sliders.
|
||||||
|
// This assumes that all vectors are identical - if not, the user should use the
|
||||||
|
// "custom" setting.
|
||||||
|
obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
|
||||||
|
Q_ASSERT(obj);
|
||||||
|
int tmpVal= m_aircraft->multiMotorChannelBox1->currentIndex()-1;
|
||||||
|
// tmpVal will be -1 if value is set to "None"
|
||||||
|
if (tmpVal > -1) {
|
||||||
|
field = obj->getField(mixerVectors.at(tmpVal));
|
||||||
|
int i = field->getElementNames().indexOf("Pitch");
|
||||||
|
double val = field->getDouble(i)/1.27;
|
||||||
|
m_aircraft->mrPitchMixLevel->setValue(val);
|
||||||
|
i = field->getElementNames().indexOf("Yaw");
|
||||||
|
val = 1-field->getDouble(i)/1.27;
|
||||||
|
m_aircraft->mrYawMixLevel->setValue(val);
|
||||||
|
i = field->getElementNames().indexOf("Roll");
|
||||||
|
val = field->getDouble(i)/1.27;
|
||||||
|
m_aircraft->mrRollMixLevel->setValue(val);
|
||||||
|
}
|
||||||
|
} else if (frameType == "Hexa") {
|
||||||
|
// Motors 1/2/3 4/5/6 are: N / NE / SE / S / SW / NW
|
||||||
|
field = obj->getField(QString("VTOLMotorN"));
|
||||||
|
m_aircraft->multiMotorChannelBox1->setCurrentIndex(m_aircraft->multiMotorChannelBox1->findText(field->getValue().toString()));
|
||||||
|
field = obj->getField(QString("VTOLMotorNE"));
|
||||||
|
m_aircraft->multiMotorChannelBox2->setCurrentIndex(m_aircraft->multiMotorChannelBox2->findText(field->getValue().toString()));
|
||||||
|
field = obj->getField(QString("VTOLMotorSE"));
|
||||||
|
m_aircraft->multiMotorChannelBox3->setCurrentIndex(m_aircraft->multiMotorChannelBox3->findText(field->getValue().toString()));
|
||||||
|
field = obj->getField(QString("VTOLMotorS"));
|
||||||
|
m_aircraft->multiMotorChannelBox4->setCurrentIndex(m_aircraft->multiMotorChannelBox4->findText(field->getValue().toString()));
|
||||||
|
field = obj->getField(QString("VTOLMotorSW"));
|
||||||
|
m_aircraft->multiMotorChannelBox5->setCurrentIndex(m_aircraft->multiMotorChannelBox4->findText(field->getValue().toString()));
|
||||||
|
field = obj->getField(QString("VTOLMotorNW"));
|
||||||
|
m_aircraft->multiMotorChannelBox6->setCurrentIndex(m_aircraft->multiMotorChannelBox4->findText(field->getValue().toString()));
|
||||||
|
|
||||||
|
// Now, read the 1st mixer R/P/Y levels and initialize the mix sliders.
|
||||||
|
// This assumes that all vectors are identical - if not, the user should use the
|
||||||
|
// "custom" setting.
|
||||||
|
obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
|
||||||
|
int tmpVal= m_aircraft->multiMotorChannelBox1->currentIndex()-1;
|
||||||
|
// tmpVal will be -1 if value is set to "None"
|
||||||
|
if (tmpVal > -1) {
|
||||||
|
field = obj->getField(mixerVectors.at(tmpVal));
|
||||||
|
int i = field->getElementNames().indexOf("Pitch");
|
||||||
|
double val = floor(field->getDouble(i)/1.27);
|
||||||
|
m_aircraft->mrPitchMixLevel->setValue(val);
|
||||||
|
i = field->getElementNames().indexOf("Yaw");
|
||||||
|
val = floor(-field->getDouble(i)/1.27);
|
||||||
|
m_aircraft->mrYawMixLevel->setValue(val);
|
||||||
|
tmpVal = m_aircraft->multiMotorChannelBox2->currentIndex()-1;
|
||||||
|
if(tmpVal>-1)
|
||||||
|
{
|
||||||
|
field = obj->getField(mixerVectors.at(tmpVal));
|
||||||
|
i = field->getElementNames().indexOf("Roll");
|
||||||
|
val = floor(1-field->getDouble(i)/1.27);
|
||||||
|
m_aircraft->mrRollMixLevel->setValue(val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (frameType == "HexaX") {
|
||||||
|
// Motors 1/2/3 4/5/6 are: NE / E / SE / SW / W / NW
|
||||||
|
field = obj->getField(QString("VTOLMotorNE"));
|
||||||
|
m_aircraft->multiMotorChannelBox1->setCurrentIndex(m_aircraft->multiMotorChannelBox1->findText(field->getValue().toString()));
|
||||||
|
field = obj->getField(QString("VTOLMotorE"));
|
||||||
|
m_aircraft->multiMotorChannelBox2->setCurrentIndex(m_aircraft->multiMotorChannelBox2->findText(field->getValue().toString()));
|
||||||
|
field = obj->getField(QString("VTOLMotorSE"));
|
||||||
|
m_aircraft->multiMotorChannelBox3->setCurrentIndex(m_aircraft->multiMotorChannelBox3->findText(field->getValue().toString()));
|
||||||
|
field = obj->getField(QString("VTOLMotorSW"));
|
||||||
|
m_aircraft->multiMotorChannelBox4->setCurrentIndex(m_aircraft->multiMotorChannelBox4->findText(field->getValue().toString()));
|
||||||
|
field = obj->getField(QString("VTOLMotorW"));
|
||||||
|
m_aircraft->multiMotorChannelBox5->setCurrentIndex(m_aircraft->multiMotorChannelBox4->findText(field->getValue().toString()));
|
||||||
|
field = obj->getField(QString("VTOLMotorNW"));
|
||||||
|
m_aircraft->multiMotorChannelBox6->setCurrentIndex(m_aircraft->multiMotorChannelBox4->findText(field->getValue().toString()));
|
||||||
|
|
||||||
|
// Now, read the 1st mixer R/P/Y levels and initialize the mix sliders.
|
||||||
|
// This assumes that all vectors are identical - if not, the user should use the
|
||||||
|
// "custom" setting.
|
||||||
|
obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
|
||||||
|
int tmpVal= m_aircraft->multiMotorChannelBox1->currentIndex()-1;
|
||||||
|
// tmpVal will be -1 if value is set to "None"
|
||||||
|
if (tmpVal > -1) {
|
||||||
|
field = obj->getField(mixerVectors.at(tmpVal));
|
||||||
|
int i = field->getElementNames().indexOf("Pitch");
|
||||||
|
double val = floor(field->getDouble(i)/1.27);
|
||||||
|
m_aircraft->mrPitchMixLevel->setValue(val);
|
||||||
|
i = field->getElementNames().indexOf("Yaw");
|
||||||
|
val = floor(-field->getDouble(i)/1.27);
|
||||||
|
m_aircraft->mrYawMixLevel->setValue(val);
|
||||||
|
tmpVal = m_aircraft->multiMotorChannelBox2->currentIndex()-1;
|
||||||
|
field = obj->getField(mixerVectors.at(tmpVal));
|
||||||
|
i = field->getElementNames().indexOf("Roll");
|
||||||
|
val = floor(1-field->getDouble(i)/1.27);
|
||||||
|
m_aircraft->mrRollMixLevel->setValue(val);
|
||||||
|
}
|
||||||
|
} else if (frameType == "HexaCoax") {
|
||||||
|
// Motors 1/2/3 4/5/6 are: NW/W NE/E S/SE
|
||||||
|
field = obj->getField(QString("VTOLMotorNW"));
|
||||||
|
m_aircraft->multiMotorChannelBox1->setCurrentIndex(m_aircraft->multiMotorChannelBox1->findText(field->getValue().toString()));
|
||||||
|
field = obj->getField(QString("VTOLMotorW"));
|
||||||
|
m_aircraft->multiMotorChannelBox2->setCurrentIndex(m_aircraft->multiMotorChannelBox2->findText(field->getValue().toString()));
|
||||||
|
field = obj->getField(QString("VTOLMotorNE"));
|
||||||
|
m_aircraft->multiMotorChannelBox3->setCurrentIndex(m_aircraft->multiMotorChannelBox3->findText(field->getValue().toString()));
|
||||||
|
field = obj->getField(QString("VTOLMotorE"));
|
||||||
|
m_aircraft->multiMotorChannelBox4->setCurrentIndex(m_aircraft->multiMotorChannelBox4->findText(field->getValue().toString()));
|
||||||
|
field = obj->getField(QString("VTOLMotorS"));
|
||||||
|
m_aircraft->multiMotorChannelBox5->setCurrentIndex(m_aircraft->multiMotorChannelBox4->findText(field->getValue().toString()));
|
||||||
|
field = obj->getField(QString("VTOLMotorSE"));
|
||||||
|
m_aircraft->multiMotorChannelBox6->setCurrentIndex(m_aircraft->multiMotorChannelBox4->findText(field->getValue().toString()));
|
||||||
|
|
||||||
|
// Now, read the 1st mixer R/P/Y levels and initialize the mix sliders.
|
||||||
|
// This assumes that all vectors are identical - if not, the user should use the
|
||||||
|
// "custom" setting.
|
||||||
|
obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
|
||||||
|
int tmpVal= m_aircraft->multiMotorChannelBox1->currentIndex()-1;
|
||||||
|
// tmpVal will be -1 if value is set to "None"
|
||||||
|
if (tmpVal > -1) {
|
||||||
|
field = obj->getField(mixerVectors.at(tmpVal));
|
||||||
|
int i = field->getElementNames().indexOf("Pitch");
|
||||||
|
double val = floor(2*field->getDouble(i)/1.27);
|
||||||
|
m_aircraft->mrPitchMixLevel->setValue(val);
|
||||||
|
i = field->getElementNames().indexOf("Yaw");
|
||||||
|
val = floor(-field->getDouble(i)/1.27);
|
||||||
|
m_aircraft->mrYawMixLevel->setValue(val);
|
||||||
|
i = field->getElementNames().indexOf("Roll");
|
||||||
|
val = floor(field->getDouble(i)/1.27);
|
||||||
|
m_aircraft->mrRollMixLevel->setValue(val);
|
||||||
|
}
|
||||||
|
} else if (frameType == "Octo" || frameType == "OctoV" ||
|
||||||
|
frameType == "OctoCoaxP") {
|
||||||
|
// Motors 1 to 8 are N / NE / E / etc
|
||||||
|
field = obj->getField(QString("VTOLMotorN"));
|
||||||
|
Q_ASSERT(field);
|
||||||
|
m_aircraft->multiMotorChannelBox1->setCurrentIndex(m_aircraft->multiMotorChannelBox1->findText(field->getValue().toString()));
|
||||||
|
field = obj->getField(QString("VTOLMotorNE"));
|
||||||
|
Q_ASSERT(field);
|
||||||
|
m_aircraft->multiMotorChannelBox2->setCurrentIndex(m_aircraft->multiMotorChannelBox2->findText(field->getValue().toString()));
|
||||||
|
field = obj->getField(QString("VTOLMotorE"));
|
||||||
|
Q_ASSERT(field);
|
||||||
|
m_aircraft->multiMotorChannelBox3->setCurrentIndex(m_aircraft->multiMotorChannelBox3->findText(field->getValue().toString()));
|
||||||
|
field = obj->getField(QString("VTOLMotorSE"));
|
||||||
|
Q_ASSERT(field);
|
||||||
|
m_aircraft->multiMotorChannelBox4->setCurrentIndex(m_aircraft->multiMotorChannelBox4->findText(field->getValue().toString()));
|
||||||
|
field = obj->getField(QString("VTOLMotorS"));
|
||||||
|
Q_ASSERT(field);
|
||||||
|
m_aircraft->multiMotorChannelBox5->setCurrentIndex(m_aircraft->multiMotorChannelBox4->findText(field->getValue().toString()));
|
||||||
|
field = obj->getField(QString("VTOLMotorSW"));
|
||||||
|
Q_ASSERT(field);
|
||||||
|
m_aircraft->multiMotorChannelBox6->setCurrentIndex(m_aircraft->multiMotorChannelBox4->findText(field->getValue().toString()));
|
||||||
|
field = obj->getField(QString("VTOLMotorW"));
|
||||||
|
Q_ASSERT(field);
|
||||||
|
m_aircraft->multiMotorChannelBox7->setCurrentIndex(m_aircraft->multiMotorChannelBox4->findText(field->getValue().toString()));
|
||||||
|
field = obj->getField(QString("VTOLMotorNW"));
|
||||||
|
Q_ASSERT(field);
|
||||||
|
m_aircraft->multiMotorChannelBox8->setCurrentIndex(m_aircraft->multiMotorChannelBox4->findText(field->getValue().toString()));
|
||||||
|
|
||||||
|
// Now, read the 1st mixer R/P/Y levels and initialize the mix sliders.
|
||||||
|
// This assumes that all vectors are identical - if not, the user should use the
|
||||||
|
// "custom" setting.
|
||||||
|
obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
|
||||||
|
int tmpVal= m_aircraft->multiMotorChannelBox1->currentIndex()-1;
|
||||||
|
// tmpVal will be -1 if value is set to "None"
|
||||||
|
if (tmpVal > -1) {
|
||||||
|
if (frameType == "Octo") {
|
||||||
|
field = obj->getField(mixerVectors.at(tmpVal));
|
||||||
|
int i = field->getElementNames().indexOf("Pitch");
|
||||||
|
double val = floor(field->getDouble(i)/1.27);
|
||||||
|
m_aircraft->mrPitchMixLevel->setValue(val);
|
||||||
|
i = field->getElementNames().indexOf("Yaw");
|
||||||
|
val = floor(-field->getDouble(i)/1.27);
|
||||||
|
m_aircraft->mrYawMixLevel->setValue(val);
|
||||||
|
tmpVal = m_aircraft->multiMotorChannelBox2->currentIndex()-1;
|
||||||
|
field = obj->getField(mixerVectors.at(tmpVal));
|
||||||
|
i = field->getElementNames().indexOf("Roll");
|
||||||
|
val = floor(-field->getDouble(i)/1.27);
|
||||||
|
m_aircraft->mrRollMixLevel->setValue(val);
|
||||||
|
} else if (frameType == "OctoV") {
|
||||||
|
field = obj->getField(mixerVectors.at(tmpVal));
|
||||||
|
int i = field->getElementNames().indexOf("Yaw");
|
||||||
|
double val = floor(-field->getDouble(i)/1.27);
|
||||||
|
m_aircraft->mrYawMixLevel->setValue(val);
|
||||||
|
i = field->getElementNames().indexOf("Roll");
|
||||||
|
val = floor(-field->getDouble(i)/1.27);
|
||||||
|
m_aircraft->mrRollMixLevel->setValue(val);
|
||||||
|
tmpVal = m_aircraft->multiMotorChannelBox2->currentIndex()-1;
|
||||||
|
field = obj->getField(mixerVectors.at(tmpVal));
|
||||||
|
i = field->getElementNames().indexOf("Pitch");
|
||||||
|
val = floor(field->getDouble(i)/1.27);
|
||||||
|
m_aircraft->mrPitchMixLevel->setValue(val);
|
||||||
|
|
||||||
|
} else if (frameType == "OctoCoaxP") {
|
||||||
|
field = obj->getField(mixerVectors.at(tmpVal));
|
||||||
|
int i = field->getElementNames().indexOf("Pitch");
|
||||||
|
double val = floor(field->getDouble(i)/1.27);
|
||||||
|
m_aircraft->mrPitchMixLevel->setValue(val);
|
||||||
|
i = field->getElementNames().indexOf("Yaw");
|
||||||
|
val = floor(-field->getDouble(i)/1.27);
|
||||||
|
m_aircraft->mrYawMixLevel->setValue(val);
|
||||||
|
tmpVal = m_aircraft->multiMotorChannelBox3->currentIndex()-1;
|
||||||
|
field = obj->getField(mixerVectors.at(tmpVal));
|
||||||
|
i = field->getElementNames().indexOf("Roll");
|
||||||
|
val = floor(-field->getDouble(i)/1.27);
|
||||||
|
m_aircraft->mrRollMixLevel->setValue(val);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (frameType == "OctoCoaxX") {
|
||||||
|
// Motors 1 to 8 are N / NE / E / etc
|
||||||
|
field = obj->getField(QString("VTOLMotorNW"));
|
||||||
|
Q_ASSERT(field);
|
||||||
|
m_aircraft->multiMotorChannelBox1->setCurrentIndex(m_aircraft->multiMotorChannelBox1->findText(field->getValue().toString()));
|
||||||
|
field = obj->getField(QString("VTOLMotorN"));
|
||||||
|
Q_ASSERT(field);
|
||||||
|
m_aircraft->multiMotorChannelBox2->setCurrentIndex(m_aircraft->multiMotorChannelBox2->findText(field->getValue().toString()));
|
||||||
|
field = obj->getField(QString("VTOLMotorNE"));
|
||||||
|
Q_ASSERT(field);
|
||||||
|
m_aircraft->multiMotorChannelBox3->setCurrentIndex(m_aircraft->multiMotorChannelBox3->findText(field->getValue().toString()));
|
||||||
|
field = obj->getField(QString("VTOLMotorE"));
|
||||||
|
Q_ASSERT(field);
|
||||||
|
m_aircraft->multiMotorChannelBox4->setCurrentIndex(m_aircraft->multiMotorChannelBox4->findText(field->getValue().toString()));
|
||||||
|
field = obj->getField(QString("VTOLMotorSE"));
|
||||||
|
Q_ASSERT(field);
|
||||||
|
m_aircraft->multiMotorChannelBox5->setCurrentIndex(m_aircraft->multiMotorChannelBox4->findText(field->getValue().toString()));
|
||||||
|
field = obj->getField(QString("VTOLMotorS"));
|
||||||
|
Q_ASSERT(field);
|
||||||
|
m_aircraft->multiMotorChannelBox6->setCurrentIndex(m_aircraft->multiMotorChannelBox4->findText(field->getValue().toString()));
|
||||||
|
field = obj->getField(QString("VTOLMotorSW"));
|
||||||
|
Q_ASSERT(field);
|
||||||
|
m_aircraft->multiMotorChannelBox7->setCurrentIndex(m_aircraft->multiMotorChannelBox4->findText(field->getValue().toString()));
|
||||||
|
field = obj->getField(QString("VTOLMotorW"));
|
||||||
|
Q_ASSERT(field);
|
||||||
|
m_aircraft->multiMotorChannelBox8->setCurrentIndex(m_aircraft->multiMotorChannelBox4->findText(field->getValue().toString()));
|
||||||
|
|
||||||
|
// Now, read the 1st mixer R/P/Y levels and initialize the mix sliders.
|
||||||
|
// This assumes that all vectors are identical - if not, the user should use the
|
||||||
|
// "custom" setting.
|
||||||
|
obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
|
||||||
|
int tmpVal= m_aircraft->multiMotorChannelBox1->currentIndex()-1;
|
||||||
|
// tmpVal will be -1 if value is set to "None"
|
||||||
|
if (tmpVal > -1) {
|
||||||
|
field = obj->getField(mixerVectors.at(tmpVal));
|
||||||
|
int i = field->getElementNames().indexOf("Pitch");
|
||||||
|
double val = floor(field->getDouble(i)/1.27);
|
||||||
|
m_aircraft->mrPitchMixLevel->setValue(val);
|
||||||
|
i = field->getElementNames().indexOf("Yaw");
|
||||||
|
val = floor(-field->getDouble(i)/1.27);
|
||||||
|
m_aircraft->mrYawMixLevel->setValue(val);
|
||||||
|
i = field->getElementNames().indexOf("Roll");
|
||||||
|
val = floor(field->getDouble(i)/1.27);
|
||||||
|
m_aircraft->mrRollMixLevel->setValue(val);
|
||||||
|
}
|
||||||
|
} else if (frameType == "Tri") {
|
||||||
|
// Motors 1 to 8 are N / NE / E / etc
|
||||||
|
field = obj->getField(QString("VTOLMotorNW"));
|
||||||
|
Q_ASSERT(field);
|
||||||
|
m_aircraft->multiMotorChannelBox1->setCurrentIndex(m_aircraft->multiMotorChannelBox1->findText(field->getValue().toString()));
|
||||||
|
field = obj->getField(QString("VTOLMotorNE"));
|
||||||
|
Q_ASSERT(field);
|
||||||
|
m_aircraft->multiMotorChannelBox2->setCurrentIndex(m_aircraft->multiMotorChannelBox2->findText(field->getValue().toString()));
|
||||||
|
field = obj->getField(QString("VTOLMotorS"));
|
||||||
|
Q_ASSERT(field);
|
||||||
|
m_aircraft->multiMotorChannelBox3->setCurrentIndex(m_aircraft->multiMotorChannelBox3->findText(field->getValue().toString()));
|
||||||
|
field = obj->getField(QString("FixedWingYaw1"));
|
||||||
|
Q_ASSERT(field);
|
||||||
|
m_aircraft->triYawChannelBox->setCurrentIndex(m_aircraft->multiMotorChannelBox3->findText(field->getValue().toString()));
|
||||||
|
|
||||||
|
obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
|
||||||
|
int tmpVal= m_aircraft->multiMotorChannelBox1->currentIndex()-1;
|
||||||
|
// tmpVal will be -1 if value is set to "None"
|
||||||
|
if (tmpVal > -1) {
|
||||||
|
field = obj->getField(mixerVectors.at(tmpVal));
|
||||||
|
int i = field->getElementNames().indexOf("Pitch");
|
||||||
|
double val = floor(2*field->getDouble(i)/1.27);
|
||||||
|
m_aircraft->mrPitchMixLevel->setValue(val);
|
||||||
|
i = field->getElementNames().indexOf("Roll");
|
||||||
|
val = floor(field->getDouble(i)/1.27);
|
||||||
|
m_aircraft->mrRollMixLevel->setValue(val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Helper function: setupQuadMotor
|
||||||
|
*/
|
||||||
|
void ConfigVehicleTypeWidget::setupQuadMotor(int channel, double pitch, double roll, double yaw)
|
||||||
|
{
|
||||||
|
qDebug()<<QString("Setup quad motor channel=%0 pitch=%1 roll=%2 yaw=%3").arg(channel).arg(pitch).arg(roll).arg(yaw);
|
||||||
|
UAVDataObject* obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
|
||||||
|
Q_ASSERT(obj);
|
||||||
|
UAVObjectField *field = obj->getField(mixerTypes.at(channel));
|
||||||
|
field->setValue("Motor");
|
||||||
|
field = obj->getField(mixerVectors.at(channel));
|
||||||
|
// First of all reset the vector
|
||||||
|
resetField(field);
|
||||||
|
int ti = field->getElementNames().indexOf("ThrottleCurve1");
|
||||||
|
field->setValue(127, ti);
|
||||||
|
ti = field->getElementNames().indexOf("Roll");
|
||||||
|
field->setValue(roll*127,ti);
|
||||||
|
qDebug()<<"Set roll="<<roll*127;
|
||||||
|
ti = field->getElementNames().indexOf("Pitch");
|
||||||
|
field->setValue(pitch*127,ti);
|
||||||
|
qDebug()<<"Set pitch="<<pitch*127;
|
||||||
|
ti = field->getElementNames().indexOf("Yaw");
|
||||||
|
field->setValue(yaw*127,ti);
|
||||||
|
qDebug()<<"Set yaw="<<yaw*127;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Helper function: setup motors. Takes a list of channel names in input.
|
||||||
|
*/
|
||||||
|
void ConfigVehicleTypeWidget::setupMotors(QList<QString> motorList)
|
||||||
|
{
|
||||||
|
resetActuators();
|
||||||
|
UAVDataObject* obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("ActuatorSettings")));
|
||||||
|
Q_ASSERT(obj);
|
||||||
|
UAVObjectField *field;
|
||||||
|
QList<QComboBox*> mmList;
|
||||||
|
mmList << m_aircraft->multiMotorChannelBox1 << m_aircraft->multiMotorChannelBox2 << m_aircraft->multiMotorChannelBox3
|
||||||
|
<< m_aircraft->multiMotorChannelBox4 << m_aircraft->multiMotorChannelBox5 << m_aircraft->multiMotorChannelBox6
|
||||||
|
<< m_aircraft->multiMotorChannelBox7 << m_aircraft->multiMotorChannelBox8;
|
||||||
|
foreach (QString motor, motorList) {
|
||||||
|
field = obj->getField(motor);
|
||||||
|
field->setValue(mmList.takeFirst()->currentText());
|
||||||
|
}
|
||||||
|
//obj->updated(); // Save...
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Set up a Quad-X or Quad-P mixer
|
||||||
|
*/
|
||||||
|
bool ConfigVehicleTypeWidget::setupQuad(bool pLayout)
|
||||||
|
{
|
||||||
|
// Check coherence:
|
||||||
|
|
||||||
|
//Show any config errors in GUI
|
||||||
|
throwMultiRotorChannelConfigError(4);
|
||||||
|
|
||||||
|
// - Four engines have to be defined
|
||||||
|
if (m_aircraft->multiMotorChannelBox1->currentText() == "None" ||
|
||||||
|
m_aircraft->multiMotorChannelBox2->currentText() == "None" ||
|
||||||
|
m_aircraft->multiMotorChannelBox3->currentText() == "None" ||
|
||||||
|
m_aircraft->multiMotorChannelBox4->currentText() == "None") {
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
QList<QString> motorList;
|
||||||
|
if (pLayout) {
|
||||||
|
motorList << "VTOLMotorN" << "VTOLMotorE" << "VTOLMotorS"
|
||||||
|
<< "VTOLMotorW";
|
||||||
|
} else {
|
||||||
|
motorList << "VTOLMotorNW" << "VTOLMotorNE" << "VTOLMotorSE"
|
||||||
|
<< "VTOLMotorSW";
|
||||||
|
}
|
||||||
|
setupMotors(motorList);
|
||||||
|
|
||||||
|
// Now, setup the mixer:
|
||||||
|
// Motor 1 to 4, X Layout:
|
||||||
|
// pitch roll yaw
|
||||||
|
// {0.5 ,0.5 ,-0.5 //Front left motor (CW)
|
||||||
|
// {0.5 ,-0.5 ,0.5 //Front right motor(CCW)
|
||||||
|
// {-0.5 ,-0.5 ,-0.5 //rear right motor (CW)
|
||||||
|
// {-0.5 ,0.5 ,0.5 //Rear left motor (CCW)
|
||||||
|
double xMixer [8][3] = {
|
||||||
|
{ 1, 1, -1},
|
||||||
|
{ 1, -1, 1},
|
||||||
|
{-1, -1, -1},
|
||||||
|
{-1, 1, 1},
|
||||||
|
{ 0, 0, 0},
|
||||||
|
{ 0, 0, 0},
|
||||||
|
{ 0, 0, 0},
|
||||||
|
{ 0, 0, 0}
|
||||||
|
};
|
||||||
|
//
|
||||||
|
// Motor 1 to 4, P Layout:
|
||||||
|
// pitch roll yaw
|
||||||
|
// {1 ,0 ,-0.5 //Front motor (CW)
|
||||||
|
// {0 ,-1 ,0.5 //Right motor(CCW)
|
||||||
|
// {-1 ,0 ,-0.5 //Rear motor (CW)
|
||||||
|
// {0 ,1 ,0.5 //Left motor (CCW)
|
||||||
|
double pMixer [8][3] = {
|
||||||
|
{ 1, 0, -1},
|
||||||
|
{ 0, -1, 1},
|
||||||
|
{-1, 0, -1},
|
||||||
|
{ 0, 1, 1},
|
||||||
|
{ 0, 0, 0},
|
||||||
|
{ 0, 0, 0},
|
||||||
|
{ 0, 0, 0},
|
||||||
|
{ 0, 0, 0}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (pLayout) {
|
||||||
|
setupMultiRotorMixer(pMixer);
|
||||||
|
} else {
|
||||||
|
setupMultiRotorMixer(xMixer);
|
||||||
|
}
|
||||||
|
m_aircraft->mrStatusLabel->setText("SUCCESS: Mixer Saved OK");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Set up a Hexa-X or Hexa-P mixer
|
||||||
|
*/
|
||||||
|
bool ConfigVehicleTypeWidget::setupHexa(bool pLayout)
|
||||||
|
{
|
||||||
|
// Check coherence:
|
||||||
|
//Show any config errors in GUI
|
||||||
|
throwMultiRotorChannelConfigError(6);
|
||||||
|
|
||||||
|
// - Four engines have to be defined
|
||||||
|
if (m_aircraft->multiMotorChannelBox1->currentText() == "None" ||
|
||||||
|
m_aircraft->multiMotorChannelBox2->currentText() == "None" ||
|
||||||
|
m_aircraft->multiMotorChannelBox3->currentText() == "None" ||
|
||||||
|
m_aircraft->multiMotorChannelBox4->currentText() == "None" ||
|
||||||
|
m_aircraft->multiMotorChannelBox5->currentText() == "None" ||
|
||||||
|
m_aircraft->multiMotorChannelBox6->currentText() == "None") {
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
QList<QString> motorList;
|
||||||
|
if (pLayout) {
|
||||||
|
motorList << "VTOLMotorN" << "VTOLMotorNE" << "VTOLMotorSE"
|
||||||
|
<< "VTOLMotorS" << "VTOLMotorSW" << "VTOLMotorNW";
|
||||||
|
} else {
|
||||||
|
motorList << "VTOLMotorNE" << "VTOLMotorE" << "VTOLMotorSE"
|
||||||
|
<< "VTOLMotorSW" << "VTOLMotorW" << "VTOLMotorNW";
|
||||||
|
}
|
||||||
|
setupMotors(motorList);
|
||||||
|
|
||||||
|
// and set only the relevant channels:
|
||||||
|
|
||||||
|
// Motor 1 to 6, P Layout:
|
||||||
|
// pitch roll yaw
|
||||||
|
// 1 { 0.3 , 0 ,-0.3 // N CW
|
||||||
|
// 2 { 0.3 ,-0.5 , 0.3 // NE CCW
|
||||||
|
// 3 {-0.3 ,-0.5 ,-0.3 // SE CW
|
||||||
|
// 4 {-0.3 , 0 , 0.3 // S CCW
|
||||||
|
// 5 {-0.3 , 0.5 ,-0.3 // SW CW
|
||||||
|
// 6 { 0.3 , 0.5 , 0.3 // NW CCW
|
||||||
|
|
||||||
|
double pMixer [8][3] = {
|
||||||
|
{ 1, 0, -1},
|
||||||
|
{ 1, -1, 1},
|
||||||
|
{-1, -1, -1},
|
||||||
|
{-1, 0, 1},
|
||||||
|
{-1, 1, -1},
|
||||||
|
{ 1, 1, 1},
|
||||||
|
{ 0, 0, 0},
|
||||||
|
{ 0, 0, 0}
|
||||||
|
};
|
||||||
|
|
||||||
|
//
|
||||||
|
// Motor 1 to 6, X Layout:
|
||||||
|
// 1 [ 0.5, -0.3, -0.3 ] NE
|
||||||
|
// 2 [ 0 , -0.3, 0.3 ] E
|
||||||
|
// 3 [ -0.5, -0.3, -0.3 ] SE
|
||||||
|
// 4 [ -0.5, 0.3, 0.3 ] SW
|
||||||
|
// 5 [ 0 , 0.3, -0.3 ] W
|
||||||
|
// 6 [ 0.5, 0.3, 0.3 ] NW
|
||||||
|
double xMixer [8][3] = {
|
||||||
|
{ 1, -1, -1},
|
||||||
|
{ 0, -1, 1},
|
||||||
|
{ -1, -1, -1},
|
||||||
|
{ -1, 1, 1},
|
||||||
|
{ 0, 1, -1},
|
||||||
|
{ 1, 1, 1},
|
||||||
|
{ 0, 0, 0},
|
||||||
|
{ 0, 0, 0}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (pLayout) {
|
||||||
|
setupMultiRotorMixer(pMixer);
|
||||||
|
} else {
|
||||||
|
setupMultiRotorMixer(xMixer);
|
||||||
|
}
|
||||||
|
m_aircraft->mrStatusLabel->setText("SUCCESS: Mixer Saved OK");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
This function sets up the multirotor mixer values.
|
||||||
|
*/
|
||||||
|
bool ConfigVehicleTypeWidget::setupMultiRotorMixer(double mixerFactors[8][3])
|
||||||
|
{
|
||||||
|
qDebug()<<"Mixer factors";
|
||||||
|
qDebug()<<mixerFactors[0][0]<<" "<<mixerFactors[0][1]<<" "<<mixerFactors[0][2];
|
||||||
|
qDebug()<<mixerFactors[1][0]<<" "<<mixerFactors[1][1]<<" "<<mixerFactors[1][2];
|
||||||
|
qDebug()<<mixerFactors[2][0]<<" "<<mixerFactors[2][1]<<" "<<mixerFactors[2][2];
|
||||||
|
qDebug()<<mixerFactors[3][0]<<" "<<mixerFactors[3][1]<<" "<<mixerFactors[3][2];
|
||||||
|
qDebug()<<mixerFactors[4][0]<<" "<<mixerFactors[4][1]<<" "<<mixerFactors[4][2];
|
||||||
|
qDebug()<<mixerFactors[5][0]<<" "<<mixerFactors[5][1]<<" "<<mixerFactors[5][2];
|
||||||
|
qDebug()<<mixerFactors[6][0]<<" "<<mixerFactors[6][1]<<" "<<mixerFactors[6][2];
|
||||||
|
qDebug()<<mixerFactors[7][0]<<" "<<mixerFactors[7][1]<<" "<<mixerFactors[7][2];
|
||||||
|
|
||||||
|
UAVObjectField *field;
|
||||||
|
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 *obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
|
||||||
|
// 1. Assign the servo/motor/none for each channel
|
||||||
|
// Disable all
|
||||||
|
foreach(QString mixer, mixerTypes) {
|
||||||
|
field = obj->getField(mixer);
|
||||||
|
Q_ASSERT(field);
|
||||||
|
field->setValue("Disabled");
|
||||||
|
}
|
||||||
|
// and enable only the relevant channels:
|
||||||
|
double pFactor = (double)m_aircraft->mrPitchMixLevel->value()/100;
|
||||||
|
double rFactor = (double)m_aircraft->mrRollMixLevel->value()/100;
|
||||||
|
double yFactor = (double)m_aircraft->mrYawMixLevel->value()/100;
|
||||||
|
qDebug()<<QString("pFactor=%0 rFactor=%1 yFactor=%2").arg(pFactor).arg(rFactor).arg(yFactor);
|
||||||
|
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]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// obj->updated();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
This function displays text and color formatting in order to help the user understand what channels have not yet been configured.
|
||||||
|
*/
|
||||||
|
void ConfigVehicleTypeWidget::throwMultiRotorChannelConfigError(int numMotors)
|
||||||
|
{
|
||||||
|
//Initialize configuration error flag
|
||||||
|
bool error=false;
|
||||||
|
|
||||||
|
//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*>(this, "multiMotorChannelBox" + QString::number(i+1));
|
||||||
|
if (combobox){ //if QLabel exists
|
||||||
|
QLabel *label = qFindChild<QLabel*>(this, "MotorOutputLabel" + QString::number(i+1));
|
||||||
|
if (combobox->currentText() == "None") {
|
||||||
|
|
||||||
|
// label->setText("<font color='red'>" + label->text() + "</font>");
|
||||||
|
|
||||||
|
int size = combobox->style()->pixelMetric(QStyle::PM_SmallIconSize);
|
||||||
|
QPixmap pixmap(size,size);
|
||||||
|
pixmap.fill(QColor("red"));
|
||||||
|
combobox->setItemData(0, pixmap, Qt::DecorationRole);//Set color palettes
|
||||||
|
// combobox->setStyleSheet("QComboBox { color: red}");
|
||||||
|
error=true;
|
||||||
|
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
combobox->setItemData(0, 0, Qt::DecorationRole);//Reset color palettes
|
||||||
|
// combobox->setStyleSheet("color: black;");
|
||||||
|
// QTextEdit* htmlText=new QTextEdit(label->text()); // htmlText is any QString with html tags.
|
||||||
|
// label->setText(htmlText->toPlainText());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (error){
|
||||||
|
m_aircraft->mrStatusLabel->setText(QString("<font color='red'>ERROR: Assign all %1 motor channels</font>").arg(numMotors));
|
||||||
|
}
|
||||||
|
}
|
@ -4,7 +4,9 @@ DEFINES += CONFIG_LIBRARY
|
|||||||
QT += svg
|
QT += svg
|
||||||
include(config_dependencies.pri)
|
include(config_dependencies.pri)
|
||||||
INCLUDEPATH += ../../libs/eigen
|
INCLUDEPATH += ../../libs/eigen
|
||||||
|
|
||||||
OTHER_FILES += Config.pluginspec
|
OTHER_FILES += Config.pluginspec
|
||||||
|
|
||||||
HEADERS += configplugin.h \
|
HEADERS += configplugin.h \
|
||||||
configgadgetconfiguration.h \
|
configgadgetconfiguration.h \
|
||||||
configgadgetwidget.h \
|
configgadgetwidget.h \
|
||||||
@ -14,12 +16,12 @@ HEADERS += configplugin.h \
|
|||||||
fancytabwidget.h \
|
fancytabwidget.h \
|
||||||
configinputwidget.h \
|
configinputwidget.h \
|
||||||
configoutputwidget.h \
|
configoutputwidget.h \
|
||||||
configairframewidget.h \
|
configvehicletypewidget.h \
|
||||||
config_pro_hw_widget.h \
|
config_pro_hw_widget.h \
|
||||||
config_cc_hw_widget.h \
|
config_cc_hw_widget.h \
|
||||||
configahrswidget.h \
|
configahrswidget.h \
|
||||||
configccattitudewidget.h \
|
configccattitudewidget.h \
|
||||||
configccpmwidget.h \
|
cfg_vehicletypes/configccpmwidget.h \
|
||||||
configstabilizationwidget.h \
|
configstabilizationwidget.h \
|
||||||
assertions.h \
|
assertions.h \
|
||||||
calibration.h \
|
calibration.h \
|
||||||
@ -39,12 +41,11 @@ SOURCES += configplugin.cpp \
|
|||||||
fancytabwidget.cpp \
|
fancytabwidget.cpp \
|
||||||
configinputwidget.cpp \
|
configinputwidget.cpp \
|
||||||
configoutputwidget.cpp \
|
configoutputwidget.cpp \
|
||||||
configairframewidget.cpp \
|
configvehicletypewidget.cpp \
|
||||||
config_pro_hw_widget.cpp \
|
config_pro_hw_widget.cpp \
|
||||||
config_cc_hw_widget.cpp \
|
config_cc_hw_widget.cpp \
|
||||||
configahrswidget.cpp \
|
configahrswidget.cpp \
|
||||||
configccattitudewidget.cpp \
|
configccattitudewidget.cpp \
|
||||||
configccpmwidget.cpp \
|
|
||||||
configstabilizationwidget.cpp \
|
configstabilizationwidget.cpp \
|
||||||
twostep.cpp \
|
twostep.cpp \
|
||||||
legacy-calibration.cpp \
|
legacy-calibration.cpp \
|
||||||
@ -55,6 +56,10 @@ SOURCES += configplugin.cpp \
|
|||||||
inputchannelform.cpp \
|
inputchannelform.cpp \
|
||||||
configcamerastabilizationwidget.cpp \
|
configcamerastabilizationwidget.cpp \
|
||||||
configtxpidwidget.cpp \
|
configtxpidwidget.cpp \
|
||||||
|
cfg_vehicletypes/configmultirotorwidget.cpp \
|
||||||
|
cfg_vehicletypes/configgroundvehiclewidget.cpp \
|
||||||
|
cfg_vehicletypes/configfixedwingwidget.cpp \
|
||||||
|
cfg_vehicletypes/configccpmwidget.cpp \
|
||||||
outputchannelform.cpp
|
outputchannelform.cpp
|
||||||
FORMS += airframe.ui \
|
FORMS += airframe.ui \
|
||||||
cc_hw_settings.ui \
|
cc_hw_settings.ui \
|
||||||
|
@ -1,2221 +0,0 @@
|
|||||||
/**
|
|
||||||
******************************************************************************
|
|
||||||
*
|
|
||||||
* @file configairframewidget.cpp
|
|
||||||
* @author E. Lafargue & The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
|
|
||||||
* @addtogroup GCSPlugins GCS Plugins
|
|
||||||
* @{
|
|
||||||
* @addtogroup ConfigPlugin Config Plugin
|
|
||||||
* @{
|
|
||||||
* @brief Airframe configuration panel
|
|
||||||
*****************************************************************************/
|
|
||||||
/*
|
|
||||||
* This program is free software; you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation; either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful, but
|
|
||||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
|
||||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
||||||
* for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License along
|
|
||||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
|
||||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
*/
|
|
||||||
#include "configairframewidget.h"
|
|
||||||
|
|
||||||
#include <QDebug>
|
|
||||||
#include <QStringList>
|
|
||||||
#include <QTimer>
|
|
||||||
#include <QtGui/QWidget>
|
|
||||||
#include <QtGui/QTextEdit>
|
|
||||||
#include <QtGui/QVBoxLayout>
|
|
||||||
#include <QtGui/QPushButton>
|
|
||||||
#include <math.h>
|
|
||||||
#include <QDesktopServices>
|
|
||||||
#include <QUrl>
|
|
||||||
#include "systemsettings.h"
|
|
||||||
#include "mixersettings.h"
|
|
||||||
#include "actuatorsettings.h"
|
|
||||||
#include <QEventLoop>
|
|
||||||
|
|
||||||
/**
|
|
||||||
Helper delegate for the custom mixer editor table.
|
|
||||||
Taken straight from Qt examples, thanks!
|
|
||||||
*/
|
|
||||||
SpinBoxDelegate::SpinBoxDelegate(QObject *parent)
|
|
||||||
: QItemDelegate(parent)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
QWidget *SpinBoxDelegate::createEditor(QWidget *parent,
|
|
||||||
const QStyleOptionViewItem &/* option */,
|
|
||||||
const QModelIndex &/* index */) const
|
|
||||||
{
|
|
||||||
QSpinBox *editor = new QSpinBox(parent);
|
|
||||||
editor->setMinimum(-127);
|
|
||||||
editor->setMaximum(127);
|
|
||||||
|
|
||||||
return editor;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SpinBoxDelegate::setEditorData(QWidget *editor,
|
|
||||||
const QModelIndex &index) const
|
|
||||||
{
|
|
||||||
int value = index.model()->data(index, Qt::EditRole).toInt();
|
|
||||||
|
|
||||||
QSpinBox *spinBox = static_cast<QSpinBox*>(editor);
|
|
||||||
spinBox->setValue(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SpinBoxDelegate::setModelData(QWidget *editor, QAbstractItemModel *model,
|
|
||||||
const QModelIndex &index) const
|
|
||||||
{
|
|
||||||
QSpinBox *spinBox = static_cast<QSpinBox*>(editor);
|
|
||||||
spinBox->interpretText();
|
|
||||||
int value = spinBox->value();
|
|
||||||
|
|
||||||
model->setData(index, value, Qt::EditRole);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SpinBoxDelegate::updateEditorGeometry(QWidget *editor,
|
|
||||||
const QStyleOptionViewItem &option, const QModelIndex &/* index */) const
|
|
||||||
{
|
|
||||||
editor->setGeometry(option.rect);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**********************************************************************************/
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
ConfigAirframeWidget::ConfigAirframeWidget(QWidget *parent) : ConfigTaskWidget(parent)
|
|
||||||
{
|
|
||||||
m_aircraft = new Ui_AircraftWidget();
|
|
||||||
m_aircraft->setupUi(this);
|
|
||||||
|
|
||||||
addApplySaveButtons(m_aircraft->saveAircraftToRAM,m_aircraft->saveAircraftToSD);
|
|
||||||
|
|
||||||
addUAVObject("SystemSettings");
|
|
||||||
addUAVObject("MixerSettings");
|
|
||||||
addUAVObject("ActuatorSettings");
|
|
||||||
|
|
||||||
|
|
||||||
ffTuningInProgress = false;
|
|
||||||
ffTuningPhase = false;
|
|
||||||
|
|
||||||
QStringList channels;
|
|
||||||
channels << "None";
|
|
||||||
for (int i = 0; i < ActuatorSettings::CHANNELADDR_NUMELEM; i++) {
|
|
||||||
mixerTypes << QString("Mixer%1Type").arg(i+1);
|
|
||||||
mixerVectors << QString("Mixer%1Vector").arg(i+1);
|
|
||||||
channels << QString("Channel%1").arg(i+1);
|
|
||||||
}
|
|
||||||
|
|
||||||
QStringList airframeTypes;
|
|
||||||
airframeTypes << "Fixed Wing" << "Multirotor" << "Helicopter" << "Custom";
|
|
||||||
m_aircraft->aircraftType->addItems(airframeTypes);
|
|
||||||
m_aircraft->aircraftType->setCurrentIndex(1);
|
|
||||||
|
|
||||||
QStringList fixedWingTypes;
|
|
||||||
fixedWingTypes << "Elevator aileron rudder" << "Elevon" << "Vtail";
|
|
||||||
m_aircraft->fixedWingType->addItems(fixedWingTypes);
|
|
||||||
|
|
||||||
QStringList multiRotorTypes;
|
|
||||||
multiRotorTypes << "Quad +" << "Quad X" << "Hexacopter" << "Octocopter" << "Hexacopter X" << "Octocopter V" << "Octo Coax +"
|
|
||||||
<< "Octo Coax X" << "Hexacopter Y6" << "Tricopter Y";
|
|
||||||
m_aircraft->multirotorFrameType->addItems(multiRotorTypes);
|
|
||||||
|
|
||||||
// Now load all the channel assignements for fixed wing
|
|
||||||
m_aircraft->fwElevator1Channel->addItems(channels);
|
|
||||||
m_aircraft->fwElevator2Channel->addItems(channels);
|
|
||||||
m_aircraft->fwEngineChannel->addItems(channels);
|
|
||||||
m_aircraft->fwRudder1Channel->addItems(channels);
|
|
||||||
m_aircraft->fwRudder2Channel->addItems(channels);
|
|
||||||
m_aircraft->fwAileron1Channel->addItems(channels);
|
|
||||||
m_aircraft->fwAileron2Channel->addItems(channels);
|
|
||||||
m_aircraft->multiMotor1->addItems(channels);
|
|
||||||
m_aircraft->multiMotor2->addItems(channels);
|
|
||||||
m_aircraft->multiMotor3->addItems(channels);
|
|
||||||
m_aircraft->multiMotor4->addItems(channels);
|
|
||||||
m_aircraft->multiMotor5->addItems(channels);
|
|
||||||
m_aircraft->multiMotor6->addItems(channels);
|
|
||||||
m_aircraft->multiMotor7->addItems(channels);
|
|
||||||
m_aircraft->multiMotor8->addItems(channels);
|
|
||||||
m_aircraft->triYawChannel->addItems(channels);
|
|
||||||
|
|
||||||
// Setup the Multirotor picture in the Quad settings interface
|
|
||||||
m_aircraft->quadShape->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
|
||||||
m_aircraft->quadShape->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
|
||||||
QSvgRenderer *renderer = new QSvgRenderer();
|
|
||||||
renderer->load(QString(":/configgadget/images/quad-shapes.svg"));
|
|
||||||
quad = new QGraphicsSvgItem();
|
|
||||||
quad->setSharedRenderer(renderer);
|
|
||||||
quad->setElementId("quad-plus");
|
|
||||||
QGraphicsScene *scene = new QGraphicsScene(this);
|
|
||||||
scene->addItem(quad);
|
|
||||||
scene->setSceneRect(quad->boundingRect());
|
|
||||||
m_aircraft->quadShape->setScene(scene);
|
|
||||||
|
|
||||||
// Put combo boxes in line one of the custom mixer table:
|
|
||||||
UAVDataObject* obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
|
|
||||||
UAVObjectField* field = obj->getField(QString("Mixer1Type"));
|
|
||||||
QStringList list = field->getOptions();
|
|
||||||
for (int i=0;i<8;i++) {
|
|
||||||
QComboBox* qb = new QComboBox(m_aircraft->customMixerTable);
|
|
||||||
qb->addItems(list);
|
|
||||||
m_aircraft->customMixerTable->setCellWidget(0,i,qb);
|
|
||||||
}
|
|
||||||
|
|
||||||
SpinBoxDelegate *sbd = new SpinBoxDelegate();
|
|
||||||
for (int i=1;i<8; i++) {
|
|
||||||
m_aircraft->customMixerTable->setItemDelegateForRow(i, sbd);
|
|
||||||
}
|
|
||||||
|
|
||||||
connect(m_aircraft->fixedWingType, SIGNAL(currentIndexChanged(QString)), this, SLOT(setupAirframeUI(QString)));
|
|
||||||
connect(m_aircraft->multirotorFrameType, SIGNAL(currentIndexChanged(QString)), this, SLOT(setupAirframeUI(QString)));
|
|
||||||
connect(m_aircraft->aircraftType, SIGNAL(currentIndexChanged(int)), this, SLOT(switchAirframeType(int)));
|
|
||||||
|
|
||||||
connect(m_aircraft->fwThrottleReset, SIGNAL(clicked()), this, SLOT(resetFwMixer()));
|
|
||||||
connect(m_aircraft->mrThrottleCurveReset, SIGNAL(clicked()), this, SLOT(resetMrMixer()));
|
|
||||||
connect(m_aircraft->customReset1, SIGNAL(clicked()), this, SLOT(resetCt1Mixer()));
|
|
||||||
connect(m_aircraft->customReset2, SIGNAL(clicked()), this, SLOT(resetCt2Mixer()));
|
|
||||||
connect(m_aircraft->fixedWingThrottle, SIGNAL(curveUpdated(QList<double>,double)), this, SLOT(updateFwThrottleCurveValue(QList<double>,double)));
|
|
||||||
connect(m_aircraft->multiThrottleCurve, SIGNAL(curveUpdated(QList<double>,double)), this, SLOT(updateMrThrottleCurveValue(QList<double>,double)));
|
|
||||||
connect(m_aircraft->customThrottle1Curve, SIGNAL(curveUpdated(QList<double>,double)), this, SLOT(updateCustomThrottle1CurveValue(QList<double>,double)));
|
|
||||||
connect(m_aircraft->customThrottle2Curve, SIGNAL(curveUpdated(QList<double>,double)), this, SLOT(updateCustomThrottle2CurveValue(QList<double>,double)));
|
|
||||||
|
|
||||||
// connect(m_aircraft->fwAileron1Channel, SIGNAL(currentIndexChanged(int)), this, SLOT(toggleAileron2(int)));
|
|
||||||
// connect(m_aircraft->fwElevator1Channel, SIGNAL(currentIndexChanged(int)), this, SLOT(toggleElevator2(int)));
|
|
||||||
|
|
||||||
// Now connect the three feed forward test checkboxes
|
|
||||||
connect(m_aircraft->ffTestBox1, SIGNAL(clicked(bool)), this, SLOT(enableFFTest()));
|
|
||||||
connect(m_aircraft->ffTestBox2, SIGNAL(clicked(bool)), this, SLOT(enableFFTest()));
|
|
||||||
connect(m_aircraft->ffTestBox3, SIGNAL(clicked(bool)), this, SLOT(enableFFTest()));
|
|
||||||
|
|
||||||
enableControls(false);
|
|
||||||
refreshWidgetsValues();
|
|
||||||
|
|
||||||
|
|
||||||
// Connect the help button
|
|
||||||
connect(m_aircraft->airframeHelp, SIGNAL(clicked()), this, SLOT(openHelp()));
|
|
||||||
addToDirtyMonitor();
|
|
||||||
}
|
|
||||||
|
|
||||||
ConfigAirframeWidget::~ConfigAirframeWidget()
|
|
||||||
{
|
|
||||||
// Do nothing
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
Slot for switching the airframe type. We do it explicitely
|
|
||||||
rather than a signal in the UI, because we want to force a fitInView of the quad shapes.
|
|
||||||
This is because this method (fitinview) only works when the widget is shown.
|
|
||||||
*/
|
|
||||||
void ConfigAirframeWidget::switchAirframeType(int index){
|
|
||||||
m_aircraft->airframesWidget->setCurrentIndex(index);
|
|
||||||
m_aircraft->quadShape->setSceneRect(quad->boundingRect());
|
|
||||||
m_aircraft->quadShape->fitInView(quad, Qt::KeepAspectRatio);
|
|
||||||
if (m_aircraft->aircraftType->findText("Custom")) {
|
|
||||||
m_aircraft->customMixerTable->resizeColumnsToContents();
|
|
||||||
for (int i=0;i<8;i++) {
|
|
||||||
m_aircraft->customMixerTable->setColumnWidth(i,(m_aircraft->customMixerTable->width()-
|
|
||||||
m_aircraft->customMixerTable->verticalHeader()->width())/8);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ConfigAirframeWidget::showEvent(QShowEvent *event)
|
|
||||||
{
|
|
||||||
Q_UNUSED(event)
|
|
||||||
// Thit fitInView method should only be called now, once the
|
|
||||||
// widget is shown, otherwise it cannot compute its values and
|
|
||||||
// the result is usually a ahrsbargraph that is way too small.
|
|
||||||
m_aircraft->quadShape->fitInView(quad, Qt::KeepAspectRatio);
|
|
||||||
m_aircraft->customMixerTable->resizeColumnsToContents();
|
|
||||||
for (int i=0;i<8;i++) {
|
|
||||||
m_aircraft->customMixerTable->setColumnWidth(i,(m_aircraft->customMixerTable->width()-
|
|
||||||
m_aircraft->customMixerTable->verticalHeader()->width())/8);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ConfigAirframeWidget::resizeEvent(QResizeEvent* event)
|
|
||||||
{
|
|
||||||
Q_UNUSED(event);
|
|
||||||
m_aircraft->quadShape->fitInView(quad, Qt::KeepAspectRatio);
|
|
||||||
// Make the custom table columns autostretch:
|
|
||||||
m_aircraft->customMixerTable->resizeColumnsToContents();
|
|
||||||
for (int i=0;i<8;i++) {
|
|
||||||
m_aircraft->customMixerTable->setColumnWidth(i,(m_aircraft->customMixerTable->width()-
|
|
||||||
m_aircraft->customMixerTable->verticalHeader()->width())/8);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void ConfigAirframeWidget::toggleAileron2(int index)
|
|
||||||
{
|
|
||||||
if (index) {
|
|
||||||
m_aircraft->fwAileron2Channel->setEnabled(true);
|
|
||||||
m_aircraft->fwAileron2Label->setEnabled(true);
|
|
||||||
} else {
|
|
||||||
m_aircraft->fwAileron2Channel->setEnabled(false);
|
|
||||||
m_aircraft->fwAileron2Label->setEnabled(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ConfigAirframeWidget::toggleElevator2(int index)
|
|
||||||
{
|
|
||||||
if (index) {
|
|
||||||
m_aircraft->fwElevator2Channel->setEnabled(true);
|
|
||||||
m_aircraft->fwElevator2Label->setEnabled(true);
|
|
||||||
} else {
|
|
||||||
m_aircraft->fwElevator2Channel->setEnabled(false);
|
|
||||||
m_aircraft->fwElevator2Label->setEnabled(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ConfigAirframeWidget::toggleRudder2(int index)
|
|
||||||
{
|
|
||||||
if (index) {
|
|
||||||
m_aircraft->fwRudder2Channel->setEnabled(true);
|
|
||||||
m_aircraft->fwRudder2Label->setEnabled(true);
|
|
||||||
} else {
|
|
||||||
m_aircraft->fwRudder2Channel->setEnabled(false);
|
|
||||||
m_aircraft->fwRudder2Label->setEnabled(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////
|
|
||||||
/// Feed Forward Testing
|
|
||||||
/////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
/**
|
|
||||||
Enables and runs feed forward testing
|
|
||||||
*/
|
|
||||||
void ConfigAirframeWidget::enableFFTest()
|
|
||||||
{
|
|
||||||
// Role:
|
|
||||||
// - Check if all three checkboxes are checked
|
|
||||||
// - Every other timer event: toggle engine from 45% to 55%
|
|
||||||
// - Every other time event: send FF settings to flight FW
|
|
||||||
if (m_aircraft->ffTestBox1->isChecked() &&
|
|
||||||
m_aircraft->ffTestBox2->isChecked() &&
|
|
||||||
m_aircraft->ffTestBox3->isChecked()) {
|
|
||||||
if (!ffTuningInProgress)
|
|
||||||
{
|
|
||||||
// Initiate tuning:
|
|
||||||
UAVDataObject* obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("ManualControlCommand")));
|
|
||||||
UAVObject::Metadata mdata = obj->getMetadata();
|
|
||||||
accInitialData = mdata;
|
|
||||||
mdata.flightAccess = UAVObject::ACCESS_READONLY;
|
|
||||||
obj->setMetadata(mdata);
|
|
||||||
}
|
|
||||||
// Depending on phase, either move actuator or send FF settings:
|
|
||||||
if (ffTuningPhase) {
|
|
||||||
// Send FF settings to the board
|
|
||||||
UAVDataObject* obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
|
|
||||||
UAVObjectField* field = obj->getField(QString("FeedForward"));
|
|
||||||
field->setDouble((double)m_aircraft->feedForwardSlider->value()/100);
|
|
||||||
field = obj->getField(QString("AccelTime"));
|
|
||||||
field->setDouble(m_aircraft->accelTime->value());
|
|
||||||
field = obj->getField(QString("DecelTime"));
|
|
||||||
field->setDouble(m_aircraft->decelTime->value());
|
|
||||||
field = obj->getField(QString("MaxAccel"));
|
|
||||||
field->setDouble(m_aircraft->maxAccelSlider->value());
|
|
||||||
obj->updated();
|
|
||||||
} else {
|
|
||||||
// Toggle motor state
|
|
||||||
UAVDataObject* obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("ManualControlCommand")));
|
|
||||||
double value = obj->getField("Throttle")->getDouble();
|
|
||||||
double target = (value < 0.5) ? 0.55 : 0.45;
|
|
||||||
obj->getField("Throttle")->setValue(target);
|
|
||||||
obj->updated();
|
|
||||||
}
|
|
||||||
ffTuningPhase = !ffTuningPhase;
|
|
||||||
ffTuningInProgress = true;
|
|
||||||
QTimer::singleShot(1000, this, SLOT(enableFFTest()));
|
|
||||||
} else {
|
|
||||||
// - If no: disarm timer, restore actuatorcommand metadata
|
|
||||||
// Disarm!
|
|
||||||
if (ffTuningInProgress) {
|
|
||||||
ffTuningInProgress = false;
|
|
||||||
UAVDataObject* obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("ManualControlCommand")));
|
|
||||||
UAVObject::Metadata mdata = obj->getMetadata();
|
|
||||||
mdata = accInitialData; // Restore metadata
|
|
||||||
obj->setMetadata(mdata);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
Resets Fixed wing throttle mixer
|
|
||||||
*/
|
|
||||||
void ConfigAirframeWidget::resetFwMixer()
|
|
||||||
{
|
|
||||||
UAVDataObject* obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
|
|
||||||
UAVObjectField* field = obj->getField(QString("ThrottleCurve1"));
|
|
||||||
resetMixer(m_aircraft->fixedWingThrottle, field->getNumElements(),1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
Resets Multirotor throttle mixer
|
|
||||||
*/
|
|
||||||
void ConfigAirframeWidget::resetMrMixer()
|
|
||||||
{
|
|
||||||
UAVDataObject* obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
|
|
||||||
UAVObjectField* field = obj->getField(QString("ThrottleCurve1"));
|
|
||||||
resetMixer(m_aircraft->multiThrottleCurve, field->getNumElements(),0.9);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
Resets Custom throttle 1 mixer
|
|
||||||
*/
|
|
||||||
void ConfigAirframeWidget::resetCt1Mixer()
|
|
||||||
{
|
|
||||||
UAVDataObject* obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
|
|
||||||
UAVObjectField* field = obj->getField(QString("ThrottleCurve1"));
|
|
||||||
resetMixer(m_aircraft->customThrottle1Curve, field->getNumElements(),1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
Resets Custom throttle 2 mixer
|
|
||||||
*/
|
|
||||||
void ConfigAirframeWidget::resetCt2Mixer()
|
|
||||||
{
|
|
||||||
UAVDataObject* obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
|
|
||||||
UAVObjectField* field = obj->getField(QString("ThrottleCurve2"));
|
|
||||||
resetMixer(m_aircraft->customThrottle2Curve, field->getNumElements(),1);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
Resets a mixer curve
|
|
||||||
*/
|
|
||||||
void ConfigAirframeWidget::resetMixer(MixerCurveWidget *mixer, int numElements, double maxvalue)
|
|
||||||
{
|
|
||||||
// Setup all Throttle1 curves for all types of airframes
|
|
||||||
mixer->initLinearCurve((quint32)numElements,maxvalue);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
Updates the currently moved throttle curve item value
|
|
||||||
*/
|
|
||||||
void ConfigAirframeWidget::updateFwThrottleCurveValue(QList<double> list, double value)
|
|
||||||
{
|
|
||||||
Q_UNUSED(list);
|
|
||||||
m_aircraft->fwThrottleCurveItemValue->setText(QString().sprintf("Val: %.2f",value));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
Updates the currently moved throttle curve item value
|
|
||||||
*/
|
|
||||||
void ConfigAirframeWidget::updateMrThrottleCurveValue(QList<double> list, double value)
|
|
||||||
{
|
|
||||||
Q_UNUSED(list);
|
|
||||||
m_aircraft->mrThrottleCurveItemValue->setText(QString().sprintf("Val: %.2f",value));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
Updates the currently moved throttle curve item value (Custom throttle 1)
|
|
||||||
*/
|
|
||||||
void ConfigAirframeWidget::updateCustomThrottle1CurveValue(QList<double> list, double value)
|
|
||||||
{
|
|
||||||
Q_UNUSED(list);
|
|
||||||
m_aircraft->customThrottleCurve1Value->setText(QString().sprintf("Val: %.2f",value));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
Updates the currently moved throttle curve item value (Custom throttle 2)
|
|
||||||
*/
|
|
||||||
void ConfigAirframeWidget::updateCustomThrottle2CurveValue(QList<double> list, double value)
|
|
||||||
{
|
|
||||||
Q_UNUSED(list);
|
|
||||||
m_aircraft->customThrottleCurve2Value->setText(QString().sprintf("Val: %.2f",value));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**************************
|
|
||||||
* Aircraft settings
|
|
||||||
**************************/
|
|
||||||
/**
|
|
||||||
Refreshes the current value of the SystemSettings which holds the aircraft type
|
|
||||||
*/
|
|
||||||
void ConfigAirframeWidget::refreshWidgetsValues()
|
|
||||||
{
|
|
||||||
if(!allObjectsUpdated())
|
|
||||||
return;
|
|
||||||
bool dirty=isDirty();
|
|
||||||
// Get the Airframe type from the system settings:
|
|
||||||
UAVDataObject* obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("SystemSettings")));
|
|
||||||
Q_ASSERT(obj);
|
|
||||||
UAVObjectField *field = obj->getField(QString("AirframeType"));
|
|
||||||
Q_ASSERT(field);
|
|
||||||
// At this stage, we will need to have some hardcoded settings in this code, this
|
|
||||||
// is not ideal, but here you go.
|
|
||||||
QString frameType = field->getValue().toString();
|
|
||||||
setupAirframeUI(frameType);
|
|
||||||
|
|
||||||
obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
|
|
||||||
Q_ASSERT(obj);
|
|
||||||
field = obj->getField(QString("ThrottleCurve1"));
|
|
||||||
Q_ASSERT(field);
|
|
||||||
QList<double> curveValues;
|
|
||||||
// If the 1st element of the curve is <= -10, then the curve
|
|
||||||
// is a straight line (that's how the mixer works on the mainboard):
|
|
||||||
if (field->getValue(0).toInt() <= -10) {
|
|
||||||
m_aircraft->multiThrottleCurve->initLinearCurve(field->getNumElements(),(double)1);
|
|
||||||
m_aircraft->fixedWingThrottle->initLinearCurve(field->getNumElements(),(double)1);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
double temp=0;
|
|
||||||
double value;
|
|
||||||
for (unsigned int i=0; i < field->getNumElements(); i++) {
|
|
||||||
value=field->getValue(i).toDouble();
|
|
||||||
temp+=value;
|
|
||||||
curveValues.append(value);
|
|
||||||
}
|
|
||||||
if(temp==0)
|
|
||||||
{
|
|
||||||
m_aircraft->multiThrottleCurve->initLinearCurve(field->getNumElements(),0.9);;
|
|
||||||
m_aircraft->fixedWingThrottle->initLinearCurve(field->getNumElements(),(double)1);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
m_aircraft->multiThrottleCurve->initCurve(curveValues);
|
|
||||||
m_aircraft->fixedWingThrottle->initCurve(curveValues);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Setup all Throttle1 curves for all types of airframes
|
|
||||||
// Load the Settings for fixed wing frames:
|
|
||||||
if (frameType.startsWith("FixedWing")) {
|
|
||||||
// Then retrieve how channels are setup
|
|
||||||
obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("ActuatorSettings")));
|
|
||||||
Q_ASSERT(obj);
|
|
||||||
field = obj->getField(QString("FixedWingThrottle"));
|
|
||||||
Q_ASSERT(field);
|
|
||||||
m_aircraft->fwEngineChannel->setCurrentIndex(m_aircraft->fwEngineChannel->findText(field->getValue().toString()));
|
|
||||||
field = obj->getField(QString("FixedWingRoll1"));
|
|
||||||
Q_ASSERT(field);
|
|
||||||
m_aircraft->fwAileron1Channel->setCurrentIndex(m_aircraft->fwAileron1Channel->findText(field->getValue().toString()));
|
|
||||||
field = obj->getField(QString("FixedWingRoll2"));
|
|
||||||
Q_ASSERT(field);
|
|
||||||
m_aircraft->fwAileron2Channel->setCurrentIndex(m_aircraft->fwAileron2Channel->findText(field->getValue().toString()));
|
|
||||||
field = obj->getField(QString("FixedWingPitch1"));
|
|
||||||
Q_ASSERT(field);
|
|
||||||
m_aircraft->fwElevator1Channel->setCurrentIndex(m_aircraft->fwElevator1Channel->findText(field->getValue().toString()));
|
|
||||||
field = obj->getField(QString("FixedWingPitch2"));
|
|
||||||
Q_ASSERT(field);
|
|
||||||
m_aircraft->fwElevator2Channel->setCurrentIndex(m_aircraft->fwElevator2Channel->findText(field->getValue().toString()));
|
|
||||||
field = obj->getField(QString("FixedWingYaw1"));
|
|
||||||
Q_ASSERT(field);
|
|
||||||
m_aircraft->fwRudder1Channel->setCurrentIndex(m_aircraft->fwRudder1Channel->findText(field->getValue().toString()));
|
|
||||||
field = obj->getField(QString("FixedWingYaw2"));
|
|
||||||
Q_ASSERT(field);
|
|
||||||
m_aircraft->fwRudder2Channel->setCurrentIndex(m_aircraft->fwRudder2Channel->findText(field->getValue().toString()));
|
|
||||||
|
|
||||||
if (frameType == "FixedWingElevon") {
|
|
||||||
// If the airframe is elevon, restore the slider setting
|
|
||||||
// Find the channel number for Elevon1 (FixedWingRoll1)
|
|
||||||
obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
|
|
||||||
Q_ASSERT(obj);
|
|
||||||
int chMixerNumber = m_aircraft->fwAileron1Channel->currentIndex()-1;
|
|
||||||
if (chMixerNumber >= 0) { // If for some reason the actuators were incoherent, we might fail here, hence the check.
|
|
||||||
field = obj->getField(mixerVectors.at(chMixerNumber));
|
|
||||||
int ti = field->getElementNames().indexOf("Roll");
|
|
||||||
m_aircraft->elevonSlider1->setValue(field->getDouble(ti)*100);
|
|
||||||
ti = field->getElementNames().indexOf("Pitch");
|
|
||||||
m_aircraft->elevonSlider2->setValue(field->getDouble(ti)*100);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (frameType == "FixedWingVtail") {
|
|
||||||
obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
|
|
||||||
Q_ASSERT(obj);
|
|
||||||
int chMixerNumber = m_aircraft->fwElevator1Channel->currentIndex()-1;
|
|
||||||
if (chMixerNumber >=0) {
|
|
||||||
field = obj->getField(mixerVectors.at(chMixerNumber));
|
|
||||||
int ti = field->getElementNames().indexOf("Yaw");
|
|
||||||
m_aircraft->elevonSlider1->setValue(field->getDouble(ti)*100);
|
|
||||||
ti = field->getElementNames().indexOf("Pitch");
|
|
||||||
m_aircraft->elevonSlider2->setValue(field->getDouble(ti)*100);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} else if (frameType == "QuadX" || frameType == "QuadP" ||
|
|
||||||
frameType == "Hexa" || frameType == "Octo" ||
|
|
||||||
frameType == "HexaCoax" || frameType == "OctoV" ||
|
|
||||||
frameType == "HexaX" || frameType == "OctoCoaxP" ||
|
|
||||||
frameType == "OctoCoaxX" || frameType == "Tri") {
|
|
||||||
//////////////////////////////////////////////////////////////////
|
|
||||||
// Retrieve Multirotor settings
|
|
||||||
//////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("ActuatorSettings")));
|
|
||||||
Q_ASSERT(obj);
|
|
||||||
if (frameType == "QuadP") {
|
|
||||||
// Motors 1/2/3/4 are: N / E / S / W
|
|
||||||
field = obj->getField(QString("VTOLMotorN"));
|
|
||||||
Q_ASSERT(field);
|
|
||||||
m_aircraft->multiMotor1->setCurrentIndex(m_aircraft->multiMotor1->findText(field->getValue().toString()));
|
|
||||||
field = obj->getField(QString("VTOLMotorE"));
|
|
||||||
Q_ASSERT(field);
|
|
||||||
m_aircraft->multiMotor2->setCurrentIndex(m_aircraft->multiMotor2->findText(field->getValue().toString()));
|
|
||||||
field = obj->getField(QString("VTOLMotorS"));
|
|
||||||
Q_ASSERT(field);
|
|
||||||
m_aircraft->multiMotor3->setCurrentIndex(m_aircraft->multiMotor3->findText(field->getValue().toString()));
|
|
||||||
field = obj->getField(QString("VTOLMotorW"));
|
|
||||||
Q_ASSERT(field);
|
|
||||||
m_aircraft->multiMotor4->setCurrentIndex(m_aircraft->multiMotor4->findText(field->getValue().toString()));
|
|
||||||
// Now, read the 1st mixer R/P/Y levels and initialize the mix sliders.
|
|
||||||
// This assumes that all vectors are identical - if not, the user should use the
|
|
||||||
// "custom" setting.
|
|
||||||
obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
|
|
||||||
Q_ASSERT(obj);
|
|
||||||
int eng= m_aircraft->multiMotor1->currentIndex()-1;
|
|
||||||
// eng will be -1 if value is set to "None"
|
|
||||||
if (eng > -1) {
|
|
||||||
field = obj->getField(mixerVectors.at(eng));
|
|
||||||
int i = field->getElementNames().indexOf("Pitch");
|
|
||||||
double val = field->getDouble(i)/1.27;
|
|
||||||
m_aircraft->mrPitchMixLevel->setValue(val);
|
|
||||||
i = field->getElementNames().indexOf("Yaw");
|
|
||||||
val = (1-field->getDouble(i)/1.27);
|
|
||||||
m_aircraft->mrYawMixLevel->setValue(val);
|
|
||||||
eng = m_aircraft->multiMotor2->currentIndex()-1;
|
|
||||||
field = obj->getField(mixerVectors.at(eng));
|
|
||||||
i = field->getElementNames().indexOf("Roll");
|
|
||||||
val = -field->getDouble(i)/1.27;
|
|
||||||
m_aircraft->mrRollMixLevel->setValue(val);
|
|
||||||
}
|
|
||||||
} else if (frameType == "QuadX") {
|
|
||||||
// Motors 1/2/3/4 are: NW / NE / SE / SW
|
|
||||||
field = obj->getField(QString("VTOLMotorNW"));
|
|
||||||
Q_ASSERT(field);
|
|
||||||
m_aircraft->multiMotor1->setCurrentIndex(m_aircraft->multiMotor1->findText(field->getValue().toString()));
|
|
||||||
field = obj->getField(QString("VTOLMotorNE"));
|
|
||||||
Q_ASSERT(field);
|
|
||||||
m_aircraft->multiMotor2->setCurrentIndex(m_aircraft->multiMotor2->findText(field->getValue().toString()));
|
|
||||||
field = obj->getField(QString("VTOLMotorSE"));
|
|
||||||
Q_ASSERT(field);
|
|
||||||
m_aircraft->multiMotor3->setCurrentIndex(m_aircraft->multiMotor3->findText(field->getValue().toString()));
|
|
||||||
field = obj->getField(QString("VTOLMotorSW"));
|
|
||||||
Q_ASSERT(field);
|
|
||||||
m_aircraft->multiMotor4->setCurrentIndex(m_aircraft->multiMotor4->findText(field->getValue().toString()));
|
|
||||||
// Now, read the 1st mixer R/P/Y levels and initialize the mix sliders.
|
|
||||||
// This assumes that all vectors are identical - if not, the user should use the
|
|
||||||
// "custom" setting.
|
|
||||||
obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
|
|
||||||
Q_ASSERT(obj);
|
|
||||||
int eng= m_aircraft->multiMotor1->currentIndex()-1;
|
|
||||||
// eng will be -1 if value is set to "None"
|
|
||||||
if (eng > -1) {
|
|
||||||
field = obj->getField(mixerVectors.at(eng));
|
|
||||||
int i = field->getElementNames().indexOf("Pitch");
|
|
||||||
double val = field->getDouble(i)/1.27;
|
|
||||||
m_aircraft->mrPitchMixLevel->setValue(val);
|
|
||||||
i = field->getElementNames().indexOf("Yaw");
|
|
||||||
val = 1-field->getDouble(i)/1.27;
|
|
||||||
m_aircraft->mrYawMixLevel->setValue(val);
|
|
||||||
i = field->getElementNames().indexOf("Roll");
|
|
||||||
val = field->getDouble(i)/1.27;
|
|
||||||
m_aircraft->mrRollMixLevel->setValue(val);
|
|
||||||
}
|
|
||||||
} else if (frameType == "Hexa") {
|
|
||||||
// Motors 1/2/3 4/5/6 are: N / NE / SE / S / SW / NW
|
|
||||||
field = obj->getField(QString("VTOLMotorN"));
|
|
||||||
m_aircraft->multiMotor1->setCurrentIndex(m_aircraft->multiMotor1->findText(field->getValue().toString()));
|
|
||||||
field = obj->getField(QString("VTOLMotorNE"));
|
|
||||||
m_aircraft->multiMotor2->setCurrentIndex(m_aircraft->multiMotor2->findText(field->getValue().toString()));
|
|
||||||
field = obj->getField(QString("VTOLMotorSE"));
|
|
||||||
m_aircraft->multiMotor3->setCurrentIndex(m_aircraft->multiMotor3->findText(field->getValue().toString()));
|
|
||||||
field = obj->getField(QString("VTOLMotorS"));
|
|
||||||
m_aircraft->multiMotor4->setCurrentIndex(m_aircraft->multiMotor4->findText(field->getValue().toString()));
|
|
||||||
field = obj->getField(QString("VTOLMotorSW"));
|
|
||||||
m_aircraft->multiMotor5->setCurrentIndex(m_aircraft->multiMotor4->findText(field->getValue().toString()));
|
|
||||||
field = obj->getField(QString("VTOLMotorNW"));
|
|
||||||
m_aircraft->multiMotor6->setCurrentIndex(m_aircraft->multiMotor4->findText(field->getValue().toString()));
|
|
||||||
// Now, read the 1st mixer R/P/Y levels and initialize the mix sliders.
|
|
||||||
// This assumes that all vectors are identical - if not, the user should use the
|
|
||||||
// "custom" setting.
|
|
||||||
obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
|
|
||||||
int eng= m_aircraft->multiMotor1->currentIndex()-1;
|
|
||||||
// eng will be -1 if value is set to "None"
|
|
||||||
if (eng > -1) {
|
|
||||||
field = obj->getField(mixerVectors.at(eng));
|
|
||||||
int i = field->getElementNames().indexOf("Pitch");
|
|
||||||
double val = floor(field->getDouble(i)/1.27);
|
|
||||||
m_aircraft->mrPitchMixLevel->setValue(val);
|
|
||||||
i = field->getElementNames().indexOf("Yaw");
|
|
||||||
val = floor(-field->getDouble(i)/1.27);
|
|
||||||
m_aircraft->mrYawMixLevel->setValue(val);
|
|
||||||
eng = m_aircraft->multiMotor2->currentIndex()-1;
|
|
||||||
if(eng>-1)
|
|
||||||
{
|
|
||||||
field = obj->getField(mixerVectors.at(eng));
|
|
||||||
i = field->getElementNames().indexOf("Roll");
|
|
||||||
val = floor(1-field->getDouble(i)/1.27);
|
|
||||||
m_aircraft->mrRollMixLevel->setValue(val);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (frameType == "HexaX") {
|
|
||||||
// Motors 1/2/3 4/5/6 are: NE / E / SE / SW / W / NW
|
|
||||||
field = obj->getField(QString("VTOLMotorNE"));
|
|
||||||
m_aircraft->multiMotor1->setCurrentIndex(m_aircraft->multiMotor1->findText(field->getValue().toString()));
|
|
||||||
field = obj->getField(QString("VTOLMotorE"));
|
|
||||||
m_aircraft->multiMotor2->setCurrentIndex(m_aircraft->multiMotor2->findText(field->getValue().toString()));
|
|
||||||
field = obj->getField(QString("VTOLMotorSE"));
|
|
||||||
m_aircraft->multiMotor3->setCurrentIndex(m_aircraft->multiMotor3->findText(field->getValue().toString()));
|
|
||||||
field = obj->getField(QString("VTOLMotorSW"));
|
|
||||||
m_aircraft->multiMotor4->setCurrentIndex(m_aircraft->multiMotor4->findText(field->getValue().toString()));
|
|
||||||
field = obj->getField(QString("VTOLMotorW"));
|
|
||||||
m_aircraft->multiMotor5->setCurrentIndex(m_aircraft->multiMotor4->findText(field->getValue().toString()));
|
|
||||||
field = obj->getField(QString("VTOLMotorNW"));
|
|
||||||
m_aircraft->multiMotor6->setCurrentIndex(m_aircraft->multiMotor4->findText(field->getValue().toString()));
|
|
||||||
// Now, read the 1st mixer R/P/Y levels and initialize the mix sliders.
|
|
||||||
// This assumes that all vectors are identical - if not, the user should use the
|
|
||||||
// "custom" setting.
|
|
||||||
obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
|
|
||||||
int eng= m_aircraft->multiMotor1->currentIndex()-1;
|
|
||||||
// eng will be -1 if value is set to "None"
|
|
||||||
if (eng > -1) {
|
|
||||||
field = obj->getField(mixerVectors.at(eng));
|
|
||||||
int i = field->getElementNames().indexOf("Pitch");
|
|
||||||
double val = floor(field->getDouble(i)/1.27);
|
|
||||||
m_aircraft->mrPitchMixLevel->setValue(val);
|
|
||||||
i = field->getElementNames().indexOf("Yaw");
|
|
||||||
val = floor(-field->getDouble(i)/1.27);
|
|
||||||
m_aircraft->mrYawMixLevel->setValue(val);
|
|
||||||
eng = m_aircraft->multiMotor2->currentIndex()-1;
|
|
||||||
field = obj->getField(mixerVectors.at(eng));
|
|
||||||
i = field->getElementNames().indexOf("Roll");
|
|
||||||
val = floor(1-field->getDouble(i)/1.27);
|
|
||||||
m_aircraft->mrRollMixLevel->setValue(val);
|
|
||||||
}
|
|
||||||
} else if (frameType == "HexaCoax") {
|
|
||||||
// Motors 1/2/3 4/5/6 are: NW/W NE/E S/SE
|
|
||||||
field = obj->getField(QString("VTOLMotorNW"));
|
|
||||||
m_aircraft->multiMotor1->setCurrentIndex(m_aircraft->multiMotor1->findText(field->getValue().toString()));
|
|
||||||
field = obj->getField(QString("VTOLMotorW"));
|
|
||||||
m_aircraft->multiMotor2->setCurrentIndex(m_aircraft->multiMotor2->findText(field->getValue().toString()));
|
|
||||||
field = obj->getField(QString("VTOLMotorNE"));
|
|
||||||
m_aircraft->multiMotor3->setCurrentIndex(m_aircraft->multiMotor3->findText(field->getValue().toString()));
|
|
||||||
field = obj->getField(QString("VTOLMotorE"));
|
|
||||||
m_aircraft->multiMotor4->setCurrentIndex(m_aircraft->multiMotor4->findText(field->getValue().toString()));
|
|
||||||
field = obj->getField(QString("VTOLMotorS"));
|
|
||||||
m_aircraft->multiMotor5->setCurrentIndex(m_aircraft->multiMotor4->findText(field->getValue().toString()));
|
|
||||||
field = obj->getField(QString("VTOLMotorSE"));
|
|
||||||
m_aircraft->multiMotor6->setCurrentIndex(m_aircraft->multiMotor4->findText(field->getValue().toString()));
|
|
||||||
// Now, read the 1st mixer R/P/Y levels and initialize the mix sliders.
|
|
||||||
// This assumes that all vectors are identical - if not, the user should use the
|
|
||||||
// "custom" setting.
|
|
||||||
obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
|
|
||||||
int eng= m_aircraft->multiMotor1->currentIndex()-1;
|
|
||||||
// eng will be -1 if value is set to "None"
|
|
||||||
if (eng > -1) {
|
|
||||||
field = obj->getField(mixerVectors.at(eng));
|
|
||||||
int i = field->getElementNames().indexOf("Pitch");
|
|
||||||
double val = floor(2*field->getDouble(i)/1.27);
|
|
||||||
m_aircraft->mrPitchMixLevel->setValue(val);
|
|
||||||
i = field->getElementNames().indexOf("Yaw");
|
|
||||||
val = floor(-field->getDouble(i)/1.27);
|
|
||||||
m_aircraft->mrYawMixLevel->setValue(val);
|
|
||||||
i = field->getElementNames().indexOf("Roll");
|
|
||||||
val = floor(field->getDouble(i)/1.27);
|
|
||||||
m_aircraft->mrRollMixLevel->setValue(val);
|
|
||||||
}
|
|
||||||
} else if (frameType == "Octo" || frameType == "OctoV" ||
|
|
||||||
frameType == "OctoCoaxP") {
|
|
||||||
// Motors 1 to 8 are N / NE / E / etc
|
|
||||||
field = obj->getField(QString("VTOLMotorN"));
|
|
||||||
Q_ASSERT(field);
|
|
||||||
m_aircraft->multiMotor1->setCurrentIndex(m_aircraft->multiMotor1->findText(field->getValue().toString()));
|
|
||||||
field = obj->getField(QString("VTOLMotorNE"));
|
|
||||||
Q_ASSERT(field);
|
|
||||||
m_aircraft->multiMotor2->setCurrentIndex(m_aircraft->multiMotor2->findText(field->getValue().toString()));
|
|
||||||
field = obj->getField(QString("VTOLMotorE"));
|
|
||||||
Q_ASSERT(field);
|
|
||||||
m_aircraft->multiMotor3->setCurrentIndex(m_aircraft->multiMotor3->findText(field->getValue().toString()));
|
|
||||||
field = obj->getField(QString("VTOLMotorSE"));
|
|
||||||
Q_ASSERT(field);
|
|
||||||
m_aircraft->multiMotor4->setCurrentIndex(m_aircraft->multiMotor4->findText(field->getValue().toString()));
|
|
||||||
field = obj->getField(QString("VTOLMotorS"));
|
|
||||||
Q_ASSERT(field);
|
|
||||||
m_aircraft->multiMotor5->setCurrentIndex(m_aircraft->multiMotor4->findText(field->getValue().toString()));
|
|
||||||
field = obj->getField(QString("VTOLMotorSW"));
|
|
||||||
Q_ASSERT(field);
|
|
||||||
m_aircraft->multiMotor6->setCurrentIndex(m_aircraft->multiMotor4->findText(field->getValue().toString()));
|
|
||||||
field = obj->getField(QString("VTOLMotorW"));
|
|
||||||
Q_ASSERT(field);
|
|
||||||
m_aircraft->multiMotor7->setCurrentIndex(m_aircraft->multiMotor4->findText(field->getValue().toString()));
|
|
||||||
field = obj->getField(QString("VTOLMotorNW"));
|
|
||||||
Q_ASSERT(field);
|
|
||||||
m_aircraft->multiMotor8->setCurrentIndex(m_aircraft->multiMotor4->findText(field->getValue().toString()));
|
|
||||||
// Now, read the 1st mixer R/P/Y levels and initialize the mix sliders.
|
|
||||||
// This assumes that all vectors are identical - if not, the user should use the
|
|
||||||
// "custom" setting.
|
|
||||||
obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
|
|
||||||
int eng= m_aircraft->multiMotor1->currentIndex()-1;
|
|
||||||
// eng will be -1 if value is set to "None"
|
|
||||||
if (eng > -1) {
|
|
||||||
if (frameType == "Octo") {
|
|
||||||
field = obj->getField(mixerVectors.at(eng));
|
|
||||||
int i = field->getElementNames().indexOf("Pitch");
|
|
||||||
double val = floor(field->getDouble(i)/1.27);
|
|
||||||
m_aircraft->mrPitchMixLevel->setValue(val);
|
|
||||||
i = field->getElementNames().indexOf("Yaw");
|
|
||||||
val = floor(-field->getDouble(i)/1.27);
|
|
||||||
m_aircraft->mrYawMixLevel->setValue(val);
|
|
||||||
eng = m_aircraft->multiMotor2->currentIndex()-1;
|
|
||||||
field = obj->getField(mixerVectors.at(eng));
|
|
||||||
i = field->getElementNames().indexOf("Roll");
|
|
||||||
val = floor(-field->getDouble(i)/1.27);
|
|
||||||
m_aircraft->mrRollMixLevel->setValue(val);
|
|
||||||
} else if (frameType == "OctoV") {
|
|
||||||
field = obj->getField(mixerVectors.at(eng));
|
|
||||||
int i = field->getElementNames().indexOf("Yaw");
|
|
||||||
double val = floor(-field->getDouble(i)/1.27);
|
|
||||||
m_aircraft->mrYawMixLevel->setValue(val);
|
|
||||||
i = field->getElementNames().indexOf("Roll");
|
|
||||||
val = floor(-field->getDouble(i)/1.27);
|
|
||||||
m_aircraft->mrRollMixLevel->setValue(val);
|
|
||||||
eng = m_aircraft->multiMotor2->currentIndex()-1;
|
|
||||||
field = obj->getField(mixerVectors.at(eng));
|
|
||||||
i = field->getElementNames().indexOf("Pitch");
|
|
||||||
val = floor(field->getDouble(i)/1.27);
|
|
||||||
m_aircraft->mrPitchMixLevel->setValue(val);
|
|
||||||
|
|
||||||
} else if (frameType == "OctoCoaxP") {
|
|
||||||
field = obj->getField(mixerVectors.at(eng));
|
|
||||||
int i = field->getElementNames().indexOf("Pitch");
|
|
||||||
double val = floor(field->getDouble(i)/1.27);
|
|
||||||
m_aircraft->mrPitchMixLevel->setValue(val);
|
|
||||||
i = field->getElementNames().indexOf("Yaw");
|
|
||||||
val = floor(-field->getDouble(i)/1.27);
|
|
||||||
m_aircraft->mrYawMixLevel->setValue(val);
|
|
||||||
eng = m_aircraft->multiMotor3->currentIndex()-1;
|
|
||||||
field = obj->getField(mixerVectors.at(eng));
|
|
||||||
i = field->getElementNames().indexOf("Roll");
|
|
||||||
val = floor(-field->getDouble(i)/1.27);
|
|
||||||
m_aircraft->mrRollMixLevel->setValue(val);
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (frameType == "OctoCoaxX") {
|
|
||||||
// Motors 1 to 8 are N / NE / E / etc
|
|
||||||
field = obj->getField(QString("VTOLMotorNW"));
|
|
||||||
Q_ASSERT(field);
|
|
||||||
m_aircraft->multiMotor1->setCurrentIndex(m_aircraft->multiMotor1->findText(field->getValue().toString()));
|
|
||||||
field = obj->getField(QString("VTOLMotorN"));
|
|
||||||
Q_ASSERT(field);
|
|
||||||
m_aircraft->multiMotor2->setCurrentIndex(m_aircraft->multiMotor2->findText(field->getValue().toString()));
|
|
||||||
field = obj->getField(QString("VTOLMotorNE"));
|
|
||||||
Q_ASSERT(field);
|
|
||||||
m_aircraft->multiMotor3->setCurrentIndex(m_aircraft->multiMotor3->findText(field->getValue().toString()));
|
|
||||||
field = obj->getField(QString("VTOLMotorE"));
|
|
||||||
Q_ASSERT(field);
|
|
||||||
m_aircraft->multiMotor4->setCurrentIndex(m_aircraft->multiMotor4->findText(field->getValue().toString()));
|
|
||||||
field = obj->getField(QString("VTOLMotorSE"));
|
|
||||||
Q_ASSERT(field);
|
|
||||||
m_aircraft->multiMotor5->setCurrentIndex(m_aircraft->multiMotor4->findText(field->getValue().toString()));
|
|
||||||
field = obj->getField(QString("VTOLMotorS"));
|
|
||||||
Q_ASSERT(field);
|
|
||||||
m_aircraft->multiMotor6->setCurrentIndex(m_aircraft->multiMotor4->findText(field->getValue().toString()));
|
|
||||||
field = obj->getField(QString("VTOLMotorSW"));
|
|
||||||
Q_ASSERT(field);
|
|
||||||
m_aircraft->multiMotor7->setCurrentIndex(m_aircraft->multiMotor4->findText(field->getValue().toString()));
|
|
||||||
field = obj->getField(QString("VTOLMotorW"));
|
|
||||||
Q_ASSERT(field);
|
|
||||||
m_aircraft->multiMotor8->setCurrentIndex(m_aircraft->multiMotor4->findText(field->getValue().toString()));
|
|
||||||
// Now, read the 1st mixer R/P/Y levels and initialize the mix sliders.
|
|
||||||
// This assumes that all vectors are identical - if not, the user should use the
|
|
||||||
// "custom" setting.
|
|
||||||
obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
|
|
||||||
int eng= m_aircraft->multiMotor1->currentIndex()-1;
|
|
||||||
// eng will be -1 if value is set to "None"
|
|
||||||
if (eng > -1) {
|
|
||||||
field = obj->getField(mixerVectors.at(eng));
|
|
||||||
int i = field->getElementNames().indexOf("Pitch");
|
|
||||||
double val = floor(field->getDouble(i)/1.27);
|
|
||||||
m_aircraft->mrPitchMixLevel->setValue(val);
|
|
||||||
i = field->getElementNames().indexOf("Yaw");
|
|
||||||
val = floor(-field->getDouble(i)/1.27);
|
|
||||||
m_aircraft->mrYawMixLevel->setValue(val);
|
|
||||||
i = field->getElementNames().indexOf("Roll");
|
|
||||||
val = floor(field->getDouble(i)/1.27);
|
|
||||||
m_aircraft->mrRollMixLevel->setValue(val);
|
|
||||||
}
|
|
||||||
} else if (frameType == "Tri") {
|
|
||||||
// Motors 1 to 8 are N / NE / E / etc
|
|
||||||
field = obj->getField(QString("VTOLMotorNW"));
|
|
||||||
Q_ASSERT(field);
|
|
||||||
m_aircraft->multiMotor1->setCurrentIndex(m_aircraft->multiMotor1->findText(field->getValue().toString()));
|
|
||||||
field = obj->getField(QString("VTOLMotorNE"));
|
|
||||||
Q_ASSERT(field);
|
|
||||||
m_aircraft->multiMotor2->setCurrentIndex(m_aircraft->multiMotor2->findText(field->getValue().toString()));
|
|
||||||
field = obj->getField(QString("VTOLMotorS"));
|
|
||||||
Q_ASSERT(field);
|
|
||||||
m_aircraft->multiMotor3->setCurrentIndex(m_aircraft->multiMotor3->findText(field->getValue().toString()));
|
|
||||||
field = obj->getField(QString("FixedWingYaw1"));
|
|
||||||
Q_ASSERT(field);
|
|
||||||
m_aircraft->triYawChannel->setCurrentIndex(m_aircraft->multiMotor3->findText(field->getValue().toString()));
|
|
||||||
|
|
||||||
obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
|
|
||||||
int eng= m_aircraft->multiMotor1->currentIndex()-1;
|
|
||||||
// eng will be -1 if value is set to "None"
|
|
||||||
if (eng > -1) {
|
|
||||||
field = obj->getField(mixerVectors.at(eng));
|
|
||||||
int i = field->getElementNames().indexOf("Pitch");
|
|
||||||
double val = floor(2*field->getDouble(i)/1.27);
|
|
||||||
m_aircraft->mrPitchMixLevel->setValue(val);
|
|
||||||
i = field->getElementNames().indexOf("Roll");
|
|
||||||
val = floor(field->getDouble(i)/1.27);
|
|
||||||
m_aircraft->mrRollMixLevel->setValue(val);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
|
|
||||||
Q_ASSERT(obj);
|
|
||||||
// Now, retrieve the Feedforward values:
|
|
||||||
field = obj->getField(QString("FeedForward"));
|
|
||||||
Q_ASSERT(field);
|
|
||||||
m_aircraft->feedForwardSlider->setValue(field->getDouble()*100);
|
|
||||||
field = obj->getField(QString("AccelTime"));
|
|
||||||
Q_ASSERT(field);
|
|
||||||
m_aircraft->accelTime->setValue(field->getDouble());
|
|
||||||
field = obj->getField(QString("DecelTime"));
|
|
||||||
Q_ASSERT(field);
|
|
||||||
m_aircraft->decelTime->setValue(field->getDouble());
|
|
||||||
field = obj->getField(QString("MaxAccel"));
|
|
||||||
Q_ASSERT(field);
|
|
||||||
m_aircraft->maxAccelSlider->setValue(field->getDouble());
|
|
||||||
|
|
||||||
} else if (frameType == "HeliCP") {
|
|
||||||
m_aircraft->widget_3->requestccpmUpdate();
|
|
||||||
m_aircraft->aircraftType->setCurrentIndex(m_aircraft->aircraftType->findText("Helicopter"));//"Helicopter"
|
|
||||||
} else if (frameType == "Custom") {
|
|
||||||
m_aircraft->aircraftType->setCurrentIndex(m_aircraft->aircraftType->findText("Custom"));
|
|
||||||
}
|
|
||||||
|
|
||||||
updateCustomAirframeUI();
|
|
||||||
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 ConfigAirframeWidget::setupAirframeUI(QString frameType)
|
|
||||||
{
|
|
||||||
bool dirty=isDirty();
|
|
||||||
if (frameType == "FixedWing" || frameType == "Elevator aileron rudder") {
|
|
||||||
// Setup the UI
|
|
||||||
m_aircraft->aircraftType->setCurrentIndex(m_aircraft->aircraftType->findText("Fixed Wing"));
|
|
||||||
m_aircraft->fixedWingType->setCurrentIndex(m_aircraft->fixedWingType->findText("Elevator aileron rudder"));
|
|
||||||
m_aircraft->fwRudder1Channel->setEnabled(true);
|
|
||||||
m_aircraft->fwRudder1Label->setEnabled(true);
|
|
||||||
m_aircraft->fwRudder2Channel->setEnabled(true);
|
|
||||||
m_aircraft->fwRudder2Label->setEnabled(true);
|
|
||||||
m_aircraft->fwElevator1Channel->setEnabled(true);
|
|
||||||
m_aircraft->fwElevator1Label->setEnabled(true);
|
|
||||||
m_aircraft->fwElevator2Channel->setEnabled(true);
|
|
||||||
m_aircraft->fwElevator2Label->setEnabled(true);
|
|
||||||
m_aircraft->fwAileron1Channel->setEnabled(true);
|
|
||||||
m_aircraft->fwAileron1Label->setEnabled(true);
|
|
||||||
m_aircraft->fwAileron2Channel->setEnabled(true);
|
|
||||||
m_aircraft->fwAileron2Label->setEnabled(true);
|
|
||||||
|
|
||||||
m_aircraft->fwAileron1Label->setText("Aileron 1");
|
|
||||||
m_aircraft->fwAileron2Label->setText("Aileron 2");
|
|
||||||
m_aircraft->fwElevator1Label->setText("Elevator 1");
|
|
||||||
m_aircraft->fwElevator2Label->setText("Elevator 2");
|
|
||||||
m_aircraft->elevonMixBox->setHidden(true);
|
|
||||||
|
|
||||||
} else if (frameType == "FixedWingElevon" || frameType == "Elevon") {
|
|
||||||
m_aircraft->aircraftType->setCurrentIndex(m_aircraft->aircraftType->findText("Fixed Wing"));
|
|
||||||
m_aircraft->fixedWingType->setCurrentIndex(m_aircraft->fixedWingType->findText("Elevon"));
|
|
||||||
m_aircraft->fwAileron1Label->setText("Elevon 1");
|
|
||||||
m_aircraft->fwAileron2Label->setText("Elevon 2");
|
|
||||||
m_aircraft->fwElevator1Channel->setEnabled(false);
|
|
||||||
m_aircraft->fwElevator1Label->setEnabled(false);
|
|
||||||
m_aircraft->fwElevator2Channel->setEnabled(false);
|
|
||||||
m_aircraft->fwElevator2Label->setEnabled(false);
|
|
||||||
m_aircraft->fwRudder1Channel->setEnabled(true);
|
|
||||||
m_aircraft->fwRudder1Label->setEnabled(true);
|
|
||||||
m_aircraft->fwRudder2Channel->setEnabled(true);
|
|
||||||
m_aircraft->fwRudder2Label->setEnabled(true);
|
|
||||||
m_aircraft->fwElevator1Label->setText("Elevator 1");
|
|
||||||
m_aircraft->fwElevator2Label->setText("Elevator 2");
|
|
||||||
m_aircraft->elevonMixBox->setHidden(false);
|
|
||||||
m_aircraft->elevonLabel1->setText("Roll");
|
|
||||||
m_aircraft->elevonLabel2->setText("Pitch");
|
|
||||||
|
|
||||||
} else if (frameType == "FixedWingVtail" || frameType == "Vtail") {
|
|
||||||
m_aircraft->aircraftType->setCurrentIndex(m_aircraft->aircraftType->findText("Fixed Wing"));
|
|
||||||
m_aircraft->fixedWingType->setCurrentIndex(m_aircraft->fixedWingType->findText("Vtail"));
|
|
||||||
m_aircraft->fwRudder1Channel->setEnabled(false);
|
|
||||||
m_aircraft->fwRudder1Label->setEnabled(false);
|
|
||||||
m_aircraft->fwRudder2Channel->setEnabled(false);
|
|
||||||
m_aircraft->fwRudder2Label->setEnabled(false);
|
|
||||||
m_aircraft->fwElevator1Channel->setEnabled(true);
|
|
||||||
m_aircraft->fwElevator1Label->setEnabled(true);
|
|
||||||
m_aircraft->fwElevator1Label->setText("Vtail 1");
|
|
||||||
m_aircraft->fwElevator2Label->setText("Vtail 2");
|
|
||||||
m_aircraft->elevonMixBox->setHidden(false);
|
|
||||||
m_aircraft->fwElevator2Channel->setEnabled(true);
|
|
||||||
m_aircraft->fwElevator2Label->setEnabled(true);
|
|
||||||
m_aircraft->fwAileron1Label->setText("Aileron 1");
|
|
||||||
m_aircraft->fwAileron2Label->setText("Aileron 2");
|
|
||||||
m_aircraft->elevonLabel1->setText("Rudder");
|
|
||||||
m_aircraft->elevonLabel2->setText("Pitch");
|
|
||||||
|
|
||||||
} else if (frameType == "QuadX" || frameType == "Quad X") {
|
|
||||||
m_aircraft->aircraftType->setCurrentIndex(m_aircraft->aircraftType->findText("Multirotor"));
|
|
||||||
m_aircraft->multirotorFrameType->setCurrentIndex(m_aircraft->multirotorFrameType->findText("Quad X"));
|
|
||||||
quad->setElementId("quad-X");
|
|
||||||
m_aircraft->multiMotor4->setEnabled(true);
|
|
||||||
m_aircraft->multiMotor5->setEnabled(false);
|
|
||||||
m_aircraft->multiMotor6->setEnabled(false);
|
|
||||||
m_aircraft->multiMotor7->setEnabled(false);
|
|
||||||
m_aircraft->multiMotor8->setEnabled(false);
|
|
||||||
m_aircraft->triYawChannel->setEnabled(false);
|
|
||||||
m_aircraft->mrRollMixLevel->setValue(50);
|
|
||||||
m_aircraft->mrPitchMixLevel->setValue(50);
|
|
||||||
m_aircraft->mrYawMixLevel->setValue(50);
|
|
||||||
} else if (frameType == "QuadP" || frameType == "Quad +") {
|
|
||||||
m_aircraft->aircraftType->setCurrentIndex(m_aircraft->aircraftType->findText("Multirotor"));
|
|
||||||
m_aircraft->multirotorFrameType->setCurrentIndex(m_aircraft->multirotorFrameType->findText("Quad +"));
|
|
||||||
quad->setElementId("quad-plus");
|
|
||||||
m_aircraft->multiMotor4->setEnabled(true);
|
|
||||||
m_aircraft->multiMotor5->setEnabled(false);
|
|
||||||
m_aircraft->multiMotor6->setEnabled(false);
|
|
||||||
m_aircraft->multiMotor7->setEnabled(false);
|
|
||||||
m_aircraft->multiMotor8->setEnabled(false);
|
|
||||||
m_aircraft->triYawChannel->setEnabled(false);
|
|
||||||
m_aircraft->mrRollMixLevel->setValue(100);
|
|
||||||
m_aircraft->mrPitchMixLevel->setValue(100);
|
|
||||||
m_aircraft->mrYawMixLevel->setValue(50);
|
|
||||||
} else if (frameType == "Hexa" || frameType == "Hexacopter") {
|
|
||||||
m_aircraft->aircraftType->setCurrentIndex(m_aircraft->aircraftType->findText("Multirotor"));
|
|
||||||
m_aircraft->multirotorFrameType->setCurrentIndex(m_aircraft->multirotorFrameType->findText("Hexacopter"));
|
|
||||||
quad->setElementId("quad-hexa");
|
|
||||||
m_aircraft->multiMotor4->setEnabled(true);
|
|
||||||
m_aircraft->multiMotor5->setEnabled(true);
|
|
||||||
m_aircraft->multiMotor6->setEnabled(true);
|
|
||||||
m_aircraft->multiMotor7->setEnabled(false);
|
|
||||||
m_aircraft->multiMotor8->setEnabled(false);
|
|
||||||
m_aircraft->triYawChannel->setEnabled(false);
|
|
||||||
m_aircraft->mrRollMixLevel->setValue(50);
|
|
||||||
m_aircraft->mrPitchMixLevel->setValue(33);
|
|
||||||
m_aircraft->mrYawMixLevel->setValue(33);
|
|
||||||
} else if (frameType == "Octo" || frameType == "Octocopter") {
|
|
||||||
m_aircraft->aircraftType->setCurrentIndex(m_aircraft->aircraftType->findText("Multirotor"));
|
|
||||||
m_aircraft->multirotorFrameType->setCurrentIndex(m_aircraft->multirotorFrameType->findText("Octocopter"));
|
|
||||||
quad->setElementId("quad-octo");
|
|
||||||
m_aircraft->multiMotor4->setEnabled(true);
|
|
||||||
m_aircraft->multiMotor5->setEnabled(true);
|
|
||||||
m_aircraft->multiMotor6->setEnabled(true);
|
|
||||||
m_aircraft->multiMotor7->setEnabled(true);
|
|
||||||
m_aircraft->multiMotor8->setEnabled(true);
|
|
||||||
m_aircraft->triYawChannel->setEnabled(false);
|
|
||||||
m_aircraft->mrRollMixLevel->setValue(33);
|
|
||||||
m_aircraft->mrPitchMixLevel->setValue(33);
|
|
||||||
m_aircraft->mrYawMixLevel->setValue(25);
|
|
||||||
} else if (frameType == "HexaX" || frameType == "Hexacopter X" ) {
|
|
||||||
m_aircraft->aircraftType->setCurrentIndex(m_aircraft->aircraftType->findText("Multirotor"));
|
|
||||||
m_aircraft->multirotorFrameType->setCurrentIndex(m_aircraft->multirotorFrameType->findText("Hexacopter X"));
|
|
||||||
quad->setElementId("quad-hexa-H");
|
|
||||||
m_aircraft->multiMotor4->setEnabled(true);
|
|
||||||
m_aircraft->multiMotor5->setEnabled(true);
|
|
||||||
m_aircraft->multiMotor6->setEnabled(true);
|
|
||||||
m_aircraft->multiMotor7->setEnabled(false);
|
|
||||||
m_aircraft->multiMotor8->setEnabled(false);
|
|
||||||
m_aircraft->triYawChannel->setEnabled(false);
|
|
||||||
m_aircraft->mrRollMixLevel->setValue(33);
|
|
||||||
m_aircraft->mrPitchMixLevel->setValue(50);
|
|
||||||
m_aircraft->mrYawMixLevel->setValue(33);
|
|
||||||
|
|
||||||
} else if (frameType == "OctoV" || frameType == "Octocopter V") {
|
|
||||||
m_aircraft->aircraftType->setCurrentIndex(m_aircraft->aircraftType->findText("Multirotor"));
|
|
||||||
m_aircraft->multirotorFrameType->setCurrentIndex(m_aircraft->multirotorFrameType->findText("Octocopter V"));
|
|
||||||
quad->setElementId("quad-octo-v");
|
|
||||||
m_aircraft->multiMotor4->setEnabled(true);
|
|
||||||
m_aircraft->multiMotor5->setEnabled(true);
|
|
||||||
m_aircraft->multiMotor6->setEnabled(true);
|
|
||||||
m_aircraft->multiMotor7->setEnabled(true);
|
|
||||||
m_aircraft->multiMotor8->setEnabled(true);
|
|
||||||
m_aircraft->triYawChannel->setEnabled(false);
|
|
||||||
m_aircraft->mrRollMixLevel->setValue(25);
|
|
||||||
m_aircraft->mrPitchMixLevel->setValue(25);
|
|
||||||
m_aircraft->mrYawMixLevel->setValue(25);
|
|
||||||
|
|
||||||
} else if (frameType == "OctoCoaxP" || frameType == "Octo Coax +") {
|
|
||||||
m_aircraft->aircraftType->setCurrentIndex(m_aircraft->aircraftType->findText("Multirotor"));
|
|
||||||
m_aircraft->multirotorFrameType->setCurrentIndex(m_aircraft->multirotorFrameType->findText("Octo Coax +"));
|
|
||||||
quad->setElementId("octo-coax-P");
|
|
||||||
m_aircraft->multiMotor4->setEnabled(true);
|
|
||||||
m_aircraft->multiMotor5->setEnabled(true);
|
|
||||||
m_aircraft->multiMotor6->setEnabled(true);
|
|
||||||
m_aircraft->multiMotor7->setEnabled(true);
|
|
||||||
m_aircraft->multiMotor8->setEnabled(true);
|
|
||||||
m_aircraft->triYawChannel->setEnabled(false);
|
|
||||||
m_aircraft->mrRollMixLevel->setValue(100);
|
|
||||||
m_aircraft->mrPitchMixLevel->setValue(100);
|
|
||||||
m_aircraft->mrYawMixLevel->setValue(50);
|
|
||||||
|
|
||||||
} else if (frameType == "OctoCoaxX" || frameType == "Octo Coax X") {
|
|
||||||
m_aircraft->aircraftType->setCurrentIndex(m_aircraft->aircraftType->findText("Multirotor"));
|
|
||||||
m_aircraft->multirotorFrameType->setCurrentIndex(m_aircraft->multirotorFrameType->findText("Octo Coax X"));
|
|
||||||
quad->setElementId("octo-coax-X");
|
|
||||||
m_aircraft->multiMotor4->setEnabled(true);
|
|
||||||
m_aircraft->multiMotor5->setEnabled(true);
|
|
||||||
m_aircraft->multiMotor6->setEnabled(true);
|
|
||||||
m_aircraft->multiMotor7->setEnabled(true);
|
|
||||||
m_aircraft->multiMotor8->setEnabled(true);
|
|
||||||
m_aircraft->triYawChannel->setEnabled(false);
|
|
||||||
m_aircraft->mrRollMixLevel->setValue(50);
|
|
||||||
m_aircraft->mrPitchMixLevel->setValue(50);
|
|
||||||
m_aircraft->mrYawMixLevel->setValue(50);
|
|
||||||
|
|
||||||
} else if (frameType == "HexaCoax" || frameType == "Hexacopter Y6") {
|
|
||||||
m_aircraft->aircraftType->setCurrentIndex(m_aircraft->aircraftType->findText("Multirotor"));
|
|
||||||
m_aircraft->multirotorFrameType->setCurrentIndex(m_aircraft->multirotorFrameType->findText("Hexacopter Y6"));
|
|
||||||
quad->setElementId("hexa-coax");
|
|
||||||
m_aircraft->multiMotor4->setEnabled(true);
|
|
||||||
m_aircraft->multiMotor5->setEnabled(true);
|
|
||||||
m_aircraft->multiMotor6->setEnabled(true);
|
|
||||||
m_aircraft->multiMotor7->setEnabled(false);
|
|
||||||
m_aircraft->multiMotor8->setEnabled(false);
|
|
||||||
m_aircraft->triYawChannel->setEnabled(false);
|
|
||||||
m_aircraft->mrRollMixLevel->setValue(100);
|
|
||||||
m_aircraft->mrPitchMixLevel->setValue(50);
|
|
||||||
m_aircraft->mrYawMixLevel->setValue(66);
|
|
||||||
|
|
||||||
} else if (frameType == "Tri" || frameType == "Tricopter Y") {
|
|
||||||
m_aircraft->aircraftType->setCurrentIndex(m_aircraft->aircraftType->findText("Multirotor"));
|
|
||||||
m_aircraft->multirotorFrameType->setCurrentIndex(m_aircraft->multirotorFrameType->findText("Tricopter Y"));
|
|
||||||
quad->setElementId("tri");
|
|
||||||
m_aircraft->multiMotor4->setEnabled(false);
|
|
||||||
m_aircraft->multiMotor5->setEnabled(false);
|
|
||||||
m_aircraft->multiMotor6->setEnabled(false);
|
|
||||||
m_aircraft->multiMotor7->setEnabled(false);
|
|
||||||
m_aircraft->multiMotor8->setEnabled(false);
|
|
||||||
m_aircraft->triYawChannel->setEnabled(true);
|
|
||||||
|
|
||||||
}
|
|
||||||
m_aircraft->quadShape->setSceneRect(quad->boundingRect());
|
|
||||||
m_aircraft->quadShape->fitInView(quad, Qt::KeepAspectRatio);
|
|
||||||
setDirty(dirty);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
Reset the contents of a field
|
|
||||||
*/
|
|
||||||
void ConfigAirframeWidget::resetField(UAVObjectField * field)
|
|
||||||
{
|
|
||||||
for (unsigned int i=0;i<field->getNumElements();i++) {
|
|
||||||
field->setValue(0,i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
Reset actuator values
|
|
||||||
*/
|
|
||||||
void ConfigAirframeWidget::resetActuators()
|
|
||||||
{
|
|
||||||
UAVDataObject* obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("ActuatorSettings")));
|
|
||||||
Q_ASSERT(obj);
|
|
||||||
QList<UAVObjectField*> fieldList = obj->getFields();
|
|
||||||
// Reset all assignements first:
|
|
||||||
foreach (UAVObjectField* field, fieldList) {
|
|
||||||
// NOTE: we assume that all options in ActuatorSettings are a channel assignement
|
|
||||||
// except for the options called "ChannelXXX"
|
|
||||||
if (field->getUnits().contains("channel")) {
|
|
||||||
field->setValue(field->getOptions().last());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
Setup Elevator/Aileron/Rudder airframe.
|
|
||||||
|
|
||||||
If both Aileron channels are set to 'None' (EasyStar), do Pitch/Rudder mixing
|
|
||||||
|
|
||||||
Returns False if impossible to create the mixer.
|
|
||||||
*/
|
|
||||||
bool ConfigAirframeWidget::setupFrameFixedWing()
|
|
||||||
{
|
|
||||||
// Check coherence:
|
|
||||||
// - At least Pitch and either Roll or Yaw
|
|
||||||
if (m_aircraft->fwEngineChannel->currentText() == "None" ||
|
|
||||||
m_aircraft->fwElevator1Channel->currentText() == "None" ||
|
|
||||||
((m_aircraft->fwAileron1Channel->currentText() == "None") &&
|
|
||||||
(m_aircraft->fwRudder1Channel->currentText() == "None"))) {
|
|
||||||
// TODO: explain the problem in the UI
|
|
||||||
m_aircraft->fwStatusLabel->setText("ERROR: check channel assignment");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
// Now setup the channels:
|
|
||||||
resetActuators();
|
|
||||||
|
|
||||||
UAVDataObject* obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("ActuatorSettings")));
|
|
||||||
Q_ASSERT(obj);
|
|
||||||
|
|
||||||
// Elevator
|
|
||||||
UAVObjectField *field = obj->getField("FixedWingPitch1");
|
|
||||||
Q_ASSERT(field);
|
|
||||||
field->setValue(m_aircraft->fwElevator1Channel->currentText());
|
|
||||||
field = obj->getField("FixedWingPitch2");
|
|
||||||
Q_ASSERT(field);
|
|
||||||
field->setValue(m_aircraft->fwElevator2Channel->currentText());
|
|
||||||
// Aileron
|
|
||||||
field = obj->getField("FixedWingRoll1");
|
|
||||||
Q_ASSERT(field);
|
|
||||||
field->setValue(m_aircraft->fwAileron1Channel->currentText());
|
|
||||||
field = obj->getField("FixedWingRoll2");
|
|
||||||
Q_ASSERT(field);
|
|
||||||
field->setValue(m_aircraft->fwAileron2Channel->currentText());
|
|
||||||
// Rudder
|
|
||||||
field = obj->getField("FixedWingYaw1");
|
|
||||||
Q_ASSERT(field);
|
|
||||||
field->setValue(m_aircraft->fwRudder1Channel->currentText());
|
|
||||||
// Throttle
|
|
||||||
field = obj->getField("FixedWingThrottle");
|
|
||||||
Q_ASSERT(field);
|
|
||||||
field->setValue(m_aircraft->fwEngineChannel->currentText());
|
|
||||||
|
|
||||||
obj->updated();
|
|
||||||
|
|
||||||
obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
|
|
||||||
Q_ASSERT(obj);
|
|
||||||
// ... and compute the matrix:
|
|
||||||
// In order to make code a bit nicer, we assume:
|
|
||||||
// - Channel dropdowns start with 'None', then 0 to 7
|
|
||||||
|
|
||||||
// 1. Assign the servo/motor/none for each channel
|
|
||||||
// Disable all
|
|
||||||
foreach(QString mixer, mixerTypes) {
|
|
||||||
field = obj->getField(mixer);
|
|
||||||
Q_ASSERT(field);
|
|
||||||
field->setValue("Disabled");
|
|
||||||
}
|
|
||||||
// and set only the relevant channels:
|
|
||||||
// Engine
|
|
||||||
int eng = m_aircraft->fwEngineChannel->currentIndex()-1;
|
|
||||||
field = obj->getField(mixerTypes.at(eng));
|
|
||||||
field->setValue("Motor");
|
|
||||||
field = obj->getField(mixerVectors.at(eng));
|
|
||||||
// First of all reset the vector
|
|
||||||
resetField(field);
|
|
||||||
int ti = field->getElementNames().indexOf("ThrottleCurve1");
|
|
||||||
field->setValue(127, ti);
|
|
||||||
|
|
||||||
// Rudder
|
|
||||||
eng = m_aircraft->fwRudder1Channel->currentIndex()-1;
|
|
||||||
// eng will be -1 if rudder is set to "None"
|
|
||||||
if (eng > -1) {
|
|
||||||
field = obj->getField(mixerTypes.at(eng));
|
|
||||||
field->setValue("Servo");
|
|
||||||
field = obj->getField(mixerVectors.at(eng));
|
|
||||||
resetField(field);
|
|
||||||
ti = field->getElementNames().indexOf("Yaw");
|
|
||||||
field->setValue(127, ti);
|
|
||||||
} // Else: we have no rudder, only ailerons, we're fine with it.
|
|
||||||
|
|
||||||
// Ailerons
|
|
||||||
eng = m_aircraft->fwAileron1Channel->currentIndex()-1;
|
|
||||||
if (eng > -1) {
|
|
||||||
field = obj->getField(mixerTypes.at(eng));
|
|
||||||
field->setValue("Servo");
|
|
||||||
field = obj->getField(mixerVectors.at(eng));
|
|
||||||
resetField(field);
|
|
||||||
ti = field->getElementNames().indexOf("Roll");
|
|
||||||
field->setValue(127, ti);
|
|
||||||
// Only set Aileron 2 if Aileron 1 is defined
|
|
||||||
eng = m_aircraft->fwAileron2Channel->currentIndex()-1;
|
|
||||||
if (eng > -1) {
|
|
||||||
field = obj->getField(mixerTypes.at(eng));
|
|
||||||
field->setValue("Servo");
|
|
||||||
field = obj->getField(mixerVectors.at(eng));
|
|
||||||
resetField(field);
|
|
||||||
ti = field->getElementNames().indexOf("Roll");
|
|
||||||
field->setValue(127, ti);
|
|
||||||
}
|
|
||||||
} // Else we have no ailerons. Our consistency check guarantees we have
|
|
||||||
// rudder in this case, so we're fine with it too.
|
|
||||||
|
|
||||||
// Elevator
|
|
||||||
eng = m_aircraft->fwElevator1Channel->currentIndex()-1;
|
|
||||||
field = obj->getField(mixerTypes.at(eng));
|
|
||||||
field->setValue("Servo");
|
|
||||||
field = obj->getField(mixerVectors.at(eng));
|
|
||||||
resetField(field);
|
|
||||||
ti = field->getElementNames().indexOf("Pitch");
|
|
||||||
field->setValue(127, ti);
|
|
||||||
// Only set Elevator 2 if it is defined
|
|
||||||
eng = m_aircraft->fwElevator2Channel->currentIndex()-1;
|
|
||||||
if (eng > -1) {
|
|
||||||
field = obj->getField(mixerTypes.at(eng));
|
|
||||||
field->setValue("Servo");
|
|
||||||
field = obj->getField(mixerVectors.at(eng));
|
|
||||||
resetField(field);
|
|
||||||
ti = field->getElementNames().indexOf("Pitch");
|
|
||||||
field->setValue(127, ti);
|
|
||||||
}
|
|
||||||
|
|
||||||
obj->updated();
|
|
||||||
m_aircraft->fwStatusLabel->setText("Mixer generated");
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
Setup Elevon
|
|
||||||
*/
|
|
||||||
bool ConfigAirframeWidget::setupFrameElevon()
|
|
||||||
{
|
|
||||||
// Check coherence:
|
|
||||||
// - At least Aileron1 and Aileron 2, and engine
|
|
||||||
if (m_aircraft->fwEngineChannel->currentText() == "None" ||
|
|
||||||
m_aircraft->fwAileron1Channel->currentText() == "None" ||
|
|
||||||
m_aircraft->fwAileron2Channel->currentText() == "None") {
|
|
||||||
// TODO: explain the problem in the UI
|
|
||||||
m_aircraft->fwStatusLabel->setText("ERROR: check channel assignment");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
resetActuators();
|
|
||||||
UAVDataObject* obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("ActuatorSettings")));
|
|
||||||
Q_ASSERT(obj);
|
|
||||||
|
|
||||||
// Elevons
|
|
||||||
UAVObjectField *field = obj->getField("FixedWingRoll1");
|
|
||||||
Q_ASSERT(field);
|
|
||||||
field->setValue(m_aircraft->fwAileron1Channel->currentText());
|
|
||||||
field = obj->getField("FixedWingRoll2");
|
|
||||||
Q_ASSERT(field);
|
|
||||||
field->setValue(m_aircraft->fwAileron2Channel->currentText());
|
|
||||||
// Rudder 1 (can be None)
|
|
||||||
field = obj->getField("FixedWingYaw1");
|
|
||||||
Q_ASSERT(field);
|
|
||||||
field->setValue(m_aircraft->fwRudder1Channel->currentText());
|
|
||||||
// Rudder 2 (can be None)
|
|
||||||
field = obj->getField("FixedWingYaw2");
|
|
||||||
Q_ASSERT(field);
|
|
||||||
field->setValue(m_aircraft->fwRudder2Channel->currentText());
|
|
||||||
// Throttle
|
|
||||||
field = obj->getField("FixedWingThrottle");
|
|
||||||
Q_ASSERT(field);
|
|
||||||
field->setValue(m_aircraft->fwEngineChannel->currentText());
|
|
||||||
|
|
||||||
obj->updated();
|
|
||||||
|
|
||||||
// Save the curve:
|
|
||||||
obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
|
|
||||||
Q_ASSERT(obj);
|
|
||||||
// ... and compute the matrix:
|
|
||||||
// In order to make code a bit nicer, we assume:
|
|
||||||
// - Channel dropdowns start with 'None', then 0 to 7
|
|
||||||
|
|
||||||
// 1. Assign the servo/motor/none for each channel
|
|
||||||
// Disable all
|
|
||||||
foreach(QString mixer, mixerTypes) {
|
|
||||||
field = obj->getField(mixer);
|
|
||||||
Q_ASSERT(field);
|
|
||||||
field->setValue("Disabled");
|
|
||||||
}
|
|
||||||
// and set only the relevant channels:
|
|
||||||
// Engine
|
|
||||||
int eng = m_aircraft->fwEngineChannel->currentIndex()-1;
|
|
||||||
field = obj->getField(mixerTypes.at(eng));
|
|
||||||
field->setValue("Motor");
|
|
||||||
field = obj->getField(mixerVectors.at(eng));
|
|
||||||
// First of all reset the vector
|
|
||||||
resetField(field);
|
|
||||||
int ti = field->getElementNames().indexOf("ThrottleCurve1");
|
|
||||||
field->setValue(127, ti);
|
|
||||||
|
|
||||||
// Rudder 1
|
|
||||||
eng = m_aircraft->fwRudder1Channel->currentIndex()-1;
|
|
||||||
// eng will be -1 if rudder 1 is set to "None"
|
|
||||||
if (eng > -1) {
|
|
||||||
field = obj->getField(mixerTypes.at(eng));
|
|
||||||
field->setValue("Servo");
|
|
||||||
field = obj->getField(mixerVectors.at(eng));
|
|
||||||
resetField(field);
|
|
||||||
ti = field->getElementNames().indexOf("Yaw");
|
|
||||||
field->setValue(127, ti);
|
|
||||||
} // Else: we have no rudder, only elevons, we're fine with it.
|
|
||||||
|
|
||||||
// Rudder 2
|
|
||||||
eng = m_aircraft->fwRudder2Channel->currentIndex()-1;
|
|
||||||
// eng will be -1 if rudder 2 is set to "None"
|
|
||||||
if (eng > -1) {
|
|
||||||
field = obj->getField(mixerTypes.at(eng));
|
|
||||||
field->setValue("Servo");
|
|
||||||
field = obj->getField(mixerVectors.at(eng));
|
|
||||||
resetField(field);
|
|
||||||
ti = field->getElementNames().indexOf("Yaw");
|
|
||||||
field->setValue(-127, ti);
|
|
||||||
} // Else: we have no rudder, only elevons, we're fine with it.
|
|
||||||
|
|
||||||
eng = m_aircraft->fwAileron1Channel->currentIndex()-1;
|
|
||||||
if (eng > -1) {
|
|
||||||
field = obj->getField(mixerTypes.at(eng));
|
|
||||||
field->setValue("Servo");
|
|
||||||
field = obj->getField(mixerVectors.at(eng));
|
|
||||||
resetField(field);
|
|
||||||
ti = field->getElementNames().indexOf("Pitch");
|
|
||||||
field->setValue((double)m_aircraft->elevonSlider2->value()*1.27, ti);
|
|
||||||
ti = field->getElementNames().indexOf("Roll");
|
|
||||||
field->setValue((double)m_aircraft->elevonSlider1->value()*1.27,ti);
|
|
||||||
}
|
|
||||||
|
|
||||||
eng = m_aircraft->fwAileron2Channel->currentIndex()-1;
|
|
||||||
if (eng > -1) {
|
|
||||||
field = obj->getField(mixerTypes.at(eng));
|
|
||||||
field->setValue("Servo");
|
|
||||||
field = obj->getField(mixerVectors.at(eng));
|
|
||||||
resetField(field);
|
|
||||||
ti = field->getElementNames().indexOf("Pitch");
|
|
||||||
field->setValue((double)m_aircraft->elevonSlider2->value()*1.27, ti);
|
|
||||||
ti = field->getElementNames().indexOf("Roll");
|
|
||||||
field->setValue(-(double)m_aircraft->elevonSlider1->value()*1.27,ti);
|
|
||||||
}
|
|
||||||
|
|
||||||
obj->updated();
|
|
||||||
m_aircraft->fwStatusLabel->setText("Mixer generated");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
Setup VTail
|
|
||||||
*/
|
|
||||||
bool ConfigAirframeWidget::setupFrameVtail()
|
|
||||||
{
|
|
||||||
// Check coherence:
|
|
||||||
// - At least Pitch1 and Pitch2, and engine
|
|
||||||
if (m_aircraft->fwEngineChannel->currentText() == "None" ||
|
|
||||||
m_aircraft->fwElevator1Channel->currentText() == "None" ||
|
|
||||||
m_aircraft->fwElevator2Channel->currentText() == "None") {
|
|
||||||
// TODO: explain the problem in the UI
|
|
||||||
m_aircraft->fwStatusLabel->setText("WARNING: check channel assignment");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
resetActuators();
|
|
||||||
UAVDataObject* obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("ActuatorSettings")));
|
|
||||||
Q_ASSERT(obj);
|
|
||||||
|
|
||||||
// Elevons
|
|
||||||
UAVObjectField *field = obj->getField("FixedWingPitch1");
|
|
||||||
Q_ASSERT(field);
|
|
||||||
field->setValue(m_aircraft->fwElevator1Channel->currentText());
|
|
||||||
field = obj->getField("FixedWingPitch2");
|
|
||||||
Q_ASSERT(field);
|
|
||||||
field->setValue(m_aircraft->fwElevator2Channel->currentText());
|
|
||||||
field = obj->getField("FixedWingRoll1");
|
|
||||||
Q_ASSERT(field);
|
|
||||||
field->setValue(m_aircraft->fwAileron1Channel->currentText());
|
|
||||||
field = obj->getField("FixedWingRoll2");
|
|
||||||
Q_ASSERT(field);
|
|
||||||
field->setValue(m_aircraft->fwAileron2Channel->currentText());
|
|
||||||
|
|
||||||
// Throttle
|
|
||||||
field = obj->getField("FixedWingThrottle");
|
|
||||||
Q_ASSERT(field);
|
|
||||||
field->setValue(m_aircraft->fwEngineChannel->currentText());
|
|
||||||
|
|
||||||
obj->updated();
|
|
||||||
|
|
||||||
obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
|
|
||||||
Q_ASSERT(obj);
|
|
||||||
// ... and compute the matrix:
|
|
||||||
// In order to make code a bit nicer, we assume:
|
|
||||||
// - Channel dropdowns start with 'None', then 0 to 7
|
|
||||||
|
|
||||||
// 1. Assign the servo/motor/none for each channel
|
|
||||||
// Disable all
|
|
||||||
foreach(QString mixer, mixerTypes) {
|
|
||||||
field = obj->getField(mixer);
|
|
||||||
Q_ASSERT(field);
|
|
||||||
field->setValue("Disabled");
|
|
||||||
}
|
|
||||||
// and set only the relevant channels:
|
|
||||||
// Engine
|
|
||||||
int eng = m_aircraft->fwEngineChannel->currentIndex()-1;
|
|
||||||
field = obj->getField(mixerTypes.at(eng));
|
|
||||||
field->setValue("Motor");
|
|
||||||
field = obj->getField(mixerVectors.at(eng));
|
|
||||||
// First of all reset the vector
|
|
||||||
resetField(field);
|
|
||||||
int ti = field->getElementNames().indexOf("ThrottleCurve1");
|
|
||||||
field->setValue(127, ti);
|
|
||||||
|
|
||||||
eng = m_aircraft->fwAileron1Channel->currentIndex()-1;
|
|
||||||
if (eng > -1) {
|
|
||||||
field = obj->getField(mixerTypes.at(eng));
|
|
||||||
field->setValue("Servo");
|
|
||||||
field = obj->getField(mixerVectors.at(eng));
|
|
||||||
resetField(field);
|
|
||||||
ti = field->getElementNames().indexOf("Roll");
|
|
||||||
field->setValue(127,ti);
|
|
||||||
}
|
|
||||||
|
|
||||||
eng = m_aircraft->fwAileron2Channel->currentIndex()-1;
|
|
||||||
if (eng > -1) {
|
|
||||||
field = obj->getField(mixerTypes.at(eng));
|
|
||||||
field->setValue("Servo");
|
|
||||||
field = obj->getField(mixerVectors.at(eng));
|
|
||||||
resetField(field);
|
|
||||||
ti = field->getElementNames().indexOf("Roll");
|
|
||||||
field->setValue(-127,ti);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Now compute the VTail
|
|
||||||
eng = m_aircraft->fwElevator1Channel->currentIndex()-1;
|
|
||||||
field = obj->getField(mixerTypes.at(eng));
|
|
||||||
field->setValue("Servo");
|
|
||||||
field = obj->getField(mixerVectors.at(eng));
|
|
||||||
resetField(field);
|
|
||||||
ti = field->getElementNames().indexOf("Pitch");
|
|
||||||
field->setValue((double)m_aircraft->elevonSlider2->value()*1.27, ti);
|
|
||||||
ti = field->getElementNames().indexOf("Yaw");
|
|
||||||
field->setValue((double)m_aircraft->elevonSlider1->value()*1.27,ti);
|
|
||||||
|
|
||||||
eng = m_aircraft->fwElevator2Channel->currentIndex()-1;
|
|
||||||
field = obj->getField(mixerTypes.at(eng));
|
|
||||||
field->setValue("Servo");
|
|
||||||
field = obj->getField(mixerVectors.at(eng));
|
|
||||||
resetField(field);
|
|
||||||
ti = field->getElementNames().indexOf("Pitch");
|
|
||||||
field->setValue((double)m_aircraft->elevonSlider2->value()*1.27, ti);
|
|
||||||
ti = field->getElementNames().indexOf("Yaw");
|
|
||||||
field->setValue(-(double)m_aircraft->elevonSlider1->value()*1.27,ti);
|
|
||||||
|
|
||||||
obj->updated();
|
|
||||||
m_aircraft->fwStatusLabel->setText("Mixer generated");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
Set up a complete mixer, taking a table of factors. The factors
|
|
||||||
shoudl mainly be +/- 1 factors, since they will be weighted by the
|
|
||||||
value of the Pitch/Roll/Yaw sliders.
|
|
||||||
|
|
||||||
Example:
|
|
||||||
double xMixer [8][3] = {
|
|
||||||
P R Y
|
|
||||||
{ 1, 1, -1}, Motor 1
|
|
||||||
{ 1, -1, 1}, Motor 2
|
|
||||||
{-1, -1, -1}, Motor 3
|
|
||||||
{-1, 1, 1}, ...
|
|
||||||
{ 0, 0, 0},
|
|
||||||
{ 0, 0, 0},
|
|
||||||
{ 0, 0, 0},
|
|
||||||
{ 0, 0, 0}
|
|
||||||
};
|
|
||||||
*/
|
|
||||||
bool ConfigAirframeWidget::setupMixer(double mixerFactors[8][3])
|
|
||||||
{
|
|
||||||
qDebug()<<"Mixer factors";
|
|
||||||
qDebug()<<mixerFactors[0][0]<<" "<<mixerFactors[0][1]<<" "<<mixerFactors[0][2];
|
|
||||||
qDebug()<<mixerFactors[1][0]<<" "<<mixerFactors[1][1]<<" "<<mixerFactors[1][2];
|
|
||||||
qDebug()<<mixerFactors[2][0]<<" "<<mixerFactors[2][1]<<" "<<mixerFactors[2][2];
|
|
||||||
qDebug()<<mixerFactors[3][0]<<" "<<mixerFactors[3][1]<<" "<<mixerFactors[3][2];
|
|
||||||
qDebug()<<mixerFactors[4][0]<<" "<<mixerFactors[4][1]<<" "<<mixerFactors[4][2];
|
|
||||||
qDebug()<<mixerFactors[5][0]<<" "<<mixerFactors[5][1]<<" "<<mixerFactors[5][2];
|
|
||||||
qDebug()<<mixerFactors[6][0]<<" "<<mixerFactors[6][1]<<" "<<mixerFactors[6][2];
|
|
||||||
qDebug()<<mixerFactors[7][0]<<" "<<mixerFactors[7][1]<<" "<<mixerFactors[7][2];
|
|
||||||
|
|
||||||
UAVObjectField *field;
|
|
||||||
QList<QComboBox*> mmList;
|
|
||||||
mmList << m_aircraft->multiMotor1 << m_aircraft->multiMotor2 << m_aircraft->multiMotor3
|
|
||||||
<< m_aircraft->multiMotor4 << m_aircraft->multiMotor5 << m_aircraft->multiMotor6
|
|
||||||
<< m_aircraft->multiMotor7 << m_aircraft->multiMotor8;
|
|
||||||
UAVDataObject *obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
|
|
||||||
// 1. Assign the servo/motor/none for each channel
|
|
||||||
// Disable all
|
|
||||||
foreach(QString mixer, mixerTypes) {
|
|
||||||
field = obj->getField(mixer);
|
|
||||||
Q_ASSERT(field);
|
|
||||||
field->setValue("Disabled");
|
|
||||||
}
|
|
||||||
// and enable only the relevant channels:
|
|
||||||
double pFactor = (double)m_aircraft->mrPitchMixLevel->value()/100;
|
|
||||||
double rFactor = (double)m_aircraft->mrRollMixLevel->value()/100;
|
|
||||||
double yFactor = (double)m_aircraft->mrYawMixLevel->value()/100;
|
|
||||||
qDebug()<<QString("pFactor=%0 rFactor=%1 yFactor=%2").arg(pFactor).arg(rFactor).arg(yFactor);
|
|
||||||
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]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// obj->updated();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
Help function: setupQuadMotor
|
|
||||||
*/
|
|
||||||
void ConfigAirframeWidget::setupQuadMotor(int channel, double pitch, double roll, double yaw)
|
|
||||||
{
|
|
||||||
qDebug()<<QString("Setup quad motor channel=%0 pitch=%1 roll=%2 yaw=%3").arg(channel).arg(pitch).arg(roll).arg(yaw);
|
|
||||||
UAVDataObject* obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
|
|
||||||
Q_ASSERT(obj);
|
|
||||||
UAVObjectField *field = obj->getField(mixerTypes.at(channel));
|
|
||||||
field->setValue("Motor");
|
|
||||||
field = obj->getField(mixerVectors.at(channel));
|
|
||||||
// First of all reset the vector
|
|
||||||
resetField(field);
|
|
||||||
int ti = field->getElementNames().indexOf("ThrottleCurve1");
|
|
||||||
field->setValue(127, ti);
|
|
||||||
ti = field->getElementNames().indexOf("Roll");
|
|
||||||
field->setValue(roll*127,ti);
|
|
||||||
qDebug()<<"Set roll="<<roll*127;
|
|
||||||
ti = field->getElementNames().indexOf("Pitch");
|
|
||||||
field->setValue(pitch*127,ti);
|
|
||||||
qDebug()<<"Set pitch="<<pitch*127;
|
|
||||||
ti = field->getElementNames().indexOf("Yaw");
|
|
||||||
field->setValue(yaw*127,ti);
|
|
||||||
qDebug()<<"Set yaw="<<yaw*127;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
Helper function: setup motors. Takes a list of channel names in input.
|
|
||||||
*/
|
|
||||||
void ConfigAirframeWidget::setupMotors(QList<QString> motorList)
|
|
||||||
{
|
|
||||||
resetActuators();
|
|
||||||
UAVDataObject* obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("ActuatorSettings")));
|
|
||||||
Q_ASSERT(obj);
|
|
||||||
UAVObjectField *field;
|
|
||||||
QList<QComboBox*> mmList;
|
|
||||||
mmList << m_aircraft->multiMotor1 << m_aircraft->multiMotor2 << m_aircraft->multiMotor3
|
|
||||||
<< m_aircraft->multiMotor4 << m_aircraft->multiMotor5 << m_aircraft->multiMotor6
|
|
||||||
<< m_aircraft->multiMotor7 << m_aircraft->multiMotor8;
|
|
||||||
foreach (QString motor, motorList) {
|
|
||||||
field = obj->getField(motor);
|
|
||||||
field->setValue(mmList.takeFirst()->currentText());
|
|
||||||
}
|
|
||||||
//obj->updated(); // Save...
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
Set up a Quad-X or Quad-P
|
|
||||||
*/
|
|
||||||
bool ConfigAirframeWidget::setupQuad(bool pLayout)
|
|
||||||
{
|
|
||||||
// Check coherence:
|
|
||||||
// - Four engines have to be defined
|
|
||||||
if (m_aircraft->multiMotor1->currentText() == "None" ||
|
|
||||||
m_aircraft->multiMotor2->currentText() == "None" ||
|
|
||||||
m_aircraft->multiMotor3->currentText() == "None" ||
|
|
||||||
m_aircraft->multiMotor4->currentText() == "None") {
|
|
||||||
m_aircraft->mrStatusLabel->setText("ERROR: Assign 4 motor channels");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
QList<QString> motorList;
|
|
||||||
if (pLayout) {
|
|
||||||
motorList << "VTOLMotorN" << "VTOLMotorE" << "VTOLMotorS"
|
|
||||||
<< "VTOLMotorW";
|
|
||||||
} else {
|
|
||||||
motorList << "VTOLMotorNW" << "VTOLMotorNE" << "VTOLMotorSE"
|
|
||||||
<< "VTOLMotorSW";
|
|
||||||
}
|
|
||||||
setupMotors(motorList);
|
|
||||||
|
|
||||||
// Now, setup the mixer:
|
|
||||||
// Motor 1 to 4, X Layout:
|
|
||||||
// pitch roll yaw
|
|
||||||
// {0.5 ,0.5 ,-0.5 //Front left motor (CW)
|
|
||||||
// {0.5 ,-0.5 ,0.5 //Front right motor(CCW)
|
|
||||||
// {-0.5 ,-0.5 ,-0.5 //rear right motor (CW)
|
|
||||||
// {-0.5 ,0.5 ,0.5 //Rear left motor (CCW)
|
|
||||||
double xMixer [8][3] = {
|
|
||||||
{ 1, 1, -1},
|
|
||||||
{ 1, -1, 1},
|
|
||||||
{-1, -1, -1},
|
|
||||||
{-1, 1, 1},
|
|
||||||
{ 0, 0, 0},
|
|
||||||
{ 0, 0, 0},
|
|
||||||
{ 0, 0, 0},
|
|
||||||
{ 0, 0, 0}
|
|
||||||
};
|
|
||||||
//
|
|
||||||
// Motor 1 to 4, P Layout:
|
|
||||||
// pitch roll yaw
|
|
||||||
// {1 ,0 ,-0.5 //Front motor (CW)
|
|
||||||
// {0 ,-1 ,0.5 //Right motor(CCW)
|
|
||||||
// {-1 ,0 ,-0.5 //Rear motor (CW)
|
|
||||||
// {0 ,1 ,0.5 //Left motor (CCW)
|
|
||||||
double pMixer [8][3] = {
|
|
||||||
{ 1, 0, -1},
|
|
||||||
{ 0, -1, 1},
|
|
||||||
{-1, 0, -1},
|
|
||||||
{ 0, 1, 1},
|
|
||||||
{ 0, 0, 0},
|
|
||||||
{ 0, 0, 0},
|
|
||||||
{ 0, 0, 0},
|
|
||||||
{ 0, 0, 0}
|
|
||||||
};
|
|
||||||
|
|
||||||
if (pLayout) {
|
|
||||||
setupMixer(pMixer);
|
|
||||||
} else {
|
|
||||||
setupMixer(xMixer);
|
|
||||||
}
|
|
||||||
m_aircraft->mrStatusLabel->setText("SUCCESS: Mixer Saved OK");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
Set up a Hexa-X or Hexa-P
|
|
||||||
*/
|
|
||||||
bool ConfigAirframeWidget::setupHexa(bool pLayout)
|
|
||||||
{
|
|
||||||
// Check coherence:
|
|
||||||
// - Four engines have to be defined
|
|
||||||
if (m_aircraft->multiMotor1->currentText() == "None" ||
|
|
||||||
m_aircraft->multiMotor2->currentText() == "None" ||
|
|
||||||
m_aircraft->multiMotor3->currentText() == "None" ||
|
|
||||||
m_aircraft->multiMotor4->currentText() == "None" ||
|
|
||||||
m_aircraft->multiMotor5->currentText() == "None" ||
|
|
||||||
m_aircraft->multiMotor6->currentText() == "None") {
|
|
||||||
m_aircraft->mrStatusLabel->setText("ERROR: Assign 6 motor channels");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
QList<QString> motorList;
|
|
||||||
if (pLayout) {
|
|
||||||
motorList << "VTOLMotorN" << "VTOLMotorNE" << "VTOLMotorSE"
|
|
||||||
<< "VTOLMotorS" << "VTOLMotorSW" << "VTOLMotorNW";
|
|
||||||
} else {
|
|
||||||
motorList << "VTOLMotorNE" << "VTOLMotorE" << "VTOLMotorSE"
|
|
||||||
<< "VTOLMotorSW" << "VTOLMotorW" << "VTOLMotorNW";
|
|
||||||
}
|
|
||||||
setupMotors(motorList);
|
|
||||||
|
|
||||||
// and set only the relevant channels:
|
|
||||||
|
|
||||||
// Motor 1 to 6, P Layout:
|
|
||||||
// pitch roll yaw
|
|
||||||
// 1 { 0.3 , 0 ,-0.3 // N CW
|
|
||||||
// 2 { 0.3 ,-0.5 , 0.3 // NE CCW
|
|
||||||
// 3 {-0.3 ,-0.5 ,-0.3 // SE CW
|
|
||||||
// 4 {-0.3 , 0 , 0.3 // S CCW
|
|
||||||
// 5 {-0.3 , 0.5 ,-0.3 // SW CW
|
|
||||||
// 6 { 0.3 , 0.5 , 0.3 // NW CCW
|
|
||||||
|
|
||||||
double pMixer [8][3] = {
|
|
||||||
{ 1, 0, -1},
|
|
||||||
{ 1, -1, 1},
|
|
||||||
{-1, -1, -1},
|
|
||||||
{-1, 0, 1},
|
|
||||||
{-1, 1, -1},
|
|
||||||
{ 1, 1, 1},
|
|
||||||
{ 0, 0, 0},
|
|
||||||
{ 0, 0, 0}
|
|
||||||
};
|
|
||||||
|
|
||||||
//
|
|
||||||
// Motor 1 to 6, X Layout:
|
|
||||||
// 1 [ 0.5, -0.3, -0.3 ] NE
|
|
||||||
// 2 [ 0 , -0.3, 0.3 ] E
|
|
||||||
// 3 [ -0.5, -0.3, -0.3 ] SE
|
|
||||||
// 4 [ -0.5, 0.3, 0.3 ] SW
|
|
||||||
// 5 [ 0 , 0.3, -0.3 ] W
|
|
||||||
// 6 [ 0.5, 0.3, 0.3 ] NW
|
|
||||||
double xMixer [8][3] = {
|
|
||||||
{ 1, -1, -1},
|
|
||||||
{ 0, -1, 1},
|
|
||||||
{ -1, -1, -1},
|
|
||||||
{ -1, 1, 1},
|
|
||||||
{ 0, 1, -1},
|
|
||||||
{ 1, 1, 1},
|
|
||||||
{ 0, 0, 0},
|
|
||||||
{ 0, 0, 0}
|
|
||||||
};
|
|
||||||
|
|
||||||
if (pLayout) {
|
|
||||||
setupMixer(pMixer);
|
|
||||||
} else {
|
|
||||||
setupMixer(xMixer);
|
|
||||||
}
|
|
||||||
m_aircraft->mrStatusLabel->setText("SUCCESS: Mixer Saved OK");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
Updates the custom airframe settings based on the current airframe.
|
|
||||||
|
|
||||||
Note: does NOT ask for an object refresh itself!
|
|
||||||
*/
|
|
||||||
void ConfigAirframeWidget::updateCustomAirframeUI()
|
|
||||||
{
|
|
||||||
UAVDataObject* obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
|
|
||||||
UAVObjectField* field = obj->getField(QString("ThrottleCurve1"));
|
|
||||||
QList<double> curveValues;
|
|
||||||
// If the 1st element of the curve is <= -10, then the curve
|
|
||||||
// is a straight line (that's how the mixer works on the mainboard):
|
|
||||||
if (field->getValue(0).toInt() <= -10) {
|
|
||||||
m_aircraft->customThrottle1Curve->initLinearCurve(field->getNumElements(),(double)1);
|
|
||||||
} else {
|
|
||||||
double temp=0;
|
|
||||||
double value;
|
|
||||||
for (unsigned int i=0; i < field->getNumElements(); i++) {
|
|
||||||
value=field->getValue(i).toDouble();
|
|
||||||
temp+=value;
|
|
||||||
curveValues.append(value);
|
|
||||||
}
|
|
||||||
if(temp==0)
|
|
||||||
m_aircraft->customThrottle1Curve->initLinearCurve(field->getNumElements(),(double)1);
|
|
||||||
else
|
|
||||||
m_aircraft->customThrottle1Curve->initCurve(curveValues);
|
|
||||||
}
|
|
||||||
field = obj->getField(QString("ThrottleCurve2"));
|
|
||||||
curveValues.clear();;
|
|
||||||
// If the 1st element of the curve is <= -10, then the curve
|
|
||||||
// is a straight line (that's how the mixer works on the mainboard):
|
|
||||||
if (field->getValue(0).toInt() <= -10) {
|
|
||||||
m_aircraft->customThrottle2Curve->initLinearCurve(field->getNumElements(),(double)1);
|
|
||||||
} else {
|
|
||||||
for (unsigned int i=0; i < field->getNumElements(); i++) {
|
|
||||||
curveValues.append(field->getValue(i).toDouble());
|
|
||||||
}
|
|
||||||
m_aircraft->customThrottle2Curve->initCurve(curveValues);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update the table:
|
|
||||||
for (int i=0; i<8; i++) {
|
|
||||||
field = obj->getField(mixerTypes.at(i));
|
|
||||||
QComboBox* q = (QComboBox*)m_aircraft->customMixerTable->cellWidget(0,i);
|
|
||||||
QString s = field->getValue().toString();
|
|
||||||
q->setCurrentIndex(q->findText(s));
|
|
||||||
//bool en = (s != "Disabled");
|
|
||||||
field = obj->getField(mixerVectors.at(i));
|
|
||||||
int ti = field->getElementNames().indexOf("ThrottleCurve1");
|
|
||||||
m_aircraft->customMixerTable->item(1,i)->setText(field->getValue(ti).toString());
|
|
||||||
ti = field->getElementNames().indexOf("ThrottleCurve2");
|
|
||||||
m_aircraft->customMixerTable->item(2,i)->setText(field->getValue(ti).toString());
|
|
||||||
ti = field->getElementNames().indexOf("Roll");
|
|
||||||
m_aircraft->customMixerTable->item(3,i)->setText(field->getValue(ti).toString());
|
|
||||||
ti = field->getElementNames().indexOf("Pitch");
|
|
||||||
m_aircraft->customMixerTable->item(4,i)->setText(field->getValue(ti).toString());
|
|
||||||
ti = field->getElementNames().indexOf("Yaw");
|
|
||||||
m_aircraft->customMixerTable->item(5,i)->setText(field->getValue(ti).toString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
Sends the config to the board (airframe type)
|
|
||||||
|
|
||||||
We do all the tasks common to all airframes, or family of airframes, and
|
|
||||||
we call additional methods for specific frames, so that we do not have a code
|
|
||||||
that is too heavy.
|
|
||||||
*/
|
|
||||||
void ConfigAirframeWidget::updateObjectsFromWidgets()
|
|
||||||
{
|
|
||||||
qDebug()<<"updateObjectsFromWidgets";
|
|
||||||
QString airframeType = "Custom";
|
|
||||||
if (m_aircraft->aircraftType->currentText() == "Fixed Wing") {
|
|
||||||
// Save the curve (common to all Fixed wing frames)
|
|
||||||
UAVDataObject *obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
|
|
||||||
// Remove Feed Forward, it is pointless on a plane:
|
|
||||||
UAVObjectField* field = obj->getField(QString("FeedForward"));
|
|
||||||
field->setDouble(0);
|
|
||||||
field = obj->getField("ThrottleCurve1");
|
|
||||||
QList<double> curve = m_aircraft->fixedWingThrottle->getCurve();
|
|
||||||
for (int i=0;i<curve.length();i++) {
|
|
||||||
field->setValue(curve.at(i),i);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_aircraft->fixedWingType->currentText() == "Elevator aileron rudder" ) {
|
|
||||||
airframeType = "FixedWing";
|
|
||||||
setupFrameFixedWing();
|
|
||||||
} else if (m_aircraft->fixedWingType->currentText() == "Elevon") {
|
|
||||||
airframeType = "FixedWingElevon";
|
|
||||||
setupFrameElevon();
|
|
||||||
} else { // "Vtail"
|
|
||||||
airframeType = "FixedWingVtail";
|
|
||||||
setupFrameVtail();
|
|
||||||
}
|
|
||||||
// Now reflect those settings in the "Custom" panel as well
|
|
||||||
updateCustomAirframeUI();
|
|
||||||
} else if (m_aircraft->aircraftType->currentText() == "Multirotor") {
|
|
||||||
|
|
||||||
QList<QString> motorList;
|
|
||||||
|
|
||||||
// We can already setup the feedforward here, as it is common to all platforms
|
|
||||||
UAVDataObject* obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
|
|
||||||
UAVObjectField* field = obj->getField(QString("FeedForward"));
|
|
||||||
field->setDouble((double)m_aircraft->feedForwardSlider->value()/100);
|
|
||||||
field = obj->getField(QString("AccelTime"));
|
|
||||||
field->setDouble(m_aircraft->accelTime->value());
|
|
||||||
field = obj->getField(QString("DecelTime"));
|
|
||||||
field->setDouble(m_aircraft->decelTime->value());
|
|
||||||
field = obj->getField(QString("MaxAccel"));
|
|
||||||
field->setDouble(m_aircraft->maxAccelSlider->value());
|
|
||||||
|
|
||||||
// Curve is also common to all quads:
|
|
||||||
field = obj->getField("ThrottleCurve1");
|
|
||||||
QList<double> curve = m_aircraft->multiThrottleCurve->getCurve();
|
|
||||||
for (int i=0;i<curve.length();i++) {
|
|
||||||
field->setValue(curve.at(i),i);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_aircraft->multirotorFrameType->currentText() == "Quad +") {
|
|
||||||
airframeType = "QuadP";
|
|
||||||
setupQuad(true);
|
|
||||||
} else if (m_aircraft->multirotorFrameType->currentText() == "Quad X") {
|
|
||||||
airframeType = "QuadX";
|
|
||||||
setupQuad(false);
|
|
||||||
} else if (m_aircraft->multirotorFrameType->currentText() == "Hexacopter") {
|
|
||||||
airframeType = "Hexa";
|
|
||||||
setupHexa(true);
|
|
||||||
} else if (m_aircraft->multirotorFrameType->currentText() == "Octocopter") {
|
|
||||||
airframeType = "Octo";
|
|
||||||
if (m_aircraft->multiMotor1->currentText() == "None" ||
|
|
||||||
m_aircraft->multiMotor2->currentText() == "None" ||
|
|
||||||
m_aircraft->multiMotor3->currentText() == "None" ||
|
|
||||||
m_aircraft->multiMotor4->currentText() == "None" ||
|
|
||||||
m_aircraft->multiMotor5->currentText() == "None" ||
|
|
||||||
m_aircraft->multiMotor6->currentText() == "None" ||
|
|
||||||
m_aircraft->multiMotor7->currentText() == "None" ||
|
|
||||||
m_aircraft->multiMotor8->currentText() == "None") {
|
|
||||||
m_aircraft->mrStatusLabel->setText("ERROR: Assign 8 motor channels");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
motorList << "VTOLMotorN" << "VTOLMotorNE" << "VTOLMotorE" << "VTOLMotorSE"
|
|
||||||
<< "VTOLMotorS" << "VTOLMotorSW" << "VTOLMotorW" << "VTOLMotorNW";
|
|
||||||
setupMotors(motorList);
|
|
||||||
// Motor 1 to 8:
|
|
||||||
// pitch roll yaw
|
|
||||||
double mixer [8][3] = {
|
|
||||||
{ 1, 0, -1},
|
|
||||||
{ 1, -1, 1},
|
|
||||||
{ 0, -1, -1},
|
|
||||||
{ -1, -1, 1},
|
|
||||||
{ -1, 0, -1},
|
|
||||||
{ -1, 1, 1},
|
|
||||||
{ 0, 1, -1},
|
|
||||||
{ 1, 1, 1}
|
|
||||||
};
|
|
||||||
setupMixer(mixer);
|
|
||||||
m_aircraft->mrStatusLabel->setText("SUCCESS: Mixer Saved OK");
|
|
||||||
|
|
||||||
} else if (m_aircraft->multirotorFrameType->currentText() == "Hexacopter X") {
|
|
||||||
airframeType = "HexaX";
|
|
||||||
setupHexa(false);
|
|
||||||
} else if (m_aircraft->multirotorFrameType->currentText() == "Octocopter V") {
|
|
||||||
airframeType = "OctoV";
|
|
||||||
if (m_aircraft->multiMotor1->currentText() == "None" ||
|
|
||||||
m_aircraft->multiMotor2->currentText() == "None" ||
|
|
||||||
m_aircraft->multiMotor3->currentText() == "None" ||
|
|
||||||
m_aircraft->multiMotor4->currentText() == "None" ||
|
|
||||||
m_aircraft->multiMotor5->currentText() == "None" ||
|
|
||||||
m_aircraft->multiMotor6->currentText() == "None" ||
|
|
||||||
m_aircraft->multiMotor7->currentText() == "None" ||
|
|
||||||
m_aircraft->multiMotor8->currentText() == "None") {
|
|
||||||
m_aircraft->mrStatusLabel->setText("ERROR: Assign 8 motor channels");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
motorList << "VTOLMotorN" << "VTOLMotorNE" << "VTOLMotorE" << "VTOLMotorSE"
|
|
||||||
<< "VTOLMotorS" << "VTOLMotorSW" << "VTOLMotorW" << "VTOLMotorNW";
|
|
||||||
setupMotors(motorList);
|
|
||||||
// Motor 1 to 8:
|
|
||||||
// IMPORTANT: Assumes evenly spaced engines
|
|
||||||
// pitch roll yaw
|
|
||||||
double mixer [8][3] = {
|
|
||||||
{ 0.33, -1, -1},
|
|
||||||
{ 1 , -1, 1},
|
|
||||||
{ -1 , -1, -1},
|
|
||||||
{ -0.33, -1, 1},
|
|
||||||
{ -0.33, 1, -1},
|
|
||||||
{ -1 , 1, 1},
|
|
||||||
{ 1 , 1, -1},
|
|
||||||
{ 0.33, 1, 1}
|
|
||||||
};
|
|
||||||
setupMixer(mixer);
|
|
||||||
m_aircraft->mrStatusLabel->setText("SUCCESS: Mixer Saved OK");
|
|
||||||
|
|
||||||
} else if (m_aircraft->multirotorFrameType->currentText() == "Octo Coax +") {
|
|
||||||
airframeType = "OctoCoaxP";
|
|
||||||
if (m_aircraft->multiMotor1->currentText() == "None" ||
|
|
||||||
m_aircraft->multiMotor2->currentText() == "None" ||
|
|
||||||
m_aircraft->multiMotor3->currentText() == "None" ||
|
|
||||||
m_aircraft->multiMotor4->currentText() == "None" ||
|
|
||||||
m_aircraft->multiMotor5->currentText() == "None" ||
|
|
||||||
m_aircraft->multiMotor6->currentText() == "None" ||
|
|
||||||
m_aircraft->multiMotor7->currentText() == "None" ||
|
|
||||||
m_aircraft->multiMotor8->currentText() == "None") {
|
|
||||||
m_aircraft->mrStatusLabel->setText("ERROR: Assign 8 motor channels");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
motorList << "VTOLMotorN" << "VTOLMotorNE" << "VTOLMotorE" << "VTOLMotorSE"
|
|
||||||
<< "VTOLMotorS" << "VTOLMotorSW" << "VTOLMotorW" << "VTOLMotorNW";
|
|
||||||
setupMotors(motorList);
|
|
||||||
// Motor 1 to 8:
|
|
||||||
// pitch roll yaw
|
|
||||||
double mixer [8][3] = {
|
|
||||||
{ 1, 0, -1},
|
|
||||||
{ 1, 0, 1},
|
|
||||||
{ 0, -1, -1},
|
|
||||||
{ 0, -1, 1},
|
|
||||||
{ -1, 0, -1},
|
|
||||||
{ -1, 0, 1},
|
|
||||||
{ 0, 1, -1},
|
|
||||||
{ 0, 1, 1}
|
|
||||||
};
|
|
||||||
setupMixer(mixer);
|
|
||||||
m_aircraft->mrStatusLabel->setText("SUCCESS: Mixer Saved OK");
|
|
||||||
|
|
||||||
} else if (m_aircraft->multirotorFrameType->currentText() == "Octo Coax X") {
|
|
||||||
airframeType = "OctoCoaxX";
|
|
||||||
if (m_aircraft->multiMotor1->currentText() == "None" ||
|
|
||||||
m_aircraft->multiMotor2->currentText() == "None" ||
|
|
||||||
m_aircraft->multiMotor3->currentText() == "None" ||
|
|
||||||
m_aircraft->multiMotor4->currentText() == "None" ||
|
|
||||||
m_aircraft->multiMotor5->currentText() == "None" ||
|
|
||||||
m_aircraft->multiMotor6->currentText() == "None" ||
|
|
||||||
m_aircraft->multiMotor7->currentText() == "None" ||
|
|
||||||
m_aircraft->multiMotor8->currentText() == "None") {
|
|
||||||
m_aircraft->mrStatusLabel->setText("ERROR: Assign 8 motor channels");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
motorList << "VTOLMotorNW" << "VTOLMotorN" << "VTOLMotorNE" << "VTOLMotorE"
|
|
||||||
<< "VTOLMotorSE" << "VTOLMotorS" << "VTOLMotorSW" << "VTOLMotorW";
|
|
||||||
setupMotors(motorList);
|
|
||||||
// Motor 1 to 8:
|
|
||||||
// pitch roll yaw
|
|
||||||
double mixer [8][3] = {
|
|
||||||
{ 1, 1, -1},
|
|
||||||
{ 1, 1, 1},
|
|
||||||
{ 1, -1, -1},
|
|
||||||
{ 1, -1, 1},
|
|
||||||
{ -1, -1, -1},
|
|
||||||
{ -1, -1, 1},
|
|
||||||
{ -1, 1, -1},
|
|
||||||
{ -1, 1, 1}
|
|
||||||
};
|
|
||||||
setupMixer(mixer);
|
|
||||||
m_aircraft->mrStatusLabel->setText("SUCCESS: Mixer Saved OK");
|
|
||||||
|
|
||||||
} else if (m_aircraft->multirotorFrameType->currentText() == "Hexacopter Y6") {
|
|
||||||
airframeType = "HexaCoax";
|
|
||||||
if (m_aircraft->multiMotor1->currentText() == "None" ||
|
|
||||||
m_aircraft->multiMotor2->currentText() == "None" ||
|
|
||||||
m_aircraft->multiMotor3->currentText() == "None" ||
|
|
||||||
m_aircraft->multiMotor4->currentText() == "None" ||
|
|
||||||
m_aircraft->multiMotor5->currentText() == "None" ||
|
|
||||||
m_aircraft->multiMotor6->currentText() == "None" ) {
|
|
||||||
m_aircraft->mrStatusLabel->setText("ERROR: Assign 6 motor channels");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
motorList << "VTOLMotorNW" << "VTOLMotorW" << "VTOLMotorNE" << "VTOLMotorE"
|
|
||||||
<< "VTOLMotorS" << "VTOLMotorSE";
|
|
||||||
setupMotors(motorList);
|
|
||||||
|
|
||||||
// Motor 1 to 6, Y6 Layout:
|
|
||||||
// pitch roll yaw
|
|
||||||
double mixer [8][3] = {
|
|
||||||
{ 0.5, 1, -1},
|
|
||||||
{ 0.5, 1, 1},
|
|
||||||
{ 0.5, -1, -1},
|
|
||||||
{ 0.5, -1, 1},
|
|
||||||
{ -1, 0, -1},
|
|
||||||
{ -1, 0, 1},
|
|
||||||
{ 0, 0, 0},
|
|
||||||
{ 0, 0, 0}
|
|
||||||
};
|
|
||||||
setupMixer(mixer);
|
|
||||||
m_aircraft->mrStatusLabel->setText("SUCCESS: Mixer Saved OK");
|
|
||||||
|
|
||||||
} else if (m_aircraft->multirotorFrameType->currentText() == "Tricopter Y") {
|
|
||||||
airframeType = "Tri";
|
|
||||||
if (m_aircraft->multiMotor1->currentText() == "None" ||
|
|
||||||
m_aircraft->multiMotor2->currentText() == "None" ||
|
|
||||||
m_aircraft->multiMotor3->currentText() == "None" ) {
|
|
||||||
m_aircraft->mrStatusLabel->setText("ERROR: Assign 3 motor channels");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (m_aircraft->triYawChannel->currentText() == "None") {
|
|
||||||
m_aircraft->mrStatusLabel->setText("Error: Assign a Yaw channel");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
motorList << "VTOLMotorNW" << "VTOLMotorNE" << "VTOLMotorS";
|
|
||||||
setupMotors(motorList);
|
|
||||||
obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("ActuatorSettings")));
|
|
||||||
Q_ASSERT(obj);
|
|
||||||
field = obj->getField("FixedWingYaw1");
|
|
||||||
field->setValue(m_aircraft->triYawChannel->currentText());
|
|
||||||
|
|
||||||
// Motor 1 to 6, Y6 Layout:
|
|
||||||
// pitch roll yaw
|
|
||||||
double mixer [8][3] = {
|
|
||||||
{ 0.5, 1, 0},
|
|
||||||
{ 0.5, -1, 0},
|
|
||||||
{ -1, 0, 0},
|
|
||||||
{ 0, 0, 0},
|
|
||||||
{ 0, 0, 0},
|
|
||||||
{ 0, 0, 0},
|
|
||||||
{ 0, 0, 0},
|
|
||||||
{ 0, 0, 0}
|
|
||||||
};
|
|
||||||
setupMixer(mixer);
|
|
||||||
|
|
||||||
int eng = m_aircraft->triYawChannel->currentIndex()-1;
|
|
||||||
obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
|
|
||||||
field = obj->getField(mixerTypes.at(eng));
|
|
||||||
field->setValue("Servo");
|
|
||||||
field = obj->getField(mixerVectors.at(eng));
|
|
||||||
resetField(field);
|
|
||||||
int ti = field->getElementNames().indexOf("Yaw");
|
|
||||||
field->setValue(127,ti);
|
|
||||||
|
|
||||||
m_aircraft->mrStatusLabel->setText("SUCCESS: Mixer Saved OK");
|
|
||||||
|
|
||||||
}
|
|
||||||
// Now reflect those settings in the "Custom" panel as well
|
|
||||||
updateCustomAirframeUI();
|
|
||||||
|
|
||||||
} else if (m_aircraft->aircraftType->currentText() == "Helicopter") {
|
|
||||||
airframeType = "HeliCP";
|
|
||||||
m_aircraft->widget_3->sendccpmUpdate();
|
|
||||||
} else {
|
|
||||||
airframeType = "Custom";
|
|
||||||
|
|
||||||
UAVDataObject* obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
|
|
||||||
UAVObjectField* field = obj->getField(QString("FeedForward"));
|
|
||||||
|
|
||||||
// Curve is also common to all quads:
|
|
||||||
field = obj->getField("ThrottleCurve1");
|
|
||||||
QList<double> curve = m_aircraft->customThrottle1Curve->getCurve();
|
|
||||||
for (int i=0;i<curve.length();i++) {
|
|
||||||
field->setValue(curve.at(i),i);
|
|
||||||
}
|
|
||||||
|
|
||||||
field = obj->getField("ThrottleCurve2");
|
|
||||||
curve.clear();
|
|
||||||
curve = m_aircraft->customThrottle2Curve->getCurve();
|
|
||||||
for (int i=0;i<curve.length();i++) {
|
|
||||||
field->setValue(curve.at(i),i);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update the table:
|
|
||||||
for (int i=0; i<8; i++) {
|
|
||||||
field = obj->getField(mixerTypes.at(i));
|
|
||||||
QComboBox* q = (QComboBox*)m_aircraft->customMixerTable->cellWidget(0,i);
|
|
||||||
field->setValue(q->currentText());
|
|
||||||
field = obj->getField(mixerVectors.at(i));
|
|
||||||
int ti = field->getElementNames().indexOf("ThrottleCurve1");
|
|
||||||
field->setValue(m_aircraft->customMixerTable->item(1,i)->text(),ti);
|
|
||||||
ti = field->getElementNames().indexOf("ThrottleCurve2");
|
|
||||||
field->setValue(m_aircraft->customMixerTable->item(2,i)->text(),ti);
|
|
||||||
ti = field->getElementNames().indexOf("Roll");
|
|
||||||
field->setValue(m_aircraft->customMixerTable->item(3,i)->text(),ti);
|
|
||||||
ti = field->getElementNames().indexOf("Pitch");
|
|
||||||
field->setValue(m_aircraft->customMixerTable->item(4,i)->text(),ti);
|
|
||||||
ti = field->getElementNames().indexOf("Yaw");
|
|
||||||
field->setValue(m_aircraft->customMixerTable->item(5,i)->text(),ti);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
UAVDataObject* obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("SystemSettings")));
|
|
||||||
UAVObjectField* field = obj->getField(QString("AirframeType"));
|
|
||||||
field->setValue(airframeType);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void ConfigAirframeWidget::openHelp()
|
|
||||||
{
|
|
||||||
|
|
||||||
QDesktopServices::openUrl( QUrl("http://wiki.openpilot.org/display/Doc/Airframe+configuration", QUrl::StrictMode) );
|
|
||||||
}
|
|
||||||
|
|
||||||
void ConfigAirframeWidget::addToDirtyMonitor()
|
|
||||||
{
|
|
||||||
addWidget(m_aircraft->customMixerTable);
|
|
||||||
addWidget(m_aircraft->customThrottle2Curve);
|
|
||||||
addWidget(m_aircraft->customThrottle1Curve);
|
|
||||||
addWidget(m_aircraft->multiThrottleCurve);
|
|
||||||
addWidget(m_aircraft->fixedWingThrottle);
|
|
||||||
addWidget(m_aircraft->fixedWingType);
|
|
||||||
addWidget(m_aircraft->feedForwardSlider);
|
|
||||||
addWidget(m_aircraft->accelTime);
|
|
||||||
addWidget(m_aircraft->decelTime);
|
|
||||||
addWidget(m_aircraft->maxAccelSlider);
|
|
||||||
addWidget(m_aircraft->multirotorFrameType);
|
|
||||||
addWidget(m_aircraft->multiMotor1);
|
|
||||||
addWidget(m_aircraft->multiMotor2);
|
|
||||||
addWidget(m_aircraft->multiMotor3);
|
|
||||||
addWidget(m_aircraft->multiMotor4);
|
|
||||||
addWidget(m_aircraft->multiMotor5);
|
|
||||||
addWidget(m_aircraft->multiMotor6);
|
|
||||||
addWidget(m_aircraft->multiMotor7);
|
|
||||||
addWidget(m_aircraft->multiMotor8);
|
|
||||||
addWidget(m_aircraft->triYawChannel);
|
|
||||||
addWidget(m_aircraft->aircraftType);
|
|
||||||
addWidget(m_aircraft->fwEngineChannel);
|
|
||||||
addWidget(m_aircraft->fwAileron1Channel);
|
|
||||||
addWidget(m_aircraft->fwAileron2Channel);
|
|
||||||
addWidget(m_aircraft->fwElevator1Channel);
|
|
||||||
addWidget(m_aircraft->fwElevator2Channel);
|
|
||||||
addWidget(m_aircraft->fwRudder1Channel);
|
|
||||||
addWidget(m_aircraft->fwRudder2Channel);
|
|
||||||
addWidget(m_aircraft->elevonSlider1);
|
|
||||||
addWidget(m_aircraft->elevonSlider2);
|
|
||||||
addWidget(m_aircraft->widget_3->m_ccpm->ccpmType);
|
|
||||||
addWidget(m_aircraft->widget_3->m_ccpm->ccpmTailChannel);
|
|
||||||
addWidget(m_aircraft->widget_3->m_ccpm->ccpmEngineChannel);
|
|
||||||
addWidget(m_aircraft->widget_3->m_ccpm->ccpmServoWChannel);
|
|
||||||
addWidget(m_aircraft->widget_3->m_ccpm->ccpmServoXChannel);
|
|
||||||
addWidget(m_aircraft->widget_3->m_ccpm->ccpmServoYChannel);
|
|
||||||
addWidget(m_aircraft->widget_3->m_ccpm->ccpmSingleServo);
|
|
||||||
addWidget(m_aircraft->widget_3->m_ccpm->ccpmServoZChannel);
|
|
||||||
addWidget(m_aircraft->widget_3->m_ccpm->ccpmAngleW);
|
|
||||||
addWidget(m_aircraft->widget_3->m_ccpm->ccpmAngleX);
|
|
||||||
addWidget(m_aircraft->widget_3->m_ccpm->ccpmCorrectionAngle);
|
|
||||||
addWidget(m_aircraft->widget_3->m_ccpm->ccpmAngleZ);
|
|
||||||
addWidget(m_aircraft->widget_3->m_ccpm->ccpmAngleY);
|
|
||||||
addWidget(m_aircraft->widget_3->m_ccpm->ccpmCollectivePassthrough);
|
|
||||||
addWidget(m_aircraft->widget_3->m_ccpm->ccpmLinkRoll);
|
|
||||||
addWidget(m_aircraft->widget_3->m_ccpm->ccpmLinkCyclic);
|
|
||||||
addWidget(m_aircraft->widget_3->m_ccpm->ccpmRevoSlider);
|
|
||||||
addWidget(m_aircraft->widget_3->m_ccpm->ccpmREVOspinBox);
|
|
||||||
addWidget(m_aircraft->widget_3->m_ccpm->ccpmCollectiveSlider);
|
|
||||||
addWidget(m_aircraft->widget_3->m_ccpm->ccpmCollectivespinBox);
|
|
||||||
addWidget(m_aircraft->widget_3->m_ccpm->ccpmCollectiveScale);
|
|
||||||
addWidget(m_aircraft->widget_3->m_ccpm->ccpmCollectiveScaleBox);
|
|
||||||
addWidget(m_aircraft->widget_3->m_ccpm->ccpmCyclicScale);
|
|
||||||
addWidget(m_aircraft->widget_3->m_ccpm->ccpmPitchScale);
|
|
||||||
addWidget(m_aircraft->widget_3->m_ccpm->ccpmPitchScaleBox);
|
|
||||||
addWidget(m_aircraft->widget_3->m_ccpm->ccpmRollScale);
|
|
||||||
addWidget(m_aircraft->widget_3->m_ccpm->ccpmRollScaleBox);
|
|
||||||
addWidget(m_aircraft->widget_3->m_ccpm->SwashLvlPositionSlider);
|
|
||||||
addWidget(m_aircraft->widget_3->m_ccpm->SwashLvlPositionSpinBox);
|
|
||||||
addWidget(m_aircraft->widget_3->m_ccpm->CurveType);
|
|
||||||
addWidget(m_aircraft->widget_3->m_ccpm->NumCurvePoints);
|
|
||||||
addWidget(m_aircraft->widget_3->m_ccpm->CurveValue1);
|
|
||||||
addWidget(m_aircraft->widget_3->m_ccpm->CurveValue2);
|
|
||||||
addWidget(m_aircraft->widget_3->m_ccpm->CurveValue3);
|
|
||||||
addWidget(m_aircraft->widget_3->m_ccpm->CurveToGenerate);
|
|
||||||
addWidget(m_aircraft->widget_3->m_ccpm->CurveSettings);
|
|
||||||
addWidget(m_aircraft->widget_3->m_ccpm->ThrottleCurve);
|
|
||||||
addWidget(m_aircraft->widget_3->m_ccpm->PitchCurve);
|
|
||||||
addWidget(m_aircraft->widget_3->m_ccpm->ccpmAdvancedSettingsTable);
|
|
||||||
}
|
|
||||||
|
|
@ -28,7 +28,7 @@
|
|||||||
#include "configahrswidget.h"
|
#include "configahrswidget.h"
|
||||||
#include "configgadgetwidget.h"
|
#include "configgadgetwidget.h"
|
||||||
|
|
||||||
#include "configairframewidget.h"
|
#include "ConfigVehicleTypeWidget.h"
|
||||||
#include "configccattitudewidget.h"
|
#include "configccattitudewidget.h"
|
||||||
#include "configinputwidget.h"
|
#include "configinputwidget.h"
|
||||||
#include "configoutputwidget.h"
|
#include "configoutputwidget.h"
|
||||||
@ -68,7 +68,7 @@ ConfigGadgetWidget::ConfigGadgetWidget(QWidget *parent) : QWidget(parent)
|
|||||||
qwd = new DefaultHwSettingsWidget(this);
|
qwd = new DefaultHwSettingsWidget(this);
|
||||||
ftw->insertTab(ConfigGadgetWidget::hardware, qwd, QIcon(":/configgadget/images/hw_config.png"), QString("HW Settings"));
|
ftw->insertTab(ConfigGadgetWidget::hardware, qwd, QIcon(":/configgadget/images/hw_config.png"), QString("HW Settings"));
|
||||||
|
|
||||||
qwd = new ConfigAirframeWidget(this);
|
qwd = new ConfigVehicleTypeWidget(this);
|
||||||
ftw->insertTab(ConfigGadgetWidget::aircraft, qwd, QIcon(":/configgadget/images/Airframe.png"), QString("Aircraft"));
|
ftw->insertTab(ConfigGadgetWidget::aircraft, qwd, QIcon(":/configgadget/images/Airframe.png"), QString("Aircraft"));
|
||||||
|
|
||||||
qwd = new ConfigInputWidget(this);
|
qwd = new ConfigInputWidget(this);
|
||||||
|
2751
ground/openpilotgcs/src/plugins/config/configvehicletypewidget.cpp
Normal file
2751
ground/openpilotgcs/src/plugins/config/configvehicletypewidget.cpp
Normal file
@ -0,0 +1,2751 @@
|
|||||||
|
/**
|
||||||
|
******************************************************************************
|
||||||
|
*
|
||||||
|
* @file configvehicletypewidget.cpp
|
||||||
|
* @author E. Lafargue & The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
|
||||||
|
* @addtogroup GCSPlugins GCS Plugins
|
||||||
|
* @{
|
||||||
|
* @addtogroup ConfigPlugin Config Plugin
|
||||||
|
* @{
|
||||||
|
* @brief Airframe configuration panel
|
||||||
|
*****************************************************************************/
|
||||||
|
/*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along
|
||||||
|
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
#include "configvehicletypewidget.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 "systemsettings.h"
|
||||||
|
#include "mixersettings.h"
|
||||||
|
#include "actuatorsettings.h"
|
||||||
|
#include <QEventLoop>
|
||||||
|
|
||||||
|
/**
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**********************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Constructor
|
||||||
|
*/
|
||||||
|
ConfigVehicleTypeWidget::ConfigVehicleTypeWidget(QWidget *parent) : ConfigTaskWidget(parent)
|
||||||
|
{
|
||||||
|
m_aircraft = new Ui_AircraftWidget();
|
||||||
|
m_aircraft->setupUi(this);
|
||||||
|
|
||||||
|
addApplySaveButtons(m_aircraft->saveAircraftToRAM,m_aircraft->saveAircraftToSD);
|
||||||
|
|
||||||
|
addUAVObject("SystemSettings");
|
||||||
|
addUAVObject("MixerSettings");
|
||||||
|
addUAVObject("ActuatorSettings");
|
||||||
|
|
||||||
|
|
||||||
|
ffTuningInProgress = false;
|
||||||
|
ffTuningPhase = false;
|
||||||
|
|
||||||
|
//Generate list of channels
|
||||||
|
QStringList channels;
|
||||||
|
channels << "None";
|
||||||
|
for (int i = 0; i < ActuatorSettings::CHANNELADDR_NUMELEM; i++) {
|
||||||
|
mixerTypes << QString("Mixer%1Type").arg(i+1);
|
||||||
|
mixerVectors << QString("Mixer%1Vector").arg(i+1);
|
||||||
|
channels << 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);
|
||||||
|
|
||||||
|
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"
|
||||||
|
|
||||||
|
QStringList groundVehicleTypes;
|
||||||
|
groundVehicleTypes << "Turnable (car)" << "Differential (tank)" << "Motorcycle";
|
||||||
|
// groundVehicleTypes << "Turnable (car)";
|
||||||
|
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(1); //Set default model to "Quad +"
|
||||||
|
|
||||||
|
// Now load all the channel assignements
|
||||||
|
//OLD STYLE: DO IT MANUALLY
|
||||||
|
// m_aircraft->triYawChannelBox->addItems(channels);
|
||||||
|
// m_aircraft->gvMotor1ChannelBox->addItems(channels);
|
||||||
|
// m_aircraft->gvMotor2ChannelBox->addItems(channels);
|
||||||
|
// m_aircraft->gvSteering1ChannelBox->addItems(channels);
|
||||||
|
// m_aircraft->gvSteering2ChannelBox->addItems(channels);
|
||||||
|
// m_aircraft->fwElevator1ChannelBox->addItems(channels);
|
||||||
|
// m_aircraft->fwElevator2ChannelBox->addItems(channels);
|
||||||
|
// m_aircraft->fwEngineChannelBox->addItems(channels);
|
||||||
|
// m_aircraft->fwRudder1ChannelBox->addItems(channels);
|
||||||
|
// m_aircraft->fwRudder2ChannelBox->addItems(channels);
|
||||||
|
// m_aircraft->fwAileron1ChannelBox->addItems(channels);
|
||||||
|
// m_aircraft->fwAileron2ChannelBox->addItems(channels);
|
||||||
|
|
||||||
|
//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(channels);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Setup the Multirotor picture in the Quad settings interface
|
||||||
|
m_aircraft->quadShape->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
||||||
|
m_aircraft->quadShape->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
||||||
|
QSvgRenderer *renderer = new QSvgRenderer();
|
||||||
|
renderer->load(QString(":/configgadget/images/quad-shapes.svg"));
|
||||||
|
quad = new QGraphicsSvgItem();
|
||||||
|
quad->setSharedRenderer(renderer);
|
||||||
|
quad->setElementId("quad-plus");
|
||||||
|
QGraphicsScene *scene = new QGraphicsScene(this);
|
||||||
|
scene->addItem(quad);
|
||||||
|
scene->setSceneRect(quad->boundingRect());
|
||||||
|
m_aircraft->quadShape->setScene(scene);
|
||||||
|
|
||||||
|
// Put combo boxes in line one of the custom mixer table:
|
||||||
|
UAVDataObject* obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
|
||||||
|
UAVObjectField* field = obj->getField(QString("Mixer1Type"));
|
||||||
|
QStringList list = field->getOptions();
|
||||||
|
for (int i=0;i<8;i++) {
|
||||||
|
QComboBox* qb = new QComboBox(m_aircraft->customMixerTable);
|
||||||
|
qb->addItems(list);
|
||||||
|
m_aircraft->customMixerTable->setCellWidget(0,i,qb);
|
||||||
|
}
|
||||||
|
|
||||||
|
SpinBoxDelegate *sbd = new SpinBoxDelegate();
|
||||||
|
for (int i=1;i<8; i++) {
|
||||||
|
m_aircraft->customMixerTable->setItemDelegateForRow(i, sbd);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Connect 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)));
|
||||||
|
|
||||||
|
//Connect throttle curve reset pushbuttons to reset functions
|
||||||
|
connect(m_aircraft->fwThrottleReset, SIGNAL(clicked()), this, SLOT(resetFwMixer()));
|
||||||
|
connect(m_aircraft->mrThrottleCurveReset, SIGNAL(clicked()), this, SLOT(resetMrMixer()));
|
||||||
|
connect(m_aircraft->gvThrottleCurve1Reset, SIGNAL(clicked()), this, SLOT(resetGvFrontMixer()));
|
||||||
|
connect(m_aircraft->gvThrottleCurve2Reset, SIGNAL(clicked()), this, SLOT(resetGvRearMixer()));
|
||||||
|
connect(m_aircraft->customReset1, SIGNAL(clicked()), this, SLOT(resetCt1Mixer()));
|
||||||
|
connect(m_aircraft->customReset2, SIGNAL(clicked()), this, SLOT(resetCt2Mixer()));
|
||||||
|
|
||||||
|
//Connect throttle curve manipulation points to output text
|
||||||
|
connect(m_aircraft->fixedWingThrottle, SIGNAL(curveUpdated(QList<double>,double)), this, SLOT(updateFwThrottleCurveValue(QList<double>,double)));
|
||||||
|
connect(m_aircraft->multiThrottleCurve, SIGNAL(curveUpdated(QList<double>,double)), this, SLOT(updateMrThrottleCurveValue(QList<double>,double)));
|
||||||
|
connect(m_aircraft->groundVehicleThrottle1, SIGNAL(curveUpdated(QList<double>,double)), this, SLOT(updateGvThrottle1CurveValue(QList<double>,double)));
|
||||||
|
connect(m_aircraft->groundVehicleThrottle2, SIGNAL(curveUpdated(QList<double>,double)), this, SLOT(updateGvThrottle2CurveValue(QList<double>,double)));
|
||||||
|
connect(m_aircraft->customThrottle1Curve, SIGNAL(curveUpdated(QList<double>,double)), this, SLOT(updateCustomThrottle1CurveValue(QList<double>,double)));
|
||||||
|
connect(m_aircraft->customThrottle2Curve, SIGNAL(curveUpdated(QList<double>,double)), this, SLOT(updateCustomThrottle2CurveValue(QList<double>,double)));
|
||||||
|
|
||||||
|
// connect(m_aircraft->fwAileron1Channel, SIGNAL(currentIndexChanged(int)), this, SLOT(toggleAileron2(int)));
|
||||||
|
// connect(m_aircraft->fwElevator1Channel, SIGNAL(currentIndexChanged(int)), this, SLOT(toggleElevator2(int)));
|
||||||
|
|
||||||
|
//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()));
|
||||||
|
|
||||||
|
//WHAT DOES THIS DO?
|
||||||
|
enableControls(false);
|
||||||
|
refreshWidgetsValues();
|
||||||
|
|
||||||
|
// Connect the help pushbutton
|
||||||
|
connect(m_aircraft->airframeHelp, SIGNAL(clicked()), this, SLOT(openHelp()));
|
||||||
|
addToDirtyMonitor();
|
||||||
|
|
||||||
|
//Initialize GUI tabs //MOVING THIS FROM THE END OF THIS FUNCTION CAN CAUSE RUNTIME ERRORS DUE TO setupMultiRotorUI. WHY?
|
||||||
|
setupMultiRotorUI( m_aircraft->multirotorFrameType->currentText() );
|
||||||
|
setupGroundVehicleUI( m_aircraft->groundVehicleType->currentText() );
|
||||||
|
setupFixedWingUI( m_aircraft->fixedWingType->currentText() );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Destructor
|
||||||
|
*/
|
||||||
|
ConfigVehicleTypeWidget::~ConfigVehicleTypeWidget()
|
||||||
|
{
|
||||||
|
// Do nothing
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Slot for switching the airframe type. We do it explicitely
|
||||||
|
rather than a signal in the UI, because we want to force a fitInView of the quad shapes.
|
||||||
|
This is because this method (fitinview) only works when the widget is shown.
|
||||||
|
*/
|
||||||
|
void 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<8;i++) {
|
||||||
|
m_aircraft->customMixerTable->setColumnWidth(i,(m_aircraft->customMixerTable->width()-
|
||||||
|
m_aircraft->customMixerTable->verticalHeader()->width())/8);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
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<8;i++) {
|
||||||
|
m_aircraft->customMixerTable->setColumnWidth(i,(m_aircraft->customMixerTable->width()-
|
||||||
|
m_aircraft->customMixerTable->verticalHeader()->width())/8);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Resize the GUI contents when the user changes the window size
|
||||||
|
*/
|
||||||
|
void ConfigVehicleTypeWidget::resizeEvent(QResizeEvent* event)
|
||||||
|
{
|
||||||
|
Q_UNUSED(event);
|
||||||
|
m_aircraft->quadShape->fitInView(quad, Qt::KeepAspectRatio);
|
||||||
|
// Make the custom table columns autostretch:
|
||||||
|
m_aircraft->customMixerTable->resizeColumnsToContents();
|
||||||
|
for (int i=0;i<8;i++) {
|
||||||
|
m_aircraft->customMixerTable->setColumnWidth(i,(m_aircraft->customMixerTable->width()-
|
||||||
|
m_aircraft->customMixerTable->verticalHeader()->width())/8);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void ConfigVehicleTypeWidget::toggleAileron2(int index)
|
||||||
|
{
|
||||||
|
if (index) {
|
||||||
|
m_aircraft->fwAileron2ChannelBox->setEnabled(true);
|
||||||
|
m_aircraft->fwAileron2Label->setEnabled(true);
|
||||||
|
} else {
|
||||||
|
m_aircraft->fwAileron2ChannelBox->setEnabled(false);
|
||||||
|
m_aircraft->fwAileron2Label->setEnabled(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ConfigVehicleTypeWidget::toggleElevator2(int index)
|
||||||
|
{
|
||||||
|
if (index) {
|
||||||
|
m_aircraft->fwElevator2ChannelBox->setEnabled(true);
|
||||||
|
m_aircraft->fwElevator2Label->setEnabled(true);
|
||||||
|
} else {
|
||||||
|
m_aircraft->fwElevator2ChannelBox->setEnabled(false);
|
||||||
|
m_aircraft->fwElevator2Label->setEnabled(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ConfigVehicleTypeWidget::toggleRudder2(int index)
|
||||||
|
{
|
||||||
|
if (index) {
|
||||||
|
m_aircraft->fwRudder2ChannelBox->setEnabled(true);
|
||||||
|
m_aircraft->fwRudder2Label->setEnabled(true);
|
||||||
|
} else {
|
||||||
|
m_aircraft->fwRudder2ChannelBox->setEnabled(false);
|
||||||
|
m_aircraft->fwRudder2Label->setEnabled(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////
|
||||||
|
/// Feed Forward Testing
|
||||||
|
/////////////////////////////////////////////////////////
|
||||||
|
/**
|
||||||
|
Enables and runs feed forward testing
|
||||||
|
*/
|
||||||
|
void ConfigVehicleTypeWidget::enableFFTest()
|
||||||
|
{
|
||||||
|
// Role:
|
||||||
|
// - Check if all three checkboxes are checked
|
||||||
|
// - Every other timer event: toggle engine from 45% to 55%
|
||||||
|
// - Every other time event: send FF settings to flight FW
|
||||||
|
if (m_aircraft->ffTestBox1->isChecked() &&
|
||||||
|
m_aircraft->ffTestBox2->isChecked() &&
|
||||||
|
m_aircraft->ffTestBox3->isChecked()) {
|
||||||
|
if (!ffTuningInProgress)
|
||||||
|
{
|
||||||
|
// Initiate tuning:
|
||||||
|
UAVDataObject* obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("ManualControlCommand")));
|
||||||
|
UAVObject::Metadata mdata = obj->getMetadata();
|
||||||
|
accInitialData = mdata;
|
||||||
|
mdata.flightAccess = UAVObject::ACCESS_READONLY;
|
||||||
|
obj->setMetadata(mdata);
|
||||||
|
}
|
||||||
|
// Depending on phase, either move actuator or send FF settings:
|
||||||
|
if (ffTuningPhase) {
|
||||||
|
// Send FF settings to the board
|
||||||
|
UAVDataObject* obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
|
||||||
|
UAVObjectField* field = obj->getField(QString("FeedForward"));
|
||||||
|
field->setDouble((double)m_aircraft->feedForwardSlider->value()/100);
|
||||||
|
field = obj->getField(QString("AccelTime"));
|
||||||
|
field->setDouble(m_aircraft->accelTime->value());
|
||||||
|
field = obj->getField(QString("DecelTime"));
|
||||||
|
field->setDouble(m_aircraft->decelTime->value());
|
||||||
|
field = obj->getField(QString("MaxAccel"));
|
||||||
|
field->setDouble(m_aircraft->maxAccelSlider->value());
|
||||||
|
obj->updated();
|
||||||
|
} else {
|
||||||
|
// Toggle motor state
|
||||||
|
UAVDataObject* obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("ManualControlCommand")));
|
||||||
|
double value = obj->getField("Throttle")->getDouble();
|
||||||
|
double target = (value < 0.5) ? 0.55 : 0.45;
|
||||||
|
obj->getField("Throttle")->setValue(target);
|
||||||
|
obj->updated();
|
||||||
|
}
|
||||||
|
ffTuningPhase = !ffTuningPhase;
|
||||||
|
ffTuningInProgress = true;
|
||||||
|
QTimer::singleShot(1000, this, SLOT(enableFFTest()));
|
||||||
|
} else {
|
||||||
|
// - If no: disarm timer, restore actuatorcommand metadata
|
||||||
|
// Disarm!
|
||||||
|
if (ffTuningInProgress) {
|
||||||
|
ffTuningInProgress = false;
|
||||||
|
UAVDataObject* obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("ManualControlCommand")));
|
||||||
|
UAVObject::Metadata mdata = obj->getMetadata();
|
||||||
|
mdata = accInitialData; // Restore metadata
|
||||||
|
obj->setMetadata(mdata);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Resets Fixed wing throttle mixer
|
||||||
|
*/
|
||||||
|
void ConfigVehicleTypeWidget::resetFwMixer()
|
||||||
|
{
|
||||||
|
UAVDataObject* obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
|
||||||
|
UAVObjectField* field = obj->getField(QString("ThrottleCurve1"));
|
||||||
|
resetMixer(m_aircraft->fixedWingThrottle, field->getNumElements(),1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Resets Multirotor throttle mixer
|
||||||
|
*/
|
||||||
|
void ConfigVehicleTypeWidget::resetMrMixer()
|
||||||
|
{
|
||||||
|
UAVDataObject* obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
|
||||||
|
UAVObjectField* field = obj->getField(QString("ThrottleCurve1"));
|
||||||
|
resetMixer(m_aircraft->multiThrottleCurve, field->getNumElements(),0.9);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Resets Ground vehicle front throttle mixer
|
||||||
|
*/
|
||||||
|
void ConfigVehicleTypeWidget::resetGvFrontMixer()
|
||||||
|
{
|
||||||
|
UAVDataObject* obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
|
||||||
|
UAVObjectField* field = obj->getField(QString("ThrottleCurve1"));
|
||||||
|
resetMixer(m_aircraft->groundVehicleThrottle1, field->getNumElements(),1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Resets Ground vehicle rear throttle mixer
|
||||||
|
*/
|
||||||
|
void ConfigVehicleTypeWidget::resetGvRearMixer()
|
||||||
|
{
|
||||||
|
UAVDataObject* obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
|
||||||
|
UAVObjectField* field = obj->getField(QString("ThrottleCurve2"));
|
||||||
|
resetMixer(m_aircraft->groundVehicleThrottle2, field->getNumElements(),1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Resets Custom throttle 1 mixer
|
||||||
|
*/
|
||||||
|
void ConfigVehicleTypeWidget::resetCt1Mixer()
|
||||||
|
{
|
||||||
|
UAVDataObject* obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
|
||||||
|
UAVObjectField* field = obj->getField(QString("ThrottleCurve1"));
|
||||||
|
resetMixer(m_aircraft->customThrottle1Curve, field->getNumElements(),1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Resets Custom throttle 2 mixer
|
||||||
|
*/
|
||||||
|
void ConfigVehicleTypeWidget::resetCt2Mixer()
|
||||||
|
{
|
||||||
|
UAVDataObject* obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
|
||||||
|
UAVObjectField* field = obj->getField(QString("ThrottleCurve2"));
|
||||||
|
resetMixer(m_aircraft->customThrottle2Curve, field->getNumElements(),1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Resets a mixer curve
|
||||||
|
*/
|
||||||
|
void ConfigVehicleTypeWidget::resetMixer(MixerCurveWidget *mixer, int numElements, double maxvalue)
|
||||||
|
{
|
||||||
|
// Setup all Throttle1 curves for all types of airframes
|
||||||
|
mixer->initLinearCurve((quint32)numElements,maxvalue);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Updates the currently moved fixed wing throttle curve item value
|
||||||
|
*/
|
||||||
|
void ConfigVehicleTypeWidget::updateFwThrottleCurveValue(QList<double> list, double value)
|
||||||
|
{
|
||||||
|
Q_UNUSED(list);
|
||||||
|
m_aircraft->fwThrottleCurveItemValue->setText(QString().sprintf("Val: %.2f",value));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Updates the currently moved multi-rotor throttle curve item value
|
||||||
|
*/
|
||||||
|
void ConfigVehicleTypeWidget::updateMrThrottleCurveValue(QList<double> list, double value)
|
||||||
|
{
|
||||||
|
Q_UNUSED(list);
|
||||||
|
m_aircraft->mrThrottleCurveItemValue->setText(QString().sprintf("Val: %.2f",value));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Updates the moved ground vehicle front throttle curve item value
|
||||||
|
*/
|
||||||
|
void ConfigVehicleTypeWidget::updateGvThrottle1CurveValue(QList<double> list, double value)
|
||||||
|
{
|
||||||
|
Q_UNUSED(list);
|
||||||
|
m_aircraft->gvThrottleCurve1ItemValue->setText(QString().sprintf("Val: %.2f",value));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Updates the moved ground vehicle rear throttle curve item value
|
||||||
|
*/
|
||||||
|
void ConfigVehicleTypeWidget::updateGvThrottle2CurveValue(QList<double> list, double value)
|
||||||
|
{
|
||||||
|
Q_UNUSED(list);
|
||||||
|
m_aircraft->gvThrottleCurve2ItemValue->setText(QString().sprintf("Val: %.2f",value));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Updates the currently moved custom throttle curve item value (Custom throttle 1)
|
||||||
|
*/
|
||||||
|
void ConfigVehicleTypeWidget::updateCustomThrottle1CurveValue(QList<double> list, double value)
|
||||||
|
{
|
||||||
|
Q_UNUSED(list);
|
||||||
|
m_aircraft->customThrottleCurve1Value->setText(QString().sprintf("Val: %.2f",value));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Updates the currently moved custom throttle curve item value (Custom throttle 2)
|
||||||
|
*/
|
||||||
|
void ConfigVehicleTypeWidget::updateCustomThrottle2CurveValue(QList<double> list, double value)
|
||||||
|
{
|
||||||
|
Q_UNUSED(list);
|
||||||
|
m_aircraft->customThrottleCurve2Value->setText(QString().sprintf("Val: %.2f",value));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************
|
||||||
|
* Aircraft settings
|
||||||
|
**************************/
|
||||||
|
/**
|
||||||
|
Refreshes the current value of the SystemSettings which holds the aircraft type
|
||||||
|
*/
|
||||||
|
void ConfigVehicleTypeWidget::refreshWidgetsValues()
|
||||||
|
{
|
||||||
|
if(!allObjectsUpdated())
|
||||||
|
return;
|
||||||
|
|
||||||
|
//WHAT DOES THIS DO?
|
||||||
|
bool dirty=isDirty(); //WHY IS THIS CALLED HERE AND THEN AGAIN SEVERAL LINES LATER IN setupAirframeUI()
|
||||||
|
|
||||||
|
// Get the Airframe type from the system settings:
|
||||||
|
UAVDataObject* obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("SystemSettings")));
|
||||||
|
Q_ASSERT(obj);
|
||||||
|
UAVObjectField *field = obj->getField(QString("AirframeType"));
|
||||||
|
Q_ASSERT(field);
|
||||||
|
// At this stage, we will need to have some hardcoded settings in this code, this
|
||||||
|
// is not ideal, but here you go.
|
||||||
|
QString frameType = field->getValue().toString();
|
||||||
|
setupAirframeUI(frameType);
|
||||||
|
|
||||||
|
obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
|
||||||
|
Q_ASSERT(obj);
|
||||||
|
field = obj->getField(QString("ThrottleCurve1"));
|
||||||
|
Q_ASSERT(field);
|
||||||
|
QList<double> curveValues;
|
||||||
|
// If the 1st element of the curve is <= -10, then the curve
|
||||||
|
// is a straight line (that's how the mixer works on the mainboard):
|
||||||
|
if (field->getValue(0).toInt() <= -10) {
|
||||||
|
m_aircraft->multiThrottleCurve->initLinearCurve(field->getNumElements(),(double)1);
|
||||||
|
m_aircraft->fixedWingThrottle->initLinearCurve(field->getNumElements(),(double)1);
|
||||||
|
m_aircraft->groundVehicleThrottle1->initLinearCurve(field->getNumElements(),(double)1);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
double temp=0;
|
||||||
|
double value;
|
||||||
|
for (unsigned int i=0; i < field->getNumElements(); i++) {
|
||||||
|
value=field->getValue(i).toDouble();
|
||||||
|
temp+=value;
|
||||||
|
curveValues.append(value);
|
||||||
|
}
|
||||||
|
if(temp==0)
|
||||||
|
{
|
||||||
|
m_aircraft->multiThrottleCurve->initLinearCurve(field->getNumElements(),0.9);
|
||||||
|
m_aircraft->fixedWingThrottle->initLinearCurve(field->getNumElements(),(double)1);
|
||||||
|
m_aircraft->groundVehicleThrottle1->initLinearCurve(field->getNumElements(),(double)1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_aircraft->multiThrottleCurve->initCurve(curveValues);
|
||||||
|
m_aircraft->fixedWingThrottle->initCurve(curveValues);
|
||||||
|
m_aircraft->groundVehicleThrottle1->initCurve(curveValues);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Setup all Throttle2 curves for all types of airframes //AT THIS MOMENT, THAT MEANS ONLY GROUND VEHICLES
|
||||||
|
Q_ASSERT(obj);
|
||||||
|
field = obj->getField(QString("ThrottleCurve2"));
|
||||||
|
Q_ASSERT(field);
|
||||||
|
curveValues.clear();
|
||||||
|
// If the 1st element of the curve is <= -10, then the curve
|
||||||
|
// is a straight line (that's how the mixer works on the mainboard):
|
||||||
|
if (field->getValue(0).toInt() <= -10) {
|
||||||
|
m_aircraft->groundVehicleThrottle2->initLinearCurve(field->getNumElements(),(double)1);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
double temp=0;
|
||||||
|
double value;
|
||||||
|
for (unsigned int i=0; i < field->getNumElements(); i++) {
|
||||||
|
value=field->getValue(i).toDouble();
|
||||||
|
temp+=value;
|
||||||
|
curveValues.append(value);
|
||||||
|
}
|
||||||
|
if(temp==0)
|
||||||
|
{
|
||||||
|
m_aircraft->groundVehicleThrottle2->initLinearCurve(field->getNumElements(),(double)1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_aircraft->groundVehicleThrottle2->initCurve(curveValues);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load the Settings for fixed wing frames:
|
||||||
|
if (frameType.startsWith("FixedWing")) {
|
||||||
|
|
||||||
|
// Retrieve fixed wing settings
|
||||||
|
if(1){
|
||||||
|
refreshFixedWingWidgetsValues(frameType);
|
||||||
|
}
|
||||||
|
// // Then retrieve how channels are setup
|
||||||
|
// obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("ActuatorSettings")));
|
||||||
|
// Q_ASSERT(obj);
|
||||||
|
// field = obj->getField(QString("FixedWingThrottle"));
|
||||||
|
// Q_ASSERT(field);
|
||||||
|
// m_aircraft->fwEngineChannelBox->setCurrentIndex(m_aircraft->fwEngineChannelBox->findText(field->getValue().toString()));
|
||||||
|
// field = obj->getField(QString("FixedWingRoll1"));
|
||||||
|
// Q_ASSERT(field);
|
||||||
|
// m_aircraft->fwAileron1ChannelBox->setCurrentIndex(m_aircraft->fwAileron1ChannelBox->findText(field->getValue().toString()));
|
||||||
|
// field = obj->getField(QString("FixedWingRoll2"));
|
||||||
|
// Q_ASSERT(field);
|
||||||
|
// m_aircraft->fwAileron2ChannelBox->setCurrentIndex(m_aircraft->fwAileron2ChannelBox->findText(field->getValue().toString()));
|
||||||
|
// field = obj->getField(QString("FixedWingPitch1"));
|
||||||
|
// Q_ASSERT(field);
|
||||||
|
// m_aircraft->fwElevator1ChannelBox->setCurrentIndex(m_aircraft->fwElevator1ChannelBox->findText(field->getValue().toString()));
|
||||||
|
// field = obj->getField(QString("FixedWingPitch2"));
|
||||||
|
// Q_ASSERT(field);
|
||||||
|
// m_aircraft->fwElevator2ChannelBox->setCurrentIndex(m_aircraft->fwElevator2ChannelBox->findText(field->getValue().toString()));
|
||||||
|
// field = obj->getField(QString("FixedWingYaw1"));
|
||||||
|
// Q_ASSERT(field);
|
||||||
|
// m_aircraft->fwRudder1ChannelBox->setCurrentIndex(m_aircraft->fwRudder1ChannelBox->findText(field->getValue().toString()));
|
||||||
|
// field = obj->getField(QString("FixedWingYaw2"));
|
||||||
|
// Q_ASSERT(field);
|
||||||
|
// m_aircraft->fwRudder2ChannelBox->setCurrentIndex(m_aircraft->fwRudder2ChannelBox->findText(field->getValue().toString()));
|
||||||
|
//
|
||||||
|
// if (frameType == "FixedWingElevon") {
|
||||||
|
// // If the airframe is elevon, restore the slider setting
|
||||||
|
// // Find the channel number for Elevon1 (FixedWingRoll1)
|
||||||
|
// obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
|
||||||
|
// Q_ASSERT(obj);
|
||||||
|
// int chMixerNumber = m_aircraft->fwAileron1ChannelBox->currentIndex()-1;
|
||||||
|
// if (chMixerNumber >= 0) { // If for some reason the actuators were incoherent, we might fail here, hence the check.
|
||||||
|
// field = obj->getField(mixerVectors.at(chMixerNumber));
|
||||||
|
// int ti = field->getElementNames().indexOf("Roll");
|
||||||
|
// m_aircraft->elevonSlider1->setValue(field->getDouble(ti)*100);
|
||||||
|
// ti = field->getElementNames().indexOf("Pitch");
|
||||||
|
// m_aircraft->elevonSlider2->setValue(field->getDouble(ti)*100);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// if (frameType == "FixedWingVtail") {
|
||||||
|
// obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
|
||||||
|
// Q_ASSERT(obj);
|
||||||
|
// int chMixerNumber = m_aircraft->fwElevator1ChannelBox->currentIndex()-1;
|
||||||
|
// if (chMixerNumber >=0) {
|
||||||
|
// field = obj->getField(mixerVectors.at(chMixerNumber));
|
||||||
|
// int ti = field->getElementNames().indexOf("Yaw");
|
||||||
|
// m_aircraft->elevonSlider1->setValue(field->getDouble(ti)*100);
|
||||||
|
// ti = field->getElementNames().indexOf("Pitch");
|
||||||
|
// m_aircraft->elevonSlider2->setValue(field->getDouble(ti)*100);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
} else if (frameType == "Tri" ||
|
||||||
|
frameType == "QuadX" || frameType == "QuadP" ||
|
||||||
|
frameType == "Hexa" || frameType == "HexaCoax" || frameType == "HexaX" ||
|
||||||
|
frameType == "Octo" || frameType == "OctoV" || frameType == "OctoCoaxP" || frameType == "OctoCoaxX" ) {
|
||||||
|
|
||||||
|
// Retrieve multirotor settings
|
||||||
|
if(1){
|
||||||
|
refreshMultiRotorWidgetsValues(frameType);
|
||||||
|
}
|
||||||
|
else{//
|
||||||
|
// //////////////////////////////////////////////////////////////////
|
||||||
|
// // Retrieve Multirotor settings
|
||||||
|
// //////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("ActuatorSettings")));
|
||||||
|
// Q_ASSERT(obj);
|
||||||
|
// if (frameType == "QuadP") {
|
||||||
|
// // Motors 1/2/3/4 are: N / E / S / W
|
||||||
|
// field = obj->getField(QString("VTOLMotorN"));
|
||||||
|
// Q_ASSERT(field);
|
||||||
|
// m_aircraft->multiMotor1->setCurrentIndex(m_aircraft->multiMotor1->findText(field->getValue().toString()));
|
||||||
|
// field = obj->getField(QString("VTOLMotorE"));
|
||||||
|
// Q_ASSERT(field);
|
||||||
|
// m_aircraft->multiMotor2->setCurrentIndex(m_aircraft->multiMotor2->findText(field->getValue().toString()));
|
||||||
|
// field = obj->getField(QString("VTOLMotorS"));
|
||||||
|
// Q_ASSERT(field);
|
||||||
|
// m_aircraft->multiMotor3->setCurrentIndex(m_aircraft->multiMotor3->findText(field->getValue().toString()));
|
||||||
|
// field = obj->getField(QString("VTOLMotorW"));
|
||||||
|
// Q_ASSERT(field);
|
||||||
|
// m_aircraft->multiMotor4->setCurrentIndex(m_aircraft->multiMotor4->findText(field->getValue().toString()));
|
||||||
|
//
|
||||||
|
// // Now, read the 1st mixer R/P/Y levels and initialize the mix sliders.
|
||||||
|
// // This assumes that all vectors are identical - if not, the user should use the
|
||||||
|
// // "custom" setting.
|
||||||
|
// obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
|
||||||
|
// Q_ASSERT(obj);
|
||||||
|
// int tmpVal= m_aircraft->multiMotor1->currentIndex()-1;
|
||||||
|
// // tmpVal will be -1 if value is set to "None"
|
||||||
|
// if (tmpVal > -1) {
|
||||||
|
// field = obj->getField(mixerVectors.at(tmpVal));
|
||||||
|
// int i = field->getElementNames().indexOf("Pitch");
|
||||||
|
// double val = field->getDouble(i)/1.27;
|
||||||
|
// m_aircraft->mrPitchMixLevel->setValue(val);
|
||||||
|
// i = field->getElementNames().indexOf("Yaw");
|
||||||
|
// val = (1-field->getDouble(i)/1.27);
|
||||||
|
// m_aircraft->mrYawMixLevel->setValue(val);
|
||||||
|
// tmpVal = m_aircraft->multiMotor2->currentIndex()-1;
|
||||||
|
// field = obj->getField(mixerVectors.at(tmpVal));
|
||||||
|
// i = field->getElementNames().indexOf("Roll");
|
||||||
|
// val = -field->getDouble(i)/1.27;
|
||||||
|
// m_aircraft->mrRollMixLevel->setValue(val);
|
||||||
|
// }
|
||||||
|
// } else if (frameType == "QuadX") {
|
||||||
|
// // Motors 1/2/3/4 are: NW / NE / SE / SW
|
||||||
|
// field = obj->getField(QString("VTOLMotorNW"));
|
||||||
|
// Q_ASSERT(field);
|
||||||
|
// m_aircraft->multiMotor1->setCurrentIndex(m_aircraft->multiMotor1->findText(field->getValue().toString()));
|
||||||
|
// field = obj->getField(QString("VTOLMotorNE"));
|
||||||
|
// Q_ASSERT(field);
|
||||||
|
// m_aircraft->multiMotor2->setCurrentIndex(m_aircraft->multiMotor2->findText(field->getValue().toString()));
|
||||||
|
// field = obj->getField(QString("VTOLMotorSE"));
|
||||||
|
// Q_ASSERT(field);
|
||||||
|
// m_aircraft->multiMotor3->setCurrentIndex(m_aircraft->multiMotor3->findText(field->getValue().toString()));
|
||||||
|
// field = obj->getField(QString("VTOLMotorSW"));
|
||||||
|
// Q_ASSERT(field);
|
||||||
|
// m_aircraft->multiMotor4->setCurrentIndex(m_aircraft->multiMotor4->findText(field->getValue().toString()));
|
||||||
|
//
|
||||||
|
// // Now, read the 1st mixer R/P/Y levels and initialize the mix sliders.
|
||||||
|
// // This assumes that all vectors are identical - if not, the user should use the
|
||||||
|
// // "custom" setting.
|
||||||
|
// obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
|
||||||
|
// Q_ASSERT(obj);
|
||||||
|
// int tmpVal= m_aircraft->multiMotor1->currentIndex()-1;
|
||||||
|
// // tmpVal will be -1 if value is set to "None"
|
||||||
|
// if (tmpVal > -1) {
|
||||||
|
// field = obj->getField(mixerVectors.at(tmpVal));
|
||||||
|
// int i = field->getElementNames().indexOf("Pitch");
|
||||||
|
// double val = field->getDouble(i)/1.27;
|
||||||
|
// m_aircraft->mrPitchMixLevel->setValue(val);
|
||||||
|
// i = field->getElementNames().indexOf("Yaw");
|
||||||
|
// val = 1-field->getDouble(i)/1.27;
|
||||||
|
// m_aircraft->mrYawMixLevel->setValue(val);
|
||||||
|
// i = field->getElementNames().indexOf("Roll");
|
||||||
|
// val = field->getDouble(i)/1.27;
|
||||||
|
// m_aircraft->mrRollMixLevel->setValue(val);
|
||||||
|
// }
|
||||||
|
// } else if (frameType == "Hexa") {
|
||||||
|
// // Motors 1/2/3 4/5/6 are: N / NE / SE / S / SW / NW
|
||||||
|
// field = obj->getField(QString("VTOLMotorN"));
|
||||||
|
// m_aircraft->multiMotor1->setCurrentIndex(m_aircraft->multiMotor1->findText(field->getValue().toString()));
|
||||||
|
// field = obj->getField(QString("VTOLMotorNE"));
|
||||||
|
// m_aircraft->multiMotor2->setCurrentIndex(m_aircraft->multiMotor2->findText(field->getValue().toString()));
|
||||||
|
// field = obj->getField(QString("VTOLMotorSE"));
|
||||||
|
// m_aircraft->multiMotor3->setCurrentIndex(m_aircraft->multiMotor3->findText(field->getValue().toString()));
|
||||||
|
// field = obj->getField(QString("VTOLMotorS"));
|
||||||
|
// m_aircraft->multiMotor4->setCurrentIndex(m_aircraft->multiMotor4->findText(field->getValue().toString()));
|
||||||
|
// field = obj->getField(QString("VTOLMotorSW"));
|
||||||
|
// m_aircraft->multiMotor5->setCurrentIndex(m_aircraft->multiMotor4->findText(field->getValue().toString()));
|
||||||
|
// field = obj->getField(QString("VTOLMotorNW"));
|
||||||
|
// m_aircraft->multiMotor6->setCurrentIndex(m_aircraft->multiMotor4->findText(field->getValue().toString()));
|
||||||
|
//
|
||||||
|
// // Now, read the 1st mixer R/P/Y levels and initialize the mix sliders.
|
||||||
|
// // This assumes that all vectors are identical - if not, the user should use the
|
||||||
|
// // "custom" setting.
|
||||||
|
// obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
|
||||||
|
// int tmpVal= m_aircraft->multiMotor1->currentIndex()-1;
|
||||||
|
// // tmpVal will be -1 if value is set to "None"
|
||||||
|
// if (tmpVal > -1) {
|
||||||
|
// field = obj->getField(mixerVectors.at(tmpVal));
|
||||||
|
// int i = field->getElementNames().indexOf("Pitch");
|
||||||
|
// double val = floor(field->getDouble(i)/1.27);
|
||||||
|
// m_aircraft->mrPitchMixLevel->setValue(val);
|
||||||
|
// i = field->getElementNames().indexOf("Yaw");
|
||||||
|
// val = floor(-field->getDouble(i)/1.27);
|
||||||
|
// m_aircraft->mrYawMixLevel->setValue(val);
|
||||||
|
// tmpVal = m_aircraft->multiMotor2->currentIndex()-1;
|
||||||
|
// if(tmpVal>-1)
|
||||||
|
// {
|
||||||
|
// field = obj->getField(mixerVectors.at(tmpVal));
|
||||||
|
// i = field->getElementNames().indexOf("Roll");
|
||||||
|
// val = floor(1-field->getDouble(i)/1.27);
|
||||||
|
// m_aircraft->mrRollMixLevel->setValue(val);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// } else if (frameType == "HexaX") {
|
||||||
|
// // Motors 1/2/3 4/5/6 are: NE / E / SE / SW / W / NW
|
||||||
|
// field = obj->getField(QString("VTOLMotorNE"));
|
||||||
|
// m_aircraft->multiMotor1->setCurrentIndex(m_aircraft->multiMotor1->findText(field->getValue().toString()));
|
||||||
|
// field = obj->getField(QString("VTOLMotorE"));
|
||||||
|
// m_aircraft->multiMotor2->setCurrentIndex(m_aircraft->multiMotor2->findText(field->getValue().toString()));
|
||||||
|
// field = obj->getField(QString("VTOLMotorSE"));
|
||||||
|
// m_aircraft->multiMotor3->setCurrentIndex(m_aircraft->multiMotor3->findText(field->getValue().toString()));
|
||||||
|
// field = obj->getField(QString("VTOLMotorSW"));
|
||||||
|
// m_aircraft->multiMotor4->setCurrentIndex(m_aircraft->multiMotor4->findText(field->getValue().toString()));
|
||||||
|
// field = obj->getField(QString("VTOLMotorW"));
|
||||||
|
// m_aircraft->multiMotor5->setCurrentIndex(m_aircraft->multiMotor4->findText(field->getValue().toString()));
|
||||||
|
// field = obj->getField(QString("VTOLMotorNW"));
|
||||||
|
// m_aircraft->multiMotor6->setCurrentIndex(m_aircraft->multiMotor4->findText(field->getValue().toString()));
|
||||||
|
//
|
||||||
|
// // Now, read the 1st mixer R/P/Y levels and initialize the mix sliders.
|
||||||
|
// // This assumes that all vectors are identical - if not, the user should use the
|
||||||
|
// // "custom" setting.
|
||||||
|
// obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
|
||||||
|
// int tmpVal= m_aircraft->multiMotor1->currentIndex()-1;
|
||||||
|
// // tmpVal will be -1 if value is set to "None"
|
||||||
|
// if (tmpVal > -1) {
|
||||||
|
// field = obj->getField(mixerVectors.at(tmpVal));
|
||||||
|
// int i = field->getElementNames().indexOf("Pitch");
|
||||||
|
// double val = floor(field->getDouble(i)/1.27);
|
||||||
|
// m_aircraft->mrPitchMixLevel->setValue(val);
|
||||||
|
// i = field->getElementNames().indexOf("Yaw");
|
||||||
|
// val = floor(-field->getDouble(i)/1.27);
|
||||||
|
// m_aircraft->mrYawMixLevel->setValue(val);
|
||||||
|
// tmpVal = m_aircraft->multiMotor2->currentIndex()-1;
|
||||||
|
// field = obj->getField(mixerVectors.at(tmpVal));
|
||||||
|
// i = field->getElementNames().indexOf("Roll");
|
||||||
|
// val = floor(1-field->getDouble(i)/1.27);
|
||||||
|
// m_aircraft->mrRollMixLevel->setValue(val);
|
||||||
|
// }
|
||||||
|
// } else if (frameType == "HexaCoax") {
|
||||||
|
// // Motors 1/2/3 4/5/6 are: NW/W NE/E S/SE
|
||||||
|
// field = obj->getField(QString("VTOLMotorNW"));
|
||||||
|
// m_aircraft->multiMotor1->setCurrentIndex(m_aircraft->multiMotor1->findText(field->getValue().toString()));
|
||||||
|
// field = obj->getField(QString("VTOLMotorW"));
|
||||||
|
// m_aircraft->multiMotor2->setCurrentIndex(m_aircraft->multiMotor2->findText(field->getValue().toString()));
|
||||||
|
// field = obj->getField(QString("VTOLMotorNE"));
|
||||||
|
// m_aircraft->multiMotor3->setCurrentIndex(m_aircraft->multiMotor3->findText(field->getValue().toString()));
|
||||||
|
// field = obj->getField(QString("VTOLMotorE"));
|
||||||
|
// m_aircraft->multiMotor4->setCurrentIndex(m_aircraft->multiMotor4->findText(field->getValue().toString()));
|
||||||
|
// field = obj->getField(QString("VTOLMotorS"));
|
||||||
|
// m_aircraft->multiMotor5->setCurrentIndex(m_aircraft->multiMotor4->findText(field->getValue().toString()));
|
||||||
|
// field = obj->getField(QString("VTOLMotorSE"));
|
||||||
|
// m_aircraft->multiMotor6->setCurrentIndex(m_aircraft->multiMotor4->findText(field->getValue().toString()));
|
||||||
|
//
|
||||||
|
// // Now, read the 1st mixer R/P/Y levels and initialize the mix sliders.
|
||||||
|
// // This assumes that all vectors are identical - if not, the user should use the
|
||||||
|
// // "custom" setting.
|
||||||
|
// obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
|
||||||
|
// int tmpVal= m_aircraft->multiMotor1->currentIndex()-1;
|
||||||
|
// // tmpVal will be -1 if value is set to "None"
|
||||||
|
// if (tmpVal > -1) {
|
||||||
|
// field = obj->getField(mixerVectors.at(tmpVal));
|
||||||
|
// int i = field->getElementNames().indexOf("Pitch");
|
||||||
|
// double val = floor(2*field->getDouble(i)/1.27);
|
||||||
|
// m_aircraft->mrPitchMixLevel->setValue(val);
|
||||||
|
// i = field->getElementNames().indexOf("Yaw");
|
||||||
|
// val = floor(-field->getDouble(i)/1.27);
|
||||||
|
// m_aircraft->mrYawMixLevel->setValue(val);
|
||||||
|
// i = field->getElementNames().indexOf("Roll");
|
||||||
|
// val = floor(field->getDouble(i)/1.27);
|
||||||
|
// m_aircraft->mrRollMixLevel->setValue(val);
|
||||||
|
// }
|
||||||
|
// } else if (frameType == "Octo" || frameType == "OctoV" ||
|
||||||
|
// frameType == "OctoCoaxP") {
|
||||||
|
// // Motors 1 to 8 are N / NE / E / etc
|
||||||
|
// field = obj->getField(QString("VTOLMotorN"));
|
||||||
|
// Q_ASSERT(field);
|
||||||
|
// m_aircraft->multiMotor1->setCurrentIndex(m_aircraft->multiMotor1->findText(field->getValue().toString()));
|
||||||
|
// field = obj->getField(QString("VTOLMotorNE"));
|
||||||
|
// Q_ASSERT(field);
|
||||||
|
// m_aircraft->multiMotor2->setCurrentIndex(m_aircraft->multiMotor2->findText(field->getValue().toString()));
|
||||||
|
// field = obj->getField(QString("VTOLMotorE"));
|
||||||
|
// Q_ASSERT(field);
|
||||||
|
// m_aircraft->multiMotor3->setCurrentIndex(m_aircraft->multiMotor3->findText(field->getValue().toString()));
|
||||||
|
// field = obj->getField(QString("VTOLMotorSE"));
|
||||||
|
// Q_ASSERT(field);
|
||||||
|
// m_aircraft->multiMotor4->setCurrentIndex(m_aircraft->multiMotor4->findText(field->getValue().toString()));
|
||||||
|
// field = obj->getField(QString("VTOLMotorS"));
|
||||||
|
// Q_ASSERT(field);
|
||||||
|
// m_aircraft->multiMotor5->setCurrentIndex(m_aircraft->multiMotor4->findText(field->getValue().toString()));
|
||||||
|
// field = obj->getField(QString("VTOLMotorSW"));
|
||||||
|
// Q_ASSERT(field);
|
||||||
|
// m_aircraft->multiMotor6->setCurrentIndex(m_aircraft->multiMotor4->findText(field->getValue().toString()));
|
||||||
|
// field = obj->getField(QString("VTOLMotorW"));
|
||||||
|
// Q_ASSERT(field);
|
||||||
|
// m_aircraft->multiMotor7->setCurrentIndex(m_aircraft->multiMotor4->findText(field->getValue().toString()));
|
||||||
|
// field = obj->getField(QString("VTOLMotorNW"));
|
||||||
|
// Q_ASSERT(field);
|
||||||
|
// m_aircraft->multiMotor8->setCurrentIndex(m_aircraft->multiMotor4->findText(field->getValue().toString()));
|
||||||
|
//
|
||||||
|
// // Now, read the 1st mixer R/P/Y levels and initialize the mix sliders.
|
||||||
|
// // This assumes that all vectors are identical - if not, the user should use the
|
||||||
|
// // "custom" setting.
|
||||||
|
// obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
|
||||||
|
// int tmpVal= m_aircraft->multiMotor1->currentIndex()-1;
|
||||||
|
// // tmpVal will be -1 if value is set to "None"
|
||||||
|
// if (tmpVal > -1) {
|
||||||
|
// if (frameType == "Octo") {
|
||||||
|
// field = obj->getField(mixerVectors.at(tmpVal));
|
||||||
|
// int i = field->getElementNames().indexOf("Pitch");
|
||||||
|
// double val = floor(field->getDouble(i)/1.27);
|
||||||
|
// m_aircraft->mrPitchMixLevel->setValue(val);
|
||||||
|
// i = field->getElementNames().indexOf("Yaw");
|
||||||
|
// val = floor(-field->getDouble(i)/1.27);
|
||||||
|
// m_aircraft->mrYawMixLevel->setValue(val);
|
||||||
|
// tmpVal = m_aircraft->multiMotor2->currentIndex()-1;
|
||||||
|
// field = obj->getField(mixerVectors.at(tmpVal));
|
||||||
|
// i = field->getElementNames().indexOf("Roll");
|
||||||
|
// val = floor(-field->getDouble(i)/1.27);
|
||||||
|
// m_aircraft->mrRollMixLevel->setValue(val);
|
||||||
|
// } else if (frameType == "OctoV") {
|
||||||
|
// field = obj->getField(mixerVectors.at(tmpVal));
|
||||||
|
// int i = field->getElementNames().indexOf("Yaw");
|
||||||
|
// double val = floor(-field->getDouble(i)/1.27);
|
||||||
|
// m_aircraft->mrYawMixLevel->setValue(val);
|
||||||
|
// i = field->getElementNames().indexOf("Roll");
|
||||||
|
// val = floor(-field->getDouble(i)/1.27);
|
||||||
|
// m_aircraft->mrRollMixLevel->setValue(val);
|
||||||
|
// tmpVal = m_aircraft->multiMotor2->currentIndex()-1;
|
||||||
|
// field = obj->getField(mixerVectors.at(tmpVal));
|
||||||
|
// i = field->getElementNames().indexOf("Pitch");
|
||||||
|
// val = floor(field->getDouble(i)/1.27);
|
||||||
|
// m_aircraft->mrPitchMixLevel->setValue(val);
|
||||||
|
//
|
||||||
|
// } else if (frameType == "OctoCoaxP") {
|
||||||
|
// field = obj->getField(mixerVectors.at(tmpVal));
|
||||||
|
// int i = field->getElementNames().indexOf("Pitch");
|
||||||
|
// double val = floor(field->getDouble(i)/1.27);
|
||||||
|
// m_aircraft->mrPitchMixLevel->setValue(val);
|
||||||
|
// i = field->getElementNames().indexOf("Yaw");
|
||||||
|
// val = floor(-field->getDouble(i)/1.27);
|
||||||
|
// m_aircraft->mrYawMixLevel->setValue(val);
|
||||||
|
// tmpVal = m_aircraft->multiMotor3->currentIndex()-1;
|
||||||
|
// field = obj->getField(mixerVectors.at(tmpVal));
|
||||||
|
// i = field->getElementNames().indexOf("Roll");
|
||||||
|
// val = floor(-field->getDouble(i)/1.27);
|
||||||
|
// m_aircraft->mrRollMixLevel->setValue(val);
|
||||||
|
//
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// } else if (frameType == "OctoCoaxX") {
|
||||||
|
// // Motors 1 to 8 are N / NE / E / etc
|
||||||
|
// field = obj->getField(QString("VTOLMotorNW"));
|
||||||
|
// Q_ASSERT(field);
|
||||||
|
// m_aircraft->multiMotor1->setCurrentIndex(m_aircraft->multiMotor1->findText(field->getValue().toString()));
|
||||||
|
// field = obj->getField(QString("VTOLMotorN"));
|
||||||
|
// Q_ASSERT(field);
|
||||||
|
// m_aircraft->multiMotor2->setCurrentIndex(m_aircraft->multiMotor2->findText(field->getValue().toString()));
|
||||||
|
// field = obj->getField(QString("VTOLMotorNE"));
|
||||||
|
// Q_ASSERT(field);
|
||||||
|
// m_aircraft->multiMotor3->setCurrentIndex(m_aircraft->multiMotor3->findText(field->getValue().toString()));
|
||||||
|
// field = obj->getField(QString("VTOLMotorE"));
|
||||||
|
// Q_ASSERT(field);
|
||||||
|
// m_aircraft->multiMotor4->setCurrentIndex(m_aircraft->multiMotor4->findText(field->getValue().toString()));
|
||||||
|
// field = obj->getField(QString("VTOLMotorSE"));
|
||||||
|
// Q_ASSERT(field);
|
||||||
|
// m_aircraft->multiMotor5->setCurrentIndex(m_aircraft->multiMotor4->findText(field->getValue().toString()));
|
||||||
|
// field = obj->getField(QString("VTOLMotorS"));
|
||||||
|
// Q_ASSERT(field);
|
||||||
|
// m_aircraft->multiMotor6->setCurrentIndex(m_aircraft->multiMotor4->findText(field->getValue().toString()));
|
||||||
|
// field = obj->getField(QString("VTOLMotorSW"));
|
||||||
|
// Q_ASSERT(field);
|
||||||
|
// m_aircraft->multiMotor7->setCurrentIndex(m_aircraft->multiMotor4->findText(field->getValue().toString()));
|
||||||
|
// field = obj->getField(QString("VTOLMotorW"));
|
||||||
|
// Q_ASSERT(field);
|
||||||
|
// m_aircraft->multiMotor8->setCurrentIndex(m_aircraft->multiMotor4->findText(field->getValue().toString()));
|
||||||
|
//
|
||||||
|
// // Now, read the 1st mixer R/P/Y levels and initialize the mix sliders.
|
||||||
|
// // This assumes that all vectors are identical - if not, the user should use the
|
||||||
|
// // "custom" setting.
|
||||||
|
// obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
|
||||||
|
// int tmpVal= m_aircraft->multiMotor1->currentIndex()-1;
|
||||||
|
// // tmpVal will be -1 if value is set to "None"
|
||||||
|
// if (tmpVal > -1) {
|
||||||
|
// field = obj->getField(mixerVectors.at(tmpVal));
|
||||||
|
// int i = field->getElementNames().indexOf("Pitch");
|
||||||
|
// double val = floor(field->getDouble(i)/1.27);
|
||||||
|
// m_aircraft->mrPitchMixLevel->setValue(val);
|
||||||
|
// i = field->getElementNames().indexOf("Yaw");
|
||||||
|
// val = floor(-field->getDouble(i)/1.27);
|
||||||
|
// m_aircraft->mrYawMixLevel->setValue(val);
|
||||||
|
// i = field->getElementNames().indexOf("Roll");
|
||||||
|
// val = floor(field->getDouble(i)/1.27);
|
||||||
|
// m_aircraft->mrRollMixLevel->setValue(val);
|
||||||
|
// }
|
||||||
|
// } else if (frameType == "Tri") {
|
||||||
|
// // Motors 1 to 8 are N / NE / E / etc
|
||||||
|
// field = obj->getField(QString("VTOLMotorNW"));
|
||||||
|
// Q_ASSERT(field);
|
||||||
|
// m_aircraft->multiMotor1->setCurrentIndex(m_aircraft->multiMotor1->findText(field->getValue().toString()));
|
||||||
|
// field = obj->getField(QString("VTOLMotorNE"));
|
||||||
|
// Q_ASSERT(field);
|
||||||
|
// m_aircraft->multiMotor2->setCurrentIndex(m_aircraft->multiMotor2->findText(field->getValue().toString()));
|
||||||
|
// field = obj->getField(QString("VTOLMotorS"));
|
||||||
|
// Q_ASSERT(field);
|
||||||
|
// m_aircraft->multiMotor3->setCurrentIndex(m_aircraft->multiMotor3->findText(field->getValue().toString()));
|
||||||
|
// field = obj->getField(QString("FixedWingYaw1"));
|
||||||
|
// Q_ASSERT(field);
|
||||||
|
// m_aircraft->triYawChannelBoxBox->setCurrentIndex(m_aircraft->multiMotor3->findText(field->getValue().toString()));
|
||||||
|
//
|
||||||
|
// obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
|
||||||
|
// int tmpVal= m_aircraft->multiMotor1->currentIndex()-1;
|
||||||
|
// // tmpVal will be -1 if value is set to "None"
|
||||||
|
// if (tmpVal > -1) {
|
||||||
|
// field = obj->getField(mixerVectors.at(tmpVal));
|
||||||
|
// int i = field->getElementNames().indexOf("Pitch");
|
||||||
|
// double val = floor(2*field->getDouble(i)/1.27);
|
||||||
|
// m_aircraft->mrPitchMixLevel->setValue(val);
|
||||||
|
// i = field->getElementNames().indexOf("Roll");
|
||||||
|
// val = floor(field->getDouble(i)/1.27);
|
||||||
|
// m_aircraft->mrRollMixLevel->setValue(val);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// }
|
||||||
|
// obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
|
||||||
|
// Q_ASSERT(obj);
|
||||||
|
// // Now, retrieve the Feedforward values:
|
||||||
|
// field = obj->getField(QString("FeedForward"));
|
||||||
|
// Q_ASSERT(field);
|
||||||
|
// m_aircraft->feedForwardSlider->setValue(field->getDouble()*100);
|
||||||
|
// field = obj->getField(QString("AccelTime"));
|
||||||
|
// Q_ASSERT(field);
|
||||||
|
// m_aircraft->accelTime->setValue(field->getDouble());
|
||||||
|
// field = obj->getField(QString("DecelTime"));
|
||||||
|
// Q_ASSERT(field);
|
||||||
|
// m_aircraft->decelTime->setValue(field->getDouble());
|
||||||
|
// field = obj->getField(QString("MaxAccel"));
|
||||||
|
// Q_ASSERT(field);
|
||||||
|
// m_aircraft->maxAccelSlider->setValue(field->getDouble());
|
||||||
|
}
|
||||||
|
} else if (frameType == "HeliCP") {
|
||||||
|
m_aircraft->widget_3->requestccpmUpdate();
|
||||||
|
m_aircraft->aircraftType->setCurrentIndex(m_aircraft->aircraftType->findText("Helicopter"));//"Helicopter"
|
||||||
|
} else if (frameType.startsWith("GroundVehicle")) {
|
||||||
|
|
||||||
|
// Retrieve ground vehicle settings
|
||||||
|
if(1){
|
||||||
|
refreshGroundVehicleWidgetsValues(frameType);
|
||||||
|
}
|
||||||
|
|
||||||
|
// //THIS SECTION STILL NEEDS WORK. FOR THE MOMENT, USE THE FIXED-WING ONBOARD SETTING IN ORDER TO MINIMIZE CHANCES OF BOLLOXING REAL CODE
|
||||||
|
// // Then retrieve channel setup values
|
||||||
|
// obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("ActuatorSettings")));
|
||||||
|
// Q_ASSERT(obj);
|
||||||
|
// field = obj->getField(QString("FixedWingThrottle"));
|
||||||
|
// Q_ASSERT(field);
|
||||||
|
// m_aircraft->fwEngineChannelBox->setCurrentIndex(m_aircraft->fwEngineChannelBox->findText(field->getValue().toString()));
|
||||||
|
// field = obj->getField(QString("FixedWingRoll1"));
|
||||||
|
// Q_ASSERT(field);
|
||||||
|
// m_aircraft->fwAileron1ChannelBox->setCurrentIndex(m_aircraft->fwAileron1ChannelBox->findText(field->getValue().toString()));
|
||||||
|
// field = obj->getField(QString("FixedWingRoll2"));
|
||||||
|
// Q_ASSERT(field);
|
||||||
|
// m_aircraft->fwAileron2ChannelBox->setCurrentIndex(m_aircraft->fwAileron2ChannelBox->findText(field->getValue().toString()));
|
||||||
|
// field = obj->getField(QString("FixedWingPitch1"));
|
||||||
|
// Q_ASSERT(field);
|
||||||
|
// m_aircraft->fwElevator1ChannelBox->setCurrentIndex(m_aircraft->fwElevator1ChannelBox->findText(field->getValue().toString()));
|
||||||
|
// field = obj->getField(QString("FixedWingPitch2"));
|
||||||
|
// Q_ASSERT(field);
|
||||||
|
// m_aircraft->fwElevator2ChannelBox->setCurrentIndex(m_aircraft->fwElevator2ChannelBox->findText(field->getValue().toString()));
|
||||||
|
// field = obj->getField(QString("FixedWingYaw1"));
|
||||||
|
// Q_ASSERT(field);
|
||||||
|
// m_aircraft->fwRudder1ChannelBox->setCurrentIndex(m_aircraft->fwRudder1ChannelBox->findText(field->getValue().toString()));
|
||||||
|
// field = obj->getField(QString("FixedWingYaw2"));
|
||||||
|
// Q_ASSERT(field);
|
||||||
|
// m_aircraft->fwRudder2ChannelBox->setCurrentIndex(m_aircraft->fwRudder2ChannelBox->findText(field->getValue().toString()));
|
||||||
|
//
|
||||||
|
// if (frameType == "GroundDifferential") {
|
||||||
|
// //CURRENTLY BROKEN UNTIL WE DECIDE HOW DIFFERENTIAL SHOULD BEHAVE
|
||||||
|
// // If the airframe is differential, restore the slider setting
|
||||||
|
// // Find the channel number for Elevon1 (FixedWingRoll1)
|
||||||
|
// obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
|
||||||
|
// Q_ASSERT(obj);
|
||||||
|
// int chMixerNumber = m_aircraft->fwAileron1ChannelBox->currentIndex()-1;
|
||||||
|
// if (chMixerNumber >= 0) { // If for some reason the actuators were incoherent, we might fail here, hence the check.
|
||||||
|
// field = obj->getField(mixerVectors.at(chMixerNumber));
|
||||||
|
// int ti = field->getElementNames().indexOf("Roll");
|
||||||
|
// m_aircraft->differentialSteeringSlider1->setValue(field->getDouble(ti)*100);
|
||||||
|
//
|
||||||
|
// ti = field->getElementNames().indexOf("Pitch");
|
||||||
|
// m_aircraft->differentialSteeringSlider2->setValue(field->getDouble(ti)*100);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// if (frameType == "GroundMotorcycle") {
|
||||||
|
// //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);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
} else if (frameType == "Custom") {
|
||||||
|
m_aircraft->aircraftType->setCurrentIndex(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"){
|
||||||
|
setupFixedWingUI(frameType);
|
||||||
|
// }
|
||||||
|
// else if (frameType == "FixedWing" || frameType == "Elevator aileron rudder") {
|
||||||
|
// // Setup the UI
|
||||||
|
// m_aircraft->aircraftType->setCurrentIndex(m_aircraft->aircraftType->findText("Fixed Wing"));
|
||||||
|
// m_aircraft->fixedWingType->setCurrentIndex(m_aircraft->fixedWingType->findText("Elevator aileron rudder"));
|
||||||
|
// m_aircraft->fwRudder1ChannelBox->setEnabled(true);
|
||||||
|
// m_aircraft->fwRudder1Label->setEnabled(true);
|
||||||
|
// m_aircraft->fwRudder2ChannelBox->setEnabled(true);
|
||||||
|
// m_aircraft->fwRudder2Label->setEnabled(true);
|
||||||
|
// m_aircraft->fwElevator1ChannelBox->setEnabled(true);
|
||||||
|
// m_aircraft->fwElevator1Label->setEnabled(true);
|
||||||
|
// m_aircraft->fwElevator2ChannelBox->setEnabled(true);
|
||||||
|
// m_aircraft->fwElevator2Label->setEnabled(true);
|
||||||
|
// m_aircraft->fwAileron1ChannelBox->setEnabled(true);
|
||||||
|
// m_aircraft->fwAileron1Label->setEnabled(true);
|
||||||
|
// m_aircraft->fwAileron2ChannelBox->setEnabled(true);
|
||||||
|
// m_aircraft->fwAileron2Label->setEnabled(true);
|
||||||
|
//
|
||||||
|
// m_aircraft->fwAileron1Label->setText("Aileron 1");
|
||||||
|
// m_aircraft->fwAileron2Label->setText("Aileron 2");
|
||||||
|
// m_aircraft->fwElevator1Label->setText("Elevator 1");
|
||||||
|
// m_aircraft->fwElevator2Label->setText("Elevator 2");
|
||||||
|
// m_aircraft->elevonMixBox->setHidden(true);
|
||||||
|
//
|
||||||
|
// } else if (frameType == "FixedWingElevon" || frameType == "Elevon") {
|
||||||
|
// m_aircraft->aircraftType->setCurrentIndex(m_aircraft->aircraftType->findText("Fixed Wing"));
|
||||||
|
// m_aircraft->fixedWingType->setCurrentIndex(m_aircraft->fixedWingType->findText("Elevon"));
|
||||||
|
// m_aircraft->fwAileron1Label->setText("Elevon 1");
|
||||||
|
// m_aircraft->fwAileron2Label->setText("Elevon 2");
|
||||||
|
// m_aircraft->fwElevator1ChannelBox->setEnabled(false);
|
||||||
|
// m_aircraft->fwElevator1Label->setEnabled(false);
|
||||||
|
// m_aircraft->fwElevator2ChannelBox->setEnabled(false);
|
||||||
|
// m_aircraft->fwElevator2Label->setEnabled(false);
|
||||||
|
// m_aircraft->fwRudder1ChannelBox->setEnabled(true);
|
||||||
|
// m_aircraft->fwRudder1Label->setEnabled(true);
|
||||||
|
// m_aircraft->fwRudder2ChannelBox->setEnabled(true);
|
||||||
|
// m_aircraft->fwRudder2Label->setEnabled(true);
|
||||||
|
// m_aircraft->fwElevator1Label->setText("Elevator 1");
|
||||||
|
// m_aircraft->fwElevator2Label->setText("Elevator 2");
|
||||||
|
// m_aircraft->elevonMixBox->setHidden(false);
|
||||||
|
// m_aircraft->elevonLabel1->setText("Roll");
|
||||||
|
// m_aircraft->elevonLabel2->setText("Pitch");
|
||||||
|
//
|
||||||
|
// } else if (frameType == "FixedWingVtail" || frameType == "Vtail") {
|
||||||
|
// m_aircraft->aircraftType->setCurrentIndex(m_aircraft->aircraftType->findText("Fixed Wing"));
|
||||||
|
// m_aircraft->fixedWingType->setCurrentIndex(m_aircraft->fixedWingType->findText("Vtail"));
|
||||||
|
// m_aircraft->fwRudder1ChannelBox->setEnabled(false);
|
||||||
|
// m_aircraft->fwRudder1Label->setEnabled(false);
|
||||||
|
// m_aircraft->fwRudder2ChannelBox->setEnabled(false);
|
||||||
|
// m_aircraft->fwRudder2Label->setEnabled(false);
|
||||||
|
// m_aircraft->fwElevator1ChannelBox->setEnabled(true);
|
||||||
|
// m_aircraft->fwElevator1Label->setEnabled(true);
|
||||||
|
// m_aircraft->fwElevator1Label->setText("Vtail 1");
|
||||||
|
// m_aircraft->fwElevator2Label->setText("Vtail 2");
|
||||||
|
// m_aircraft->elevonMixBox->setHidden(false);
|
||||||
|
// m_aircraft->fwElevator2ChannelBox->setEnabled(true);
|
||||||
|
// m_aircraft->fwElevator2Label->setEnabled(true);
|
||||||
|
// m_aircraft->fwAileron1Label->setText("Aileron 1");
|
||||||
|
// m_aircraft->fwAileron2Label->setText("Aileron 2");
|
||||||
|
// m_aircraft->elevonLabel1->setText("Rudder");
|
||||||
|
// m_aircraft->elevonLabel2->setText("Pitch");
|
||||||
|
|
||||||
|
} else if (frameType == "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 +" ) {
|
||||||
|
|
||||||
|
//Call multi-rotor setup UI
|
||||||
|
setupMultiRotorUI(frameType);
|
||||||
|
}
|
||||||
|
// } else if (frameType == "QuadX" || frameType == "Quad X") {
|
||||||
|
// m_aircraft->aircraftType->setCurrentIndex(m_aircraft->aircraftType->findText("Multirotor"));
|
||||||
|
// m_aircraft->multirotorFrameType->setCurrentIndex(m_aircraft->multirotorFrameType->findText("Quad X"));
|
||||||
|
// quad->setElementId("quad-X");
|
||||||
|
// m_aircraft->multiMotor4->setEnabled(true);
|
||||||
|
// m_aircraft->multiMotor5->setEnabled(false);
|
||||||
|
// m_aircraft->multiMotor6->setEnabled(false);
|
||||||
|
// m_aircraft->multiMotor7->setEnabled(false);
|
||||||
|
// m_aircraft->multiMotor8->setEnabled(false);
|
||||||
|
// m_aircraft->triYawChannelBox->setEnabled(false);
|
||||||
|
// m_aircraft->mrRollMixLevel->setValue(50);
|
||||||
|
// m_aircraft->mrPitchMixLevel->setValue(50);
|
||||||
|
// m_aircraft->mrYawMixLevel->setValue(50);
|
||||||
|
// } else if (frameType == "QuadP" || frameType == "Quad +") {
|
||||||
|
// m_aircraft->aircraftType->setCurrentIndex(m_aircraft->aircraftType->findText("Multirotor"));
|
||||||
|
// m_aircraft->multirotorFrameType->setCurrentIndex(m_aircraft->multirotorFrameType->findText("Quad +"));
|
||||||
|
// quad->setElementId("quad-plus");
|
||||||
|
// m_aircraft->multiMotor4->setEnabled(true);
|
||||||
|
// m_aircraft->multiMotor5->setEnabled(false);
|
||||||
|
// m_aircraft->multiMotor6->setEnabled(false);
|
||||||
|
// m_aircraft->multiMotor7->setEnabled(false);
|
||||||
|
// m_aircraft->multiMotor8->setEnabled(false);
|
||||||
|
// m_aircraft->triYawChannelBox->setEnabled(false);
|
||||||
|
// m_aircraft->mrRollMixLevel->setValue(100);
|
||||||
|
// m_aircraft->mrPitchMixLevel->setValue(100);
|
||||||
|
// m_aircraft->mrYawMixLevel->setValue(50);
|
||||||
|
// } else if (frameType == "Hexa" || frameType == "Hexacopter") {
|
||||||
|
// m_aircraft->aircraftType->setCurrentIndex(m_aircraft->aircraftType->findText("Multirotor"));
|
||||||
|
// m_aircraft->multirotorFrameType->setCurrentIndex(m_aircraft->multirotorFrameType->findText("Hexacopter"));
|
||||||
|
// quad->setElementId("quad-hexa");
|
||||||
|
// m_aircraft->multiMotor4->setEnabled(true);
|
||||||
|
// m_aircraft->multiMotor5->setEnabled(true);
|
||||||
|
// m_aircraft->multiMotor6->setEnabled(true);
|
||||||
|
// m_aircraft->multiMotor7->setEnabled(false);
|
||||||
|
// m_aircraft->multiMotor8->setEnabled(false);
|
||||||
|
// m_aircraft->triYawChannelBox->setEnabled(false);
|
||||||
|
// m_aircraft->mrRollMixLevel->setValue(50);
|
||||||
|
// m_aircraft->mrPitchMixLevel->setValue(33);
|
||||||
|
// m_aircraft->mrYawMixLevel->setValue(33);
|
||||||
|
// } else if (frameType == "Octo" || frameType == "Octocopter") {
|
||||||
|
// m_aircraft->aircraftType->setCurrentIndex(m_aircraft->aircraftType->findText("Multirotor"));
|
||||||
|
// m_aircraft->multirotorFrameType->setCurrentIndex(m_aircraft->multirotorFrameType->findText("Octocopter"));
|
||||||
|
// quad->setElementId("quad-octo");
|
||||||
|
// m_aircraft->multiMotor4->setEnabled(true);
|
||||||
|
// m_aircraft->multiMotor5->setEnabled(true);
|
||||||
|
// m_aircraft->multiMotor6->setEnabled(true);
|
||||||
|
// m_aircraft->multiMotor7->setEnabled(true);
|
||||||
|
// m_aircraft->multiMotor8->setEnabled(true);
|
||||||
|
// m_aircraft->triYawChannelBox->setEnabled(false);
|
||||||
|
// m_aircraft->mrRollMixLevel->setValue(33);
|
||||||
|
// m_aircraft->mrPitchMixLevel->setValue(33);
|
||||||
|
// m_aircraft->mrYawMixLevel->setValue(25);
|
||||||
|
// } else if (frameType == "HexaX" || frameType == "Hexacopter X" ) {
|
||||||
|
// m_aircraft->aircraftType->setCurrentIndex(m_aircraft->aircraftType->findText("Multirotor"));
|
||||||
|
// m_aircraft->multirotorFrameType->setCurrentIndex(m_aircraft->multirotorFrameType->findText("Hexacopter X"));
|
||||||
|
// quad->setElementId("quad-hexa-H");
|
||||||
|
// m_aircraft->multiMotor4->setEnabled(true);
|
||||||
|
// m_aircraft->multiMotor5->setEnabled(true);
|
||||||
|
// m_aircraft->multiMotor6->setEnabled(true);
|
||||||
|
// m_aircraft->multiMotor7->setEnabled(false);
|
||||||
|
// m_aircraft->multiMotor8->setEnabled(false);
|
||||||
|
// m_aircraft->triYawChannelBox->setEnabled(false);
|
||||||
|
// m_aircraft->mrRollMixLevel->setValue(33);
|
||||||
|
// m_aircraft->mrPitchMixLevel->setValue(50);
|
||||||
|
// m_aircraft->mrYawMixLevel->setValue(33);
|
||||||
|
//
|
||||||
|
// } else if (frameType == "OctoV" || frameType == "Octocopter V") {
|
||||||
|
// m_aircraft->aircraftType->setCurrentIndex(m_aircraft->aircraftType->findText("Multirotor"));
|
||||||
|
// m_aircraft->multirotorFrameType->setCurrentIndex(m_aircraft->multirotorFrameType->findText("Octocopter V"));
|
||||||
|
// quad->setElementId("quad-octo-v");
|
||||||
|
// m_aircraft->multiMotor4->setEnabled(true);
|
||||||
|
// m_aircraft->multiMotor5->setEnabled(true);
|
||||||
|
// m_aircraft->multiMotor6->setEnabled(true);
|
||||||
|
// m_aircraft->multiMotor7->setEnabled(true);
|
||||||
|
// m_aircraft->multiMotor8->setEnabled(true);
|
||||||
|
// m_aircraft->triYawChannelBox->setEnabled(false);
|
||||||
|
// m_aircraft->mrRollMixLevel->setValue(25);
|
||||||
|
// m_aircraft->mrPitchMixLevel->setValue(25);
|
||||||
|
// m_aircraft->mrYawMixLevel->setValue(25);
|
||||||
|
//
|
||||||
|
// } else if (frameType == "OctoCoaxP" || frameType == "Octo Coax +") {
|
||||||
|
// m_aircraft->aircraftType->setCurrentIndex(m_aircraft->aircraftType->findText("Multirotor"));
|
||||||
|
// m_aircraft->multirotorFrameType->setCurrentIndex(m_aircraft->multirotorFrameType->findText("Octo Coax +"));
|
||||||
|
// quad->setElementId("octo-coax-P");
|
||||||
|
// m_aircraft->multiMotor4->setEnabled(true);
|
||||||
|
// m_aircraft->multiMotor5->setEnabled(true);
|
||||||
|
// m_aircraft->multiMotor6->setEnabled(true);
|
||||||
|
// m_aircraft->multiMotor7->setEnabled(true);
|
||||||
|
// m_aircraft->multiMotor8->setEnabled(true);
|
||||||
|
// m_aircraft->triYawChannelBox->setEnabled(false);
|
||||||
|
// m_aircraft->mrRollMixLevel->setValue(100);
|
||||||
|
// m_aircraft->mrPitchMixLevel->setValue(100);
|
||||||
|
// m_aircraft->mrYawMixLevel->setValue(50);
|
||||||
|
//
|
||||||
|
// } else if (frameType == "OctoCoaxX" || frameType == "Octo Coax X") {
|
||||||
|
// m_aircraft->aircraftType->setCurrentIndex(m_aircraft->aircraftType->findText("Multirotor"));
|
||||||
|
// m_aircraft->multirotorFrameType->setCurrentIndex(m_aircraft->multirotorFrameType->findText("Octo Coax X"));
|
||||||
|
// quad->setElementId("octo-coax-X");
|
||||||
|
// m_aircraft->multiMotor4->setEnabled(true);
|
||||||
|
// m_aircraft->multiMotor5->setEnabled(true);
|
||||||
|
// m_aircraft->multiMotor6->setEnabled(true);
|
||||||
|
// m_aircraft->multiMotor7->setEnabled(true);
|
||||||
|
// m_aircraft->multiMotor8->setEnabled(true);
|
||||||
|
// m_aircraft->triYawChannelBox->setEnabled(false);
|
||||||
|
// m_aircraft->mrRollMixLevel->setValue(50);
|
||||||
|
// m_aircraft->mrPitchMixLevel->setValue(50);
|
||||||
|
// m_aircraft->mrYawMixLevel->setValue(50);
|
||||||
|
//
|
||||||
|
// } else if (frameType == "HexaCoax" || frameType == "Hexacopter Y6") {
|
||||||
|
// m_aircraft->aircraftType->setCurrentIndex(m_aircraft->aircraftType->findText("Multirotor"));
|
||||||
|
// m_aircraft->multirotorFrameType->setCurrentIndex(m_aircraft->multirotorFrameType->findText("Hexacopter Y6"));
|
||||||
|
// quad->setElementId("hexa-coax");
|
||||||
|
// m_aircraft->multiMotor4->setEnabled(true);
|
||||||
|
// m_aircraft->multiMotor5->setEnabled(true);
|
||||||
|
// m_aircraft->multiMotor6->setEnabled(true);
|
||||||
|
// m_aircraft->multiMotor7->setEnabled(false);
|
||||||
|
// m_aircraft->multiMotor8->setEnabled(false);
|
||||||
|
// m_aircraft->triYawChannelBox->setEnabled(false);
|
||||||
|
// m_aircraft->mrRollMixLevel->setValue(100);
|
||||||
|
// m_aircraft->mrPitchMixLevel->setValue(50);
|
||||||
|
// m_aircraft->mrYawMixLevel->setValue(66);
|
||||||
|
//
|
||||||
|
// } else if (frameType == "Tri" || frameType == "Tricopter Y") {
|
||||||
|
// m_aircraft->aircraftType->setCurrentIndex(m_aircraft->aircraftType->findText("Multirotor"));
|
||||||
|
// m_aircraft->multirotorFrameType->setCurrentIndex(m_aircraft->multirotorFrameType->findText("Tricopter Y"));
|
||||||
|
// quad->setElementId("tri");
|
||||||
|
// m_aircraft->multiMotor4->setEnabled(false);
|
||||||
|
// m_aircraft->multiMotor5->setEnabled(false);
|
||||||
|
// m_aircraft->multiMotor6->setEnabled(false);
|
||||||
|
// m_aircraft->multiMotor7->setEnabled(false);
|
||||||
|
// m_aircraft->multiMotor8->setEnabled(false);
|
||||||
|
// m_aircraft->triYawChannelBox->setEnabled(true);
|
||||||
|
//
|
||||||
|
else if (frameType == "GroundVehicleCar" || frameType == "Turnable (car)" ||
|
||||||
|
frameType == "GroundVehicleDifferential" || frameType == "Differential (tank)" ||
|
||||||
|
frameType == "GroundVehicleMotorcyle" || frameType == "Motorcycle") {
|
||||||
|
setupGroundVehicleUI(frameType);
|
||||||
|
|
||||||
|
//// } else if (m_aircraft->aircraftType->currentText() == "Ground") {
|
||||||
|
// m_aircraft->differentialSteeringMixBox->setHidden(true);
|
||||||
|
// //STILL NEEDS WORK
|
||||||
|
// // Setup the UI
|
||||||
|
// m_aircraft->aircraftType->setCurrentIndex(m_aircraft->aircraftType->findText("Ground"));
|
||||||
|
//
|
||||||
|
// m_aircraft->gvSteering1Label->setEnabled(true);
|
||||||
|
// m_aircraft->gvSteering1Label->setEnabled(true);
|
||||||
|
// m_aircraft->gvSteering2Label->setEnabled(true);
|
||||||
|
// m_aircraft->gvSteering2Label->setEnabled(true);
|
||||||
|
// m_aircraft->gvMotor1ChannelBox->setEnabled(true);
|
||||||
|
// m_aircraft->gvMotor1Label->setEnabled(true);
|
||||||
|
// m_aircraft->gvAileron1ChannelBox->setEnabled(true);
|
||||||
|
// m_aircraft->gvAileron1Label->setEnabled(true);
|
||||||
|
// m_aircraft->gvAileron2ChannelBox->setEnabled(true);
|
||||||
|
// m_aircraft->gvAileron2Label->setEnabled(true);
|
||||||
|
//
|
||||||
|
// if (frameType == "GroundVehicleDifferential" || frameType == "Differential (tank)"){
|
||||||
|
// m_aircraft->groundVehicleType->setCurrentIndex(m_aircraft->groundVehicleType->findText("Differential (tank)"));
|
||||||
|
// m_aircraft->gvMotor2ChannelBox->setEnabled(true);
|
||||||
|
// m_aircraft->gvMotor2Label->setEnabled(true);
|
||||||
|
//
|
||||||
|
// m_aircraft->gvMotor1Label->setText("Left motor");
|
||||||
|
// m_aircraft->gvMotor2Label->setText("Right motor");
|
||||||
|
// m_aircraft->differentialSteeringMixBox->setHidden(false);
|
||||||
|
// }
|
||||||
|
// else if (frameType == "GroundVehicleMotorcyle" || frameType == "Motorcycle"){
|
||||||
|
// m_aircraft->groundVehicleType->setCurrentIndex(m_aircraft->groundVehicleType->findText("Motorcycle"));
|
||||||
|
// m_aircraft->gvMotor2ChannelBox->setEnabled(false);
|
||||||
|
// m_aircraft->gvMotor2Label->setEnabled(false);
|
||||||
|
//
|
||||||
|
// m_aircraft->gvMotor1Label->setText("Motor");
|
||||||
|
// m_aircraft->gvMotor2Label->setText("Elevator 2");
|
||||||
|
// m_aircraft->differentialSteeringMixBox->setHidden(true);
|
||||||
|
// }
|
||||||
|
// else {
|
||||||
|
// m_aircraft->groundVehicleType->setCurrentIndex(m_aircraft->groundVehicleType->findText("Turnable (car)"));
|
||||||
|
//
|
||||||
|
// m_aircraft->gvMotor2ChannelBox->setEnabled(true);
|
||||||
|
// m_aircraft->gvMotor2Label->setEnabled(true);
|
||||||
|
//
|
||||||
|
// m_aircraft->gvMotor1Label->setText("Front motor");
|
||||||
|
// m_aircraft->gvMotor2Label->setText("Rear motor");
|
||||||
|
// m_aircraft->differentialSteeringMixBox->setHidden(true);
|
||||||
|
// }
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Reset actuator values
|
||||||
|
*/
|
||||||
|
void ConfigVehicleTypeWidget::resetActuators()
|
||||||
|
{
|
||||||
|
UAVDataObject* obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("ActuatorSettings")));
|
||||||
|
Q_ASSERT(obj);
|
||||||
|
QList<UAVObjectField*> fieldList = obj->getFields();
|
||||||
|
// Reset all assignements first:
|
||||||
|
foreach (UAVObjectField* field, fieldList) {
|
||||||
|
// NOTE: we assume that all options in ActuatorSettings are a channel assignement
|
||||||
|
// except for the options called "ChannelBoxXXX"
|
||||||
|
if (field->getUnits().contains("channel")) {
|
||||||
|
field->setValue(field->getOptions().last());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//
|
||||||
|
///**
|
||||||
|
// Setup Elevator/Aileron/Rudder airframe.
|
||||||
|
//
|
||||||
|
// If both Aileron channels are set to 'None' (EasyStar), do Pitch/Rudder mixing
|
||||||
|
//
|
||||||
|
// Returns False if impossible to create the mixer.
|
||||||
|
// */
|
||||||
|
//bool ConfigVehicleTypeWidget::setupFrameFixedWing()
|
||||||
|
//{
|
||||||
|
// // Check coherence:
|
||||||
|
// // - At least Pitch and either Roll or Yaw
|
||||||
|
// if (m_aircraft->fwEngineChannelBox->currentText() == "None" ||
|
||||||
|
// m_aircraft->fwElevator1ChannelBox->currentText() == "None" ||
|
||||||
|
// ((m_aircraft->fwAileron1ChannelBox->currentText() == "None") &&
|
||||||
|
// (m_aircraft->fwRudder1ChannelBox->currentText() == "None"))) {
|
||||||
|
// // TODO: explain the problem in the UI
|
||||||
|
// m_aircraft->fwStatusLabel->setText("ERROR: check channel assignment");
|
||||||
|
// return false;
|
||||||
|
// }
|
||||||
|
// // Now setup the channels:
|
||||||
|
// resetActuators();
|
||||||
|
//
|
||||||
|
// UAVDataObject* obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("ActuatorSettings")));
|
||||||
|
// Q_ASSERT(obj);
|
||||||
|
//
|
||||||
|
// // Elevator
|
||||||
|
// UAVObjectField *field = obj->getField("FixedWingPitch1");
|
||||||
|
// Q_ASSERT(field);
|
||||||
|
// field->setValue(m_aircraft->fwElevator1ChannelBox->currentText());
|
||||||
|
// field = obj->getField("FixedWingPitch2");
|
||||||
|
// Q_ASSERT(field);
|
||||||
|
// field->setValue(m_aircraft->fwElevator2ChannelBox->currentText());
|
||||||
|
// // Aileron
|
||||||
|
// field = obj->getField("FixedWingRoll1");
|
||||||
|
// Q_ASSERT(field);
|
||||||
|
// field->setValue(m_aircraft->fwAileron1ChannelBox->currentText());
|
||||||
|
// field = obj->getField("FixedWingRoll2");
|
||||||
|
// Q_ASSERT(field);
|
||||||
|
// field->setValue(m_aircraft->fwAileron2ChannelBox->currentText());
|
||||||
|
// // Rudder
|
||||||
|
// field = obj->getField("FixedWingYaw1");
|
||||||
|
// Q_ASSERT(field);
|
||||||
|
// field->setValue(m_aircraft->fwRudder1ChannelBox->currentText());
|
||||||
|
// // Throttle
|
||||||
|
// field = obj->getField("FixedWingThrottle");
|
||||||
|
// Q_ASSERT(field);
|
||||||
|
// field->setValue(m_aircraft->fwEngineChannelBox->currentText());
|
||||||
|
//
|
||||||
|
// obj->updated();
|
||||||
|
//
|
||||||
|
// obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
|
||||||
|
// Q_ASSERT(obj);
|
||||||
|
// // ... and compute the matrix:
|
||||||
|
// // In order to make code a bit nicer, we assume:
|
||||||
|
// // - ChannelBox dropdowns start with 'None', then 0 to 7
|
||||||
|
//
|
||||||
|
// // 1. Assign the servo/motor/none for each channel
|
||||||
|
// // Disable all
|
||||||
|
// foreach(QString mixer, mixerTypes) {
|
||||||
|
// field = obj->getField(mixer);
|
||||||
|
// Q_ASSERT(field);
|
||||||
|
// field->setValue("Disabled");
|
||||||
|
// }
|
||||||
|
// // and set only the relevant channels:
|
||||||
|
// // Engine
|
||||||
|
// int tmpVal = m_aircraft->fwEngineChannelBox->currentIndex()-1;
|
||||||
|
// field = obj->getField(mixerTypes.at(tmpVal));
|
||||||
|
// field->setValue("Motor");
|
||||||
|
// field = obj->getField(mixerVectors.at(tmpVal));
|
||||||
|
// // First of all reset the vector
|
||||||
|
// resetField(field);
|
||||||
|
// int ti = field->getElementNames().indexOf("ThrottleCurve1");
|
||||||
|
// field->setValue(127, ti);
|
||||||
|
//
|
||||||
|
// // Rudder
|
||||||
|
// tmpVal = m_aircraft->fwRudder1ChannelBox->currentIndex()-1;
|
||||||
|
// // tmpVal will be -1 if rudder is set to "None"
|
||||||
|
// if (tmpVal > -1) {
|
||||||
|
// field = obj->getField(mixerTypes.at(tmpVal));
|
||||||
|
// field->setValue("Servo");
|
||||||
|
// field = obj->getField(mixerVectors.at(tmpVal));
|
||||||
|
// resetField(field);
|
||||||
|
// ti = field->getElementNames().indexOf("Yaw");
|
||||||
|
// field->setValue(127, ti);
|
||||||
|
// } // Else: we have no rudder, only ailerons, we're fine with it.
|
||||||
|
//
|
||||||
|
// // Ailerons
|
||||||
|
// tmpVal = m_aircraft->fwAileron1ChannelBox->currentIndex()-1;
|
||||||
|
// if (tmpVal > -1) {
|
||||||
|
// field = obj->getField(mixerTypes.at(tmpVal));
|
||||||
|
// field->setValue("Servo");
|
||||||
|
// field = obj->getField(mixerVectors.at(tmpVal));
|
||||||
|
// resetField(field);
|
||||||
|
// ti = field->getElementNames().indexOf("Roll");
|
||||||
|
// field->setValue(127, ti);
|
||||||
|
// // Only set Aileron 2 if Aileron 1 is defined
|
||||||
|
// tmpVal = m_aircraft->fwAileron2ChannelBox->currentIndex()-1;
|
||||||
|
// if (tmpVal > -1) {
|
||||||
|
// field = obj->getField(mixerTypes.at(tmpVal));
|
||||||
|
// field->setValue("Servo");
|
||||||
|
// field = obj->getField(mixerVectors.at(tmpVal));
|
||||||
|
// resetField(field);
|
||||||
|
// ti = field->getElementNames().indexOf("Roll");
|
||||||
|
// field->setValue(127, ti);
|
||||||
|
// }
|
||||||
|
// } // Else we have no ailerons. Our consistency check guarantees we have
|
||||||
|
// // rudder in this case, so we're fine with it too.
|
||||||
|
//
|
||||||
|
// // Elevator
|
||||||
|
// tmpVal = m_aircraft->fwElevator1ChannelBox->currentIndex()-1;
|
||||||
|
// field = obj->getField(mixerTypes.at(tmpVal));
|
||||||
|
// field->setValue("Servo");
|
||||||
|
// field = obj->getField(mixerVectors.at(tmpVal));
|
||||||
|
// resetField(field);
|
||||||
|
// ti = field->getElementNames().indexOf("Pitch");
|
||||||
|
// field->setValue(127, ti);
|
||||||
|
// // Only set Elevator 2 if it is defined
|
||||||
|
// tmpVal = m_aircraft->fwElevator2ChannelBox->currentIndex()-1;
|
||||||
|
// if (tmpVal > -1) {
|
||||||
|
// field = obj->getField(mixerTypes.at(tmpVal));
|
||||||
|
// field->setValue("Servo");
|
||||||
|
// field = obj->getField(mixerVectors.at(tmpVal));
|
||||||
|
// resetField(field);
|
||||||
|
// ti = field->getElementNames().indexOf("Pitch");
|
||||||
|
// field->setValue(127, ti);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// obj->updated();
|
||||||
|
// m_aircraft->fwStatusLabel->setText("Mixer generated");
|
||||||
|
//
|
||||||
|
// return true;
|
||||||
|
//}
|
||||||
|
//
|
||||||
|
///**
|
||||||
|
// Setup Elevon
|
||||||
|
// */
|
||||||
|
//bool ConfigVehicleTypeWidget::setupFrameElevon()
|
||||||
|
//{
|
||||||
|
// // Check coherence:
|
||||||
|
// // - At least Aileron1 and Aileron 2, and engine
|
||||||
|
// if (m_aircraft->fwEngineChannelBox->currentText() == "None" ||
|
||||||
|
// m_aircraft->fwAileron1ChannelBox->currentText() == "None" ||
|
||||||
|
// m_aircraft->fwAileron2ChannelBox->currentText() == "None") {
|
||||||
|
// // TODO: explain the problem in the UI
|
||||||
|
// m_aircraft->fwStatusLabel->setText("ERROR: check channel assignment");
|
||||||
|
// return false;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// resetActuators();
|
||||||
|
// UAVDataObject* obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("ActuatorSettings")));
|
||||||
|
// Q_ASSERT(obj);
|
||||||
|
//
|
||||||
|
// // Elevons
|
||||||
|
// UAVObjectField *field = obj->getField("FixedWingRoll1");
|
||||||
|
// Q_ASSERT(field);
|
||||||
|
// field->setValue(m_aircraft->fwAileron1ChannelBox->currentText());
|
||||||
|
// field = obj->getField("FixedWingRoll2");
|
||||||
|
// Q_ASSERT(field);
|
||||||
|
// field->setValue(m_aircraft->fwAileron2ChannelBox->currentText());
|
||||||
|
// // Rudder 1 (can be None)
|
||||||
|
// field = obj->getField("FixedWingYaw1");
|
||||||
|
// Q_ASSERT(field);
|
||||||
|
// field->setValue(m_aircraft->fwRudder1ChannelBox->currentText());
|
||||||
|
// // Rudder 2 (can be None)
|
||||||
|
// field = obj->getField("FixedWingYaw2");
|
||||||
|
// Q_ASSERT(field);
|
||||||
|
// field->setValue(m_aircraft->fwRudder2ChannelBox->currentText());
|
||||||
|
// // Throttle
|
||||||
|
// field = obj->getField("FixedWingThrottle");
|
||||||
|
// Q_ASSERT(field);
|
||||||
|
// field->setValue(m_aircraft->fwEngineChannelBox->currentText());
|
||||||
|
//
|
||||||
|
// obj->updated();
|
||||||
|
//
|
||||||
|
// // Save the curve:
|
||||||
|
// obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
|
||||||
|
// Q_ASSERT(obj);
|
||||||
|
// // ... and compute the matrix:
|
||||||
|
// // In order to make code a bit nicer, we assume:
|
||||||
|
// // - ChannelBox dropdowns start with 'None', then 0 to 7
|
||||||
|
//
|
||||||
|
// // 1. Assign the servo/motor/none for each channel
|
||||||
|
// // Disable all
|
||||||
|
// foreach(QString mixer, mixerTypes) {
|
||||||
|
// field = obj->getField(mixer);
|
||||||
|
// Q_ASSERT(field);
|
||||||
|
// field->setValue("Disabled");
|
||||||
|
// }
|
||||||
|
// // and set only the relevant channels:
|
||||||
|
// // Engine
|
||||||
|
// int tmpVal = m_aircraft->fwEngineChannelBox->currentIndex()-1;
|
||||||
|
// field = obj->getField(mixerTypes.at(tmpVal));
|
||||||
|
// field->setValue("Motor");
|
||||||
|
// field = obj->getField(mixerVectors.at(tmpVal));
|
||||||
|
// // First of all reset the vector
|
||||||
|
// resetField(field);
|
||||||
|
// int ti = field->getElementNames().indexOf("ThrottleCurve1");
|
||||||
|
// field->setValue(127, ti);
|
||||||
|
//
|
||||||
|
// // Rudder 1
|
||||||
|
// tmpVal = m_aircraft->fwRudder1ChannelBox->currentIndex()-1;
|
||||||
|
// // tmpVal will be -1 if rudder 1 is set to "None"
|
||||||
|
// if (tmpVal > -1) {
|
||||||
|
// field = obj->getField(mixerTypes.at(tmpVal));
|
||||||
|
// field->setValue("Servo");
|
||||||
|
// field = obj->getField(mixerVectors.at(tmpVal));
|
||||||
|
// resetField(field);
|
||||||
|
// ti = field->getElementNames().indexOf("Yaw");
|
||||||
|
// field->setValue(127, ti);
|
||||||
|
// } // Else: we have no rudder, only elevons, we're fine with it.
|
||||||
|
//
|
||||||
|
// // Rudder 2
|
||||||
|
// tmpVal = m_aircraft->fwRudder2ChannelBox->currentIndex()-1;
|
||||||
|
// // tmpVal will be -1 if rudder 2 is set to "None"
|
||||||
|
// if (tmpVal > -1) {
|
||||||
|
// field = obj->getField(mixerTypes.at(tmpVal));
|
||||||
|
// field->setValue("Servo");
|
||||||
|
// field = obj->getField(mixerVectors.at(tmpVal));
|
||||||
|
// resetField(field);
|
||||||
|
// ti = field->getElementNames().indexOf("Yaw");
|
||||||
|
// field->setValue(-127, ti);
|
||||||
|
// } // Else: we have no rudder, only elevons, we're fine with it.
|
||||||
|
//
|
||||||
|
// tmpVal = m_aircraft->fwAileron1ChannelBox->currentIndex()-1;
|
||||||
|
// if (tmpVal > -1) {
|
||||||
|
// field = obj->getField(mixerTypes.at(tmpVal));
|
||||||
|
// field->setValue("Servo");
|
||||||
|
// field = obj->getField(mixerVectors.at(tmpVal));
|
||||||
|
// resetField(field);
|
||||||
|
// ti = field->getElementNames().indexOf("Pitch");
|
||||||
|
// field->setValue((double)m_aircraft->elevonSlider2->value()*1.27, ti);
|
||||||
|
// ti = field->getElementNames().indexOf("Roll");
|
||||||
|
// field->setValue((double)m_aircraft->elevonSlider1->value()*1.27,ti);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// tmpVal = m_aircraft->fwAileron2ChannelBox->currentIndex()-1;
|
||||||
|
// if (tmpVal > -1) {
|
||||||
|
// field = obj->getField(mixerTypes.at(tmpVal));
|
||||||
|
// field->setValue("Servo");
|
||||||
|
// field = obj->getField(mixerVectors.at(tmpVal));
|
||||||
|
// resetField(field);
|
||||||
|
// ti = field->getElementNames().indexOf("Pitch");
|
||||||
|
// field->setValue((double)m_aircraft->elevonSlider2->value()*1.27, ti);
|
||||||
|
// ti = field->getElementNames().indexOf("Roll");
|
||||||
|
// field->setValue(-(double)m_aircraft->elevonSlider1->value()*1.27,ti);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// obj->updated();
|
||||||
|
// m_aircraft->fwStatusLabel->setText("Mixer generated");
|
||||||
|
// return true;
|
||||||
|
//}
|
||||||
|
//
|
||||||
|
//
|
||||||
|
///**
|
||||||
|
// Setup VTail
|
||||||
|
// */
|
||||||
|
//bool ConfigVehicleTypeWidget::setupFrameVtail()
|
||||||
|
//{
|
||||||
|
// // Check coherence:
|
||||||
|
// // - At least Pitch1 and Pitch2, and engine
|
||||||
|
// if (m_aircraft->fwEngineChannelBox->currentText() == "None" ||
|
||||||
|
// m_aircraft->fwElevator1ChannelBox->currentText() == "None" ||
|
||||||
|
// m_aircraft->fwElevator2ChannelBox->currentText() == "None") {
|
||||||
|
// // TODO: explain the problem in the UI
|
||||||
|
// m_aircraft->fwStatusLabel->setText("WARNING: check channel assignment");
|
||||||
|
// return false;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// resetActuators();
|
||||||
|
// UAVDataObject* obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("ActuatorSettings")));
|
||||||
|
// Q_ASSERT(obj);
|
||||||
|
//
|
||||||
|
// // Elevons
|
||||||
|
// UAVObjectField *field = obj->getField("FixedWingPitch1");
|
||||||
|
// Q_ASSERT(field);
|
||||||
|
// field->setValue(m_aircraft->fwElevator1ChannelBox->currentText());
|
||||||
|
// field = obj->getField("FixedWingPitch2");
|
||||||
|
// Q_ASSERT(field);
|
||||||
|
// field->setValue(m_aircraft->fwElevator2ChannelBox->currentText());
|
||||||
|
// field = obj->getField("FixedWingRoll1");
|
||||||
|
// Q_ASSERT(field);
|
||||||
|
// field->setValue(m_aircraft->fwAileron1ChannelBox->currentText());
|
||||||
|
// field = obj->getField("FixedWingRoll2");
|
||||||
|
// Q_ASSERT(field);
|
||||||
|
// field->setValue(m_aircraft->fwAileron2ChannelBox->currentText());
|
||||||
|
//
|
||||||
|
// // Throttle
|
||||||
|
// field = obj->getField("FixedWingThrottle");
|
||||||
|
// Q_ASSERT(field);
|
||||||
|
// field->setValue(m_aircraft->fwEngineChannelBox->currentText());
|
||||||
|
//
|
||||||
|
// obj->updated();
|
||||||
|
//
|
||||||
|
// obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
|
||||||
|
// Q_ASSERT(obj);
|
||||||
|
// // ... and compute the matrix:
|
||||||
|
// // In order to make code a bit nicer, we assume:
|
||||||
|
// // - ChannelBox dropdowns start with 'None', then 0 to 7
|
||||||
|
//
|
||||||
|
// // 1. Assign the servo/motor/none for each channel
|
||||||
|
// // Disable all
|
||||||
|
// foreach(QString mixer, mixerTypes) {
|
||||||
|
// field = obj->getField(mixer);
|
||||||
|
// Q_ASSERT(field);
|
||||||
|
// field->setValue("Disabled");
|
||||||
|
// }
|
||||||
|
// // and set only the relevant channels:
|
||||||
|
// // Engine
|
||||||
|
// int tmpVal = m_aircraft->fwEngineChannelBox->currentIndex()-1;
|
||||||
|
// field = obj->getField(mixerTypes.at(tmpVal));
|
||||||
|
// field->setValue("Motor");
|
||||||
|
// field = obj->getField(mixerVectors.at(tmpVal));
|
||||||
|
// // First of all reset the vector
|
||||||
|
// resetField(field);
|
||||||
|
// int ti = field->getElementNames().indexOf("ThrottleCurve1");
|
||||||
|
// field->setValue(127, ti);
|
||||||
|
//
|
||||||
|
// tmpVal = m_aircraft->fwAileron1ChannelBox->currentIndex()-1;
|
||||||
|
// if (tmpVal > -1) {
|
||||||
|
// field = obj->getField(mixerTypes.at(tmpVal));
|
||||||
|
// field->setValue("Servo");
|
||||||
|
// field = obj->getField(mixerVectors.at(tmpVal));
|
||||||
|
// resetField(field);
|
||||||
|
// ti = field->getElementNames().indexOf("Roll");
|
||||||
|
// field->setValue(127,ti);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// tmpVal = m_aircraft->fwAileron2ChannelBox->currentIndex()-1;
|
||||||
|
// if (tmpVal > -1) {
|
||||||
|
// field = obj->getField(mixerTypes.at(tmpVal));
|
||||||
|
// field->setValue("Servo");
|
||||||
|
// field = obj->getField(mixerVectors.at(tmpVal));
|
||||||
|
// resetField(field);
|
||||||
|
// ti = field->getElementNames().indexOf("Roll");
|
||||||
|
// field->setValue(-127,ti);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// // Now compute the VTail
|
||||||
|
// tmpVal = m_aircraft->fwElevator1ChannelBox->currentIndex()-1;
|
||||||
|
// field = obj->getField(mixerTypes.at(tmpVal));
|
||||||
|
// field->setValue("Servo");
|
||||||
|
// field = obj->getField(mixerVectors.at(tmpVal));
|
||||||
|
// resetField(field);
|
||||||
|
// ti = field->getElementNames().indexOf("Pitch");
|
||||||
|
// field->setValue((double)m_aircraft->elevonSlider2->value()*1.27, ti);
|
||||||
|
// ti = field->getElementNames().indexOf("Yaw");
|
||||||
|
// field->setValue((double)m_aircraft->elevonSlider1->value()*1.27,ti);
|
||||||
|
//
|
||||||
|
// tmpVal = m_aircraft->fwElevator2ChannelBox->currentIndex()-1;
|
||||||
|
// field = obj->getField(mixerTypes.at(tmpVal));
|
||||||
|
// field->setValue("Servo");
|
||||||
|
// field = obj->getField(mixerVectors.at(tmpVal));
|
||||||
|
// resetField(field);
|
||||||
|
// ti = field->getElementNames().indexOf("Pitch");
|
||||||
|
// field->setValue((double)m_aircraft->elevonSlider2->value()*1.27, ti);
|
||||||
|
// ti = field->getElementNames().indexOf("Yaw");
|
||||||
|
// field->setValue(-(double)m_aircraft->elevonSlider1->value()*1.27,ti);
|
||||||
|
//
|
||||||
|
// obj->updated();
|
||||||
|
// m_aircraft->fwStatusLabel->setText("Mixer generated");
|
||||||
|
// return true;
|
||||||
|
//}
|
||||||
|
|
||||||
|
|
||||||
|
///**
|
||||||
|
// Setup steerable ground vehicle.
|
||||||
|
//
|
||||||
|
// If both Aileron channels are set to 'None' (EasyStar), do Pitch/Rudder mixing
|
||||||
|
//
|
||||||
|
// Returns False if impossible to create the mixer.
|
||||||
|
// */
|
||||||
|
//bool ConfigVehicleTypeWidget::setupGroundVehicle()
|
||||||
|
//{
|
||||||
|
// // Check coherence:
|
||||||
|
// // - At least Pitch and either Roll or Yaw
|
||||||
|
// if ((m_aircraft->gvMotor1ChannelBox->currentText() == "None" &&
|
||||||
|
// m_aircraft->gvMotor2ChannelBox->currentText() == "None") ||
|
||||||
|
// (m_aircraft->gvSteering1ChannelBox->currentText() == "None" &&
|
||||||
|
// m_aircraft->gvSteering2ChannelBox->currentText() == "None")) {
|
||||||
|
// // TODO: explain the problem in the UI
|
||||||
|
// m_aircraft->gvStatusLabel->setText("<font color='red'>ERROR: check channel assignments</font>");
|
||||||
|
// if(m_aircraft->gvMotor1ChannelBox->currentText() == "None" && m_aircraft->gvMotor2ChannelBox->currentText() == "None"){
|
||||||
|
// m_aircraft->gvStatusLabel->setText("<font color='red'>ERROR: check motor channel assignment</font>");
|
||||||
|
// m_aircraft->gvMotor1Label->setText("<font color='red'>" + m_aircraft->gvMotor1Label->text() + "</font>");
|
||||||
|
// m_aircraft->gvMotor2Label->setText("<font color='red'>" + m_aircraft->gvMotor2Label->text() + "</font>");
|
||||||
|
//
|
||||||
|
// }
|
||||||
|
// else{
|
||||||
|
// 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->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>");
|
||||||
|
// }
|
||||||
|
// else{
|
||||||
|
// 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());
|
||||||
|
// }
|
||||||
|
// return false;
|
||||||
|
// }
|
||||||
|
// else{
|
||||||
|
//// m_aircraft->gvStatusLabel->setText("Mixer generated");
|
||||||
|
// 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());
|
||||||
|
// delete htmlText;
|
||||||
|
//
|
||||||
|
// 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 0
|
||||||
|
// // Now setup the channels:
|
||||||
|
// resetActuators();
|
||||||
|
//
|
||||||
|
// UAVDataObject* obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("ActuatorSettings")));
|
||||||
|
// Q_ASSERT(obj);
|
||||||
|
//
|
||||||
|
// // Elevator
|
||||||
|
// UAVObjectField *field = obj->getField("FixedWingPitch1");
|
||||||
|
// Q_ASSERT(field);
|
||||||
|
// field->setValue(m_aircraft->gvMotor1ChannelBox->currentText());
|
||||||
|
// field = obj->getField("FixedWingPitch2");
|
||||||
|
// Q_ASSERT(field);
|
||||||
|
// field->setValue(m_aircraft->gvMotor2ChannelBox->currentText());
|
||||||
|
// // Aileron
|
||||||
|
// field = obj->getField("FixedWingRoll1");
|
||||||
|
// Q_ASSERT(field);
|
||||||
|
// field->setValue(m_aircraft->fwAileron1ChannelBox->currentText());
|
||||||
|
// field = obj->getField("FixedWingRoll2");
|
||||||
|
// Q_ASSERT(field);
|
||||||
|
// field->setValue(m_aircraft->fwAileron2ChannelBox->currentText());
|
||||||
|
// // Rudder
|
||||||
|
// field = obj->getField("FixedWingYaw1");
|
||||||
|
// Q_ASSERT(field);
|
||||||
|
// field->setValue(m_aircraft->gvSteering1ChannelBox->currentText());
|
||||||
|
// // Throttle
|
||||||
|
// field = obj->getField("FixedWingThrottle");
|
||||||
|
// Q_ASSERT(field);
|
||||||
|
// field->setValue(m_aircraft->gvSteering2ChannelBox->currentText());
|
||||||
|
//
|
||||||
|
// obj->updated();
|
||||||
|
//
|
||||||
|
// obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
|
||||||
|
// Q_ASSERT(obj);
|
||||||
|
// // ... and compute the matrix:
|
||||||
|
// // In order to make code a bit nicer, we assume:
|
||||||
|
// // - ChannelBox dropdowns start with 'None', then 0 to 7
|
||||||
|
//
|
||||||
|
// // 1. Assign the servo/motor/none for each channel
|
||||||
|
// // Disable all
|
||||||
|
// foreach(QString mixer, mixerTypes) {
|
||||||
|
// field = obj->getField(mixer);
|
||||||
|
// Q_ASSERT(field);
|
||||||
|
// field->setValue("Disabled");
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// int tmpVal, ti;
|
||||||
|
//#if 0
|
||||||
|
// // and set only the relevant channels:
|
||||||
|
// // Engine
|
||||||
|
// tmpVal = m_aircraft->fwEngineChannelBox->currentIndex()-1;
|
||||||
|
// field = obj->getField(mixerTypes.at(tmpVal));
|
||||||
|
// field->setValue("Motor");
|
||||||
|
// field = obj->getField(mixerVectors.at(tmpVal));
|
||||||
|
// // First of all reset the vector
|
||||||
|
// resetField(field);
|
||||||
|
// ti = field->getElementNames().indexOf("ThrottleCurve1");
|
||||||
|
// field->setValue(127, ti);
|
||||||
|
//#endif
|
||||||
|
// // Steering
|
||||||
|
// tmpVal = m_aircraft->gvSteering1ChannelBox->currentIndex()-1;
|
||||||
|
// // tmpVal will be -1 if steering is set to "None"
|
||||||
|
// if (tmpVal > -1) {
|
||||||
|
// field = obj->getField(mixerTypes.at(tmpVal));
|
||||||
|
// field->setValue("Servo");
|
||||||
|
// field = obj->getField(mixerVectors.at(tmpVal));
|
||||||
|
// resetField(field);
|
||||||
|
// ti = field->getElementNames().indexOf("Yaw");
|
||||||
|
// field->setValue(127, ti);
|
||||||
|
// } // Else: we have no rudder, only ailerons, we're fine with it.
|
||||||
|
//
|
||||||
|
//#if 0
|
||||||
|
// // Ailerons
|
||||||
|
// tmpVal = m_aircraft->fwAileron1ChannelBox->currentIndex()-1;
|
||||||
|
// if (tmpVal > -1) {
|
||||||
|
// field = obj->getField(mixerTypes.at(tmpVal));
|
||||||
|
// field->setValue("Servo");
|
||||||
|
// field = obj->getField(mixerVectors.at(tmpVal));
|
||||||
|
// resetField(field);
|
||||||
|
// ti = field->getElementNames().indexOf("Roll");
|
||||||
|
// field->setValue(127, ti);
|
||||||
|
// // Only set Aileron 2 if Aileron 1 is defined
|
||||||
|
// tmpVal = m_aircraft->fwAileron2ChannelBox->currentIndex()-1;
|
||||||
|
// if (tmpVal > -1) {
|
||||||
|
// field = obj->getField(mixerTypes.at(tmpVal));
|
||||||
|
// field->setValue("Servo");
|
||||||
|
// field = obj->getField(mixerVectors.at(tmpVal));
|
||||||
|
// resetField(field);
|
||||||
|
// ti = field->getElementNames().indexOf("Roll");
|
||||||
|
// field->setValue(127, ti);
|
||||||
|
// }
|
||||||
|
// } // Else we have no ailerons. Our consistency check guarantees we have
|
||||||
|
// // rudder in this case, so we're fine with it too.
|
||||||
|
//#endif
|
||||||
|
//
|
||||||
|
// // Motor
|
||||||
|
// tmpVal = m_aircraft->gvMotor1ChannelBox->currentIndex()-1;
|
||||||
|
// field = obj->getField(mixerTypes.at(tmpVal));
|
||||||
|
// field->setValue("Servo");
|
||||||
|
// field = obj->getField(mixerVectors.at(tmpVal));
|
||||||
|
// resetField(field);
|
||||||
|
// ti = field->getElementNames().indexOf("ThrottleCurve1");
|
||||||
|
// field->setValue(127, ti);
|
||||||
|
//
|
||||||
|
// // Only set Motor 2 if it is defined
|
||||||
|
// tmpVal = m_aircraft->gvMotor2ChannelBox->currentIndex()-1;
|
||||||
|
// if (tmpVal > -1) {
|
||||||
|
// field = obj->getField(mixerTypes.at(tmpVal));
|
||||||
|
// field->setValue("Servo");
|
||||||
|
// field = obj->getField(mixerVectors.at(tmpVal));
|
||||||
|
// resetField(field);
|
||||||
|
// ti = field->getElementNames().indexOf("ThrottleCurve2");
|
||||||
|
// field->setValue(127, ti);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// obj->updated();
|
||||||
|
////#endif
|
||||||
|
// m_aircraft->gvStatusLabel->setText("Mixer generated");
|
||||||
|
//
|
||||||
|
// return true;
|
||||||
|
//}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Set up a complete mixer, taking a table of factors. The factors
|
||||||
|
shoudl mainly be +/- 1 factors, since they will be weighted by the
|
||||||
|
value of the Pitch/Roll/Yaw sliders.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
double xMixer [8][3] = {
|
||||||
|
P R Y
|
||||||
|
{ 1, 1, -1}, Motor 1
|
||||||
|
{ 1, -1, 1}, Motor 2
|
||||||
|
{-1, -1, -1}, Motor 3
|
||||||
|
{-1, 1, 1}, ...
|
||||||
|
{ 0, 0, 0},
|
||||||
|
{ 0, 0, 0},
|
||||||
|
{ 0, 0, 0},
|
||||||
|
{ 0, 0, 0}
|
||||||
|
};
|
||||||
|
*/
|
||||||
|
//bool ConfigVehicleTypeWidget::setupMultiRotorMixer(double mixerFactors[8][3])
|
||||||
|
//{
|
||||||
|
// qDebug()<<"Mixer factors";
|
||||||
|
// qDebug()<<mixerFactors[0][0]<<" "<<mixerFactors[0][1]<<" "<<mixerFactors[0][2];
|
||||||
|
// qDebug()<<mixerFactors[1][0]<<" "<<mixerFactors[1][1]<<" "<<mixerFactors[1][2];
|
||||||
|
// qDebug()<<mixerFactors[2][0]<<" "<<mixerFactors[2][1]<<" "<<mixerFactors[2][2];
|
||||||
|
// qDebug()<<mixerFactors[3][0]<<" "<<mixerFactors[3][1]<<" "<<mixerFactors[3][2];
|
||||||
|
// qDebug()<<mixerFactors[4][0]<<" "<<mixerFactors[4][1]<<" "<<mixerFactors[4][2];
|
||||||
|
// qDebug()<<mixerFactors[5][0]<<" "<<mixerFactors[5][1]<<" "<<mixerFactors[5][2];
|
||||||
|
// qDebug()<<mixerFactors[6][0]<<" "<<mixerFactors[6][1]<<" "<<mixerFactors[6][2];
|
||||||
|
// qDebug()<<mixerFactors[7][0]<<" "<<mixerFactors[7][1]<<" "<<mixerFactors[7][2];
|
||||||
|
//
|
||||||
|
// UAVObjectField *field;
|
||||||
|
// 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 *obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
|
||||||
|
// // 1. Assign the servo/motor/none for each channel
|
||||||
|
// // Disable all
|
||||||
|
// foreach(QString mixer, mixerTypes) {
|
||||||
|
// field = obj->getField(mixer);
|
||||||
|
// Q_ASSERT(field);
|
||||||
|
// field->setValue("Disabled");
|
||||||
|
// }
|
||||||
|
// // and enable only the relevant channels:
|
||||||
|
// double pFactor = (double)m_aircraft->mrPitchMixLevel->value()/100;
|
||||||
|
// double rFactor = (double)m_aircraft->mrRollMixLevel->value()/100;
|
||||||
|
// double yFactor = (double)m_aircraft->mrYawMixLevel->value()/100;
|
||||||
|
// qDebug()<<QString("pFactor=%0 rFactor=%1 yFactor=%2").arg(pFactor).arg(rFactor).arg(yFactor);
|
||||||
|
// 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]);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//// obj->updated();
|
||||||
|
// return true;
|
||||||
|
//}
|
||||||
|
|
||||||
|
|
||||||
|
///**
|
||||||
|
// Helper function: setupQuadMotor
|
||||||
|
// */
|
||||||
|
//void ConfigVehicleTypeWidget::setupQuadMotor(int channel, double pitch, double roll, double yaw)
|
||||||
|
//{
|
||||||
|
// qDebug()<<QString("Setup quad motor channel=%0 pitch=%1 roll=%2 yaw=%3").arg(channel).arg(pitch).arg(roll).arg(yaw);
|
||||||
|
// UAVDataObject* obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
|
||||||
|
// Q_ASSERT(obj);
|
||||||
|
// UAVObjectField *field = obj->getField(mixerTypes.at(channel));
|
||||||
|
// field->setValue("Motor");
|
||||||
|
// field = obj->getField(mixerVectors.at(channel));
|
||||||
|
// // First of all reset the vector
|
||||||
|
// resetField(field);
|
||||||
|
// int ti = field->getElementNames().indexOf("ThrottleCurve1");
|
||||||
|
// field->setValue(127, ti);
|
||||||
|
// ti = field->getElementNames().indexOf("Roll");
|
||||||
|
// field->setValue(roll*127,ti);
|
||||||
|
// qDebug()<<"Set roll="<<roll*127;
|
||||||
|
// ti = field->getElementNames().indexOf("Pitch");
|
||||||
|
// field->setValue(pitch*127,ti);
|
||||||
|
// qDebug()<<"Set pitch="<<pitch*127;
|
||||||
|
// ti = field->getElementNames().indexOf("Yaw");
|
||||||
|
// field->setValue(yaw*127,ti);
|
||||||
|
// qDebug()<<"Set yaw="<<yaw*127;
|
||||||
|
//}
|
||||||
|
|
||||||
|
///**
|
||||||
|
// Helper function: setup motors. Takes a list of channel names in input.
|
||||||
|
// */
|
||||||
|
//void ConfigVehicleTypeWidget::setupMotors(QList<QString> motorList)
|
||||||
|
//{
|
||||||
|
// resetActuators();
|
||||||
|
// UAVDataObject* obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("ActuatorSettings")));
|
||||||
|
// Q_ASSERT(obj);
|
||||||
|
// UAVObjectField *field;
|
||||||
|
// QList<QComboBox*> mmList;
|
||||||
|
// mmList << m_aircraft->multiMotor1 << m_aircraft->multiMotor2 << m_aircraft->multiMotor3
|
||||||
|
// << m_aircraft->multiMotor4 << m_aircraft->multiMotor5 << m_aircraft->multiMotor6
|
||||||
|
// << m_aircraft->multiMotor7 << m_aircraft->multiMotor8;
|
||||||
|
// foreach (QString motor, motorList) {
|
||||||
|
// field = obj->getField(motor);
|
||||||
|
// field->setValue(mmList.takeFirst()->currentText());
|
||||||
|
// }
|
||||||
|
// //obj->updated(); // Save...
|
||||||
|
//}
|
||||||
|
|
||||||
|
|
||||||
|
///**
|
||||||
|
// Set up a Quad-X or Quad-P
|
||||||
|
//*/
|
||||||
|
//bool ConfigVehicleTypeWidget::setupQuad(bool pLayout)
|
||||||
|
//{
|
||||||
|
// // Check coherence:
|
||||||
|
// // - Four engines have to be defined
|
||||||
|
// if (m_aircraft->multiMotor1->currentText() == "None" ||
|
||||||
|
// m_aircraft->multiMotor2->currentText() == "None" ||
|
||||||
|
// m_aircraft->multiMotor3->currentText() == "None" ||
|
||||||
|
// m_aircraft->multiMotor4->currentText() == "None") {
|
||||||
|
// m_aircraft->mrStatusLabel->setText("ERROR: Assign 4 motor channels");
|
||||||
|
// return false;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// QList<QString> motorList;
|
||||||
|
// if (pLayout) {
|
||||||
|
// motorList << "VTOLMotorN" << "VTOLMotorE" << "VTOLMotorS"
|
||||||
|
// << "VTOLMotorW";
|
||||||
|
// } else {
|
||||||
|
// motorList << "VTOLMotorNW" << "VTOLMotorNE" << "VTOLMotorSE"
|
||||||
|
// << "VTOLMotorSW";
|
||||||
|
// }
|
||||||
|
// setupMotors(motorList);
|
||||||
|
//
|
||||||
|
// // Now, setup the mixer:
|
||||||
|
// // Motor 1 to 4, X Layout:
|
||||||
|
// // pitch roll yaw
|
||||||
|
// // {0.5 ,0.5 ,-0.5 //Front left motor (CW)
|
||||||
|
// // {0.5 ,-0.5 ,0.5 //Front right motor(CCW)
|
||||||
|
// // {-0.5 ,-0.5 ,-0.5 //rear right motor (CW)
|
||||||
|
// // {-0.5 ,0.5 ,0.5 //Rear left motor (CCW)
|
||||||
|
// double xMixer [8][3] = {
|
||||||
|
// { 1, 1, -1},
|
||||||
|
// { 1, -1, 1},
|
||||||
|
// {-1, -1, -1},
|
||||||
|
// {-1, 1, 1},
|
||||||
|
// { 0, 0, 0},
|
||||||
|
// { 0, 0, 0},
|
||||||
|
// { 0, 0, 0},
|
||||||
|
// { 0, 0, 0}
|
||||||
|
// };
|
||||||
|
// //
|
||||||
|
// // Motor 1 to 4, P Layout:
|
||||||
|
// // pitch roll yaw
|
||||||
|
// // {1 ,0 ,-0.5 //Front motor (CW)
|
||||||
|
// // {0 ,-1 ,0.5 //Right motor(CCW)
|
||||||
|
// // {-1 ,0 ,-0.5 //Rear motor (CW)
|
||||||
|
// // {0 ,1 ,0.5 //Left motor (CCW)
|
||||||
|
// double pMixer [8][3] = {
|
||||||
|
// { 1, 0, -1},
|
||||||
|
// { 0, -1, 1},
|
||||||
|
// {-1, 0, -1},
|
||||||
|
// { 0, 1, 1},
|
||||||
|
// { 0, 0, 0},
|
||||||
|
// { 0, 0, 0},
|
||||||
|
// { 0, 0, 0},
|
||||||
|
// { 0, 0, 0}
|
||||||
|
// };
|
||||||
|
//
|
||||||
|
// if (pLayout) {
|
||||||
|
// setupMultiRotorMixer(pMixer);
|
||||||
|
// } else {
|
||||||
|
// setupMultiRotorMixer(xMixer);
|
||||||
|
// }
|
||||||
|
// m_aircraft->mrStatusLabel->setText("SUCCESS: Mixer Saved OK");
|
||||||
|
// return true;
|
||||||
|
//}
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
///**
|
||||||
|
// Set up a Hexa-X or Hexa-P
|
||||||
|
//*/
|
||||||
|
//bool ConfigVehicleTypeWidget::setupHexa(bool pLayout)
|
||||||
|
//{
|
||||||
|
// // Check coherence:
|
||||||
|
// // - Four engines have to be defined
|
||||||
|
// if (m_aircraft->multiMotor1->currentText() == "None" ||
|
||||||
|
// m_aircraft->multiMotor2->currentText() == "None" ||
|
||||||
|
// m_aircraft->multiMotor3->currentText() == "None" ||
|
||||||
|
// m_aircraft->multiMotor4->currentText() == "None" ||
|
||||||
|
// m_aircraft->multiMotor5->currentText() == "None" ||
|
||||||
|
// m_aircraft->multiMotor6->currentText() == "None") {
|
||||||
|
// m_aircraft->mrStatusLabel->setText("ERROR: Assign 6 motor channels");
|
||||||
|
// return false;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// QList<QString> motorList;
|
||||||
|
// if (pLayout) {
|
||||||
|
// motorList << "VTOLMotorN" << "VTOLMotorNE" << "VTOLMotorSE"
|
||||||
|
// << "VTOLMotorS" << "VTOLMotorSW" << "VTOLMotorNW";
|
||||||
|
// } else {
|
||||||
|
// motorList << "VTOLMotorNE" << "VTOLMotorE" << "VTOLMotorSE"
|
||||||
|
// << "VTOLMotorSW" << "VTOLMotorW" << "VTOLMotorNW";
|
||||||
|
// }
|
||||||
|
// setupMotors(motorList);
|
||||||
|
//
|
||||||
|
// // and set only the relevant channels:
|
||||||
|
//
|
||||||
|
// // Motor 1 to 6, P Layout:
|
||||||
|
// // pitch roll yaw
|
||||||
|
// // 1 { 0.3 , 0 ,-0.3 // N CW
|
||||||
|
// // 2 { 0.3 ,-0.5 , 0.3 // NE CCW
|
||||||
|
// // 3 {-0.3 ,-0.5 ,-0.3 // SE CW
|
||||||
|
// // 4 {-0.3 , 0 , 0.3 // S CCW
|
||||||
|
// // 5 {-0.3 , 0.5 ,-0.3 // SW CW
|
||||||
|
// // 6 { 0.3 , 0.5 , 0.3 // NW CCW
|
||||||
|
//
|
||||||
|
// double pMixer [8][3] = {
|
||||||
|
// { 1, 0, -1},
|
||||||
|
// { 1, -1, 1},
|
||||||
|
// {-1, -1, -1},
|
||||||
|
// {-1, 0, 1},
|
||||||
|
// {-1, 1, -1},
|
||||||
|
// { 1, 1, 1},
|
||||||
|
// { 0, 0, 0},
|
||||||
|
// { 0, 0, 0}
|
||||||
|
// };
|
||||||
|
//
|
||||||
|
// //
|
||||||
|
// // Motor 1 to 6, X Layout:
|
||||||
|
// // 1 [ 0.5, -0.3, -0.3 ] NE
|
||||||
|
// // 2 [ 0 , -0.3, 0.3 ] E
|
||||||
|
// // 3 [ -0.5, -0.3, -0.3 ] SE
|
||||||
|
// // 4 [ -0.5, 0.3, 0.3 ] SW
|
||||||
|
// // 5 [ 0 , 0.3, -0.3 ] W
|
||||||
|
// // 6 [ 0.5, 0.3, 0.3 ] NW
|
||||||
|
// double xMixer [8][3] = {
|
||||||
|
// { 1, -1, -1},
|
||||||
|
// { 0, -1, 1},
|
||||||
|
// { -1, -1, -1},
|
||||||
|
// { -1, 1, 1},
|
||||||
|
// { 0, 1, -1},
|
||||||
|
// { 1, 1, 1},
|
||||||
|
// { 0, 0, 0},
|
||||||
|
// { 0, 0, 0}
|
||||||
|
// };
|
||||||
|
//
|
||||||
|
// if (pLayout) {
|
||||||
|
// setupMultiRotorMixer(pMixer);
|
||||||
|
// } else {
|
||||||
|
// setupMultiRotorMixer(xMixer);
|
||||||
|
// }
|
||||||
|
// m_aircraft->mrStatusLabel->setText("SUCCESS: Mixer Saved OK");
|
||||||
|
// return true;
|
||||||
|
//}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Updates the custom airframe settings based on the current airframe.
|
||||||
|
|
||||||
|
Note: does NOT ask for an object refresh itself!
|
||||||
|
*/
|
||||||
|
void ConfigVehicleTypeWidget::updateCustomAirframeUI()
|
||||||
|
{
|
||||||
|
UAVDataObject* obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
|
||||||
|
UAVObjectField* field = obj->getField(QString("ThrottleCurve1"));
|
||||||
|
QList<double> curveValues;
|
||||||
|
// If the 1st element of the curve is <= -10, then the curve
|
||||||
|
// is a straight line (that's how the mixer works on the mainboard):
|
||||||
|
if (field->getValue(0).toInt() <= -10) {
|
||||||
|
m_aircraft->customThrottle1Curve->initLinearCurve(field->getNumElements(),(double)1);
|
||||||
|
} else {
|
||||||
|
double temp=0;
|
||||||
|
double value;
|
||||||
|
for (unsigned int i=0; i < field->getNumElements(); i++) {
|
||||||
|
value=field->getValue(i).toDouble();
|
||||||
|
temp+=value;
|
||||||
|
curveValues.append(value);
|
||||||
|
}
|
||||||
|
if(temp==0)
|
||||||
|
m_aircraft->customThrottle1Curve->initLinearCurve(field->getNumElements(),(double)1);
|
||||||
|
else
|
||||||
|
m_aircraft->customThrottle1Curve->initCurve(curveValues);
|
||||||
|
}
|
||||||
|
|
||||||
|
field = obj->getField(QString("ThrottleCurve2"));
|
||||||
|
curveValues.clear();
|
||||||
|
// If the 1st element of the curve is <= -10, then the curve
|
||||||
|
// is a straight line (that's how the mixer works on the mainboard):
|
||||||
|
if (field->getValue(0).toInt() <= -10) {
|
||||||
|
m_aircraft->customThrottle2Curve->initLinearCurve(field->getNumElements(),(double)1);
|
||||||
|
} else {
|
||||||
|
for (unsigned int i=0; i < field->getNumElements(); i++) {
|
||||||
|
curveValues.append(field->getValue(i).toDouble());
|
||||||
|
}
|
||||||
|
m_aircraft->customThrottle2Curve->initCurve(curveValues);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update the table:
|
||||||
|
for (int i=0; i<8; i++) {
|
||||||
|
field = obj->getField(mixerTypes.at(i));
|
||||||
|
QComboBox* q = (QComboBox*)m_aircraft->customMixerTable->cellWidget(0,i);
|
||||||
|
QString s = field->getValue().toString();
|
||||||
|
q->setCurrentIndex(q->findText(s));
|
||||||
|
//bool en = (s != "Disabled");
|
||||||
|
field = obj->getField(mixerVectors.at(i));
|
||||||
|
int ti = field->getElementNames().indexOf("ThrottleCurve1");
|
||||||
|
m_aircraft->customMixerTable->item(1,i)->setText(field->getValue(ti).toString());
|
||||||
|
ti = field->getElementNames().indexOf("ThrottleCurve2");
|
||||||
|
m_aircraft->customMixerTable->item(2,i)->setText(field->getValue(ti).toString());
|
||||||
|
ti = field->getElementNames().indexOf("Roll");
|
||||||
|
m_aircraft->customMixerTable->item(3,i)->setText(field->getValue(ti).toString());
|
||||||
|
ti = field->getElementNames().indexOf("Pitch");
|
||||||
|
m_aircraft->customMixerTable->item(4,i)->setText(field->getValue(ti).toString());
|
||||||
|
ti = field->getElementNames().indexOf("Yaw");
|
||||||
|
m_aircraft->customMixerTable->item(5,i)->setText(field->getValue(ti).toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Sends the config to the board (airframe type)
|
||||||
|
|
||||||
|
We do all the tasks common to all airframes, or family of airframes, and
|
||||||
|
we call additional methods for specific frames, so that we do not have a code
|
||||||
|
that is too heavy.
|
||||||
|
*/
|
||||||
|
void ConfigVehicleTypeWidget::updateObjectsFromWidgets()
|
||||||
|
{
|
||||||
|
qDebug()<<"updateObjectsFromWidgets";
|
||||||
|
QString airframeType = "Custom"; //Sets airframe type default to "Custom"
|
||||||
|
if (m_aircraft->aircraftType->currentText() == "Fixed Wing") {
|
||||||
|
if(1){
|
||||||
|
airframeType = updateFixedWingObjectsFromWidgets();
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
// // Save the curve (common to all Fixed wing frames)
|
||||||
|
// UAVDataObject *obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
|
||||||
|
// // Remove Feed Forward, it is pointless on a plane:
|
||||||
|
// UAVObjectField* field = obj->getField(QString("FeedForward"));
|
||||||
|
// field->setDouble(0);
|
||||||
|
// field = obj->getField("ThrottleCurve1");
|
||||||
|
// QList<double> curve = m_aircraft->fixedWingThrottle->getCurve();
|
||||||
|
// for (int i=0;i<curve.length();i++) {
|
||||||
|
// field->setValue(curve.at(i),i);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// if (m_aircraft->fixedWingType->currentText() == "Elevator aileron rudder" ) {
|
||||||
|
// airframeType = "FixedWing";
|
||||||
|
// setupFrameFixedWing();
|
||||||
|
// } else if (m_aircraft->fixedWingType->currentText() == "Elevon") {
|
||||||
|
// airframeType = "FixedWingElevon";
|
||||||
|
// setupFrameElevon();
|
||||||
|
// } else { // "Vtail"
|
||||||
|
// airframeType = "FixedWingVtail";
|
||||||
|
// setupFrameVtail();
|
||||||
|
// }
|
||||||
|
// // Now reflect those settings in the "Custom" panel as well
|
||||||
|
// updateCustomAirframeUI();
|
||||||
|
}
|
||||||
|
} else if (m_aircraft->aircraftType->currentText() == "Multirotor") {
|
||||||
|
|
||||||
|
//update the mixer
|
||||||
|
if(1){
|
||||||
|
airframeType = updateMultiRotorObjectsFromWidgets();
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
//
|
||||||
|
// QList<QString> motorList;
|
||||||
|
//
|
||||||
|
// // We can already setup the feedforward here, as it is common to all platforms
|
||||||
|
// UAVDataObject* obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
|
||||||
|
// UAVObjectField* field = obj->getField(QString("FeedForward"));
|
||||||
|
// field->setDouble((double)m_aircraft->feedForwardSlider->value()/100);
|
||||||
|
// field = obj->getField(QString("AccelTime"));
|
||||||
|
// field->setDouble(m_aircraft->accelTime->value());
|
||||||
|
// field = obj->getField(QString("DecelTime"));
|
||||||
|
// field->setDouble(m_aircraft->decelTime->value());
|
||||||
|
// field = obj->getField(QString("MaxAccel"));
|
||||||
|
// field->setDouble(m_aircraft->maxAccelSlider->value());
|
||||||
|
//
|
||||||
|
// // Curve is also common to all quads:
|
||||||
|
// field = obj->getField("ThrottleCurve1");
|
||||||
|
// QList<double> curve = m_aircraft->multiThrottleCurve->getCurve();
|
||||||
|
// for (int i=0;i<curve.length();i++) {
|
||||||
|
// field->setValue(curve.at(i),i);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// if (m_aircraft->multirotorFrameType->currentText() == "Quad +") {
|
||||||
|
// airframeType = "QuadP";
|
||||||
|
// setupQuad(true);
|
||||||
|
// } else if (m_aircraft->multirotorFrameType->currentText() == "Quad X") {
|
||||||
|
// airframeType = "QuadX";
|
||||||
|
// setupQuad(false);
|
||||||
|
// } else if (m_aircraft->multirotorFrameType->currentText() == "Hexacopter") {
|
||||||
|
// airframeType = "Hexa";
|
||||||
|
// setupHexa(true);
|
||||||
|
// } else if (m_aircraft->multirotorFrameType->currentText() == "Octocopter") {
|
||||||
|
// airframeType = "Octo";
|
||||||
|
// if (m_aircraft->multiMotor1->currentText() == "None" ||
|
||||||
|
// m_aircraft->multiMotor2->currentText() == "None" ||
|
||||||
|
// m_aircraft->multiMotor3->currentText() == "None" ||
|
||||||
|
// m_aircraft->multiMotor4->currentText() == "None" ||
|
||||||
|
// m_aircraft->multiMotor5->currentText() == "None" ||
|
||||||
|
// m_aircraft->multiMotor6->currentText() == "None" ||
|
||||||
|
// m_aircraft->multiMotor7->currentText() == "None" ||
|
||||||
|
// m_aircraft->multiMotor8->currentText() == "None") {
|
||||||
|
// m_aircraft->mrStatusLabel->setText("ERROR: Assign 8 motor channels");
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
// motorList << "VTOLMotorN" << "VTOLMotorNE" << "VTOLMotorE" << "VTOLMotorSE"
|
||||||
|
// << "VTOLMotorS" << "VTOLMotorSW" << "VTOLMotorW" << "VTOLMotorNW";
|
||||||
|
// setupMotors(motorList);
|
||||||
|
// // Motor 1 to 8:
|
||||||
|
// // pitch roll yaw
|
||||||
|
// double mixer [8][3] = {
|
||||||
|
// { 1, 0, -1},
|
||||||
|
// { 1, -1, 1},
|
||||||
|
// { 0, -1, -1},
|
||||||
|
// { -1, -1, 1},
|
||||||
|
// { -1, 0, -1},
|
||||||
|
// { -1, 1, 1},
|
||||||
|
// { 0, 1, -1},
|
||||||
|
// { 1, 1, 1}
|
||||||
|
// };
|
||||||
|
// setupMultiRotorMixer(mixer);
|
||||||
|
// m_aircraft->mrStatusLabel->setText("SUCCESS: Mixer Saved OK");
|
||||||
|
//
|
||||||
|
// } else if (m_aircraft->multirotorFrameType->currentText() == "Hexacopter X") {
|
||||||
|
// airframeType = "HexaX";
|
||||||
|
// setupHexa(false);
|
||||||
|
// } else if (m_aircraft->multirotorFrameType->currentText() == "Octocopter V") {
|
||||||
|
// airframeType = "OctoV";
|
||||||
|
// if (m_aircraft->multiMotor1->currentText() == "None" ||
|
||||||
|
// m_aircraft->multiMotor2->currentText() == "None" ||
|
||||||
|
// m_aircraft->multiMotor3->currentText() == "None" ||
|
||||||
|
// m_aircraft->multiMotor4->currentText() == "None" ||
|
||||||
|
// m_aircraft->multiMotor5->currentText() == "None" ||
|
||||||
|
// m_aircraft->multiMotor6->currentText() == "None" ||
|
||||||
|
// m_aircraft->multiMotor7->currentText() == "None" ||
|
||||||
|
// m_aircraft->multiMotor8->currentText() == "None") {
|
||||||
|
// m_aircraft->mrStatusLabel->setText("ERROR: Assign 8 motor channels");
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
// motorList << "VTOLMotorN" << "VTOLMotorNE" << "VTOLMotorE" << "VTOLMotorSE"
|
||||||
|
// << "VTOLMotorS" << "VTOLMotorSW" << "VTOLMotorW" << "VTOLMotorNW";
|
||||||
|
// setupMotors(motorList);
|
||||||
|
// // Motor 1 to 8:
|
||||||
|
// // IMPORTANT: Assumes evenly spaced engines
|
||||||
|
// // pitch roll yaw
|
||||||
|
// double mixer [8][3] = {
|
||||||
|
// { 0.33, -1, -1},
|
||||||
|
// { 1 , -1, 1},
|
||||||
|
// { -1 , -1, -1},
|
||||||
|
// { -0.33, -1, 1},
|
||||||
|
// { -0.33, 1, -1},
|
||||||
|
// { -1 , 1, 1},
|
||||||
|
// { 1 , 1, -1},
|
||||||
|
// { 0.33, 1, 1}
|
||||||
|
// };
|
||||||
|
// setupMultiRotorMixer(mixer);
|
||||||
|
// m_aircraft->mrStatusLabel->setText("SUCCESS: Mixer Saved OK");
|
||||||
|
//
|
||||||
|
// } else if (m_aircraft->multirotorFrameType->currentText() == "Octo Coax +") {
|
||||||
|
// airframeType = "OctoCoaxP";
|
||||||
|
// if (m_aircraft->multiMotor1->currentText() == "None" ||
|
||||||
|
// m_aircraft->multiMotor2->currentText() == "None" ||
|
||||||
|
// m_aircraft->multiMotor3->currentText() == "None" ||
|
||||||
|
// m_aircraft->multiMotor4->currentText() == "None" ||
|
||||||
|
// m_aircraft->multiMotor5->currentText() == "None" ||
|
||||||
|
// m_aircraft->multiMotor6->currentText() == "None" ||
|
||||||
|
// m_aircraft->multiMotor7->currentText() == "None" ||
|
||||||
|
// m_aircraft->multiMotor8->currentText() == "None") {
|
||||||
|
// m_aircraft->mrStatusLabel->setText("ERROR: Assign 8 motor channels");
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
// motorList << "VTOLMotorN" << "VTOLMotorNE" << "VTOLMotorE" << "VTOLMotorSE"
|
||||||
|
// << "VTOLMotorS" << "VTOLMotorSW" << "VTOLMotorW" << "VTOLMotorNW";
|
||||||
|
// setupMotors(motorList);
|
||||||
|
// // Motor 1 to 8:
|
||||||
|
// // pitch roll yaw
|
||||||
|
// double mixer [8][3] = {
|
||||||
|
// { 1, 0, -1},
|
||||||
|
// { 1, 0, 1},
|
||||||
|
// { 0, -1, -1},
|
||||||
|
// { 0, -1, 1},
|
||||||
|
// { -1, 0, -1},
|
||||||
|
// { -1, 0, 1},
|
||||||
|
// { 0, 1, -1},
|
||||||
|
// { 0, 1, 1}
|
||||||
|
// };
|
||||||
|
// setupMultiRotorMixer(mixer);
|
||||||
|
// m_aircraft->mrStatusLabel->setText("SUCCESS: Mixer Saved OK");
|
||||||
|
//
|
||||||
|
// } else if (m_aircraft->multirotorFrameType->currentText() == "Octo Coax X") {
|
||||||
|
// airframeType = "OctoCoaxX";
|
||||||
|
// if (m_aircraft->multiMotor1->currentText() == "None" ||
|
||||||
|
// m_aircraft->multiMotor2->currentText() == "None" ||
|
||||||
|
// m_aircraft->multiMotor3->currentText() == "None" ||
|
||||||
|
// m_aircraft->multiMotor4->currentText() == "None" ||
|
||||||
|
// m_aircraft->multiMotor5->currentText() == "None" ||
|
||||||
|
// m_aircraft->multiMotor6->currentText() == "None" ||
|
||||||
|
// m_aircraft->multiMotor7->currentText() == "None" ||
|
||||||
|
// m_aircraft->multiMotor8->currentText() == "None") {
|
||||||
|
// m_aircraft->mrStatusLabel->setText("ERROR: Assign 8 motor channels");
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
// motorList << "VTOLMotorNW" << "VTOLMotorN" << "VTOLMotorNE" << "VTOLMotorE"
|
||||||
|
// << "VTOLMotorSE" << "VTOLMotorS" << "VTOLMotorSW" << "VTOLMotorW";
|
||||||
|
// setupMotors(motorList);
|
||||||
|
// // Motor 1 to 8:
|
||||||
|
// // pitch roll yaw
|
||||||
|
// double mixer [8][3] = {
|
||||||
|
// { 1, 1, -1},
|
||||||
|
// { 1, 1, 1},
|
||||||
|
// { 1, -1, -1},
|
||||||
|
// { 1, -1, 1},
|
||||||
|
// { -1, -1, -1},
|
||||||
|
// { -1, -1, 1},
|
||||||
|
// { -1, 1, -1},
|
||||||
|
// { -1, 1, 1}
|
||||||
|
// };
|
||||||
|
// setupMultiRotorMixer(mixer);
|
||||||
|
// m_aircraft->mrStatusLabel->setText("SUCCESS: Mixer Saved OK");
|
||||||
|
//
|
||||||
|
// } else if (m_aircraft->multirotorFrameType->currentText() == "Hexacopter Y6") {
|
||||||
|
// airframeType = "HexaCoax";
|
||||||
|
// if (m_aircraft->multiMotor1->currentText() == "None" ||
|
||||||
|
// m_aircraft->multiMotor2->currentText() == "None" ||
|
||||||
|
// m_aircraft->multiMotor3->currentText() == "None" ||
|
||||||
|
// m_aircraft->multiMotor4->currentText() == "None" ||
|
||||||
|
// m_aircraft->multiMotor5->currentText() == "None" ||
|
||||||
|
// m_aircraft->multiMotor6->currentText() == "None" ) {
|
||||||
|
// m_aircraft->mrStatusLabel->setText("ERROR: Assign 6 motor channels");
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
// motorList << "VTOLMotorNW" << "VTOLMotorW" << "VTOLMotorNE" << "VTOLMotorE"
|
||||||
|
// << "VTOLMotorS" << "VTOLMotorSE";
|
||||||
|
// setupMotors(motorList);
|
||||||
|
//
|
||||||
|
// // Motor 1 to 6, Y6 Layout:
|
||||||
|
// // pitch roll yaw
|
||||||
|
// double mixer [8][3] = {
|
||||||
|
// { 0.5, 1, -1},
|
||||||
|
// { 0.5, 1, 1},
|
||||||
|
// { 0.5, -1, -1},
|
||||||
|
// { 0.5, -1, 1},
|
||||||
|
// { -1, 0, -1},
|
||||||
|
// { -1, 0, 1},
|
||||||
|
// { 0, 0, 0},
|
||||||
|
// { 0, 0, 0}
|
||||||
|
// };
|
||||||
|
// setupMultiRotorMixer(mixer);
|
||||||
|
// m_aircraft->mrStatusLabel->setText("SUCCESS: Mixer Saved OK");
|
||||||
|
//
|
||||||
|
// } else if (m_aircraft->multirotorFrameType->currentText() == "Tricopter Y") {
|
||||||
|
// airframeType = "Tri";
|
||||||
|
// if (m_aircraft->multiMotor1->currentText() == "None" ||
|
||||||
|
// m_aircraft->multiMotor2->currentText() == "None" ||
|
||||||
|
// m_aircraft->multiMotor3->currentText() == "None" ) {
|
||||||
|
// m_aircraft->mrStatusLabel->setText("ERROR: Assign 3 motor channels");
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
// if (m_aircraft->triYawChannelBoxBox->currentText() == "None") {
|
||||||
|
// m_aircraft->mrStatusLabel->setText("Error: Assign a Yaw channel");
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
// motorList << "VTOLMotorNW" << "VTOLMotorNE" << "VTOLMotorS";
|
||||||
|
// setupMotors(motorList);
|
||||||
|
// obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("ActuatorSettings")));
|
||||||
|
// Q_ASSERT(obj);
|
||||||
|
// field = obj->getField("FixedWingYaw1");
|
||||||
|
// field->setValue(m_aircraft->triYawChannelBoxBox->currentText());
|
||||||
|
//
|
||||||
|
// // Motor 1 to 6, Y6 Layout:
|
||||||
|
// // pitch roll yaw
|
||||||
|
// double mixer [8][3] = {
|
||||||
|
// { 0.5, 1, 0},
|
||||||
|
// { 0.5, -1, 0},
|
||||||
|
// { -1, 0, 0},
|
||||||
|
// { 0, 0, 0},
|
||||||
|
// { 0, 0, 0},
|
||||||
|
// { 0, 0, 0},
|
||||||
|
// { 0, 0, 0},
|
||||||
|
// { 0, 0, 0}
|
||||||
|
// };
|
||||||
|
// setupMultiRotorMixer(mixer);
|
||||||
|
//
|
||||||
|
// int tmpVal = m_aircraft->triYawChannelBoxBox->currentIndex()-1;
|
||||||
|
// obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
|
||||||
|
// field = obj->getField(mixerTypes.at(tmpVal));
|
||||||
|
// field->setValue("Servo");
|
||||||
|
// field = obj->getField(mixerVectors.at(tmpVal));
|
||||||
|
// resetField(field);
|
||||||
|
// int ti = field->getElementNames().indexOf("Yaw");
|
||||||
|
// field->setValue(127,ti);
|
||||||
|
//
|
||||||
|
// m_aircraft->mrStatusLabel->setText("SUCCESS: Mixer Saved OK");
|
||||||
|
//
|
||||||
|
// }
|
||||||
|
// // Now reflect those settings in the "Custom" panel as well
|
||||||
|
// updateCustomAirframeUI();
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if (m_aircraft->aircraftType->currentText() == "Helicopter") {
|
||||||
|
airframeType = "HeliCP";
|
||||||
|
m_aircraft->widget_3->sendccpmUpdate();
|
||||||
|
} else if (m_aircraft->aircraftType->currentText() == "Ground") {
|
||||||
|
if(1){
|
||||||
|
airframeType = updateGroundVehicleObjectsFromWidgets();
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
// airframeType = "Ground";
|
||||||
|
// // Save the curve (common to all ground vehicle frames)
|
||||||
|
// UAVDataObject *obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
|
||||||
|
// UAVObjectField* field;
|
||||||
|
//
|
||||||
|
// if (0){ //DON'T REMOVE FEEDFORWARD
|
||||||
|
// // Remove Feed Forward, it is pointless on a plane:
|
||||||
|
// field = obj->getField(QString("FeedForward"));
|
||||||
|
// field->setDouble(0);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// field = obj->getField("ThrottleCurve1");
|
||||||
|
// QList<double> curve = m_aircraft->groundVehicleThrottle->getCurve();
|
||||||
|
// for (int i=0;i<curve.length();i++) {
|
||||||
|
// field->setValue(curve.at(i),i);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// if (m_aircraft->groundVehicleType->currentText() == "Turnable (car)" ) {
|
||||||
|
// airframeType = "GroundVehicleCar";
|
||||||
|
// setupGroundVehicle();
|
||||||
|
// } else if (m_aircraft->groundVehicleType->currentText() == "Differential (tank)") {
|
||||||
|
// airframeType = "GroundVehicleDifferential";
|
||||||
|
// setupGroundVehicle();
|
||||||
|
// } else { // "Motorcycle"
|
||||||
|
// airframeType = "GroundVehicleMotorcycle";
|
||||||
|
// setupGroundVehicle();
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// // Now reflect those settings in the "Custom" panel as well
|
||||||
|
// updateCustomAirframeUI();
|
||||||
|
//
|
||||||
|
//// m_aircraft->widget_3->sendccpmUpdate();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
airframeType = "Custom";
|
||||||
|
|
||||||
|
UAVDataObject* obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
|
||||||
|
UAVObjectField* field = obj->getField(QString("FeedForward"));
|
||||||
|
|
||||||
|
// Curve is also common to all quads:
|
||||||
|
field = obj->getField("ThrottleCurve1");
|
||||||
|
QList<double> curve = m_aircraft->customThrottle1Curve->getCurve();
|
||||||
|
for (int i=0;i<curve.length();i++) {
|
||||||
|
field->setValue(curve.at(i),i);
|
||||||
|
}
|
||||||
|
|
||||||
|
field = obj->getField("ThrottleCurve2");
|
||||||
|
curve.clear();
|
||||||
|
curve = m_aircraft->customThrottle2Curve->getCurve();
|
||||||
|
for (int i=0;i<curve.length();i++) {
|
||||||
|
field->setValue(curve.at(i),i);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update the table:
|
||||||
|
for (int i=0; i<8; i++) {
|
||||||
|
field = obj->getField(mixerTypes.at(i));
|
||||||
|
QComboBox* q = (QComboBox*)m_aircraft->customMixerTable->cellWidget(0,i);
|
||||||
|
field->setValue(q->currentText());
|
||||||
|
field = obj->getField(mixerVectors.at(i));
|
||||||
|
int ti = field->getElementNames().indexOf("ThrottleCurve1");
|
||||||
|
field->setValue(m_aircraft->customMixerTable->item(1,i)->text(),ti);
|
||||||
|
ti = field->getElementNames().indexOf("ThrottleCurve2");
|
||||||
|
field->setValue(m_aircraft->customMixerTable->item(2,i)->text(),ti);
|
||||||
|
ti = field->getElementNames().indexOf("Roll");
|
||||||
|
field->setValue(m_aircraft->customMixerTable->item(3,i)->text(),ti);
|
||||||
|
ti = field->getElementNames().indexOf("Pitch");
|
||||||
|
field->setValue(m_aircraft->customMixerTable->item(4,i)->text(),ti);
|
||||||
|
ti = field->getElementNames().indexOf("Yaw");
|
||||||
|
field->setValue(m_aircraft->customMixerTable->item(5,i)->text(),ti);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//WHAT DOES THIS DO?
|
||||||
|
UAVDataObject* obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("SystemSettings")));
|
||||||
|
UAVObjectField* field = obj->getField(QString("AirframeType"));
|
||||||
|
field->setValue(airframeType);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Opens the wiki from the user's default browser
|
||||||
|
*/
|
||||||
|
void ConfigVehicleTypeWidget::openHelp()
|
||||||
|
{
|
||||||
|
|
||||||
|
QDesktopServices::openUrl( QUrl("http://wiki.openpilot.org/display/Doc/Airframe+configuration", QUrl::StrictMode) );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
WHAT DOES THIS DO???
|
||||||
|
*/
|
||||||
|
void ConfigVehicleTypeWidget::addToDirtyMonitor()
|
||||||
|
{
|
||||||
|
addWidget(m_aircraft->customMixerTable);
|
||||||
|
addWidget(m_aircraft->customThrottle1Curve);
|
||||||
|
addWidget(m_aircraft->customThrottle2Curve);
|
||||||
|
addWidget(m_aircraft->multiThrottleCurve);
|
||||||
|
addWidget(m_aircraft->fixedWingThrottle);
|
||||||
|
addWidget(m_aircraft->fixedWingType);
|
||||||
|
addWidget(m_aircraft->groundVehicleThrottle1);
|
||||||
|
addWidget(m_aircraft->groundVehicleThrottle2);
|
||||||
|
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->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_aircraft->widget_3->m_ccpm->ccpmType);
|
||||||
|
addWidget(m_aircraft->widget_3->m_ccpm->ccpmTailChannel);
|
||||||
|
addWidget(m_aircraft->widget_3->m_ccpm->ccpmEngineChannel);
|
||||||
|
addWidget(m_aircraft->widget_3->m_ccpm->ccpmServoWChannel);
|
||||||
|
addWidget(m_aircraft->widget_3->m_ccpm->ccpmServoXChannel);
|
||||||
|
addWidget(m_aircraft->widget_3->m_ccpm->ccpmServoYChannel);
|
||||||
|
addWidget(m_aircraft->widget_3->m_ccpm->ccpmSingleServo);
|
||||||
|
addWidget(m_aircraft->widget_3->m_ccpm->ccpmServoZChannel);
|
||||||
|
addWidget(m_aircraft->widget_3->m_ccpm->ccpmAngleW);
|
||||||
|
addWidget(m_aircraft->widget_3->m_ccpm->ccpmAngleX);
|
||||||
|
addWidget(m_aircraft->widget_3->m_ccpm->ccpmCorrectionAngle);
|
||||||
|
addWidget(m_aircraft->widget_3->m_ccpm->ccpmAngleZ);
|
||||||
|
addWidget(m_aircraft->widget_3->m_ccpm->ccpmAngleY);
|
||||||
|
addWidget(m_aircraft->widget_3->m_ccpm->ccpmCollectivePassthrough);
|
||||||
|
addWidget(m_aircraft->widget_3->m_ccpm->ccpmLinkRoll);
|
||||||
|
addWidget(m_aircraft->widget_3->m_ccpm->ccpmLinkCyclic);
|
||||||
|
addWidget(m_aircraft->widget_3->m_ccpm->ccpmRevoSlider);
|
||||||
|
addWidget(m_aircraft->widget_3->m_ccpm->ccpmREVOspinBox);
|
||||||
|
addWidget(m_aircraft->widget_3->m_ccpm->ccpmCollectiveSlider);
|
||||||
|
addWidget(m_aircraft->widget_3->m_ccpm->ccpmCollectivespinBox);
|
||||||
|
addWidget(m_aircraft->widget_3->m_ccpm->ccpmCollectiveScale);
|
||||||
|
addWidget(m_aircraft->widget_3->m_ccpm->ccpmCollectiveScaleBox);
|
||||||
|
addWidget(m_aircraft->widget_3->m_ccpm->ccpmCyclicScale);
|
||||||
|
addWidget(m_aircraft->widget_3->m_ccpm->ccpmPitchScale);
|
||||||
|
addWidget(m_aircraft->widget_3->m_ccpm->ccpmPitchScaleBox);
|
||||||
|
addWidget(m_aircraft->widget_3->m_ccpm->ccpmRollScale);
|
||||||
|
addWidget(m_aircraft->widget_3->m_ccpm->ccpmRollScaleBox);
|
||||||
|
addWidget(m_aircraft->widget_3->m_ccpm->SwashLvlPositionSlider);
|
||||||
|
addWidget(m_aircraft->widget_3->m_ccpm->SwashLvlPositionSpinBox);
|
||||||
|
addWidget(m_aircraft->widget_3->m_ccpm->CurveType);
|
||||||
|
addWidget(m_aircraft->widget_3->m_ccpm->NumCurvePoints);
|
||||||
|
addWidget(m_aircraft->widget_3->m_ccpm->CurveValue1);
|
||||||
|
addWidget(m_aircraft->widget_3->m_ccpm->CurveValue2);
|
||||||
|
addWidget(m_aircraft->widget_3->m_ccpm->CurveValue3);
|
||||||
|
addWidget(m_aircraft->widget_3->m_ccpm->CurveToGenerate);
|
||||||
|
addWidget(m_aircraft->widget_3->m_ccpm->CurveSettings);
|
||||||
|
addWidget(m_aircraft->widget_3->m_ccpm->ThrottleCurve);
|
||||||
|
addWidget(m_aircraft->widget_3->m_ccpm->PitchCurve);
|
||||||
|
addWidget(m_aircraft->widget_3->m_ccpm->ccpmAdvancedSettingsTable);
|
||||||
|
}
|
||||||
|
|
@ -24,8 +24,8 @@
|
|||||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
*/
|
*/
|
||||||
#ifndef CONFIGAIRFRAMEWIDGET_H
|
#ifndef CONFIGVEHICLETYPEWIDGET_H
|
||||||
#define CONFIGAIRFRAMEWIDGET_H
|
#define CONFIGVEHICLETYPEWIDGET_H
|
||||||
|
|
||||||
#include "ui_airframe.h"
|
#include "ui_airframe.h"
|
||||||
#include "../uavobjectwidgetutils/configtaskwidget.h"
|
#include "../uavobjectwidgetutils/configtaskwidget.h"
|
||||||
@ -39,24 +39,27 @@
|
|||||||
|
|
||||||
class Ui_Widget;
|
class Ui_Widget;
|
||||||
|
|
||||||
class ConfigAirframeWidget: public ConfigTaskWidget
|
class ConfigVehicleTypeWidget: public ConfigTaskWidget
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ConfigAirframeWidget(QWidget *parent = 0);
|
ConfigVehicleTypeWidget(QWidget *parent = 0);
|
||||||
~ConfigAirframeWidget();
|
~ConfigVehicleTypeWidget();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Ui_AircraftWidget *m_aircraft;
|
Ui_AircraftWidget *m_aircraft;
|
||||||
bool setupFrameFixedWing();
|
bool setupFrameFixedWing(QString airframeType);
|
||||||
bool setupFrameElevon();
|
bool setupFrameElevon(QString airframeType);
|
||||||
bool setupFrameVtail();
|
bool setupFrameVtail(QString airframeType);
|
||||||
bool setupQuad(bool pLayout);
|
bool setupQuad(bool pLayout);
|
||||||
bool setupHexa(bool pLayout);
|
bool setupHexa(bool pLayout);
|
||||||
bool setupOcto();
|
bool setupOcto();
|
||||||
|
bool setupGroundVehicleCar(QString airframeType);
|
||||||
|
bool setupGroundVehicleDifferential(QString airframeType);
|
||||||
|
bool setupGroundVehicleMotorcycle(QString airframeType);
|
||||||
void updateCustomAirframeUI();
|
void updateCustomAirframeUI();
|
||||||
bool setupMixer(double mixerFactors[8][3]);
|
bool setupMultiRotorMixer(double mixerFactors[8][3]);
|
||||||
void setupMotors(QList<QString> motorList);
|
void setupMotors(QList<QString> motorList);
|
||||||
void addToDirtyMonitor();
|
void addToDirtyMonitor();
|
||||||
void resetField(UAVObjectField * field);
|
void resetField(UAVObjectField * field);
|
||||||
@ -74,19 +77,39 @@ private:
|
|||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
virtual void refreshWidgetsValues();
|
virtual void refreshWidgetsValues();
|
||||||
|
void refreshFixedWingWidgetsValues(QString frameType);
|
||||||
|
void refreshMultiRotorWidgetsValues(QString frameType);
|
||||||
|
void refreshGroundVehicleWidgetsValues(QString frameType);
|
||||||
|
|
||||||
void updateObjectsFromWidgets();
|
void updateObjectsFromWidgets();
|
||||||
|
QString updateFixedWingObjectsFromWidgets();
|
||||||
|
QString updateMultiRotorObjectsFromWidgets();
|
||||||
|
QString updateGroundVehicleObjectsFromWidgets();
|
||||||
// void saveAircraftUpdate();
|
// void saveAircraftUpdate();
|
||||||
|
|
||||||
void setupAirframeUI(QString type);
|
void setupAirframeUI(QString type);
|
||||||
|
void setupFixedWingUI(QString frameType);
|
||||||
|
void setupMultiRotorUI(QString frameType);
|
||||||
|
void setupGroundVehicleUI(QString frameType);
|
||||||
|
|
||||||
|
void throwMultiRotorChannelConfigError(int numMotors);
|
||||||
|
void throwFixedWingChannelConfigError(QString airframeType);
|
||||||
|
void throwGroundVehicleChannelConfigError(QString airframeType);
|
||||||
|
|
||||||
void toggleAileron2(int index);
|
void toggleAileron2(int index);
|
||||||
void toggleElevator2(int index);
|
void toggleElevator2(int index);
|
||||||
void toggleRudder2(int index);
|
void toggleRudder2(int index);
|
||||||
void switchAirframeType(int index);
|
void switchAirframeType(int index);
|
||||||
void resetFwMixer();
|
void resetFwMixer();
|
||||||
void resetMrMixer();
|
void resetMrMixer();
|
||||||
|
void resetGvFrontMixer();
|
||||||
|
void resetGvRearMixer();
|
||||||
void resetCt1Mixer();
|
void resetCt1Mixer();
|
||||||
void resetCt2Mixer();
|
void resetCt2Mixer();
|
||||||
void updateFwThrottleCurveValue(QList<double> list, double value);
|
void updateFwThrottleCurveValue(QList<double> list, double value);
|
||||||
void updateMrThrottleCurveValue(QList<double> list, double value);
|
void updateMrThrottleCurveValue(QList<double> list, double value);
|
||||||
|
void updateGvThrottle1CurveValue(QList<double> list, double value);
|
||||||
|
void updateGvThrottle2CurveValue(QList<double> list, double value);
|
||||||
void updateCustomThrottle1CurveValue(QList<double> list, double value);
|
void updateCustomThrottle1CurveValue(QList<double> list, double value);
|
||||||
void updateCustomThrottle2CurveValue(QList<double> list, double value);
|
void updateCustomThrottle2CurveValue(QList<double> list, double value);
|
||||||
void enableFFTest();
|
void enableFFTest();
|
||||||
@ -117,4 +140,4 @@ public:
|
|||||||
const QStyleOptionViewItem &option, const QModelIndex &index) const;
|
const QStyleOptionViewItem &option, const QModelIndex &index) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // CONFIGAIRFRAMEWIDGET_H
|
#endif // CONFIGVEHICLETYPEWIDGET_H
|
@ -16,6 +16,10 @@
|
|||||||
<field name="VTOLMotorSW" units="channel" type="enum" elements="1" options="Channel1,Channel2,Channel3,Channel4,Channel5,Channel6,Channel7,Channel8,Channel9,Channel10,None" defaultvalue="None"/>
|
<field name="VTOLMotorSW" units="channel" type="enum" elements="1" options="Channel1,Channel2,Channel3,Channel4,Channel5,Channel6,Channel7,Channel8,Channel9,Channel10,None" defaultvalue="None"/>
|
||||||
<field name="VTOLMotorW" units="channel" type="enum" elements="1" options="Channel1,Channel2,Channel3,Channel4,Channel5,Channel6,Channel7,Channel8,Channel9,Channel10,None" defaultvalue="None"/>
|
<field name="VTOLMotorW" units="channel" type="enum" elements="1" options="Channel1,Channel2,Channel3,Channel4,Channel5,Channel6,Channel7,Channel8,Channel9,Channel10,None" defaultvalue="None"/>
|
||||||
<field name="VTOLMotorNW" units="channel" type="enum" elements="1" options="Channel1,Channel2,Channel3,Channel4,Channel5,Channel6,Channel7,Channel8,Channel9,Channel10,None" defaultvalue="None"/>
|
<field name="VTOLMotorNW" units="channel" type="enum" elements="1" options="Channel1,Channel2,Channel3,Channel4,Channel5,Channel6,Channel7,Channel8,Channel9,Channel10,None" defaultvalue="None"/>
|
||||||
|
<field name="GroundVehicleThrottle1" units="channel" type="enum" elements="1" options="Channel1,Channel2,Channel3,Channel4,Channel5,Channel6,Channel7,Channel8,Channel9,Channel10,None" defaultvalue="None"/>
|
||||||
|
<field name="GroundVehicleThrottle2" units="channel" type="enum" elements="1" options="Channel1,Channel2,Channel3,Channel4,Channel5,Channel6,Channel7,Channel8,Channel9,Channel10,None" defaultvalue="None"/>
|
||||||
|
<field name="GroundVehicleSteering1" units="channel" type="enum" elements="1" options="Channel1,Channel2,Channel3,Channel4,Channel5,Channel6,Channel7,Channel8,Channel9,Channel10,None" defaultvalue="None"/>
|
||||||
|
<field name="GroundVehicleSteering2" units="channel" type="enum" elements="1" options="Channel1,Channel2,Channel3,Channel4,Channel5,Channel6,Channel7,Channel8,Channel9,Channel10,None" defaultvalue="None"/>
|
||||||
<field name="ChannelUpdateFreq" units="Hz" type="uint16" elements="4" defaultvalue="50"/>
|
<field name="ChannelUpdateFreq" units="Hz" type="uint16" elements="4" defaultvalue="50"/>
|
||||||
<field name="ChannelMax" units="us" type="int16" elements="10" defaultvalue="1000"/>
|
<field name="ChannelMax" units="us" type="int16" elements="10" defaultvalue="1000"/>
|
||||||
<field name="ChannelNeutral" units="us" type="int16" elements="10" defaultvalue="1000"/>
|
<field name="ChannelNeutral" units="us" type="int16" elements="10" defaultvalue="1000"/>
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<xml>
|
<xml>
|
||||||
<object name="SystemSettings" singleinstance="true" settings="true">
|
<object name="SystemSettings" singleinstance="true" settings="true">
|
||||||
<description>Select airframe type. Currently used by @ref ActuatorModule to choose mixing from @ref ActuatorDesired to @ref ActuatorCommand</description>
|
<description>Select airframe type. Currently used by @ref ActuatorModule to choose mixing from @ref ActuatorDesired to @ref ActuatorCommand</description>
|
||||||
<field name="AirframeType" units="" type="enum" elements="1" options="FixedWing,FixedWingElevon,FixedWingVtail,VTOL,HeliCP,QuadX,QuadP,Hexa,Octo,Custom,HexaX,OctoV,OctoCoaxP,OctoCoaxX,HexaCoax,Tri" defaultvalue="FixedWing"/>
|
<field name="AirframeType" units="" type="enum" elements="1" options="FixedWing,FixedWingElevon,FixedWingVtail,VTOL,HeliCP,QuadX,QuadP,Hexa,Octo,Custom,HexaX,OctoV,OctoCoaxP,OctoCoaxX,HexaCoax,Tri,GroundVehicleCar,GroundVehicleDifferential,GroundVehicleMotorcycle" defaultvalue="FixedWing"/>
|
||||||
<field name="GUIConfigData" units="bits" type="uint32" elements="2" defaultvalue="0"/>
|
<field name="GUIConfigData" units="bits" type="uint32" elements="2" defaultvalue="0"/>
|
||||||
<access gcs="readwrite" flight="readwrite"/>
|
<access gcs="readwrite" flight="readwrite"/>
|
||||||
<telemetrygcs acked="true" updatemode="onchange" period="0"/>
|
<telemetrygcs acked="true" updatemode="onchange" period="0"/>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user