diff --git a/ground/src/plugins/config/airframe.ui b/ground/src/plugins/config/airframe.ui
index 5118e7d58..96e027f6a 100644
--- a/ground/src/plugins/config/airframe.ui
+++ b/ground/src/plugins/config/airframe.ui
@@ -107,8 +107,26 @@
Aircraft type:
+
+
+
+ 90
+ 70
+ 131
+ 131
+
+
+
+
+
+ MixerCurveWidget
+ QWidget
+
+ 1
+
+
diff --git a/ground/src/plugins/config/config.pro b/ground/src/plugins/config/config.pro
index 9f9c00fe6..475bf9340 100644
--- a/ground/src/plugins/config/config.pro
+++ b/ground/src/plugins/config/config.pro
@@ -17,7 +17,10 @@ HEADERS += configplugin.h \
configtaskwidget.h \
configairframewidget.h \
configtelemetrywidget.h \
- configahrswidget.h
+ configahrswidget.h \
+ mixercurvewidget.h \
+ mixercurvepoint.h \
+ mixercurveline.h
SOURCES += configplugin.cpp \
configgadgetconfiguration.cpp \
configgadgetwidget.cpp \
@@ -29,7 +32,10 @@ SOURCES += configplugin.cpp \
configservowidget.cpp \
configairframewidget.cpp \
configtelemetrywidget.cpp \
- configahrswidget.cpp
+ configahrswidget.cpp \
+ mixercurvewidget.cpp \
+ mixercurvepoint.cpp \
+ mixercurveline.cpp
FORMS += settingswidget.ui \
airframe.ui \
telemetry.ui \
diff --git a/ground/src/plugins/config/configgadget.qrc b/ground/src/plugins/config/configgadget.qrc
index 903601653..0b36bd1f6 100644
--- a/ground/src/plugins/config/configgadget.qrc
+++ b/ground/src/plugins/config/configgadget.qrc
@@ -6,5 +6,6 @@
images/ahrs-calib.svg
images/AHRS-v1.3.png
images/paper-plane.svg
+ images/curve-bg.svg
diff --git a/ground/src/plugins/config/images/curve-bg.svg b/ground/src/plugins/config/images/curve-bg.svg
new file mode 100644
index 000000000..4b424a335
--- /dev/null
+++ b/ground/src/plugins/config/images/curve-bg.svg
@@ -0,0 +1,128 @@
+
+
+
+
diff --git a/ground/src/plugins/config/mixercurveline.cpp b/ground/src/plugins/config/mixercurveline.cpp
new file mode 100644
index 000000000..d3ace9220
--- /dev/null
+++ b/ground/src/plugins/config/mixercurveline.cpp
@@ -0,0 +1,139 @@
+/**
+ ******************************************************************************
+ *
+ * @file mixercurveline.h
+ * @author Edouard Lafargue Copyright (C) 2010.
+ * Parts by Nokia Corporation (qt-info@nokia.com) Copyright (C) 2010.
+ * @addtogroup GCSPlugins GCS Plugins
+ * @{
+ * @addtogroup ConfigPlugin Configuration Plugin
+ * @{
+ * @brief A line connecting two mixer points
+ *****************************************************************************/
+/*
+ * 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
+
+#include "mixercurveline.h"
+#include "mixercurvepoint.h"
+
+#include
+
+static const double Pi = 3.14159265358979323846264338327950288419717;
+static double TwoPi = 2.0 * Pi;
+
+Edge::Edge(Node *sourceNode, Node *destNode)
+ : arrowSize(10)
+{
+ setAcceptedMouseButtons(0);
+ source = sourceNode;
+ dest = destNode;
+ source->addEdge(this);
+ dest->addEdge(this);
+ adjust();
+}
+
+Edge::~Edge()
+{
+}
+
+Node *Edge::sourceNode() const
+{
+ return source;
+}
+
+void Edge::setSourceNode(Node *node)
+{
+ source = node;
+ adjust();
+}
+
+Node *Edge::destNode() const
+{
+ return dest;
+}
+
+void Edge::setDestNode(Node *node)
+{
+ dest = node;
+ adjust();
+}
+
+void Edge::adjust()
+{
+ if (!source || !dest)
+ return;
+
+ QLineF line(mapFromItem(source, 0, 0), mapFromItem(dest, 0, 0));
+ qreal length = line.length();
+
+ prepareGeometryChange();
+
+ if (length > qreal(20.)) {
+ QPointF edgeOffset((line.dx() * 10) / length, (line.dy() * 10) / length);
+ sourcePoint = line.p1() + edgeOffset;
+ destPoint = line.p2() - edgeOffset;
+ } else {
+ sourcePoint = destPoint = line.p1();
+ }
+}
+
+QRectF Edge::boundingRect() const
+{
+ if (!source || !dest)
+ return QRectF();
+
+ qreal penWidth = 1;
+ qreal extra = (penWidth + arrowSize) / 2.0;
+
+ return QRectF(sourcePoint, QSizeF(destPoint.x() - sourcePoint.x(),
+ destPoint.y() - sourcePoint.y()))
+ .normalized()
+ .adjusted(-extra, -extra, extra, extra);
+}
+
+void Edge::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *)
+{
+ if (!source || !dest)
+ return;
+
+ QLineF line(sourcePoint, destPoint);
+ if (qFuzzyCompare(line.length(), qreal(0.)))
+ return;
+
+ // Draw the line itself
+ painter->setPen(QPen(Qt::black, 1, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin));
+ painter->drawLine(line);
+
+ // Draw the arrows
+ double angle = ::acos(line.dx() / line.length());
+ if (line.dy() >= 0)
+ angle = TwoPi - angle;
+
+ QPointF sourceArrowP1 = sourcePoint + QPointF(sin(angle + Pi / 3) * arrowSize,
+ cos(angle + Pi / 3) * arrowSize);
+ QPointF sourceArrowP2 = sourcePoint + QPointF(sin(angle + Pi - Pi / 3) * arrowSize,
+ cos(angle + Pi - Pi / 3) * arrowSize);
+ QPointF destArrowP1 = destPoint + QPointF(sin(angle - Pi / 3) * arrowSize,
+ cos(angle - Pi / 3) * arrowSize);
+ QPointF destArrowP2 = destPoint + QPointF(sin(angle - Pi + Pi / 3) * arrowSize,
+ cos(angle - Pi + Pi / 3) * arrowSize);
+
+ painter->setBrush(Qt::black);
+ painter->drawPolygon(QPolygonF() << line.p1() << sourceArrowP1 << sourceArrowP2);
+ painter->drawPolygon(QPolygonF() << line.p2() << destArrowP1 << destArrowP2);
+}
diff --git a/ground/src/plugins/config/mixercurveline.h b/ground/src/plugins/config/mixercurveline.h
new file mode 100644
index 000000000..540a36457
--- /dev/null
+++ b/ground/src/plugins/config/mixercurveline.h
@@ -0,0 +1,71 @@
+/**
+ ******************************************************************************
+ *
+ * @file mixercurveline.h
+ * @author Edouard Lafargue Copyright (C) 2010.
+ * Parts by Nokia Corporation (qt-info@nokia.com) Copyright (C) 2010.
+ * @addtogroup GCSPlugins GCS Plugins
+ * @{
+ * @addtogroup ConfigPlugin Configuration Plugin
+ * @{
+ * @brief A line connecting two mixer points
+ *****************************************************************************/
+/*
+ * 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
+ */
+
+/*
+ * This is inspired by the elastic nodes and edges demo in the Qt examples
+ * I have reinventing the wheel!
+ */
+
+#ifndef MIXERCURVELINE_H
+#define MIXERCURVELINE_H
+
+#include
+
+class Node;
+
+class Edge : public QGraphicsItem
+{
+public:
+ Edge(Node *sourceNode, Node *destNode);
+ ~Edge();
+
+ Node *sourceNode() const;
+ void setSourceNode(Node *node);
+
+ Node *destNode() const;
+ void setDestNode(Node *node);
+
+ void adjust();
+
+ enum { Type = UserType + 2 };
+ int type() const { return Type; }
+
+protected:
+ QRectF boundingRect() const;
+ void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);
+
+private:
+ Node *source, *dest;
+
+ QPointF sourcePoint;
+ QPointF destPoint;
+ qreal arrowSize;
+};
+
+#endif // MIXERCURVELINE_H
+
diff --git a/ground/src/plugins/config/mixercurvepoint.cpp b/ground/src/plugins/config/mixercurvepoint.cpp
new file mode 100644
index 000000000..127f2d825
--- /dev/null
+++ b/ground/src/plugins/config/mixercurvepoint.cpp
@@ -0,0 +1,173 @@
+/**
+ ******************************************************************************
+ *
+ * @file mixercurvepoint.h
+ * @author Edouard Lafargue Copyright (C) 2010.
+ * Parts by Nokia Corporation (qt-info@nokia.com) Copyright (C) 2010.
+ * @addtogroup GCSPlugins GCS Plugins
+ * @{
+ * @addtogroup ConfigPlugin Configuration Plugin
+ * @{
+ * @brief A point on the mixer curve
+ *****************************************************************************/
+/*
+ * 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
+#include
+#include
+#include
+
+#include "mixercurveline.h"
+#include "mixercurvepoint.h"
+#include "mixercurvewidget.h"
+
+Node::Node(MixerCurveWidget *graphWidget)
+ : graph(graphWidget)
+{
+ setFlag(ItemIsMovable);
+ setFlag(ItemSendsGeometryChanges);
+ setCacheMode(DeviceCoordinateCache);
+ setZValue(-1);
+}
+
+void Node::addEdge(Edge *edge)
+{
+ edgeList << edge;
+ edge->adjust();
+}
+
+QList Node::edges() const
+{
+ return edgeList;
+}
+
+void Node::calculateForces()
+{
+ if (!scene() || scene()->mouseGrabberItem() == this) {
+ newPos = pos();
+ return;
+ }
+
+ // Sum up all forces pushing this item away
+ qreal xvel = 0;
+ qreal yvel = 0;
+ foreach (QGraphicsItem *item, scene()->items()) {
+ Node *node = qgraphicsitem_cast(item);
+ if (!node)
+ continue;
+
+ QLineF line(mapFromItem(node, 0, 0), QPointF(0, 0));
+ qreal dx = line.dx();
+ qreal dy = line.dy();
+ double l = 2.0 * (dx * dx + dy * dy);
+ if (l > 0) {
+ xvel += (dx * 150.0) / l;
+ yvel += (dy * 150.0) / l;
+ }
+ }
+
+ // Now subtract all forces pulling items together
+ double weight = (edgeList.size() + 1) * 10;
+ foreach (Edge *edge, edgeList) {
+ QPointF pos;
+ if (edge->sourceNode() == this)
+ pos = mapFromItem(edge->destNode(), 0, 0);
+ else
+ pos = mapFromItem(edge->sourceNode(), 0, 0);
+ xvel += pos.x() / weight;
+ yvel += pos.y() / weight;
+ }
+
+ if (qAbs(xvel) < 0.1 && qAbs(yvel) < 0.1)
+ xvel = yvel = 0;
+
+ QRectF sceneRect = scene()->sceneRect();
+ newPos = pos() + QPointF(xvel, yvel);
+ newPos.setX(qMin(qMax(newPos.x(), sceneRect.left() + 10), sceneRect.right() - 10));
+ newPos.setY(qMin(qMax(newPos.y(), sceneRect.top() + 10), sceneRect.bottom() - 10));
+}
+
+bool Node::advance()
+{
+ if (newPos == pos())
+ return false;
+
+ setPos(newPos);
+ return true;
+}
+
+QRectF Node::boundingRect() const
+{
+ qreal adjust = 2;
+ return QRectF(-10 - adjust, -10 - adjust,
+ 23 + adjust, 23 + adjust);
+}
+
+QPainterPath Node::shape() const
+{
+ QPainterPath path;
+ path.addEllipse(-10, -10, 20, 20);
+ return path;
+}
+
+void Node::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *)
+{
+ painter->setPen(Qt::NoPen);
+ painter->setBrush(Qt::darkGray);
+ painter->drawEllipse(-7, -7, 20, 20);
+
+ QRadialGradient gradient(-3, -3, 10);
+ if (option->state & QStyle::State_Sunken) {
+ gradient.setCenter(3, 3);
+ gradient.setFocalPoint(3, 3);
+ gradient.setColorAt(1, QColor(Qt::yellow).light(120));
+ gradient.setColorAt(0, QColor(Qt::darkYellow).light(120));
+ } else {
+ gradient.setColorAt(0, Qt::yellow);
+ gradient.setColorAt(1, Qt::darkYellow);
+ }
+ painter->setBrush(gradient);
+ painter->setPen(QPen(Qt::black, 0));
+ painter->drawEllipse(-10, -10, 20, 20);
+}
+
+QVariant Node::itemChange(GraphicsItemChange change, const QVariant &value)
+{
+ switch (change) {
+ case ItemPositionHasChanged:
+ foreach (Edge *edge, edgeList)
+ edge->adjust();
+ graph->itemMoved();
+ break;
+ default:
+ break;
+ };
+
+ return QGraphicsItem::itemChange(change, value);
+}
+
+void Node::mousePressEvent(QGraphicsSceneMouseEvent *event)
+{
+ update();
+ QGraphicsItem::mousePressEvent(event);
+}
+
+void Node::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
+{
+ update();
+ QGraphicsItem::mouseReleaseEvent(event);
+}
diff --git a/ground/src/plugins/config/mixercurvepoint.h b/ground/src/plugins/config/mixercurvepoint.h
new file mode 100644
index 000000000..75de06543
--- /dev/null
+++ b/ground/src/plugins/config/mixercurvepoint.h
@@ -0,0 +1,71 @@
+/**
+ ******************************************************************************
+ *
+ * @file mixercurvepoint.h
+ * @author Edouard Lafargue Copyright (C) 2010.
+ * Parts by Nokia Corporation (qt-info@nokia.com) Copyright (C) 2010.
+ * @addtogroup GCSPlugins GCS Plugins
+ * @{
+ * @addtogroup ConfigPlugin Configuration Plugin
+ * @{
+ * @brief A point on the mixer curve
+ *****************************************************************************/
+/*
+ * 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 MIXERCURVEPOINT_H
+#define MIXERCURVEPOINT_H
+
+#include
+#include
+
+class Edge;
+class MixerCurveWidget;
+QT_BEGIN_NAMESPACE
+class QGraphicsSceneMouseEvent;
+QT_END_NAMESPACE
+
+class Node : public QGraphicsItem
+{
+public:
+ Node(MixerCurveWidget *graphWidget);
+
+ void addEdge(Edge *edge);
+ QList edges() const;
+
+ enum { Type = UserType + 1 };
+ int type() const { return Type; }
+
+ void calculateForces();
+ bool advance();
+
+ QRectF boundingRect() const;
+ QPainterPath shape() const;
+ void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);
+
+protected:
+ QVariant itemChange(GraphicsItemChange change, const QVariant &value);
+
+ void mousePressEvent(QGraphicsSceneMouseEvent *event);
+ void mouseReleaseEvent(QGraphicsSceneMouseEvent *event);
+
+private:
+ QList edgeList;
+ QPointF newPos;
+ MixerCurveWidget *graph;
+};
+
+#endif // MIXERCURVEPOINT_H
diff --git a/ground/src/plugins/config/mixercurvewidget.cpp b/ground/src/plugins/config/mixercurvewidget.cpp
new file mode 100644
index 000000000..a7cd15fb1
--- /dev/null
+++ b/ground/src/plugins/config/mixercurvewidget.cpp
@@ -0,0 +1,123 @@
+/**
+ ******************************************************************************
+ *
+ * @file mixercurvewidget.cpp
+ * @author Edouard Lafargue Copyright (C) 2010.
+ * @addtogroup GCSPlugins GCS Plugins
+ * @{
+ * @addtogroup ConfigPlugin Config Plugin
+ * @{
+ * @brief A widget which displays an adjustable mixer curve
+ *****************************************************************************/
+/*
+ * 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 "mixercurvewidget.h"
+#include "mixercurveline.h"
+#include "mixercurvepoint.h"
+
+#include
+#include
+
+
+
+/*
+ * Initialize the widget
+ */
+MixerCurveWidget::MixerCurveWidget(QWidget *parent) : QGraphicsView(parent)
+{
+
+ // Create a layout, add a QGraphicsView and put the SVG inside.
+ // The Mixer Curve widget looks like this:
+ // |--------------------|
+ // | |
+ // | |
+ // | Graph |
+ // | |
+ // | |
+ // | |
+ // |--------------------|
+
+
+ setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
+ setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
+ setRenderHint(QPainter::Antialiasing);
+
+ QGraphicsScene *scene = new QGraphicsScene(this);
+ QSvgRenderer *renderer = new QSvgRenderer();
+ plot = new QGraphicsSvgItem();
+ renderer->load(QString(":/configgadget/images/curve-bg.svg"));
+ plot->setSharedRenderer(renderer);
+ //plot->setElementId("map");
+ scene->addItem(plot);
+ plot->setZValue(-1);
+ scene->setSceneRect(plot->boundingRect());
+ setScene(scene);
+
+ Node *node1 = new Node(this);
+ Node *node2 = new Node(this);
+ Node *node3 = new Node(this);
+ Node *node4 = new Node(this);
+ Node *node5 = new Node(this);
+ scene->addItem(node1);
+ scene->addItem(node2);
+ scene->addItem(node3);
+ scene->addItem(node4);
+ scene->addItem(node5);
+
+ scene->addItem(new Edge(node1, node2));
+ scene->addItem(new Edge(node2, node3));
+ scene->addItem(new Edge(node3, node4));
+ scene->addItem(new Edge(node4, node5));
+
+ qreal w = plot->boundingRect().width()/5;
+
+ node1->setPos(w-w/2,50);
+ node2->setPos(2*w-w/2, 50);
+ node3->setPos(3*w-w/2, 50);
+ node4->setPos(4*w-w/2, 50);
+ node5->setPos(5*w-w/2, 50);
+
+
+}
+
+MixerCurveWidget::~MixerCurveWidget()
+{
+
+}
+
+void MixerCurveWidget::showEvent(QShowEvent *event)
+{
+ Q_UNUSED(event)
+ // Thit fitInView method should only be called now, once the
+ // widget is shown, otherwise it cannot compute its values and
+ // the result is usually a ahrsbargraph that is way too small.
+ fitInView(plot, Qt::KeepAspectRatio);
+
+}
+
+void MixerCurveWidget::resizeEvent(QResizeEvent* event)
+{
+ Q_UNUSED(event);
+ fitInView(plot, Qt::KeepAspectRatio);
+}
+
+
+
+void MixerCurveWidget::itemMoved()
+{
+
+}
diff --git a/ground/src/plugins/config/mixercurvewidget.h b/ground/src/plugins/config/mixercurvewidget.h
new file mode 100644
index 000000000..8f305bf09
--- /dev/null
+++ b/ground/src/plugins/config/mixercurvewidget.h
@@ -0,0 +1,59 @@
+/**
+ ******************************************************************************
+ *
+ * @file mixercurvewidget.h
+ * @author Edouard Lafargue Copyright (C) 2010.
+ * @addtogroup GCSPlugins GCS Plugins
+ * @{
+ * @addtogroup ConfigPlugin Configuration Plugin
+ * @{
+ * @brief A widget which displays a mixer curve
+ *****************************************************************************/
+/*
+ * 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 MIXERCURVEWIDGET_H_
+#define MIXERCURVEWIDGET_H_
+
+#include
+#include
+#include
+
+
+class MixerCurveWidget : public QGraphicsView
+{
+ Q_OBJECT
+
+public:
+ MixerCurveWidget(QWidget *parent = 0);
+ ~MixerCurveWidget();
+ void itemMoved();
+
+public slots:
+
+
+private slots:
+
+private:
+ QGraphicsSvgItem *plot;
+
+protected:
+ void showEvent(QShowEvent *event);
+ void resizeEvent(QResizeEvent *event);
+
+
+};
+#endif /* MIXERCURVEWIDGET_H_ */