diff --git a/artwork/Dials/README.txt b/artwork/Dials/README.txt index 1e4e6be4a..54d0f7c90 100644 --- a/artwork/Dials/README.txt +++ b/artwork/Dials/README.txt @@ -12,3 +12,6 @@ extracts directory: TODO: ideally, extracting the layers from the master SVG should be automated, but for now we are doing it manually. +defaultset directory: + + This directory contains dials which are ready for use in the GCS. \ No newline at end of file diff --git a/artwork/Dials/defaultset/attitude.svg b/artwork/Dials/defaultset/attitude.svg new file mode 100644 index 000000000..6417926f7 --- /dev/null +++ b/artwork/Dials/defaultset/attitude.svg @@ -0,0 +1,509 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + Edouard Lafargue + + + + + + + + + + + + + + + + + + + + 5 + 15 + 5 + 15 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/artwork/Dials/simpledial-vertical.svg b/artwork/Dials/simpledial-vertical.svg new file mode 100644 index 000000000..f7c09a326 --- /dev/null +++ b/artwork/Dials/simpledial-vertical.svg @@ -0,0 +1,397 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + Edouard Lafargue + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ground/src/plugins/airspeed/airspeedgadget.cpp b/ground/src/plugins/airspeed/airspeedgadget.cpp index 23e1e3451..d9e6b9476 100644 --- a/ground/src/plugins/airspeed/airspeedgadget.cpp +++ b/ground/src/plugins/airspeed/airspeedgadget.cpp @@ -49,7 +49,8 @@ void AirspeedGadget::loadConfiguration(IUAVGadgetConfiguration* config) { AirspeedGadgetConfiguration *m = qobject_cast(config); m_widget->setDialFile(m->dialFile(), m->dialBackground(), m->dialForeground(), m->dialNeedle1(), - m->dialNeedle2(),m->getN1Move(), m->getN2Move()); + m->dialNeedle2(),m->dialNeedle3(),m->getN1Move(), m->getN2Move(), + m->getN3Move()); m_widget->setN1Min(m->getN1Min()); m_widget->setN1Max(m->getN1Max()); @@ -57,6 +58,11 @@ void AirspeedGadget::loadConfiguration(IUAVGadgetConfiguration* config) m_widget->setN2Min(m->getN2Min()); m_widget->setN2Max(m->getN2Max()); m_widget->setN2Factor(m->getN2Factor()); + m_widget->setN3Min(m->getN3Min()); + m_widget->setN3Max(m->getN3Max()); + m_widget->setN3Factor(m->getN3Factor()); m_widget->connectNeedles(m->getN1DataObject(),m->getN1ObjField(), - m->getN2DataObject(),m->getN2ObjField()); + m->getN2DataObject(),m->getN2ObjField(), + m->getN3DataObject(),m->getN3ObjField() + ); } diff --git a/ground/src/plugins/airspeed/airspeedgadgetconfiguration.cpp b/ground/src/plugins/airspeed/airspeedgadgetconfiguration.cpp index fefefc360..32870767a 100644 --- a/ground/src/plugins/airspeed/airspeedgadgetconfiguration.cpp +++ b/ground/src/plugins/airspeed/airspeedgadgetconfiguration.cpp @@ -39,14 +39,19 @@ AirspeedGadgetConfiguration::AirspeedGadgetConfiguration(QString classId, const dialForegroundID("foreground"), dialNeedleID1("needle"), dialNeedleID2("needle2"), + dialNeedleID3("needle3"), needle1MinValue(0), needle1MaxValue(100), needle2MinValue(0), needle2MaxValue(100), + needle3MinValue(0), + needle3MaxValue(100), needle1Factor(1), needle2Factor(1), + needle3Factor(1), needle1Move("Rotate"), - needle2Move("Rotate") + needle2Move("Rotate"), + needle3Move("Rotate") { //if a saved configuration exists load it if (state.count() > 0) { @@ -58,18 +63,25 @@ AirspeedGadgetConfiguration::AirspeedGadgetConfiguration(QString classId, const stream >> dialForegroundID; stream >> dialNeedleID1; stream >> dialNeedleID2; + stream >> dialNeedleID3; stream >> needle1MinValue; stream >> needle1MaxValue; stream >> needle2MinValue; stream >> needle2MaxValue; + stream >> needle3MinValue; + stream >> needle3MaxValue; stream >> needle1DataObject; stream >> needle1ObjectField; stream >> needle2DataObject; stream >> needle2ObjectField; + stream >> needle3DataObject; + stream >> needle3ObjectField; stream >> needle1Factor; stream >> needle2Factor; + stream >> needle3Factor; stream >> needle1Move; stream >> needle2Move; + stream >> needle3Move; } } /** @@ -95,18 +107,25 @@ QByteArray AirspeedGadgetConfiguration::saveState() const stream << dialForegroundID; stream << dialNeedleID1; stream << dialNeedleID2; + stream << dialNeedleID3; stream << needle1MinValue; stream << needle1MaxValue; stream << needle2MinValue; stream << needle2MaxValue; + stream << needle3MinValue; + stream << needle3MaxValue; stream << needle1DataObject; stream << needle1ObjectField; stream << needle2DataObject; stream << needle2ObjectField; + stream << needle3DataObject; + stream << needle3ObjectField; stream << needle1Factor; stream << needle2Factor; + stream << needle3Factor; stream << needle1Move; stream << needle2Move; + stream << needle3Move; return bytes; } diff --git a/ground/src/plugins/airspeed/airspeedgadgetconfiguration.h b/ground/src/plugins/airspeed/airspeedgadgetconfiguration.h index dbb9f57c2..080b82953 100644 --- a/ground/src/plugins/airspeed/airspeedgadgetconfiguration.h +++ b/ground/src/plugins/airspeed/airspeedgadgetconfiguration.h @@ -47,18 +47,25 @@ public: void setDialForegroundID(QString elementID) { dialForegroundID = elementID;} void setDialNeedleID1(QString elementID) { dialNeedleID1 = elementID;} void setDialNeedleID2(QString elementID) { dialNeedleID2 = elementID;} + void setDialNeedleID3(QString elementID) { dialNeedleID3 = elementID;} void setN1Min(double val) { needle1MinValue = val;} void setN2Min(double val) { needle2MinValue = val;} + void setN3Min(double val) { needle3MinValue = val;} void setN1Max(double val) { needle1MaxValue = val;} void setN2Max(double val) { needle2MaxValue = val;} + void setN3Max(double val) { needle3MaxValue = val;} void setN1Factor(double val) { needle1Factor = val;} void setN2Factor(double val) { needle2Factor = val;} + void setN3Factor(double val) { needle3Factor = val;} void setN1DataObject(QString text) {needle1DataObject = text; } void setN2DataObject(QString text){ needle2DataObject = text; } + void setN3DataObject(QString text){ needle3DataObject = text; } void setN1ObjField(QString text) { needle1ObjectField = text; } void setN2ObjField(QString text) { needle2ObjectField = text; } + void setN3ObjField(QString text) { needle3ObjectField = text; } void setN1Move( QString move) { needle1Move = move; } void setN2Move( QString move) { needle2Move = move; } + void setN3Move( QString move) { needle3Move = move; } //get dial configuration functions QString dialFile() {return m_defaultDial;} @@ -66,18 +73,25 @@ public: QString dialForeground() {return dialForegroundID;} QString dialNeedle1() {return dialNeedleID1;} QString dialNeedle2() {return dialNeedleID2;} + QString dialNeedle3() {return dialNeedleID3;} double getN1Min() { return needle1MinValue;} double getN2Min() { return needle2MinValue;} + double getN3Min() { return needle3MinValue;} double getN1Max() { return needle1MaxValue;} double getN2Max() { return needle2MaxValue;} + double getN3Max() { return needle3MaxValue;} double getN1Factor() { return needle1Factor;} double getN2Factor() { return needle2Factor;} + double getN3Factor() { return needle3Factor;} QString getN1DataObject() { return needle1DataObject; } QString getN2DataObject() { return needle2DataObject; } + QString getN3DataObject() { return needle3DataObject; } QString getN1ObjField() { return needle1ObjectField; } QString getN2ObjField() { return needle2ObjectField; } + QString getN3ObjField() { return needle3ObjectField; } QString getN1Move() { return needle1Move; } QString getN2Move() { return needle2Move; } + QString getN3Move() { return needle3Move; } QByteArray saveState() const; IUAVGadgetConfiguration *clone(); @@ -88,23 +102,30 @@ private: QString dialForegroundID; // ... of the foreground QString dialNeedleID1; // ... and the first needle QString dialNeedleID2; // ... and the second + QString dialNeedleID3; // ... and the third // Note: MinValue not used at the moment! double needle1MinValue; // Value corresponding to a 0 degree angle; double needle1MaxValue; // Value corresponding to a 360 degree angle; double needle2MinValue; double needle2MaxValue; + double needle3MinValue; + double needle3MaxValue; double needle1Factor; double needle2Factor; + double needle3Factor; QString needle1DataObject; QString needle1ObjectField; QString needle2DataObject; QString needle2ObjectField; + QString needle3DataObject; + QString needle3ObjectField; // How the two dials move: QString needle1Move; QString needle2Move; + QString needle3Move; }; #endif // AIRSPEEDGADGETCONFIGURATION_H diff --git a/ground/src/plugins/airspeed/airspeedgadgetoptionspage.cpp b/ground/src/plugins/airspeed/airspeedgadgetoptionspage.cpp index 19e7d1da8..0cf46b887 100644 --- a/ground/src/plugins/airspeed/airspeedgadgetoptionspage.cpp +++ b/ground/src/plugins/airspeed/airspeedgadgetoptionspage.cpp @@ -61,6 +61,7 @@ QWidget *AirspeedGadgetOptionsPage::createPage(QWidget *parent) foreach (UAVDataObject* obj, list) { options_page->uavObject1->addItem(obj->getName()); options_page->uavObject2->addItem(obj->getName()); + options_page->uavObject3->addItem(obj->getName()); } } @@ -73,20 +74,29 @@ QWidget *AirspeedGadgetOptionsPage::createPage(QWidget *parent) options_page->moveNeedle2->addItem("Horizontal"); options_page->moveNeedle2->addItem("Vertical"); + options_page->moveNeedle3->addItem("Rotate"); + options_page->moveNeedle3->addItem("Horizontal"); + options_page->moveNeedle3->addItem("Vertical"); + // Restore the contents from the settings: options_page->svgSourceFile->setText(m_config->dialFile()); options_page->backgroundID->setText(m_config->dialBackground()); options_page->foregroundID->setText(m_config->dialForeground()); options_page->needle1ID->setText(m_config->dialNeedle1()); options_page->needle2ID->setText(m_config->dialNeedle2()); + options_page->needle3ID->setText(m_config->dialNeedle3()); options_page->needle1Min->setValue(m_config->getN1Min()); options_page->needle1Max->setValue(m_config->getN1Max()); options_page->needle2Min->setValue(m_config->getN2Min()); options_page->needle2Max->setValue(m_config->getN2Max()); + options_page->needle3Min->setValue(m_config->getN3Min()); + options_page->needle3Max->setValue(m_config->getN3Max()); options_page->factor1->setValue(m_config->getN1Factor()); options_page->factor2->setValue(m_config->getN2Factor()); + options_page->factor3->setValue(m_config->getN3Factor()); options_page->moveNeedle1->setCurrentIndex(options_page->moveNeedle1->findText(m_config->getN1Move())); options_page->moveNeedle2->setCurrentIndex(options_page->moveNeedle2->findText(m_config->getN2Move())); + options_page->moveNeedle3->setCurrentIndex(options_page->moveNeedle3->findText(m_config->getN3Move())); //select saved UAV Object field values if(options_page->uavObject1->findText(m_config->getN1DataObject())!=-1){ @@ -103,6 +113,7 @@ QWidget *AirspeedGadgetOptionsPage::createPage(QWidget *parent) } } connect(options_page->uavObject1, SIGNAL(currentIndexChanged(QString)), this, SLOT(on_uavObject1_currentIndexChanged(QString))); + if(options_page->uavObject2->findText(m_config->getN2DataObject())!=-1){ options_page->uavObject2->setCurrentIndex(options_page->uavObject2->findText(m_config->getN2DataObject())); // Now load the object field values: @@ -116,6 +127,21 @@ QWidget *AirspeedGadgetOptionsPage::createPage(QWidget *parent) } } connect(options_page->uavObject2, SIGNAL(currentIndexChanged(QString)), this, SLOT(on_uavObject2_currentIndexChanged(QString))); + + if(options_page->uavObject3->findText(m_config->getN3DataObject())!=-1){ + options_page->uavObject3->setCurrentIndex(options_page->uavObject3->findText(m_config->getN3DataObject())); + // Now load the object field values: + UAVDataObject* obj = dynamic_cast( objManager->getObject(m_config->getN3DataObject())); + if (obj != NULL ) { + QList fieldList = obj->getFields(); + foreach (UAVObjectField* field, fieldList) { + options_page->objectField3->addItem(field->getName()); + } + options_page->objectField3->setCurrentIndex(options_page->objectField3->findText(m_config->getN3ObjField())); + } + } + connect(options_page->uavObject3, SIGNAL(currentIndexChanged(QString)), this, SLOT(on_uavObject3_currentIndexChanged(QString))); + connect(options_page->loadFile, SIGNAL(clicked()), this, SLOT(on_loadFile_clicked())); return optionsPageWidget; } @@ -133,18 +159,25 @@ void AirspeedGadgetOptionsPage::apply() m_config->setDialForegroundID(options_page->foregroundID->text()); m_config->setDialNeedleID1(options_page->needle1ID->text()); m_config->setDialNeedleID2(options_page->needle2ID->text()); + m_config->setDialNeedleID3(options_page->needle3ID->text()); m_config->setN1Min(options_page->needle1Min->value()); m_config->setN1Max(options_page->needle1Max->value()); m_config->setN1Factor(options_page->factor1->value()); m_config->setN2Min(options_page->needle2Min->value()); m_config->setN2Max(options_page->needle2Max->value()); m_config->setN2Factor(options_page->factor2->value()); + m_config->setN3Min(options_page->needle3Min->value()); + m_config->setN3Max(options_page->needle3Max->value()); + m_config->setN3Factor(options_page->factor3->value()); m_config->setN1DataObject(options_page->uavObject1->currentText()); m_config->setN2DataObject(options_page->uavObject2->currentText()); + m_config->setN3DataObject(options_page->uavObject3->currentText()); m_config->setN1ObjField(options_page->objectField1->currentText()); m_config->setN2ObjField(options_page->objectField2->currentText()); + m_config->setN3ObjField(options_page->objectField3->currentText()); m_config->setN1Move(options_page->moveNeedle1->currentText()); m_config->setN2Move(options_page->moveNeedle2->currentText()); + m_config->setN3Move(options_page->moveNeedle3->currentText()); } /* @@ -164,7 +197,7 @@ void AirspeedGadgetOptionsPage::on_uavObject1_currentIndexChanged(QString val) { /* Fills in the field2 combo box when value is changed in the - object1 field + object2 field */ void AirspeedGadgetOptionsPage::on_uavObject2_currentIndexChanged(QString val) { options_page->objectField2->clear(); @@ -177,6 +210,21 @@ void AirspeedGadgetOptionsPage::on_uavObject2_currentIndexChanged(QString val) { } } +/* + Fills in the field3 combo box when value is changed in the + object3 field +*/ +void AirspeedGadgetOptionsPage::on_uavObject3_currentIndexChanged(QString val) { + options_page->objectField3->clear(); + ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance(); + UAVObjectManager *objManager = pm->getObject(); + UAVDataObject* obj = dynamic_cast( objManager->getObject(val) ); + QList fieldList = obj->getFields(); + foreach (UAVObjectField* field, fieldList) { + options_page->objectField3->addItem(field->getName()); + } +} + /* Opens an open file dialog. diff --git a/ground/src/plugins/airspeed/airspeedgadgetoptionspage.h b/ground/src/plugins/airspeed/airspeedgadgetoptionspage.h index a91805fa4..4872e5eeb 100644 --- a/ground/src/plugins/airspeed/airspeedgadgetoptionspage.h +++ b/ground/src/plugins/airspeed/airspeedgadgetoptionspage.h @@ -63,6 +63,7 @@ private slots: void on_loadFile_clicked(); void on_uavObject1_currentIndexChanged(QString val); void on_uavObject2_currentIndexChanged(QString val); + void on_uavObject3_currentIndexChanged(QString val); }; #endif // AIRSPEEDGADGETOPTIONSPAGE_H diff --git a/ground/src/plugins/airspeed/airspeedgadgetoptionspage.ui b/ground/src/plugins/airspeed/airspeedgadgetoptionspage.ui index 840e59e2b..dd37fac11 100644 --- a/ground/src/plugins/airspeed/airspeedgadgetoptionspage.ui +++ b/ground/src/plugins/airspeed/airspeedgadgetoptionspage.ui @@ -7,7 +7,7 @@ 0 0 487 - 326 + 346 @@ -24,11 +24,11 @@ -1 -1 - 481 - 354 + 504 + 331 - + QLayout::SetMinimumSize @@ -106,414 +106,647 @@ - - - Qt::Horizontal + + + 2 + + + Indicator 1 + + + + + 0 + 10 + 471 + 110 + + + + + 4 + + + 0 + + + 4 + + + + + + + Indicator 1 + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Movement: + + + + + + + + + + ID: + + + + + + + + 0 + 0 + + + + + 50 + 0 + + + + + 16777215 + 16777215 + + + + + + + + + + 10 + + + + + Min: + + + + + + + + 0 + 0 + + + + 3 + + + -100000.000000000000000 + + + 100000.000000000000000 + + + + + + + Max: + + + + + + + + 0 + 0 + + + + 3 + + + -100000.000000000000000 + + + 100000.000000000000000 + + + + + + + Factor: + + + + + + + + 0 + 0 + + + + -100000.000000000000000 + + + 100000.000000000000000 + + + + + + + + + 10 + + + + + DataObject + + + + + + + + 0 + 0 + + + + + + + + ObjectField + + + + + + + + 0 + 0 + + + + + + + + + + Qt::Horizontal + + + + + + + + + Indicator 2 + + + + + 0 + 10 + 471 + 116 + + + + + 0 + + + 4 + + + + + + + Indicator 2 + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Movement: + + + + + + + + + + ID: + + + + + + + + 0 + 0 + + + + + + + + + + 10 + + + + + Min: + + + + + + + + 0 + 0 + + + + 3 + + + -10000.000000000000000 + + + 100000.000000000000000 + + + + + + + Max: + + + + + + + + 0 + 0 + + + + 3 + + + -100000.000000000000000 + + + 100000.000000000000000 + + + + + + + Factor: + + + + + + + + 0 + 0 + + + + -100000.000000000000000 + + + 100000.000000000000000 + + + + + + + + + 10 + + + + + DataObject + + + + + + + + 0 + 0 + + + + + + + + ObjectField + + + + + + + + 0 + 0 + + + + + + + + + + Qt::Horizontal + + + + + + + + + Indicator 3 + + + + + 0 + 10 + 471 + 116 + + + + + 0 + + + 4 + + + + + + + Indicator 3 + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Movement: + + + + + + + + + + ID: + + + + + + + + 0 + 0 + + + + + + + + + + 10 + + + + + Min: + + + + + + + + 0 + 0 + + + + 3 + + + -10000.000000000000000 + + + 100000.000000000000000 + + + + + + + Max: + + + + + + + + 0 + 0 + + + + 3 + + + -100000.000000000000000 + + + 100000.000000000000000 + + + + + + + Factor: + + + + + + + + 0 + 0 + + + + -100000.000000000000000 + + + 100000.000000000000000 + + + + + + + + + 10 + + + + + DataObject + + + + + + + + 0 + 0 + + + + + + + + ObjectField + + + + + + + + 0 + 0 + + + + + + + + + + Qt::Horizontal + + + + + + - - - - 4 - - - 0 - - - 10 - - - - - - - Indicator 1 - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - Movement: - - - - - - - - - - ID: - - - - - - - - 0 - 0 - - - - - 50 - 0 - - - - - 16777215 - 16777215 - - - - - - - - - - 10 - - - - - Min: - - - - - - - - 0 - 0 - - - - 3 - - - -100000.000000000000000 - - - 100000.000000000000000 - - - - - - - Max: - - - - - - - - 0 - 0 - - - - 3 - - - -100000.000000000000000 - - - 100000.000000000000000 - - - - - - - Factor: - - - - - - - - 0 - 0 - - - - -100000.000000000000000 - - - 100000.000000000000000 - - - - - - - - - 10 - - - - - DataObject - - - - - - - - 0 - 0 - - - - - - - - ObjectField - - - - - - - - 0 - 0 - - - - - - - - - - Qt::Horizontal - - - - - - - - - 0 - - - 10 - - - - - - - Indicator 2 - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - Movement: - - - - - - - - - - ID: - - - - - - - - 0 - 0 - - - - - - - - - - 10 - - - - - Min: - - - - - - - - 0 - 0 - - - - 3 - - - -10000.000000000000000 - - - 100000.000000000000000 - - - - - - - Max: - - - - - - - - 0 - 0 - - - - 3 - - - -100000.000000000000000 - - - 100000.000000000000000 - - - - - - - Factor: - - - - - - - - 0 - 0 - - - - -100000.000000000000000 - - - 100000.000000000000000 - - - - - - - - - 10 - - - - - DataObject - - - - - - - - 0 - 0 - - - - - - - - ObjectField - - - - - - - - 0 - 0 - - - - - - - - - - Qt::Horizontal - - - - - Qt::Vertical + + QSizePolicy::Minimum + 20 @@ -522,6 +755,13 @@ + + + + Qt::Horizontal + + + diff --git a/ground/src/plugins/airspeed/airspeedgadgetwidget.cpp b/ground/src/plugins/airspeed/airspeedgadgetwidget.cpp index 0626bdb5a..5cc60ec58 100644 --- a/ground/src/plugins/airspeed/airspeedgadgetwidget.cpp +++ b/ground/src/plugins/airspeed/airspeedgadgetwidget.cpp @@ -28,31 +28,35 @@ #include "airspeedgadgetwidget.h" #include #include -#include "math.h" AirspeedGadgetWidget::AirspeedGadgetWidget(QWidget *parent) : QGraphicsView(parent) { + // TODO: create a proper "needle" object instead of hardcoding all this + // which is ugly (but easy). + setMinimumSize(64,64); setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding); setScene(new QGraphicsScene(this)); + m_renderer = new QSvgRenderer(); m_background = new QGraphicsSvgItem(); m_foreground = new QGraphicsSvgItem(); m_needle1 = new QGraphicsSvgItem(); m_needle2 = new QGraphicsSvgItem(); + m_needle3 = new QGraphicsSvgItem(); paint(); needle1Target = 0; needle2Target = 0; + needle3Target = 0; needle1Value = 0; needle2Value = 0; + needle3Value = 0; obj1 = NULL; obj2 = NULL; - - rotateN1 = horizN1 = vertN1 = false; - rotateN2 = horizN2 = vertN2 = false; + obj3 = NULL; // This timer mechanism makes needles rotate smoothly connect(&dialTimer, SIGNAL(timeout()), this, SLOT(rotateNeedles())); @@ -68,15 +72,18 @@ AirspeedGadgetWidget::~AirspeedGadgetWidget() /*! \brief Connects the widget to the relevant UAVObjects */ -void AirspeedGadgetWidget::connectNeedles(QString object1, QString nfield1, QString object2, QString nfield2 ) { +void AirspeedGadgetWidget::connectNeedles(QString object1, QString nfield1, + QString object2, QString nfield2, + QString object3, QString nfield3) { if (obj1 != NULL) disconnect(obj1,SIGNAL(objectUpdated(UAVObject*)),this,SLOT(updateNeedle1(UAVObject*))); if (obj2 != NULL) disconnect(obj2,SIGNAL(objectUpdated(UAVObject*)),this,SLOT(updateNeedle2(UAVObject*))); + if (obj3 != NULL) + disconnect(obj3,SIGNAL(objectUpdated(UAVObject*)),this,SLOT(updateNeedle3(UAVObject*))); + ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance(); UAVObjectManager *objManager = pm->getObject(); - std::cout << "Connect needles - " << object1.toStdString() << "-"<< nfield1.toStdString() << " - " << - object2.toStdString() << "-" << nfield2.toStdString() << std::endl; // Check validity of arguments first, reject empty args and unknown fields. if (!(object1.isEmpty() || nfield1.isEmpty())) { @@ -101,6 +108,18 @@ void AirspeedGadgetWidget::connectNeedles(QString object1, QString nfield1, QStr std::cout << "Error: Object is unknown (" << object2.toStdString() << ")." << std::endl; } } + + // And do the same for the third needle. + if (!(object3.isEmpty() || nfield3.isEmpty())) { + obj3 = dynamic_cast( objManager->getObject(object3) ); + if (obj3 != NULL ) { + std::cout << "Connected Object 3 (" << object3.toStdString() << ")." << std::endl; + connect(obj3, SIGNAL(objectUpdated(UAVObject*)), this, SLOT(updateNeedle3(UAVObject*))); + field3 = nfield3; + } else { + std::cout << "Error: Object is unknown (" << object3.toStdString() << ")." << std::endl; + } + } } /*! @@ -114,7 +133,6 @@ void AirspeedGadgetWidget::updateNeedle1(UAVObject *object1) { } else { std::cout << "Wrong field, maybe an issue with object disconnection ?" << std::endl; } - std::cout << "Update Needle 1 with value of field " << field1.toStdString() << std::endl; } /*! @@ -129,8 +147,24 @@ void AirspeedGadgetWidget::updateNeedle2(UAVObject *object2) { } } +/*! + \brief Called by the UAVObject which got updated + */ +void AirspeedGadgetWidget::updateNeedle3(UAVObject *object3) { + UAVObjectField* field = object3->getField(field3); + if (field) { + setNeedle3(field->getDouble()); + } else { + std::cout << "Wrong field, maybe an issue with object disconnection ?" << std::endl; + } +} + +/* + Initializes the dial file, and does all the one-time calculations for + display later. + */ void AirspeedGadgetWidget::setDialFile(QString dfn, QString bg, QString fg, QString n1, QString n2, - QString n1Move, QString n2Move) + QString n3, QString n1Move, QString n2Move, QString n3Move) { if (QFile::exists(dfn)) { @@ -139,25 +173,28 @@ void AirspeedGadgetWidget::setDialFile(QString dfn, QString bg, QString fg, QStr { fgenabled = false; n2enabled = false; + n3enabled = false; QGraphicsScene *l_scene = scene(); + l_scene->removeItem(m_foreground); + l_scene->removeItem(m_background); + l_scene->removeItem(m_needle1); + l_scene->removeItem(m_needle2); + l_scene->removeItem(m_needle3); + // We assume the scene contains at least the background + // and needle1 m_background->setSharedRenderer(m_renderer); m_background->setElementId(bg); + l_scene->addItem(m_background); + m_needle1->setSharedRenderer(m_renderer); m_needle1->setElementId(n1); + l_scene->addItem(m_needle1); - if (m_renderer->elementExists(fg)) { - m_foreground->setSharedRenderer(m_renderer); - m_foreground->setElementId(fg); - if (!l_scene->items().contains(m_foreground)) - l_scene->addItem(m_foreground); - fgenabled = true; - } else { - if (l_scene->items().contains(m_foreground)) - l_scene->removeItem(m_foreground); - fgenabled = false; - } + // The dial gadget allows Needle1 and Needle2 to be + // the same element, for combined movement. Needle3 + // is always independent. if (n1 == n2) { m_needle2 = m_needle1; n2enabled = true; @@ -165,15 +202,35 @@ void AirspeedGadgetWidget::setDialFile(QString dfn, QString bg, QString fg, QStr if (m_renderer->elementExists(n2)) { m_needle2->setSharedRenderer(m_renderer); m_needle2->setElementId(n2); - if (!l_scene->items().contains(m_needle2)) - l_scene->addItem(m_needle2); + l_scene->addItem(m_needle2); n2enabled = true; - } else { - if (l_scene->items().contains(m_needle2)) - l_scene->removeItem(m_needle2); - n2enabled = false; + } } - } + + if (m_renderer->elementExists(n3)) { + m_needle3->setSharedRenderer(m_renderer); + m_needle3->setElementId(n3); + l_scene->addItem(m_needle3); + n3enabled = true; + } + + if (m_renderer->elementExists(fg)) { + m_foreground->setSharedRenderer(m_renderer); + m_foreground->setElementId(fg); + l_scene->addItem(m_foreground); + fgenabled = true; + } + + rotateN1 = false; + horizN1 = false; + vertN1 = false; + rotateN2 = false; + horizN2 = false; + vertN2 = false; + rotateN3 = false; + horizN3 = false; + vertN3 = false; + // Now setup the rotation/translation settings: // this is UGLY UGLY UGLY, sorry... @@ -193,17 +250,37 @@ void AirspeedGadgetWidget::setDialFile(QString dfn, QString bg, QString fg, QStr vertN2 = true; } - // std::cout<<"Dial file loaded ("<< dfn.toStdString() << ")" << std::endl; - l_scene->setSceneRect(m_background->boundingRect()); + if (n3Move.contains("Rotate")) { + rotateN3 = true; + } else if (n3Move.contains("Horizontal")) { + horizN3 = true; + } else if (n3Move.contains("Vertical")) { + vertN3 = true; + } - // Initialize the center for all transforms of the dials to the + l_scene->setSceneRect(m_background->boundingRect()); + // Now Initialize the center for all transforms of the dial needles to the // center of the background: - QRectF rect1 = m_background->boundingRect(); - QPointF tr1 = m_background->mapToScene(rect1.width()/2,rect1.height()/2); - QPointF tr = m_needle1->mapFromScene(tr1); - m_needle1->setTransformOriginPoint(tr.x(),tr.y()); - tr = m_needle2->mapFromScene(tr1); - m_needle2->setTransformOriginPoint(tr.x(),tr.y()); + // - Move the center of the needle to the center of the background. + QRectF rectB = m_background->boundingRect(); + QRectF rectN = m_needle1->boundingRect(); + m_needle1->setPos(rectB.width()/2-rectN.width()/2,rectB.height()/2-rectN.height()/2); + // - Put the transform origin point of the needle at its center. + m_needle1->setTransformOriginPoint(rectN.width()/2,rectN.height()/2); + if ((n1 != n2) && n2enabled) { + // Only do it for needle1 if it is not the same as n2 + rectN = m_needle2->boundingRect(); + m_needle2->setPos(rectB.width()/2-rectN.width()/2,rectB.height()/2-rectN.height()/2); + m_needle2->setTransformOriginPoint(rectN.width()/2,rectN.height()/2); + } + if (n3enabled) { + rectN = m_needle3->boundingRect(); + m_needle3->setPos(rectB.width()/2-rectN.width()/2,rectB.height()/2-rectN.height()/2); + m_needle3->setTransformOriginPoint(rectN.width()/2,rectN.height()/2); + } + + // Last: clip the display region to the rectangle of the background + // TODO } } else @@ -217,6 +294,7 @@ void AirspeedGadgetWidget::paint() l_scene->addItem(m_background); l_scene->addItem(m_needle1); l_scene->addItem(m_needle2); + l_scene->addItem(m_needle3); l_scene->addItem(m_foreground); l_scene->setSceneRect(m_background->boundingRect()); update(); @@ -266,6 +344,18 @@ void AirspeedGadgetWidget::setNeedle2(double value) { } } +void AirspeedGadgetWidget::setNeedle3(double value) { + if (rotateN3) { + needle3Target = 360*value*n3Factor/(n3MaxValue-n3MinValue); + } + if (horizN3) { + needle3Target = value*n3Factor/(n3MaxValue-n3MinValue); + } + if (vertN3) { + needle3Target = value*n3Factor/(n3MaxValue-n3MinValue); + } +} + // Take an input value and rotate the dial accordingly // Rotation is smooth, starts fast and slows down when // approaching the target. @@ -275,6 +365,9 @@ void AirspeedGadgetWidget::setNeedle2(double value) { // to the same element. void AirspeedGadgetWidget::rotateNeedles() { + // TODO: watch out of potential drift of needles due to + // rounding errors. Should implement a way to set the value + // exactly to the target once it falls below the threshold. if ((abs((needle2Value-needle2Target)*10) > 5) && n2enabled) { double needle2Diff; needle2Diff =(needle2Target - needle2Value)/5; @@ -293,7 +386,7 @@ void AirspeedGadgetWidget::rotateNeedles() // the transform origin point the opposite way // so that it keeps rotating from the same point. // (this is only useful if needle1 and needle2 are the - // same object, for combined movement. + // same object, for combined movement such as attitude indicator). QPointF oop = m_needle2->transformOriginPoint(); m_needle2->setTransformOriginPoint(oop.x()-opd.x(),oop.y()-opd.y()); } @@ -320,6 +413,25 @@ void AirspeedGadgetWidget::rotateNeedles() needle1Value += needle1Diff; } + if ((abs((needle3Value-needle3Target)*10) > 5)) { + double needle3Diff; + needle3Diff = (needle3Target - needle3Value)/5; + if (rotateN3) { + m_needle3->setRotation(m_needle3->rotation()+needle3Diff); + } else { + QPointF opd = QPointF(0,0); + if (horizN3) { + opd = QPointF(needle3Diff,0); + } + if (vertN3) { + opd = QPointF(0,needle3Diff); + } + m_needle3->setTransform(QTransform::fromTranslate(opd.x(),opd.y()), true); + QPointF oop = m_needle3->transformOriginPoint(); + m_needle3->setTransformOriginPoint((oop.x()-opd.x()),(oop.y()-opd.y())); + } + needle3Value += needle3Diff; + } + update(); } - diff --git a/ground/src/plugins/airspeed/airspeedgadgetwidget.h b/ground/src/plugins/airspeed/airspeedgadgetwidget.h index c91ef98be..e7a1f6e91 100644 --- a/ground/src/plugins/airspeed/airspeedgadgetwidget.h +++ b/ground/src/plugins/airspeed/airspeedgadgetwidget.h @@ -46,26 +46,32 @@ class AirspeedGadgetWidget : public QGraphicsView public: AirspeedGadgetWidget(QWidget *parent = 0); ~AirspeedGadgetWidget(); - void setDialFile(QString dfn, QString bg, QString fg, QString n1, QString n2, QString n1Move, - QString n2Move); + void setDialFile(QString dfn, QString bg, QString fg, QString n1, QString n2, QString n3, + QString n1Move, QString n2Move, QString n3Move); void paint(); // setNeedle1 and setNeedle2 use a timer to simulate // needle inertia void setNeedle1(double value); void setNeedle2(double value); + void setNeedle3(double value); void setN1Min(double value) {n1MinValue = value;} void setN1Max(double value) {n1MaxValue = value;} void setN1Factor(double value) {n1Factor = value;} void setN2Min(double value) {n2MinValue = value;} void setN2Max(double value) {n2MaxValue = value;} void setN2Factor(double value) {n2Factor = value;} + void setN3Min(double value) {n3MinValue = value;} + void setN3Max(double value) {n3MaxValue = value;} + void setN3Factor(double value) {n3Factor = value;} // Sets up needle/UAVObject connections: void connectNeedles(QString object1, QString field1, - QString object2, QString field2); + QString object2, QString field2, + QString object3, QString field3); public slots: void updateNeedle1(UAVObject *object1); // Called by the UAVObject void updateNeedle2(UAVObject *object2); // Called by the UAVObject + void updateNeedle3(UAVObject *object3); // Called by the UAVObject protected: void paintEvent(QPaintEvent *event); @@ -81,17 +87,22 @@ private: QGraphicsSvgItem *m_foreground; QGraphicsSvgItem *m_needle1; QGraphicsSvgItem *m_needle2; + QGraphicsSvgItem *m_needle3; + bool n3enabled; bool n2enabled; // Simple flag to skip rendering if the bool fgenabled; // layer does not exist. // Settings concerning move of the dials bool rotateN1; bool rotateN2; + bool rotateN3; bool horizN1; bool horizN2; + bool horizN3; bool vertN1; bool vertN2; + bool vertN3; double n1MinValue; double n1MaxValue; @@ -99,6 +110,9 @@ private: double n2MinValue; double n2MaxValue; double n2Factor; + double n3MinValue; + double n3MaxValue; + double n3Factor; // The Value and target variables // are expressed in degrees @@ -106,12 +120,16 @@ private: double needle1Value; double needle2Target; double needle2Value; + double needle3Target; + double needle3Value; // Name of the fields to read when an update is received: UAVDataObject* obj1; UAVDataObject* obj2; + UAVDataObject* obj3; QString field1; QString field2; + QString field3; // Rotation timer QTimer dialTimer;