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

OP-138 Quad and Hexa implemented, custom table works (read only, not edit), and code improved to enable definition of matrices

in simple tables instead of ugly lines of code. Testers needed. Cautious testers. Also reshuffled the AHRS UI to put 6-point above sensor noise.
Next will be octo and coaxial frames.




git-svn-id: svn://svn.openpilot.org/OpenPilot/trunk@1999 ebee16cc-31ac-478f-84a7-5cbb03baadba
This commit is contained in:
edouard 2010-10-21 22:05:07 +00:00 committed by edouard
parent d6e9080ec6
commit 9ad1618739
4 changed files with 332 additions and 208 deletions

View File

@ -32,7 +32,7 @@
<property name="geometry">
<rect>
<x>10</x>
<y>10</y>
<y>210</y>
<width>341</width>
<height>131</height>
</rect>
@ -52,8 +52,8 @@ Tip: lower is better!</string>
<widget class="QLabel" name="calibInstructions">
<property name="geometry">
<rect>
<x>390</x>
<y>90</y>
<x>380</x>
<y>280</y>
<width>231</width>
<height>17</height>
</rect>
@ -68,8 +68,8 @@ Tip: lower is better!</string>
</property>
<property name="geometry">
<rect>
<x>440</x>
<y>40</y>
<x>450</x>
<y>240</y>
<width>93</width>
<height>27</height>
</rect>
@ -86,8 +86,8 @@ Hint: run this with engines at cruising speed.</string>
<widget class="Line" name="line">
<property name="geometry">
<rect>
<x>127</x>
<y>150</y>
<x>220</x>
<y>180</y>
<width>411</width>
<height>20</height>
</rect>
@ -128,7 +128,7 @@ Hint: run this with engines at cruising speed.</string>
<property name="geometry">
<rect>
<x>10</x>
<y>190</y>
<y>40</y>
<width>191</width>
<height>151</height>
</rect>
@ -140,14 +140,14 @@ Hint: run this with engines at cruising speed.</string>
<widget class="QLabel" name="label_3">
<property name="geometry">
<rect>
<x>40</x>
<y>170</y>
<width>151</width>
<x>20</x>
<y>10</y>
<width>181</width>
<height>17</height>
</rect>
</property>
<property name="text">
<string>Six Point Calibration</string>
<string>#1: Six Point Calibration</string>
</property>
</widget>
<widget class="QPushButton" name="sixPointsStart">
@ -156,8 +156,8 @@ Hint: run this with engines at cruising speed.</string>
</property>
<property name="geometry">
<rect>
<x>220</x>
<y>180</y>
<x>250</x>
<y>10</y>
<width>111</width>
<height>27</height>
</rect>
@ -173,7 +173,7 @@ Hint: run this with engines at cruising speed.</string>
<property name="geometry">
<rect>
<x>220</x>
<y>220</y>
<y>50</y>
<width>411</width>
<height>121</height>
</rect>
@ -243,14 +243,14 @@ Disabled if there is no GPS fix.</string>
<widget class="QLabel" name="label">
<property name="geometry">
<rect>
<x>370</x>
<y>10</y>
<x>380</x>
<y>210</y>
<width>251</width>
<height>17</height>
</rect>
</property>
<property name="text">
<string>Sensor noise calibration</string>
<string>#2: Sensor noise calibration</string>
</property>
</widget>
<widget class="QProgressBar" name="calibProgress">
@ -260,7 +260,7 @@ Disabled if there is no GPS fix.</string>
<property name="geometry">
<rect>
<x>390</x>
<y>120</y>
<y>310</y>
<width>201</width>
<height>23</height>
</rect>
@ -281,8 +281,8 @@ Disabled if there is no GPS fix.</string>
</property>
<property name="geometry">
<rect>
<x>350</x>
<y>180</y>
<x>380</x>
<y>10</y>
<width>111</width>
<height>27</height>
</rect>

View File

