From 50d63d35faf2c9044afa0cda39b24dfd3d18ba99 Mon Sep 17 00:00:00 2001 From: edouard Date: Mon, 14 Jun 2010 13:09:26 +0000 Subject: [PATCH] OP-60: Analog dial needles can now also move horizontally and vertically. Combined move can be achieved if both needles have the same name, this enables fancy indicators such as artificial horizon. Additional work still needed for proper display, but it's a start. git-svn-id: svn://svn.openpilot.org/OpenPilot/trunk@764 ebee16cc-31ac-478f-84a7-5cbb03baadba --- .../src/plugins/airspeed/airspeedgadget.cpp | 2 +- .../airspeed/airspeedgadgetconfiguration.cpp | 11 +- .../airspeed/airspeedgadgetconfiguration.h | 10 +- .../airspeed/airspeedgadgetoptionspage.cpp | 13 ++ .../airspeed/airspeedgadgetoptionspage.ui | 20 +++ .../plugins/airspeed/airspeedgadgetwidget.cpp | 130 +++++++++++++----- .../plugins/airspeed/airspeedgadgetwidget.h | 19 +-- 7 files changed, 158 insertions(+), 47 deletions(-) diff --git a/ground/src/plugins/airspeed/airspeedgadget.cpp b/ground/src/plugins/airspeed/airspeedgadget.cpp index 669b331a0..23e1e3451 100644 --- a/ground/src/plugins/airspeed/airspeedgadget.cpp +++ b/ground/src/plugins/airspeed/airspeedgadget.cpp @@ -49,7 +49,7 @@ void AirspeedGadget::loadConfiguration(IUAVGadgetConfiguration* config) { AirspeedGadgetConfiguration *m = qobject_cast(config); m_widget->setDialFile(m->dialFile(), m->dialBackground(), m->dialForeground(), m->dialNeedle1(), - m->dialNeedle2()); + m->dialNeedle2(),m->getN1Move(), m->getN2Move()); m_widget->setN1Min(m->getN1Min()); m_widget->setN1Max(m->getN1Max()); diff --git a/ground/src/plugins/airspeed/airspeedgadgetconfiguration.cpp b/ground/src/plugins/airspeed/airspeedgadgetconfiguration.cpp index b412b3811..fefefc360 100644 --- a/ground/src/plugins/airspeed/airspeedgadgetconfiguration.cpp +++ b/ground/src/plugins/airspeed/airspeedgadgetconfiguration.cpp @@ -38,13 +38,15 @@ AirspeedGadgetConfiguration::AirspeedGadgetConfiguration(QString classId, const dialBackgroundID("background"), dialForegroundID("foreground"), dialNeedleID1("needle"), - dialNeedleID2("needle-2"), + dialNeedleID2("needle2"), needle1MinValue(0), needle1MaxValue(100), needle2MinValue(0), needle2MaxValue(100), needle1Factor(1), - needle2Factor(1) + needle2Factor(1), + needle1Move("Rotate"), + needle2Move("Rotate") { //if a saved configuration exists load it if (state.count() > 0) { @@ -66,7 +68,8 @@ AirspeedGadgetConfiguration::AirspeedGadgetConfiguration(QString classId, const stream >> needle2ObjectField; stream >> needle1Factor; stream >> needle2Factor; - + stream >> needle1Move; + stream >> needle2Move; } } /** @@ -102,6 +105,8 @@ QByteArray AirspeedGadgetConfiguration::saveState() const stream << needle2ObjectField; stream << needle1Factor; stream << needle2Factor; + stream << needle1Move; + stream << needle2Move; return bytes; } diff --git a/ground/src/plugins/airspeed/airspeedgadgetconfiguration.h b/ground/src/plugins/airspeed/airspeedgadgetconfiguration.h index b76c605b6..dbb9f57c2 100644 --- a/ground/src/plugins/airspeed/airspeedgadgetconfiguration.h +++ b/ground/src/plugins/airspeed/airspeedgadgetconfiguration.h @@ -57,6 +57,8 @@ public: void setN2DataObject(QString text){ needle2DataObject = text; } void setN1ObjField(QString text) { needle1ObjectField = text; } void setN2ObjField(QString text) { needle2ObjectField = text; } + void setN1Move( QString move) { needle1Move = move; } + void setN2Move( QString move) { needle2Move = move; } //get dial configuration functions QString dialFile() {return m_defaultDial;} @@ -74,8 +76,8 @@ public: QString getN2DataObject() { return needle2DataObject; } QString getN1ObjField() { return needle1ObjectField; } QString getN2ObjField() { return needle2ObjectField; } - - + QString getN1Move() { return needle1Move; } + QString getN2Move() { return needle2Move; } QByteArray saveState() const; IUAVGadgetConfiguration *clone(); @@ -99,6 +101,10 @@ private: QString needle1ObjectField; QString needle2DataObject; QString needle2ObjectField; + + // How the two dials move: + QString needle1Move; + QString needle2Move; }; #endif // AIRSPEEDGADGETCONFIGURATION_H diff --git a/ground/src/plugins/airspeed/airspeedgadgetoptionspage.cpp b/ground/src/plugins/airspeed/airspeedgadgetoptionspage.cpp index 4b563c076..19e7d1da8 100644 --- a/ground/src/plugins/airspeed/airspeedgadgetoptionspage.cpp +++ b/ground/src/plugins/airspeed/airspeedgadgetoptionspage.cpp @@ -64,6 +64,15 @@ QWidget *AirspeedGadgetOptionsPage::createPage(QWidget *parent) } } + // Fills the combo boxes for Needle movement options + options_page->moveNeedle1->addItem("Rotate"); + options_page->moveNeedle1->addItem("Horizontal"); + options_page->moveNeedle1->addItem("Vertical"); + + options_page->moveNeedle2->addItem("Rotate"); + options_page->moveNeedle2->addItem("Horizontal"); + options_page->moveNeedle2->addItem("Vertical"); + // Restore the contents from the settings: options_page->svgSourceFile->setText(m_config->dialFile()); options_page->backgroundID->setText(m_config->dialBackground()); @@ -76,6 +85,8 @@ QWidget *AirspeedGadgetOptionsPage::createPage(QWidget *parent) options_page->needle2Max->setValue(m_config->getN2Max()); options_page->factor1->setValue(m_config->getN1Factor()); options_page->factor2->setValue(m_config->getN2Factor()); + options_page->moveNeedle1->setCurrentIndex(options_page->moveNeedle1->findText(m_config->getN1Move())); + options_page->moveNeedle2->setCurrentIndex(options_page->moveNeedle2->findText(m_config->getN2Move())); //select saved UAV Object field values if(options_page->uavObject1->findText(m_config->getN1DataObject())!=-1){ @@ -132,6 +143,8 @@ void AirspeedGadgetOptionsPage::apply() m_config->setN2DataObject(options_page->uavObject2->currentText()); m_config->setN1ObjField(options_page->objectField1->currentText()); m_config->setN2ObjField(options_page->objectField2->currentText()); + m_config->setN1Move(options_page->moveNeedle1->currentText()); + m_config->setN2Move(options_page->moveNeedle2->currentText()); } /* diff --git a/ground/src/plugins/airspeed/airspeedgadgetoptionspage.ui b/ground/src/plugins/airspeed/airspeedgadgetoptionspage.ui index f4417de3c..840e59e2b 100644 --- a/ground/src/plugins/airspeed/airspeedgadgetoptionspage.ui +++ b/ground/src/plugins/airspeed/airspeedgadgetoptionspage.ui @@ -145,6 +145,16 @@ + + + + Movement: + + + + + + @@ -338,6 +348,16 @@ + + + + Movement: + + + + + + diff --git a/ground/src/plugins/airspeed/airspeedgadgetwidget.cpp b/ground/src/plugins/airspeed/airspeedgadgetwidget.cpp index 050302e41..0626bdb5a 100644 --- a/ground/src/plugins/airspeed/airspeedgadgetwidget.cpp +++ b/ground/src/plugins/airspeed/airspeedgadgetwidget.cpp @@ -28,6 +28,7 @@ #include "airspeedgadgetwidget.h" #include #include +#include "math.h" AirspeedGadgetWidget::AirspeedGadgetWidget(QWidget *parent) : QGraphicsView(parent) { @@ -50,16 +51,13 @@ AirspeedGadgetWidget::AirspeedGadgetWidget(QWidget *parent) : QGraphicsView(pare obj1 = NULL; obj2 = NULL; + rotateN1 = horizN1 = vertN1 = false; + rotateN2 = horizN2 = vertN2 = false; + // This timer mechanism makes needles rotate smoothly connect(&dialTimer, SIGNAL(timeout()), this, SLOT(rotateNeedles())); dialTimer.start(20); - // Test code for timer to rotate the needle -#if 0 - testSpeed=0; - connect(&m_testTimer, SIGNAL(timeout()), this, SLOT(testRotate())); - m_testTimer.start(4000); -#endif } AirspeedGadgetWidget::~AirspeedGadgetWidget() @@ -131,7 +129,8 @@ void AirspeedGadgetWidget::updateNeedle2(UAVObject *object2) { } } -void AirspeedGadgetWidget::setDialFile(QString dfn, QString bg, QString fg, QString n1, QString n2) +void AirspeedGadgetWidget::setDialFile(QString dfn, QString bg, QString fg, QString n1, QString n2, + QString n1Move, QString n2Move) { if (QFile::exists(dfn)) { @@ -159,6 +158,10 @@ void AirspeedGadgetWidget::setDialFile(QString dfn, QString bg, QString fg, QStr fgenabled = false; } + if (n1 == n2) { + m_needle2 = m_needle1; + n2enabled = true; + } else { if (m_renderer->elementExists(n2)) { m_needle2->setSharedRenderer(m_renderer); m_needle2->setElementId(n2); @@ -170,9 +173,37 @@ void AirspeedGadgetWidget::setDialFile(QString dfn, QString bg, QString fg, QStr l_scene->removeItem(m_needle2); n2enabled = false; } + } + + // Now setup the rotation/translation settings: + // this is UGLY UGLY UGLY, sorry... + if (n1Move.contains("Rotate")) { + rotateN1 = true; + } else if (n1Move.contains("Horizontal")) { + horizN1 = true; + } else if (n1Move.contains("Vertical")) { + vertN1 = true; + } + + if (n2Move.contains("Rotate")) { + rotateN2 = true; + } else if (n2Move.contains("Horizontal")) { + horizN2 = true; + } else if (n2Move.contains("Vertical")) { + vertN2 = true; + } // std::cout<<"Dial file loaded ("<< dfn.toStdString() << ")" << std::endl; l_scene->setSceneRect(m_background->boundingRect()); + + // Initialize the center for all transforms of the dials 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()); } } else @@ -212,48 +243,83 @@ void AirspeedGadgetWidget::resizeEvent(QResizeEvent *event) // Converts the value into an angle: // this enables smooth rotation in rotateNeedles below void AirspeedGadgetWidget::setNeedle1(double value) { - needle1Target = 360*value*n1Factor/(n1MaxValue-n1MinValue); + if (rotateN1) { + needle1Target = 360*value*n1Factor/(n1MaxValue-n1MinValue); + } + if (horizN1) { + needle1Target = value*n1Factor/(n1MaxValue-n1MinValue); + } + if (vertN1) { + needle1Target = value*n1Factor/(n1MaxValue-n1MinValue); + } } void AirspeedGadgetWidget::setNeedle2(double value) { - needle2Target = 360*value*n2Factor/(n2MaxValue-n2MinValue); + if (rotateN2) { + needle2Target = 360*value*n2Factor/(n2MaxValue-n2MinValue); + } + if (horizN2) { + needle2Target = value*n2Factor/(n2MaxValue-n2MinValue); + } + if (vertN2) { + needle2Target = value*n2Factor/(n2MaxValue-n2MinValue); + } } - // Take an input value and rotate the dial accordingly // Rotation is smooth, starts fast and slows down when // approaching the target. // We aim for a 0.5 degree precision. +// +// Note: this code is valid even if needle1 and needle2 point +// to the same element. void AirspeedGadgetWidget::rotateNeedles() { if ((abs((needle2Value-needle2Target)*10) > 5) && n2enabled) { - needle2Value+=(needle2Target - needle2Value)/5; - m_needle2->resetTransform(); - QRectF rect = m_needle2->boundingRect(); - m_needle2->translate(rect.width()/2,rect.height()/2); - m_needle2->rotate(needle2Value); - m_needle2->translate(-rect.width()/2,-rect.height()/2); + double needle2Diff; + needle2Diff =(needle2Target - needle2Value)/5; + if (rotateN2) { + m_needle2->setRotation(m_needle2->rotation()+needle2Diff); + } else { + QPointF opd = QPointF(0,0); + if (horizN2) { + opd = QPointF(needle2Diff,0); + } + if (vertN2) { + opd = QPointF(0,needle2Diff); + } + m_needle2->setTransform(QTransform::fromTranslate(opd.x(),opd.y()), true); + // Since we have moved the needle, we need to move + // 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. + QPointF oop = m_needle2->transformOriginPoint(); + m_needle2->setTransformOriginPoint(oop.x()-opd.x(),oop.y()-opd.y()); + } + needle2Value += needle2Diff; } if ((abs((needle1Value-needle1Target)*10) > 5)) { - needle1Value += (needle1Target - needle1Value)/5; - m_needle1->resetTransform(); - QRectF rect = m_needle1->boundingRect(); - m_needle1->translate(rect.width()/2,rect.height()/2); - m_needle1->rotate(needle1Value); - m_needle1->translate(-rect.width()/2,-rect.height()/2); + double needle1Diff; + needle1Diff = (needle1Target - needle1Value)/5; + if (rotateN1) { + m_needle1->setRotation(m_needle1->rotation()+needle1Diff); + } else { + QPointF opd = QPointF(0,0); + if (horizN1) { + opd = QPointF(needle1Diff,0); + } + if (vertN1) { + opd = QPointF(0,needle1Diff); + } + m_needle1->setTransform(QTransform::fromTranslate(opd.x(),opd.y()), true); + QPointF oop = m_needle1->transformOriginPoint(); + m_needle1->setTransformOriginPoint((oop.x()-opd.x()),(oop.y()-opd.y())); + } + needle1Value += needle1Diff; } update(); } - -// Test function for timer to rotate needles -void AirspeedGadgetWidget::testRotate() -{ - int testVal1 = rand() % (int)n1MaxValue; - int testVal2 = rand() % (int)n2MaxValue; - setNeedle1((double)testVal1); - setNeedle2((double)testVal2); - -} diff --git a/ground/src/plugins/airspeed/airspeedgadgetwidget.h b/ground/src/plugins/airspeed/airspeedgadgetwidget.h index 27ac44399..c91ef98be 100644 --- a/ground/src/plugins/airspeed/airspeedgadgetwidget.h +++ b/ground/src/plugins/airspeed/airspeedgadgetwidget.h @@ -46,7 +46,8 @@ class AirspeedGadgetWidget : public QGraphicsView public: AirspeedGadgetWidget(QWidget *parent = 0); ~AirspeedGadgetWidget(); - void setDialFile(QString dfn, QString bg, QString fg, QString n1, QString n2); + void setDialFile(QString dfn, QString bg, QString fg, QString n1, QString n2, QString n1Move, + QString n2Move); void paint(); // setNeedle1 and setNeedle2 use a timer to simulate // needle inertia @@ -72,8 +73,6 @@ protected: private slots: - // Test function - void testRotate(); void rotateNeedles(); private: @@ -86,6 +85,14 @@ private: 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 horizN1; + bool horizN2; + bool vertN1; + bool vertN2; + double n1MinValue; double n1MaxValue; double n1Factor; @@ -109,11 +116,5 @@ private: // Rotation timer QTimer dialTimer; - // Test variables -#if 0 - int testSpeed; - QTimer m_testTimer; - // End test variables -#endif }; #endif /* AIRSPEEDGADGETWIDGET_H_ */