mirror of
https://bitbucket.org/librepilot/librepilot.git
synced 2025-01-17 02:52:12 +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:
parent
106bdca20e
commit
50d63d35fa
@ -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());
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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());
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -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">
|
||||
|
@ -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) {
|
||||
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);
|
||||
|
||||
}
|
||||
|
@ -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_ */
|
||||
|
Loading…
x
Reference in New Issue
Block a user