@ -7,7 +7,7 @@
<x>0</x>
<y>0</y>
<width>730</width>
<height>527</height>
<height>559</height>
</rect>
</property>
<property name="windowTitle">
@ -69,7 +69,7 @@
<item>
<widget class="QStackedWidget" name="airframesWidget">
<property name="currentIndex">
<number>3</number>
<number>1</number>
</property>
<widget class="QWidget" name="fixedWing">
<property name="enabled">
@ -504,6 +504,9 @@
<property name="text">
<string>100</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item>
@ -528,18 +531,8 @@ Typical values are 100% for + configuration and 50% for X configuration on quads
<property name="text">
<string>R</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="checkBox_3">
<property name="enabled">
<bool>false</bool>
</property>
<property name="toolTip">
<string>All checked sliders will move together.</string>
</property>
<property name="text">
<string/>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
@ -552,6 +545,9 @@ Typical values are 100% for + configuration and 50% for X configuration on quads
<property name="text">
<string>100</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item>
@ -576,15 +572,8 @@ Typical values are 100% for + configuration and 50% for X configuration on quads
<property name="text">
<string>P</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="checkBox_2">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string/>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
@ -597,6 +586,9 @@ Typical values are 100% for + configuration and 50% for X configuration on quads
<property name="text">
<string>50</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item>
@ -618,18 +610,14 @@ Typical value is 50% for + or X configuration on quads.</string>
</item>
<item>
<widget class="QLabel" name="label_6">
<property name="text">
<string>Y</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="checkBox">
<property name="enabled">
<property name="autoFillBackground">
<bool>false</bool>
</property>
<property name="text">
<string/>
<string>Y</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
@ -825,10 +813,9 @@ In 'units per second', a sound default is 1000.</string>
<string>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
p, li { white-space: pre-wrap; }
&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'Sans'; font-size:10pt; font-weight:400; font-style:normal;&quot;&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;Beware! Check &lt;span style=&quot; font-weight:600;&quot;&gt;all three&lt;/span&gt; checkboxes to test the&lt;/p&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;selected channel.&lt;/p&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;It will run only if your airframe armed.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'Ubuntu'; font-size:11pt; font-weight:400; font-style:normal;&quot;&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-family:'Sans'; font-size:10pt;&quot;&gt;Beware! Check &lt;/span&gt;&lt;span style=&quot; font-family:'Sans'; font-size:10pt; font-weight:600;&quot;&gt;all three&lt;/span&gt;&lt;span style=&quot; font-family:'Sans'; font-size:10pt;&quot;&gt; checkboxes to test Feed Forward.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-family:'Sans'; font-size:10pt;&quot;&gt;It will run only if your airframe armed.&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string/>
@ -841,10 +828,9 @@ p, li { white-space: pre-wrap; }
<string>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
p, li { white-space: pre-wrap; }
&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'Sans'; font-size:10pt; font-weight:400; font-style:normal;&quot;&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;Beware! Check &lt;span style=&quot; font-weight:600;&quot;&gt;all three&lt;/span&gt; checkboxes to test the&lt;/p&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;selected channel.&lt;/p&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;It will run only if your airframe armed.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'Ubuntu'; font-size:11pt; font-weight:400; font-style:normal;&quot;&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-family:'Sans'; font-size:10pt;&quot;&gt;Beware! Check &lt;/span&gt;&lt;span style=&quot; font-family:'Sans'; font-size:10pt; font-weight:600;&quot;&gt;all three&lt;/span&gt;&lt;span style=&quot; font-family:'Sans'; font-size:10pt;&quot;&gt; checkboxes to test Feed Forward.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-family:'Sans'; font-size:10pt;&quot;&gt;It will run only if your airframe armed.&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string/>
@ -857,10 +843,9 @@ p, li { white-space: pre-wrap; }
<string>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
p, li { white-space: pre-wrap; }
&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'Sans'; font-size:10pt; font-weight:400; font-style:normal;&quot;&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;Beware! Check &lt;span style=&quot; font-weight:600;&quot;&gt;all three&lt;/span&gt; checkboxes to test the&lt;/p&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;selected channel.&lt;/p&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;It will run only if your airframe armed.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'Ubuntu'; font-size:11pt; font-weight:400; font-style:normal;&quot;&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-family:'Sans'; font-size:10pt;&quot;&gt;Beware! Check &lt;/span&gt;&lt;span style=&quot; font-family:'Sans'; font-size:10pt; font-weight:600;&quot;&gt;all three&lt;/span&gt;&lt;span style=&quot; font-family:'Sans'; font-size:10pt;&quot;&gt; checkboxes to test Feed Forward.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-family:'Sans'; font-size:10pt;&quot;&gt;It will run only if your airframe armed.&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>Enable FF tuning</string>
@ -883,20 +868,30 @@ p, li { white-space: pre-wrap; }
</layout>
</item>
<item>
<spacer name="verticalSpacer_5">
<property name="orientation">
<enum>Qt::Vertical</enum>
<widget class="QTextBrowser" name="textBrowser">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="MinimumExpanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="sizeHint" stdset="0">
<property name="minimumSize">
<size>
<width>20</width>
<width>0</width>
<height>40</height>
</size>
</property>
</spacer>
<property name="html">
<string>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
p, li { white-space: pre-wrap; }
&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'Ubuntu'; font-size:11pt; font-weight:400; font-style:normal;&quot;&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:10pt; font-weight:600;&quot;&gt;Beware&lt;/span&gt;&lt;span style=&quot; font-size:10pt;&quot;&gt;: Feed Forward Tuning will launch all engines around mid-throttle, you have been warned!&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer_3">
<spacer name="verticalSpacer_5">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
@ -1464,18 +1459,15 @@ p, li { white-space: pre-wrap; }
<pointsize>8</pointsize>
</font>
</property>
<property name="alternatingRowColors">
<bool>true</bool>
</property>
<attribute name="horizontalHeaderDefaultSectionSize">
<number>50</number>
</attribute>
<attribute name="horizontalHeaderStretchLastSection">
<bool>false</bool>
</attribute>
<attribute name="horizontalHeaderStretchLastSection">
<bool>false</bool>
</attribute>
<attribute name="horizontalHeaderDefaultSectionSize">
<number>50</number>
</attribute>
<row>
<property name="text">
<string>Type</string>
@ -2014,11 +2006,11 @@ p, li { white-space: pre-wrap; }
<hints>
<hint type="sourcelabel">
<x>78</x>
<y>116</y>
<y>111</y>
</hint>
<hint type="destinationlabel">
<x>78</x>
<y>118</y>
<y>113</y>
</hint>
</hints>
</connection>
@ -2030,11 +2022,11 @@ p, li { white-space: pre-wrap; }
<hints>
<hint type="sourcelabel">
<x>74</x>
<y>116</y>
<y>111</y>
</hint>
<hint type="destinationlabel">
<x>74</x>
<y>118</y>
<y>113</y>
</hint>
</hints>
</connection>
@ -2045,8 +2037,8 @@ p, li { white-space: pre-wrap; }
<slot>setNum(int)</slot>
<hints>
<hint type="sourcelabel">
<x>496</x>
<y>171</y>
<x>493</x>
<y>173</y>
</hint>
<hint type="destinationlabel">
<x>271</x>
@ -2097,8 +2089,8 @@ p, li { white-space: pre-wrap; }
<y>199</y>
</hint>
<hint type="destinationlabel">
<x>108</x>
<y>151</y>
<x>135</x>
<y>150</y>
</hint>
</hints>
</connection>

