Commit aa5f67d4 authored by lm's avatar lm

Merge branch 'dev-mac' of github.com:pixhawk/qgroundcontrol into dev-mac

parents 10ad437c 33da8692
......@@ -8,7 +8,6 @@ Info.plist
obj
*.log
*~
*qtc*
bin/*.exe
bin/*.txt
bin/mac
......
......@@ -28,7 +28,7 @@ do
elif [ $OPT = "grab_debian_dependencies" ] &> /dev/null
then
echo you chose to install debian dependencies
sudo apt-get install cmake libqt4-dev flite1-dev libphonon-dev libopenscenegraph-dev
sudo apt-get install cmake libqt4-dev flite1-dev libphonon-dev libopenscenegraph-dev libsdl1.2-dev
exit 0
elif [ $OPT = "remake" ] &> /dev/null
......
Name "QGroundcontrol"
OutFile "qgroundcontrol-installer-win32.exe"
InstallDir $PROGRAMFILES\qgroundcontrol
Page license
Page directory
Page components
Page instfiles
UninstPage uninstConfirm
UninstPage instfiles
LicenseData ..\license.txt
Section ""
SetOutPath $INSTDIR
File ..\release\*.*
WriteUninstaller $INSTDIR\QGroundControl_uninstall.exe
SectionEnd
Section "Uninstall"
Delete $INSTDIR\QGroundControl_uninstall.exe
Delete $INSTDIR\*.*
RMDir $INSTDIR
Delete "$SMPROGRAMS\QGroundControl\*.*"
RMDir "$SMPROGRAMS\QGroundControl\"
SectionEnd
Section "create Start Menu Shortcuts"
CreateDirectory "$SMPROGRAMS\QGroundControl"
CreateShortCut "$SMPROGRAMS\QGroundControl\uninstall.lnk" "$INSTDIR\QGroundControl_uninstall.exe" "" "$INSTDIR\QGroundControl_uninstall.exe" 0
CreateShortCut "$SMPROGRAMS\QGroundControl\QGroundControl.lnk" "$INSTDIR\qgroundcontrol.exe" "" "$INSTDIR\qgroundcontrol.exe" 0
SectionEnd
\ No newline at end of file
......@@ -65,6 +65,10 @@ var trailPlacemarks = [];
var trailsVisible = [];
var trailColors = [];
var waypoints = [];
var waypointLines = [];
var waypointLinePlacemarks = [];
var waypointLineColors = [];
//var waypointLines = [];
//var trailPlacemarks[id];
var lineStyle;
......@@ -362,6 +366,8 @@ function updateWaypoint(id, index, lat, lon, alt, action)
location.setAltitude(alt);
waypoints[index].setGeometry(location);
waypoints[index].setDescription(index+"");
}
else
{
......@@ -388,7 +394,26 @@ function updateWaypoint(id, index, lat, lon, alt, action)
// Add the placemark to Earth.
ge.getFeatures().appendChild(placemark);
waypoints[index] = placemark;
}
}
// Add waypoint line
waypointLines[id].setExtrude(false);
waypointLines[id].setAltitudeMode(ge.ALTITUDE_ABSOLUTE);
// Add LineString points
waypointLines[id].getCoordinates().pushLatLngAlt(lat, lon, alt);
// Create a style and set width and color of line
waypointLinePlacemarks[id].setStyleSelector(ge.createStyle(''));
lineStyle = waypointLinePlacemarks[id].getStyleSelector().getLineStyle();
lineStyle.setWidth(5);
lineStyle.getColor().set(waypointLineColors[id]);  // aabbggrr format
//lineStyle.getColor().set(color);  // aabbggrr format
// Add the feature to Earth
//if (waypointLinesVisible[id] == true)
ge.getFeatures().replaceChild(waypointLinePlacemarks[id], waypointLinePlacemarks[id]);
// Add connecting line
}
......@@ -423,6 +448,7 @@ function createAircraft(id, type, color)
//planeColor = color;
createTrail(id, color);
createWaypointLine(id, color);
//console.log(color);
}
......@@ -454,6 +480,32 @@ trailsVisible[id] = false;
}
function createWaypointLine(id, color)
{
waypointLinePlacemarks[id] = ge.createPlacemark('');
// Create the placemark
// Create the LineString; set it to extend down to the ground
// and set the altitude mode
waypointLines[id] = ge.createLineString('');
waypointLinePlacemarks[id].setGeometry(waypointLines[id]);
waypointLines[id].setExtrude(false);
waypointLines[id].setAltitudeMode(ge.ALTITUDE_ABSOLUTE);
// Add LineString points
//lineString.getCoordinates().pushLatLngAlt(48.754, -121.835, 700);
// Create a style and set width and color of line
waypointLinePlacemarks[id].setStyleSelector(ge.createStyle(''));
lineStyle = waypointLinePlacemarks[id].getStyleSelector().getLineStyle();
lineStyle.setWidth(10);
waypointLineColors[id] = color;
lineStyle.getColor().set('00000000');  // aabbggrr format
// Add the feature to Earth
//ge.getFeatures().appendChild(trailPlacemarks[id]);
}
function clearTrail(id)
{
ge.getFeatures().removeChild(trailPlacemarks[id]);
......
images/splash.png

27.8 KB | W: | H:

images/splash.png

25.5 KB | W: | H:

images/splash.png
images/splash.png
images/splash.png
images/splash.png
  • 2-up
  • Swipe
  • Onion skin
......@@ -39,9 +39,12 @@
#include <QFont>
#include <QObject>
#include "waypointitem.h"
#include "configuration.h"
//#include "uavitem.h"
namespace mapcontrol
{
using namespace mapcontrol;
class OPMapWidget;
/**
* @brief The main graphicsItem used on the widget, contains the map and map logic
......
......@@ -37,6 +37,7 @@
#include <QtOpenGL/QGLWidget>
#include "waypointitem.h"
#include "QtSvg/QGraphicsSvgItem"
#include "configuration.h"
#include "uavitem.h"
#include "gpsitem.h"
#include "homeitem.h"
......@@ -168,7 +169,7 @@ namespace mapcontrol
* @param config pointer to configuration classed to be used
* @return
*/
OPMapWidget(QWidget *parent=0,Configuration *config=new Configuration);
OPMapWidget(QWidget *parent=0, mapcontrol::Configuration *config=new mapcontrol::Configuration());
~OPMapWidget();
/**
......
......@@ -37,12 +37,12 @@ HEADERS += src/standalone/mavlinkgen/MAVLinkGen.h \
src/comm/MAVLinkXMLParser.h \
src/ui/mavlink/DomItem.h \
src/ui/mavlink/DomModel.h \
src/comm/MAVLinkSyntaxHighlighter.h
src/ui/mavlink/QGCMAVLinkTextEdit.h
SOURCES += src/standalone/mavlinkgen/main.cc \
src/standalone/mavlinkgen/MAVLinkGen.cc \
src/ui/XMLCommProtocolWidget.cc \
src/ui/mavlink/DomItem.cc \
src/ui/mavlink/DomModel.cc \
src/comm/MAVLinkXMLParser.cc \
src/comm/MAVLinkSyntaxHighlighter.cc
src/ui/mavlink/QGCMAVLinkTextEdit.cc
RESOURCES = mavground.qrc
# Video streaming application for simple UDP direct byte streaming
QT += svg network opengl
TEMPLATE = app
TARGET = qgcvideo
BASEDIR = .
BUILDDIR = build/qgcvideo
LANGUAGE = C++
CONFIG += release
CONFIG -= debug
OBJECTS_DIR = $$BUILDDIR/obj
MOC_DIR = $$BUILDDIR/moc
UI_HEADERS_DIR = src/ui/generated
macx:DESTDIR = $$BASEDIR/bin/mac
INCLUDEPATH += . \
src \
src/ui \
src/comm \
include/ui \
src/apps/qgcvideo \
# Input
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/QGCVideoWidget.cc
FORMS += \
src/apps/qgcvideo/QGCVideoMainWindow.ui
RESOURCES = mavground.qrc
......@@ -29,7 +29,7 @@
# $$BASEDIR/lib/openjaus/libopenJaus/include
message(Qt version $$[QT_VERSION])
message(Using Qt from $QTDIR)
message(Using Qt from $$[QTDIR])
release {
# DEFINES += QT_NO_DEBUG_OUTPUT
......@@ -340,7 +340,8 @@ win32-msvc2008 {
#"C:\Program Files\Microsoft SDKs\Windows\v7.0\Include"
LIBS += -L$$BASEDIR/lib/sdl/msvc/lib \
-lSDLmain -lSDL
-lSDLmain -lSDL \
-lsetupapi
exists($$BASEDIR/lib/osg123) {
message("Building support for OSG")
......@@ -403,7 +404,8 @@ win32-g++ {
#"C:\Program Files\Microsoft SDKs\Windows\v7.0\Include"
LIBS += -L$$BASEDIR/lib/sdl/win32 \
-lmingw32 -lSDLmain -lSDL -mwindows
-lmingw32 -lSDLmain -lSDL -mwindows \
-lsetupapi
CONFIG += windows
......
# -------------------------------------------------
# QGroundControl - Micro Air Vehicle Groundstation
# Please see our website at <http://qgroundcontrol.org>
# Author:
# Lorenz Meier <mavteam@student.ethz.ch>
# (c) 2009-2010 PIXHAWK Team
# This file is part of the mav groundstation project
# Maintainer:
# Lorenz Meier <lm@inf.ethz.ch>
# (c) 2009-2011 QGroundControl Developers
# This file is part of the open groundstation 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
......@@ -23,18 +23,57 @@
# Version from GIT repository is preferred
# include ( "../qmapcontrol/QMapControl/QMapControl.pri" ) #{
# Include bundled version if necessary
include(lib/QMapControl/QMapControl.pri)
# include(lib/QMapControl/QMapControl.pri)
include(lib/nmea/nmea.pri)
#include(lib/opmapcontrol/opmapcontrol.pri)
# This is a HACK - linking to openpilot repo for now
# OPMapControl is a OpenPilot-independent map library
# provided by the OpenPilot team - thanks, great piece
# of open-source software!
# (We're not reusing any part of the OP GCS, just the map library)
# Try to get it from OP mainline, if this fails fall back to internal copies
exists(../openpilot/ground/openpilotgcs/src/libs) {
include(../openpilot/ground/openpilotgcs/src/libs/utils/utils_external.pri)
include(../openpilot/ground/openpilotgcs/src/libs/opmapcontrol/opmapcontrol_external.pri)
DEPENDPATH += \
../openpilot/ground/openpilotgcs/src/libs/utils \
../openpilot/ground/openpilotgcs/src/libs/utils/src \
../openpilot/ground/openpilotgcs/src/libs/opmapcontrol \
../openpilot/ground/openpilotgcs/src/libs/opmapcontrol/src
INCLUDEPATH += \
../openpilot/ground/openpilotgcs/src/libs/utils \
../openpilot/ground/openpilotgcs/src/libs \
../openpilot/ground/openpilotgcs/src/libs/opmapcontrol
message("----- USING MAINLINE OPENPILOT FROM ../openpilot -----")
message("Using OpenPilot's mapcontrol library from external folder")
message("------------------------------------------------------------------------")
} else {
include(src/libs/utils/utils_external.pri)
include(src/libs/opmapcontrol/opmapcontrol_external.pri)
DEPENDPATH += \
src/libs/utils \
src/libs/utils/src \
src/libs/opmapcontrol \
src/libs/opmapcontrol/src
INCLUDEPATH += \
src/libs/utils \
src/libs \
src/libs/opmapcontrol
}
# include(lib/opmapcontrol/opmapcontrol.pri)
# message("Including bundled QMapControl version as FALLBACK. This is fine on Linux and MacOS, but not the best choice in Windows")
QT += network \
opengl \
svg \
xml \
phonon \
webkit
webkit \
sql
TEMPLATE = app
TARGET = qgroundcontrol
BASEDIR = $$IN_PWD
......@@ -56,7 +95,6 @@ exists(user_config.pri) {
message("Adding support for additional MAVLink messages for: " $$MAVLINK_CONF)
message("------------------------------------------------------------------------")
}
INCLUDEPATH += $$BASEDIR/../mavlink/include/common
INCLUDEPATH += $$BASEDIR/../mavlink/include
INCLUDEPATH += $$BASEDIR/thirdParty/mavlink/include/common
......@@ -111,26 +149,27 @@ include(qgroundcontrol.pri)
# Include QWT plotting library
include(src/lib/qwt/qwt.pri)
DEPENDPATH += . \
lib/QMapControl \
lib/QMapControl/src \
lib/opmapcontrol \
lib/opmapcontrol/src \
plugins \
thirdParty/qserialport/include \
thirdParty/qserialport/include/QtSerialPort \
thirdParty/qserialport
thirdParty/qserialport \
src/libs/qextserialport
INCLUDEPATH += . \
lib/QMapControl \
lib/opmapcontrol \
thirdParty/qserialport/include \
thirdParty/qserialport/include/QtSerialPort \
thirdParty/qserialport/src
thirdParty/qserialport/src \
src/libs/qextserialport
# Include serial port library
include(src/lib/qextserialport/qextserialport.pri)
# include(src/lib/qextserialport/qextserialport.pri)
# include qserial library
include(thirdParty/qserialport/qgroundcontrol-qserialport.pri)
# Serial port detection
macx::SOURCES += src/libs/qextserialport/qextserialenumerator_osx.cpp
linux-g++::SOURCES += src/libs/qextserialport/qextserialenumerator_unix.cpp
win32::SOURCES += src/libs/qextserialport/qextserialenumerator_win.cpp
# ../mavlink/include \
# MAVLink/include \
......@@ -150,7 +189,6 @@ FORMS += src/ui/MainWindow.ui \
src/ui/ObjectDetectionView.ui \
src/ui/JoystickWidget.ui \
src/ui/DebugConsole.ui \
src/ui/MapWidget.ui \
src/ui/XMLCommProtocolWidget.ui \
src/ui/HDDisplay.ui \
src/ui/MAVLinkSettingsWidget.ui \
......@@ -181,8 +219,9 @@ FORMS += src/ui/MainWindow.ui \
src/ui/QGCSettingsWidget.ui \
src/ui/UASControlParameters.ui \
src/ui/mission/QGCMissionDoWidget.ui \
src/ui/mission/QGCMissionConditionWidget.ui
src/ui/mission/QGCMissionConditionWidget.ui \
src/ui/map/QGCMapTool.ui \
src/ui/map/QGCMapToolBar.ui
INCLUDEPATH += src \
src/ui \
src/ui/linechart \
......@@ -198,16 +237,14 @@ INCLUDEPATH += src \
src/ui/watchdog \
src/ui/map3D \
src/ui/designer
HEADERS += src/MG.h \
src/Core.h \
src/QGCCore.h \
src/uas/UASInterface.h \
src/uas/UAS.h \
src/uas/UASManager.h \
src/comm/LinkManager.h \
src/comm/LinkInterface.h \
src/comm/SerialLinkInterface.h \
src/comm/SerialInterface.h \
src/comm/SerialLink.h \
src/comm/SerialSimulationLink.h \
src/comm/ProtocolInterface.h \
......@@ -237,7 +274,6 @@ HEADERS += src/MG.h \
src/input/JoystickInput.h \
src/ui/JoystickWidget.h \
src/ui/DebugConsole.h \
src/ui/MapWidget.h \
src/ui/XMLCommProtocolWidget.h \
src/ui/mavlink/DomItem.h \
src/ui/mavlink/DomModel.h \
......@@ -264,8 +300,6 @@ HEADERS += src/MG.h \
src/ui/QGCPxImuFirmwareUpdate.h \
src/ui/QGCDataPlot2D.h \
src/ui/linechart/IncrementalPlot.h \
src/ui/map/Waypoint2DIcon.h \
src/ui/map/MAV2DIcon.h \
src/ui/QGCRemoteControlView.h \
src/ui/RadioCalibration/RadioCalibrationData.h \
src/ui/RadioCalibration/RadioCalibrationWindow.h \
......@@ -297,13 +331,17 @@ HEADERS += src/MG.h \
src/ui/uas/UASControlParameters.h \
src/ui/mission/QGCMissionDoWidget.h \
src/ui/mission/QGCMissionConditionWidget.h \
src/uas/QGCUASParamManager.h
src/uas/QGCUASParamManager.h \
src/ui/map/QGCMapWidget.h \
src/ui/map/MAV2DIcon.h \
src/ui/map/Waypoint2DIcon.h \
src/ui/mavlink/QGCMAVLinkTextEdit.h \
src/ui/map/QGCMapTool.h \
src/ui/map/QGCMapToolBar.h \
src/libs/qextserialport/qextserialenumerator.h
# Google Earth is only supported on Mac OS and Windows with Visual Studio Compiler
macx|win32-msvc2008: {
HEADERS += src/ui/map3D/QGCGoogleEarthView.h
}
macx|win32-msvc2008::HEADERS += src/ui/map3D/QGCGoogleEarthView.h
contains(DEPENDENCIES_PRESENT, osg) {
message("Including headers for OpenSceneGraph")
......@@ -335,9 +373,8 @@ contains(DEPENDENCIES_PRESENT, libfreenect) {
# Enable only if libfreenect is available
HEADERS += src/input/Freenect.h
}
SOURCES += src/main.cc \
src/Core.cc \
src/QGCCore.cc \
src/uas/UASManager.cc \
src/uas/UAS.cc \
src/comm/LinkManager.cc \
......@@ -368,7 +405,6 @@ SOURCES += src/main.cc \
src/input/JoystickInput.cc \
src/ui/JoystickWidget.cc \
src/ui/DebugConsole.cc \
src/ui/MapWidget.cc \
src/ui/XMLCommProtocolWidget.cc \
src/ui/mavlink/DomItem.cc \
src/ui/mavlink/DomModel.cc \
......@@ -395,8 +431,6 @@ SOURCES += src/main.cc \
src/ui/QGCPxImuFirmwareUpdate.cc \
src/ui/QGCDataPlot2D.cc \
src/ui/linechart/IncrementalPlot.cc \
src/ui/map/Waypoint2DIcon.cc \
src/ui/map/MAV2DIcon.cc \
src/ui/QGCRemoteControlView.cc \
src/ui/RadioCalibration/RadioCalibrationWindow.cc \
src/ui/RadioCalibration/AirfoilServoCalibrator.cc \
......@@ -427,12 +461,14 @@ SOURCES += src/main.cc \
src/ui/uas/UASControlParameters.cpp \
src/ui/mission/QGCMissionDoWidget.cc \
src/ui/mission/QGCMissionConditionWidget.cc \
src/uas/QGCUASParamManager.cc
macx|win32-msvc2008: {
SOURCES += src/ui/map3D/QGCGoogleEarthView.cc
}
src/uas/QGCUASParamManager.cc \
src/ui/map/QGCMapWidget.cc \
src/ui/map/MAV2DIcon.cc \
src/ui/map/Waypoint2DIcon.cc \
src/ui/mavlink/QGCMAVLinkTextEdit.cc \
src/ui/map/QGCMapTool.cc \
src/ui/map/QGCMapToolBar.cc
macx|win32-msvc2008::SOURCES += src/ui/map3D/QGCGoogleEarthView.cc
contains(DEPENDENCIES_PRESENT, osg) {
message("Including sources for OpenSceneGraph")
......@@ -450,9 +486,7 @@ contains(DEPENDENCIES_PRESENT, osg) {
src/ui/map3D/Texture.cc \
src/ui/map3D/Imagery.cc \
src/ui/map3D/HUDScaleGeode.cc \
src/ui/map3D/WaypointGroupNode.cc \
src/ui/map3D/WaypointGroupNode.cc
contains(DEPENDENCIES_PRESENT, osgearth) {
message("Including sources for osgEarth")
......@@ -469,7 +503,7 @@ contains(DEPENDENCIES_PRESENT, libfreenect) {
RESOURCES += mavground.qrc
# Include RT-LAB Library
win32:exists(src/lib/opalrt/OpalApi.h):exists(C:/OPAL-RT/RT-LAB7.2.4/Common/bin) {
win32:exists(src/lib/opalrt/OpalApi.h):exists(C:/OPAL-RT/RT-LAB7.2.4/Common/bin) {
message("Building support for Opal-RT")
LIBS += -LC:/OPAL-RT/RT-LAB7.2.4/Common/bin \
-lOpalApi
......@@ -489,6 +523,5 @@ win32:exists(src/lib/opalrt/OpalApi.h):exists(C:/OPAL-RT/RT-LAB7.2.4/Common/bin)
FORMS += src/ui/OpalLinkSettings.ui
DEFINES += OPAL_RT
}
TRANSLATIONS += es-MX.ts \
TRANSLATIONS += es-MX.ts \
en-US.ts
......@@ -2,7 +2,7 @@
QGroundControl Open Source Ground Control Station
(c) 2009, 2010 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
(c) 2009 - 2011 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
This file is part of the QGROUNDCONTROL project
......
/*=====================================================================
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/>.
======================================================================*/
#ifndef QGC_H
#define QGC_H
......
......@@ -23,7 +23,7 @@ This file is part of the QGROUNDCONTROL project
/**
* @file
* @brief Implementation of class Core
* @brief Implementation of class QGCCore
*
* @author Lorenz Meier <mavteam@student.ethz.ch>
*
......@@ -43,7 +43,7 @@ This file is part of the QGROUNDCONTROL project
#include "configuration.h"
#include "QGC.h"
#include "Core.h"
#include "QGCCore.h"
#include "MG.h"
#include "MainWindow.h"
#include "GAudioOutput.h"
......@@ -66,7 +66,7 @@ This file is part of the QGROUNDCONTROL project
**/
Core::Core(int &argc, char* argv[]) : QApplication(argc, argv)
QGCCore::QGCCore(int &argc, char* argv[]) : QApplication(argc, argv)
{
......@@ -201,7 +201,7 @@ Core::Core(int &argc, char* argv[]) : QApplication(argc, argv)
* @brief Destructor for the groundstation. It destroys all loaded instances.
*
**/
Core::~Core()
QGCCore::~QGCCore()
{
//mainWindow->storeSettings();
mainWindow->hide();
......@@ -217,7 +217,7 @@ Core::~Core()
* The link manager keeps track of all communication links and provides the global
* packet queue. It is the main communication hub
**/
void Core::startLinkManager()
void QGCCore::startLinkManager()
{
LinkManager::instance();
}
......@@ -226,7 +226,7 @@ void Core::startLinkManager()
* @brief Start the Unmanned Air System Manager
*
**/
void Core::startUASManager()
void QGCCore::startUASManager()
{
// Load UAS plugins
QDir pluginsDir = QDir(qApp->applicationDirPath());
......
......@@ -30,8 +30,8 @@ This file is part of the PIXHAWK project
*/
#ifndef _CORE_H_
#define _CORE_H_
#ifndef QGC_CORE_H
#define QGC_CORE_H
#include <QApplication>
......@@ -51,13 +51,13 @@ This file is part of the PIXHAWK project
* the central management unit of the groundstation application.
*
**/
class Core : public QApplication
class QGCCore : public QApplication
{
Q_OBJECT
public:
Core(int &argc, char* argv[]);
~Core();
QGCCore(int &argc, char* argv[]);
~QGCCore();
protected:
void startLinkManager();
......@@ -71,7 +71,6 @@ protected:
private:
MainWindow* mainWindow;
//ViconTarsusProtocol* tarsus;
};
#endif /* _CORE_H_ */
......@@ -35,7 +35,7 @@ This file is part of the QGROUNDCONTROL project
#include "Waypoint.h"
Waypoint::Waypoint(quint16 _id, double _x, double _y, double _z, double _param1, double _param2, double _param3, double _param4,
bool _autocontinue, bool _current, MAV_FRAME _frame, MAV_CMD _action)
bool _autocontinue, bool _current, MAV_FRAME _frame, MAV_CMD _action, const QString& _description)
: id(_id),
x(_x),
y(_y),
......@@ -48,7 +48,9 @@ Waypoint::Waypoint(quint16 _id, double _x, double _y, double _z, double _param1,
orbit(_param3),
param1(_param1),
param2(_param2),
name(QString("WP%1").arg(id, 2, 10, QChar('0')))
name(QString("WP%1").arg(id, 2, 10, QChar('0'))),
description(_description),
reachedTime(0)
{
}
......@@ -70,9 +72,9 @@ void Waypoint::save(QTextStream &saveStream)
position = position.arg(z, 0, 'g', 18);
QString parameters("%1\t%2\t%3\t%4");
parameters = parameters.arg(param1, 0, 'g', 18).arg(param2, 0, 'g', 18).arg(orbit, 0, 'g', 18).arg(yaw, 0, 'g', 18);
// FORMAT: <INDEX> <CURRENT WP> <COORD FRAME> <COMMAND> <PARAM1> <PARAM2> <PARAM3> <PARAM4> <PARAM5/X/LONGITUDE> <PARAM6/Y/LATITUDE> <PARAM7/Z/ALTITUDE> <AUTOCONTINUE>
// FORMAT: <INDEX> <CURRENT WP> <COORD FRAME> <COMMAND> <PARAM1> <PARAM2> <PARAM3> <PARAM4> <PARAM5/X/LONGITUDE> <PARAM6/Y/LATITUDE> <PARAM7/Z/ALTITUDE> <AUTOCONTINUE> <DESCRIPTION>
// as documented here: http://qgroundcontrol.org/waypoint_protocol
saveStream << this->getId() << "\t" << this->getCurrent() << "\t" << this->getFrame() << "\t" << this->getAction() << "\t" << parameters << "\t" << position << "\t" << this->getAutoContinue() << "\r\n";
saveStream << this->getId() << "\t" << this->getCurrent() << "\t" << this->getFrame() << "\t" << this->getAction() << "\t" << parameters << "\t" << position << "\t" << this->getAutoContinue() << "\r\n"; //"\t" << this->getDescription() << "\r\n";
}
bool Waypoint::load(QTextStream &loadStream)
......@@ -91,6 +93,7 @@ bool Waypoint::load(QTextStream &loadStream)
this->y = wpParams[9].toDouble();
this->z = wpParams[10].toDouble();
this->autocontinue = (wpParams[11].toInt() == 1 ? true : false);
//this->description = wpParams[12];
return true;
}
return false;
......@@ -106,7 +109,7 @@ void Waypoint::setId(quint16 id)
void Waypoint::setX(double x)
{
if (this->x != x) {
if (this->x != x && (this->frame == MAV_FRAME_LOCAL)) {
this->x = x;
emit changed(this);
}
......@@ -114,7 +117,7 @@ void Waypoint::setX(double x)
void Waypoint::setY(double y)
{
if (this->y != y) {
if (this->y != y && (this->frame == MAV_FRAME_LOCAL)) {
this->y = y;
emit changed(this);
}
......@@ -122,7 +125,7 @@ void Waypoint::setY(double y)
void Waypoint::setZ(double z)
{
if (this->z != z) {
if (this->z != z && (this->frame == MAV_FRAME_LOCAL)) {
this->z = z;
emit changed(this);
}
......@@ -130,27 +133,24 @@ void Waypoint::setZ(double z)
void Waypoint::setLatitude(double lat)
{
if (this->x != lat) {
if (this->x != lat && ((this->frame == MAV_FRAME_GLOBAL) || (this->frame == MAV_FRAME_GLOBAL_RELATIVE_ALT))) {
this->x = lat;
this->frame = MAV_FRAME_GLOBAL;
emit changed(this);
}
}
void Waypoint::setLongitude(double lon)
{
if (this->y != lon) {
if (this->y != lon && ((this->frame == MAV_FRAME_GLOBAL) || (this->frame == MAV_FRAME_GLOBAL_RELATIVE_ALT))) {
this->y = lon;
this->frame = MAV_FRAME_GLOBAL;
emit changed(this);
}
}
void Waypoint::setAltitude(double altitude)
{
if (this->z != altitude) {
if (this->z != altitude && ((this->frame == MAV_FRAME_GLOBAL) || (this->frame == MAV_FRAME_GLOBAL_RELATIVE_ALT))) {
this->z = altitude;
this->frame = MAV_FRAME_GLOBAL;
emit changed(this);
}
}
......
......@@ -37,6 +37,7 @@ This file is part of the PIXHAWK project
#include <QString>
#include <QTextStream>
#include "QGCMAVLink.h"
#include "QGC.h"
class Waypoint : public QObject
{
......@@ -44,7 +45,7 @@ class Waypoint : public QObject
public:
Waypoint(quint16 id = 0, double x = 0.0, double y = 0.0, double z = 0.0, double param1 = 0.0, double param2 = 0.0, double param3 = 0.0, double param4 = 0.0,
bool autocontinue = true, bool current = false, MAV_FRAME frame=MAV_FRAME_GLOBAL, MAV_CMD action=MAV_CMD_NAV_WAYPOINT);
bool autocontinue = true, bool current = false, MAV_FRAME frame=MAV_FRAME_GLOBAL, MAV_CMD action=MAV_CMD_NAV_WAYPOINT, const QString& description=QString(""));
~Waypoint();
quint16 getId() const {
......@@ -119,6 +120,9 @@ public:
const QString& getName() const {
return name;
}
const QString& getDescription() const {
return description;
}
/** @brief Returns true if x, y, z contain reasonable navigation data */
bool isNavigationType();
......@@ -141,6 +145,8 @@ protected:
double param2;
int turns;
QString name;
QString description;
quint64 reachedTime;
public slots:
void setId(quint16 id);
......@@ -173,6 +179,12 @@ public slots:
void setHoldTime(double holdTime);
/** @brief Number of turns for loiter waypoints */
void setTurns(int turns);
/** @brief Set waypoint as reached */
void setReached() { reachedTime = QGC::groundTimeMilliseconds(); }
/** @brief Wether this waypoint has been reached yet */
bool isReached() { return (reachedTime > 0); }
/** @brief Get the time this waypoint was reached */
quint64 getReachedTime() { return reachedTime; }
signals:
/** @brief Announces a change to the waypoint data */
......
/*=====================================================================
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 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"
/**
* @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)
{
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()
{
}
/*=====================================================================
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 application class
*
* @author Lorenz Meier <lm@inf.ethz.ch>
*
*/
#ifndef QGCVIDEOAPP_H
#define QGCVIDEOAPP_H
#include <QApplication>
/**
* @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:
QGCVideoApp(int &argc, char* argv[]);
~QGCVideoApp();
protected:
private:
};
#endif /* QGCVIDEOAPP_H */
/*=====================================================================
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
/*=====================================================================
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
* @author Lorenz Meier <lm@inf.ethz.ch>
*
*/
#include <QtGui/QApplication>
#include "QGCVideoApp.h"
/**
* @brief Starts the application
*
* @param argc Number of commandline arguments
* @param argv Commandline arguments
* @return exit code, 0 for normal exit and !=0 for error cases
*/
int main(int argc, char *argv[])
{
QGCVideoApp app(argc, argv);
return app.exec();
}
......@@ -182,6 +182,14 @@ void MAVLinkProtocol::receiveBytes(LinkInterface* link, QByteArray b)
unsigned int decodeState = mavlink_parse_char(link->getId(), (uint8_t)(b.at(position)), &message, &status);
if (decodeState == 1) {
#ifdef MAVLINK_MESSAGE_LENGTHS
const uint8_t message_lengths[] = MAVLINK_MESSAGE_LENGTHS;
if (message.msgid >= sizeof(message_lengths) ||
message.len != message_lengths[message.msgid]) {
qDebug() << "MAVLink message " << message.msgid << " length incorrect (was " << message.len << " expected " << message_lengths[message.msgid] << ")";
continue;
}
#endif
// Log data
if (m_loggingEnabled && m_logfile) {
const int len = MAVLINK_MAX_PACKET_LEN+sizeof(quint64);
......
......@@ -934,7 +934,7 @@ bool MAVLinkSimulationLink::connect()
emit connected(true);
start(LowPriority);
MAVLinkSimulationMAV* mav1 = new MAVLinkSimulationMAV(this, 1, 47.376, 8.548);
MAVLinkSimulationMAV* mav1 = new MAVLinkSimulationMAV(this, 1, 37.480391, -122.282883);
Q_UNUSED(mav1);
// MAVLinkSimulationMAV* mav2 = new MAVLinkSimulationMAV(this, 2, 47.375, 8.548, 1);
// Q_UNUSED(mav2);
......
......@@ -23,13 +23,20 @@ MAVLinkSimulationMAV::MAVLinkSimulationMAV(MAVLinkSimulationLink *parent, int sy
yaw(0.0),
globalNavigation(true),
firstWP(false),
previousSPX(8.548056),
previousSPY(47.376389),
previousSPZ(550),
previousSPYaw(0.0),
nextSPX(8.548056),
nextSPY(47.376389),
nextSPZ(550),
// previousSPX(8.548056),
// previousSPY(47.376389),
// previousSPZ(550),
// previousSPYaw(0.0),
// nextSPX(8.548056),
// nextSPY(47.376389),
// nextSPZ(550),
previousSPX(37.480391),
previousSPY(122.282883),
previousSPZ(550),
previousSPYaw(0.0),
nextSPX(37.480391),
nextSPY(122.282883),
nextSPZ(550),
nextSPYaw(0.0),
sys_mode(MAV_MODE_READY),
sys_state(MAV_STATE_STANDBY),
......
......@@ -90,6 +90,16 @@ bool MAVLinkXMLParser::generate()
int mavlinkVersion = 0;
// we need to gather the message lengths across multiple includes,
// which we can do via detecting recursion
static unsigned message_lengths[256];
static int highest_message_id;
static int recursion_level;
if (recursion_level == 0) {
highest_message_id = 0;
memset(message_lengths, 0, sizeof(message_lengths));
}
// Start main header
......@@ -138,7 +148,10 @@ bool MAVLinkXMLParser::generate()
MAVLinkXMLParser includeParser(incFilePath, topLevelOutputDirName, this);
connect(&includeParser, SIGNAL(parseState(QString)), this, SIGNAL(parseState(QString)));
// Generate and write
includeParser.generate();
recursion_level++;
// Abort if inclusion fails
if (!includeParser.generate()) return false;
recursion_level--;
mainHeader += "\n#include \"../" + pureIncludeFileName + "/" + pureIncludeFileName + ".h\"\n";
......@@ -250,13 +263,30 @@ bool MAVLinkXMLParser::generate()
// Add comment of field if there is one
QString fieldComment;
if (e2.text().length() > 0) {
fieldComment = " /* " + e2.text() + "*/";
if (e2.text().length() > 0)
{
QString sep(" | ");
QDomNode pp = e2.firstChild();
while (!pp.isNull()) {
QDomElement pp2 = pp.toElement();
if (pp2.isText() || pp2.isCDATASection())
{
fieldComment += pp2.nodeValue() + sep;
}
else if (pp2.isElement())
{
fieldComment += pp2.text() + sep;
pp = pp.nextSibling();
}
}
fieldComment = fieldComment.replace("\n", " ");
fieldComment = " /* " + fieldComment.simplified() + " */";
}
currEnum += "\t" + fieldName.toUpper() + "=" + fieldValue + "," + fieldComment + "\n";
} else if(!e2.isNull() && e2.tagName() == "description") {
comment = e2.text().replace("\n", " ") + comment;
}
else if(!e2.isNull() && e2.tagName() == "description")
{
comment = " " + e2.text().replace("\n", " ") + comment;
}
f = f.nextSibling();
}
......@@ -340,7 +370,7 @@ bool MAVLinkXMLParser::generate()
QString decodeLines;
QString sendArguments;
QString commentLines;
unsigned message_length = 0;
// Get the message fields
......@@ -437,6 +467,40 @@ bool MAVLinkXMLParser::generate()
}
// message length calculation
unsigned element_multiplier = 1;
unsigned element_length = 0;
const struct {
const char *prefix;
unsigned length;
} length_map[] = {
{ "array", 1 },
{ "char", 1 },
{ "uint8", 1 },
{ "int8", 1 },
{ "uint16", 2 },
{ "int16", 2 },
{ "uint32", 4 },
{ "int32", 4 },
{ "uint64", 8 },
{ "int64", 8 },
{ "float", 4 },
{ "double", 8 },
};
if (fieldType.contains("[")) {
element_multiplier = fieldType.split("[").at(1).split("]").first().toInt();
}
for (unsigned i=0; i<sizeof(length_map)/sizeof(length_map[0]); i++) {
if (fieldType.startsWith(length_map[i].prefix)) {
element_length = length_map[i].length * element_multiplier;
break;
}
}
if (element_length == 0) {
emit parseState(tr("<font color=\"red\">ERROR: Unable to calculate length for %2 near line %1\nAbort.</font>").arg(QString::number(e.lineNumber()), fieldType));
}
message_length += element_length;
//
// QString unpackingCode;
......@@ -489,6 +553,11 @@ bool MAVLinkXMLParser::generate()
f = f.nextSibling();
}
if (messageId > highest_message_id) {
highest_message_id = messageId;
}
message_lengths[messageId] = message_length;
cStruct = cStruct.arg(cStructName, cStructLines);
lcmStructDefs.append("\n").append(cStruct).append("\n");
pack = pack.arg(messageName, packParameters, messageName.toUpper(), packLines);
......@@ -540,6 +609,15 @@ bool MAVLinkXMLParser::generate()
mainHeader += includeLine.arg(messagesDirName + "/" + cFiles.at(i).first);
}
mainHeader += "\n\n// MESSAGE LENGTHS\n\n";
mainHeader += "#undef MAVLINK_MESSAGE_LENGTHS\n";
mainHeader += "#define MAVLINK_MESSAGE_LENGTHS { ";
for (int i=0; i<highest_message_id; i++) {
mainHeader += QString::number(message_lengths[i]);
if (i < highest_message_id-1) mainHeader += ", ";
}
mainHeader += " }\n\n";
mainHeader += "#ifdef __cplusplus\n}\n#endif\n";
mainHeader += "#endif";
// Newline to make compiler happy
......
......@@ -33,7 +33,6 @@ This file is part of the QGROUNDCONTROL project
#define SERIALINTERFACE_H
#include <QIODevice>
#include "qextserialport.h"
#include <QtSerialPort/QSerialPort>
#include <iostream>
......@@ -138,67 +137,6 @@ public:
virtual void setFlow(flowType flow) = 0;
};
class SerialQextserial : public SerialInterface
{
Q_OBJECT
private:
QextSerialPort * _port;
signals:
void aboutToClose();
public:
SerialQextserial(QString porthandle, QextSerialPort::QueryMode mode) : _port(NULL) {
_port = new QextSerialPort(porthandle, QextSerialPort::Polling);
QObject::connect(_port,SIGNAL(aboutToClose()),this,SIGNAL(aboutToClose()));
}
~SerialQextserial() {
delete _port;
_port = NULL;
}
virtual bool isOpen() {
return _port->isOpen();
}
virtual bool isWritable() {
return _port->isWritable();
}
virtual qint64 bytesAvailable() {
return _port->bytesAvailable();
}
virtual int write(const char * data, qint64 size) {
return _port->write(data,size);
}
virtual void read(char * data, qint64 numBytes) {
_port->read(data,numBytes);
}
virtual void flush() {
_port->flush();
}
virtual void close() {
_port->close();
}
virtual void open(QIODevice::OpenModeFlag flag) {
_port->open(flag);
}
virtual void setBaudRate(SerialInterface::baudRateType baudrate) {
_port->setBaudRate((BaudRateType)baudrate);
}
virtual void setParity(SerialInterface::parityType parity) {
_port->setParity((ParityType)parity);
}
virtual void setStopBits(SerialInterface::stopBitsType stopBits) {
_port->setStopBits((StopBitsType)stopBits);
}
virtual void setDataBits(SerialInterface::dataBitsType dataBits) {
_port->setDataBits((DataBitsType)dataBits);
}
virtual void setTimeout(qint64 timeout) {
_port->setTimeout(timeout);
}
virtual void setFlow(SerialInterface::flowType flow) {
// TODO implement
_port->setFlowControl((FlowType)flow);
}
};
using namespace TNX;
class SerialQserial : public SerialInterface
......
This diff is collapsed.
......@@ -36,7 +36,7 @@ This file is part of the QGROUNDCONTROL project
#include <QThread>
#include <QMutex>
#include <QString>
#include "SerialInterface.h"
#include "qserialport.h"
#include <configuration.h>
#include "SerialLinkInterface.h"
#ifdef _WIN32
......@@ -59,11 +59,11 @@ class SerialLink : public SerialLinkInterface
public:
SerialLink(QString portname = "",
SerialInterface::baudRateType baudrate=SerialInterface::BAUD57600,
SerialInterface::flowType flow=SerialInterface::FLOW_OFF,
SerialInterface::parityType parity=SerialInterface::PAR_NONE,
SerialInterface::dataBitsType dataBits=SerialInterface::DATA_8,
SerialInterface::stopBitsType stopBits=SerialInterface::STOP_1);
int baudrate=57600,
bool flow=false,
bool parity=false,
int dataBits=8,
int stopBits=1);
~SerialLink();
static const int poll_interval = SERIAL_POLL_INTERVAL; ///< Polling interval, defined in configuration.h
......@@ -116,6 +116,9 @@ public slots:
bool setDataBits(int dataBits);
bool setStopBits(int stopBits);
// Set string rate
bool setBaudRateString(const QString& rate);
// Set ENUM values
bool setBaudRateType(int rateIndex);
bool setFlowType(int flow);
......@@ -138,18 +141,14 @@ protected slots:
void checkForBytes();
protected:
SerialInterface * port;
TNX::QSerialPort * port;
TNX::QPortSettings portSettings;
#ifdef _WIN32
HANDLE winPort;
DCB winPortSettings;
#endif
QString porthandle;
QString name;
SerialInterface::baudRateType baudrate;
SerialInterface::flowType flow;
SerialInterface::parityType parity;
SerialInterface::dataBitsType dataBits;
SerialInterface::stopBitsType stopBits;
int timeout;
int id;
......
......@@ -85,18 +85,20 @@ void UDPLink::setPort(int port)
*/
void UDPLink::addHost(const QString& host)
{
if (host != "")
{
qDebug() << "UDP:" << "ADDING HOST:" << host;
if (host.contains(":")) {
qDebug() << "HOST: " << host.split(":").first();
QHostInfo info = QHostInfo::fromName(host.split(":").first());
qDebug() << "UDP:" << "ADDING HOST:" << host;
if (host.contains(":")) {
qDebug() << "HOST: " << host.split(":").first();
QHostInfo info = QHostInfo::fromName(host.split(":").first());
if (info.error() == QHostInfo::NoError)
{
// Add host
QList<QHostAddress> hostAddresses = info.addresses();
QHostAddress address;
for (int i = 0; i < hostAddresses.size(); i++) {
for (int i = 0; i < hostAddresses.size(); i++)
{
// Exclude loopback IPv4 and all IPv6 addresses
if (!hostAddresses.at(i).toString().contains(":")) {
if (!hostAddresses.at(i).toString().contains(":"))
{
address = hostAddresses.at(i);
}
}
......@@ -104,8 +106,13 @@ void UDPLink::addHost(const QString& host)
qDebug() << "Address:" << address.toString();
// Set port according to user input
ports.append(host.split(":").last().toInt());
} else {
QHostInfo info = QHostInfo::fromName(host);
}
}
else
{
QHostInfo info = QHostInfo::fromName(host);
if (info.error() == QHostInfo::NoError)
{
// Add host
hosts.append(info.addresses().first());
// Set port according to default (this port)
......@@ -136,7 +143,6 @@ void UDPLink::removeHost(const QString& hostname)
}
}
void UDPLink::writeBytes(const char* data, qint64 size)
{
// Broadcast to all connected systems
......@@ -144,18 +150,26 @@ void UDPLink::writeBytes(const char* data, qint64 size)
{
QHostAddress currentHost = hosts.at(h);
quint16 currentPort = ports.at(h);
//#define UDPLINK_DEBUG
#ifdef UDPLINK_DEBUG
QString bytes;
QString ascii;
//qDebug() << "WRITING DATA TO" << currentHost.toString() << currentPort;
for (int i=0; i<size; i++) {
unsigned char v = data[i];
bytes.append(QString().sprintf("%02x ", v));
ascii.append(data[i]);
if (data[i] > 31 && data[i] < 127)
{
ascii.append(data[i]);
}
else
{
ascii.append(219);
}
}
qDebug() << "Sent" << size << "bytes to" << currentHost.toString() << ":" << currentPort << "data:";
qDebug() << bytes;
qDebug() << "ASCII:" << ascii;
#endif
socket->writeDatagram(data, size, currentHost, currentPort);
}
}
......
#ifndef CONFIGURATION_H
#define CONFIGURATION_H
#ifndef QGC_CONFIGURATION_H
#define QGC_CONFIGURATION_H
#include "mavlink.h"
#include <QString>
/** @brief Polling interval in ms */
#ifdef MAVLINK_ENABLED_SLUGS
#define SERIAL_POLL_INTERVAL 7
#else
#define SERIAL_POLL_INTERVAL 7
#endif
#define SERIAL_POLL_INTERVAL 9
/** @brief Heartbeat emission rate, in Hertz (times per second) */
#define MAVLINK_HEARTBEAT_DEFAULT_RATE 1
......@@ -17,14 +12,14 @@
#define WITH_TEXT_TO_SPEECH 1
#define QGC_APPLICATION_NAME "QGroundControl"
#define QGC_APPLICATION_VERSION "v. 0.8.3 (Alpha RC7)"
#define QGC_APPLICATION_VERSION "v. 0.9.0 (Alpha RC1)"
namespace QGC
{
const QString APPNAME = "QGROUNDCONTROL";
const QString COMPANYNAME = "OPENMAV";
const int APPLICATIONVERSION = 83; // 0.8.0
const QString COMPANYNAME = "QGROUNDCONTROL";
const int APPLICATIONVERSION = 90; // 0.9.0
}
#endif // CONFIGURATION_H
#endif // QGC_CONFIGURATION_H
This diff is collapsed.
#ifndef _POSIX_QEXTSERIALPORT_H_
#define _POSIX_QEXTSERIALPORT_H_
#include <stdio.h>
#include <termios.h>
#include <errno.h>
#include <unistd.h>
#include <sys/time.h>
#include <sys/ioctl.h>
#include <sys/select.h>
#include "qextserialbase.h"
class Posix_QextSerialPort:public QextSerialBase
{
private:
/*!
* This method is a part of constructor.
*/
void init();
protected:
int fd;
struct termios Posix_CommConfig;
struct termios old_termios;
struct timeval Posix_Timeout;
struct timeval Posix_Copy_Timeout;
virtual qint64 readData(char * data, qint64 maxSize);
virtual qint64 writeData(const char * data, qint64 maxSize);
public:
Posix_QextSerialPort(QextSerialBase::QueryMode mode);
Posix_QextSerialPort(const Posix_QextSerialPort& s);
Posix_QextSerialPort(const QString & name, QextSerialBase::QueryMode mode);
Posix_QextSerialPort(const PortSettings& settings, QextSerialBase::QueryMode mode);
Posix_QextSerialPort(const QString & name, const PortSettings& settings, QextSerialBase::QueryMode mode);
Posix_QextSerialPort& operator=(const Posix_QextSerialPort& s);
virtual ~Posix_QextSerialPort();
virtual void setBaudRate(BaudRateType);
virtual void setDataBits(DataBitsType);
virtual void setParity(ParityType);
virtual void setStopBits(StopBitsType);
virtual void setFlowControl(FlowType);
virtual void setTimeout(long);
virtual bool open(OpenMode mode);
virtual void close();
virtual void flush();
virtual qint64 size() const;
virtual qint64 bytesAvailable() const;
virtual void ungetChar(char c);
virtual void translateError(ulong error);
virtual void setDtr(bool set=true);
virtual void setRts(bool set=true);
virtual ulong lineStatus();
};
#endif
#include "qextserialbase.h"
/*!
\fn QextSerialBase::QextSerialBase()
Default constructor.
*/
QextSerialBase::QextSerialBase()
: QIODevice()
{
#ifdef _TTY_WIN_
setPortName("COM1");
#elif defined(_TTY_IRIX_)
setPortName("/dev/ttyf1");
#elif defined(_TTY_HPUX_)
setPortName("/dev/tty1p0");
#elif defined(_TTY_SUN_)
setPortName("/dev/ttya");
#elif defined(_TTY_DIGITAL_)
setPortName("/dev/tty01");
#elif defined(_TTY_FREEBSD_)
setPortName("/dev/ttyd1");
#elif defined(_TTY_OPENBSD_)
setPortName("/dev/tty00");
#else
setPortName("/dev/ttyS0");
#endif
construct();
}
/*!
\fn QextSerialBase::QextSerialBase(const QString & name)
Construct a port and assign it to the device specified by the name parameter.
*/
QextSerialBase::QextSerialBase(const QString & name)
: QIODevice()
{
setPortName(name);
construct();
}
/*!
\fn QextSerialBase::~QextSerialBase()
Standard destructor.
*/
QextSerialBase::~QextSerialBase()
{
delete mutex;
}
/*!
\fn void QextSerialBase::construct()
Common constructor function for setting up default port settings.
(115200 Baud, 8N1, Hardware flow control where supported, otherwise no flow control, and 0 ms timeout).
*/
void QextSerialBase::construct()
{
lastErr = E_NO_ERROR;
Settings.BaudRate=BAUD115200;
Settings.DataBits=DATA_8;
Settings.Parity=PAR_NONE;
Settings.StopBits=STOP_1;
Settings.FlowControl=FLOW_HARDWARE;
Settings.Timeout_Millisec=500;
mutex = new QMutex( QMutex::Recursive );
setOpenMode(QIODevice::NotOpen);
}
void QextSerialBase::setQueryMode(QueryMode mechanism)
{
_queryMode = mechanism;
}
/*!
\fn void QextSerialBase::setPortName(const QString & name)
Sets the name of the device associated with the object, e.g. "COM1", or "/dev/ttyS0".
*/
void QextSerialBase::setPortName(const QString & name)
{
port = name;
}
/*!
\fn QString QextSerialBase::portName() const
Returns the name set by setPortName().
*/
QString QextSerialBase::portName() const
{
return port;
}
/*!
\fn BaudRateType QextSerialBase::baudRate(void) const
Returns the baud rate of the serial port. For a list of possible return values see
the definition of the enum BaudRateType.
*/
BaudRateType QextSerialBase::baudRate(void) const
{
return Settings.BaudRate;
}
/*!
\fn DataBitsType QextSerialBase::dataBits() const
Returns the number of data bits used by the port. For a list of possible values returned by
this function, see the definition of the enum DataBitsType.
*/
DataBitsType QextSerialBase::dataBits() const
{
return Settings.DataBits;
}
/*!
\fn ParityType QextSerialBase::parity() const
Returns the type of parity used by the port. For a list of possible values returned by
this function, see the definition of the enum ParityType.
*/
ParityType QextSerialBase::parity() const
{
return Settings.Parity;
}
/*!
\fn StopBitsType QextSerialBase::stopBits() const
Returns the number of stop bits used by the port. For a list of possible return values, see
the definition of the enum StopBitsType.
*/
StopBitsType QextSerialBase::stopBits() const
{
return Settings.StopBits;
}
/*!
\fn FlowType QextSerialBase::flowControl() const
Returns the type of flow control used by the port. For a list of possible values returned
by this function, see the definition of the enum FlowType.
*/
FlowType QextSerialBase::flowControl() const
{
return Settings.FlowControl;
}
/*!
\fn bool QextSerialBase::isSequential() const
Returns true if device is sequential, otherwise returns false. Serial port is sequential device
so this function always returns true. Check QIODevice::isSequential() documentation for more
information.
*/
bool QextSerialBase::isSequential() const
{
return true;
}
/*!
\fn bool QextSerialBase::atEnd() const
This function will return true if the input buffer is empty (or on error), and false otherwise.
Call QextSerialBase::lastError() for error information.
*/
bool QextSerialBase::atEnd() const
{
if (size()) {
return true;
}
return false;
}
/*!
\fn qint64 QextSerialBase::readLine(char * data, qint64 maxSize)
This function will read a line of buffered input from the port, stopping when either maxSize bytes
have been read, the port has no more data available, or a newline is encountered.
The value returned is the length of the string that was read.
*/
qint64 QextSerialBase::readLine(char * data, qint64 maxSize)
{
qint64 numBytes = bytesAvailable();
char* pData = data;
if (maxSize < 2) //maxSize must be larger than 1
return -1;
/*read a byte at a time for MIN(bytesAvail, maxSize - 1) iterations, or until a newline*/
while (pData<(data+numBytes) && --maxSize) {
readData(pData, 1);
if (*pData++ == '\n') {
break;
}
}
*pData='\0';
/*return size of data read*/
return (pData-data);
}
/*!
\fn ulong QextSerialBase::lastError() const
Returns the code for the last error encountered by the port, or E_NO_ERROR if the last port
operation was successful. Possible error codes are:
\verbatim
Error Explanation
--------------------------- -------------------------------------------------------------
E_NO_ERROR No Error has occured
E_INVALID_FD Invalid file descriptor (port was not opened correctly)
E_NO_MEMORY Unable to allocate memory tables (POSIX)
E_CAUGHT_NON_BLOCKED_SIGNAL Caught a non-blocked signal (POSIX)
E_PORT_TIMEOUT Operation timed out (POSIX)
E_INVALID_DEVICE The file opened by the port is not a character device (POSIX)
E_BREAK_CONDITION The port detected a break condition
E_FRAMING_ERROR The port detected a framing error
(usually caused by incorrect baud rate settings)
E_IO_ERROR There was an I/O error while communicating with the port
E_BUFFER_OVERRUN Character buffer overrun
E_RECEIVE_OVERFLOW Receive buffer overflow
E_RECEIVE_PARITY_ERROR The port detected a parity error in the received data
E_TRANSMIT_OVERFLOW Transmit buffer overflow
E_READ_FAILED General read operation failure
E_WRITE_FAILED General write operation failure
\endverbatim
*/
ulong QextSerialBase::lastError() const
{
return lastErr;
}
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
#ifndef _QEXTSERIALPORT_H_
#define _QEXTSERIALPORT_H_
/*POSIX CODE*/
#ifdef _TTY_POSIX_
#include "posix_qextserialport.h"
#define QextBaseType Posix_QextSerialPort
/*MS WINDOWS CODE*/
#else
#include "win_qextserialport.h"
#define QextBaseType Win_QextSerialPort
#endif
class QextSerialPort: public QextBaseType
{
Q_OBJECT
public:
typedef QextSerialBase::QueryMode QueryMode;
QextSerialPort(QueryMode mode = QextSerialPort::EventDriven);
QextSerialPort(const QString & name, QueryMode mode = QextSerialPort::EventDriven);
QextSerialPort(PortSettings const& s, QueryMode mode = QextSerialPort::EventDriven);
QextSerialPort(const QString & name, PortSettings const& s, QueryMode mode = QextSerialPort::EventDriven);
QextSerialPort(const QextSerialPort& s);
QextSerialPort& operator=(const QextSerialPort&);
virtual ~QextSerialPort();
};
#endif
QPORTDIR = src/lib/qextserialport
INCLUDEPATH += $$QPORTDIR
HEADERS += $$QPORTDIR/qextserialbase.h \
$$QPORTDIR/qextserialport.h \
$$QPORTDIR/qextserialenumerator.h
SOURCES += $$QPORTDIR/qextserialbase.cpp \
$$QPORTDIR/qextserialport.cpp \
$$QPORTDIR/qextserialenumerator.cpp
unix:HEADERS += $$QPORTDIR/posix_qextserialport.h
unix:SOURCES += $$QPORTDIR/posix_qextserialport.cpp
unix:DEFINES += _TTY_POSIX_
win32:HEADERS += $$QPORTDIR/win_qextserialport.h
win32:SOURCES += $$QPORTDIR/win_qextserialport.cpp
win32:DEFINES += _TTY_WIN_
win32:LIBS += -lsetupapi
unix:VERSION = 1.2.0
This diff is collapsed.
This diff is collapsed.
#include "src/mapwidget/opmapwidget.h"
LIBS *= -l$$qtLibraryTarget(opmapwidget)
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment