Commit 1888a8dc authored by Don Gagne's avatar Don Gagne

New Joystick config, new Joystick control classes

parent 58d4ff15
......@@ -142,6 +142,7 @@ INCLUDEPATH += \
src/comm \
src/FlightDisplay \
src/input \
src/Joystick \
src/lib/qmapcontrol \
src/QmlControls \
src/uas \
......@@ -214,9 +215,6 @@ FORMS += \
!MobileBuild {
FORMS += \
src/ui/JoystickButton.ui \
src/ui/JoystickAxis.ui \
src/ui/JoystickWidget.ui \
src/ui/QGCHilConfiguration.ui \
src/ui/QGCHilFlightGearConfiguration.ui \
src/ui/QGCHilJSBSimConfiguration.ui \
......@@ -242,6 +240,8 @@ HEADERS += \
src/FlightDisplay/FlightDisplayView.h \
src/GAudioOutput.h \
src/HomePositionManager.h \
src/Joystick/Joystick.h \
src/Joystick/JoystickManager.h \
src/LogCompressor.h \
src/MG.h \
src/QGC.h \
......@@ -352,15 +352,12 @@ HEADERS += \
src/comm/QGCHilLink.h \
src/comm/QGCJSBSimLink.h \
src/comm/QGCXPlaneLink.h \
src/input/JoystickInput.h \
src/ui/CameraView.h \
src/ui/JoystickAxis.h \
src/ui/JoystickButton.h \
src/ui/JoystickWidget.h \
src/ui/QGCHilConfiguration.h \
src/ui/QGCHilFlightGearConfiguration.h \
src/ui/QGCHilJSBSimConfiguration.h \
src/ui/QGCHilXPlaneConfiguration.h \
src/VehicleSetup/JoystickConfigController.h \
}
SOURCES += \
......@@ -379,6 +376,8 @@ SOURCES += \
src/FlightDisplay/FlightDisplayView.cc \
src/GAudioOutput.cc \
src/HomePositionManager.cc \
src/Joystick/Joystick.cc \
src/Joystick/JoystickManager.cc \
src/LogCompressor.cc \
src/main.cc \
src/QGC.cc \
......@@ -482,15 +481,12 @@ SOURCES += \
src/comm/QGCFlightGearLink.cc \
src/comm/QGCJSBSimLink.cc \
src/comm/QGCXPlaneLink.cc \
src/input/JoystickInput.cc \
src/ui/CameraView.cc \
src/ui/JoystickAxis.cc \
src/ui/JoystickButton.cc \
src/ui/JoystickWidget.cc \
src/ui/QGCHilConfiguration.cc \
src/ui/QGCHilFlightGearConfiguration.cc \
src/ui/QGCHilJSBSimConfiguration.cc \
src/ui/QGCHilXPlaneConfiguration.cc \
src/VehicleSetup/JoystickConfigController.cc \
}
#
......
......@@ -99,15 +99,16 @@
<file alias="QGroundControl/Controls/MissionItemIndexLabel.qml">src/QmlControls/MissionItemIndexLabel.qml</file>
<file alias="QGroundControl/Controls/MissionItemSummary.qml">src/QmlControls/MissionItemSummary.qml</file>
<file alias="ScreenToolsFontQuery.qml">src/QmlControls/ScreenToolsFontQuery.qml</file>
<file alias="ParameterEditorWidget.qml">src/ViewWidgets/ParameterEditorWidget.qml</file>
<file alias="CustomCommandWidget.qml">src/ViewWidgets/CustomCommandWidget.qml</file>
<!-- Vehicle Setup -->
<file alias="SetupView.qml">src/VehicleSetup/SetupView.qml</file>
<file alias="SetupViewButtonsConnected.qml">src/VehicleSetup/SetupViewButtonsConnected.qml</file>
<file alias="SetupViewButtonsDisconnected.qml">src/VehicleSetup/SetupViewButtonsDisconnected.qml</file>
<file alias="VehicleSummary.qml">src/VehicleSetup/VehicleSummary.qml</file>
<file alias="FirmwareUpgrade.qml">src/VehicleSetup/FirmwareUpgrade.qml</file>
<file alias="JoystickConfig.qml">src/VehicleSetup/JoystickConfig.qml</file>
<file alias="SetupParameterEditor.qml">src/VehicleSetup/SetupParameterEditor.qml</file>
<file alias="ScreenToolsFontQuery.qml">src/QmlControls/ScreenToolsFontQuery.qml</file>
<file alias="ParameterEditorWidget.qml">src/ViewWidgets/ParameterEditorWidget.qml</file>
<file alias="CustomCommandWidget.qml">src/ViewWidgets/CustomCommandWidget.qml</file>
<file alias="SafetyComponent.qml">src/AutoPilotPlugins/PX4/SafetyComponent.qml</file>
<file alias="RadioComponent.qml">src/AutoPilotPlugins/PX4/RadioComponent.qml</file>
<file alias="PowerComponent.qml">src/AutoPilotPlugins/PX4/PowerComponent.qml</file>
......@@ -222,6 +223,7 @@
<file alias="accel_up.png">resources/calibration/accel_up.png</file>
<file alias="accel_left.png">resources/calibration/accel_left.png</file>
</qresource>
<qresource prefix="/qml/calibration/mode1">
<file alias="radioCenter.png">resources/calibration/mode1/radioCenter.png</file>
<file alias="radioHome.png">resources/calibration/mode1/radioHome.png</file>
......@@ -235,6 +237,7 @@
<file alias="radioThrottleDown.png">resources/calibration/mode1/radioThrottleDown.png</file>
<file alias="radioSwitchMinMax.png">resources/calibration/mode1/radioSwitchMinMax.png</file>
</qresource>
<qresource prefix="/qml/calibration/mode2">
<file alias="radioCenter.png">resources/calibration/mode2/radioCenter.png</file>
<file alias="radioHome.png">resources/calibration/mode2/radioHome.png</file>
......@@ -248,6 +251,19 @@
<file alias="radioThrottleDown.png">resources/calibration/mode2/radioThrottleDown.png</file>
<file alias="radioSwitchMinMax.png">resources/calibration/mode2/radioSwitchMinMax.png</file>
</qresource>
<qresource prefix="/qml/calibration/joystick">
<file alias="joystickCenter.png">resources/calibration/joystick/joystickCenter.png</file>
<file alias="joystickRollLeft.png">resources/calibration/joystick/joystickRollLeft.png</file>
<file alias="joystickRollRight.png">resources/calibration/joystick/joystickRollRight.png</file>
<file alias="joystickPitchUp.png">resources/calibration/joystick/joystickPitchUp.png</file>
<file alias="joystickPitchDown.png">resources/calibration/joystick/joystickPitchDown.png</file>
<file alias="joystickYawLeft.png">resources/calibration/joystick/joystickYawLeft.png</file>
<file alias="joystickYawRight.png">resources/calibration/joystick/joystickYawRight.png</file>
<file alias="joystickThrottleUp.png">resources/calibration/joystick/joystickThrottleUp.png</file>
<file alias="joystickThrottleDown.png">resources/calibration/joystick/joystickThrottleDown.png</file>
</qresource>
<qresource prefix="/res/styles">
<file alias="style-dark.css">resources/styles/style-dark.css</file>
<file alias="style-light.css">resources/styles/style-light.css</file>
......
......@@ -50,6 +50,9 @@ QGCView {
function updateChannelCount()
{
if (controllerAndViewReady) {
if (joystickManager.activeJoystick && joystickManager.activeJoystick.enabled) {
showDialog(joystickEnabledDialogComponent, dialogTitle, 50, 0)
}
/*
FIXME: Turned off for now, since it prevents binding. Need to restructure to
allow binding and still check channel count
......@@ -128,6 +131,14 @@ QGCView {
}
}
Component {
id: joystickEnabledDialogComponent
QGCViewMessage {
message: "Radio Config is disabled since you have a Joystick enabled."
}
}
Component {
id: spektrumBindDialogComponent
......
......@@ -76,6 +76,12 @@ public:
/// @param[out] custom_mode Custom mode for SET_MODE mavlink message
virtual bool setFlightMode(const QString& flightMode, uint8_t* base_mode, uint32_t* custom_mode) = 0;
/// Returns the number of buttons which are reserved for firmware use in the MANUAL_CONTROL mavlink
/// message. For example PX4 Flight Stack reserves the first 8 buttons to simulate rc switches.
/// The remainder can be assigned to Vehicle actions.
/// @return -1: reserver all buttons, >0 number of buttons to reserve
virtual int manualControlReservedButtonCount(void) = 0;
protected:
FirmwarePlugin(QObject* parent = NULL) : QGCSingleton(parent) { }
};
......
......@@ -89,3 +89,10 @@ bool GenericFirmwarePlugin::setFlightMode(const QString& flightMode, uint8_t* ba
return false;
}
int GenericFirmwarePlugin::manualControlReservedButtonCount(void)
{
// We don't know whether the firmware is going to used any of these buttons.
// So reserve them all.
return -1;
}
......@@ -43,6 +43,7 @@ public:
virtual QStringList flightModes(void) { return QStringList(); }
virtual QString flightMode(uint8_t base_mode, uint32_t custom_mode);
virtual bool setFlightMode(const QString& flightMode, uint8_t* base_mode, uint32_t* custom_mode);
virtual int manualControlReservedButtonCount(void);
private:
/// All access to singleton is through AutoPilotPluginManager::instance
......
......@@ -176,3 +176,8 @@ bool PX4FirmwarePlugin::setFlightMode(const QString& flightMode, uint8_t* base_m
return found;
}
int PX4FirmwarePlugin::manualControlReservedButtonCount(void)
{
return 8; // 8 buttons reserved for rc switch simulation
}
......@@ -43,6 +43,7 @@ public:
virtual QStringList flightModes(void);
virtual QString flightMode(uint8_t base_mode, uint32_t custom_mode);
virtual bool setFlightMode(const QString& flightMode, uint8_t* base_mode, uint32_t* custom_mode);
virtual int manualControlReservedButtonCount(void);
private:
/// All access to singleton is through AutoPilotPluginManager::instance
......
This diff is collapsed.
/*=====================================================================
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 Joystick_H
#define Joystick_H
#include <QObject>
#include <QThread>
#include "QGCLoggingCategory.h"
#include "Vehicle.h"
Q_DECLARE_LOGGING_CATEGORY(JoystickLog)
class Joystick : public QThread
{
Q_OBJECT
public:
Joystick(const QString& name, int axisCount, int buttonCount, int sdlIndex);
~Joystick();
typedef struct {
int min;
int max;
int center;
bool reversed;
} Calibration_t;
typedef enum {
rollFunction,
pitchFunction,
yawFunction,
throttleFunction,
maxFunction
} AxisFunction_t;
typedef enum {
ThrottleModeCenterZero,
ThrottleModeDownZero,
ThrottleModeMax
} ThrottleMode_t;
Q_PROPERTY(QString name READ name CONSTANT)
Q_PROPERTY(bool calibrated MEMBER _calibrated NOTIFY calibratedChanged)
Q_PROPERTY(bool enabled READ enabled WRITE setEnabled NOTIFY enabledChanged)
Q_PROPERTY(int buttonCount MEMBER _buttonCount CONSTANT)
Q_PROPERTY(int axisCount MEMBER _axisCount CONSTANT)
Q_PROPERTY(QStringList actions READ actions CONSTANT)
Q_PROPERTY(QVariantList buttonActions READ buttonActions NOTIFY buttonActionsChanged)
Q_INVOKABLE void setButtonAction(int button, int action);
Q_INVOKABLE int getButtonAction(int button);
Q_PROPERTY(int throttleMode READ throttleMode WRITE setThrottleMode NOTIFY throttleModeChanged)
/// Start the polling thread which will in turn emit joystick signals
void startPolling(void);
void stopPolling(void);
void setCalibration(int axis, Calibration_t& calibration);
Calibration_t getCalibration(int axis);
void setFunctionAxis(AxisFunction_t function, int axis);
int getFunctionAxis(AxisFunction_t function);
QStringList actions(void);
QVariantList buttonActions(void);
QString name(void) { return _name; }
int throttleMode(void);
void setThrottleMode(int mode);
bool enabled(void);
void setEnabled(bool enabled);
bool calibrating(void) { return _calibrating; }
void setCalibrating(bool calibrating) { _calibrating = calibrating; }
signals:
void calibratedChanged(bool calibrated);
// The raw signals are only meant for use by calibration
void rawAxisValueChanged(int index, int value);
void rawButtonPressedChanged(int index, int pressed);
void buttonActionsChanged(QVariantList actions);
void throttleModeChanged(int mode);
void enabledChanged(bool enabled);
/// Signal containing new joystick information
/// @param roll Range is -1:1, negative meaning roll left, positive meaning roll right
/// @param pitch Range i -1:1, negative meaning pitch down, positive meaning pitch up
/// @param yaw Range is -1:1, negative meaning yaw left, positive meaning yaw right
/// @param throttle Range is 0:1, 0 meaning no throttle, 1 meaning full throttle
/// @param mode See Vehicle::JoystickMode_t enum
void manualControl(float roll, float pitch, float yaw, float throttle, quint16 buttons, int joystickMmode);
void buttonActionTriggered(int action);
private:
void _saveSettings(void);
void _loadSettings(void);
float _adjustRange(int value, Calibration_t calibration);
// Override from QThread
virtual void run(void);
private:
int _sdlIndex; ///< Index for SDL_JoystickOpen
bool _exitThread; ///< true: signal thread to exit
QString _name;
bool _enabled;
bool _calibrated;
bool _calibrating;
int _axisCount;
int _buttonCount;
static const int _cAxes = 4;
int _rgAxisValues[_cAxes];
Calibration_t _rgCalibration[_cAxes];
int _rgFunctionAxis[maxFunction];
static const char* _rgFunctionSettingsKey[maxFunction];
static const int _cButtons = 12;
int _rgButtonValues[_cButtons];
int _rgButtonActions[_cButtons];
quint16 _lastButtonBits;
ThrottleMode_t _throttleMode;
static const char* _settingsGroup;
static const char* _calibratedSettingsKey;
static const char* _buttonActionSettingsKey;
static const char* _throttleModeSettingsKey;
static const char* _enabledSettingsKey;
};
#endif
/*=====================================================================
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 "JoystickManager.h"
#include <QQmlEngine>
#ifdef Q_OS_MAC
#include <SDL.h>
#else
#include <SDL/SDL.h>
#endif
QGC_LOGGING_CATEGORY(JoystickManagerLog, "JoystickManagerLog")
IMPLEMENT_QGC_SINGLETON(JoystickManager, JoystickManager)
const char * JoystickManager::_settingsGroup = "JoystickManager";
const char * JoystickManager::_settingsKeyActiveJoystick = "ActiveJoystick";
JoystickManager::JoystickManager(QObject* parent)
: QGCSingleton(parent)
, _activeJoystick(NULL)
{
QQmlEngine::setObjectOwnership(this, QQmlEngine::CppOwnership);
if (SDL_InitSubSystem(SDL_INIT_JOYSTICK | SDL_INIT_NOPARACHUTE) < 0) {
qWarning() << "Couldn't initialize SimpleDirectMediaLayer:" << SDL_GetError();
return;
}
// Load available joysticks
qCDebug(JoystickManagerLog) << "Available joysticks";
for (int i=0; i<SDL_NumJoysticks(); i++) {
QString name = SDL_JoystickName(i);
if (!_name2JoystickMap.contains(name)) {
int axisCount, buttonCount;
SDL_Joystick* sdlJoystick = SDL_JoystickOpen(i);
axisCount = SDL_JoystickNumAxes(sdlJoystick);
buttonCount = SDL_JoystickNumButtons(sdlJoystick);
SDL_JoystickClose(sdlJoystick);
qCDebug(JoystickManagerLog) << "\t" << name << "axes:" << axisCount << "buttons:" << buttonCount;
_name2JoystickMap[name] = new Joystick(name, axisCount, buttonCount, i);
} else {
qCDebug(JoystickManagerLog) << "\tSkipping duplicate" << name;
}
}
if (!_name2JoystickMap.count()) {
qCDebug(JoystickManagerLog) << "\tnone found";
return;
}
_setActiveJoystickFromSettings();
}
JoystickManager::~JoystickManager()
{
}
void JoystickManager::_setActiveJoystickFromSettings(void)
{
QSettings settings;
settings.beginGroup(_settingsGroup);
QString name = settings.value(_settingsKeyActiveJoystick).toString();
if (name.isEmpty()) {
name = _name2JoystickMap.first()->name();
}
setActiveJoystick(_name2JoystickMap.value(name, _name2JoystickMap.first()));
settings.setValue(_settingsKeyActiveJoystick, _activeJoystick->name());
}
Joystick* JoystickManager::activeJoystick(void)
{
return _activeJoystick;
}
void JoystickManager::setActiveJoystick(Joystick* joystick)
{
QSettings settings;
if (!_name2JoystickMap.contains(joystick->name())) {
qCWarning(JoystickManagerLog) << "Set active not in map" << joystick->name();
return;
}
if (_activeJoystick) {
_activeJoystick->stopPolling();
}
_activeJoystick = joystick;
settings.beginGroup(_settingsGroup);
settings.setValue(_settingsKeyActiveJoystick, _activeJoystick->name());
emit activeJoystickChanged(_activeJoystick);
emit activeJoystickNameChanged(_activeJoystick->name());
}
QVariantList JoystickManager::joysticks(void)
{
QVariantList list;
foreach (QString name, _name2JoystickMap.keys()) {
list += QVariant::fromValue(_name2JoystickMap[name]);
}
return list;
}
QStringList JoystickManager::joystickNames(void)
{
return _name2JoystickMap.keys();
}
QString JoystickManager::activeJoystickName(void)
{
return _activeJoystick ? _activeJoystick->name() : QString();
}
void JoystickManager::setActiveJoystickName(const QString& name)
{
if (!_name2JoystickMap.contains(name)) {
qCWarning(JoystickManagerLog) << "Set active not in map" << name;
return;
}
setActiveJoystick(_name2JoystickMap[name]);
}
/*=====================================================================
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 JoystickManager_H
#define JoystickManager_H
#include "QGCSingleton.h"
#include "QGCLoggingCategory.h"
#include "Joystick.h"
#include <QVariantList>
Q_DECLARE_LOGGING_CATEGORY(JoystickManagerLog)
class JoystickManager : public QGCSingleton
{
Q_OBJECT
DECLARE_QGC_SINGLETON(JoystickManager, JoystickManager)
public:
/// List of available joysticks
Q_PROPERTY(QVariantList joysticks READ joysticks CONSTANT)
Q_PROPERTY(QStringList joystickNames READ joystickNames CONSTANT)
/// Active joystick
Q_PROPERTY(Joystick* activeJoystick READ activeJoystick WRITE setActiveJoystick NOTIFY activeJoystickChanged)
Q_PROPERTY(QString activeJoystickName READ activeJoystickName WRITE setActiveJoystickName NOTIFY activeJoystickNameChanged)
QVariantList joysticks();
QStringList joystickNames(void);
Joystick* activeJoystick(void);
void setActiveJoystick(Joystick* joystick);
QString activeJoystickName(void);
void setActiveJoystickName(const QString& name);
signals:
void activeJoystickChanged(Joystick* joystick);
void activeJoystickNameChanged(const QString& name);
private slots:
private:
/// All access to singleton is through JoystickManager::instance
JoystickManager(QObject* parent = NULL);
~JoystickManager();
void _setActiveJoystickFromSettings(void);
private:
Joystick* _activeJoystick;
QMap<QString, Joystick*> _name2JoystickMap;
static const char * _settingsGroup;
static const char * _settingsKeyActiveJoystick;
};
#endif
......@@ -89,6 +89,8 @@ G_END_DECLS
#include "PX4/PX4FirmwarePlugin.h"
#include "Vehicle.h"
#include "MavlinkQmlSingleton.h"
#include "JoystickManager.h"
#include "JoystickConfigController.h"
#ifdef QGC_RTLAB_ENABLED
#include "OpalLink.h"
......@@ -327,16 +329,19 @@ void QGCApplication::_initCommon(void)
qmlRegisterUncreatableType<AutoPilotPlugin>("QGroundControl.AutoPilotPlugin", 1, 0, "AutoPilotPlugin", "Can only reference, cannot create");
qmlRegisterUncreatableType<VehicleComponent>("QGroundControl.AutoPilotPlugin", 1, 0, "VehicleComponent", "Can only reference, cannot create");
qmlRegisterUncreatableType<Vehicle>("QGroundControl.Vehicle", 1, 0, "Vehicle", "Can only reference, cannot create");
qmlRegisterUncreatableType<JoystickManager> ("QGroundControl.JoystickManager", 1, 0, "JoystickManager", "Reference only");
qmlRegisterUncreatableType<Joystick> ("QGroundControl.JoystickManager", 1, 0, "Joystick", "Reference only");
qmlRegisterType<ViewWidgetController>("QGroundControl.Controllers", 1, 0, "ViewWidgetController");
qmlRegisterType<ParameterEditorController>("QGroundControl.Controllers", 1, 0, "ParameterEditorController");
qmlRegisterType<CustomCommandWidgetController>("QGroundControl.Controllers", 1, 0, "CustomCommandWidgetController");
qmlRegisterType<FlightModesComponentController>("QGroundControl.Controllers", 1, 0, "FlightModesComponentController");
qmlRegisterType<AirframeComponentController>("QGroundControl.Controllers", 1, 0, "AirframeComponentController");
qmlRegisterType<SensorsComponentController>("QGroundControl.Controllers", 1, 0, "SensorsComponentController");
qmlRegisterType<PowerComponentController>("QGroundControl.Controllers", 1, 0, "PowerComponentController");
qmlRegisterType<RadioComponentController>("QGroundControl.Controllers", 1, 0, "RadioComponentController");
qmlRegisterType<ScreenToolsController>("QGroundControl.Controllers", 1, 0, "ScreenToolsController");
qmlRegisterType<ViewWidgetController> ("QGroundControl.Controllers", 1, 0, "ViewWidgetController");
qmlRegisterType<ParameterEditorController> ("QGroundControl.Controllers", 1, 0, "ParameterEditorController");
qmlRegisterType<CustomCommandWidgetController> ("QGroundControl.Controllers", 1, 0, "CustomCommandWidgetController");
qmlRegisterType<FlightModesComponentController> ("QGroundControl.Controllers", 1, 0, "FlightModesComponentController");
qmlRegisterType<AirframeComponentController> ("QGroundControl.Controllers", 1, 0, "AirframeComponentController");
qmlRegisterType<SensorsComponentController> ("QGroundControl.Controllers", 1, 0, "SensorsComponentController");
qmlRegisterType<PowerComponentController> ("QGroundControl.Controllers", 1, 0, "PowerComponentController");
qmlRegisterType<RadioComponentController> ("QGroundControl.Controllers", 1, 0, "RadioComponentController");
qmlRegisterType<ScreenToolsController> ("QGroundControl.Controllers", 1, 0, "ScreenToolsController");
qmlRegisterType<JoystickConfigController> ("QGroundControl.Controllers", 1, 0, "JoystickConfigController");
#ifndef __mobile__
qmlRegisterType<FirmwareUpgradeController>("QGroundControl.Controllers", 1, 0, "FirmwareUpgradeController");
......@@ -576,6 +581,11 @@ void QGCApplication::_createSingletons(void)
Q_UNUSED(multiVehicleManager);
Q_ASSERT(multiVehicleManager);
// No dependencies
JoystickManager* joystickManager = JoystickManager::_createSingleton();
Q_UNUSED(joystickManager);
Q_ASSERT(joystickManager);
// No dependencies
GAudioOutput* audio = GAudioOutput::_createSingleton();
Q_UNUSED(audio);
......@@ -636,6 +646,7 @@ void QGCApplication::_destroySingletons(void)
HomePositionManager::_deleteSingleton();
LinkManager::_deleteSingleton();
GAudioOutput::_deleteSingleton();
JoystickManager::_deleteSingleton();
MultiVehicleManager::_deleteSingleton();
FirmwarePluginManager::_deleteSingleton();
GenericFirmwarePlugin::_deleteSingleton();
......
......@@ -25,6 +25,7 @@
#include "AutoPilotPluginManager.h"
#include "QGCMessageBox.h"
#include "MultiVehicleManager.h"
#include "JoystickManager.h"
#include <QQmlContext>
#include <QQmlEngine>
......@@ -40,6 +41,7 @@ QGCQuickWidget::QGCQuickWidget(QWidget* parent) :
{
rootContext()->engine()->addImportPath("qrc:/qml");
rootContext()->setContextProperty("multiVehicleManager", MultiVehicleManager::instance());
rootContext()->setContextProperty("joystickManager", JoystickManager::instance());
}
void QGCQuickWidget::setAutoPilot(AutoPilotPlugin* autoPilot)
......
......@@ -26,6 +26,9 @@
#include "MultiVehicleManager.h"
#include "AutoPilotPlugin.h"
#include "JoystickManager.h"
#include "MAVLinkProtocol.h"
#include "UAS.h"
IMPLEMENT_QGC_SINGLETON(MultiVehicleManager, MultiVehicleManager)
......@@ -107,6 +110,15 @@ void MultiVehicleManager::_deleteVehiclePhase1(void)
qWarning() << "Vehicle not found in map!";
}
// Disconnect the vehicle from the uas
vehicle->uas()->clearVehicle();
// Disconnect joystick
Joystick* joystick = JoystickManager::instance()->activeJoystick();
if (joystick) {
joystick->stopPolling();
}
// First we must signal that a vehicle is no longer available.
_activeVehicleAvailable = false;
_parameterReadyVehicleAvailable = false;
......@@ -150,6 +162,12 @@ void MultiVehicleManager::setActiveVehicle(Vehicle* vehicle)
{
if (vehicle != _activeVehicle) {
if (_activeVehicle) {
// Disconnect joystick
Joystick* joystick = JoystickManager::instance()->activeJoystick();
if (joystick) {
joystick->stopPolling();
}
// The sequence of signals is very important in order to not leave Qml elements connected
// to a non-existent vehicle.
......@@ -195,6 +213,12 @@ void MultiVehicleManager::_autopilotPluginReadyChanged(bool pluginReady)
}
if (autopilot->vehicle() == _activeVehicle) {
// Connect joystick
Joystick* joystick = JoystickManager::instance()->activeJoystick();
if (joystick && joystick->enabled()) {
joystick->startPolling();
}
_parameterReadyVehicleAvailable = pluginReady;
emit parameterReadyVehicleAvailableChanged(pluginReady);
}
......
......@@ -28,6 +28,7 @@
#include "FirmwarePlugin.h"
#include "AutoPilotPluginManager.h"
#include "UASMessageHandler.h"
#include "UAS.h"
QGC_LOGGING_CATEGORY(VehicleLog, "VehicleLog")
......@@ -35,9 +36,15 @@ QGC_LOGGING_CATEGORY(VehicleLog, "VehicleLog")
#define DEFAULT_LAT 38.965767f
#define DEFAULT_LON -120.083923f
const char* Vehicle::_settingsGroup = "Vehicle%1"; // %1 replace with mavlink system id
const char* Vehicle::_joystickModeSettingsKey = "JoystickMode";
Vehicle::Vehicle(LinkInterface* link, int vehicleId, MAV_AUTOPILOT firmwareType)
: _id(vehicleId)
, _firmwareType(firmwareType)
, _firmwarePlugin(NULL)
, _autopilotPlugin(NULL)
, _joystickMode(JoystickModeRC)
, _uas(NULL)
, _mav(NULL)
, _currentMessageCount(0)
......@@ -74,6 +81,8 @@ Vehicle::Vehicle(LinkInterface* link, int vehicleId, MAV_AUTOPILOT firmwareType)
, _wpm(NULL)
, _updateCount(0)
{
_loadSettings();
_addLink(link);
connect(MAVLinkProtocol::instance(), &MAVLinkProtocol::messageReceived, this, &Vehicle::_mavlinkMessageReceived);
......@@ -809,3 +818,57 @@ void Vehicle::resetMessages()
emit messageTypeChanged();
}
}
int Vehicle::manualControlReservedButtonCount(void)
{
return _firmwarePlugin->manualControlReservedButtonCount();
}
void Vehicle::_loadSettings(void)
{
QSettings settings;
settings.beginGroup(QString(_settingsGroup).arg(_id));
bool convertOk;
_joystickMode = (JoystickMode_t)settings.value(_joystickModeSettingsKey, JoystickModeRC).toInt(&convertOk);
if (!convertOk) {
_joystickMode = JoystickModeRC;
}
}
void Vehicle::_saveSettings(void)
{
QSettings settings;
settings.beginGroup(QString(_settingsGroup).arg(_id));
settings.setValue(_joystickModeSettingsKey, _joystickMode);
}
int Vehicle::joystickMode(void)
{
return _joystickMode;
}
void Vehicle::setJoystickMode(int mode)
{
if (mode < 0 || mode >= JoystickModeMax) {
qCWarning(VehicleLog) << "Invalid joystick mode" << mode;
return;
}
_joystickMode = (JoystickMode_t)mode;
_saveSettings();
emit joystickModeChanged(mode);
}
QStringList Vehicle::joystickModes(void)
{
QStringList list;
list << "Simulate RC" << "Attitude" << "Position" << "Force" << "Velocity";
return list;
}
......@@ -29,13 +29,17 @@
#include <QObject>
#include <QGeoCoordinate>
#include <QQmlListProperty>
#include "LinkInterface.h"
#include "QGCMAVLink.h"
#include "UAS.h"
#include "MissionItem.h"
class UAS;
class UASInterface;
class FirmwarePlugin;
class AutoPilotPlugin;
class UASWaypointManager;
Q_DECLARE_LOGGING_CATEGORY(VehicleLog)
......@@ -91,6 +95,30 @@ public:
//-- MissionItem management
Q_PROPERTY(QQmlListProperty<MissionItem> missionItems READ missionItems NOTIFY missionItemsChanged)
/// Returns the number of buttons which are reserved for firmware use in the MANUAL_CONTROL mavlink
/// message. For example PX4 Flight Stack reserves the first 8 buttons to simulate rc switches.
/// The remainder can be assigned to Vehicle actions.
/// @return -1: reserver all buttons, >0 number of buttons to reserve
Q_PROPERTY(int manualControlReservedButtonCount READ manualControlReservedButtonCount CONSTANT)
typedef enum {
JoystickModeRC, ///< Joystick emulates am RC Transmitter
JoystickModeAttitude,
JoystickModePosition,
JoystickModeForce,
JoystickModeVelocity,
JoystickModeMax
} JoystickMode_t;
/// The joystick mode associated with this vehicle. Joystick modes are stored keyed by mavlink system id.
Q_PROPERTY(int joystickMode READ joystickMode WRITE setJoystickMode NOTIFY joystickModeChanged)
int joystickMode(void);
void setJoystickMode(int mode);
/// List of joystick mode names
Q_PROPERTY(QStringList joystickModes READ joystickModes CONSTANT)
QStringList joystickModes(void);
// Property accesors
int id(void) { return _id; }
MAV_AUTOPILOT firmwareType(void) { return _firmwareType; }
......@@ -106,6 +134,8 @@ public:
QList<LinkInterface*> links(void);
int manualControlReservedButtonCount(void);
typedef enum {
MessageNone,
MessageNormal,
......@@ -171,6 +201,7 @@ public slots:
signals:
void allLinksDisconnected(void);
void coordinateChanged(QGeoCoordinate coordinate);
void joystickModeChanged(int mode);
/// Used internally to move sendMessage call to main thread
void _sendMessageOnThread(mavlink_message_t message);
......@@ -241,6 +272,9 @@ private slots:
private:
bool _containsLink(LinkInterface* link);
void _addLink(LinkInterface* link);
void _loadSettings(void);
void _saveSettings(void);
bool _isAirplane ();
void _addChange (int id);
float _oneDecimal (float value);
......@@ -257,6 +291,8 @@ private:
/// This way Link deletion works correctly.
QList<SharedLinkInterface> _links;
JoystickMode_t _joystickMode;
UAS* _uas;
QGeoCoordinate _geoCoordinate;
......@@ -302,5 +338,8 @@ private:
UASWaypointManager* _wpm;
int _updateCount;
QList<MissionItem*>_waypoints;
static const char* _settingsGroup;
static const char* _joystickModeSettingsKey;
};
#endif
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -72,6 +72,16 @@ Rectangle {
}
}
function showJoystickPanel()
{
if (multiVehicleManager.activeVehicleAvailable && multiVehicleManager.activeVehicle.autopilot.armed) {
messagePanelText = armedVehicleText
panelLoader.sourceComponent = messagePanelComponent
} else {
panelLoader.source = "JoystickConfig.qml";
}
}
function showParametersPanel()
{
panelLoader.source = "SetupParameterEditor.qml";
......@@ -170,6 +180,18 @@ Rectangle {
onClicked: showFirmwarePanel()
}
SubMenuButton {
id: joystickButton
width: buttonWidth
setupIndicator: true
setupComplete: joystickManager.activeJoystick.calibrated
exclusiveGroup: setupButtonGroup
visible: multiVehicleManager.parameterReadyVehicleAvailable && joystickManager.joysticks.length != 0
text: "JOYSTICK"
onClicked: showJoystickPanel()
}
Repeater {
model: multiVehicleManager.parameterReadyVehicleAvailable ? multiVehicleManager.activeVehicle.autopilot.vehicleComponents : 0
......
import QtQuick 2.3
import QtQuick.Controls 1.2
import QtQuick.Controls.Styles 1.2
import QtGraphicalEffects 1.0
import QGroundControl.FactSystem 1.0
import QGroundControl.Palette 1.0
import QGroundControl.Controls 1.0
Rectangle {
id: topLevel
QGCPalette { id: palette; colorGroupEnabled: true }
color: palette.window
ExclusiveGroup { id: setupButtonGroup }
Column {
anchors.fill: parent
SubMenuButton {
id: summaryButton; objectName: "summaryButton"
width: parent.width
text: "SUMMARY"
imageResource: "VehicleSummaryIcon.png"
setupIndicator: false
exclusiveGroup: setupButtonGroup
onClicked: controller.summaryButtonClicked()
}
SubMenuButton {
id: firmwareButton; objectName: "firmwareButton"
width: parent.width
text: "FIRMWARE"
imageResource: "FirmwareUpgradeIcon.png"
setupIndicator: false
exclusiveGroup: setupButtonGroup
onClicked: controller.firmwareButtonClicked()
}
Repeater {
model: autopilot ? autopilot.vehicleComponents : 0
SubMenuButton {
width: parent.width
text: modelData.name.toUpperCase()
imageResource: modelData.iconResource
setupComplete: modelData.setupComplete
exclusiveGroup: setupButtonGroup
onClicked: controller.setupButtonClicked(modelData)
}
}
SubMenuButton {
width: parent.width
text: "PARAMETERS"
setupIndicator: false
exclusiveGroup: setupButtonGroup
onClicked: controller.parametersButtonClicked()
}
}
}
import QtQuick 2.3
import QtQuick.Controls 1.2
import QtQuick.Controls.Styles 1.2
import QtGraphicalEffects 1.0
import QGroundControl.FactSystem 1.0
import QGroundControl.Palette 1.0
import QGroundControl.Controls 1.0
Rectangle {
id: topLevel
QGCPalette { id: palette; colorGroupEnabled: true }
color: palette.window
ExclusiveGroup { id: setupButtonGroup }
Column {
anchors.fill: parent
SubMenuButton {
id: firmwareButton; objectName: "firmwareButton"
width: parent.width
text: "FIRMWARE"
imageResource: "FirmwareUpgradeIcon.png"
setupIndicator: false
exclusiveGroup: setupButtonGroup
onClicked: controller.firmwareButtonClicked()
}
Item { width: parent.width; height: 10 } // spacer
QGCLabel {
width: parent.width
text: "Full setup options are only available when connected to vehicle and full parameter list has completed downloading."
wrapMode: Text.WordWrap
horizontalAlignment: Text.AlignHCenter
}
}
}
......@@ -25,6 +25,7 @@
#include "MultiVehicleManager.h"
#include "QGCMAVLink.h"
#include "QGCFileDialog.h"
#include "UAS.h"
#include <QSettings>
#include <QUrl>
......
......@@ -23,6 +23,7 @@
#include "ViewWidgetController.h"
#include "MultiVehicleManager.h"
#include "UAS.h"
ViewWidgetController::ViewWidgetController(void) :
_autopilot(NULL),
......
This diff is collapsed.
This diff is collapsed.
......@@ -26,6 +26,7 @@
#include "FileManagerTest.h"
#include "MultiVehicleManager.h"
#include "UAS.h"
//UT_REGISTER_TEST(FileManagerTest)
......
This diff is collapsed.
......@@ -37,8 +37,9 @@ This file is part of the QGROUNDCONTROL project
#include <QVector3D>
#include "QGCMAVLink.h"
#include "FileManager.h"
#include "Vehicle.h"
#ifndef __mobile__
#include "JoystickInput.h"
#include "QGCHilLink.h"
#include "QGCFlightGearLink.h"
#include "QGCJSBSimLink.h"
......@@ -110,6 +111,8 @@ public:
Q_PROPERTY(double altitudeWGS84 READ getAltitudeWGS84 WRITE setAltitudeWGS84 NOTIFY altitudeWGS84Changed)
Q_PROPERTY(double altitudeRelative READ getAltitudeRelative WRITE setAltitudeRelative NOTIFY altitudeRelativeChanged)
void clearVehicle(void) { _vehicle = NULL; }
void setGroundSpeed(double val)
{
groundSpeed = val;
......@@ -847,7 +850,7 @@ public slots:
/** @brief Set the values for the manual control of the vehicle */
#ifndef __mobile__
void setExternalControlSetpoint(float roll, float pitch, float yaw, float thrust, qint8 xHat, qint8 yHat, quint16 buttons, quint8);
void setExternalControlSetpoint(float roll, float pitch, float yaw, float thrust, quint16 buttons, int joystickMode);
#endif
/** @brief Set the values for the 6dof manual control of the vehicle */
......
......@@ -30,6 +30,7 @@ This file is part of the QGROUNDCONTROL project
#include "QGCApplication.h"
#include "UASMessageHandler.h"
#include "MultiVehicleManager.h"
#include "UAS.h"
UASMessage::UASMessage(int componentid, int severity, QString text)
{
......
......@@ -18,14 +18,17 @@
#include <QMouseEvent>
#include <QMenu>
#include <QSettings>
#include <QDebug>
#include <qmath.h>
#include "HDDisplay.h"
#include "ui_HDDisplay.h"
#include "MG.h"
#include "QGC.h"
#include "QGCApplication.h"
#include <QDebug>
#include "MultiVehicleManager.h"
#include "UAS.h"
HDDisplay::HDDisplay(const QStringList &plotList, QString title, QWidget *parent) :
QGraphicsView(parent),
......
......@@ -46,6 +46,7 @@ This file is part of the QGROUNDCONTROL project
#include <qmath.h>
#include "MAV2DIcon.h"
#include "QGCApplication.h"
#include "UAS.h"
HSIDisplay::HSIDisplay(QWidget *parent) :
HDDisplay(QStringList(), "HSI", parent),
......
#include "JoystickAxis.h"
#include "JoystickInput.h"
#include "ui_JoystickAxis.h"
#include "MultiVehicleManager.h"
#include <QString>
JoystickAxis::JoystickAxis(int id, QWidget *parent) :
QWidget(parent),
id(id),
ui(new Ui::JoystickAxis)
{
ui->setupUi(this);
mappingComboBoxChanged(JoystickInput::JOYSTICK_INPUT_MAPPING_NONE);
ui->label->setText(QString::number(id));
connect(ui->comboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(mappingComboBoxChanged(int)));
connect(ui->invertedCheckBox, SIGNAL(clicked(bool)), this, SLOT(inversionCheckBoxChanged(bool)));
connect(ui->rangeCheckBox, SIGNAL(clicked(bool)), this, SLOT(rangeCheckBoxChanged(bool)));
}
JoystickAxis::~JoystickAxis()
{
delete ui;
}
void JoystickAxis::setValue(float value)
{
ui->progressBar->setValue(100.0f * value);
}
void JoystickAxis::setMapping(JoystickInput::JOYSTICK_INPUT_MAPPING newMapping)
{
ui->comboBox->setCurrentIndex(newMapping);
if (newMapping == JoystickInput::JOYSTICK_INPUT_MAPPING_THROTTLE)
{
ui->rangeCheckBox->show();
}
else
{
ui->rangeCheckBox->hide();
}
this->activeVehicleChanged(MultiVehicleManager::instance()->activeVehicle());
}
void JoystickAxis::setInverted(bool newValue)
{
ui->invertedCheckBox->setChecked(newValue);
}
void JoystickAxis::setRangeLimit(bool newValue)
{
ui->rangeCheckBox->setChecked(newValue);
}
void JoystickAxis::mappingComboBoxChanged(int newMapping)
{
JoystickInput::JOYSTICK_INPUT_MAPPING mapping = (JoystickInput::JOYSTICK_INPUT_MAPPING)newMapping;
emit mappingChanged(id, mapping);
updateUIBasedOnUAS(MultiVehicleManager::instance()->activeVehicle(), mapping);
}
void JoystickAxis::inversionCheckBoxChanged(bool inverted)
{
emit inversionChanged(id, inverted);
}
void JoystickAxis::rangeCheckBoxChanged(bool limited)
{
emit rangeChanged(id, limited);
}
void JoystickAxis::activeVehicleChanged(Vehicle* vehicle)
{
updateUIBasedOnUAS(vehicle, (JoystickInput::JOYSTICK_INPUT_MAPPING)ui->comboBox->currentIndex());
}
void JoystickAxis::updateUIBasedOnUAS(Vehicle* vehicle, JoystickInput::JOYSTICK_INPUT_MAPPING axisMapping)
{
UAS* uas = NULL;
if (vehicle) {
uas = vehicle->uas();
}
// Set the throttle display to only positive if:
// * This is the throttle axis AND
// * The current UAS can't reverse OR there is no current UAS
// This causes us to default to systems with no negative throttle.
if (((uas && !uas->systemCanReverse()) || !uas) && axisMapping == JoystickInput::JOYSTICK_INPUT_MAPPING_THROTTLE)
{
ui->progressBar->setRange(0, 100);
ui->rangeCheckBox->show();
}
else
{
ui->progressBar->setRange(-100, 100);
ui->rangeCheckBox->hide();
}
}
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.
......@@ -46,9 +46,6 @@ This file is part of the QGROUNDCONTROL project
#include "WaypointList.h"
#include "CameraView.h"
#include "UASListWidget.h"
#ifndef __mobile__
#include "input/JoystickInput.h"
#endif
#if (defined QGC_MOUSE_ENABLED_WIN) | (defined QGC_MOUSE_ENABLED_LINUX)
#include "Mouse6dofInput.h"
#endif // QGC_MOUSE_ENABLED_WIN
......@@ -241,10 +238,6 @@ protected:
QPointer<QGCUASFileViewMulti> fileWidget;
#ifndef __mobile__
JoystickInput* joystick; ///< The joystick manager for QGC
#endif
#ifdef QGC_MOUSE_ENABLED_WIN
/** @brief 3d Mouse support (WIN only) */
Mouse3DInput* mouseInput; ///< 3dConnexion 3dMouse SDK
......
......@@ -3,6 +3,8 @@
#include "QGCMAVLink.h"
#include "QGCMAVLinkInspector.h"
#include "MultiVehicleManager.h"
#include "UAS.h"
#include "ui_QGCMAVLinkInspector.h"
#include <QDebug>
......
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