1
0
mirror of https://bitbucket.org/librepilot/librepilot.git synced 2025-01-18 03:52:11 +01:00

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
This commit is contained in:
edouard 2010-06-14 13:09:26 +00:00 committed by edouard
parent 106bdca20e
commit 50d63d35fa
7 changed files with 158 additions and 47 deletions

View File

@ -49,7 +49,7 @@ void AirspeedGadget::loadConfiguration(IUAVGadgetConfiguration* config)
{
AirspeedGadgetConfiguration *m = qobject_cast<AirspeedGadgetConfiguration*>(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());

View File

@ -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;
}

View File

@ -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

View File

@ -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());
}
/*

View File

@ -145,6 +145,16 @@
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="label_12">
<property name="text">
<string>Movement:</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="moveNeedle1"/>
</item>
<item>
<widget class="QLabel" name="label_5">
<property name="text">
@ -338,6 +348,16 @@
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="label_13">
<property name="text">
<string>Movement:</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="moveNeedle2"/>
</item>
<item>
<widget class="QLabel" name="label_17">
<property name="text">

View File

@ -28,6 +28,7 @@
#include "airspeedgadgetwidget.h"
#include <iostream>
#include <QDebug>
#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) {
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) {
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);
}

View File

@ -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_ */