mirror of
https://bitbucket.org/librepilot/librepilot.git
synced 2025-02-20 10:54:14 +01:00
OP-138 Mixer: fixed wing works, and Quad-Plus and Quad-X configurations are supported. Not tested for obvious reasons, since I am working in the train.
You can check how this works for you and report bugs. Layout works fine with screens as small as 800x600. git-svn-id: svn://svn.openpilot.org/OpenPilot/trunk@1791 ebee16cc-31ac-478f-84a7-5cbb03baadba
This commit is contained in:
parent
6f1f990d85
commit
bd6754cd6b
@ -7,7 +7,7 @@
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>720</width>
|
||||
<height>480</height>
|
||||
<height>508</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
@ -69,7 +69,7 @@
|
||||
<item>
|
||||
<widget class="QStackedWidget" name="stackedWidget">
|
||||
<property name="currentIndex">
|
||||
<number>0</number>
|
||||
<number>1</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="fixedWing">
|
||||
<property name="enabled">
|
||||
@ -247,50 +247,84 @@
|
||||
<string>Elevon Mix</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_13">
|
||||
<item>
|
||||
<widget class="QLabel" name="elevonLabel1">
|
||||
<property name="text">
|
||||
<string>Roll / Pitch</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_8">
|
||||
<item>
|
||||
<widget class="QSlider" name="elevonSlider1">
|
||||
<property name="maximum">
|
||||
<number>100</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>50</number>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
</widget>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_14">
|
||||
<item>
|
||||
<widget class="QLabel" name="elevonLabel1">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>65</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Rudder %</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSlider" name="elevonSlider1">
|
||||
<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="label_18">
|
||||
<property name="text">
|
||||
<string>50</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSlider" name="elevonSlider2">
|
||||
<property name="maximum">
|
||||
<number>100</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>50</number>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
</widget>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_15">
|
||||
<item>
|
||||
<widget class="QLabel" name="elevonLabel2">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>50</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Pitch %</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSlider" name="elevonSlider2">
|
||||
<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="label_25">
|
||||
<property name="text">
|
||||
<string>50</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="elevonLabel2">
|
||||
<property name="text">
|
||||
<string>Pitch 0%</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer_2">
|
||||
<property name="orientation">
|
||||
@ -444,15 +478,8 @@
|
||||
<property name="fieldGrowthPolicy">
|
||||
<enum>QFormLayout::AllNonFixedFieldsGrow</enum>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_20">
|
||||
<property name="text">
|
||||
<string>Feed Forward</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QSlider" name="horizontalSlider">
|
||||
<item row="2" column="1">
|
||||
<widget class="QSlider" name="feedForwardSlider">
|
||||
<property name="maximum">
|
||||
<number>100</number>
|
||||
</property>
|
||||
@ -467,25 +494,57 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="label_21">
|
||||
<property name="text">
|
||||
<string>Accel Time Constant</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLineEdit" name="lineEdit_4"/>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<item row="5" column="0">
|
||||
<widget class="QLabel" name="label_22">
|
||||
<property name="text">
|
||||
<string>Decel Time Constant</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QLineEdit" name="lineEdit_5"/>
|
||||
<item row="2" column="0">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_12">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_20">
|
||||
<property name="text">
|
||||
<string>FeedForward </string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="feedForwardValue">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>30</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>000</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<widget class="QDoubleSpinBox" name="accelTime">
|
||||
<property name="maximum">
|
||||
<double>1000.000000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="1">
|
||||
<widget class="QDoubleSpinBox" name="decelTime">
|
||||
<property name="maximum">
|
||||
<double>1000.000000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
@ -528,7 +587,7 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="MixerCurveWidget" name="widget" native="true">
|
||||
<widget class="MixerCurveWidget" name="multiThrottleCurve" native="true">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
|
||||
<horstretch>0</horstretch>
|
||||
@ -640,7 +699,7 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QComboBox" name="comboBox">
|
||||
<widget class="QComboBox" name="multiMotor1">
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>8</pointsize>
|
||||
@ -656,7 +715,7 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QComboBox" name="comboBox_2">
|
||||
<widget class="QComboBox" name="multiMotor2">
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>8</pointsize>
|
||||
@ -672,7 +731,7 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QComboBox" name="comboBox_3">
|
||||
<widget class="QComboBox" name="multiMotor3">
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>8</pointsize>
|
||||
@ -688,7 +747,7 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QComboBox" name="comboBox_4">
|
||||
<widget class="QComboBox" name="multiMotor4">
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>8</pointsize>
|
||||
@ -714,7 +773,7 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QComboBox" name="comboBox_5">
|
||||
<widget class="QComboBox" name="multiMotor5">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
@ -736,7 +795,7 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QComboBox" name="comboBox_6">
|
||||
<widget class="QComboBox" name="multiMotor6">
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>8</pointsize>
|
||||
@ -752,7 +811,7 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QComboBox" name="comboBox_7">
|
||||
<widget class="QComboBox" name="multiMotor7">
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>8</pointsize>
|
||||
@ -768,7 +827,7 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QComboBox" name="comboBox_8">
|
||||
<widget class="QComboBox" name="multiMotor8">
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>8</pointsize>
|
||||
@ -916,5 +975,53 @@
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>elevonSlider2</sender>
|
||||
<signal>valueChanged(int)</signal>
|
||||
<receiver>label_25</receiver>
|
||||
<slot>setNum(int)</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>127</x>
|
||||
<y>105</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>127</x>
|
||||
<y>105</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>elevonSlider1</sender>
|
||||
<signal>valueChanged(int)</signal>
|
||||
<receiver>label_18</receiver>
|
||||
<slot>setNum(int)</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>127</x>
|
||||
<y>105</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>127</x>
|
||||
<y>105</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>feedForwardSlider</sender>
|
||||
<signal>valueChanged(int)</signal>
|
||||
<receiver>feedForwardValue</receiver>
|
||||
<slot>setNum(int)</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>214</x>
|
||||
<y>157</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>144</x>
|
||||
<y>161</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
||||
|
@ -40,24 +40,11 @@ ConfigAirframeWidget::ConfigAirframeWidget(QWidget *parent) : ConfigTaskWidget(p
|
||||
m_aircraft = new Ui_AircraftWidget();
|
||||
m_aircraft->setupUi(this);
|
||||
|
||||
// Now connect the widget to the ManualControlCommand / Channel UAVObject
|
||||
/*
|
||||
ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance();
|
||||
UAVObjectManager *objManager = pm->getObject<UAVObjectManager>();
|
||||
|
||||
UAVObject *obj = dynamic_cast<UAVDataObject*>(objManager->getObject(QString("SystemSettings")));
|
||||
QString fieldName = QString("AirframeType");
|
||||
UAVObjectField *field = obj->getField(fieldName);
|
||||
m_aircraft->aircraftType->addItems(field->getOptions());
|
||||
*/
|
||||
|
||||
mixerTypes << "Mixer0Type" << "Mixer1Type" << "Mixer2Type" << "Mixer3Type"
|
||||
<< "Mixer4Type" << "Mixer5Type" << "Mixer6Type" << "Mixer7Type";
|
||||
mixerVectors << "Mixer0Vector" << "Mixer1Vector" << "Mixer2Vector" << "Mixer3Vector"
|
||||
<< "Mixer4Vector" << "Mixer5Vector" << "Mixer6Vector" << "Mixer7Vector";
|
||||
|
||||
|
||||
|
||||
QStringList airframeTypes;
|
||||
airframeTypes << "Fixed Wing" << "Multirotor" << "Helicopter" << "Custom";
|
||||
m_aircraft->aircraftType->addItems(airframeTypes);
|
||||
@ -71,6 +58,8 @@ ConfigAirframeWidget::ConfigAirframeWidget(QWidget *parent) : ConfigTaskWidget(p
|
||||
multiRotorTypes << "Quad +" << "Quad X" << "Hexacopter" << "Octocopter";
|
||||
m_aircraft->multirotorFrameType->addItems(multiRotorTypes);
|
||||
|
||||
|
||||
|
||||
QStringList channels;
|
||||
channels << "None" << "Channel0" << "Channel1" << "Channel2" <<
|
||||
"Channel3" << "Channel4" << "Channel5" << "Channel6" << "Channel7";
|
||||
@ -81,16 +70,37 @@ ConfigAirframeWidget::ConfigAirframeWidget(QWidget *parent) : ConfigTaskWidget(p
|
||||
m_aircraft->fwRudderChannel->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);
|
||||
|
||||
|
||||
// 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);
|
||||
|
||||
|
||||
requestAircraftUpdate();
|
||||
connect(m_aircraft->saveAircraftToSD, SIGNAL(clicked()), this, SLOT(saveAircraftUpdate()));
|
||||
connect(m_aircraft->saveAircraftToRAM, SIGNAL(clicked()), this, SLOT(sendAircraftUpdate()));
|
||||
connect(m_aircraft->getAircraftCurrent, SIGNAL(clicked()), this, SLOT(requestAircraftUpdate()));
|
||||
connect(m_aircraft->fixedWingType, SIGNAL(currentIndexChanged(QString)), this, SLOT(setupAirframeUI(QString)));
|
||||
connect(m_aircraft->fwAileron1Channel, SIGNAL(currentIndexChanged(int)), this, SLOT(toggleAileron2(int)));
|
||||
connect(m_aircraft->fwElevator1Channel, SIGNAL(currentIndexChanged(int)), this, SLOT(toggleElevator2(int)));
|
||||
connect(m_aircraft->multirotorFrameType, SIGNAL(currentIndexChanged(QString)), this, SLOT(setupAirframeUI(QString)));
|
||||
// connect(m_aircraft->fwAileron1Channel, SIGNAL(currentIndexChanged(int)), this, SLOT(toggleAileron2(int)));
|
||||
// connect(m_aircraft->fwElevator1Channel, SIGNAL(currentIndexChanged(int)), this, SLOT(toggleElevator2(int)));
|
||||
|
||||
connect(parent, SIGNAL(autopilotConnected()),this, SLOT(requestAircraftUpdate()));
|
||||
|
||||
@ -101,6 +111,22 @@ ConfigAirframeWidget::~ConfigAirframeWidget()
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
void ConfigAirframeWidget::resizeEvent(QResizeEvent* event)
|
||||
{
|
||||
Q_UNUSED(event);
|
||||
m_aircraft->quadShape->fitInView(quad, Qt::KeepAspectRatio);
|
||||
}
|
||||
|
||||
|
||||
void ConfigAirframeWidget::toggleAileron2(int index)
|
||||
{
|
||||
if (index) {
|
||||
@ -140,13 +166,12 @@ void ConfigAirframeWidget::requestAircraftUpdate()
|
||||
obj->requestUpdate();
|
||||
UAVObjectField *field = obj->getField(QString("AirframeType"));
|
||||
Q_ASSERT(field);
|
||||
// m_aircraft->aircraftType->setCurrentIndex(m_aircraft->aircraftType->findText(field->getValue().toString()));
|
||||
// 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);
|
||||
|
||||
// Load the throttle curve for fixed wing frames:
|
||||
// Load the Settings for fixed wing frames:
|
||||
if (frameType.startsWith("FixedWing")) {
|
||||
obj = dynamic_cast<UAVDataObject*>(objManager->getObject(QString("MixerSettings")));
|
||||
Q_ASSERT(obj);
|
||||
@ -188,6 +213,127 @@ void ConfigAirframeWidget::requestAircraftUpdate()
|
||||
Q_ASSERT(field);
|
||||
m_aircraft->fwRudderChannel->setCurrentIndex(m_aircraft->fwRudderChannel->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;
|
||||
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;
|
||||
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" ) {
|
||||
//////////////////////////////////////////////////////////////////
|
||||
// Retrieve Multirotor settings
|
||||
//////////////////////////////////////////////////////////////////
|
||||
|
||||
// First of all, curve settings:
|
||||
obj = dynamic_cast<UAVDataObject*>(objManager->getObject(QString("MixerSettings")));
|
||||
Q_ASSERT(obj);
|
||||
obj->requestUpdate();
|
||||
field = obj->getField(QString("ThrottleCurve1"));
|
||||
Q_ASSERT(field);
|
||||
QList<double> curveValues;
|
||||
// If the 1st element of the curve is <= -10, then the curve
|
||||
// is a straight line (that's how the mixer works on the mainboard):
|
||||
if (field->getValue(0).toInt() <= -10) {
|
||||
for (double i=0; i<field->getNumElements(); i++) {
|
||||
curveValues.append(-1.0 + 2*i/(field->getNumElements()-1));
|
||||
}
|
||||
} else {
|
||||
for (unsigned int i=0; i < field->getNumElements(); i++) {
|
||||
curveValues.append(field->getValue(i).toDouble());
|
||||
}
|
||||
}
|
||||
m_aircraft->multiThrottleCurve->initCurve(curveValues);
|
||||
obj = dynamic_cast<UAVDataObject*>(objManager->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()));
|
||||
} else if (frameType == "QuadX") {
|
||||
// Motors 1/2/3/4 are: NE / SE / SW / NW
|
||||
field = obj->getField(QString("VTOLMotorNE"));
|
||||
Q_ASSERT(field);
|
||||
m_aircraft->multiMotor1->setCurrentIndex(m_aircraft->multiMotor1->findText(field->getValue().toString()));
|
||||
field = obj->getField(QString("VTOLMotorSE"));
|
||||
Q_ASSERT(field);
|
||||
m_aircraft->multiMotor2->setCurrentIndex(m_aircraft->multiMotor2->findText(field->getValue().toString()));
|
||||
field = obj->getField(QString("VTOLMotorSW"));
|
||||
Q_ASSERT(field);
|
||||
m_aircraft->multiMotor3->setCurrentIndex(m_aircraft->multiMotor3->findText(field->getValue().toString()));
|
||||
field = obj->getField(QString("VTOLMotorNW"));
|
||||
Q_ASSERT(field);
|
||||
m_aircraft->multiMotor4->setCurrentIndex(m_aircraft->multiMotor4->findText(field->getValue().toString()));
|
||||
|
||||
} else if (frameType == "Hexa") {
|
||||
// Motors 1/2/3 4/5/6 are: ???
|
||||
} else if (frameType == "Octo") {
|
||||
// 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()));
|
||||
}
|
||||
|
||||
obj = dynamic_cast<UAVDataObject*>(objManager->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());
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@ -206,8 +352,13 @@ void ConfigAirframeWidget::setupAirframeUI(QString frameType)
|
||||
m_aircraft->fwRudderLabel->setEnabled(true);
|
||||
m_aircraft->fwElevator1Channel->setEnabled(true);
|
||||
m_aircraft->fwElevator1Label->setEnabled(true);
|
||||
//m_aircraft->fwElevator2Channel->setEnabled(true);
|
||||
//m_aircraft->fwElevator2Label->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");
|
||||
@ -228,7 +379,8 @@ void ConfigAirframeWidget::setupAirframeUI(QString frameType)
|
||||
m_aircraft->fwElevator1Label->setText("Elevator 1");
|
||||
m_aircraft->fwElevator2Label->setText("Elevator 2");
|
||||
m_aircraft->elevonMixBox->setHidden(false);
|
||||
m_aircraft->elevonLabel1->setText("Roll / Pitch");
|
||||
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"));
|
||||
@ -240,14 +392,45 @@ void ConfigAirframeWidget::setupAirframeUI(QString frameType)
|
||||
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->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 / Pitch");
|
||||
|
||||
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->quadShape->fitInView(quad, Qt::KeepAspectRatio);
|
||||
m_aircraft->multiMotor5->setEnabled(false);
|
||||
m_aircraft->multiMotor6->setEnabled(false);
|
||||
m_aircraft->multiMotor7->setEnabled(false);
|
||||
m_aircraft->multiMotor8->setEnabled(false);
|
||||
} 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->quadShape->fitInView(quad, Qt::KeepAspectRatio);
|
||||
m_aircraft->multiMotor5->setEnabled(false);
|
||||
m_aircraft->multiMotor6->setEnabled(false);
|
||||
m_aircraft->multiMotor7->setEnabled(false);
|
||||
m_aircraft->multiMotor8->setEnabled(false);
|
||||
} else if (frameType == "Hexa" || frameType == "Hexacopter") {
|
||||
m_aircraft->aircraftType->setCurrentIndex(m_aircraft->aircraftType->findText("Multirotor"));
|
||||
m_aircraft->multirotorFrameType->setCurrentIndex(m_aircraft->multirotorFrameType->findText("Hexacopter"));
|
||||
m_aircraft->multiMotor5->setEnabled(true);
|
||||
m_aircraft->multiMotor6->setEnabled(true);
|
||||
m_aircraft->multiMotor7->setEnabled(false);
|
||||
m_aircraft->multiMotor8->setEnabled(false);
|
||||
} else if (frameType == "Octo" || frameType == "Octocopter") {
|
||||
m_aircraft->aircraftType->setCurrentIndex(m_aircraft->aircraftType->findText("Multirotor"));
|
||||
m_aircraft->multirotorFrameType->setCurrentIndex(m_aircraft->multirotorFrameType->findText("Octocopter"));
|
||||
m_aircraft->multiMotor5->setEnabled(true);
|
||||
m_aircraft->multiMotor6->setEnabled(true);
|
||||
m_aircraft->multiMotor7->setEnabled(true);
|
||||
m_aircraft->multiMotor8->setEnabled(true);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@ -258,7 +441,6 @@ void ConfigAirframeWidget::resetField(UAVObjectField * field)
|
||||
for (unsigned int i=0;i<field->getNumElements();i++) {
|
||||
field->setValue(0,i);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@ -295,7 +477,7 @@ bool ConfigAirframeWidget::setupFrameFixedWing()
|
||||
((m_aircraft->fwAileron1Channel->currentText() == "None") &&
|
||||
(m_aircraft->fwRudderChannel->currentText() == "None"))) {
|
||||
// TODO: explain the problem in the UI
|
||||
m_aircraft->fwStatusLabel->setText("WARNING: check channel assignment");
|
||||
m_aircraft->fwStatusLabel->setText("ERROR: check channel assignment");
|
||||
return false;
|
||||
}
|
||||
// Now setup the channels:
|
||||
@ -329,15 +511,8 @@ bool ConfigAirframeWidget::setupFrameFixedWing()
|
||||
|
||||
obj->updated();
|
||||
|
||||
// Save the curve:
|
||||
obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
|
||||
Q_ASSERT(obj);
|
||||
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);
|
||||
}
|
||||
|
||||
// ... and compute the matrix:
|
||||
// In order to make code a bit nicer, we assume:
|
||||
// - Channel dropdowns start with 'None', then 0 to 7
|
||||
@ -391,10 +566,19 @@ bool ConfigAirframeWidget::setupFrameFixedWing()
|
||||
ti = field->getElementNames().indexOf("Roll");
|
||||
field->setValue(1, 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(1, 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");
|
||||
@ -402,16 +586,6 @@ bool ConfigAirframeWidget::setupFrameFixedWing()
|
||||
resetField(field);
|
||||
ti = field->getElementNames().indexOf("Pitch");
|
||||
field->setValue(1, ti);
|
||||
// Only set Elevator 2 if Aileron 1 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(1, ti);
|
||||
}
|
||||
}
|
||||
|
||||
obj->updated();
|
||||
@ -432,7 +606,7 @@ bool ConfigAirframeWidget::setupFrameElevon()
|
||||
m_aircraft->fwAileron1Channel->currentText() == "None" ||
|
||||
m_aircraft->fwAileron2Channel->currentText() == "None") {
|
||||
// TODO: explain the problem in the UI
|
||||
m_aircraft->fwStatusLabel->setText("WARNING: check channel assignment");
|
||||
m_aircraft->fwStatusLabel->setText("ERROR: check channel assignment");
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -461,12 +635,6 @@ bool ConfigAirframeWidget::setupFrameElevon()
|
||||
// Save the curve:
|
||||
obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
|
||||
Q_ASSERT(obj);
|
||||
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);
|
||||
}
|
||||
|
||||
// ... and compute the matrix:
|
||||
// In order to make code a bit nicer, we assume:
|
||||
// - Channel dropdowns start with 'None', then 0 to 7
|
||||
@ -508,9 +676,9 @@ bool ConfigAirframeWidget::setupFrameElevon()
|
||||
field = obj->getField(mixerVectors.at(eng));
|
||||
resetField(field);
|
||||
ti = field->getElementNames().indexOf("Pitch");
|
||||
field->setValue(1, ti);
|
||||
field->setDouble((double)m_aircraft->elevonSlider2->value()/100, ti);
|
||||
ti = field->getElementNames().indexOf("Roll");
|
||||
field->setValue(1,ti);
|
||||
field->setDouble((double)m_aircraft->elevonSlider1->value()/100,ti);
|
||||
}
|
||||
|
||||
eng = m_aircraft->fwAileron2Channel->currentIndex()-1;
|
||||
@ -520,9 +688,9 @@ bool ConfigAirframeWidget::setupFrameElevon()
|
||||
field = obj->getField(mixerVectors.at(eng));
|
||||
resetField(field);
|
||||
ti = field->getElementNames().indexOf("Pitch");
|
||||
field->setValue(1, ti);
|
||||
field->setDouble((double)m_aircraft->elevonSlider2->value()/100, ti);
|
||||
ti = field->getElementNames().indexOf("Roll");
|
||||
field->setValue(-1,ti);
|
||||
field->setDouble(-(double)m_aircraft->elevonSlider1->value()/100,ti);
|
||||
}
|
||||
|
||||
obj->updated();
|
||||
@ -530,61 +698,238 @@ bool ConfigAirframeWidget::setupFrameElevon()
|
||||
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(1, 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->setDouble(1,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->setDouble(-1,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->setDouble((double)m_aircraft->elevonSlider2->value()/100, ti);
|
||||
ti = field->getElementNames().indexOf("Yaw");
|
||||
field->setDouble((double)m_aircraft->elevonSlider1->value()/100,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->setDouble((double)m_aircraft->elevonSlider2->value()/100, ti);
|
||||
ti = field->getElementNames().indexOf("Yaw");
|
||||
field->setDouble(-(double)m_aircraft->elevonSlider1->value()/100,ti);
|
||||
|
||||
obj->updated();
|
||||
m_aircraft->fwStatusLabel->setText("Mixer generated");
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Set up a Quad-X
|
||||
|
||||
#ifdef MATRIX_QUAD_X
|
||||
#define MATRIX_OUTPUTS 4
|
||||
#define MATRIX_QUAD
|
||||
|
||||
//Note the offset is 0 for a servo (zero in the middle) and -1
|
||||
//for a motor (zero at min pulse width)
|
||||
|
||||
//Throttle needs to be double because normal throttle range is 0 to +1 instead of -1 to +1
|
||||
//as with pitch, roll, yaw. The final output range is -1 to +1
|
||||
const float matrixGains[MATRIX_OUTPUTS][MAX_COMMANDS + 1]=
|
||||
Help function: setupQuadMotor
|
||||
*/
|
||||
void ConfigAirframeWidget::setupQuadMotor(int channel, double pitch, double roll, double yaw)
|
||||
{
|
||||
// pitch roll yaw throttle offset
|
||||
{0.5 ,0.5 ,0.5 ,1.8 ,-1 }, //Front left motor (CW)
|
||||
{0.5 ,-0.5 ,-0.5 ,1.8 ,-1 }, //Front right motor(CCW)
|
||||
{-0.5 ,-0.5 ,0.5 ,1.8 ,-1 }, //rear right motor (CW)
|
||||
{-0.5 ,0.5 ,-0.5 ,1.8 ,-1 }, //Rear left motor (CCW)
|
||||
};
|
||||
|
||||
|
||||
#ifdef MATRIX_QUAD_PLUS
|
||||
#define MATRIX_OUTPUTS 4
|
||||
#define MATRIX_QUAD
|
||||
|
||||
//Note the offset is 0 for a servo (zero in the middle) and -1
|
||||
//for a motor (zero at min pulse width)
|
||||
|
||||
//Throttle needs to be double because normal throttle range is 0 to +1 instead of -1 to +1
|
||||
//as with pitch, roll, yaw. The final output range is -1 to +1
|
||||
const float matrixGains[MATRIX_OUTPUTS][MAX_COMMANDS + 1]=
|
||||
{
|
||||
// pitch roll yaw throttle offset
|
||||
{1 ,0 ,0.5 ,1.8 ,-1 }, //Front motor (CW)
|
||||
{0 ,-1 ,-0.5 ,1.8 ,-1 }, //Right motor(CCW)
|
||||
{-1 ,0 ,0.5 ,1.8 ,-1 }, //Rear motor (CW)
|
||||
{0 ,1 ,-0.5 ,1.8 ,-1 }, //Left motor (CCW)
|
||||
};
|
||||
|
||||
#endif
|
||||
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(1, ti);
|
||||
ti = field->getElementNames().indexOf("Roll");
|
||||
field->setValue(roll,ti);
|
||||
ti = field->getElementNames().indexOf("Pitch");
|
||||
field->setValue(pitch,ti);
|
||||
ti = field->getElementNames().indexOf("Yaw");
|
||||
field->setValue(yaw,ti);
|
||||
}
|
||||
|
||||
/**
|
||||
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;
|
||||
}
|
||||
|
||||
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...
|
||||
|
||||
// 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 throttle offset
|
||||
// {0.5 ,0.5 ,0.5 ,1.8 ,-1 }, //Front left motor (CW)
|
||||
// {0.5 ,-0.5 ,-0.5 ,1.8 ,-1 }, //Front right motor(CCW)
|
||||
// {-0.5 ,-0.5 ,0.5 ,1.8 ,-1 }, //rear right motor (CW)
|
||||
// {-0.5 ,0.5 ,-0.5 ,1.8 ,-1 }, //Rear left motor (CCW)
|
||||
//
|
||||
// Motor 1 to 4, P Layout:
|
||||
// pitch roll yaw throttle offset
|
||||
// {1 ,0 ,0.5 ,1.8 ,-1 }, //Front motor (CW)
|
||||
// {0 ,-1 ,-0.5 ,1.8 ,-1 }, //Right motor(CCW)
|
||||
// {-1 ,0 ,0.5 ,1.8 ,-1 }, //Rear motor (CW)
|
||||
// {0 ,1 ,-0.5 ,1.8 ,-1 }, //Left motor (CCW)
|
||||
int channel = m_aircraft->multiMotor1->currentIndex()-1;
|
||||
pLayout ? setupQuadMotor(channel, 1, 0, 0.5)
|
||||
: setupQuadMotor(channel, 0.5, 0.5, 0.5);
|
||||
channel = m_aircraft->multiMotor2->currentIndex()-1;
|
||||
pLayout ? setupQuadMotor(channel, 0, -1, -0.5)
|
||||
: setupQuadMotor(channel, 0.5, -0.5, -0.5);
|
||||
channel = m_aircraft->multiMotor3->currentIndex()-1;
|
||||
pLayout ? setupQuadMotor(channel, -1, 0, 0.5)
|
||||
: setupQuadMotor(channel, -0.5, -0.5, 0.5);
|
||||
channel = m_aircraft->multiMotor4->currentIndex()-1;
|
||||
pLayout ? setupQuadMotor(channel, 0, 1, -0.5)
|
||||
: setupQuadMotor(channel, -0.5, 0.5, -0.5);
|
||||
|
||||
obj->updated();
|
||||
m_aircraft->mrStatusLabel->setText("SUCCESS: Mixer Saved OK");
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Sends the config to the board (airframe type)
|
||||
|
||||
We do all the tasks commong to all airframes, or family of airframes, and
|
||||
we call additional methods for specific frames, so that we do not have a code
|
||||
that is too heavy.
|
||||
*/
|
||||
void ConfigAirframeWidget::sendAircraftUpdate()
|
||||
{
|
||||
ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance();
|
||||
UAVObjectManager *objManager = pm->getObject<UAVObjectManager>();
|
||||
QString airframeType;
|
||||
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")));
|
||||
Q_ASSERT(obj);
|
||||
UAVObjectField* 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();
|
||||
@ -593,13 +938,46 @@ void ConfigAirframeWidget::sendAircraftUpdate()
|
||||
setupFrameElevon();
|
||||
} else { // Vtail
|
||||
airframeType = "FixedWingVtail";
|
||||
m_aircraft->fwStatusLabel->setText("Mixed Not Implemented");
|
||||
setupFrameVtail();
|
||||
}
|
||||
} else if (m_aircraft->aircraftType->currentText() == "Multirotor") {
|
||||
// We can already setup the feedforward here, as it is common to all platforms
|
||||
UAVDataObject* obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("MixerSettings")));
|
||||
Q_ASSERT(obj);
|
||||
UAVObjectField* field = obj->getField(QString("FeedForward"));
|
||||
Q_ASSERT(field);
|
||||
field->setDouble((double)m_aircraft->feedForwardSlider->value()/100);
|
||||
field = obj->getField(QString("AccelTime"));
|
||||
Q_ASSERT(field);
|
||||
field->setDouble(m_aircraft->accelTime->value());
|
||||
field = obj->getField(QString("DecelTime"));
|
||||
Q_ASSERT(field);
|
||||
field->setDouble(m_aircraft->decelTime->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";
|
||||
} else if (m_aircraft->multirotorFrameType->currentText() == "Octocopter") {
|
||||
airframeType = "Octo";
|
||||
}
|
||||
|
||||
} else {
|
||||
airframeType = "FixedWing";
|
||||
}
|
||||
|
||||
UAVDataObject* obj = dynamic_cast<UAVDataObject*>(objManager->getObject(QString("SystemSettings")));
|
||||
UAVDataObject* obj = dynamic_cast<UAVDataObject*>(getObjectManager()->getObject(QString("SystemSettings")));
|
||||
Q_ASSERT(obj);
|
||||
UAVObjectField* field = obj->getField(QString("AirframeType"));
|
||||
field->setValue(airframeType);
|
||||
|
@ -49,12 +49,17 @@ private:
|
||||
Ui_AircraftWidget *m_aircraft;
|
||||
bool setupFrameFixedWing();
|
||||
bool setupFrameElevon();
|
||||
bool setupFrameVtail();
|
||||
bool setupQuad(bool pLayout);
|
||||
|
||||
void resetField(UAVObjectField * field);
|
||||
void resetActuators();
|
||||
//void setMixerChannel(int channelNumber, bool channelIsMotor, QList<double> vector);
|
||||
void setupQuadMotor(int channel, double roll, double pitch, double yaw);
|
||||
|
||||
QStringList mixerTypes;
|
||||
QStringList mixerVectors;
|
||||
|
||||
|
||||
QGraphicsSvgItem *quad;
|
||||
|
||||
private slots:
|
||||
void requestAircraftUpdate();
|
||||
@ -64,6 +69,11 @@ private slots:
|
||||
void toggleAileron2(int index);
|
||||
void toggleElevator2(int index);
|
||||
|
||||
protected:
|
||||
void showEvent(QShowEvent *event);
|
||||
void resizeEvent(QResizeEvent *event);
|
||||
|
||||
|
||||
};
|
||||
|
||||
#endif // CONFIGAIRFRAMEWIDGET_H
|
||||
|
@ -7,5 +7,6 @@
|
||||
<file>images/AHRS-v1.3.png</file>
|
||||
<file>images/paper-plane.svg</file>
|
||||
<file>images/curve-bg.svg</file>
|
||||
<file>images/quad-shapes.svg</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
@ -9,77 +9,21 @@
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="1052.3622"
|
||||
height="744.09448"
|
||||
id="svg2"
|
||||
width="744.09448819"
|
||||
height="1052.3622047"
|
||||
id="svg2917"
|
||||
version="1.1"
|
||||
inkscape:version="0.47 r22583"
|
||||
sodipodi:docname="quad-shapes.svg">
|
||||
<defs
|
||||
id="defs4">
|
||||
id="defs2919">
|
||||
<inkscape:perspective
|
||||
sodipodi:type="inkscape:persp3d"
|
||||
inkscape:vp_x="0 : 526.18109 : 1"
|
||||
inkscape:vp_y="0 : 1000 : 0"
|
||||
inkscape:vp_z="744.09448 : 526.18109 : 1"
|
||||
inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
|
||||
id="perspective10" />
|
||||
<inkscape:perspective
|
||||
id="perspective3598"
|
||||
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
|
||||
inkscape:vp_z="1 : 0.5 : 1"
|
||||
inkscape:vp_y="0 : 1000 : 0"
|
||||
inkscape:vp_x="0 : 0.5 : 1"
|
||||
sodipodi:type="inkscape:persp3d" />
|
||||
<inkscape:perspective
|
||||
id="perspective3598-7"
|
||||
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
|
||||
inkscape:vp_z="1 : 0.5 : 1"
|
||||
inkscape:vp_y="0 : 1000 : 0"
|
||||
inkscape:vp_x="0 : 0.5 : 1"
|
||||
sodipodi:type="inkscape:persp3d" />
|
||||
<inkscape:perspective
|
||||
id="perspective3598-3"
|
||||
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
|
||||
inkscape:vp_z="1 : 0.5 : 1"
|
||||
inkscape:vp_y="0 : 1000 : 0"
|
||||
inkscape:vp_x="0 : 0.5 : 1"
|
||||
sodipodi:type="inkscape:persp3d" />
|
||||
<inkscape:perspective
|
||||
id="perspective3787"
|
||||
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
|
||||
inkscape:vp_z="1 : 0.5 : 1"
|
||||
inkscape:vp_y="0 : 1000 : 0"
|
||||
inkscape:vp_x="0 : 0.5 : 1"
|
||||
sodipodi:type="inkscape:persp3d" />
|
||||
<inkscape:perspective
|
||||
id="perspective3812"
|
||||
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
|
||||
inkscape:vp_z="1 : 0.5 : 1"
|
||||
inkscape:vp_y="0 : 1000 : 0"
|
||||
inkscape:vp_x="0 : 0.5 : 1"
|
||||
sodipodi:type="inkscape:persp3d" />
|
||||
<inkscape:perspective
|
||||
id="perspective3837"
|
||||
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
|
||||
inkscape:vp_z="1 : 0.5 : 1"
|
||||
inkscape:vp_y="0 : 1000 : 0"
|
||||
inkscape:vp_x="0 : 0.5 : 1"
|
||||
sodipodi:type="inkscape:persp3d" />
|
||||
<inkscape:perspective
|
||||
id="perspective3862"
|
||||
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
|
||||
inkscape:vp_z="1 : 0.5 : 1"
|
||||
inkscape:vp_y="0 : 1000 : 0"
|
||||
inkscape:vp_x="0 : 0.5 : 1"
|
||||
sodipodi:type="inkscape:persp3d" />
|
||||
<inkscape:perspective
|
||||
id="perspective3893"
|
||||
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
|
||||
inkscape:vp_z="1 : 0.5 : 1"
|
||||
inkscape:vp_y="0 : 1000 : 0"
|
||||
inkscape:vp_x="0 : 0.5 : 1"
|
||||
sodipodi:type="inkscape:persp3d" />
|
||||
id="perspective2925" />
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
@ -88,38 +32,48 @@
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="0.98994949"
|
||||
inkscape:cx="500.32237"
|
||||
inkscape:cy="220.64359"
|
||||
inkscape:zoom="1.979899"
|
||||
inkscape:cx="400.42368"
|
||||
inkscape:cy="914.60167"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="quad-X"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="false"
|
||||
showguides="true"
|
||||
inkscape:guide-bbox="true"
|
||||
inkscape:snap-to-guides="true"
|
||||
inkscape:snap-grids="true"
|
||||
inkscape:window-width="1366"
|
||||
inkscape:window-height="693"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="24"
|
||||
inkscape:window-maximized="1"
|
||||
showguides="true"
|
||||
inkscape:guide-bbox="true">
|
||||
inkscape:window-maximized="1">
|
||||
<sodipodi:guide
|
||||
orientation="0,1"
|
||||
position="615.1829,267.69042"
|
||||
id="guide3751" />
|
||||
<sodipodi:guide
|
||||
orientation="1,0"
|
||||
position="540.43161,247.48737"
|
||||
id="guide3753" />
|
||||
<sodipodi:guide
|
||||
orientation="1,0"
|
||||
position="753.5738,135.36044"
|
||||
id="guide3755" />
|
||||
position="394.46457,984.89873"
|
||||
id="guide2927" />
|
||||
<sodipodi:guide
|
||||
orientation="0,1"
|
||||
position="655.589,87.883271"
|
||||
id="guide3757" />
|
||||
position="386.38335,864.69058"
|
||||
id="guide2929" />
|
||||
<sodipodi:guide
|
||||
orientation="1,0"
|
||||
position="442.95189,999.54594"
|
||||
id="guide2931" />
|
||||
<sodipodi:guide
|
||||
orientation="0,1"
|
||||
position="152.53303,923.57143"
|
||||
id="guide3709" />
|
||||
<sodipodi:guide
|
||||
orientation="1,0"
|
||||
position="88.571429,923.57143"
|
||||
id="guide3711" />
|
||||
<sodipodi:guide
|
||||
orientation="1,0"
|
||||
position="346.48232,984.89873"
|
||||
id="guide3713" />
|
||||
</sodipodi:namedview>
|
||||
<metadata
|
||||
id="metadata7">
|
||||
id="metadata2922">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
@ -133,389 +87,382 @@
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
transform="translate(-188.30535,184.5505)">
|
||||
id="layer1">
|
||||
<g
|
||||
style="stroke-width:5;stroke-miterlimit:4;stroke-dasharray:none"
|
||||
id="g3675"
|
||||
transform="matrix(-1,0,0,1,639.78188,112)">
|
||||
id="quad-plus"
|
||||
inkscape:label="#g3890">
|
||||
<path
|
||||
id="path3721"
|
||||
d="m 88.571429,129.03959 127.857141,0"
|
||||
style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none" />
|
||||
<path
|
||||
id="path3723"
|
||||
d="m 152.03811,74.534523 0,107.113367"
|
||||
style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none" />
|
||||
<path
|
||||
transform="translate(-0.50000024,0.50000029)"
|
||||
d="m 176.7767,75.039597 a 23.738585,23.738585 0 1 1 -47.47717,0 23.738585,23.738585 0 1 1 47.47717,0 z"
|
||||
sodipodi:ry="23.738585"
|
||||
sodipodi:rx="23.738585"
|
||||
sodipodi:cy="75.039597"
|
||||
sodipodi:cx="153.03812"
|
||||
id="path2935"
|
||||
style="fill:#a3a3a3;fill-opacity:1;stroke:none"
|
||||
sodipodi:type="arc" />
|
||||
<path
|
||||
transform="translate(-66,54)"
|
||||
sodipodi:type="arc"
|
||||
style="fill:#a3a3a3;fill-opacity:1;stroke:none"
|
||||
id="path3715"
|
||||
sodipodi:cx="153.03812"
|
||||
sodipodi:cy="75.039597"
|
||||
sodipodi:rx="23.738585"
|
||||
sodipodi:ry="23.738585"
|
||||
d="m 176.7767,75.039597 a 23.738585,23.738585 0 1 1 -47.47717,0 23.738585,23.738585 0 1 1 47.47717,0 z" />
|
||||
<path
|
||||
d="m 176.7767,75.039597 a 23.738585,23.738585 0 1 1 -47.47717,0 23.738585,23.738585 0 1 1 47.47717,0 z"
|
||||
sodipodi:ry="23.738585"
|
||||
sodipodi:rx="23.738585"
|
||||
sodipodi:cy="75.039597"
|
||||
sodipodi:cx="153.03812"
|
||||
id="path3717"
|
||||
style="fill:#a3a3a3;fill-opacity:1;stroke:none"
|
||||
sodipodi:type="arc"
|
||||
transform="translate(64,54)" />
|
||||
<path
|
||||
transform="translate(0,108)"
|
||||
sodipodi:type="arc"
|
||||
style="fill:#a3a3a3;fill-opacity:1;stroke:none"
|
||||
id="path3719"
|
||||
sodipodi:cx="153.03812"
|
||||
sodipodi:cy="75.039597"
|
||||
sodipodi:rx="23.738585"
|
||||
sodipodi:ry="23.738585"
|
||||
d="m 176.7767,75.039597 a 23.738585,23.738585 0 1 1 -47.47717,0 23.738585,23.738585 0 1 1 47.47717,0 z" />
|
||||
<text
|
||||
id="text3725"
|
||||
y="82.219322"
|
||||
x="143.85715"
|
||||
style="font-size:40px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
|
||||
xml:space="preserve"><tspan
|
||||
style="font-size:24px"
|
||||
y="82.219322"
|
||||
x="143.85715"
|
||||
id="tspan3727"
|
||||
sodipodi:role="line">1</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:40px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
|
||||
x="209.85715"
|
||||
y="138.21933"
|
||||
id="text3729"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan3731"
|
||||
x="209.85715"
|
||||
y="138.21933"
|
||||
style="font-size:24px">2</tspan></text>
|
||||
<text
|
||||
id="text3733"
|
||||
y="190.21933"
|
||||
x="145.85715"
|
||||
style="font-size:40px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
|
||||
xml:space="preserve"><tspan
|
||||
style="font-size:24px"
|
||||
y="190.21933"
|
||||
x="145.85715"
|
||||
id="tspan3735"
|
||||
sodipodi:role="line">3</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:40px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
|
||||
x="79.857147"
|
||||
y="136.21933"
|
||||
id="text3737"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan3739"
|
||||
x="79.857147"
|
||||
y="136.21933"
|
||||
style="font-size:24px">4</tspan></text>
|
||||
<g
|
||||
id="quad-plus"
|
||||
inkscape:label="#g3696">
|
||||
id="g3748">
|
||||
<path
|
||||
id="path3630"
|
||||
d="m 247.48737,381.85227 282.84272,0"
|
||||
style="fill:none;stroke:#000000;stroke-width:4;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
|
||||
transform="matrix(-1,0,0,1,639.78188,-112)" />
|
||||
d="m 176.7767,75.039597 a 23.738585,23.738585 0 1 1 -45.662,-9.104071"
|
||||
sodipodi:ry="23.738585"
|
||||
sodipodi:rx="23.738585"
|
||||
sodipodi:cy="75.039597"
|
||||
sodipodi:cx="153.03812"
|
||||
id="path3744"
|
||||
style="fill:none;stroke:#000000;stroke-width:2.60960245;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
|
||||
sodipodi:type="arc"
|
||||
transform="matrix(0.76640028,0,0,0.76640028,35.249661,18.029229)"
|
||||
sodipodi:start="0"
|
||||
sodipodi:end="3.5351905"
|
||||
sodipodi:open="true" />
|
||||
<path
|
||||
id="path3632"
|
||||
d="m 391.00187,260.40259 0,241.42646"
|
||||
style="fill:none;stroke:#000000;stroke-width:4;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
|
||||
transform="matrix(-1,0,0,1,639.78188,-112)" />
|
||||
style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none"
|
||||
d="m 138.92857,74.147895 -2.85714,-5.714285 -5.35714,3.928571"
|
||||
id="path3746" />
|
||||
</g>
|
||||
<g
|
||||
transform="translate(0,108)"
|
||||
id="g3752">
|
||||
<path
|
||||
transform="matrix(-1,0,0,1,474.49429,-174.48732)"
|
||||
d="m 288.57142,329.50504 c 0,34.71504 -28.1421,62.85714 -62.85714,62.85714 -34.71504,0 -62.85714,-28.1421 -62.85714,-62.85714 0,-34.71505 28.1421,-62.85715 62.85714,-62.85715 34.71504,0 62.85714,28.1421 62.85714,62.85715 z"
|
||||
sodipodi:ry="62.857143"
|
||||
sodipodi:rx="62.857143"
|
||||
sodipodi:cy="329.50504"
|
||||
sodipodi:cx="225.71428"
|
||||
id="path2816"
|
||||
style="opacity:0.87866109000000003;fill:#d1d1d1;fill-opacity:1;stroke:none"
|
||||
sodipodi:type="arc" />
|
||||
<path
|
||||
transform="matrix(-1,0,0,1,474.49429,55.18182)"
|
||||
d="m 288.57142,329.50504 c 0,34.71504 -28.1421,62.85714 -62.85714,62.85714 -34.71504,0 -62.85714,-28.1421 -62.85714,-62.85714 0,-34.71505 28.1421,-62.85715 62.85714,-62.85715 34.71504,0 62.85714,28.1421 62.85714,62.85715 z"
|
||||
sodipodi:ry="62.857143"
|
||||
sodipodi:rx="62.857143"
|
||||
sodipodi:cy="329.50504"
|
||||
sodipodi:cx="225.71428"
|
||||
id="path2816-2"
|
||||
style="opacity:0.87866109000000003;fill:#d1d1d1;fill-opacity:1;stroke:none"
|
||||
sodipodi:type="arc" />
|
||||
<path
|
||||
transform="matrix(-1,0,0,1,339.20668,-59.65276)"
|
||||
d="m 288.57142,329.50504 c 0,34.71504 -28.1421,62.85714 -62.85714,62.85714 -34.71504,0 -62.85714,-28.1421 -62.85714,-62.85714 0,-34.71505 28.1421,-62.85715 62.85714,-62.85715 34.71504,0 62.85714,28.1421 62.85714,62.85715 z"
|
||||
sodipodi:ry="62.857143"
|
||||
sodipodi:rx="62.857143"
|
||||
sodipodi:cy="329.50504"
|
||||
sodipodi:cx="225.71428"
|
||||
id="path2816-3"
|
||||
style="opacity:0.87866109000000003;fill:#d1d1d1;fill-opacity:1;stroke:none"
|
||||
sodipodi:type="arc" />
|
||||
<path
|
||||
transform="matrix(-1,0,0,1,614.33367,-59.65276)"
|
||||
d="m 288.57142,329.50504 c 0,34.71504 -28.1421,62.85714 -62.85714,62.85714 -34.71504,0 -62.85714,-28.1421 -62.85714,-62.85714 0,-34.71505 28.1421,-62.85715 62.85714,-62.85715 34.71504,0 62.85714,28.1421 62.85714,62.85715 z"
|
||||
sodipodi:ry="62.857143"
|
||||
sodipodi:rx="62.857143"
|
||||
sodipodi:cy="329.50504"
|
||||
sodipodi:cx="225.71428"
|
||||
id="path2816-7"
|
||||
style="opacity:0.87866109000000003;fill:#d1d1d1;fill-opacity:1;stroke:none"
|
||||
sodipodi:open="true"
|
||||
sodipodi:end="3.5351905"
|
||||
sodipodi:start="0"
|
||||
transform="matrix(0.76640028,0,0,0.76640028,35.249661,18.029229)"
|
||||
sodipodi:type="arc"
|
||||
style="fill:none;stroke:#000000;stroke-width:2.60960245;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
|
||||
id="path3754"
|
||||
sodipodi:cx="153.03812"
|
||||
sodipodi:cy="75.039597"
|
||||
sodipodi:rx="23.738585"
|
||||
sodipodi:ry="23.738585"
|
||||
d="m 176.7767,75.039597 c 0,13.110458 -10.62813,23.738584 -23.73858,23.738584 -13.11046,0 -23.73859,-10.628126 -23.73859,-23.738584 0,-3.124577 0.61685,-6.218415 1.81517,-9.104071" />
|
||||
<path
|
||||
id="path3756"
|
||||
d="m 138.92857,74.147895 -2.85714,-5.714285 -5.35714,3.928571"
|
||||
style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
|
||||
</g>
|
||||
<path
|
||||
sodipodi:open="true"
|
||||
sodipodi:end="3.5351905"
|
||||
sodipodi:start="0"
|
||||
transform="matrix(0.76640028,0,0,0.76640028,-30.17891,72.386372)"
|
||||
sodipodi:type="arc"
|
||||
style="fill:none;stroke:#000000;stroke-width:2.60960245;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
|
||||
id="path3868"
|
||||
sodipodi:cx="153.03812"
|
||||
sodipodi:cy="75.039597"
|
||||
sodipodi:rx="23.738585"
|
||||
sodipodi:ry="23.738585"
|
||||
d="m 176.7767,75.039597 a 23.738585,23.738585 0 1 1 -45.662,-9.104071" />
|
||||
<path
|
||||
d="m 176.7767,75.039597 a 23.738585,23.738585 0 1 1 -45.662,-9.104071"
|
||||
sodipodi:ry="23.738585"
|
||||
sodipodi:rx="23.738585"
|
||||
sodipodi:cy="75.039597"
|
||||
sodipodi:cx="153.03812"
|
||||
id="path3874"
|
||||
style="fill:none;stroke:#000000;stroke-width:2.60960245;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
|
||||
sodipodi:type="arc"
|
||||
transform="matrix(0.76640028,0,0,0.76640028,99.82109,72.386372)"
|
||||
sodipodi:start="0"
|
||||
sodipodi:end="3.5351905"
|
||||
sodipodi:open="true" />
|
||||
<path
|
||||
id="path3882"
|
||||
d="m 101.07143,134.50504 4.28571,-3.92857 2.85715,5.35714"
|
||||
style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none"
|
||||
d="m 101.07143,134.50504 4.28571,-3.92857 2.85715,5.35714"
|
||||
id="path3884" />
|
||||
<path
|
||||
id="path3886"
|
||||
d="m 101.07143,134.50504 4.28571,-3.92857 2.85715,5.35714"
|
||||
style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
|
||||
d="m 231.07143,134.50504 4.28571,-3.92857 2.85715,5.35714"
|
||||
id="path3888" />
|
||||
</g>
|
||||
<g
|
||||
id="quad-X"
|
||||
inkscape:label="#g4034">
|
||||
<path
|
||||
id="path4030"
|
||||
d="m 346.48232,88.676654 96.46957,82.832506"
|
||||
style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none"
|
||||
sodipodi:nodetypes="cc" />
|
||||
<path
|
||||
id="path4032"
|
||||
d="M 346.48232,172.51932 431.84021,87.161425"
|
||||
style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none"
|
||||
sodipodi:nodetypes="cc" />
|
||||
<g
|
||||
transform="translate(-62.055796,15.66244)"
|
||||
id="g3998">
|
||||
<path
|
||||
transform="translate(255.5,0.50000029)"
|
||||
d="m 176.7767,75.039597 c 0,13.110458 -10.62813,23.738584 -23.73858,23.738584 -13.11046,0 -23.73859,-10.628126 -23.73859,-23.738584 0,-13.110459 10.62813,-23.738585 23.73859,-23.738585 13.11045,0 23.73858,10.628126 23.73858,23.738585 z"
|
||||
sodipodi:ry="23.738585"
|
||||
sodipodi:rx="23.738585"
|
||||
sodipodi:cy="75.039597"
|
||||
sodipodi:cx="153.03812"
|
||||
id="path3924"
|
||||
style="fill:#a3a3a3;fill-opacity:1;stroke:none"
|
||||
sodipodi:type="arc" />
|
||||
<text
|
||||
id="text3932"
|
||||
y="82.219322"
|
||||
x="399.85715"
|
||||
style="font-size:40px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
|
||||
xml:space="preserve"><tspan
|
||||
style="font-size:24px"
|
||||
y="82.219322"
|
||||
x="399.85715"
|
||||
id="tspan3934"
|
||||
sodipodi:role="line">1</tspan></text>
|
||||
<g
|
||||
style="stroke-width:5;stroke-miterlimit:4;stroke-dasharray:none"
|
||||
id="g3638"
|
||||
transform="matrix(-1,0,0,1,636.67095,-112)">
|
||||
id="g3948"
|
||||
transform="translate(256,0)">
|
||||
<path
|
||||
d="m 176.7767,75.039597 c 0,13.110458 -10.62813,23.738584 -23.73858,23.738584 -13.11046,0 -23.73859,-10.628126 -23.73859,-23.738584 0,-3.124577 0.61685,-6.218415 1.81517,-9.104071"
|
||||
sodipodi:ry="23.738585"
|
||||
sodipodi:rx="23.738585"
|
||||
sodipodi:cy="75.039597"
|
||||
sodipodi:cx="153.03812"
|
||||
id="path3950"
|
||||
style="fill:none;stroke:#000000;stroke-width:2.60960245;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
|
||||
sodipodi:type="arc"
|
||||
style="fill:none;stroke:#000000;stroke-width:5;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
|
||||
id="path3634"
|
||||
sodipodi:cx="76.266518"
|
||||
sodipodi:cy="77.086395"
|
||||
sodipodi:rx="43.941635"
|
||||
sodipodi:ry="43.941635"
|
||||
d="m 120.20815,77.086395 c 0,24.268295 -19.67334,43.941635 -43.941632,43.941635 -24.268295,0 -43.941635,-19.67334 -43.941635,-43.941635 0,-6.314528 1.360941,-12.554884 3.990127,-18.29602"
|
||||
transform="translate(314.73535,188.16057)"
|
||||
transform="matrix(0.76640028,0,0,0.76640028,35.249661,18.029229)"
|
||||
sodipodi:start="0"
|
||||
sodipodi:end="3.5710428"
|
||||
sodipodi:end="3.5351905"
|
||||
sodipodi:open="true" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
|
||||
d="m 152.53303,50.82243 10.60661,-7.576144 3.53553,10.606602 0,0"
|
||||
id="path3636"
|
||||
transform="translate(188.30535,204.16057)" />
|
||||
</g>
|
||||
<g
|
||||
transform="matrix(-1,0,0,1,636.67095,122)"
|
||||
id="g3663"
|
||||
style="stroke-width:5;stroke-miterlimit:4;stroke-dasharray:none">
|
||||
<path
|
||||
sodipodi:open="true"
|
||||
sodipodi:end="3.5710428"
|
||||
sodipodi:start="0"
|
||||
transform="translate(314.73535,188.16057)"
|
||||
d="m 120.20815,77.086395 c 0,24.268295 -19.67334,43.941635 -43.941632,43.941635 -24.268295,0 -43.941635,-19.67334 -43.941635,-43.941635 0,-6.314528 1.360941,-12.554884 3.990127,-18.29602"
|
||||
sodipodi:ry="43.941635"
|
||||
sodipodi:rx="43.941635"
|
||||
sodipodi:cy="77.086395"
|
||||
sodipodi:cx="76.266518"
|
||||
id="path3665"
|
||||
style="fill:none;stroke:#000000;stroke-width:5;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
|
||||
sodipodi:type="arc" />
|
||||
<path
|
||||
transform="translate(188.30535,204.16057)"
|
||||
id="path3667"
|
||||
d="m 152.53303,50.82243 10.60661,-7.576144 3.53553,10.606602 0,0"
|
||||
style="fill:none;stroke:#000000;stroke-width:5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
|
||||
</g>
|
||||
<g
|
||||
style="stroke-width:5;stroke-miterlimit:4;stroke-dasharray:none"
|
||||
id="g3669"
|
||||
transform="translate(-274.39854,4)">
|
||||
<path
|
||||
sodipodi:type="arc"
|
||||
style="fill:none;stroke:#000000;stroke-width:5;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
|
||||
id="path3671"
|
||||
sodipodi:cx="76.266518"
|
||||
sodipodi:cy="77.086395"
|
||||
sodipodi:rx="43.941635"
|
||||
sodipodi:ry="43.941635"
|
||||
d="m 120.20815,77.086395 c 0,24.268295 -19.67334,43.941635 -43.941632,43.941635 -24.268295,0 -43.941635,-19.67334 -43.941635,-43.941635 0,-6.314528 1.360941,-12.554884 3.990127,-18.29602"
|
||||
transform="translate(314.73535,188.16057)"
|
||||
sodipodi:start="0"
|
||||
sodipodi:end="3.5710428"
|
||||
sodipodi:open="true" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
|
||||
d="m 152.53303,50.82243 10.60661,-7.576144 3.53553,10.606602 0,0"
|
||||
id="path3673"
|
||||
transform="translate(188.30535,204.16057)" />
|
||||
</g>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:40px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
|
||||
x="-261.85617"
|
||||
y="169.59779"
|
||||
id="text3763"
|
||||
transform="scale(-1,1)"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan3765"
|
||||
x="-261.85617"
|
||||
y="169.59779">1</tspan></text>
|
||||
<text
|
||||
id="text3767"
|
||||
y="284.69601"
|
||||
x="-125.6799"
|
||||
style="font-size:40px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
|
||||
xml:space="preserve"
|
||||
transform="scale(-1,1)"><tspan
|
||||
y="284.69601"
|
||||
x="-125.6799"
|
||||
id="tspan3769"
|
||||
sodipodi:role="line">2</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:40px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
|
||||
x="-261.42648"
|
||||
y="399.24741"
|
||||
id="text3771"
|
||||
transform="scale(-1,1)"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan3773"
|
||||
x="-261.42648"
|
||||
y="399.24741">3</tspan></text>
|
||||
<text
|
||||
id="text3775"
|
||||
y="284.43234"
|
||||
x="-401.19751"
|
||||
style="font-size:40px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
|
||||
xml:space="preserve"
|
||||
transform="scale(-1,1)"><tspan
|
||||
y="284.43234"
|
||||
x="-401.19751"
|
||||
id="tspan3777"
|
||||
sodipodi:role="line">4</tspan></text>
|
||||
<g
|
||||
transform="translate(0.72844944,4)"
|
||||
id="g3879"
|
||||
style="stroke-width:5;stroke-miterlimit:4;stroke-dasharray:none">
|
||||
<path
|
||||
sodipodi:open="true"
|
||||
sodipodi:end="3.5710428"
|
||||
sodipodi:start="0"
|
||||
transform="translate(314.73535,188.16057)"
|
||||
d="m 120.20815,77.086395 c 0,24.268295 -19.67334,43.941635 -43.941632,43.941635 -24.268295,0 -43.941635,-19.67334 -43.941635,-43.941635 0,-6.314528 1.360941,-12.554884 3.990127,-18.29602"
|
||||
sodipodi:ry="43.941635"
|
||||
sodipodi:rx="43.941635"
|
||||
sodipodi:cy="77.086395"
|
||||
sodipodi:cx="76.266518"
|
||||
id="path3881"
|
||||
style="fill:none;stroke:#000000;stroke-width:5;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
|
||||
sodipodi:type="arc" />
|
||||
<path
|
||||
transform="translate(188.30535,204.16057)"
|
||||
id="path3883"
|
||||
d="m 152.53303,50.82243 10.60661,-7.576144 3.53553,10.606602 0,0"
|
||||
style="fill:none;stroke:#000000;stroke-width:5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
|
||||
style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
|
||||
d="m 138.92857,74.147895 -2.85714,-5.714285 -5.35714,3.928571"
|
||||
id="path3952" />
|
||||
</g>
|
||||
</g>
|
||||
<g
|
||||
inkscape:label="#g3696"
|
||||
id="quad-X"
|
||||
transform="matrix(0.76637382,-0.64239487,0.64239487,0.76637382,-562.69849,224.32158)">
|
||||
<path
|
||||
transform="matrix(-1,0,0,1,639.78188,-112)"
|
||||
style="fill:none;stroke:#000000;stroke-width:4;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
|
||||
d="m 247.48737,381.85227 282.84272,0"
|
||||
id="path3717" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:4;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
|
||||
d="M 228.28398,133.32975 276.12336,408.0507"
|
||||
id="path3719" />
|
||||
transform="translate(29.913774,-19.106578)"
|
||||
id="g4013">
|
||||
<path
|
||||
transform="translate(256,108)"
|
||||
sodipodi:type="arc"
|
||||
style="opacity:0.87866109;fill:#d1d1d1;fill-opacity:1;stroke:none"
|
||||
id="path3721"
|
||||
sodipodi:cx="225.71428"
|
||||
sodipodi:cy="329.50504"
|
||||
sodipodi:rx="62.857143"
|
||||
sodipodi:ry="62.857143"
|
||||
d="m 288.57142,329.50504 a 62.857143,62.857143 0 1 1 -125.71428,0 62.857143,62.857143 0 1 1 125.71428,0 z"
|
||||
transform="matrix(-1,0,0,1,449.84658,-193.82959)" />
|
||||
<path
|
||||
sodipodi:type="arc"
|
||||
style="opacity:0.87866109;fill:#d1d1d1;fill-opacity:1;stroke:none"
|
||||
id="path3723"
|
||||
sodipodi:cx="225.71428"
|
||||
sodipodi:cy="329.50504"
|
||||
sodipodi:rx="62.857143"
|
||||
sodipodi:ry="62.857143"
|
||||
d="m 288.57142,329.50504 a 62.857143,62.857143 0 1 1 -125.71428,0 62.857143,62.857143 0 1 1 125.71428,0 z"
|
||||
transform="matrix(-1,0,0,1,498.74355,78.144384)" />
|
||||
<path
|
||||
sodipodi:type="arc"
|
||||
style="opacity:0.87866109;fill:#d1d1d1;fill-opacity:1;stroke:none"
|
||||
id="path3725"
|
||||
sodipodi:cx="225.71428"
|
||||
sodipodi:cy="329.50504"
|
||||
sodipodi:rx="62.857143"
|
||||
sodipodi:ry="62.857143"
|
||||
d="m 288.57142,329.50504 c 0,34.71504 -28.1421,62.85714 -62.85714,62.85714 -34.71504,0 -62.85714,-28.1421 -62.85714,-62.85714 0,-34.71505 28.1421,-62.85715 62.85714,-62.85715 34.71504,0 62.85714,28.1421 62.85714,62.85715 z"
|
||||
transform="matrix(-1,0,0,1,339.20668,-59.65276)" />
|
||||
<path
|
||||
sodipodi:type="arc"
|
||||
style="opacity:0.87866109;fill:#d1d1d1;fill-opacity:1;stroke:none"
|
||||
id="path3727"
|
||||
sodipodi:cx="225.71428"
|
||||
sodipodi:cy="329.50504"
|
||||
sodipodi:rx="62.857143"
|
||||
sodipodi:ry="62.857143"
|
||||
d="m 288.57142,329.50504 c 0,34.71504 -28.1421,62.85714 -62.85714,62.85714 -34.71504,0 -62.85714,-28.1421 -62.85714,-62.85714 0,-34.71505 28.1421,-62.85715 62.85714,-62.85715 34.71504,0 62.85714,28.1421 62.85714,62.85715 z"
|
||||
transform="matrix(-1,0,0,1,614.33367,-59.65276)" />
|
||||
style="fill:#a3a3a3;fill-opacity:1;stroke:none"
|
||||
id="path3930"
|
||||
sodipodi:cx="153.03812"
|
||||
sodipodi:cy="75.039597"
|
||||
sodipodi:rx="23.738585"
|
||||
sodipodi:ry="23.738585"
|
||||
d="m 176.7767,75.039597 c 0,13.110458 -10.62813,23.738584 -23.73858,23.738584 -13.11046,0 -23.73859,-10.628126 -23.73859,-23.738584 0,-13.110459 10.62813,-23.738585 23.73859,-23.738585 13.11045,0 23.73858,10.628126 23.73858,23.738585 z" />
|
||||
<text
|
||||
id="text3940"
|
||||
y="190.21933"
|
||||
x="401.85715"
|
||||
style="font-size:40px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
|
||||
xml:space="preserve"><tspan
|
||||
style="font-size:24px"
|
||||
y="190.21933"
|
||||
x="401.85715"
|
||||
id="tspan3942"
|
||||
sodipodi:role="line">3</tspan></text>
|
||||
<g
|
||||
transform="matrix(0.17465766,0.98462922,-0.98462922,0.17465766,420.53389,-295.20368)"
|
||||
id="g3729"
|
||||
style="stroke-width:5;stroke-miterlimit:4;stroke-dasharray:none">
|
||||
transform="translate(256,108)"
|
||||
id="g3954">
|
||||
<path
|
||||
sodipodi:open="true"
|
||||
sodipodi:end="3.5710428"
|
||||
sodipodi:end="3.5351905"
|
||||
sodipodi:start="0"
|
||||
transform="translate(314.73535,188.16057)"
|
||||
d="m 120.20815,77.086395 c 0,24.268295 -19.67334,43.941635 -43.941632,43.941635 -24.268295,0 -43.941635,-19.67334 -43.941635,-43.941635 0,-6.314528 1.360941,-12.554884 3.990127,-18.29602"
|
||||
sodipodi:ry="43.941635"
|
||||
sodipodi:rx="43.941635"
|
||||
sodipodi:cy="77.086395"
|
||||
sodipodi:cx="76.266518"
|
||||
id="path3731"
|
||||
style="fill:none;stroke:#000000;stroke-width:5;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
|
||||
sodipodi:type="arc" />
|
||||
<path
|
||||
transform="translate(188.30535,204.16057)"
|
||||
id="path3733"
|
||||
d="m 152.53303,50.82243 10.60661,-7.576144 3.53553,10.606602 0,0"
|
||||
style="fill:none;stroke:#000000;stroke-width:5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
|
||||
</g>
|
||||
<g
|
||||
style="stroke-width:5;stroke-miterlimit:4;stroke-dasharray:none"
|
||||
id="g3735"
|
||||
transform="matrix(0.17465766,0.98462922,-0.98462922,0.17465766,470.65227,-22.205893)">
|
||||
<path
|
||||
transform="matrix(0.76640028,0,0,0.76640028,35.249661,18.029229)"
|
||||
sodipodi:type="arc"
|
||||
style="fill:none;stroke:#000000;stroke-width:5;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
|
||||
id="path3737"
|
||||
sodipodi:cx="76.266518"
|
||||
sodipodi:cy="77.086395"
|
||||
sodipodi:rx="43.941635"
|
||||
sodipodi:ry="43.941635"
|
||||
d="m 120.20815,77.086395 c 0,24.268295 -19.67334,43.941635 -43.941632,43.941635 -24.268295,0 -43.941635,-19.67334 -43.941635,-43.941635 0,-6.314528 1.360941,-12.554884 3.990127,-18.29602"
|
||||
transform="translate(314.73535,188.16057)"
|
||||
sodipodi:start="0"
|
||||
sodipodi:end="3.5710428"
|
||||
sodipodi:open="true" />
|
||||
style="fill:none;stroke:#000000;stroke-width:2.60960245;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
|
||||
id="path3956"
|
||||
sodipodi:cx="153.03812"
|
||||
sodipodi:cy="75.039597"
|
||||
sodipodi:rx="23.738585"
|
||||
sodipodi:ry="23.738585"
|
||||
d="m 176.7767,75.039597 c 0,13.110458 -10.62813,23.738584 -23.73858,23.738584 -13.11046,0 -23.73859,-10.628126 -23.73859,-23.738584 0,-3.124577 0.61685,-6.218415 1.81517,-9.104071" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
|
||||
d="m 152.53303,50.82243 10.60661,-7.576144 3.53553,10.606602 0,0"
|
||||
id="path3739"
|
||||
transform="translate(188.30535,204.16057)" />
|
||||
</g>
|
||||
<g
|
||||
id="g3759"
|
||||
transform="matrix(-0.99677811,0.08020845,0.08020845,0.99677811,756.35346,-27.446074)">
|
||||
<path
|
||||
sodipodi:open="true"
|
||||
sodipodi:end="3.5710428"
|
||||
sodipodi:start="0"
|
||||
transform="translate(314.73535,188.16057)"
|
||||
d="m 120.20815,77.086395 c 0,24.268295 -19.67334,43.941635 -43.941632,43.941635 -24.268295,0 -43.941635,-19.67334 -43.941635,-43.941635 0,-6.314528 1.360941,-12.554884 3.990127,-18.29602"
|
||||
sodipodi:ry="43.941635"
|
||||
sodipodi:rx="43.941635"
|
||||
sodipodi:cy="77.086395"
|
||||
sodipodi:cx="76.266518"
|
||||
id="path3747"
|
||||
style="fill:none;stroke:#000000;stroke-width:5;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
|
||||
sodipodi:type="arc" />
|
||||
<path
|
||||
transform="translate(188.30535,204.16057)"
|
||||
id="path3749"
|
||||
d="m 152.53303,50.82243 10.60661,-7.576144 3.53553,10.606602 0,0"
|
||||
style="fill:none;stroke:#000000;stroke-width:5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
|
||||
id="path3958"
|
||||
d="m 138.92857,74.147895 -2.85714,-5.714285 -5.35714,3.928571"
|
||||
style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
|
||||
</g>
|
||||
</g>
|
||||
<g
|
||||
transform="translate(3.4442035,34.893422)"
|
||||
id="g4021">
|
||||
<path
|
||||
transform="translate(190,54)"
|
||||
sodipodi:type="arc"
|
||||
style="fill:#a3a3a3;fill-opacity:1;stroke:none"
|
||||
id="path3926"
|
||||
sodipodi:cx="153.03812"
|
||||
sodipodi:cy="75.039597"
|
||||
sodipodi:rx="23.738585"
|
||||
sodipodi:ry="23.738585"
|
||||
d="m 176.7767,75.039597 c 0,13.110458 -10.62813,23.738584 -23.73858,23.738584 -13.11046,0 -23.73859,-10.628126 -23.73859,-23.738584 0,-13.110459 10.62813,-23.738585 23.73859,-23.738585 13.11045,0 23.73858,10.628126 23.73858,23.738585 z" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:40px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
|
||||
x="-484.25562"
|
||||
y="-28.259306"
|
||||
id="text3763-9"
|
||||
transform="matrix(-0.76637382,-0.64239487,-0.64239487,0.76637382,0,0)"><tspan
|
||||
x="335.85715"
|
||||
y="136.21933"
|
||||
id="text3944"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan3765-6"
|
||||
x="-484.25562"
|
||||
y="-28.259306">1</tspan></text>
|
||||
<text
|
||||
transform="matrix(-0.76637382,-0.64239487,-0.64239487,0.76637382,0,0)"
|
||||
id="text3910"
|
||||
y="-25.15958"
|
||||
x="-271.11383"
|
||||
style="font-size:40px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
|
||||
xml:space="preserve"><tspan
|
||||
y="-25.15958"
|
||||
x="-271.11383"
|
||||
id="tspan3912"
|
||||
sodipodi:role="line">2</tspan></text>
|
||||
id="tspan3946"
|
||||
x="335.85715"
|
||||
y="136.21933"
|
||||
style="font-size:24px">4</tspan></text>
|
||||
<path
|
||||
sodipodi:open="true"
|
||||
sodipodi:end="3.5351905"
|
||||
sodipodi:start="0"
|
||||
transform="matrix(0.76640028,0,0,0.76640028,225.82109,72.386372)"
|
||||
sodipodi:type="arc"
|
||||
style="fill:none;stroke:#000000;stroke-width:2.60960245;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
|
||||
id="path3960"
|
||||
sodipodi:cx="153.03812"
|
||||
sodipodi:cy="75.039597"
|
||||
sodipodi:rx="23.738585"
|
||||
sodipodi:ry="23.738585"
|
||||
d="m 176.7767,75.039597 c 0,13.110458 -10.62813,23.738584 -23.73858,23.738584 -13.11046,0 -23.73859,-10.628126 -23.73859,-23.738584 0,-3.124577 0.61685,-6.218415 1.81517,-9.104071" />
|
||||
<path
|
||||
id="path3964"
|
||||
d="m 357.07143,134.50504 4.28571,-3.92857 2.85715,5.35714"
|
||||
style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
|
||||
d="m 357.07143,134.50504 4.28571,-3.92857 2.85715,5.35714"
|
||||
id="path3966" />
|
||||
<path
|
||||
id="path3968"
|
||||
d="m 357.07143,134.50504 4.28571,-3.92857 2.85715,5.35714"
|
||||
style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
|
||||
</g>
|
||||
<g
|
||||
transform="translate(-34.086226,-37.837559)"
|
||||
id="g4006">
|
||||
<path
|
||||
d="m 176.7767,75.039597 c 0,13.110458 -10.62813,23.738584 -23.73858,23.738584 -13.11046,0 -23.73859,-10.628126 -23.73859,-23.738584 0,-13.110459 10.62813,-23.738585 23.73859,-23.738585 13.11045,0 23.73858,10.628126 23.73858,23.738585 z"
|
||||
sodipodi:ry="23.738585"
|
||||
sodipodi:rx="23.738585"
|
||||
sodipodi:cy="75.039597"
|
||||
sodipodi:cx="153.03812"
|
||||
id="path3928"
|
||||
style="fill:#a3a3a3;fill-opacity:1;stroke:none"
|
||||
sodipodi:type="arc"
|
||||
transform="translate(320,54)" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:40px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
|
||||
x="-272.9758"
|
||||
y="148.46133"
|
||||
id="text3914"
|
||||
transform="matrix(-0.76637382,-0.64239487,-0.64239487,0.76637382,0,0)"><tspan
|
||||
x="465.85715"
|
||||
y="138.21933"
|
||||
id="text3936"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan3916"
|
||||
x="-272.9758"
|
||||
y="148.46133">3</tspan></text>
|
||||
<text
|
||||
transform="matrix(-0.76637382,-0.64239487,-0.64239487,0.76637382,0,0)"
|
||||
id="text3918"
|
||||
y="151.59932"
|
||||
x="-483.6925"
|
||||
style="font-size:40px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
|
||||
xml:space="preserve"><tspan
|
||||
y="151.59932"
|
||||
x="-483.6925"
|
||||
id="tspan3920"
|
||||
sodipodi:role="line">4</tspan></text>
|
||||
<g
|
||||
transform="matrix(-0.99677811,0.08020845,0.08020845,0.99677811,482.1726,-26.65301)"
|
||||
id="g3922">
|
||||
<path
|
||||
sodipodi:type="arc"
|
||||
style="fill:none;stroke:#000000;stroke-width:5;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
|
||||
id="path3924"
|
||||
sodipodi:cx="76.266518"
|
||||
sodipodi:cy="77.086395"
|
||||
sodipodi:rx="43.941635"
|
||||
sodipodi:ry="43.941635"
|
||||
d="m 120.20815,77.086395 c 0,24.268295 -19.67334,43.941635 -43.941632,43.941635 -24.268295,0 -43.941635,-19.67334 -43.941635,-43.941635 0,-6.314528 1.360941,-12.554884 3.990127,-18.29602"
|
||||
transform="translate(314.73535,188.16057)"
|
||||
sodipodi:start="0"
|
||||
sodipodi:end="3.5710428"
|
||||
sodipodi:open="true" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
|
||||
d="m 152.53303,50.82243 10.60661,-7.576144 3.53553,10.606602 0,0"
|
||||
id="path3926"
|
||||
transform="translate(188.30535,204.16057)" />
|
||||
</g>
|
||||
id="tspan3938"
|
||||
x="465.85715"
|
||||
y="138.21933"
|
||||
style="font-size:24px">2</tspan></text>
|
||||
<path
|
||||
d="m 176.7767,75.039597 c 0,13.110458 -10.62813,23.738584 -23.73858,23.738584 -13.11046,0 -23.73859,-10.628126 -23.73859,-23.738584 0,-3.124577 0.61685,-6.218415 1.81517,-9.104071"
|
||||
sodipodi:ry="23.738585"
|
||||
sodipodi:rx="23.738585"
|
||||
sodipodi:cy="75.039597"
|
||||
sodipodi:cx="153.03812"
|
||||
id="path3962"
|
||||
style="fill:none;stroke:#000000;stroke-width:2.60960245;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
|
||||
sodipodi:type="arc"
|
||||
transform="matrix(0.76640028,0,0,0.76640028,355.82109,72.386372)"
|
||||
sodipodi:start="0"
|
||||
sodipodi:end="3.5351905"
|
||||
sodipodi:open="true" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
|
||||
d="m 487.07143,134.50504 4.28571,-3.92857 2.85715,5.35714"
|
||||
id="path3970" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
|
Before Width: | Height: | Size: 24 KiB After Width: | Height: | Size: 20 KiB |
@ -30,6 +30,7 @@
|
||||
#include <QGraphicsSceneMouseEvent>
|
||||
#include <QPainter>
|
||||
#include <QStyleOption>
|
||||
#include <QDebug>
|
||||
|
||||
#include "mixercurveline.h"
|
||||
#include "mixercurvepoint.h"
|
||||
@ -111,9 +112,11 @@ QVariant Node::itemChange(GraphicsItemChange change, const QVariant &value)
|
||||
// Stay inside graph
|
||||
if (newPos.y() < 0)
|
||||
newPos.setY(0);
|
||||
if (newPos.y() > graph->height())
|
||||
newPos.setY(graph->height());
|
||||
return newPos;
|
||||
double h = graph->sceneRect().height();
|
||||
//qDebug() << h << " - " << newPos.y();
|
||||
if (newPos.y() > h)
|
||||
newPos.setY(h);
|
||||
return newPos;
|
||||
}
|
||||
case ItemPositionHasChanged:
|
||||
foreach (Edge *edge, edgeList)
|
||||
|
Loading…
x
Reference in New Issue
Block a user