Commit eef20c57 authored by LM's avatar LM

Working on starting version of video streamer

parent 3fec7e22
# Video streaming application for simple UDP direct byte streaming
QT += svg network
QT += svg network opengl
TEMPLATE = app
TARGET = qgcvideo
......@@ -24,18 +24,22 @@ INCLUDEPATH += . \
src/ui \
src/comm \
include/ui \
src/ui/mavlink \
src/apps/qgcstreamer
src/apps/qgcvideo \
# Input
HEADERS += src/apps/qgcvideo/QGCVideoApp.h
HEADERS += \
src/apps/qgcvideo/QGCVideoMainWindow.h \
src/apps/qgcvideo/QGCVideoApp.h \
src/apps/qgcvideo/QGCVideoWidget.h
SOURCES += \
src/apps/qgcvideo/main.cc \
src/apps/qgcvideo/QGCVideoMainWindow.cc \
src/apps/qgcvideo/QGCVideoApp.cc \
src/apps/qgcvideo/main.cc
src/apps/qgcvideo/QGCVideoWidget.cc
FORMS += \
src/apps/qgcvideo/QGCVideoApp.ui
src/apps/qgcvideo/QGCVideoMainWindow.ui
RESOURCES = mavground.qrc
/*=====================================================================
QGroundControl Open Source Ground Control Station
(c) 2009 - 2011 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
This file is part of the QGROUNDCONTROL project
QGROUNDCONTROL 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.
QGROUNDCONTROL 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 QGROUNDCONTROL. If not, see <http://www.gnu.org/licenses/>.
======================================================================*/
/**
* @file
* @brief Main executable
* @brief Implementation of main application class
*
* @author Lorenz Meier <lm@inf.ethz.ch>
*
*/
#include <QFile>
#include <QFlags>
#include <QThread>
#include <QSplashScreen>
#include <QPixmap>
#include <QDesktopWidget>
#include <QPainter>
#include <QStyleFactory>
#include <QAction>
#include <QSettings>
#include <QFontDatabase>
#include <QMainWindow>
#include "QGCVideoApp.h"
#include "ui_QGCVideoApp.h"
QGCVideoApp::QGCVideoApp(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::QGCVideoApp)
/**
* @brief Constructor for the main application.
*
* This constructor initializes and starts the whole application. It takes standard
* command-line parameters
*
* @param argc The number of command-line parameters
* @param argv The string array of parameters
**/
QGCVideoApp::QGCVideoApp(int &argc, char* argv[]) : QApplication(argc, argv)
{
ui->setupUi(this);
this->setApplicationName("QGC Video Streamer");
this->setApplicationVersion("v. 1.0.0 (Beta)");
this->setOrganizationName(QLatin1String("QGroundControl"));
this->setOrganizationDomain("http://qgroundcontrol.org");
QSettings::setDefaultFormat(QSettings::IniFormat);
// Exit main application when last window is closed
connect(this, SIGNAL(lastWindowClosed()), this, SLOT(quit()));
// Set application font
QFontDatabase fontDatabase = QFontDatabase();
const QString fontFileName = ":/general/vera.ttf"; ///< Font file is part of the QRC file and compiled into the app
const QString fontFamilyName = "Bitstream Vera Sans";
if(!QFile::exists(fontFileName)) printf("ERROR! font file: %s DOES NOT EXIST!\n", fontFileName.toStdString().c_str());
fontDatabase.addApplicationFont(fontFileName);
setFont(fontDatabase.font(fontFamilyName, "Roman", 12));
// Create main window
QMainWindow* window = new QMainWindow();
//window->setCentralWidget(new XMLCommProtocolWidget(window));
window->setWindowTitle(applicationName() + " " + applicationVersion());
window->show();
}
/**
* @brief Destructor for the groundstation. It destroys all loaded instances.
*
**/
QGCVideoApp::~QGCVideoApp()
{
delete ui;
}
/*=====================================================================
QGroundControl Open Source Ground Control Station
(c) 2009 - 2011 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
This file is part of the QGROUNDCONTROL project
QGROUNDCONTROL 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.
QGROUNDCONTROL 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 QGROUNDCONTROL. If not, see <http://www.gnu.org/licenses/>.
======================================================================*/
/**
* @file
* @brief Main executable
* @brief Definition of main application class
*
* @author Lorenz Meier <lm@inf.ethz.ch>
*
*/
#ifndef QGCVIDEOAPP_H
#define QGCVIDEOAPP_H
#include <QMainWindow>
#include <QApplication>
namespace Ui {
class QGCVideoApp;
}
class QGCVideoApp : public QMainWindow
/**
* @brief The main application and management class.
*
* This class is started by the main method and provides
* the central management unit of the groundstation application.
*
**/
class QGCVideoApp : public QApplication
{
Q_OBJECT
public:
explicit QGCVideoApp(QWidget *parent = 0);
QGCVideoApp(int &argc, char* argv[]);
~QGCVideoApp();
protected:
private:
Ui::QGCVideoApp *ui;
};
#endif // QGCVIDEOAPP_H
#endif /* QGCVIDEOAPP_H */
<ui version="4.0">
<author/>
<comment/>
<exportmacro/>
<class>QGCVideoApp</class>
<widget class="QMainWindow" name="QGCVideoApp">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>800</width>
<height>600</height>
</rect>
</property>
<property name="windowTitle">
<string>MainWindow</string>
</property>
<widget class="QMenuBar" name="menubar"/>
<widget class="QWidget" name="centralwidget"/>
<widget class="QStatusBar" name="statusbar"/>
</widget>
<pixmapfunction/>
<connections/>
</ui>
/*=====================================================================
QGroundControl Open Source Ground Control Station
(c) 2009 - 2011 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
This file is part of the QGROUNDCONTROL project
QGROUNDCONTROL 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.
QGROUNDCONTROL 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 QGROUNDCONTROL. If not, see <http://www.gnu.org/licenses/>.
======================================================================*/
/**
* @file
* @brief Implementation of main window
*
* @author Dominik Honegger
*
*/
#include "QGCVideoMainWindow.h"
#include "ui_QGCVideoMainWindow.h"
QGCVideoMainWindow::QGCVideoMainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::QGCVideoMainWindow)
{
ui->setupUi(this);
}
QGCVideoMainWindow::~QGCVideoMainWindow()
{
delete ui;
}
/*=====================================================================
QGroundControl Open Source Ground Control Station
(c) 2009 - 2011 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
This file is part of the QGROUNDCONTROL project
QGROUNDCONTROL 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.
QGROUNDCONTROL 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 QGROUNDCONTROL. If not, see <http://www.gnu.org/licenses/>.
======================================================================*/
/**
* @file
* @brief Definition of main window
*
* @author Dominik Honegger
*
*/
#ifndef QGCVIDEOMAINWINDOW_H
#define QGCVIDEOMAINWINDOW_H
#include <QMainWindow>
namespace Ui {
class QGCVideoMainWindow;
}
class QGCVideoMainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit QGCVideoMainWindow(QWidget *parent = 0);
~QGCVideoMainWindow();
private:
Ui::QGCVideoMainWindow *ui;
};
#endif // QGCVIDEOMAINWINDOW_H
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>QGCVideoMainWindow</class>
<widget class="QMainWindow" name="QGCVideoMainWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>800</width>
<height>600</height>
</rect>
</property>
<property name="windowTitle">
<string>MainWindow</string>
</property>
<widget class="QWidget" name="centralwidget">
<layout class="QGridLayout" name="gridLayout" rowstretch="1,100,1,100">
<item row="1" column="0">
<widget class="QGCVideoWidget" name="video1Widget" native="true"/>
</item>
<item row="1" column="1">
<widget class="QGCVideoWidget" name="video2Widget" native="true"/>
</item>
<item row="3" column="0">
<widget class="QGCVideoWidget" name="video3Widget" native="true"/>
</item>
<item row="3" column="1">
<widget class="QGCVideoWidget" name="video4Widget" native="true"/>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Video 1</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Video 2</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Video 3</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QLabel" name="label_4">
<property name="text">
<string>Video 4</string>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QMenuBar" name="menubar">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>800</width>
<height>22</height>
</rect>
</property>
</widget>
<widget class="QStatusBar" name="statusbar"/>
</widget>
<customwidgets>
<customwidget>
<class>QGCVideoWidget</class>
<extends>QWidget</extends>
<header>QGCVideoWidget.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>
This diff is collapsed.
#ifndef QGCVIDEOWIDGET_H
#define QGCVIDEOWIDGET_H
#include <QImage>
#include <QGLWidget>
#include <QPainter>
#include <QFontDatabase>
#include <QTimer>
/**
* @brief Video Display
*
* Displays video data from RAM via OpenGL
*/
class QGCVideoWidget : public QGLWidget
{
Q_OBJECT
public:
QGCVideoWidget(QWidget* parent = NULL);
~QGCVideoWidget();
void resizeGL(int w, int h);
public slots:
void initializeGL();
void saveImage();
void saveImage(QString fileName);
/** @brief Copy an image from an external buffer */
void copyImage(const QImage& img);
void enableHUDInstruments(bool enabled) { hudInstrumentsEnabled = enabled; }
protected slots:
void paintCenterBackground(float roll, float pitch, float yaw);
void paintRollPitchStrips();
void paintPitchLines(float pitch, QPainter* painter);
/** @brief Paint text on top of the image and OpenGL drawings */
void paintText(QString text, QColor color, float fontSize, float refX, float refY, QPainter* painter);
/** @brief Setup the OpenGL view for drawing a sub-component of the HUD */
void setupGLView(float referencePositionX, float referencePositionY, float referenceWidth, float referenceHeight);
void paintHUD();
void paintPitchLinePos(QString text, float refPosX, float refPosY, QPainter* painter);
void paintPitchLineNeg(QString text, float refPosX, float refPosY, QPainter* painter);
void drawLine(float refX1, float refY1, float refX2, float refY2, float width, const QColor& color, QPainter* painter);
void drawEllipse(float refX, float refY, float radiusX, float radiusY, float startDeg, float endDeg, float lineWidth, const QColor& color, QPainter* painter);
void drawCircle(float refX, float refY, float radius, float startDeg, float endDeg, float lineWidth, const QColor& color, QPainter* painter);
void drawChangeRateStrip(float xRef, float yRef, float height, float minRate, float maxRate, float value, QPainter* painter);
void drawChangeIndicatorGauge(float xRef, float yRef, float radius, float expectedMaxChange, float value, const QColor& color, QPainter* painter, bool solid=true);
void drawPolygon(QPolygonF refPolygon, QPainter* painter);
protected:
void commitRawDataToGL();
/** @brief Convert reference coordinates to screen coordinates */
float refToScreenX(float x);
/** @brief Convert reference coordinates to screen coordinates */
float refToScreenY(float y);
/** @brief Convert mm line widths to QPen line widths */
float refLineWidthToPen(float line);
/** @brief Rotate a polygon around a point clockwise */
void rotatePolygonClockWiseRad(QPolygonF& p, float angle, QPointF origin);
/** @brief Preferred Size */
QSize sizeHint() const;
/** @brief Start updating widget */
void showEvent(QShowEvent* event);
/** @brief Stop updating widget */
void hideEvent(QHideEvent* event);
void contextMenuEvent (QContextMenuEvent* event);
void createActions();
static const int updateInterval = 40;
QImage* image; ///< Double buffer image
QImage glImage; ///< The background / camera image
float yawInt; ///< The yaw integral. Used to damp the yaw indication.
QString mode; ///< The current vehicle mode
QString state; ///< The current vehicle state
QString fuelStatus; ///< Current fuel level / battery voltage
double scalingFactor; ///< Factor used to scale all absolute values to screen coordinates
float xCenterOffset, yCenterOffset; ///< Offset from center of window in mm coordinates
float vwidth; ///< Virtual width of this window, 200 mm per default. This allows to hardcode positions and aspect ratios. This virtual image plane is then scaled to the window size.
float vheight; ///< Virtual height of this window, 150 mm per default
float vGaugeSpacing; ///< Virtual spacing of the gauges from the center, 50 mm per default
float vPitchPerDeg; ///< Virtual pitch to mm conversion. Currently one degree is 3 mm up/down in the pitch markings
int xCenter; ///< Center of the HUD instrument in pixel coordinates. Allows to off-center the whole instrument in its OpenGL window, e.g. to fit another instrument
int yCenter; ///< Center of the HUD instrument in pixel coordinates. Allows to off-center the whole instrument in its OpenGL window, e.g. to fit another instrument
// Image buffers
unsigned char* rawBuffer1; ///< Double buffer 1 for the image
unsigned char* rawBuffer2; ///< Double buffer 2 for the image
unsigned char* rawImage; ///< Pointer to current complete image
int rawLastIndex; ///< The last byte index received of the image
int rawExpectedBytes; ///< Number of raw image bytes expected. Calculated by: image depth * channels * widht * height / 8
int bytesPerLine; ///< Bytes per image line. Is calculated as: image depth * channels * width / 8
bool imageStarted; ///< If an image is currently in transmission
int receivedDepth; ///< Image depth in bit for the current image
int receivedChannels; ///< Number of color channels
int receivedWidth; ///< Width in pixels of the current image
int receivedHeight; ///< Height in pixels of the current image
// HUD colors
QColor defaultColor; ///< Color for most HUD elements, e.g. pitch lines, center cross, change rate gauges
QColor setPointColor; ///< Color for the current control set point, e.g. yaw desired
QColor warningColor; ///< Color for warning messages
QColor criticalColor; ///< Color for caution messages
QColor infoColor; ///< Color for normal/default messages
QColor fuelColor; ///< Current color for the fuel message, can be info, warning or critical color
// Blink rates
int warningBlinkRate; ///< Blink rate of warning messages, will be rounded to the refresh rate
QTimer* refreshTimer; ///< The main timer, controls the update rate
QPainter* hudPainter;
QFont font; ///< The HUD font, per default the free Bitstream Vera SANS, which is very close to actual HUD fonts
QFontDatabase fontDatabase;///< Font database, only used to load the TrueType font file (the HUD font is directly loaded from file rather than from the system)
bool noCamera; ///< No camera images available, draw the ground/sky box to indicate the horizon
bool hardwareAcceleration; ///< Enable hardware acceleration
float strongStrokeWidth; ///< Strong line stroke width, used throughout the HUD
float normalStrokeWidth; ///< Normal line stroke width, used throughout the HUD
float fineStrokeWidth; ///< Fine line stroke width, used throughout the HUD
QString waypointName; ///< Waypoint name displayed in HUD
float roll;
float pitch;
float yaw;
float rollLP;
float pitchLP;
float yawLP;
double yawDiff;
double xPos;
double yPos;
double zPos;
double xSpeed;
double ySpeed;
double zSpeed;
quint64 lastSpeedUpdate;
double totalSpeed;
double totalAcc;
double lat;
double lon;
double alt;
float load;
QString offlineDirectory;
QString nextOfflineImage;
bool hudInstrumentsEnabled;
bool videoEnabled;
float xImageFactor;
float yImageFactor;
QAction* enableHUDAction;
QAction* enableVideoAction;
QAction* selectOfflineDirectoryAction;
QAction* selectVideoChannelAction;
void paintEvent(QPaintEvent *event);
bool imageRequested;
};
#endif // QGCVIDEOWIDGET_H
......@@ -80,15 +80,14 @@ DebugConsole::DebugConsole(QWidget *parent) :
//lineBufferTimer.setInterval(100); // 100 Hz
//lineBufferTimer.start();
loadSettings();
// Enable traffic measurements
connect(&snapShotTimer, SIGNAL(timeout()), this, SLOT(updateTrafficMeasurements()));
snapShotTimer.setInterval(snapShotInterval);
snapShotTimer.start();
// // Set hex checkbox checked
// m_ui->hexCheckBox->setChecked(!convertToAscii);
// m_ui->mavlinkCheckBox->setChecked(filterMAVLINK);
// m_ui->holdCheckBox->setChecked(autoHold);
// Update measurements the first time
updateTrafficMeasurements();
// Get a list of all existing links
links = QList<LinkInterface*>();
......@@ -114,17 +113,8 @@ DebugConsole::DebugConsole(QWidget *parent) :
connect(m_ui->addSymbolButton, SIGNAL(clicked()), this, SLOT(appendSpecialSymbol()));
// Connect Checkbox
connect(m_ui->specialComboBox, SIGNAL(highlighted(QString)), this, SLOT(specialSymbolSelected(QString)));
// Set add button invisible if auto add checkbox is checked
//connect(m_ui->specialCheckBox, SIGNAL(clicked(bool)), m_ui->addSymbolButton, SLOT(setHidden(bool)));
// Allow to send via return
connect(m_ui->sendText, SIGNAL(returnPressed()), this, SLOT(sendBytes()));
loadSettings();
// // Warn user about not activated hold
// if (!m_ui->holdCheckBox->isChecked()) {
// m_ui->receiveText->appendHtml(QString("<font color=\"%1\">%2</font>\n").arg(QColor(Qt::red).name(), tr("WARNING: You have NOT enabled auto-hold (stops updating the console if huge amounts of serial data arrive). Updating the console consumes significant CPU load, so if you receive more than about 5 KB/s of serial data, make sure to enable auto-hold if not using the console.")));
// }
}
void DebugConsole::hideEvent(QHideEvent* event)
......
......@@ -52,7 +52,7 @@ WaypointList::WaypointList(QWidget *parent, UASInterface* uas) :
m_ui->setupUi(this);
listLayout = new QVBoxLayout(m_ui->listWidget);
listLayout->setSpacing(6);
listLayout->setSpacing(0);
listLayout->setMargin(0);
listLayout->setAlignment(Qt::AlignTop);
m_ui->listWidget->setLayout(listLayout);
......
......@@ -129,6 +129,8 @@ void WaypointView::changedAutoContinue(int state)
void WaypointView::updateActionView(int action)
{
// Remove stretch item at index 17 (m_ui->removeSpacer)
m_ui->horizontalLayout->takeAt(17);
// expose ui based on action
switch(action) {
......@@ -140,6 +142,7 @@ void WaypointView::updateActionView(int action)
m_ui->holdTimeSpinBox->hide();
m_ui->acceptanceSpinBox->hide();
m_ui->customActionWidget->hide();
m_ui->horizontalLayout->insertStretch(17, 82);
m_ui->takeOffAngleSpinBox->show();
break;
case MAV_CMD_NAV_LAND:
......@@ -151,6 +154,7 @@ void WaypointView::updateActionView(int action)
m_ui->holdTimeSpinBox->hide();
m_ui->acceptanceSpinBox->hide();
m_ui->customActionWidget->hide();
m_ui->horizontalLayout->insertStretch(17, 26);
break;
case MAV_CMD_NAV_RETURN_TO_LAUNCH:
m_ui->orbitSpinBox->hide();
......@@ -161,6 +165,7 @@ void WaypointView::updateActionView(int action)
m_ui->holdTimeSpinBox->hide();
m_ui->acceptanceSpinBox->hide();
m_ui->customActionWidget->hide();
m_ui->horizontalLayout->insertStretch(17, 26);
break;
case MAV_CMD_NAV_WAYPOINT:
m_ui->orbitSpinBox->hide();
......@@ -168,6 +173,7 @@ void WaypointView::updateActionView(int action)
m_ui->turnsSpinBox->hide();
m_ui->holdTimeSpinBox->show();
m_ui->customActionWidget->hide();
m_ui->horizontalLayout->insertStretch(17, 1);
m_ui->autoContinue->show();
m_ui->acceptanceSpinBox->show();
......@@ -181,6 +187,7 @@ void WaypointView::updateActionView(int action)
m_ui->holdTimeSpinBox->hide();
m_ui->acceptanceSpinBox->hide();
m_ui->customActionWidget->hide();
m_ui->horizontalLayout->insertStretch(17, 25);
m_ui->orbitSpinBox->show();
break;
case MAV_CMD_NAV_LOITER_TURNS:
......@@ -190,6 +197,7 @@ void WaypointView::updateActionView(int action)
m_ui->holdTimeSpinBox->hide();
m_ui->acceptanceSpinBox->hide();
m_ui->customActionWidget->hide();
m_ui->horizontalLayout->insertStretch(17, 20);
m_ui->orbitSpinBox->show();
m_ui->turnsSpinBox->show();
break;
......@@ -200,6 +208,7 @@ void WaypointView::updateActionView(int action)
m_ui->autoContinue->hide();
m_ui->acceptanceSpinBox->hide();
m_ui->customActionWidget->hide();
m_ui->horizontalLayout->insertStretch(17, 20);
m_ui->orbitSpinBox->show();
m_ui->holdTimeSpinBox->show();
break;
......@@ -527,6 +536,38 @@ void WaypointView::updateValues()
}
wp->blockSignals(false);
QColor backGroundColor = QGC::colorBackground;
static int lastId = -1;
int currId = wp->getId() % 2;
if (currId != lastId)
{
qDebug() << "COLOR ID: " << currId;
if (currId == 1)
{
//backGroundColor = backGroundColor.lighter(150);
backGroundColor = QColor("#252528").lighter(150);
}
else
{
backGroundColor = QColor("#252528").lighter(250);
}
qDebug() << "COLOR:" << backGroundColor.name();
// Update color based on id
QString groupBoxStyle = QString("QGroupBox {padding: 0px; margin: 0px; border: 0px; background-color: %1; }").arg(backGroundColor.name());
QString labelStyle = QString("QWidget {background-color: %1; color: #DDDDDF; border-color: #EEEEEE; }").arg(backGroundColor.name());
QString checkBoxStyle = QString("QCheckBox {background-color: %1; color: #454545; border-color: #EEEEEE; }").arg(backGroundColor.name());
m_ui->autoContinue->setStyleSheet(checkBoxStyle);
m_ui->selectedBox->setStyleSheet(checkBoxStyle);
m_ui->idLabel->setStyleSheet(labelStyle);