View File

@ -85,7 +85,7 @@ ConfigAirframeWidget::ConfigAirframeWidget(QWidget *parent) : ConfigTaskWidget(p
m_aircraft->multiMotor7->addItems(channels);
m_aircraft->multiMotor8->addItems(channels);
// Setup the Multirotor picture in the Quad settings interface
// 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();
@ -98,6 +98,15 @@ ConfigAirframeWidget::ConfigAirframeWidget(QWidget *parent) : ConfigTaskWidget(p
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("Mixer0Type"));
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);
}
connect(m_aircraft->saveAircraftToSD, SIGNAL(clicked()), this, SLOT(saveAircraftUpdate()));
@ -139,6 +148,13 @@ 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)
@ -345,7 +361,6 @@ void ConfigAirframeWidget::requestAircraftUpdate()
// Setup all Throttle1 curves for all types of airframes
m_aircraft->fixedWingThrottle->initCurve(curveValues);
m_aircraft->multiThrottleCurve->initCurve(curveValues);
m_aircraft->customThrottle1Curve->initCurve(curveValues);
// Load the Settings for fixed wing frames:
if (frameType.startsWith("FixedWing")) {
@ -477,28 +492,55 @@ void ConfigAirframeWidget::requestAircraftUpdate()
} else if (frameType == "Hexa") {
// Motors 1/2/3 4/5/6 are: N / NE / SE / S / SW / NW
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("VTOLMotorSE"));
Q_ASSERT(field);
m_aircraft->multiMotor3->setCurrentIndex(m_aircraft->multiMotor3->findText(field->getValue().toString()));
field = obj->getField(QString("VTOLMotorS"));
Q_ASSERT(field);
m_aircraft->multiMotor4->setCurrentIndex(m_aircraft->multiMotor4->findText(field->getValue().toString()));
field = obj->getField(QString("VTOLMotorSW"));
Q_ASSERT(field);
m_aircraft->multiMotor5->setCurrentIndex(m_aircraft->multiMotor4->findText(field->getValue().toString()));
field = obj->getField(QString("VTOLMotorNW"));
Q_ASSERT(field);
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")));
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 = floor(field->getDouble(i)/1.27);
m_aircraft->mrPitchMixLevel->setValue(val);
i = field->getElementNames().indexOf("Yaw");
val = floor(-field->getDouble(i)/1.27);
m_aircraft->mrYawMixLevel->setValue(val);
eng = m_aircraft->multiMotor2->currentIndex()-1;
field = obj->getField(mixerVectors.at(eng));
i = field->getElementNames().indexOf("Roll");
val = floor(1-field->getDouble(i)/1.27);
m_aircraft->mrRollMixLevel->setValue(val);
}
} else if (frameType == "HexaX") {
// Motors 1/2/3 4/5/6 are: NE / E / SE / SW / W / NW
field = obj->getField(QString("VTOLMotorNE"));
m_aircraft->multiMotor1->setCurrentIndex(m_aircraft->multiMotor1->findText(field->getValue().toString()));
field = obj->getField(QString("VTOLMotorE"));
m_aircraft->multiMotor2->setCurrentIndex(m_aircraft->multiMotor2->findText(field->getValue().toString()));
field = obj->getField(QString("VTOLMotorSE"));
m_aircraft->multiMotor3->setCurrentIndex(m_aircraft->multiMotor3->findText(field->getValue().toString()));
field = obj->getField(QString("VTOLMotorSW"));
m_aircraft->multiMotor4->setCurrentIndex(m_aircraft->multiMotor4->findText(field->getValue().toString()));
field = obj->getField(QString("VTOLMotorW"));
m_aircraft->multiMotor5->setCurrentIndex(m_aircraft->multiMotor4->findText(field->getValue().toString()));
field = obj->getField(QString("VTOLMotorNW"));
m_aircraft->multiMotor6->setCurrentIndex(m_aircraft->multiMotor4->findText(field->getValue().toString()));
// Now, read the 1st mixer R/P/Y levels and initialize the mix sliders.
// This assumes that all vectors are identical - if not, the user should use the
// "custom" setting.
obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
int eng= m_aircraft->multiMotor1->currentIndex()-1;
// eng will be -1 if value is set to "None"
if (eng > -1) {
@ -564,6 +606,8 @@ void ConfigAirframeWidget::requestAircraftUpdate()
m_aircraft->widget_3->requestccpmUpdate();
m_aircraft->aircraftType->setCurrentIndex(m_aircraft->aircraftType->findText("Helicopter"));//"Helicopter"
}
updateCustomAirframeUI();
}
/**
@ -673,32 +717,49 @@ void ConfigAirframeWidget::setupAirframeUI(QString frameType)
m_aircraft->multiMotor8->setEnabled(true);
m_aircraft->mrRollMixLevel->setValue(33);
m_aircraft->mrPitchMixLevel->setValue(33);
m_aircraft->mrYawMixLevel->setValue(12);
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-X");
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->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->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->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);
@ -707,14 +768,17 @@ void ConfigAirframeWidget::setupAirframeUI(QString frameType)
m_aircraft->multiMotor8->setEnabled(true);
} 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);
} 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);
@ -1103,6 +1167,56 @@ bool ConfigAirframeWidget::setupFrameVtail()
}
/**
Set up a complete mixer, taking a table of factors. The factors
shoudl mainly be +/- 1 factors, since they will be weighted by the
value of the Pitch/Roll/Yaw sliders.
Example:
double xMixer [8][3] = {
P R Y
{ 1, 1, -1}, Motor 1
{ 1, -1, 1}, Motor 2
{-1, -1, -1}, Motor 3
{-1, 1, 1}, ...
{ 0, 0, 0},
{ 0, 0, 0},
{ 0, 0, 0},
{ 0, 0, 0}
};
*/
bool ConfigAirframeWidget::setupMixer(double mixerFactors[8][3])
{
UAVObjectField *field;
QList<QComboBox*> mmList;
mmList << m_aircraft->multiMotor1 << m_aircraft->multiMotor2 << m_aircraft->multiMotor3
<< m_aircraft->multiMotor4 << m_aircraft->multiMotor5 << m_aircraft->multiMotor6
<< m_aircraft->multiMotor7 << m_aircraft->multiMotor8;
UAVDataObject *obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
// 1. Assign the servo/motor/none for each channel
// Disable all
foreach(QString mixer, mixerTypes) {
field = obj->getField(mixer);
Q_ASSERT(field);
field->setValue("Disabled");
}
// and enable only the relevant channels:
double pFactor = (double)m_aircraft->mrPitchMixLevel->value()/100;
double rFactor = (double)m_aircraft->mrRollMixLevel->value()/100;
double yFactor = (double)m_aircraft->mrYawMixLevel->value()/100;
for (int i=0 ; i<8; i++) {
int channel = mmList.at(i)->currentIndex()-1;
if (channel > -1)
setupQuadMotor(channel, mixerFactors[i][0]*pFactor,
rFactor*mixerFactors[i][1], yFactor*mixerFactors[i][2]);
}
obj->updated();
return true;
}
/**
Help function: setupQuadMotor
*/
@ -1125,6 +1239,27 @@ void ConfigAirframeWidget::setupQuadMotor(int channel, double pitch, double roll
field->setValue(yaw*127,ti);
}
/**
Helper function: setup motors.
*/
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
*/
@ -1140,44 +1275,34 @@ bool ConfigAirframeWidget::setupQuad(bool pLayout)
return false;
}
resetActuators();
UAVDataObject* obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("ActuatorSettings")));
Q_ASSERT(obj);
UAVObjectField *field;
// Save the actuator channels for motor 1 to 4 (N/E/S/W)
field = pLayout ? obj->getField("VTOLMotorN") : obj->getField("VTOLMotorNW");
Q_ASSERT(field);
field->setValue(m_aircraft->multiMotor1->currentText());
field = pLayout ? obj->getField("VTOLMotorE") : obj->getField("VTOLMotorNE");
Q_ASSERT(field);
field->setValue(m_aircraft->multiMotor2->currentText());
field = pLayout ? obj->getField("VTOLMotorS") : obj->getField("VTOLMotorSE");
Q_ASSERT(field);
field->setValue(m_aircraft->multiMotor3->currentText());
field = pLayout ? obj->getField("VTOLMotorW") : obj->getField("VTOLMotorSW");
Q_ASSERT(field);
field->setValue(m_aircraft->multiMotor4->currentText());
obj->updated(); // Save...
QList<QString> motorList;
if (pLayout) {
motorList << "VTOLMotorN" << "VTOLMotorE" << "VTOLMotorS"
<< "VTOLMotorW";
} else {
motorList << "VTOLMotorNW" << "VTOLMotorNE" << "VTOLMotorSE"
<< "VTOLMotorSW";
}
setupMotors(motorList);
// Now, setup the mixer:
obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
Q_ASSERT(obj);
// 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:
// 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
@ -1185,32 +1310,32 @@ bool ConfigAirframeWidget::setupQuad(bool pLayout)
// {0 ,-1 ,0.5 //Right motor(CCW)
// {-1 ,0 ,-0.5 //Rear motor (CW)
// {0 ,1 ,0.5 //Left motor (CCW)
double pFactor = (double)m_aircraft->mrPitchMixLevel->value()/100;
double rFactor = (double)m_aircraft->mrRollMixLevel->value()/100;
double yFactor = (double)m_aircraft->mrYawMixLevel->value()/100;
int channel = m_aircraft->multiMotor1->currentIndex()-1;
pLayout ? setupQuadMotor(channel, pFactor, 0, -yFactor)
: setupQuadMotor(channel, pFactor, rFactor, -yFactor);
channel = m_aircraft->multiMotor2->currentIndex()-1;
pLayout ? setupQuadMotor(channel, 0, -rFactor, yFactor)
: setupQuadMotor(channel, pFactor, -rFactor, yFactor);
channel = m_aircraft->multiMotor3->currentIndex()-1;
pLayout ? setupQuadMotor(channel, -pFactor, 0, -yFactor)
: setupQuadMotor(channel, -pFactor, -rFactor, -yFactor);
channel = m_aircraft->multiMotor4->currentIndex()-1;
pLayout ? setupQuadMotor(channel, 0, rFactor, yFactor)
: setupQuadMotor(channel, -pFactor, rFactor, yFactor);
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}
};
obj->updated();
if (pLayout) {
setupMixer(pMixer);
} else {
setupMixer(xMixer);
}
m_aircraft->mrStatusLabel->setText("SUCCESS: Mixer Saved OK");
return true;
}
/**
Set up a Quad-X or Quad-P
Set up a Hexa-X or Hexa-P
*/
bool ConfigAirframeWidget::setupHexa()
bool ConfigAirframeWidget::setupHexa(bool pLayout)
{
// Check coherence:
// - Four engines have to be defined
@ -1224,42 +1349,16 @@ bool ConfigAirframeWidget::setupHexa()
return false;
}
resetActuators();
UAVDataObject* obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("ActuatorSettings")));
Q_ASSERT(obj);
UAVObjectField *field;
// Save the actuator channels for motor 1 to 6 (N/NE/SE/S/SW/NW)
field = obj->getField("VTOLMotorN");
Q_ASSERT(field);
field->setValue(m_aircraft->multiMotor1->currentText());
field = obj->getField("VTOLMotorNE");
Q_ASSERT(field);
field->setValue(m_aircraft->multiMotor2->currentText());
field = obj->getField("VTOLMotorSE");
Q_ASSERT(field);
field->setValue(m_aircraft->multiMotor3->currentText());
field = obj->getField("VTOLMotorS");
Q_ASSERT(field);
field->setValue(m_aircraft->multiMotor4->currentText());
field = obj->getField("VTOLMotorSW");
Q_ASSERT(field);
field->setValue(m_aircraft->multiMotor5->currentText());
field = obj->getField("VTOLMotorNW");
Q_ASSERT(field);
field->setValue(m_aircraft->multiMotor6->currentText());
obj->updated(); // Save...
// Now, setup the mixer:
obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
Q_ASSERT(obj);
// 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");
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:
@ -1270,30 +1369,50 @@ bool ConfigAirframeWidget::setupHexa()
// 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 pFactor = (double)m_aircraft->mrPitchMixLevel->value()/100;
double rFactor = (double)m_aircraft->mrRollMixLevel->value()/100;
double yFactor = (double)m_aircraft->mrYawMixLevel->value()/100;
int channel = m_aircraft->multiMotor1->currentIndex()-1;
setupQuadMotor(channel, pFactor, 0, -yFactor);
channel = m_aircraft->multiMotor2->currentIndex()-1;
setupQuadMotor(channel, pFactor, -rFactor, yFactor);
channel = m_aircraft->multiMotor3->currentIndex()-1;
setupQuadMotor(channel, -pFactor, -rFactor, -yFactor);
channel = m_aircraft->multiMotor4->currentIndex()-1;
setupQuadMotor(channel, -pFactor, 0, yFactor);
channel = m_aircraft->multiMotor5->currentIndex()-1;
setupQuadMotor(channel, -pFactor, rFactor, -yFactor);
channel = m_aircraft->multiMotor6->currentIndex()-1;
setupQuadMotor(channel, pFactor, rFactor, yFactor);
obj->updated();
m_aircraft->mrStatusLabel->setText("SUCCESS: Mixer Saved OK");
return true;
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
Updates the custom airframe settings based on the current airframe.
Note: doe NOT ask for an object refresh itself!
*/
void ConfigAirframeWidget::updateCustomAirframeUI()
{
@ -1341,7 +1460,10 @@ void ConfigAirframeWidget::updateCustomAirframeUI()
// Update the table:
for (int i=0; i<8; i++) {
field = obj->getField(mixerTypes.at(i));
m_aircraft->customMixerTable->item(0,i)->setText(field->getValue().toString());;
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());
@ -1353,14 +1475,10 @@ void ConfigAirframeWidget::updateCustomAirframeUI()
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)
@ -1370,7 +1488,7 @@ void ConfigAirframeWidget::updateCustomAirframeUI()
*/
void ConfigAirframeWidget::sendAircraftUpdate()
{
QString airframeType;
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")));
@ -1422,9 +1540,22 @@ void ConfigAirframeWidget::sendAircraftUpdate()
setupQuad(false);
} else if (m_aircraft->multirotorFrameType->currentText() == "Hexacopter") {
airframeType = "Hexa";
setupHexa();
setupHexa(true);
} else if (m_aircraft->multirotorFrameType->currentText() == "Octocopter") {
airframeType = "Octo";
} else if (m_aircraft->multirotorFrameType->currentText() == "Hexacopter X") {
airframeType = "HexaX";
setupHexa(false);
} else if (m_aircraft->multirotorFrameType->currentText() == "Octocopter V") {
airframeType = "OctoV";
} else if (m_aircraft->multirotorFrameType->currentText() == "Octo Coax +") {
airframeType = "OctoCoaxP";
} else if (m_aircraft->multirotorFrameType->currentText() == "Octo Coax X") {
airframeType = "OctoCoaxX";
} else if (m_aircraft->multirotorFrameType->currentText() == "Hexacopter Y6") {
airframeType = "HexaCoax";
} else if (m_aircraft->multirotorFrameType->currentText() == "Tricopter") {
airframeType = "Tri";
}
// Now reflect those settings in the "Custom" panel as well
updateCustomAirframeUI();
@ -1437,7 +1568,6 @@ void ConfigAirframeWidget::sendAircraftUpdate()
}
UAVDataObject* obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("SystemSettings")));
Q_ASSERT(obj);
UAVObjectField* field = obj->getField(QString("AirframeType"));
field->setValue(airframeType);
obj->updated();

View File

@ -51,9 +51,11 @@ private:
bool setupFrameElevon();
bool setupFrameVtail();
bool setupQuad(bool pLayout);
bool setupHexa();
bool setupHexa(bool pLayout);
bool setupOcto();
void updateCustomAirframeUI();
bool setupMixer(double mixerFactors[8][3]);
void setupMotors(QList<QString> motorList);
void resetField(UAVObjectField * field);
void resetMixer (MixerCurveWidget *mixer, int numElements);