Commit ff33c79e authored by Lorenz Meier's avatar Lorenz Meier

Merged FlightGear

parents c7e4a65c e3432de0
......@@ -91,7 +91,7 @@
<damping_coeff_rebound unit="LBS/FT/SEC"> 4.0 </damping_coeff_rebound>
<max_steer unit="DEG">0</max_steer>
<brake_group>NONE</brake_group>
<retractable>FIXED</retractable>
<retractable>0</retractable>
</contact>
<contact type="BOGEY" name="NOSE">
<location unit="M">
......@@ -107,7 +107,7 @@
<damping_coeff_rebound unit="LBS/FT/SEC"> 4.0 </damping_coeff_rebound>
<max_steer unit="DEG">0</max_steer>
<brake_group>NONE</brake_group>
<retractable>FIXED</retractable>
<retractable>0</retractable>
</contact>
<contact type="STRUCTURE" name="TAIL">
......
......@@ -187,7 +187,8 @@ DebugBuild {
src/qgcunittest/MockUAS.h \
src/qgcunittest/MockQGCUASParamManager.h \
src/qgcunittest/MultiSignalSpy.h \
src/qgcunittest/FlightModeConfigTest.h
src/qgcunittest/FlightModeConfigTest.h \
src/qgcunittest/FlightGearTest.h
SOURCES += \
src/qgcunittest/UASUnitTest.cc \
......@@ -195,7 +196,8 @@ DebugBuild {
src/qgcunittest/MockUAS.cc \
src/qgcunittest/MockQGCUASParamManager.cc \
src/qgcunittest/MultiSignalSpy.cc \
src/qgcunittest/FlightModeConfigTest.cc
src/qgcunittest/FlightModeConfigTest.cc \
src/qgcunittest/FlightGearTest.cc
}
#
......
This diff is collapsed.
......@@ -47,7 +47,6 @@ This file is part of the QGROUNDCONTROL project
class QGCFlightGearLink : public QGCHilLink
{
Q_OBJECT
//Q_INTERFACES(QGCFlightGearLinkInterface:LinkInterface)
public:
QGCFlightGearLink(UASInterface* mav, QString startupArguments, QString remoteHost=QString("127.0.0.1:49000"), QHostAddress host = QHostAddress::Any, quint16 port = 49005);
......@@ -87,8 +86,13 @@ public:
void sensorHilEnabled(bool sensorHilEnabled) {
_sensorHilEnabled = sensorHilEnabled;
}
static bool parseUIArguments(QString uiArgs, QStringList& argList);
void run();
signals:
void showCriticalMessageFromThread(const QString& title, const QString& message);
public slots:
// void setAddress(QString address);
......@@ -98,10 +102,6 @@ public slots:
/** @brief Send new control states to the simulation */
void updateControls(quint64 time, float rollAilerons, float pitchElevator, float yawRudder, float throttle, quint8 systemMode, quint8 navMode);
void updateActuators(quint64 time, float act1, float act2, float act3, float act4, float act5, float act6, float act7, float act8);
// /** @brief Remove a host from broadcasting messages to */
// void removeHost(const QString& host);
// void readPendingDatagrams();
void processError(QProcess::ProcessError err);
/** @brief Set the simulator version as text string */
void setVersion(const QString& version)
{
......@@ -130,12 +130,9 @@ public slots:
bool connectSimulation();
bool disconnectSimulation();
void printTerraSyncOutput();
void printTerraSyncError();
void printFgfsOutput();
void printFgfsError();
void setStartupArguments(QString startupArguments);
void setBarometerOffset(float barometerOffsetkPa);
void processError(QProcess::ProcessError err);
protected:
QString name;
......@@ -144,32 +141,29 @@ protected:
quint16 currentPort;
quint16 port;
int id;
QUdpSocket* socket;
bool connectState;
quint64 bitsSentTotal;
quint64 bitsSentCurrent;
quint64 bitsSentMax;
quint64 bitsReceivedTotal;
quint64 bitsReceivedCurrent;
quint64 bitsReceivedMax;
quint64 connectionStartTime;
QMutex statisticsMutex;
QMutex dataMutex;
QTimer refreshTimer;
UASInterface* mav;
QProcess* process;
QProcess* terraSync;
unsigned int flightGearVersion;
QString startupArguments;
bool _sensorHilEnabled;
float barometerOffsetkPa;
void setName(QString name);
signals:
private slots:
void _printFgfsOutput(void);
void _printFgfsError(void);
private:
static bool _findUIArgument(const QStringList& uiArgList, const QString& argLabel, QString& argValue);
QString _fgProcessName; ///< FlightGear process to start
QString _fgProcessWorkingDirPath; ///< Working directory to start FG process in, empty for none
QStringList _fgArgList; ///< Arguments passed to FlightGear process
QUdpSocket* _udpCommSocket; ///< UDP communication sockect between FG and QGC
QProcess* _fgProcess; ///< FlightGear process
};
#endif // QGCFLIGHTGEARLINK_H
/*=====================================================================
QGroundControl Open Source Ground Control Station
(c) 2009 - 2014 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/>.
======================================================================*/
#include "FlightGearTest.h"
#include "QGCFlightGearLink.h"
/// @file
/// @brief FlightGearUnitTest HIL Simulation class
///
/// @author Don Gagne <don@thegagnes.com>
FlightGearUnitTest::FlightGearUnitTest(void)
{
}
// Called before every test
void FlightGearUnitTest::init(void)
{
// Nothing here yet
}
// Called after every test
void FlightGearUnitTest::cleanup(void)
{
// Nothing here yet
}
/// @brief The QGCFlightGearLink::parseUIArguments method is fairly involved so we have a unit
// test for it.
void FlightGearUnitTest::_parseUIArguments_test(void)
{
typedef struct {
const char* args;
const char* expectedListAsChar;
bool expectedReturn;
} ParseUIArgumentsTestCase_t;
static const ParseUIArgumentsTestCase_t rgTestCases[] = {
{ "foo", "foo", true },
{ "foo bar", "foo|bar", true },
{ "--foo --bar", "--foo|--bar", true },
{ "foo=bar", "foo=bar", true },
{ "foo=bar bar=baz", "foo=bar|bar=baz", true },
{ "foo=\"bar\"", "foo=bar", true },
{ "foo=\"bar\" bar=\"baz\"", "foo=bar|bar=baz", true },
{ "foo=\"b ar\"", "foo=b ar", true },
{ "foo=\"b ar\" bar=\"b az\"", "foo=b ar|bar=b az", true },
{ "foo\"", NULL, false },
};
for (size_t i=0; i<sizeof(rgTestCases)/sizeof(rgTestCases[0]); i++) {
const ParseUIArgumentsTestCase_t* testCase = &rgTestCases[i];
QStringList returnedArgList;
bool actualReturn = QGCFlightGearLink::parseUIArguments(testCase->args, returnedArgList);
QCOMPARE(actualReturn, testCase->expectedReturn);
if (actualReturn) {
QStringList expectedArgList = QString(testCase->expectedListAsChar).split("|");
if (returnedArgList != expectedArgList) {
qDebug() << "About to fail: Returned" << returnedArgList << "Expected" << expectedArgList;
}
QVERIFY(returnedArgList == expectedArgList);
}
}
}
/*=====================================================================
QGroundControl Open Source Ground Control Station
(c) 2009 - 2014 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 TCPLINKTEST_H
#define TCPLINKTEST_H
#include <QObject>
#include <QtTest>
#include <QApplication>
#include "AutoTest.h"
#include "TCPLink.h"
#include "MultiSignalSpy.h"
/// @file
/// @brief FlightGear HIL Simulation unit tests
///
/// @author Don Gagne <don@thegagnes.com>
class FlightGearUnitTest : public QObject
{
Q_OBJECT
public:
FlightGearUnitTest(void);
private slots:
void init(void);
void cleanup(void);
void _parseUIArguments_test(void);
private:
};
DECLARE_TEST(FlightGearUnitTest)
#endif
......@@ -39,7 +39,7 @@
</item>
<item>
<property name="text">
<string>Flightgear</string>
<string>FlightGear 3.0+</string>
</property>
</item>
<item>
......@@ -69,7 +69,7 @@
<item row="2" column="0" colspan="2">
<widget class="QLabel" name="statusLabel">
<property name="text">
<string>No simulator active..</string>
<string></string>
</property>
</widget>
</item>
......
#include "QGCHilFlightGearConfiguration.h"
#include "ui_QGCHilFlightGearConfiguration.h"
#include "MainWindow.h"
QGCHilFlightGearConfiguration::QGCHilFlightGearConfiguration(UAS* mav,QWidget *parent) :
// Various settings groups and keys
const char* QGCHilFlightGearConfiguration::_settingsGroup = "QGC_HILCONFIG_FLIGHTGEAR";
const char* QGCHilFlightGearConfiguration::_mavSettingsSubGroupFixedWing = "FIXED_WING";
const char* QGCHilFlightGearConfiguration::_mavSettingsSubGroupQuadRotor = "QUADROTOR";
const char* QGCHilFlightGearConfiguration::_aircraftKey = "AIRCRAFT";
const char* QGCHilFlightGearConfiguration::_optionsKey = "OPTIONS";
const char* QGCHilFlightGearConfiguration::_barometerOffsetKey = "BARO_OFFSET";
const char* QGCHilFlightGearConfiguration::_sensorHilKey = "SENSOR_HIL";
// Default set of optional command line parameters. If FlightGear won't run HIL without it it should go into
// the QGCFlightGearLink code instead.
const char* QGCHilFlightGearConfiguration::_defaultOptions = "--roll=0 --pitch=0 --vc=0 --heading=300 --timeofday=noon --disable-hud-3d --disable-fullscreen --geometry=400x300 --disable-anti-alias-hud --wind=0@0 --turbulence=0.0 --control=mouse --disable-sound --disable-random-objects --disable-ai-traffic --shading-flat --fog-disable --disable-specular-highlight --disable-panel --disable-clouds --fdm=jsb --units-meters --enable-terrasync";
QGCHilFlightGearConfiguration::QGCHilFlightGearConfiguration(UAS* mav, QWidget *parent) :
QWidget(parent),
mav(mav),
ui(new Ui::QGCHilFlightGearConfiguration)
{
ui->setupUi(this);
_mav(mav),
_mavSettingsSubGroup(NULL),
_resetOptionsAction(tr("Reset to default options"), this)
QStringList items = QStringList();
if (mav->getSystemType() == MAV_TYPE_FIXED_WING)
{
Q_ASSERT(_mav);
_ui.setupUi(this);
QStringList items;
if (_mav->getSystemType() == MAV_TYPE_FIXED_WING)
{
items << "EasyStar";
items << "Rascal110-JSBSim";
items << "c172p";
items << "YardStik";
items << "Malolo1";
_mavSettingsSubGroup = _mavSettingsSubGroupFixedWing;
}
else if (mav->getSystemType() == MAV_TYPE_QUADROTOR)
else if (_mav->getSystemType() == MAV_TYPE_QUADROTOR)
{
items << "arducopter";
_mavSettingsSubGroup = _mavSettingsSubGroupQuadRotor;
}
else
{
// FIXME: Should disable all input, won't work. Show error message in the status label thing.
items << "<aircraft>";
}
ui->aircraftComboBox->addItems(items);
_ui.aircraftComboBox->addItems(items);
QSettings settings;
settings.beginGroup(_settingsGroup);
settings.beginGroup(_mavSettingsSubGroup);
QString aircraft = settings.value(_aircraftKey).toString();
QString options = settings.value(_optionsKey).toString();
QString baroOffset = settings.value(_barometerOffsetKey).toString();
bool sensorHil = settings.value(_sensorHilKey, QVariant(true)).toBool();
settings.endGroup();
settings.endGroup();
if (!aircraft.isEmpty()) {
int index = _ui.aircraftComboBox->findText(aircraft);
if (index != -1) {
_ui.aircraftComboBox->setCurrentIndex(index);
}
}
if (options.isEmpty()) {
options = _defaultOptions;
}
_ui.optionsPlainTextEdit->setPlainText(options);
_ui.barometerOffsetLineEdit->setText(baroOffset);
_ui.sensorHilCheckBox->setChecked(sensorHil);
// Provide an option on the context menu to reset the option back to default
_ui.optionsPlainTextEdit->setContextMenuPolicy(Qt::CustomContextMenu);
bool success = connect(&_resetOptionsAction, SIGNAL(triggered()), this, SLOT(_setDefaultOptions()));
Q_ASSERT(success);
success = connect(_ui.optionsPlainTextEdit, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(_showContextMenu(const QPoint &)));
Q_ASSERT(success);
}
QGCHilFlightGearConfiguration::~QGCHilFlightGearConfiguration()
{
delete ui;
QString aircraft = _ui.aircraftComboBox->currentText();
QString options = _ui.optionsPlainTextEdit->toPlainText();
QString baroOffset = _ui.barometerOffsetLineEdit->text();
bool sensorHil = _ui.sensorHilCheckBox->isChecked();
QSettings settings;
settings.beginGroup(_settingsGroup);
settings.beginGroup(_mavSettingsSubGroup);
if (aircraft.isEmpty()) {
settings.remove(_aircraftKey);
} else {
settings.setValue(_aircraftKey, aircraft);
}
if (options.isEmpty() || options == _defaultOptions) {
settings.remove(_optionsKey);
} else {
settings.setValue(_optionsKey, options);
}
// Double QVariant is to convert from string to float. It will change to 0.0 if invalid.
settings.setValue(_barometerOffsetKey, QVariant(QVariant(baroOffset).toFloat()));
settings.setValue(_sensorHilKey, QVariant(sensorHil));
settings.endGroup();
settings.endGroup();
}
void QGCHilFlightGearConfiguration::on_startButton_clicked()
{
//XXX check validity of inputs
QString options = ui->optionsPlainTextEdit->toPlainText();
options.append(" --aircraft=" + ui->aircraftComboBox->currentText());
mav->enableHilFlightGear(true, options, ui->sensorHilCheckBox->isChecked(), this);
QString options = _ui.optionsPlainTextEdit->toPlainText();
options.append(" --aircraft=" + _ui.aircraftComboBox->currentText());
_mav->enableHilFlightGear(true, options, _ui.sensorHilCheckBox->isChecked(), this);
}
void QGCHilFlightGearConfiguration::on_stopButton_clicked()
{
mav->stopHil();
_mav->stopHil();
}
void QGCHilFlightGearConfiguration::on_barometerOffsetLineEdit_textChanged(const QString& baroOffset)
......@@ -53,3 +129,16 @@ void QGCHilFlightGearConfiguration::on_barometerOffsetLineEdit_textChanged(const
emit barometerOffsetChanged(baroOffset.toFloat());
}
void QGCHilFlightGearConfiguration::_showContextMenu(const QPoint &pt)
{
QMenu* menu = _ui.optionsPlainTextEdit->createStandardContextMenu();
menu->addAction(&_resetOptionsAction);
menu->exec(_ui.optionsPlainTextEdit->mapToGlobal(pt));
delete menu;
}
void QGCHilFlightGearConfiguration::_setDefaultOptions(void)
{
_ui.optionsPlainTextEdit->setPlainText(_defaultOptions);
}
......@@ -7,6 +7,8 @@
#include "QGCFlightGearLink.h"
#include "UAS.h"
#include "ui_QGCHilFlightGearConfiguration.h"
namespace Ui {
class QGCHilFlightGearConfiguration;
}
......@@ -20,16 +22,33 @@ public:
~QGCHilFlightGearConfiguration();
protected:
UAS* mav;
private slots:
void on_startButton_clicked();
void on_stopButton_clicked();
void on_barometerOffsetLineEdit_textChanged(const QString& baroOffset);
void _setDefaultOptions(void);
void _showContextMenu(const QPoint& pt);
private:
Ui::QGCHilFlightGearConfiguration *ui;
Ui::QGCHilFlightGearConfiguration _ui;
UAS* _mav; /// mav associated with this ui
static const char* _settingsGroup; /// Top level settings group
const char* _mavSettingsSubGroup; /// We maintain a settings sub group per mav type
static const char* _mavSettingsSubGroupFixedWing; /// Subgroup if mav type is MAV_TYPE_FIXED_WING
static const char* _mavSettingsSubGroupQuadRotor; /// Subgroup is mav type is MAV_TYPE_QUADROTOR
static const char* _aircraftKey; /// Settings key for aircraft selection
static const char* _optionsKey; /// Settings key for FlightGear cmd line options
static const char* _barometerOffsetKey; /// Settings key for barometer offset
static const char* _sensorHilKey; /// Settings key for Sensor Hil checkbox
static const char* _defaultOptions; /// Default set of FlightGEar command line options
QAction _resetOptionsAction; /// Context menu item to reset options to default
signals:
void barometerOffsetChanged(float barometerOffsetkPa);
};
......
......@@ -68,7 +68,7 @@
</sizepolicy>
</property>
<property name="plainText">
<string>--roll=0 --pitch=0 --vc=0 --heading=300 --timeofday=noon --disable-hud-3d --disable-fullscreen --geometry=400x300 --disable-anti-alias-hud --wind=0@0 --turbulence=0.0 --control=mouse --disable-sound --disable-random-objects --disable-ai-models --shading-flat --fog-disable --disable-specular-highlight --disable-random-objects --disable-panel --disable-clouds --fdm=jsb --units-meters --prop:/engines/engine/running=true</string>
<string></string>
</property>
</widget>
</item>
......
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