mirror of
https://bitbucket.org/librepilot/librepilot.git
synced 2024-11-29 07:24:13 +01:00
Header updates for Doxygen
git-svn-id: svn://svn.openpilot.org/OpenPilot/trunk@892 ebee16cc-31ac-478f-84a7-5cbb03baadba
This commit is contained in:
parent
cdd3e305b0
commit
9ebfcf1617
@ -2,7 +2,7 @@
|
||||
******************************************************************************
|
||||
*
|
||||
* @file airspeedgadget.cpp
|
||||
* @author David "Buzz" Carlson Copyright (C) 2010.
|
||||
* @author Edouard Lafargue and David Carlson Copyright (C) 2010.
|
||||
* @brief
|
||||
* @see The GNU Public License (GPL) Version 3
|
||||
* @defgroup dialplugin
|
||||
|
@ -2,7 +2,7 @@
|
||||
******************************************************************************
|
||||
*
|
||||
* @file airspeedgadget.h
|
||||
* @author David "Buzz" Carlson Copyright (C) 2010.
|
||||
* @author Edouard Lafargue and David Carlson Copyright (C) 2010.
|
||||
* @brief
|
||||
* @see The GNU Public License (GPL) Version 3
|
||||
* @defgroup dialplugin
|
||||
|
@ -2,7 +2,7 @@
|
||||
******************************************************************************
|
||||
*
|
||||
* @file airspeedgadgetfactory.cpp
|
||||
* @author David "Buzz" Carlson Copyright (C) 2010.
|
||||
* @author Edouard Lafargue and David Carlson Copyright (C) 2010.
|
||||
* @brief
|
||||
* @see The GNU Public License (GPL) Version 3
|
||||
* @defgroup dialplugin
|
||||
|
@ -2,7 +2,7 @@
|
||||
******************************************************************************
|
||||
*
|
||||
* @file airspeedgadgetfactory.h
|
||||
* @author David "Buzz" Carlson Copyright (C) 2010.
|
||||
* @author Edouard Lafargue and David Carlson Copyright (C) 2010.
|
||||
* @brief
|
||||
* @see The GNU Public License (GPL) Version 3
|
||||
* @defgroup dialplugin
|
||||
|
@ -1,457 +1,457 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
*
|
||||
* @file airspeedgadgetwidget.cpp
|
||||
* @author David "Buzz" Carlson Copyright (C) 2010.
|
||||
* @brief
|
||||
* @see The GNU Public License (GPL) Version 3
|
||||
* @defgroup dialplugin
|
||||
* @{
|
||||
*
|
||||
*****************************************************************************/
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "airspeedgadgetwidget.h"
|
||||
#include <iostream>
|
||||
#include <QDebug>
|
||||
|
||||
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));
|
||||
setRenderHints(QPainter::Antialiasing);
|
||||
|
||||
m_renderer = new QSvgRenderer();
|
||||
|
||||
obj1 = NULL;
|
||||
obj2 = NULL;
|
||||
obj3 = NULL;
|
||||
|
||||
needle1Target = 0;
|
||||
needle2Target = 0;
|
||||
needle3Target = 0;
|
||||
|
||||
// This timer mechanism makes needles rotate smoothly
|
||||
connect(&dialTimer, SIGNAL(timeout()), this, SLOT(rotateNeedles()));
|
||||
}
|
||||
|
||||
AirspeedGadgetWidget::~AirspeedGadgetWidget()
|
||||
{
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Connects the widget to the relevant UAVObjects
|
||||
*/
|
||||
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<UAVObjectManager>();
|
||||
|
||||
// Check validity of arguments first, reject empty args and unknown fields.
|
||||
if (!(object1.isEmpty() || nfield1.isEmpty())) {
|
||||
obj1 = dynamic_cast<UAVDataObject*>( objManager->getObject(object1) );
|
||||
if (obj1 != NULL ) {
|
||||
std::cout << "Connected Object 1 (" << object1.toStdString() << ")." << std::endl;
|
||||
connect(obj1, SIGNAL(objectUpdated(UAVObject*)), this, SLOT(updateNeedle1(UAVObject*)));
|
||||
field1 = nfield1;
|
||||
} else {
|
||||
std::cout << "Error: Object is unknown (" << object1.toStdString() << ")." << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
// And do the same for the second needle.
|
||||
if (!(object2.isEmpty() || nfield2.isEmpty())) {
|
||||
obj2 = dynamic_cast<UAVDataObject*>( objManager->getObject(object2) );
|
||||
if (obj2 != NULL ) {
|
||||
std::cout << "Connected Object 2 (" << object2.toStdString() << ")." << std::endl;
|
||||
connect(obj2, SIGNAL(objectUpdated(UAVObject*)), this, SLOT(updateNeedle2(UAVObject*)));
|
||||
field2 = nfield2;
|
||||
} else {
|
||||
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<UAVDataObject*>( 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Called by the UAVObject which got updated
|
||||
*/
|
||||
void AirspeedGadgetWidget::updateNeedle1(UAVObject *object1) {
|
||||
// Double check that the field exists:
|
||||
UAVObjectField* field = object1->getField(field1);
|
||||
if (field) {
|
||||
setNeedle1(field->getDouble());
|
||||
} else {
|
||||
std::cout << "Wrong field, maybe an issue with object disconnection ?" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Called by the UAVObject which got updated
|
||||
*/
|
||||
void AirspeedGadgetWidget::updateNeedle2(UAVObject *object2) {
|
||||
UAVObjectField* field = object2->getField(field2);
|
||||
if (field) {
|
||||
setNeedle2(field->getDouble());
|
||||
} else {
|
||||
std::cout << "Wrong field, maybe an issue with object disconnection ?" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\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 n3, QString n1Move, QString n2Move, QString n3Move)
|
||||
{
|
||||
if (QFile::exists(dfn))
|
||||
{
|
||||
m_renderer->load(dfn);
|
||||
if(m_renderer->isValid())
|
||||
{
|
||||
fgenabled = false;
|
||||
n2enabled = false;
|
||||
n3enabled = false;
|
||||
QGraphicsScene *l_scene = scene();
|
||||
l_scene->clear(); // Deletes all items contained in the scene as well.
|
||||
m_background = new QGraphicsSvgItem();
|
||||
// All other items will be clipped to the shape of the background
|
||||
m_background->setFlags(QGraphicsItem::ItemClipsChildrenToShape|
|
||||
QGraphicsItem::ItemClipsToShape);
|
||||
m_foreground = new QGraphicsSvgItem();
|
||||
m_needle1 = new QGraphicsSvgItem();
|
||||
m_needle2 = new QGraphicsSvgItem();
|
||||
m_needle3 = new QGraphicsSvgItem();
|
||||
m_needle1->setParentItem(m_background);
|
||||
m_needle2->setParentItem(m_background);
|
||||
m_needle3->setParentItem(m_background);
|
||||
m_foreground->setParentItem(m_background);
|
||||
|
||||
// We assume the dial 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);
|
||||
|
||||
// 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;
|
||||
} else {
|
||||
if (m_renderer->elementExists(n2)) {
|
||||
m_needle2->setSharedRenderer(m_renderer);
|
||||
m_needle2->setElementId(n2);
|
||||
l_scene->addItem(m_needle2);
|
||||
n2enabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
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...
|
||||
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;
|
||||
}
|
||||
|
||||
if (n3Move.contains("Rotate")) {
|
||||
rotateN3 = true;
|
||||
} else if (n3Move.contains("Horizontal")) {
|
||||
horizN3 = true;
|
||||
} else if (n3Move.contains("Vertical")) {
|
||||
vertN3 = true;
|
||||
}
|
||||
|
||||
l_scene->setSceneRect(m_background->boundingRect());
|
||||
|
||||
// Now Initialize the center for all transforms of the dial needles to the
|
||||
// center of the background:
|
||||
// - 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: we just loaded the dial file which is by default valid for a "zero" value
|
||||
// of the needles, so we have to reset the needles too upon dial file loading, otherwise
|
||||
// we would end up with an offset when we change a dial file and the needle value
|
||||
// is not zero at that time.
|
||||
needle1Value = 0;
|
||||
needle2Value = 0;
|
||||
needle3Value = 0;
|
||||
if (!dialTimer.isActive())
|
||||
dialTimer.start();
|
||||
}
|
||||
}
|
||||
else
|
||||
{ std::cout<<"no file: "<<std::endl; }
|
||||
}
|
||||
|
||||
void AirspeedGadgetWidget::paint()
|
||||
{
|
||||
update();
|
||||
}
|
||||
|
||||
void AirspeedGadgetWidget::paintEvent(QPaintEvent *event)
|
||||
{
|
||||
// Skip painting until the dial file is loaded
|
||||
if (! m_renderer->isValid()) {
|
||||
std::cout<<"Dial file not loaded, not rendering"<<std::endl;
|
||||
return;
|
||||
}
|
||||
QGraphicsView::paintEvent(event);
|
||||
}
|
||||
|
||||
// This event enables the dial to be dynamically resized
|
||||
// whenever the gadget is resized, taking advantage of the vector
|
||||
// nature of SVG dials.
|
||||
void AirspeedGadgetWidget::resizeEvent(QResizeEvent *event)
|
||||
{
|
||||
fitInView(m_background, Qt::KeepAspectRatio );
|
||||
}
|
||||
|
||||
// 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);
|
||||
}
|
||||
if (!dialTimer.isActive())
|
||||
dialTimer.start();
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
if (!dialTimer.isActive())
|
||||
dialTimer.start();
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
if (!dialTimer.isActive())
|
||||
dialTimer.start();
|
||||
}
|
||||
|
||||
// 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()
|
||||
{
|
||||
int dialRun = 3;
|
||||
if (n2enabled) {
|
||||
double needle2Diff;
|
||||
if (abs((needle2Value-needle2Target)*10) > 5) {
|
||||
needle2Diff =(needle2Target - needle2Value)/5;
|
||||
} else {
|
||||
needle2Diff = needle2Target - needle2Value;
|
||||
dialRun--;
|
||||
}
|
||||
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 such as attitude indicator).
|
||||
QPointF oop = m_needle2->transformOriginPoint();
|
||||
m_needle2->setTransformOriginPoint(oop.x()-opd.x(),oop.y()-opd.y());
|
||||
}
|
||||
needle2Value += needle2Diff;
|
||||
} else {
|
||||
dialRun--;
|
||||
}
|
||||
|
||||
// We assume that needle1 always exists!
|
||||
double needle1Diff;
|
||||
if ((abs((needle1Value-needle1Target)*10) > 5)) {
|
||||
needle1Diff = (needle1Target - needle1Value)/5;
|
||||
} else {
|
||||
needle1Diff = needle1Target - needle1Value;
|
||||
dialRun--;
|
||||
}
|
||||
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;
|
||||
|
||||
if (n3enabled) {
|
||||
double needle3Diff;
|
||||
if ((abs((needle3Value-needle3Target)*10) > 5)) {
|
||||
needle3Diff = (needle3Target - needle3Value)/5;
|
||||
} else {
|
||||
needle3Diff = needle3Target - needle3Value;
|
||||
dialRun--;
|
||||
}
|
||||
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;
|
||||
} else {
|
||||
dialRun--;
|
||||
}
|
||||
//update();
|
||||
// Now check: if dialRun is now zero, we should
|
||||
// just stop the timer since all needles have finished moving
|
||||
if (!dialRun) dialTimer.stop();
|
||||
}
|
||||
/**
|
||||
******************************************************************************
|
||||
*
|
||||
* @file airspeedgadgetwidget.cpp
|
||||
* @author Edouard Lafargue and David Carlson Copyright (C) 2010.
|
||||
* @brief
|
||||
* @see The GNU Public License (GPL) Version 3
|
||||
* @defgroup dialplugin
|
||||
* @{
|
||||
*
|
||||
*****************************************************************************/
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "airspeedgadgetwidget.h"
|
||||
#include <iostream>
|
||||
#include <QDebug>
|
||||
|
||||
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));
|
||||
setRenderHints(QPainter::Antialiasing);
|
||||
|
||||
m_renderer = new QSvgRenderer();
|
||||
|
||||
obj1 = NULL;
|
||||
obj2 = NULL;
|
||||
obj3 = NULL;
|
||||
|
||||
needle1Target = 0;
|
||||
needle2Target = 0;
|
||||
needle3Target = 0;
|
||||
|
||||
// This timer mechanism makes needles rotate smoothly
|
||||
connect(&dialTimer, SIGNAL(timeout()), this, SLOT(rotateNeedles()));
|
||||
}
|
||||
|
||||
AirspeedGadgetWidget::~AirspeedGadgetWidget()
|
||||
{
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Connects the widget to the relevant UAVObjects
|
||||
*/
|
||||
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<UAVObjectManager>();
|
||||
|
||||
// Check validity of arguments first, reject empty args and unknown fields.
|
||||
if (!(object1.isEmpty() || nfield1.isEmpty())) {
|
||||
obj1 = dynamic_cast<UAVDataObject*>( objManager->getObject(object1) );
|
||||
if (obj1 != NULL ) {
|
||||
std::cout << "Connected Object 1 (" << object1.toStdString() << ")." << std::endl;
|
||||
connect(obj1, SIGNAL(objectUpdated(UAVObject*)), this, SLOT(updateNeedle1(UAVObject*)));
|
||||
field1 = nfield1;
|
||||
} else {
|
||||
std::cout << "Error: Object is unknown (" << object1.toStdString() << ")." << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
// And do the same for the second needle.
|
||||
if (!(object2.isEmpty() || nfield2.isEmpty())) {
|
||||
obj2 = dynamic_cast<UAVDataObject*>( objManager->getObject(object2) );
|
||||
if (obj2 != NULL ) {
|
||||
std::cout << "Connected Object 2 (" << object2.toStdString() << ")." << std::endl;
|
||||
connect(obj2, SIGNAL(objectUpdated(UAVObject*)), this, SLOT(updateNeedle2(UAVObject*)));
|
||||
field2 = nfield2;
|
||||
} else {
|
||||
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<UAVDataObject*>( 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Called by the UAVObject which got updated
|
||||
*/
|
||||
void AirspeedGadgetWidget::updateNeedle1(UAVObject *object1) {
|
||||
// Double check that the field exists:
|
||||
UAVObjectField* field = object1->getField(field1);
|
||||
if (field) {
|
||||
setNeedle1(field->getDouble());
|
||||
} else {
|
||||
std::cout << "Wrong field, maybe an issue with object disconnection ?" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Called by the UAVObject which got updated
|
||||
*/
|
||||
void AirspeedGadgetWidget::updateNeedle2(UAVObject *object2) {
|
||||
UAVObjectField* field = object2->getField(field2);
|
||||
if (field) {
|
||||
setNeedle2(field->getDouble());
|
||||
} else {
|
||||
std::cout << "Wrong field, maybe an issue with object disconnection ?" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\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 n3, QString n1Move, QString n2Move, QString n3Move)
|
||||
{
|
||||
if (QFile::exists(dfn))
|
||||
{
|
||||
m_renderer->load(dfn);
|
||||
if(m_renderer->isValid())
|
||||
{
|
||||
fgenabled = false;
|
||||
n2enabled = false;
|
||||
n3enabled = false;
|
||||
QGraphicsScene *l_scene = scene();
|
||||
l_scene->clear(); // Deletes all items contained in the scene as well.
|
||||
m_background = new QGraphicsSvgItem();
|
||||
// All other items will be clipped to the shape of the background
|
||||
m_background->setFlags(QGraphicsItem::ItemClipsChildrenToShape|
|
||||
QGraphicsItem::ItemClipsToShape);
|
||||
m_foreground = new QGraphicsSvgItem();
|
||||
m_needle1 = new QGraphicsSvgItem();
|
||||
m_needle2 = new QGraphicsSvgItem();
|
||||
m_needle3 = new QGraphicsSvgItem();
|
||||
m_needle1->setParentItem(m_background);
|
||||
m_needle2->setParentItem(m_background);
|
||||
m_needle3->setParentItem(m_background);
|
||||
m_foreground->setParentItem(m_background);
|
||||
|
||||
// We assume the dial 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);
|
||||
|
||||
// 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;
|
||||
} else {
|
||||
if (m_renderer->elementExists(n2)) {
|
||||
m_needle2->setSharedRenderer(m_renderer);
|
||||
m_needle2->setElementId(n2);
|
||||
l_scene->addItem(m_needle2);
|
||||
n2enabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
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...
|
||||
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;
|
||||
}
|
||||
|
||||
if (n3Move.contains("Rotate")) {
|
||||
rotateN3 = true;
|
||||
} else if (n3Move.contains("Horizontal")) {
|
||||
horizN3 = true;
|
||||
} else if (n3Move.contains("Vertical")) {
|
||||
vertN3 = true;
|
||||
}
|
||||
|
||||
l_scene->setSceneRect(m_background->boundingRect());
|
||||
|
||||
// Now Initialize the center for all transforms of the dial needles to the
|
||||
// center of the background:
|
||||
// - 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: we just loaded the dial file which is by default valid for a "zero" value
|
||||
// of the needles, so we have to reset the needles too upon dial file loading, otherwise
|
||||
// we would end up with an offset when we change a dial file and the needle value
|
||||
// is not zero at that time.
|
||||
needle1Value = 0;
|
||||
needle2Value = 0;
|
||||
needle3Value = 0;
|
||||
if (!dialTimer.isActive())
|
||||
dialTimer.start();
|
||||
}
|
||||
}
|
||||
else
|
||||
{ std::cout<<"no file: "<<std::endl; }
|
||||
}
|
||||
|
||||
void AirspeedGadgetWidget::paint()
|
||||
{
|
||||
update();
|
||||
}
|
||||
|
||||
void AirspeedGadgetWidget::paintEvent(QPaintEvent *event)
|
||||
{
|
||||
// Skip painting until the dial file is loaded
|
||||
if (! m_renderer->isValid()) {
|
||||
std::cout<<"Dial file not loaded, not rendering"<<std::endl;
|
||||
return;
|
||||
}
|
||||
QGraphicsView::paintEvent(event);
|
||||
}
|
||||
|
||||
// This event enables the dial to be dynamically resized
|
||||
// whenever the gadget is resized, taking advantage of the vector
|
||||
// nature of SVG dials.
|
||||
void AirspeedGadgetWidget::resizeEvent(QResizeEvent *event)
|
||||
{
|
||||
fitInView(m_background, Qt::KeepAspectRatio );
|
||||
}
|
||||
|
||||
// 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);
|
||||
}
|
||||
if (!dialTimer.isActive())
|
||||
dialTimer.start();
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
if (!dialTimer.isActive())
|
||||
dialTimer.start();
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
if (!dialTimer.isActive())
|
||||
dialTimer.start();
|
||||
}
|
||||
|
||||
// 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()
|
||||
{
|
||||
int dialRun = 3;
|
||||
if (n2enabled) {
|
||||
double needle2Diff;
|
||||
if (abs((needle2Value-needle2Target)*10) > 5) {
|
||||
needle2Diff =(needle2Target - needle2Value)/5;
|
||||
} else {
|
||||
needle2Diff = needle2Target - needle2Value;
|
||||
dialRun--;
|
||||
}
|
||||
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 such as attitude indicator).
|
||||
QPointF oop = m_needle2->transformOriginPoint();
|
||||
m_needle2->setTransformOriginPoint(oop.x()-opd.x(),oop.y()-opd.y());
|
||||
}
|
||||
needle2Value += needle2Diff;
|
||||
} else {
|
||||
dialRun--;
|
||||
}
|
||||
|
||||
// We assume that needle1 always exists!
|
||||
double needle1Diff;
|
||||
if ((abs((needle1Value-needle1Target)*10) > 5)) {
|
||||
needle1Diff = (needle1Target - needle1Value)/5;
|
||||
} else {
|
||||
needle1Diff = needle1Target - needle1Value;
|
||||
dialRun--;
|
||||
}
|
||||
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;
|
||||
|
||||
if (n3enabled) {
|
||||
double needle3Diff;
|
||||
if ((abs((needle3Value-needle3Target)*10) > 5)) {
|
||||
needle3Diff = (needle3Target - needle3Value)/5;
|
||||
} else {
|
||||
needle3Diff = needle3Target - needle3Value;
|
||||
dialRun--;
|
||||
}
|
||||
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;
|
||||
} else {
|
||||
dialRun--;
|
||||
}
|
||||
//update();
|
||||
// Now check: if dialRun is now zero, we should
|
||||
// just stop the timer since all needles have finished moving
|
||||
if (!dialRun) dialTimer.stop();
|
||||
}
|
||||
|
@ -2,7 +2,7 @@
|
||||
******************************************************************************
|
||||
*
|
||||
* @file airspeedgadgetwidget.h
|
||||
* @author David "Buzz" Carlson Copyright (C) 2010.
|
||||
* @author Edouard Lafargue and David Carlson Copyright (C) 2010.
|
||||
* @brief
|
||||
* @see The GNU Public License (GPL) Version 3
|
||||
* @defgroup dialplugin
|
||||
|
@ -2,7 +2,7 @@
|
||||
******************************************************************************
|
||||
*
|
||||
* @file airspeedplugin.h
|
||||
* @author David "Buzz" Carlson Copyright (C) 2010.
|
||||
* @author Edouard Lafargue and David Carlson Copyright (C) 2010.
|
||||
* @brief
|
||||
* @see The GNU Public License (GPL) Version 3
|
||||
* @defgroup dialplugin
|
||||
|
@ -2,7 +2,7 @@
|
||||
******************************************************************************
|
||||
*
|
||||
* @file airspeedplugin.h
|
||||
* @author David "Buzz" Carlson Copyright (C) 2010.
|
||||
* @author Edouard Lafargue and David Carlson Copyright (C) 2010.
|
||||
* @brief
|
||||
* @see The GNU Public License (GPL) Version 3
|
||||
* @defgroup dialplugin
|
||||
|
@ -1,60 +1,60 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
*
|
||||
* @file airspeedgadget.cpp
|
||||
* @author David "Buzz" Carlson Copyright (C) 2010.
|
||||
* @brief
|
||||
* @see The GNU Public License (GPL) Version 3
|
||||
* @defgroup airspeed
|
||||
* @{
|
||||
*
|
||||
*****************************************************************************/
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "pfdgadget.h"
|
||||
#include "pfdgadgetwidget.h"
|
||||
#include "pfdgadgetconfiguration.h"
|
||||
|
||||
PFDGadget::PFDGadget(QString classId, PFDGadgetWidget *widget, QWidget *parent) :
|
||||
IUAVGadget(classId, parent),
|
||||
m_widget(widget)
|
||||
{
|
||||
}
|
||||
|
||||
PFDGadget::~PFDGadget()
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
This is called when a configuration is loaded, and updates the plugin's settings.
|
||||
Careful: the plugin is already drawn before the loadConfiguration method is called the
|
||||
first time, so you have to be careful not to assume all the plugin values are initialized
|
||||
the first time you use them
|
||||
*/
|
||||
void PFDGadget::loadConfiguration(IUAVGadgetConfiguration* config)
|
||||
{
|
||||
PFDGadgetConfiguration *m = qobject_cast<PFDGadgetConfiguration*>(config);
|
||||
m_widget->setDialFile(m->dialFile());
|
||||
|
||||
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();
|
||||
}
|
||||
/**
|
||||
******************************************************************************
|
||||
*
|
||||
* @file pfdgadget.cpp
|
||||
* @author Edouard Lafargue Copyright (C) 2010.
|
||||
* @brief
|
||||
* @see The GNU Public License (GPL) Version 3
|
||||
* @defgroup pfdplugin
|
||||
* @{
|
||||
*
|
||||
*****************************************************************************/
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "pfdgadget.h"
|
||||
#include "pfdgadgetwidget.h"
|
||||
#include "pfdgadgetconfiguration.h"
|
||||
|
||||
PFDGadget::PFDGadget(QString classId, PFDGadgetWidget *widget, QWidget *parent) :
|
||||
IUAVGadget(classId, parent),
|
||||
m_widget(widget)
|
||||
{
|
||||
}
|
||||
|
||||
PFDGadget::~PFDGadget()
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
This is called when a configuration is loaded, and updates the plugin's settings.
|
||||
Careful: the plugin is already drawn before the loadConfiguration method is called the
|
||||
first time, so you have to be careful not to assume all the plugin values are initialized
|
||||
the first time you use them
|
||||
*/
|
||||
void PFDGadget::loadConfiguration(IUAVGadgetConfiguration* config)
|
||||
{
|
||||
PFDGadgetConfiguration *m = qobject_cast<PFDGadgetConfiguration*>(config);
|
||||
m_widget->setDialFile(m->dialFile());
|
||||
|
||||
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();
|
||||
}
|
||||
|
@ -1,56 +1,56 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
*
|
||||
* @file pfdgadget.h
|
||||
* @author Edouard Lafargue Copyright (C) 2010.
|
||||
* @brief
|
||||
* @see The GNU Public License (GPL) Version 3
|
||||
* @defgroup pfd
|
||||
* @{
|
||||
*
|
||||
*****************************************************************************/
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef PFDGADGET_H_
|
||||
#define PFDGADGET_H_
|
||||
|
||||
#include <coreplugin/iuavgadget.h>
|
||||
#include "pfdgadgetwidget.h"
|
||||
|
||||
class IUAVGadget;
|
||||
class QWidget;
|
||||
class QString;
|
||||
class PFDGadgetWidget;
|
||||
|
||||
using namespace Core;
|
||||
|
||||
class PFDGadget : public Core::IUAVGadget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
PFDGadget(QString classId, PFDGadgetWidget *widget, QWidget *parent = 0);
|
||||
~PFDGadget();
|
||||
|
||||
QWidget *widget() { return m_widget; }
|
||||
void loadConfiguration(IUAVGadgetConfiguration* config);
|
||||
|
||||
private:
|
||||
PFDGadgetWidget *m_widget;
|
||||
};
|
||||
|
||||
|
||||
#endif // PFDGADGET_H_
|
||||
/**
|
||||
******************************************************************************
|
||||
*
|
||||
* @file pfdgadget.h
|
||||
* @author Edouard Lafargue Copyright (C) 2010.
|
||||
* @brief
|
||||
* @see The GNU Public License (GPL) Version 3
|
||||
* @defgroup pfdplugin
|
||||
* @{
|
||||
*
|
||||
*****************************************************************************/
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef PFDGADGET_H_
|
||||
#define PFDGADGET_H_
|
||||
|
||||
#include <coreplugin/iuavgadget.h>
|
||||
#include "pfdgadgetwidget.h"
|
||||
|
||||
class IUAVGadget;
|
||||
class QWidget;
|
||||
class QString;
|
||||
class PFDGadgetWidget;
|
||||
|
||||
using namespace Core;
|
||||
|
||||
class PFDGadget : public Core::IUAVGadget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
PFDGadget(QString classId, PFDGadgetWidget *widget, QWidget *parent = 0);
|
||||
~PFDGadget();
|
||||
|
||||
QWidget *widget() { return m_widget; }
|
||||
void loadConfiguration(IUAVGadgetConfiguration* config);
|
||||
|
||||
private:
|
||||
PFDGadgetWidget *m_widget;
|
||||
};
|
||||
|
||||
|
||||
#endif // PFDGADGET_H_
|
||||
|
@ -5,7 +5,7 @@
|
||||
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
|
||||
* @brief Primary Flight Display Plugin Gadget configuration
|
||||
* @see The GNU Public License (GPL) Version 3
|
||||
* @defgroup pfd
|
||||
* @defgroup pfdplugin
|
||||
* @{
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
@ -5,7 +5,7 @@
|
||||
* @author Edouard Lafargue Copyright (C) 2010.
|
||||
* @brief Primary Flight Display Plugin Gadget configuration
|
||||
* @see The GNU Public License (GPL) Version 3
|
||||
* @defgroup pfd
|
||||
* @defgroup pfdplugin
|
||||
* @{
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
@ -1,60 +1,60 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
*
|
||||
* @file pfdgadgetfactory.cpp
|
||||
* @author Edouard Lafargue Copyright (C) 2010.
|
||||
* @brief
|
||||
* @see The GNU Public License (GPL) Version 3
|
||||
* @defgroup pfd
|
||||
* @{
|
||||
*
|
||||
*****************************************************************************/
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
#include "pfdgadgetfactory.h"
|
||||
#include "pfdgadgetwidget.h"
|
||||
#include "pfdgadget.h"
|
||||
#include "pfdgadgetconfiguration.h"
|
||||
#include "pfdgadgetoptionspage.h"
|
||||
#include <coreplugin/iuavgadget.h>
|
||||
|
||||
PFDGadgetFactory::PFDGadgetFactory(QObject *parent) :
|
||||
IUAVGadgetFactory(QString("PFDGadget"),
|
||||
tr("Primary Flight Display Gadget"),
|
||||
parent)
|
||||
{
|
||||
}
|
||||
|
||||
PFDGadgetFactory::~PFDGadgetFactory()
|
||||
{
|
||||
}
|
||||
|
||||
Core::IUAVGadget* PFDGadgetFactory::createGadget(QWidget *parent)
|
||||
{
|
||||
PFDGadgetWidget* gadgetWidget = new PFDGadgetWidget(parent);
|
||||
return new PFDGadget(QString("PFDGadget"), gadgetWidget, parent);
|
||||
}
|
||||
|
||||
IUAVGadgetConfiguration *PFDGadgetFactory::createConfiguration(const QByteArray &state)
|
||||
{
|
||||
return new PFDGadgetConfiguration(QString("PFDGadget"), state);
|
||||
}
|
||||
|
||||
IOptionsPage *PFDGadgetFactory::createOptionsPage(IUAVGadgetConfiguration *config)
|
||||
{
|
||||
return new PFDGadgetOptionsPage(qobject_cast<PFDGadgetConfiguration*>(config));
|
||||
}
|
||||
|
||||
/**
|
||||
******************************************************************************
|
||||
*
|
||||
* @file pfdgadgetfactory.cpp
|
||||
* @author Edouard Lafargue Copyright (C) 2010.
|
||||
* @brief
|
||||
* @see The GNU Public License (GPL) Version 3
|
||||
* @defgroup pfdplugin
|
||||
* @{
|
||||
*
|
||||
*****************************************************************************/
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
#include "pfdgadgetfactory.h"
|
||||
#include "pfdgadgetwidget.h"
|
||||
#include "pfdgadget.h"
|
||||
#include "pfdgadgetconfiguration.h"
|
||||
#include "pfdgadgetoptionspage.h"
|
||||
#include <coreplugin/iuavgadget.h>
|
||||
|
||||
PFDGadgetFactory::PFDGadgetFactory(QObject *parent) :
|
||||
IUAVGadgetFactory(QString("PFDGadget"),
|
||||
tr("Primary Flight Display Gadget"),
|
||||
parent)
|
||||
{
|
||||
}
|
||||
|
||||
PFDGadgetFactory::~PFDGadgetFactory()
|
||||
{
|
||||
}
|
||||
|
||||
Core::IUAVGadget* PFDGadgetFactory::createGadget(QWidget *parent)
|
||||
{
|
||||
PFDGadgetWidget* gadgetWidget = new PFDGadgetWidget(parent);
|
||||
return new PFDGadget(QString("PFDGadget"), gadgetWidget, parent);
|
||||
}
|
||||
|
||||
IUAVGadgetConfiguration *PFDGadgetFactory::createConfiguration(const QByteArray &state)
|
||||
{
|
||||
return new PFDGadgetConfiguration(QString("PFDGadget"), state);
|
||||
}
|
||||
|
||||
IOptionsPage *PFDGadgetFactory::createOptionsPage(IUAVGadgetConfiguration *config)
|
||||
{
|
||||
return new PFDGadgetOptionsPage(qobject_cast<PFDGadgetConfiguration*>(config));
|
||||
}
|
||||
|
||||
|
@ -1,52 +1,52 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
*
|
||||
* @file pfdgadgetfactory.h
|
||||
* @author Edouard Lafargue Copyright (C) 2010.
|
||||
* @brief
|
||||
* @see The GNU Public License (GPL) Version 3
|
||||
* @defgroup pfd
|
||||
* @{
|
||||
*
|
||||
*****************************************************************************/
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef PFDGADGETFACTORY_H_
|
||||
#define PFDGADGETFACTORY_H_
|
||||
|
||||
#include <coreplugin/iuavgadgetfactory.h>
|
||||
|
||||
namespace Core {
|
||||
class IUAVGadget;
|
||||
class IUAVGadgetFactory;
|
||||
}
|
||||
|
||||
using namespace Core;
|
||||
|
||||
class PFDGadgetFactory : public IUAVGadgetFactory
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
PFDGadgetFactory(QObject *parent = 0);
|
||||
~PFDGadgetFactory();
|
||||
|
||||
Core::IUAVGadget *createGadget(QWidget *parent);
|
||||
IUAVGadgetConfiguration *createConfiguration(const QByteArray &state);
|
||||
IOptionsPage *createOptionsPage(IUAVGadgetConfiguration *config);
|
||||
};
|
||||
|
||||
#endif // PFDGADGETFACTORY_H_
|
||||
/**
|
||||
******************************************************************************
|
||||
*
|
||||
* @file pfdgadgetfactory.h
|
||||
* @author Edouard Lafargue Copyright (C) 2010.
|
||||
* @brief
|
||||
* @see The GNU Public License (GPL) Version 3
|
||||
* @defgroup pfdplugin
|
||||
* @{
|
||||
*
|
||||
*****************************************************************************/
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef PFDGADGETFACTORY_H_
|
||||
#define PFDGADGETFACTORY_H_
|
||||
|
||||
#include <coreplugin/iuavgadgetfactory.h>
|
||||
|
||||
namespace Core {
|
||||
class IUAVGadget;
|
||||
class IUAVGadgetFactory;
|
||||
}
|
||||
|
||||
using namespace Core;
|
||||
|
||||
class PFDGadgetFactory : public IUAVGadgetFactory
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
PFDGadgetFactory(QObject *parent = 0);
|
||||
~PFDGadgetFactory();
|
||||
|
||||
Core::IUAVGadget *createGadget(QWidget *parent);
|
||||
IUAVGadgetConfiguration *createConfiguration(const QByteArray &state);
|
||||
IOptionsPage *createOptionsPage(IUAVGadgetConfiguration *config);
|
||||
};
|
||||
|
||||
#endif // PFDGADGETFACTORY_H_
|
||||
|
@ -5,7 +5,7 @@
|
||||
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
|
||||
* @brief Primary Flight Display Plugin Gadget options page
|
||||
* @see The GNU Public License (GPL) Version 3
|
||||
* @defgroup pfd
|
||||
* @defgroup pfdplugin
|
||||
* @{
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
@ -5,7 +5,7 @@
|
||||
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
|
||||
* @brief Primary Flight Display Plugin Gadget options page
|
||||
* @see The GNU Public License (GPL) Version 3
|
||||
* @defgroup pfd
|
||||
* @defgroup pfdplugin
|
||||
* @{
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
@ -1,371 +1,371 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
*
|
||||
* @file pfdgadgetwidget.cpp
|
||||
* @author Edouard Lafargue Copyright (C) 2010.
|
||||
* @brief
|
||||
* @see The GNU Public License (GPL) Version 3
|
||||
* @defgroup pfd
|
||||
* @{
|
||||
*
|
||||
*****************************************************************************/
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "pfdgadgetwidget.h"
|
||||
#include <iostream>
|
||||
#include <QDebug>
|
||||
|
||||
PFDGadgetWidget::PFDGadgetWidget(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));
|
||||
setRenderHints(QPainter::Antialiasing);
|
||||
|
||||
m_renderer = new QSvgRenderer();
|
||||
|
||||
attitudeObj = NULL;
|
||||
headingObj = NULL;
|
||||
compassBandWidth = 0;
|
||||
/*
|
||||
obj2 = NULL;
|
||||
obj3 = NULL;
|
||||
*/
|
||||
// This timer mechanism makes needles rotate smoothly
|
||||
connect(&dialTimer, SIGNAL(timeout()), this, SLOT(rotateNeedles()));
|
||||
dialTimer.start(20);
|
||||
|
||||
}
|
||||
|
||||
PFDGadgetWidget::~PFDGadgetWidget()
|
||||
{
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Connects the widget to the relevant UAVObjects
|
||||
|
||||
We want: AttitudeActual, FlightBattery, Location
|
||||
|
||||
*/
|
||||
void PFDGadgetWidget::connectNeedles() {
|
||||
if (attitudeObj != NULL)
|
||||
disconnect(attitudeObj,SIGNAL(objectUpdated(UAVObject*)),this,SLOT(updateAttitude(UAVObject*)));
|
||||
|
||||
if (headingObj != NULL)
|
||||
disconnect(headingObj,SIGNAL(objectUpdated(UAVObject*)),this,SLOT(updateHeading(UAVObject*)));
|
||||
|
||||
ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance();
|
||||
UAVObjectManager *objManager = pm->getObject<UAVObjectManager>();
|
||||
|
||||
attitudeObj = dynamic_cast<UAVDataObject*>(objManager->getObject("AttitudeActual"));
|
||||
if (attitudeObj != NULL ) {
|
||||
connect(attitudeObj, SIGNAL(objectUpdated(UAVObject*)), this, SLOT(updateAttitude(UAVObject*)));
|
||||
} else {
|
||||
std::cout << "Error: Object is unknown (AttitudeActual)." << std::endl;
|
||||
}
|
||||
|
||||
headingObj = dynamic_cast<UAVDataObject*>(objManager->getObject("PositionActual"));
|
||||
if (headingObj != NULL ) {
|
||||
connect(headingObj, SIGNAL(objectUpdated(UAVObject*)), this, SLOT(updateHeading(UAVObject*)));
|
||||
} else {
|
||||
std::cout << "Error: Object is unknown (PositionActual)." << std::endl;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Reads the updated attitude and computes the new display position
|
||||
*/
|
||||
void PFDGadgetWidget::updateAttitude(UAVObject *object1) {
|
||||
// Double check that the field exists:
|
||||
QString roll = QString("Roll");
|
||||
QString pitch = QString("Pitch");
|
||||
UAVObjectField* field = object1->getField(roll);
|
||||
UAVObjectField* field2 = object1->getField(pitch);
|
||||
if (field && field2) {
|
||||
// These factors assume some things about the PFD SVG, namely:
|
||||
// - Roll value in degrees
|
||||
// - Pitch lines are 300px high for a +20/-20 range, which means
|
||||
// 7.5 pixels per pitch degree.
|
||||
rollTarget = field->getDouble()*(-1);
|
||||
pitchTarget = field2->getDouble()*7.5;
|
||||
if (!dialTimer.isActive())
|
||||
dialTimer.start(); // Rearm the dial Timer which might be stopped.
|
||||
} else {
|
||||
std::cout << "UpdateAttitude: Wrong field, maybe an issue with object disconnection ?" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Called by the UAVObject which got updated
|
||||
*/
|
||||
void PFDGadgetWidget::updateHeading(UAVObject *object1) {
|
||||
// Double check that the field exists:
|
||||
QString heading = QString("Heading");
|
||||
UAVObjectField* field = object1->getField(heading);
|
||||
if (field) {
|
||||
// These factors assume some things about the PFD SVG, namely:
|
||||
// - Heading value in degrees
|
||||
// - Scale is 540 degrees large
|
||||
headingTarget = field->getDouble()*compassBandWidth/(-540);
|
||||
|
||||
if (!dialTimer.isActive())
|
||||
dialTimer.start(); // Rearm the dial Timer which might be stopped.
|
||||
} else {
|
||||
std::cout << "UpdateHeading: Wrong field, maybe an issue with object disconnection ?" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Called by the UAVObject which got updated
|
||||
*/
|
||||
void PFDGadgetWidget::updateAirspeed(UAVObject *object3) {
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Called by the UAVObject which got updated
|
||||
*/
|
||||
void PFDGadgetWidget::updateAltitude(UAVObject *object3) {
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
\brief Called by the UAVObject which got updated
|
||||
*/
|
||||
void PFDGadgetWidget::updateBattery(UAVObject *object3) {
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Initializes the dial file, and does all the one-time calculations for
|
||||
display later.
|
||||
*/
|
||||
void PFDGadgetWidget::setDialFile(QString dfn)
|
||||
{
|
||||
if (QFile::exists(dfn))
|
||||
{
|
||||
m_renderer->load(dfn);
|
||||
if(m_renderer->isValid())
|
||||
{
|
||||
/* The PFD element IDs are fixed, not like with the analog dial.
|
||||
- Background: background
|
||||
- Foreground: foreground (contains all fixed elements, including plane)
|
||||
- earth/sky : world
|
||||
- Roll scale: rollscale
|
||||
- compass frame: compass (part of the foreground)
|
||||
- compass band : compass-band
|
||||
- Home point: homewaypoint
|
||||
- Next point: nextwaypoint
|
||||
- Home point bearing: homewaypoint-bearing
|
||||
- Next point bearing: nextwaypoint-bearing
|
||||
*/
|
||||
QGraphicsScene *l_scene = scene();
|
||||
l_scene->clear(); // Deletes all items contained in the scene as well.
|
||||
m_background = new QGraphicsSvgItem();
|
||||
// All other items will be clipped to the shape of the background
|
||||
m_background->setFlags(QGraphicsItem::ItemClipsChildrenToShape|
|
||||
QGraphicsItem::ItemClipsToShape);
|
||||
m_background->setSharedRenderer(m_renderer);
|
||||
m_background->setElementId("background");
|
||||
l_scene->addItem(m_background);
|
||||
|
||||
m_world = new QGraphicsSvgItem();
|
||||
m_world->setParentItem(m_background);
|
||||
m_world->setSharedRenderer(m_renderer);
|
||||
m_world->setElementId("world");
|
||||
l_scene->addItem(m_world);
|
||||
|
||||
// red Roll scale: rollscale
|
||||
m_rollscale = new QGraphicsSvgItem();
|
||||
m_rollscale->setSharedRenderer(m_renderer);
|
||||
m_rollscale->setElementId("rollscale");
|
||||
l_scene->addItem(m_rollscale);
|
||||
|
||||
// Home point:
|
||||
m_homewaypoint = new QGraphicsSvgItem();
|
||||
// Next point:
|
||||
m_nextwaypoint = new QGraphicsSvgItem();
|
||||
// Home point bearing:
|
||||
m_homepointbearing = new QGraphicsSvgItem();
|
||||
// Next point bearing:
|
||||
m_nextpointbearing = new QGraphicsSvgItem();
|
||||
|
||||
m_foreground = new QGraphicsSvgItem();
|
||||
m_foreground->setParentItem(m_background);
|
||||
m_foreground->setSharedRenderer(m_renderer);
|
||||
m_foreground->setElementId("foreground");
|
||||
l_scene->addItem(m_foreground);
|
||||
|
||||
// Compass:
|
||||
// Get the default location of the Compass:
|
||||
QMatrix compassMatrix = m_renderer->matrixForElement("compass");
|
||||
qreal startX = compassMatrix.mapRect(m_renderer->boundsOnElement("compass")).x();
|
||||
qreal startY = compassMatrix.mapRect(m_renderer->boundsOnElement("compass")).y();
|
||||
// Then once we have the initial location, we can put it
|
||||
// into a QGraphicsSvgItem which we will display at the same
|
||||
// place: we do this so that the heading scale can be clipped to
|
||||
// the compass dial region.
|
||||
m_compass = new QGraphicsSvgItem();
|
||||
m_compass->setSharedRenderer(m_renderer);
|
||||
m_compass->setElementId("compass");
|
||||
m_compass->setFlags(QGraphicsItem::ItemClipsChildrenToShape|
|
||||
QGraphicsItem::ItemClipsToShape);
|
||||
l_scene->addItem(m_compass);
|
||||
QTransform matrix;
|
||||
matrix.translate(startX,startY);
|
||||
m_compass->setTransform(matrix,false);
|
||||
|
||||
// Now place the compass scale inside:
|
||||
m_compassband = new QGraphicsSvgItem();
|
||||
m_compassband->setSharedRenderer(m_renderer);
|
||||
m_compassband->setElementId("compass-band");
|
||||
m_compassband->setParentItem(m_compass);
|
||||
l_scene->addItem(m_compassband);
|
||||
matrix.reset();
|
||||
// Note: the compass band has to be a path, which means all text elements have to be
|
||||
// converted, ortherwise boundsOnElement does not compute the height correctly
|
||||
// if the highest element is a text element. This is a Qt Bug as far as I can tell.
|
||||
|
||||
// compass-scale is the while bottom line inside the band: using the band's width
|
||||
// includes half the width of the letters, which causes errors:
|
||||
compassBandWidth = m_renderer->boundsOnElement("compass-scale").width();
|
||||
|
||||
l_scene->setSceneRect(m_background->boundingRect());
|
||||
|
||||
// Now Initialize the center for all transforms of the relevant elements to the
|
||||
// center of the background:
|
||||
|
||||
// 1) Move the center of the needle to the center of the background.
|
||||
QRectF rectB = m_background->boundingRect();
|
||||
QRectF rectN = m_world->boundingRect();
|
||||
m_world->setPos(rectB.width()/2-rectN.width()/2,rectB.height()/2-rectN.height()/2);
|
||||
// 2) Put the transform origin point of the needle at its center.
|
||||
m_world->setTransformOriginPoint(rectN.width()/2,rectN.height()/2);
|
||||
|
||||
rectN = m_rollscale->boundingRect();
|
||||
m_rollscale->setPos(rectB.width()/2-rectN.width()/2,rectB.height()/2-rectN.height()/2);
|
||||
m_rollscale->setTransformOriginPoint(rectN.width()/2,rectN.height()/2);
|
||||
|
||||
// Also to the same init for the compass:
|
||||
rectB = m_compass->boundingRect();
|
||||
rectN = m_compassband->boundingRect();
|
||||
m_compassband->setPos(rectB.width()/2-rectN.width()/2,rectB.height()/2-rectN.height()/2);
|
||||
m_compassband->setTransformOriginPoint(rectN.width()/2,rectN.height()/2);
|
||||
|
||||
// Last: we just loaded the dial file which is by default valid for a "zero" value
|
||||
// of the needles, so we have to reset the needles too upon dial file loading, otherwise
|
||||
// we would end up with an offset when we change a dial file and the needle value
|
||||
// is not zero at that time.
|
||||
rollValue = 0;
|
||||
pitchValue = 0;
|
||||
headingValue = 0;
|
||||
if (!dialTimer.isActive())
|
||||
dialTimer.start(); // Rearm the dial Timer which might be stopped.
|
||||
}
|
||||
}
|
||||
else
|
||||
{ std::cout<<"no file: "<<std::endl; }
|
||||
}
|
||||
|
||||
void PFDGadgetWidget::paint()
|
||||
{
|
||||
update();
|
||||
}
|
||||
|
||||
void PFDGadgetWidget::paintEvent(QPaintEvent *event)
|
||||
{
|
||||
// Skip painting until the dial file is loaded
|
||||
if (! m_renderer->isValid()) {
|
||||
std::cout<<"Dial file not loaded, not rendering"<<std::endl;
|
||||
return;
|
||||
}
|
||||
QGraphicsView::paintEvent(event);
|
||||
}
|
||||
|
||||
// This event enables the dial to be dynamically resized
|
||||
// whenever the gadget is resized, taking advantage of the vector
|
||||
// nature of SVG dials.
|
||||
void PFDGadgetWidget::resizeEvent(QResizeEvent *event)
|
||||
{
|
||||
fitInView(m_background, Qt::KeepAspectRatio );
|
||||
}
|
||||
|
||||
|
||||
// Take an input value and move the elements accordingly.
|
||||
// Movement is smooth, starts fast and slows down when
|
||||
// approaching the target.
|
||||
//
|
||||
void PFDGadgetWidget::rotateNeedles()
|
||||
{
|
||||
int dialCount = 3; // Gets decreased by one for each element
|
||||
// which has finished moving
|
||||
|
||||
double rollDiff;
|
||||
if ((abs((rollValue-rollTarget)*10) > 5)) {
|
||||
rollDiff =(rollTarget - rollValue)/5;
|
||||
} else {
|
||||
rollDiff = rollTarget - rollValue;
|
||||
dialCount--;
|
||||
}
|
||||
m_world->setRotation(m_world->rotation()+rollDiff);
|
||||
m_rollscale->setRotation(m_rollscale->rotation()+rollDiff);
|
||||
rollValue += rollDiff;
|
||||
|
||||
double pitchDiff;
|
||||
if ((abs((pitchValue-pitchTarget)*10) > 5)) {
|
||||
pitchDiff = (pitchTarget - pitchValue)/5;
|
||||
} else {
|
||||
pitchDiff = pitchTarget - pitchValue;
|
||||
dialCount--;
|
||||
}
|
||||
QPointF opd = QPointF(0,pitchDiff);
|
||||
m_world->setTransform(QTransform::fromTranslate(opd.x(),opd.y()), true);
|
||||
QPointF oop = m_world->transformOriginPoint();
|
||||
m_world->setTransformOriginPoint((oop.x()-opd.x()),(oop.y()-opd.y()));
|
||||
pitchValue += pitchDiff;
|
||||
|
||||
double headingOffset = 0;
|
||||
double headingDiff;
|
||||
if ((abs((headingValue-headingTarget)*10) > 5)) {
|
||||
headingDiff = (headingTarget - headingValue)/5;
|
||||
} else {
|
||||
headingDiff = headingTarget-headingValue;
|
||||
dialCount--;
|
||||
}
|
||||
double threshold = -180*compassBandWidth/540;
|
||||
// Note: rendering can jump oh so very slightly when crossing the 180 degree
|
||||
// boundary, should not impact actual useability of the display.
|
||||
if ((headingValue < threshold) && ((headingValue+headingDiff)>=threshold)) {
|
||||
// We went over 180°: activate a -360 degree offset
|
||||
headingOffset = 2*threshold;
|
||||
} else if ((headingValue >= threshold) && ((headingValue+headingDiff)<threshold)) {
|
||||
// We went under 180°: remove the -360 degree offset
|
||||
headingOffset = -2*threshold;
|
||||
}
|
||||
opd = QPointF(headingDiff+headingOffset,0);
|
||||
m_compassband->setTransform(QTransform::fromTranslate(opd.x(),opd.y()), true);
|
||||
headingValue += headingDiff;
|
||||
|
||||
//update();
|
||||
if (!dialCount)
|
||||
dialTimer.stop();
|
||||
}
|
||||
/**
|
||||
******************************************************************************
|
||||
*
|
||||
* @file pfdgadgetwidget.cpp
|
||||
* @author Edouard Lafargue Copyright (C) 2010.
|
||||
* @brief
|
||||
* @see The GNU Public License (GPL) Version 3
|
||||
* @defgroup pfdplugin
|
||||
* @{
|
||||
*
|
||||
*****************************************************************************/
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "pfdgadgetwidget.h"
|
||||
#include <iostream>
|
||||
#include <QDebug>
|
||||
|
||||
PFDGadgetWidget::PFDGadgetWidget(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));
|
||||
setRenderHints(QPainter::Antialiasing);
|
||||
|
||||
m_renderer = new QSvgRenderer();
|
||||
|
||||
attitudeObj = NULL;
|
||||
headingObj = NULL;
|
||||
compassBandWidth = 0;
|
||||
/*
|
||||
obj2 = NULL;
|
||||
obj3 = NULL;
|
||||
*/
|
||||
// This timer mechanism makes needles rotate smoothly
|
||||
connect(&dialTimer, SIGNAL(timeout()), this, SLOT(rotateNeedles()));
|
||||
dialTimer.start(20);
|
||||
|
||||
}
|
||||
|
||||
PFDGadgetWidget::~PFDGadgetWidget()
|
||||
{
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Connects the widget to the relevant UAVObjects
|
||||
|
||||
We want: AttitudeActual, FlightBattery, Location
|
||||
|
||||
*/
|
||||
void PFDGadgetWidget::connectNeedles() {
|
||||
if (attitudeObj != NULL)
|
||||
disconnect(attitudeObj,SIGNAL(objectUpdated(UAVObject*)),this,SLOT(updateAttitude(UAVObject*)));
|
||||
|
||||
if (headingObj != NULL)
|
||||
disconnect(headingObj,SIGNAL(objectUpdated(UAVObject*)),this,SLOT(updateHeading(UAVObject*)));
|
||||
|
||||
ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance();
|
||||
UAVObjectManager *objManager = pm->getObject<UAVObjectManager>();
|
||||
|
||||
attitudeObj = dynamic_cast<UAVDataObject*>(objManager->getObject("AttitudeActual"));
|
||||
if (attitudeObj != NULL ) {
|
||||
connect(attitudeObj, SIGNAL(objectUpdated(UAVObject*)), this, SLOT(updateAttitude(UAVObject*)));
|
||||
} else {
|
||||
std::cout << "Error: Object is unknown (AttitudeActual)." << std::endl;
|
||||
}
|
||||
|
||||
headingObj = dynamic_cast<UAVDataObject*>(objManager->getObject("PositionActual"));
|
||||
if (headingObj != NULL ) {
|
||||
connect(headingObj, SIGNAL(objectUpdated(UAVObject*)), this, SLOT(updateHeading(UAVObject*)));
|
||||
} else {
|
||||
std::cout << "Error: Object is unknown (PositionActual)." << std::endl;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Reads the updated attitude and computes the new display position
|
||||
*/
|
||||
void PFDGadgetWidget::updateAttitude(UAVObject *object1) {
|
||||
// Double check that the field exists:
|
||||
QString roll = QString("Roll");
|
||||
QString pitch = QString("Pitch");
|
||||
UAVObjectField* field = object1->getField(roll);
|
||||
UAVObjectField* field2 = object1->getField(pitch);
|
||||
if (field && field2) {
|
||||
// These factors assume some things about the PFD SVG, namely:
|
||||
// - Roll value in degrees
|
||||
// - Pitch lines are 300px high for a +20/-20 range, which means
|
||||
// 7.5 pixels per pitch degree.
|
||||
rollTarget = field->getDouble()*(-1);
|
||||
pitchTarget = field2->getDouble()*7.5;
|
||||
if (!dialTimer.isActive())
|
||||
dialTimer.start(); // Rearm the dial Timer which might be stopped.
|
||||
} else {
|
||||
std::cout << "UpdateAttitude: Wrong field, maybe an issue with object disconnection ?" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Called by the UAVObject which got updated
|
||||
*/
|
||||
void PFDGadgetWidget::updateHeading(UAVObject *object1) {
|
||||
// Double check that the field exists:
|
||||
QString heading = QString("Heading");
|
||||
UAVObjectField* field = object1->getField(heading);
|
||||
if (field) {
|
||||
// These factors assume some things about the PFD SVG, namely:
|
||||
// - Heading value in degrees
|
||||
// - Scale is 540 degrees large
|
||||
headingTarget = field->getDouble()*compassBandWidth/(-540);
|
||||
|
||||
if (!dialTimer.isActive())
|
||||
dialTimer.start(); // Rearm the dial Timer which might be stopped.
|
||||
} else {
|
||||
std::cout << "UpdateHeading: Wrong field, maybe an issue with object disconnection ?" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Called by the UAVObject which got updated
|
||||
*/
|
||||
void PFDGadgetWidget::updateAirspeed(UAVObject *object3) {
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Called by the UAVObject which got updated
|
||||
*/
|
||||
void PFDGadgetWidget::updateAltitude(UAVObject *object3) {
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
\brief Called by the UAVObject which got updated
|
||||
*/
|
||||
void PFDGadgetWidget::updateBattery(UAVObject *object3) {
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Initializes the dial file, and does all the one-time calculations for
|
||||
display later.
|
||||
*/
|
||||
void PFDGadgetWidget::setDialFile(QString dfn)
|
||||
{
|
||||
if (QFile::exists(dfn))
|
||||
{
|
||||
m_renderer->load(dfn);
|
||||
if(m_renderer->isValid())
|
||||
{
|
||||
/* The PFD element IDs are fixed, not like with the analog dial.
|
||||
- Background: background
|
||||
- Foreground: foreground (contains all fixed elements, including plane)
|
||||
- earth/sky : world
|
||||
- Roll scale: rollscale
|
||||
- compass frame: compass (part of the foreground)
|
||||
- compass band : compass-band
|
||||
- Home point: homewaypoint
|
||||
- Next point: nextwaypoint
|
||||
- Home point bearing: homewaypoint-bearing
|
||||
- Next point bearing: nextwaypoint-bearing
|
||||
*/
|
||||
QGraphicsScene *l_scene = scene();
|
||||
l_scene->clear(); // Deletes all items contained in the scene as well.
|
||||
m_background = new QGraphicsSvgItem();
|
||||
// All other items will be clipped to the shape of the background
|
||||
m_background->setFlags(QGraphicsItem::ItemClipsChildrenToShape|
|
||||
QGraphicsItem::ItemClipsToShape);
|
||||
m_background->setSharedRenderer(m_renderer);
|
||||
m_background->setElementId("background");
|
||||
l_scene->addItem(m_background);
|
||||
|
||||
m_world = new QGraphicsSvgItem();
|
||||
m_world->setParentItem(m_background);
|
||||
m_world->setSharedRenderer(m_renderer);
|
||||
m_world->setElementId("world");
|
||||
l_scene->addItem(m_world);
|
||||
|
||||
// red Roll scale: rollscale
|
||||
m_rollscale = new QGraphicsSvgItem();
|
||||
m_rollscale->setSharedRenderer(m_renderer);
|
||||
m_rollscale->setElementId("rollscale");
|
||||
l_scene->addItem(m_rollscale);
|
||||
|
||||
// Home point:
|
||||
m_homewaypoint = new QGraphicsSvgItem();
|
||||
// Next point:
|
||||
m_nextwaypoint = new QGraphicsSvgItem();
|
||||
// Home point bearing:
|
||||
m_homepointbearing = new QGraphicsSvgItem();
|
||||
// Next point bearing:
|
||||
m_nextpointbearing = new QGraphicsSvgItem();
|
||||
|
||||
m_foreground = new QGraphicsSvgItem();
|
||||
m_foreground->setParentItem(m_background);
|
||||
m_foreground->setSharedRenderer(m_renderer);
|
||||
m_foreground->setElementId("foreground");
|
||||
l_scene->addItem(m_foreground);
|
||||
|
||||
// Compass:
|
||||
// Get the default location of the Compass:
|
||||
QMatrix compassMatrix = m_renderer->matrixForElement("compass");
|
||||
qreal startX = compassMatrix.mapRect(m_renderer->boundsOnElement("compass")).x();
|
||||
qreal startY = compassMatrix.mapRect(m_renderer->boundsOnElement("compass")).y();
|
||||
// Then once we have the initial location, we can put it
|
||||
// into a QGraphicsSvgItem which we will display at the same
|
||||
// place: we do this so that the heading scale can be clipped to
|
||||
// the compass dial region.
|
||||
m_compass = new QGraphicsSvgItem();
|
||||
m_compass->setSharedRenderer(m_renderer);
|
||||
m_compass->setElementId("compass");
|
||||
m_compass->setFlags(QGraphicsItem::ItemClipsChildrenToShape|
|
||||
QGraphicsItem::ItemClipsToShape);
|
||||
l_scene->addItem(m_compass);
|
||||
QTransform matrix;
|
||||
matrix.translate(startX,startY);
|
||||
m_compass->setTransform(matrix,false);
|
||||
|
||||
// Now place the compass scale inside:
|
||||
m_compassband = new QGraphicsSvgItem();
|
||||
m_compassband->setSharedRenderer(m_renderer);
|
||||
m_compassband->setElementId("compass-band");
|
||||
m_compassband->setParentItem(m_compass);
|
||||
l_scene->addItem(m_compassband);
|
||||
matrix.reset();
|
||||
// Note: the compass band has to be a path, which means all text elements have to be
|
||||
// converted, ortherwise boundsOnElement does not compute the height correctly
|
||||
// if the highest element is a text element. This is a Qt Bug as far as I can tell.
|
||||
|
||||
// compass-scale is the while bottom line inside the band: using the band's width
|
||||
// includes half the width of the letters, which causes errors:
|
||||
compassBandWidth = m_renderer->boundsOnElement("compass-scale").width();
|
||||
|
||||
l_scene->setSceneRect(m_background->boundingRect());
|
||||
|
||||
// Now Initialize the center for all transforms of the relevant elements to the
|
||||
// center of the background:
|
||||
|
||||
// 1) Move the center of the needle to the center of the background.
|
||||
QRectF rectB = m_background->boundingRect();
|
||||
QRectF rectN = m_world->boundingRect();
|
||||
m_world->setPos(rectB.width()/2-rectN.width()/2,rectB.height()/2-rectN.height()/2);
|
||||
// 2) Put the transform origin point of the needle at its center.
|
||||
m_world->setTransformOriginPoint(rectN.width()/2,rectN.height()/2);
|
||||
|
||||
rectN = m_rollscale->boundingRect();
|
||||
m_rollscale->setPos(rectB.width()/2-rectN.width()/2,rectB.height()/2-rectN.height()/2);
|
||||
m_rollscale->setTransformOriginPoint(rectN.width()/2,rectN.height()/2);
|
||||
|
||||
// Also to the same init for the compass:
|
||||
rectB = m_compass->boundingRect();
|
||||
rectN = m_compassband->boundingRect();
|
||||
m_compassband->setPos(rectB.width()/2-rectN.width()/2,rectB.height()/2-rectN.height()/2);
|
||||
m_compassband->setTransformOriginPoint(rectN.width()/2,rectN.height()/2);
|
||||
|
||||
// Last: we just loaded the dial file which is by default valid for a "zero" value
|
||||
// of the needles, so we have to reset the needles too upon dial file loading, otherwise
|
||||
// we would end up with an offset when we change a dial file and the needle value
|
||||
// is not zero at that time.
|
||||
rollValue = 0;
|
||||
pitchValue = 0;
|
||||
headingValue = 0;
|
||||
if (!dialTimer.isActive())
|
||||
dialTimer.start(); // Rearm the dial Timer which might be stopped.
|
||||
}
|
||||
}
|
||||
else
|
||||
{ std::cout<<"no file: "<<std::endl; }
|
||||
}
|
||||
|
||||
void PFDGadgetWidget::paint()
|
||||
{
|
||||
update();
|
||||
}
|
||||
|
||||
void PFDGadgetWidget::paintEvent(QPaintEvent *event)
|
||||
{
|
||||
// Skip painting until the dial file is loaded
|
||||
if (! m_renderer->isValid()) {
|
||||
std::cout<<"Dial file not loaded, not rendering"<<std::endl;
|
||||
return;
|
||||
}
|
||||
QGraphicsView::paintEvent(event);
|
||||
}
|
||||
|
||||
// This event enables the dial to be dynamically resized
|
||||
// whenever the gadget is resized, taking advantage of the vector
|
||||
// nature of SVG dials.
|
||||
void PFDGadgetWidget::resizeEvent(QResizeEvent *event)
|
||||
{
|
||||
fitInView(m_background, Qt::KeepAspectRatio );
|
||||
}
|
||||
|
||||
|
||||
// Take an input value and move the elements accordingly.
|
||||
// Movement is smooth, starts fast and slows down when
|
||||
// approaching the target.
|
||||
//
|
||||
void PFDGadgetWidget::rotateNeedles()
|
||||
{
|
||||
int dialCount = 3; // Gets decreased by one for each element
|
||||
// which has finished moving
|
||||
|
||||
double rollDiff;
|
||||
if ((abs((rollValue-rollTarget)*10) > 5)) {
|
||||
rollDiff =(rollTarget - rollValue)/5;
|
||||
} else {
|
||||
rollDiff = rollTarget - rollValue;
|
||||
dialCount--;
|
||||
}
|
||||
m_world->setRotation(m_world->rotation()+rollDiff);
|
||||
m_rollscale->setRotation(m_rollscale->rotation()+rollDiff);
|
||||
rollValue += rollDiff;
|
||||
|
||||
double pitchDiff;
|
||||
if ((abs((pitchValue-pitchTarget)*10) > 5)) {
|
||||
pitchDiff = (pitchTarget - pitchValue)/5;
|
||||
} else {
|
||||
pitchDiff = pitchTarget - pitchValue;
|
||||
dialCount--;
|
||||
}
|
||||
QPointF opd = QPointF(0,pitchDiff);
|
||||
m_world->setTransform(QTransform::fromTranslate(opd.x(),opd.y()), true);
|
||||
QPointF oop = m_world->transformOriginPoint();
|
||||
m_world->setTransformOriginPoint((oop.x()-opd.x()),(oop.y()-opd.y()));
|
||||
pitchValue += pitchDiff;
|
||||
|
||||
double headingOffset = 0;
|
||||
double headingDiff;
|
||||
if ((abs((headingValue-headingTarget)*10) > 5)) {
|
||||
headingDiff = (headingTarget - headingValue)/5;
|
||||
} else {
|
||||
headingDiff = headingTarget-headingValue;
|
||||
dialCount--;
|
||||
}
|
||||
double threshold = -180*compassBandWidth/540;
|
||||
// Note: rendering can jump oh so very slightly when crossing the 180 degree
|
||||
// boundary, should not impact actual useability of the display.
|
||||
if ((headingValue < threshold) && ((headingValue+headingDiff)>=threshold)) {
|
||||
// We went over 180°: activate a -360 degree offset
|
||||
headingOffset = 2*threshold;
|
||||
} else if ((headingValue >= threshold) && ((headingValue+headingDiff)<threshold)) {
|
||||
// We went under 180°: remove the -360 degree offset
|
||||
headingOffset = -2*threshold;
|
||||
}
|
||||
opd = QPointF(headingDiff+headingOffset,0);
|
||||
m_compassband->setTransform(QTransform::fromTranslate(opd.x(),opd.y()), true);
|
||||
headingValue += headingDiff;
|
||||
|
||||
//update();
|
||||
if (!dialCount)
|
||||
dialTimer.stop();
|
||||
}
|
||||
|
@ -1,128 +1,128 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
*
|
||||
* @file pfdgadgetwidget.h
|
||||
* @author Edouard Lafargue Copyright (C) 2010.
|
||||
* @brief
|
||||
* @see The GNU Public License (GPL) Version 3
|
||||
* @defgroup pfd
|
||||
* @{
|
||||
*
|
||||
*****************************************************************************/
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef PFDGADGETWIDGET_H_
|
||||
#define PFDGADGETWIDGET_H_
|
||||
|
||||
#include "pfdgadgetconfiguration.h"
|
||||
#include "extensionsystem/pluginmanager.h"
|
||||
#include "uavobjects/uavobjectmanager.h"
|
||||
#include "uavobjects/uavobject.h"
|
||||
#include <QGraphicsView>
|
||||
#include <QtSvg/QSvgRenderer>
|
||||
#include <QtSvg/QGraphicsSvgItem>
|
||||
|
||||
#include <QFile>
|
||||
#include <QTimer>
|
||||
|
||||
class PFDGadgetWidget : public QGraphicsView
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
PFDGadgetWidget(QWidget *parent = 0);
|
||||
~PFDGadgetWidget();
|
||||
void setDialFile(QString dfn);
|
||||
void paint();
|
||||
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();
|
||||
|
||||
public slots:
|
||||
void updateAttitude(UAVObject *object1);
|
||||
void updateHeading(UAVObject *object1);
|
||||
void updateAirspeed(UAVObject *object1);
|
||||
void updateAltitude(UAVObject *object1);
|
||||
void updateBattery(UAVObject *object1);
|
||||
|
||||
protected:
|
||||
void paintEvent(QPaintEvent *event);
|
||||
void resizeEvent(QResizeEvent *event);
|
||||
|
||||
|
||||
private slots:
|
||||
void rotateNeedles();
|
||||
|
||||
private:
|
||||
QSvgRenderer *m_renderer;
|
||||
|
||||
// Background: background
|
||||
QGraphicsSvgItem *m_background;
|
||||
// Foreground: foreground (contains all fixed elements, including plane)
|
||||
QGraphicsSvgItem *m_foreground;
|
||||
// earth/sky : world
|
||||
QGraphicsSvgItem *m_world;
|
||||
// Roll scale: rollscale
|
||||
QGraphicsSvgItem *m_rollscale;
|
||||
// Compass dial:
|
||||
QGraphicsSvgItem *m_compass;
|
||||
// Compass band:
|
||||
QGraphicsSvgItem *m_compassband;
|
||||
// Home point:
|
||||
QGraphicsSvgItem *m_homewaypoint;
|
||||
// Next point:
|
||||
QGraphicsSvgItem *m_nextwaypoint;
|
||||
// Home point bearing:
|
||||
QGraphicsSvgItem *m_homepointbearing;
|
||||
// Next point bearing:
|
||||
QGraphicsSvgItem *m_nextpointbearing;
|
||||
|
||||
double n1MinValue;
|
||||
double n1MaxValue;
|
||||
double n1Factor;
|
||||
double n2MinValue;
|
||||
double n2MaxValue;
|
||||
double n2Factor;
|
||||
double n3MinValue;
|
||||
double n3MaxValue;
|
||||
double n3Factor;
|
||||
|
||||
// The Value and target variables
|
||||
// are expressed in degrees
|
||||
double rollTarget;
|
||||
double rollValue;
|
||||
double pitchTarget;
|
||||
double pitchValue;
|
||||
double headingTarget;
|
||||
double headingValue;
|
||||
|
||||
qreal compassBandWidth;
|
||||
|
||||
// Name of the fields to read when an update is received:
|
||||
UAVDataObject* attitudeObj;
|
||||
UAVDataObject* headingObj;
|
||||
|
||||
// Rotation timer
|
||||
QTimer dialTimer;
|
||||
|
||||
};
|
||||
#endif /* PFDGADGETWIDGET_H_ */
|
||||
/**
|
||||
******************************************************************************
|
||||
*
|
||||
* @file pfdgadgetwidget.h
|
||||
* @author Edouard Lafargue Copyright (C) 2010.
|
||||
* @brief
|
||||
* @see The GNU Public License (GPL) Version 3
|
||||
* @defgroup pfdplugin
|
||||
* @{
|
||||
*
|
||||
*****************************************************************************/
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef PFDGADGETWIDGET_H_
|
||||
#define PFDGADGETWIDGET_H_
|
||||
|
||||
#include "pfdgadgetconfiguration.h"
|
||||
#include "extensionsystem/pluginmanager.h"
|
||||
#include "uavobjects/uavobjectmanager.h"
|
||||
#include "uavobjects/uavobject.h"
|
||||
#include <QGraphicsView>
|
||||
#include <QtSvg/QSvgRenderer>
|
||||
#include <QtSvg/QGraphicsSvgItem>
|
||||
|
||||
#include <QFile>
|
||||
#include <QTimer>
|
||||
|
||||
class PFDGadgetWidget : public QGraphicsView
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
PFDGadgetWidget(QWidget *parent = 0);
|
||||
~PFDGadgetWidget();
|
||||
void setDialFile(QString dfn);
|
||||
void paint();
|
||||
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();
|
||||
|
||||
public slots:
|
||||
void updateAttitude(UAVObject *object1);
|
||||
void updateHeading(UAVObject *object1);
|
||||
void updateAirspeed(UAVObject *object1);
|
||||
void updateAltitude(UAVObject *object1);
|
||||
void updateBattery(UAVObject *object1);
|
||||
|
||||
protected:
|
||||
void paintEvent(QPaintEvent *event);
|
||||
void resizeEvent(QResizeEvent *event);
|
||||
|
||||
|
||||
private slots:
|
||||
void rotateNeedles();
|
||||
|
||||
private:
|
||||
QSvgRenderer *m_renderer;
|
||||
|
||||
// Background: background
|
||||
QGraphicsSvgItem *m_background;
|
||||
// Foreground: foreground (contains all fixed elements, including plane)
|
||||
QGraphicsSvgItem *m_foreground;
|
||||
// earth/sky : world
|
||||
QGraphicsSvgItem *m_world;
|
||||
// Roll scale: rollscale
|
||||
QGraphicsSvgItem *m_rollscale;
|
||||
// Compass dial:
|
||||
QGraphicsSvgItem *m_compass;
|
||||
// Compass band:
|
||||
QGraphicsSvgItem *m_compassband;
|
||||
// Home point:
|
||||
QGraphicsSvgItem *m_homewaypoint;
|
||||
// Next point:
|
||||
QGraphicsSvgItem *m_nextwaypoint;
|
||||
// Home point bearing:
|
||||
QGraphicsSvgItem *m_homepointbearing;
|
||||
// Next point bearing:
|
||||
QGraphicsSvgItem *m_nextpointbearing;
|
||||
|
||||
double n1MinValue;
|
||||
double n1MaxValue;
|
||||
double n1Factor;
|
||||
double n2MinValue;
|
||||
double n2MaxValue;
|
||||
double n2Factor;
|
||||
double n3MinValue;
|
||||
double n3MaxValue;
|
||||
double n3Factor;
|
||||
|
||||
// The Value and target variables
|
||||
// are expressed in degrees
|
||||
double rollTarget;
|
||||
double rollValue;
|
||||
double pitchTarget;
|
||||
double pitchValue;
|
||||
double headingTarget;
|
||||
double headingValue;
|
||||
|
||||
qreal compassBandWidth;
|
||||
|
||||
// Name of the fields to read when an update is received:
|
||||
UAVDataObject* attitudeObj;
|
||||
UAVDataObject* headingObj;
|
||||
|
||||
// Rotation timer
|
||||
QTimer dialTimer;
|
||||
|
||||
};
|
||||
#endif /* PFDGADGETWIDGET_H_ */
|
||||
|
@ -1,66 +1,66 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
*
|
||||
* @file pfdplugin.h
|
||||
* @author Edouard Lafargue Copyright (C) 2010.
|
||||
* @brief
|
||||
* @see The GNU Public License (GPL) Version 3
|
||||
* @defgroup pfd
|
||||
* @{
|
||||
*
|
||||
*****************************************************************************/
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "pfdplugin.h"
|
||||
#include "pfdgadgetfactory.h"
|
||||
#include <QDebug>
|
||||
#include <QtPlugin>
|
||||
#include <QStringList>
|
||||
#include <extensionsystem/pluginmanager.h>
|
||||
|
||||
|
||||
PFDPlugin::PFDPlugin()
|
||||
{
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
PFDPlugin::~PFDPlugin()
|
||||
{
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
bool PFDPlugin::initialize(const QStringList& args, QString *errMsg)
|
||||
{
|
||||
Q_UNUSED(args);
|
||||
Q_UNUSED(errMsg);
|
||||
mf = new PFDGadgetFactory(this);
|
||||
addAutoReleasedObject(mf);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void PFDPlugin::extensionsInitialized()
|
||||
{
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
void PFDPlugin::shutdown()
|
||||
{
|
||||
// Do nothing
|
||||
}
|
||||
Q_EXPORT_PLUGIN(PFDPlugin)
|
||||
|
||||
/**
|
||||
******************************************************************************
|
||||
*
|
||||
* @file pfdplugin.h
|
||||
* @author Edouard Lafargue Copyright (C) 2010.
|
||||
* @brief
|
||||
* @see The GNU Public License (GPL) Version 3
|
||||
* @defgroup pfdplugin
|
||||
* @{
|
||||
*
|
||||
*****************************************************************************/
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "pfdplugin.h"
|
||||
#include "pfdgadgetfactory.h"
|
||||
#include <QDebug>
|
||||
#include <QtPlugin>
|
||||
#include <QStringList>
|
||||
#include <extensionsystem/pluginmanager.h>
|
||||
|
||||
|
||||
PFDPlugin::PFDPlugin()
|
||||
{
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
PFDPlugin::~PFDPlugin()
|
||||
{
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
bool PFDPlugin::initialize(const QStringList& args, QString *errMsg)
|
||||
{
|
||||
Q_UNUSED(args);
|
||||
Q_UNUSED(errMsg);
|
||||
mf = new PFDGadgetFactory(this);
|
||||
addAutoReleasedObject(mf);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void PFDPlugin::extensionsInitialized()
|
||||
{
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
void PFDPlugin::shutdown()
|
||||
{
|
||||
// Do nothing
|
||||
}
|
||||
Q_EXPORT_PLUGIN(PFDPlugin)
|
||||
|
||||
|
@ -1,47 +1,47 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
*
|
||||
* @file pfdplugin.h
|
||||
* @author Edouard Lafargue Copyright (C) 2010.
|
||||
* @brief
|
||||
* @see The GNU Public License (GPL) Version 3
|
||||
* @defgroup pfd
|
||||
* @{
|
||||
*
|
||||
*****************************************************************************/
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef PFDPLUGIN_H_
|
||||
#define PFDPLUGIN_H_
|
||||
|
||||
#include <extensionsystem/iplugin.h>
|
||||
|
||||
class PFDGadgetFactory;
|
||||
|
||||
class PFDPlugin : public ExtensionSystem::IPlugin
|
||||
{
|
||||
public:
|
||||
PFDPlugin();
|
||||
~PFDPlugin();
|
||||
|
||||
void extensionsInitialized();
|
||||
bool initialize(const QStringList & arguments, QString * errorString);
|
||||
void shutdown();
|
||||
private:
|
||||
PFDGadgetFactory *mf;
|
||||
};
|
||||
#endif /* PFDPLUGIN_H_ */
|
||||
/**
|
||||
******************************************************************************
|
||||
*
|
||||
* @file pfdplugin.h
|
||||
* @author Edouard Lafargue Copyright (C) 2010.
|
||||
* @brief
|
||||
* @see The GNU Public License (GPL) Version 3
|
||||
* @defgroup pfdplugin
|
||||
* @{
|
||||
*
|
||||
*****************************************************************************/
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef PFDPLUGIN_H_
|
||||
#define PFDPLUGIN_H_
|
||||
|
||||
#include <extensionsystem/iplugin.h>
|
||||
|
||||
class PFDGadgetFactory;
|
||||
|
||||
class PFDPlugin : public ExtensionSystem::IPlugin
|
||||
{
|
||||
public:
|
||||
PFDPlugin();
|
||||
~PFDPlugin();
|
||||
|
||||
void extensionsInitialized();
|
||||
bool initialize(const QStringList & arguments, QString * errorString);
|
||||
void shutdown();
|
||||
private:
|
||||
PFDGadgetFactory *mf;
|
||||
};
|
||||
#endif /* PFDPLUGIN_H_ */
|
||||
|
Loading…
Reference in New Issue
Block a user