Commit dc9cbc4d authored by Gus Grubba's avatar Gus Grubba

Merge branch 'master' of https://github.com/mavlink/qgroundcontrol into telemetryRSSI

* 'master' of https://github.com/mavlink/qgroundcontrol: (95 commits)
  Only mobile limits line length
  Drag support
  Fix indicator
  Correct background color
  Fix parameter mapping
  No max altitude
  Fixed support for closing all guided dialogs
  Core plugin can override Value Widgets default settings
  Add flightTime to Vehicle FactGroup
  Add support for valueTypeElapsedTimeInSeconds
  Max default mission altitude is 400ft
  Mention voiding warranty in show advanced ui confirmation
  Still trying to fix merge
  Fix merge
  Support load/save/default of NaN for param
  Allow core plugin to disable multi-vehicle
  Stop trying to pull from vehicle
  Support load/save/default of NaN for param
  Add support for FMUv4PRO and FMUv5 boards
  Remove WIP
  ...
parents f556caea fdb99e73
......@@ -6,4 +6,4 @@
url = https://github.com/PX4/GpsDrivers.git
[submodule "libs/mavlink/include/mavlink/v2.0"]
path = libs/mavlink/include/mavlink/v2.0
url = git://github.com/mavlink/c_library_v2.git
url = https://github.com/mavlink/c_library_v2.git
......@@ -173,15 +173,10 @@ script:
fi
#- ccache -s
# unit tests linux/osx
- if [ "${TRAVIS_BRANCH}" != "master" ]; then
if [[ "${SPEC}" = "linux-g++-64" && "${CONFIG}" = "debug" ]]; then
mkdir -p ~/.config/QtProject/ && cp ${TRAVIS_BUILD_DIR}/test/qtlogging.ini ~/.config/QtProject/ &&
./debug/QGroundControl --unittest;
elif [[ "${SPEC}" = "macx-clang" && "${CONFIG}" = "debug" ]]; then
mkdir -p ~/Library/Preferences/QtProject/ && cp ${TRAVIS_BUILD_DIR}/test/qtlogging.ini ~/Library/Preferences/QtProject/ &&
./debug/qgroundcontrol.app/Contents/MacOS/QGroundControl --unittest;
fi
# unit tests linux
- if [[ "${SPEC}" = "linux-g++-64" && "${CONFIG}" = "debug" ]]; then
mkdir -p ~/.config/QtProject/ && cp ${TRAVIS_BUILD_DIR}/test/qtlogging.ini ~/.config/QtProject/ &&
./debug/qgroundcontrol-start.sh --unittest;
fi
after_success:
......
......@@ -69,98 +69,94 @@ WindowsBuild {
QMAKE_POST_LINK += $$escape_expand(\\n) $$QMAKE_COPY \"$$COPY_FILE\" \"$$DESTDIR_WIN\"
}
ReleaseBuild {
ReleaseBuild {
# Copy Visual Studio DLLs
# Note that this is only done for release because the debugging versions of these DLLs cannot be redistributed.
win32-msvc2010 {
QMAKE_POST_LINK += $$escape_expand(\\n) $$QMAKE_COPY \"C:\\Windows\\System32\\msvcp100.dll\" \"$$DESTDIR_WIN\"
QMAKE_POST_LINK += $$escape_expand(\\n) $$QMAKE_COPY \"C:\\Windows\\System32\\msvcr100.dll\" \"$$DESTDIR_WIN\"
}
else:win32-msvc2012 {
} else:win32-msvc2012 {
QMAKE_POST_LINK += $$escape_expand(\\n) $$QMAKE_COPY \"C:\\Windows\\System32\\msvcp110.dll\" \"$$DESTDIR_WIN\"
QMAKE_POST_LINK += $$escape_expand(\\n) $$QMAKE_COPY \"C:\\Windows\\System32\\msvcr110.dll\" \"$$DESTDIR_WIN\"
}
else:win32-msvc2013 {
} else:win32-msvc2013 {
QMAKE_POST_LINK += $$escape_expand(\\n) $$QMAKE_COPY \"C:\\Windows\\System32\\msvcp120.dll\" \"$$DESTDIR_WIN\"
QMAKE_POST_LINK += $$escape_expand(\\n) $$QMAKE_COPY \"C:\\Windows\\System32\\msvcr120.dll\" \"$$DESTDIR_WIN\"
}
else:win32-msvc2015 {
} else:win32-msvc2015 {
QMAKE_POST_LINK += $$escape_expand(\\n) $$QMAKE_COPY \"C:\\Windows\\System32\\msvcp140.dll\" \"$$DESTDIR_WIN\"
QMAKE_POST_LINK += $$escape_expand(\\n) $$QMAKE_COPY \"C:\\Windows\\System32\\vcruntime140.dll\" \"$$DESTDIR_WIN\"
}
else {
} else {
error("Visual studio version not supported, installation cannot be completed.")
}
}
DEPLOY_TARGET = $$shell_quote($$shell_path($$DESTDIR_WIN\\$${TARGET}.exe))
QMAKE_POST_LINK += $$escape_expand(\\n) $$QT_BIN_DIR\\windeployqt --no-compiler-runtime --qmldir=$${BASEDIR_WIN}\\src $${DEPLOY_TARGET}
}
LinuxBuild {
installer {
QMAKE_POST_LINK += && mkdir -p $$DESTDIR/Qt/libs && mkdir -p $$DESTDIR/Qt/plugins
# QT_INSTALL_LIBS
QT_LIB_LIST = \
libQt5Core.so.5 \
libQt5DBus.so.5 \
libQt5Gui.so.5 \
libQt5Location.so.5 \
libQt5Multimedia.so.5 \
libQt5MultimediaQuick_p.so.5 \
libQt5Network.so.5 \
libQt5OpenGL.so.5 \
libQt5Positioning.so.5 \
libQt5PrintSupport.so.5 \
libQt5Qml.so.5 \
libQt5Quick.so.5 \
libQt5QuickWidgets.so.5 \
libQt5SerialPort.so.5 \
libQt5Sql.so.5 \
libQt5Svg.so.5 \
libQt5Test.so.5 \
libQt5Widgets.so.5 \
libQt5XcbQpa.so.5
!contains(DEFINES, __rasp_pi2__) {
QT_LIB_LIST += \
libicudata.so.56 \
libicui18n.so.56 \
libicuuc.so.56
}
QMAKE_POST_LINK += && mkdir -p $$DESTDIR/Qt/libs && mkdir -p $$DESTDIR/Qt/plugins
# QT_INSTALL_LIBS
QT_LIB_LIST = \
libQt5Core.so.5 \
libQt5DBus.so.5 \
libQt5Gui.so.5 \
libQt5Location.so.5 \
libQt5Multimedia.so.5 \
libQt5MultimediaQuick_p.so.5 \
libQt5Network.so.5 \
libQt5OpenGL.so.5 \
libQt5Positioning.so.5 \
libQt5PrintSupport.so.5 \
libQt5Qml.so.5 \
libQt5Quick.so.5 \
libQt5QuickWidgets.so.5 \
libQt5SerialPort.so.5 \
libQt5Sql.so.5 \
libQt5Svg.so.5 \
libQt5Test.so.5 \
libQt5Widgets.so.5 \
libQt5XcbQpa.so.5
!contains(DEFINES, __rasp_pi2__) {
QT_LIB_LIST += \
libicudata.so.56 \
libicui18n.so.56 \
libicuuc.so.56
}
for(QT_LIB, QT_LIB_LIST) {
QMAKE_POST_LINK += && $$QMAKE_COPY --dereference $$[QT_INSTALL_LIBS]/$$QT_LIB $$DESTDIR/Qt/libs/
}
for(QT_LIB, QT_LIB_LIST) {
QMAKE_POST_LINK += && $$QMAKE_COPY --dereference $$[QT_INSTALL_LIBS]/$$QT_LIB $$DESTDIR/Qt/libs/
}
# QT_INSTALL_PLUGINS
QT_PLUGIN_LIST = \
bearer \
geoservices \
iconengines \
imageformats \
platforminputcontexts \
platforms \
position \
sqldrivers
!contains(DEFINES, __rasp_pi2__) {
QT_PLUGIN_LIST += xcbglintegrations
}
# QT_INSTALL_PLUGINS
QT_PLUGIN_LIST = \
bearer \
geoservices \
iconengines \
imageformats \
platforminputcontexts \
platforms \
position \
sqldrivers
!contains(DEFINES, __rasp_pi2__) {
QT_PLUGIN_LIST += xcbglintegrations
}
for(QT_PLUGIN, QT_PLUGIN_LIST) {
QMAKE_POST_LINK += && $$QMAKE_COPY --dereference --recursive $$[QT_INSTALL_PLUGINS]/$$QT_PLUGIN $$DESTDIR/Qt/plugins/
}
for(QT_PLUGIN, QT_PLUGIN_LIST) {
QMAKE_POST_LINK += && $$QMAKE_COPY --dereference --recursive $$[QT_INSTALL_PLUGINS]/$$QT_PLUGIN $$DESTDIR/Qt/plugins/
}
# QT_INSTALL_QML
QMAKE_POST_LINK += && $$QMAKE_COPY --dereference --recursive $$[QT_INSTALL_QML] $$DESTDIR/Qt/
# QT_INSTALL_QML
QMAKE_POST_LINK += && $$QMAKE_COPY --dereference --recursive $$[QT_INSTALL_QML] $$DESTDIR/Qt/
# QGroundControl start script
QMAKE_POST_LINK += && $$QMAKE_COPY $$BASEDIR/deploy/qgroundcontrol-start.sh $$DESTDIR
QMAKE_POST_LINK += && $$QMAKE_COPY $$BASEDIR/deploy/qgroundcontrol.desktop $$DESTDIR
QMAKE_POST_LINK += && $$QMAKE_COPY $$BASEDIR/resources/icons/qgroundcontrol.png $$DESTDIR
}
# QGroundControl start script
QMAKE_POST_LINK += && $$QMAKE_COPY $$BASEDIR/deploy/qgroundcontrol-start.sh $$DESTDIR
QMAKE_POST_LINK += && $$QMAKE_COPY $$BASEDIR/deploy/qgroundcontrol.desktop $$DESTDIR
QMAKE_POST_LINK += && $$QMAKE_COPY $$BASEDIR/resources/icons/qgroundcontrol.png $$DESTDIR
}
......@@ -6,5 +6,7 @@
<file alias="MavCmdInfoRover.json">src/MissionManager/UnitTest/MavCmdInfoRover.json</file>
<file alias="MavCmdInfoSub.json">src/MissionManager/UnitTest/MavCmdInfoSub.json</file>
<file alias="MavCmdInfoVTOL.json">src/MissionManager/UnitTest/MavCmdInfoVTOL.json</file>
<file alias="MissionPlanner.waypoints">src/MissionManager/UnitTest/MissionPlanner.waypoints</file>
<file alias="OldFileFormat.mission">src/MissionManager/UnitTest/OldFileFormat.mission</file>
</qresource>
</RCC>
Subproject commit fb411385d5f00300ab5d04c5adb08e7e17670d58
Subproject commit 9bc6f7d5ecb8c081b554cbd934a20290a5efa529
......@@ -154,6 +154,7 @@
<file alias="TelemRSSI.svg">src/ui/toolbar/Images/TelemRSSI.svg</file>
<file alias="Yield.svg">src/ui/toolbar/Images/Yield.svg</file>
<file alias="CameraIcon.svg">src/ui/toolbar/Images/CameraIcon.svg</file>
<file alias="Joystick.png">src/ui/toolbar/Images/Joystick.png</file>
<file alias="CogWheel.svg">src/MissionManager/CogWheel.svg</file>
<file alias="StationMode.svg">src/AutoPilotPlugins/Common/Images/StationMode.svg</file>
<file alias="APMode.svg">src/AutoPilotPlugins/Common/Images/APMode.svg</file>
......
......@@ -390,6 +390,7 @@ DebugBuild { PX4FirmwarePlugin { PX4FirmwarePluginFactory { APMFirmwarePlugin {
src/MissionManager/MissionControllerTest.h \
src/MissionManager/MissionItemTest.h \
src/MissionManager/MissionManagerTest.h \
src/MissionManager/PlanMasterControllerTest.h \
src/MissionManager/SectionTest.h \
src/MissionManager/SimpleMissionItemTest.h \
src/MissionManager/SpeedSectionTest.h \
......@@ -422,6 +423,7 @@ DebugBuild { PX4FirmwarePlugin { PX4FirmwarePluginFactory { APMFirmwarePlugin {
src/MissionManager/MissionControllerTest.cc \
src/MissionManager/MissionItemTest.cc \
src/MissionManager/MissionManagerTest.cc \
src/MissionManager/PlanMasterControllerTest.cc \
src/MissionManager/SectionTest.cc \
src/MissionManager/SimpleMissionItemTest.cc \
src/MissionManager/SpeedSectionTest.cc \
......@@ -472,6 +474,7 @@ HEADERS += \
src/MissionManager/MissionManager.h \
src/MissionManager/MissionSettingsItem.h \
src/MissionManager/PlanElementController.h \
src/MissionManager/PlanMasterController.h \
src/MissionManager/QGCMapPolygon.h \
src/MissionManager/RallyPoint.h \
src/MissionManager/RallyPointController.h \
......@@ -654,6 +657,7 @@ SOURCES += \
src/MissionManager/MissionManager.cc \
src/MissionManager/MissionSettingsItem.cc \
src/MissionManager/PlanElementController.cc \
src/MissionManager/PlanMasterController.cc \
src/MissionManager/QGCMapPolygon.cc \
src/MissionManager/RallyPoint.cc \
src/MissionManager/RallyPointController.cc \
......
......@@ -10,6 +10,7 @@
<file alias="ModeIndicator.qml">src/ui/toolbar/ModeIndicator.qml</file>
<file alias="RCRSSIIndicator.qml">src/ui/toolbar/RCRSSIIndicator.qml</file>
<file alias="TelemetryRSSIIndicator.qml">src/ui/toolbar/TelemetryRSSIIndicator.qml</file>
<file alias="JoystickIndicator.qml">src/ui/toolbar/JoystickIndicator.qml</file>
</qresource>
<qresource prefix="/qml">
<file alias="AirframeComponent.qml">src/AutoPilotPlugins/PX4/AirframeComponent.qml</file>
......
......@@ -80,9 +80,10 @@ MavlinkConsoleController::_receiveData(uint8_t device, uint8_t, uint16_t, uint32
void
MavlinkConsoleController::_sendSerialData(QByteArray data, bool close)
{
Q_ASSERT(_vehicle);
if (!_vehicle)
if (!_vehicle) {
qWarning() << "Internal error";
return;
}
// Send maximum sized chunks until the complete buffer is transmitted
while(data.size()) {
......
......@@ -92,19 +92,12 @@ SetupPage {
}
function setGimbalSettingsServoInfo(loader, channel) {
var rcPrefix = "RC" + channel + "_"
var rcPrefix = "r.SERVO" + channel + "_"
loader.gimbalOutIndex = channel - 4
loader.servoPWMMinFact = controller.getParameterFact(-1, rcPrefix + "MIN")
loader.servoPWMMaxFact = controller.getParameterFact(-1, rcPrefix + "MAX")
if (controller.parameterExists(-1, "RC5_REVERSED")) {
// Newer firmware parameter
loader.servoReverseFact = controller.getParameterFact(-1, rcPrefix + "REVERSED")
} else {
// Older firmware parameter
loader.servoReverseFact = controller.getParameterFact(-1, rcPrefix + "REV")
}
loader.servoReverseFact = controller.getParameterFact(-1, rcPrefix + "REVERSED")
}
/// Gimbal output channels are stored in SERVO#_FUNCTION parameters. We need to loop through those
......
......@@ -34,15 +34,15 @@ SetupPage {
QGCPalette { id: ggcPal; colorGroupEnabled: true }
property Fact _failsafeGCSEnable: controller.getParameterFact(-1, "FS_GCS_ENABLE")
property Fact _failsafeLeakEnable: controller.getParameterFact(-1, "FS_LEAK_ENABLE")
property Fact _failsafeGCSEnable: controller.getParameterFact(-1, "FS_GCS_ENABLE")
property Fact _failsafeLeakEnable: controller.getParameterFact(-1, "FS_LEAK_ENABLE")
property Fact _failsafePressureEnable: controller.getParameterFact(-1, "FS_PRESS_ENABLE")
property Fact _failsafePressureValue: controller.getParameterFact(-1, "FS_PRESS_MAX")
property Fact _failsafeTempEnable: controller.getParameterFact(-1, "FS_TEMP_ENABLE")
property Fact _failsafeTempValue: controller.getParameterFact(-1, "FS_TEMP_MAX")
property Fact _failsafeTempEnable: controller.getParameterFact(-1, "FS_TEMP_ENABLE")
property Fact _failsafeTempValue: controller.getParameterFact(-1, "FS_TEMP_MAX")
property Fact _fenceAction: controller.getParameterFact(-1, "FENCE_ACTION")
property Fact _fenceAltMax: controller.getParameterFact(-1, "FENCE_ALT_MAX")
property Fact _fenceAltMax: controller.getParameterFact(-1, "r.FENCE_ALT_MIN")
property Fact _fenceEnable: controller.getParameterFact(-1, "FENCE_ENABLE")
property Fact _fenceMargin: controller.getParameterFact(-1, "FENCE_MARGIN")
property Fact _fenceType: controller.getParameterFact(-1, "FENCE_TYPE")
......
......@@ -607,7 +607,8 @@ void APMSensorsComponentController::nextClicked(void)
_vehicle->priorityLink()->mavlinkChannel(),
&msg,
0, // command
1); // result
1, // result
0); // progress
_vehicle->sendMessageOnLink(_vehicle->priorityLink(), msg);
......@@ -677,7 +678,7 @@ void APMSensorsComponentController::_handleMagCalProgress(mavlink_message_t& mes
mavlink_msg_mag_cal_progress_decode(&message, &magCalProgress);
qCDebug(APMSensorsComponentControllerVerboseLog) << "_handleMagCalProgress id:mask:pct"
<< magCalProgress.compass_id << magCalProgress.cal_mask << magCalProgress.completion_pct;
<< magCalProgress.compass_id << magCalProgress.cal_mask << magCalProgress.completion_pct;
// How many compasses are we calibrating?
int compassCalCount = 0;
......@@ -705,7 +706,7 @@ void APMSensorsComponentController::_handleMagCalReport(mavlink_message_t& messa
mavlink_msg_mag_cal_report_decode(&message, &magCalReport);
qCDebug(APMSensorsComponentControllerVerboseLog) << "_handleMagCalReport id:mask:status:fitness"
<< magCalReport.compass_id << magCalReport.cal_mask << magCalReport.cal_status << magCalReport.fitness;
<< magCalReport.compass_id << magCalReport.cal_mask << magCalReport.cal_status << magCalReport.fitness;
bool additionalCompassCompleted = false;
if (magCalReport.compass_id < 3 && !_rgCompassCalComplete[magCalReport.compass_id]) {
......
......@@ -21,7 +21,7 @@ AutoPilotPlugin::AutoPilotPlugin(Vehicle* vehicle, QObject* parent)
: QObject(parent)
, _vehicle(vehicle)
, _firmwarePlugin(vehicle->firmwarePlugin())
, _setupComplete(false)
, _setupComplete(false)
{
}
......@@ -33,27 +33,29 @@ AutoPilotPlugin::~AutoPilotPlugin()
void AutoPilotPlugin::_recalcSetupComplete(void)
{
bool newSetupComplete = true;
foreach(const QVariant componentVariant, vehicleComponents()) {
VehicleComponent* component = qobject_cast<VehicleComponent*>(qvariant_cast<QObject *>(componentVariant));
Q_ASSERT(component);
if (!component->setupComplete()) {
newSetupComplete = false;
break;
}
}
if (_setupComplete != newSetupComplete) {
_setupComplete = newSetupComplete;
emit setupCompleteChanged(_setupComplete);
}
bool newSetupComplete = true;
foreach(const QVariant componentVariant, vehicleComponents()) {
VehicleComponent* component = qobject_cast<VehicleComponent*>(qvariant_cast<QObject *>(componentVariant));
if (component) {
if (!component->setupComplete()) {
newSetupComplete = false;
break;
}
} else {
qWarning() << "AutoPilotPlugin::_recalcSetupComplete Incorrectly typed VehicleComponent";
}
}
if (_setupComplete != newSetupComplete) {
_setupComplete = newSetupComplete;
emit setupCompleteChanged(_setupComplete);
}
}
bool AutoPilotPlugin::setupComplete(void)
{
return _setupComplete;
return _setupComplete;
}
void AutoPilotPlugin::parametersReadyPreChecks(void)
......
......@@ -16,7 +16,9 @@
GenericAutoPilotPlugin::GenericAutoPilotPlugin(Vehicle* vehicle, QObject* parent) :
AutoPilotPlugin(vehicle, parent)
{
Q_ASSERT(vehicle);
if (!vehicle) {
qWarning() << "Internal error";
}
}
const QVariantList& GenericAutoPilotPlugin::vehicleComponents(void)
......
......@@ -15,96 +15,11 @@
#include "QGCQmlWidgetHolder.h"
#include "ParameterManager.h"
#if 0
// Broken by latest mavlink module changes. Not used yet. Comment out for now.
// Discussing mavlink fix.
struct mavType {
int type;
const char* description;
};
/// @brief Used to translate from MAV_TYPE_* id to user string
static const struct mavType mavTypeInfo[] = {
{ MAV_TYPE_GENERIC, "Generic" },
{ MAV_TYPE_FIXED_WING, "Fixed Wing" },
{ MAV_TYPE_QUADROTOR, "Quadrotor" },
{ MAV_TYPE_COAXIAL, "Coaxial" },
{ MAV_TYPE_HELICOPTER, "Helicopter"},
{ MAV_TYPE_ANTENNA_TRACKER, "Antenna Tracker" },
{ MAV_TYPE_GCS, "Ground Control Station" },
{ MAV_TYPE_AIRSHIP, "Airship" },
{ MAV_TYPE_FREE_BALLOON, "Free Balloon" },
{ MAV_TYPE_ROCKET, "Rocket" },
{ MAV_TYPE_GROUND_ROVER, "Ground Rover" },
{ MAV_TYPE_SURFACE_BOAT, "Boat" },
{ MAV_TYPE_SUBMARINE, "Submarine" },
{ MAV_TYPE_HEXAROTOR, "Hexarotor" },
{ MAV_TYPE_OCTOROTOR, "Octorotor" },
{ MAV_TYPE_TRICOPTER, "Tricopter" },
{ MAV_TYPE_FLAPPING_WING, "Flapping Wing" },
{ MAV_TYPE_KITE, "Kite" },
{ MAV_TYPE_ONBOARD_CONTROLLER, "Onbard companion controller" },
{ MAV_TYPE_VTOL_DUOROTOR, "Two-rotor VTOL" },
{ MAV_TYPE_VTOL_QUADROTOR, "Quad-rotor VTOL" },
{ MAV_TYPE_VTOL_RESERVED1, "Reserved" },
{ MAV_TYPE_VTOL_RESERVED2, "Reserved" },
{ MAV_TYPE_VTOL_RESERVED3, "Reserved" },
{ MAV_TYPE_VTOL_RESERVED4, "Reserved" },
{ MAV_TYPE_VTOL_RESERVED5, "Reserved" },
{ MAV_TYPE_GIMBAL, "Gimbal" },
};
static size_t cMavTypes = sizeof(mavTypeInfo) / sizeof(mavTypeInfo[0]);
#endif
AirframeComponent::AirframeComponent(Vehicle* vehicle, AutoPilotPlugin* autopilot, QObject* parent) :
VehicleComponent(vehicle, autopilot, parent),
_name(tr("Airframe"))
{
#if 0
// Broken by latest mavlink module changes. Not used yet. Comment out for now.
// Discussing mavlink fix.
Q_UNUSED(mavTypeInfo); // Keeping this around for later use
// Validate that our mavTypeInfo array hasn't gotten out of sync
qDebug() << cMavTypes << MAV_TYPE_ENUM_END;
Q_ASSERT(cMavTypes == MAV_TYPE_ENUM_END);
static const int mavTypes[] = {
MAV_TYPE_GENERIC,
MAV_TYPE_FIXED_WING,
MAV_TYPE_QUADROTOR,
MAV_TYPE_COAXIAL,
MAV_TYPE_HELICOPTER,
MAV_TYPE_ANTENNA_TRACKER,
MAV_TYPE_GCS,
MAV_TYPE_AIRSHIP,
MAV_TYPE_FREE_BALLOON,
MAV_TYPE_ROCKET,
MAV_TYPE_GROUND_ROVER,
MAV_TYPE_SURFACE_BOAT,
MAV_TYPE_SUBMARINE,
MAV_TYPE_HEXAROTOR,
MAV_TYPE_OCTOROTOR,
MAV_TYPE_TRICOPTER,
MAV_TYPE_FLAPPING_WING,
MAV_TYPE_KITE,
MAV_TYPE_ONBOARD_CONTROLLER,
MAV_TYPE_VTOL_DUOROTOR,
MAV_TYPE_VTOL_QUADROTOR,
MAV_TYPE_VTOL_RESERVED1,
MAV_TYPE_VTOL_RESERVED2,
MAV_TYPE_VTOL_RESERVED3,
MAV_TYPE_VTOL_RESERVED4,
MAV_TYPE_VTOL_RESERVED5,
MAV_TYPE_GIMBAL,
};
Q_UNUSED(mavTypes); // Keeping this around for later use
for (size_t i=0; i<cMavTypes; i++) {
Q_ASSERT(mavTypeInfo[i].type == mavTypes[i]);
}
#endif
}
QString AirframeComponent::name(void) const
......
......@@ -57,7 +57,9 @@ AirframeComponentController::AirframeComponentController(void) :
Q_CHECK_PTR(pInfo);
if (_autostartId == pInfo->autostartId) {
Q_ASSERT(!autostartFound);
if (autostartFound) {
qWarning() << "AirframeComponentController::AirframeComponentController duplicate ids found:" << _autostartId;
}
autostartFound = true;
_currentAirframeType = pType->name;
_currentVehicleName = pInfo->name;
......
......@@ -30,7 +30,6 @@ PX4AirframeLoader::PX4AirframeLoader(AutoPilotPlugin* autopilot, UASInterface* u
Q_UNUSED(autopilot);
Q_UNUSED(uas);
Q_UNUSED(parent);
Q_ASSERT(uas);
}
QString PX4AirframeLoader::aiframeMetaDataFile(void)
......@@ -51,7 +50,10 @@ void PX4AirframeLoader::loadAirframeMetaData(void)
qCDebug(PX4AirframeLoaderLog) << "Loading PX4 airframe fact meta data";
Q_ASSERT(AirframeComponentAirframes::get().count() == 0);
if (AirframeComponentAirframes::get().count() != 0) {
qCWarning(PX4AirframeLoaderLog) << "Internal error";
return;
}
QString airframeFilename;
......@@ -67,11 +69,12 @@ void PX4AirframeLoader::loadAirframeMetaData(void)
qCDebug(PX4AirframeLoaderLog) << "Loading meta data file:" << airframeFilename;
QFile xmlFile(airframeFilename);
Q_ASSERT(xmlFile.exists());
if (!xmlFile.exists()) {
qCWarning(PX4AirframeLoaderLog) << "Internal error";
return;
}
bool success = xmlFile.open(QIODevice::ReadOnly);
Q_UNUSED(success);
Q_ASSERT(success);
if (!success) {
qCWarning(PX4AirframeLoaderLog) << "Failed opening airframe XML";
......
......@@ -41,7 +41,10 @@ PX4AutoPilotPlugin::PX4AutoPilotPlugin(Vehicle* vehicle, QObject* parent)
, _tuningComponent(NULL)
, _mixersComponent(NULL)
{
Q_ASSERT(vehicle);
if (!vehicle) {
qWarning() << "Internal error";
return;
}
_airframeFacts = new PX4AirframeLoader(this, _vehicle->uas(), this);
Q_CHECK_PTR(_airframeFacts);
......@@ -57,68 +60,70 @@ PX4AutoPilotPlugin::~PX4AutoPilotPlugin()
const QVariantList& PX4AutoPilotPlugin::vehicleComponents(void)
{
if (_components.count() == 0 && !_incorrectParameterVersion) {
Q_ASSERT(_vehicle);
if (_vehicle->parameterManager()->parametersReady()) {
_airframeComponent = new AirframeComponent(_vehicle, this);
_airframeComponent->setupTriggerSignals();
_components.append(QVariant::fromValue((VehicleComponent*)_airframeComponent));
_radioComponent = new PX4RadioComponent(_vehicle, this);
_radioComponent->setupTriggerSignals();
_components.append(QVariant::fromValue((VehicleComponent*)_radioComponent));
if (!_vehicle->hilMode()) {
_sensorsComponent = new SensorsComponent(_vehicle, this);
_sensorsComponent->setupTriggerSignals();
_components.append(QVariant::fromValue((VehicleComponent*)_sensorsComponent));
}
_flightModesComponent = new FlightModesComponent(_vehicle, this);
_flightModesComponent->setupTriggerSignals();
_components.append(QVariant::fromValue((VehicleComponent*)_flightModesComponent));
_powerComponent = new PowerComponent(_vehicle, this);
_powerComponent->setupTriggerSignals();
_components.append(QVariant::fromValue((VehicleComponent*)_powerComponent));
if (_vehicle) {
if (_vehicle->parameterManager()->parametersReady()) {
_airframeComponent = new AirframeComponent(_vehicle, this);
_airframeComponent->setupTriggerSignals();
_components.append(QVariant::fromValue((VehicleComponent*)_airframeComponent));
_radioComponent = new PX4RadioComponent(_vehicle, this);
_radioComponent->setupTriggerSignals();
_components.append(QVariant::fromValue((VehicleComponent*)_radioComponent));
if (!_vehicle->hilMode()) {
_sensorsComponent = new SensorsComponent(_vehicle, this);
_sensorsComponent->setupTriggerSignals();
_components.append(QVariant::fromValue((VehicleComponent*)_sensorsComponent));
}
_flightModesComponent = new FlightModesComponent(_vehicle, this);
_flightModesComponent->setupTriggerSignals();
_components.append(QVariant::fromValue((VehicleComponent*)_flightModesComponent));
_powerComponent = new PowerComponent(_vehicle, this);
_powerComponent->setupTriggerSignals();
_components.append(QVariant::fromValue((VehicleComponent*)_powerComponent));
#if 0
// Coming soon
_motorComponent = new MotorComponent(_vehicle, this);
_motorComponent->setupTriggerSignals();
_components.append(QVariant::fromValue((VehicleComponent*)_motorComponent));
// Coming soon
_motorComponent = new MotorComponent(_vehicle, this);
_motorComponent->setupTriggerSignals();
_components.append(QVariant::fromValue((VehicleComponent*)_motorComponent));
#endif
_safetyComponent = new SafetyComponent(_vehicle, this);
_safetyComponent->setupTriggerSignals();
_components.append(QVariant::fromValue((VehicleComponent*)_safetyComponent));
_safetyComponent = new SafetyComponent(_vehicle, this);
_safetyComponent->setupTriggerSignals();
_components.append(QVariant::fromValue((VehicleComponent*)_safetyComponent));
_tuningComponent = new PX4TuningComponent(_vehicle, this);
_tuningComponent->setupTriggerSignals();
_components.append(QVariant::fromValue((VehicleComponent*)_tuningComponent));
_tuningComponent = new PX4TuningComponent(_vehicle, this);
_tuningComponent->setupTriggerSignals();
_components.append(QVariant::fromValue((VehicleComponent*)_tuningComponent));
#if 0
// Coming soon
_mixersComponent = new MixersComponent(_vehicle, this);
_mixersComponent->setupTriggerSignals();
_components.append(QVariant::fromValue((VehicleComponent*)_mixersComponent));
// Coming soon
_mixersComponent = new MixersComponent(_vehicle, this);
_mixersComponent->setupTriggerSignals();
_components.append(QVariant::fromValue((VehicleComponent*)_mixersComponent));
#endif
//-- Is there support for cameras?
if(_vehicle->parameterManager()->parameterExists(_vehicle->id(), "TRIG_MODE")) {
_cameraComponent = new CameraComponent(_vehicle, this);
_cameraComponent->setupTriggerSignals();
_components.append(QVariant::fromValue((VehicleComponent*)_cameraComponent));
}
//-- Is there an ESP8266 Connected?
if(_vehicle->parameterManager()->parameterExists(MAV_COMP_ID_UDP_BRIDGE, "SW_VER")) {
_esp8266Component = new ESP8266Component(_vehicle, this);
_esp8266Component->setupTriggerSignals();
_components.append(QVariant::fromValue((VehicleComponent*)_esp8266Component));
//-- Is there support for cameras?
if(_vehicle->parameterManager()->parameterExists(_vehicle->id(), "TRIG_MODE")) {
_cameraComponent = new CameraComponent(_vehicle, this);
_cameraComponent->setupTriggerSignals();
_components.append(QVariant::fromValue((VehicleComponent*)_cameraComponent));
}
//-- Is there an ESP8266 Connected?
if(_vehicle->parameterManager()->parameterExists(MAV_COMP_ID_UDP_BRIDGE, "SW_VER")) {
_esp8266Component = new ESP8266Component(_vehicle, this);
_esp8266Component->setupTriggerSignals();
_components.append(QVariant::fromValue((VehicleComponent*)_esp8266Component));
}
} else {
qWarning() << "Call to vehicleCompenents prior to parametersReady";
}
} else {
qWarning() << "Call to vehicleCompenents prior to parametersReady";
qWarning() << "Internal error";
}
}
......
......@@ -123,7 +123,7 @@ SetupPage {
sourceSize.height: height
mipmap: true
fillMode: Image.PreserveAspectFit
source: "/qmlimages/check.png"///qgcPal.globalTheme === qgcPal.Light ? "/qmlimages/LowBatteryLight.svg" : "/qmlimages/LowBattery.svg"
source: qgcPal.globalTheme === qgcPal.Light ? "/qmlimages/LowBatteryLight.svg" : "/qmlimages/LowBattery.svg"
Layout.rowSpan: 3
Layout.minimumWidth: _imageWidth
}
......@@ -177,7 +177,7 @@ SetupPage {
sourceSize.height: height
mipmap: true
fillMode: Image.PreserveAspectFit
//source: qgcPal.globalTheme === qgcPal.Light ? "/qmlimages/RCLossLight.svg" : "/qmlimages/RCLoss.svg"
source: qgcPal.globalTheme === qgcPal.Light ? "/qmlimages/RCLossLight.svg" : "/qmlimages/RCLoss.svg"
Layout.rowSpan: 3
Layout.minimumWidth: _imageWidth
}
......@@ -222,7 +222,7 @@ SetupPage {
sourceSize.height: height
mipmap: true
fillMode: Image.PreserveAspectFit
//source: qgcPal.globalTheme === qgcPal.Light ? "/qmlimages/DatalinkLossLight.svg" : "/qmlimages/DatalinkLoss.svg"
source: qgcPal.globalTheme === qgcPal.Light ? "/qmlimages/DatalinkLossLight.svg" : "/qmlimages/DatalinkLoss.svg"
Layout.rowSpan: 3
Layout.minimumWidth: _imageWidth
}
......@@ -267,7 +267,7 @@ SetupPage {
sourceSize.height: height
mipmap: true
fillMode: Image.PreserveAspectFit
//source: qgcPal.globalTheme === qgcPal.Light ? "/qmlimages/GeoFenceLight.svg" : "/qmlimages/GeoFence.svg"
source: qgcPal.globalTheme === qgcPal.Light ? "/qmlimages/GeoFenceLight.svg" : "/qmlimages/GeoFence.svg"
Layout.rowSpan: 3
Layout.minimumWidth: _imageWidth
}
......@@ -330,7 +330,7 @@ SetupPage {
sourceSize.height: height
mipmap: true
fillMode: Image.PreserveAspectFit
//source: controller.vehicle.fixedWing ? "/qmlimages/ReturnToHomeAltitude.svg" : "/qmlimages/ReturnToHomeAltitudeCopter.svg"
source: controller.vehicle.fixedWing ? "/qmlimages/ReturnToHomeAltitude.svg" : "/qmlimages/ReturnToHomeAltitudeCopter.svg"
Layout.rowSpan: 7
Layout.minimumWidth: _imageWidth
}
......@@ -424,7 +424,7 @@ SetupPage {
sourceSize.height: height
mipmap: true
fillMode: Image.PreserveAspectFit
//source: controller.vehicle.fixedWing ? "/qmlimages/LandMode.svg" : "/qmlimages/LandModeCopter.svg"
source: controller.vehicle.fixedWing ? "/qmlimages/LandMode.svg" : "/qmlimages/LandModeCopter.svg"
Layout.rowSpan: landVelocityLabel.visible ? 2 : 1
Layout.minimumWidth: _imageWidth
}
......
......@@ -73,7 +73,10 @@ bool SensorsComponentController::usingUDPLink(void)
/// Appends the specified text to the status log area in the ui
void SensorsComponentController::_appendStatusLog(const QString& text)
{
Q_ASSERT(_statusLog);
if (!_statusLog) {
qWarning() << "Internal error";
return;
}
QVariant returnedValue;
QVariant varText = text;
......@@ -229,8 +232,11 @@ void SensorsComponentController::_handleUASTextMessage(int uasId, int compId, in
bool ok;
int p = percent.toInt(&ok);
if (ok) {
Q_ASSERT(_progressBar);
_progressBar->setProperty("value", (float)(p / 100.0));
if (_progressBar) {
_progressBar->setProperty("value", (float)(p / 100.0));
} else {
qWarning() << "Internal error";
}
}
return;
}
......@@ -324,7 +330,7 @@ void SensorsComponentController::_handleUASTextMessage(int uasId, int compId, in
_gyroCalInProgress = true;
_orientationCalDownSideVisible = true;
} else {
Q_ASSERT(false);
qWarning() << "Unknown calibration message type" << text;
}
emit orientationCalSidesDoneChanged();
emit orientationCalSidesVisibleChanged();
......
......@@ -270,6 +270,18 @@ QString Fact::_variantToString(const QVariant& variant, int decimalPlaces) const
}
}
break;
case FactMetaData::valueTypeElapsedTimeInSeconds:
{
double dValue = variant.toDouble();
if (qIsNaN(dValue)) {
valueString = QStringLiteral("--:--:--");
} else {
QTime time(0, 0, 0, 0);
time = time.addSecs(dValue);
valueString = time.toString(QStringLiteral("hh:mm:ss"));
}
}
break;
default:
valueString = variant.toString();
break;
......
......@@ -34,9 +34,10 @@ const qreal FactMetaData::UnitConsts_s::inchesToCentimeters = 2.54;
// Built in translations for all Facts
const FactMetaData::BuiltInTranslation_s FactMetaData::_rgBuiltInTranslations[] = {
{ "centi-degrees", "deg", FactMetaData::_centiDegreesToDegrees, FactMetaData::_degreesToCentiDegrees },
{ "radians", "deg", FactMetaData::_radiansToDegrees, FactMetaData::_degreesToRadians },
{ "norm", "%", FactMetaData::_normToPercent, FactMetaData::_percentToNorm },
{ "centi-degrees", "deg", FactMetaData::_centiDegreesToDegrees, FactMetaData::_degreesToCentiDegrees },
{ "radians", "deg", FactMetaData::_radiansToDegrees, FactMetaData::_degreesToRadians },
{ "gimbal-degrees", "deg", FactMetaData::_mavlinkGimbalDegreesToUserGimbalDegrees, FactMetaData::_userGimbalDegreesToMavlinkGimbalDegrees },
{ "norm", "%", FactMetaData::_normToPercent, FactMetaData::_percentToNorm },
};
// Translations driven by app settings
......@@ -209,6 +210,8 @@ QVariant FactMetaData::_minForType(void) const
return QVariant();
case valueTypeBool:
return QVariant(0);
case valueTypeElapsedTimeInSeconds:
return QVariant(0.0);
}
// Make windows compiler happy, even switch is full cased
......@@ -232,6 +235,7 @@ QVariant FactMetaData::_maxForType(void) const
return QVariant(std::numeric_limits<int>::max());
case valueTypeFloat:
return QVariant(std::numeric_limits<float>::max());
case valueTypeElapsedTimeInSeconds:
case valueTypeDouble:
return QVariant(std::numeric_limits<double>::max());
case valueTypeString:
......@@ -256,36 +260,34 @@ bool FactMetaData::convertAndValidateRaw(const QVariant& rawValue, bool convertO
case FactMetaData::valueTypeInt32:
typedValue = QVariant(rawValue.toInt(&convertOk));
if (!convertOnly && convertOk) {
if (rawMin() > typedValue || typedValue > rawMax()) {
if (typedValue < rawMin() || typedValue > rawMax()) {
errorString = QString("Value must be within %1 and %2").arg(cookedMin().toInt()).arg(cookedMax().toInt());
}
}
break;
case FactMetaData::valueTypeUint8:
case FactMetaData::valueTypeUint16:
case FactMetaData::valueTypeUint32:
typedValue = QVariant(rawValue.toUInt(&convertOk));
if (!convertOnly && convertOk) {
if (rawMin() > typedValue || typedValue > rawMax()) {
if (typedValue < rawMin() || typedValue > rawMax()) {
errorString = QString("Value must be within %1 and %2").arg(cookedMin().toUInt()).arg(cookedMax().toUInt());
}
}
break;
case FactMetaData::valueTypeFloat:
typedValue = QVariant(rawValue.toFloat(&convertOk));
if (!convertOnly && convertOk) {
if (rawMin() > typedValue || typedValue > rawMax()) {
if (typedValue < rawMin() || typedValue > rawMax()) {
errorString = QString("Value must be within %1 and %2").arg(cookedMin().toFloat()).arg(cookedMax().toFloat());
}
}
break;
case FactMetaData::valueTypeElapsedTimeInSeconds:
case FactMetaData::valueTypeDouble:
typedValue = QVariant(rawValue.toDouble(&convertOk));
if (!convertOnly && convertOk) {
if (rawMin() > typedValue || typedValue > rawMax()) {
if (typedValue < rawMin() || typedValue > rawMax()) {
errorString = QString("Value must be within %1 and %2").arg(cookedMin().toDouble()).arg(cookedMax().toDouble());
}
}
......@@ -324,7 +326,6 @@ bool FactMetaData::convertAndValidateCooked(const QVariant& cookedValue, bool co
}
}
break;
case FactMetaData::valueTypeUint8:
case FactMetaData::valueTypeUint16:
case FactMetaData::valueTypeUint32:
......@@ -335,7 +336,6 @@ bool FactMetaData::convertAndValidateCooked(const QVariant& cookedValue, bool co
}
}
break;
case FactMetaData::valueTypeFloat:
typedValue = QVariant(cookedValue.toFloat(&convertOk));
if (!convertOnly && convertOk) {
......@@ -344,7 +344,7 @@ bool FactMetaData::convertAndValidateCooked(const QVariant& cookedValue, bool co
}
}
break;
case FactMetaData::valueTypeElapsedTimeInSeconds:
case FactMetaData::valueTypeDouble:
typedValue = QVariant(cookedValue.toDouble(&convertOk));
if (!convertOnly && convertOk) {
......@@ -455,6 +455,20 @@ QVariant FactMetaData::_degreesToCentiDegrees(const QVariant& degrees)
return QVariant(qRound(degrees.toReal() * 100.0));
}
QVariant FactMetaData::_userGimbalDegreesToMavlinkGimbalDegrees(const QVariant& userGimbalDegrees)
{
// User facing gimbal degree values are from 0 (level) to 90 (straight down)
// Mavlink gimbal degree values are from 0 (level) to -90 (straight down)
return userGimbalDegrees.toDouble() * -1.0;
}
QVariant FactMetaData::_mavlinkGimbalDegreesToUserGimbalDegrees(const QVariant& mavlinkGimbalDegrees)
{
// User facing gimbal degree values are from 0 (level) to 90 (straight down)
// Mavlink gimbal degree values are from 0 (level) to -90 (straight down)
return mavlinkGimbalDegrees.toDouble() * -1.0;
}
QVariant FactMetaData::_metersToFeet(const QVariant& meters)
{
return QVariant(meters.toDouble() * 1.0/constants.feetToMeters);
......@@ -589,7 +603,8 @@ FactMetaData::ValueType_t FactMetaData::stringToType(const QString& typeString,
<< QStringLiteral("Float")
<< QStringLiteral("Double")
<< QStringLiteral("String")
<< QStringLiteral("Bool");
<< QStringLiteral("Bool")
<< QStringLiteral("ElapsedSeconds");
knownTypes << valueTypeUint8
<< valueTypeInt8
......@@ -600,7 +615,8 @@ FactMetaData::ValueType_t FactMetaData::stringToType(const QString& typeString,
<< valueTypeFloat
<< valueTypeDouble
<< valueTypeString
<< valueTypeBool;
<< valueTypeBool
<< valueTypeElapsedTimeInSeconds;
for (int i=0; i<knownTypeStrings.count(); i++) {
if (knownTypeStrings[i].compare(typeString, Qt::CaseInsensitive) == 0) {
......@@ -908,3 +924,29 @@ QMap<QString, FactMetaData*> FactMetaData::createMapFromJsonFile(const QString&
return metaDataMap;
}
QVariant FactMetaData::cookedMax(void) const
{
// We have to be careful with cooked min/max. Running the raw values through the translator could flip min and max.
QVariant cookedMax = _rawTranslator(_rawMax);
QVariant cookedMin = _rawTranslator(_rawMin);
if (cookedMax < cookedMin) {
// We need to flip
return cookedMin;
} else {
return cookedMax;
}
}
QVariant FactMetaData::cookedMin(void) const
{
// We have to be careful with cooked min/max. Running the raw values through the translator could flip min and max.
QVariant cookedMax = _rawTranslator(_rawMax);
QVariant cookedMin = _rawTranslator(_rawMin);
if (cookedMax < cookedMin) {
// We need to flip
return cookedMax;
} else {
return cookedMin;
}
}
......@@ -39,7 +39,8 @@ public:
valueTypeFloat,
valueTypeDouble,
valueTypeString,
valueTypeBool
valueTypeBool,
valueTypeElapsedTimeInSeconds, // Internally stored as double, valueString displays as HH:MM:SS
} ValueType_t;
typedef QVariant (*Translator)(const QVariant& from);
......@@ -83,10 +84,10 @@ public:
QString group (void) const { return _group; }
QString longDescription (void) const { return _longDescription;}
QVariant rawMax (void) const { return _rawMax; }
QVariant cookedMax (void) const { return _rawTranslator(_rawMax); }
QVariant cookedMax (void) const;
bool maxIsDefaultForType (void) const { return _maxIsDefaultForType; }
QVariant rawMin (void) const { return _rawMin; }
QVariant cookedMin (void) const { return _rawTranslator(_rawMin); }
QVariant cookedMin (void) const;
bool minIsDefaultForType (void) const { return _minIsDefaultForType; }
QString name (void) const { return _name; }
QString shortDescription (void) const { return _shortDescription; }
......@@ -155,6 +156,8 @@ private:
static QVariant _radiansToDegrees(const QVariant& radians);
static QVariant _centiDegreesToDegrees(const QVariant& centiDegrees);
static QVariant _degreesToCentiDegrees(const QVariant& degrees);
static QVariant _userGimbalDegreesToMavlinkGimbalDegrees(const QVariant& userGimbalDegrees);
static QVariant _mavlinkGimbalDegreesToUserGimbalDegrees(const QVariant& mavlinkGimbalDegrees);
static QVariant _metersToFeet(const QVariant& meters);
static QVariant _feetToMeters(const QVariant& feet);
static QVariant _squareMetersToSquareKilometers(const QVariant& squareMeters);
......
......@@ -303,11 +303,15 @@ void ParameterManager::_parameterUpdate(int vehicleId, int componentId, QString
_dataMutex.unlock();
Q_ASSERT(_mapParameterName2Variant[componentId].contains(parameterName));
Fact* fact = _mapParameterName2Variant[componentId][parameterName].value<Fact*>();
Q_ASSERT(fact);
fact->_containerSetRawValue(value);
Fact* fact = NULL;
if (_mapParameterName2Variant[componentId].contains(parameterName)) {
fact = _mapParameterName2Variant[componentId][parameterName].value<Fact*>();
}
if (fact) {
fact->_containerSetRawValue(value);
} else {
qWarning() << "Internal error";
}
if (componentParamsComplete) {
if (componentId == _vehicle->defaultComponentId()) {
......@@ -352,18 +356,24 @@ void ParameterManager::_parameterUpdate(int vehicleId, int componentId, QString
void ParameterManager::_valueUpdated(const QVariant& value)
{
Fact* fact = qobject_cast<Fact*>(sender());
Q_ASSERT(fact);
if (!fact) {
qWarning() << "Internal error";
return;
}
int componentId = fact->componentId();
QString name = fact->name();
_dataMutex.lock();
Q_ASSERT(_waitingWriteParamNameMap.contains(componentId));
_waitingWriteParamNameMap[componentId].remove(name); // Remove any old entry
_waitingWriteParamNameMap[componentId][name] = 0; // Add new entry and set retry count
_waitingParamTimeoutTimer.start();
_saveRequired = true;
if (_waitingWriteParamNameMap.contains(componentId)) {
_waitingWriteParamNameMap[componentId].remove(name); // Remove any old entry
_waitingWriteParamNameMap[componentId][name] = 0; // Add new entry and set retry count
_waitingParamTimeoutTimer.start();
_saveRequired = true;
} else {
qWarning() << "Internal error";
}
_dataMutex.unlock();
......@@ -397,7 +407,6 @@ void ParameterManager::refreshAllParameters(uint8_t componentId)
_dataMutex.unlock();
MAVLinkProtocol* mavlink = qgcApp()->toolbox()->mavlinkProtocol();
Q_ASSERT(mavlink);
mavlink_message_t msg;
mavlink_msg_param_request_list_pack_chan(mavlink->getSystemId(),
......@@ -432,8 +441,6 @@ void ParameterManager::refreshParameter(int componentId, const QString& name)
_dataMutex.lock();
Q_ASSERT(_waitingReadParamNameMap.contains(componentId));
if (_waitingReadParamNameMap.contains(componentId)) {
QString mappedParamName = _remapParamNameToVersion(name);
......@@ -441,6 +448,8 @@ void ParameterManager::refreshParameter(int componentId, const QString& name)
_waitingReadParamNameMap[componentId][mappedParamName] = 0; // Add new wait entry and update retry count
qCDebug(ParameterManagerLog) << _logVehiclePrefix(componentId) << "restarting _waitingParamTimeout";
_waitingParamTimeoutTimer.start();
} else {
qWarning() << "Internal error";
}
_dataMutex.unlock();
......
......@@ -444,7 +444,7 @@ void APMFirmwarePlugin::_handleIncomingHeartbeat(Vehicle* vehicle, mavlink_messa
}
}
vehicle->setFlying(flying);
vehicle->_setFlying(flying);
}
bool APMFirmwarePlugin::adjustIncomingMavlinkMessage(Vehicle* vehicle, mavlink_message_t* message)
......
......@@ -82,6 +82,7 @@ void APMGeoFenceManager::sendToVehicle(const QGeoCoordinate& breachReturn, QmlOb
// Total point count, +1 polygon close in last index, +1 for breach in index 0
_cWriteFencePoints = validatedPolygonCount ? validatedPolygonCount + 1 + 1 : 0;
qCDebug(GeoFenceManagerLog) << "APMGeoFenceManager::sendToVehicle validatedPolygonCount:_cWriteFencePoints" << validatedPolygonCount << _cWriteFencePoints;
_vehicle->parameterManager()->getParameter(FactSystem::defaultComponentId, _fenceTotalParam)->setRawValue(_cWriteFencePoints);
// FIXME: No validation of correct fence received
......@@ -89,7 +90,7 @@ void APMGeoFenceManager::sendToVehicle(const QGeoCoordinate& breachReturn, QmlOb
_sendFencePoint(index);
}
emit loadComplete(_breachReturnPoint, _polygon);
emit sendComplete(false /* error */);
}
void APMGeoFenceManager::loadFromVehicle(void)
......@@ -132,7 +133,7 @@ void APMGeoFenceManager::loadFromVehicle(void)
_requestFencePoint(_currentFencePoint);
}
/// Called when a new mavlink message for out vehicle is received
/// Called when a new mavlink message for our vehicle is received
void APMGeoFenceManager::_mavlinkMessageReceived(const mavlink_message_t& message)
{
if (message.msgid == MAVLINK_MSG_ID_FENCE_POINT) {
......@@ -326,7 +327,10 @@ void APMGeoFenceManager::_parametersReady(void)
void APMGeoFenceManager::removeAll(void)
{
qCDebug(GeoFenceManagerLog) << "APMGeoFenceManager::removeAll";
QmlObjectListModel emptyPolygon;
sendToVehicle(_breachReturnPoint, emptyPolygon);
emit removeAllComplete(false /* error */);
}
......@@ -52,6 +52,7 @@ QVariant APMParameterMetaData::_stringToTypedVariant(const QString& string,
case FactMetaData::valueTypeFloat:
convertTo = QMetaType::Float;
break;
case FactMetaData::valueTypeElapsedTimeInSeconds:
case FactMetaData::valueTypeDouble:
convertTo = QVariant::Double;
break;
......
......@@ -48,7 +48,7 @@ void APMRallyPointManager::sendToVehicle(const QList<QGeoCoordinate>& rgPoints)
_sendRallyPoint(index);
}
emit loadComplete(_rgPoints);
emit sendComplete(false /* error */);
}
void APMRallyPointManager::loadFromVehicle(void)
......@@ -60,7 +60,7 @@ void APMRallyPointManager::loadFromVehicle(void)
_rgPoints.clear();
_cReadRallyPoints = _vehicle->parameterManager()->getParameter(FactSystem::defaultComponentId, _rallyTotalParam)->rawValue().toInt();
qCDebug(GeoFenceManagerLog) << "APMGeoFenceManager::loadFromVehicle" << _cReadRallyPoints;
qCDebug(RallyPointManagerLog) << "APMRallyPointManager::loadFromVehicle - point count" << _cReadRallyPoints;
if (_cReadRallyPoints == 0) {
emit loadComplete(_rgPoints);
return;
......@@ -152,7 +152,10 @@ bool APMRallyPointManager::rallyPointsSupported(void) const
void APMRallyPointManager::removeAll(void)
{
qCDebug(RallyPointManagerLog) << "APMRallyPointManager::removeAll";
QList<QGeoCoordinate> noRallyPoints;
sendToVehicle(noRallyPoints);
emit removeAllComplete(false /* error */);
}
......@@ -108,6 +108,39 @@ ArduCopterFirmwarePlugin::ArduCopterFirmwarePlugin(void)
remapV3_5["SERVO13_FUNCTION"] = QStringLiteral("RC13_FUNCTION");
remapV3_5["SERVO14_FUNCTION"] = QStringLiteral("RC14_FUNCTION");
remapV3_5["SERVO5_MIN"] = QStringLiteral("RC5_MIN");
remapV3_5["SERVO6_MIN"] = QStringLiteral("RC6_MIN");
remapV3_5["SERVO7_MIN"] = QStringLiteral("RC7_MIN");
remapV3_5["SERVO8_MIN"] = QStringLiteral("RC8_MIN");
remapV3_5["SERVO9_MIN"] = QStringLiteral("RC9_MIN");
remapV3_5["SERVO10_MIN"] = QStringLiteral("RC10_MIN");
remapV3_5["SERVO11_MIN"] = QStringLiteral("RC11_MIN");
remapV3_5["SERVO12_MIN"] = QStringLiteral("RC12_MIN");
remapV3_5["SERVO13_MIN"] = QStringLiteral("RC13_MIN");
remapV3_5["SERVO14_MIN"] = QStringLiteral("RC14_MIN");
remapV3_5["SERVO5_MAX"] = QStringLiteral("RC5_MAX");
remapV3_5["SERVO6_MAX"] = QStringLiteral("RC6_MAX");
remapV3_5["SERVO7_MAX"] = QStringLiteral("RC7_MAX");
remapV3_5["SERVO8_MAX"] = QStringLiteral("RC8_MAX");
remapV3_5["SERVO9_MAX"] = QStringLiteral("RC9_MAX");
remapV3_5["SERVO10_MAX"] = QStringLiteral("RC10_MAX");
remapV3_5["SERVO11_MAX"] = QStringLiteral("RC11_MAX");
remapV3_5["SERVO12_MAX"] = QStringLiteral("RC12_MAX");
remapV3_5["SERVO13_MAX"] = QStringLiteral("RC13_MAX");
remapV3_5["SERVO14_MAX"] = QStringLiteral("RC14_MAX");
remapV3_5["SERVO5_REVERSED"] = QStringLiteral("RC5_REVERSED");
remapV3_5["SERVO6_REVERSED"] = QStringLiteral("RC6_REVERSED");
remapV3_5["SERVO7_REVERSED"] = QStringLiteral("RC7_REVERSED");
remapV3_5["SERVO8_REVERSED"] = QStringLiteral("RC8_REVERSED");
remapV3_5["SERVO9_REVERSED"] = QStringLiteral("RC9_REVERSED");
remapV3_5["SERVO10_REVERSED"] = QStringLiteral("RC10_REVERSED");
remapV3_5["SERVO11_REVERSED"] = QStringLiteral("RC11_REVERSED");
remapV3_5["SERVO12_REVERSED"] = QStringLiteral("RC12_REVERSED");
remapV3_5["SERVO13_REVERSED"] = QStringLiteral("RC13_REVERSED");
remapV3_5["SERVO14_REVERSED"] = QStringLiteral("RC14_REVERSED");
_remapParamNameIntialized = true;
}
}
......@@ -139,7 +172,7 @@ void ArduCopterFirmwarePlugin::guidedModeLand(Vehicle* vehicle)
void ArduCopterFirmwarePlugin::guidedModeTakeoff(Vehicle* vehicle)
{
if (!_armVehicle(vehicle)) {
if (!_armVehicleAndValidate(vehicle)) {
qgcApp()->showMessage(tr("Unable to takeoff: Vehicle failed to arm."));
return;
}
......@@ -237,23 +270,13 @@ QString ArduCopterFirmwarePlugin::geoFenceRadiusParam(Vehicle* vehicle)
bool ArduCopterFirmwarePlugin::vehicleYawsToNextWaypointInMission(const Vehicle* vehicle) const
{
if (!vehicle->isOfflineEditingVehicle() && vehicle->parameterManager()->parameterExists(FactSystem::defaultComponentId, QStringLiteral("WP_YAW_BEHAVIOR"))) {
Fact* yawMode = vehicle->parameterManager()->getParameter(FactSystem::defaultComponentId, QStringLiteral("WP_YAW_BEHAVIOR"));
return yawMode && yawMode->rawValue().toInt() != 0;
if (vehicle->isOfflineEditingVehicle()) {
return FirmwarePlugin::vehicleYawsToNextWaypointInMission(vehicle);
} else {
if (vehicle->multiRotor() && vehicle->parameterManager()->parameterExists(FactSystem::defaultComponentId, QStringLiteral("WP_YAW_BEHAVIOR"))) {
Fact* yawMode = vehicle->parameterManager()->getParameter(FactSystem::defaultComponentId, QStringLiteral("WP_YAW_BEHAVIOR"));
return yawMode && yawMode->rawValue().toInt() != 0;
}
}
return true;
}
void ArduCopterFirmwarePlugin::missionFlightSpeedInfo(Vehicle* vehicle, double& hoverSpeed, double& cruiseSpeed)
{
QString hoverSpeedParam("WPNAV_SPEED");
// First pull settings defaults
FirmwarePlugin::missionFlightSpeedInfo(vehicle, hoverSpeed, cruiseSpeed);
cruiseSpeed = 0;
if (vehicle->parameterManager()->parameterExists(FactSystem::defaultComponentId, hoverSpeedParam)) {
Fact* speed = vehicle->parameterManager()->getParameter(FactSystem::defaultComponentId, hoverSpeedParam);
hoverSpeed = speed->rawValue().toDouble() / 100; // cm/s -> m/s
}
}
......@@ -76,7 +76,6 @@ public:
QString takeControlFlightMode(void) const override { return QString("Stablize"); }
bool vehicleYawsToNextWaypointInMission(const Vehicle* vehicle) const final;
QString autoDisarmParameter(Vehicle* vehicle) final { Q_UNUSED(vehicle); return QStringLiteral("DISARM_DELAY"); }
void missionFlightSpeedInfo(Vehicle* vehicle, double& hoverSpeed, double& cruiseSpeed) override;
private:
static bool _remapParamNameIntialized;
......
......@@ -77,6 +77,39 @@ ArduPlaneFirmwarePlugin::ArduPlaneFirmwarePlugin(void)
remapV3_8["SERVO13_FUNCTION"] = QStringLiteral("RC13_FUNCTION");
remapV3_8["SERVO14_FUNCTION"] = QStringLiteral("RC14_FUNCTION");
remapV3_8["SERVO5_MIN"] = QStringLiteral("RC5_MIN");
remapV3_8["SERVO6_MIN"] = QStringLiteral("RC6_MIN");
remapV3_8["SERVO7_MIN"] = QStringLiteral("RC7_MIN");
remapV3_8["SERVO8_MIN"] = QStringLiteral("RC8_MIN");
remapV3_8["SERVO9_MIN"] = QStringLiteral("RC9_MIN");
remapV3_8["SERVO10_MIN"] = QStringLiteral("RC10_MIN");
remapV3_8["SERVO11_MIN"] = QStringLiteral("RC11_MIN");
remapV3_8["SERVO12_MIN"] = QStringLiteral("RC12_MIN");
remapV3_8["SERVO13_MIN"] = QStringLiteral("RC13_MIN");
remapV3_8["SERVO14_MIN"] = QStringLiteral("RC14_MIN");
remapV3_8["SERVO5_MAX"] = QStringLiteral("RC5_MAX");
remapV3_8["SERVO6_MAX"] = QStringLiteral("RC6_MAX");
remapV3_8["SERVO7_MAX"] = QStringLiteral("RC7_MAX");
remapV3_8["SERVO8_MAX"] = QStringLiteral("RC8_MAX");
remapV3_8["SERVO9_MAX"] = QStringLiteral("RC9_MAX");
remapV3_8["SERVO10_MAX"] = QStringLiteral("RC10_MAX");
remapV3_8["SERVO11_MAX"] = QStringLiteral("RC11_MAX");
remapV3_8["SERVO12_MAX"] = QStringLiteral("RC12_MAX");
remapV3_8["SERVO13_MAX"] = QStringLiteral("RC13_MAX");
remapV3_8["SERVO14_MAX"] = QStringLiteral("RC14_MAX");
remapV3_8["SERVO5_REVERSED"] = QStringLiteral("RC5_REVERSED");
remapV3_8["SERVO6_REVERSED"] = QStringLiteral("RC6_REVERSED");
remapV3_8["SERVO7_REVERSED"] = QStringLiteral("RC7_REVERSED");
remapV3_8["SERVO8_REVERSED"] = QStringLiteral("RC8_REVERSED");
remapV3_8["SERVO9_REVERSED"] = QStringLiteral("RC9_REVERSED");
remapV3_8["SERVO10_REVERSED"] = QStringLiteral("RC10_REVERSED");
remapV3_8["SERVO11_REVERSED"] = QStringLiteral("RC11_REVERSED");
remapV3_8["SERVO12_REVERSED"] = QStringLiteral("RC12_REVERSED");
remapV3_8["SERVO13_REVERSED"] = QStringLiteral("RC13_REVERSED");
remapV3_8["SERVO14_REVERSED"] = QStringLiteral("RC14_REVERSED");
_remapParamNameIntialized = true;
}
}
......
......@@ -55,6 +55,39 @@ ArduRoverFirmwarePlugin::ArduRoverFirmwarePlugin(void)
remapV3_2["SERVO13_FUNCTION"] = QStringLiteral("RC13_FUNCTION");
remapV3_2["SERVO14_FUNCTION"] = QStringLiteral("RC14_FUNCTION");
remapV3_2["SERVO5_MIN"] = QStringLiteral("RC5_MIN");
remapV3_2["SERVO6_MIN"] = QStringLiteral("RC6_MIN");
remapV3_2["SERVO7_MIN"] = QStringLiteral("RC7_MIN");
remapV3_2["SERVO8_MIN"] = QStringLiteral("RC8_MIN");
remapV3_2["SERVO9_MIN"] = QStringLiteral("RC9_MIN");
remapV3_2["SERVO10_MIN"] = QStringLiteral("RC10_MIN");
remapV3_2["SERVO11_MIN"] = QStringLiteral("RC11_MIN");
remapV3_2["SERVO12_MIN"] = QStringLiteral("RC12_MIN");
remapV3_2["SERVO13_MIN"] = QStringLiteral("RC13_MIN");
remapV3_2["SERVO14_MIN"] = QStringLiteral("RC14_MIN");
remapV3_2["SERVO5_MAX"] = QStringLiteral("RC5_MAX");
remapV3_2["SERVO6_MAX"] = QStringLiteral("RC6_MAX");
remapV3_2["SERVO7_MAX"] = QStringLiteral("RC7_MAX");
remapV3_2["SERVO8_MAX"] = QStringLiteral("RC8_MAX");
remapV3_2["SERVO9_MAX"] = QStringLiteral("RC9_MAX");
remapV3_2["SERVO10_MAX"] = QStringLiteral("RC10_MAX");
remapV3_2["SERVO11_MAX"] = QStringLiteral("RC11_MAX");
remapV3_2["SERVO12_MAX"] = QStringLiteral("RC12_MAX");
remapV3_2["SERVO13_MAX"] = QStringLiteral("RC13_MAX");
remapV3_2["SERVO14_MAX"] = QStringLiteral("RC14_MAX");
remapV3_2["SERVO5_REVERSED"] = QStringLiteral("RC5_REVERSED");
remapV3_2["SERVO6_REVERSED"] = QStringLiteral("RC6_REVERSED");
remapV3_2["SERVO7_REVERSED"] = QStringLiteral("RC7_REVERSED");
remapV3_2["SERVO8_REVERSED"] = QStringLiteral("RC8_REVERSED");
remapV3_2["SERVO9_REVERSED"] = QStringLiteral("RC9_REVERSED");
remapV3_2["SERVO10_REVERSED"] = QStringLiteral("RC10_REVERSED");
remapV3_2["SERVO11_REVERSED"] = QStringLiteral("RC11_REVERSED");
remapV3_2["SERVO12_REVERSED"] = QStringLiteral("RC12_REVERSED");
remapV3_2["SERVO13_REVERSED"] = QStringLiteral("RC13_REVERSED");
remapV3_2["SERVO14_REVERSED"] = QStringLiteral("RC14_REVERSED");
_remapParamNameIntialized = true;
}
}
......
......@@ -62,6 +62,41 @@ ArduSubFirmwarePlugin::ArduSubFirmwarePlugin(void)
remapV3_5["SERVO13_FUNCTION"] = QStringLiteral("RC13_FUNCTION");
remapV3_5["SERVO14_FUNCTION"] = QStringLiteral("RC14_FUNCTION");
remapV3_5["SERVO5_MIN"] = QStringLiteral("RC5_MIN");
remapV3_5["SERVO6_MIN"] = QStringLiteral("RC6_MIN");
remapV3_5["SERVO7_MIN"] = QStringLiteral("RC7_MIN");
remapV3_5["SERVO8_MIN"] = QStringLiteral("RC8_MIN");
remapV3_5["SERVO9_MIN"] = QStringLiteral("RC9_MIN");
remapV3_5["SERVO10_MIN"] = QStringLiteral("RC10_MIN");
remapV3_5["SERVO11_MIN"] = QStringLiteral("RC11_MIN");
remapV3_5["SERVO12_MIN"] = QStringLiteral("RC12_MIN");
remapV3_5["SERVO13_MIN"] = QStringLiteral("RC13_MIN");
remapV3_5["SERVO14_MIN"] = QStringLiteral("RC14_MIN");
remapV3_5["SERVO5_MAX"] = QStringLiteral("RC5_MAX");
remapV3_5["SERVO6_MAX"] = QStringLiteral("RC6_MAX");
remapV3_5["SERVO7_MAX"] = QStringLiteral("RC7_MAX");
remapV3_5["SERVO8_MAX"] = QStringLiteral("RC8_MAX");
remapV3_5["SERVO9_MAX"] = QStringLiteral("RC9_MAX");
remapV3_5["SERVO10_MAX"] = QStringLiteral("RC10_MAX");
remapV3_5["SERVO11_MAX"] = QStringLiteral("RC11_MAX");
remapV3_5["SERVO12_MAX"] = QStringLiteral("RC12_MAX");
remapV3_5["SERVO13_MAX"] = QStringLiteral("RC13_MAX");
remapV3_5["SERVO14_MAX"] = QStringLiteral("RC14_MAX");
remapV3_5["SERVO5_REVERSED"] = QStringLiteral("RC5_REVERSED");
remapV3_5["SERVO6_REVERSED"] = QStringLiteral("RC6_REVERSED");
remapV3_5["SERVO7_REVERSED"] = QStringLiteral("RC7_REVERSED");
remapV3_5["SERVO8_REVERSED"] = QStringLiteral("RC8_REVERSED");
remapV3_5["SERVO9_REVERSED"] = QStringLiteral("RC9_REVERSED");
remapV3_5["SERVO10_REVERSED"] = QStringLiteral("RC10_REVERSED");
remapV3_5["SERVO11_REVERSED"] = QStringLiteral("RC11_REVERSED");
remapV3_5["SERVO12_REVERSED"] = QStringLiteral("RC12_REVERSED");
remapV3_5["SERVO13_REVERSED"] = QStringLiteral("RC13_REVERSED");
remapV3_5["SERVO14_REVERSED"] = QStringLiteral("RC14_REVERSED");
remapV3_5["FENCE_ALT_MIN"] = QStringLiteral("FENCE_DEPTH_MAX");
_remapParamNameIntialized = true;
}
}
......@@ -115,6 +150,7 @@ const QVariantList& ArduSubFirmwarePlugin::toolBarIndicators(const Vehicle* vehi
_toolBarIndicators.append(QVariant::fromValue(QUrl::fromUserInput("qrc:/toolbar/MessageIndicator.qml")));
_toolBarIndicators.append(QVariant::fromValue(QUrl::fromUserInput("qrc:/toolbar/BatteryIndicator.qml")));
_toolBarIndicators.append(QVariant::fromValue(QUrl::fromUserInput("qrc:/toolbar/ModeIndicator.qml")));
_toolBarIndicators.append(QVariant::fromValue(QUrl::fromUserInput("qrc:/toolbar/JoystickIndicator.qml")));
}
return _toolBarIndicators;
}
......@@ -435,7 +435,7 @@ bool FirmwarePlugin::vehicleYawsToNextWaypointInMission(const Vehicle* vehicle)
return vehicle->multiRotor() ? false : true;
}
bool FirmwarePlugin::_armVehicle(Vehicle* vehicle)
bool FirmwarePlugin::_armVehicleAndValidate(Vehicle* vehicle)
{
if (!vehicle->armed()) {
vehicle->setArmed(true);
......@@ -466,12 +466,11 @@ QString FirmwarePlugin::autoDisarmParameter(Vehicle* vehicle)
return QString();
}
void FirmwarePlugin::missionFlightSpeedInfo(Vehicle* vehicle, double& hoverSpeed, double& cruiseSpeed)
bool FirmwarePlugin::hasGimbal(Vehicle* vehicle, bool& rollSupported, bool& pitchSupported, bool& yawSupported)
{
Q_UNUSED(vehicle);
// Best we can do is use settings
AppSettings* appSettings = qgcApp()->toolbox()->settingsManager()->appSettings();
hoverSpeed = appSettings->offlineEditingHoverSpeed()->rawValue().toDouble();
cruiseSpeed = appSettings->offlineEditingCruiseSpeed()->rawValue().toDouble();
rollSupported = false;
pitchSupported = false;
yawSupported = false;
return false;
}
......@@ -282,21 +282,23 @@ public:
/// @param[out] cruiseAmps Current draw in amps during cruise
virtual void batteryConsumptionData(Vehicle* vehicle, int& mAhBattery, double& hoverAmps, double& cruiseAmps) const;
/// Returns the default mission flight speeds.
/// @param[out] hoverSpeed Flight speed for vehicle flying in multi-rotor mode. 0 for none, or not available.
/// @param[out] cruiseSpeed Flight speed for vehicle flying in fixed wing forward flight mode. 0 for none, or not available.
virtual void missionFlightSpeedInfo(Vehicle* vehicle, double& hoverSpeed, double& cruiseSpeed);
// Returns the parameter which control auto-dismar. Assume == 0 means no auto disarm
// Returns the parameter which control auto-disarm. Assume == 0 means no auto disarm
virtual QString autoDisarmParameter(Vehicle* vehicle);
/// Used to determine whether a vehicle has a gimbal.
/// @param[out] rollSupported Gimbal supports roll
/// @param[out] pitchSupported Gimbal supports pitch
/// @param[out] yawSupported Gimbal supports yaw
/// @return true: vehicle has gimbal, false: gimbal support unknown
virtual bool hasGimbal(Vehicle* vehicle, bool& rollSupported, bool& pitchSupported, bool& yawSupported);
// FIXME: Hack workaround for non pluginize FollowMe support
static const char* px4FollowMeFlightMode;
protected:
// Arms the vehicle, waiting for the arm state to change.
// @return: true - vehicle armed, false - vehicle failed to arm
bool _armVehicle(Vehicle* vehicle);
bool _armVehicleAndValidate(Vehicle* vehicle);
private:
QVariantList _toolBarIndicatorList;
......
......@@ -352,6 +352,29 @@ void PX4FirmwarePlugin::guidedModeOrbit(Vehicle* vehicle, const QGeoCoordinate&
centerCoord.isValid() ? centerCoord.altitude() : NAN);
}
void PX4FirmwarePlugin::_mavCommandResult(int vehicleId, int component, int command, int result, bool noReponseFromVehicle)
{
Q_UNUSED(vehicleId);
Q_UNUSED(component);
Q_UNUSED(noReponseFromVehicle);
Vehicle* vehicle = dynamic_cast<Vehicle*>(sender());
if (!vehicle) {
qWarning() << "Dynamic cast failed!";
return;
}
if (command == MAV_CMD_NAV_TAKEOFF && result == MAV_RESULT_ACCEPTED) {
// Now that we are in takeoff mode we can arm the vehicle which will cause it to takeoff.
// We specifically don't retry arming if it fails. This way we don't fight with the user if
// They are trying to disarm.
disconnect(vehicle, &Vehicle::mavCommandResult, this, &PX4FirmwarePlugin::_mavCommandResult);
if (!vehicle->armed()) {
vehicle->setArmed(true);
}
}
}
void PX4FirmwarePlugin::guidedModeTakeoff(Vehicle* vehicle)
{
QString takeoffAltParam("MIS_TAKEOFF_ALT");
......@@ -367,11 +390,7 @@ void PX4FirmwarePlugin::guidedModeTakeoff(Vehicle* vehicle)
}
Fact* takeoffAlt = vehicle->parameterManager()->getParameter(FactSystem::defaultComponentId, takeoffAltParam);
if (!_armVehicle(vehicle)) {
qgcApp()->showMessage(tr("Unable to takeoff: Vehicle failed to arm."));
return;
}
connect(vehicle, &Vehicle::mavCommandResult, this, &PX4FirmwarePlugin::_mavCommandResult);
vehicle->sendMavCommand(vehicle->defaultComponentId(),
MAV_CMD_NAV_TAKEOFF,
true, // show error is fails
......@@ -436,7 +455,7 @@ void PX4FirmwarePlugin::guidedModeChangeAltitude(Vehicle* vehicle, double altitu
void PX4FirmwarePlugin::startMission(Vehicle* vehicle)
{
if (!_armVehicle(vehicle)) {
if (!_armVehicleAndValidate(vehicle)) {
qgcApp()->showMessage(tr("Unable to start mission: Vehicle failed to arm."));
return;
}
......@@ -518,27 +537,13 @@ void PX4FirmwarePlugin::_handleAutopilotVersion(Vehicle* vehicle, mavlink_messag
bool PX4FirmwarePlugin::vehicleYawsToNextWaypointInMission(const Vehicle* vehicle) const
{
if (!vehicle->isOfflineEditingVehicle() && vehicle->parameterManager()->parameterExists(FactSystem::defaultComponentId, QStringLiteral("MIS_YAWMODE"))) {
Fact* yawMode = vehicle->parameterManager()->getParameter(FactSystem::defaultComponentId, QStringLiteral("MIS_YAWMODE"));
return yawMode && yawMode->rawValue().toInt() == 1;
if (vehicle->isOfflineEditingVehicle()) {
return FirmwarePlugin::vehicleYawsToNextWaypointInMission(vehicle);
} else {
if (vehicle->multiRotor() && vehicle->parameterManager()->parameterExists(FactSystem::defaultComponentId, QStringLiteral("MIS_YAWMODE"))) {
Fact* yawMode = vehicle->parameterManager()->getParameter(FactSystem::defaultComponentId, QStringLiteral("MIS_YAWMODE"));
return yawMode && yawMode->rawValue().toInt() == 1;
}
}
return true;
}
void PX4FirmwarePlugin::missionFlightSpeedInfo(Vehicle* vehicle, double& hoverSpeed, double& cruiseSpeed)
{
QString hoverSpeedParam("MPC_XY_CRUISE");
QString cruiseSpeedParam("FW_AIRSPD_TRIM");
// First pull settings defaults
FirmwarePlugin::missionFlightSpeedInfo(vehicle, hoverSpeed, cruiseSpeed);
if (vehicle->parameterManager()->parameterExists(FactSystem::defaultComponentId, hoverSpeedParam)) {
Fact* speed = vehicle->parameterManager()->getParameter(FactSystem::defaultComponentId, hoverSpeedParam);
hoverSpeed = speed->rawValue().toDouble();
}
if (vehicle->parameterManager()->parameterExists(FactSystem::defaultComponentId, cruiseSpeedParam)) {
Fact* speed = vehicle->parameterManager()->getParameter(FactSystem::defaultComponentId, cruiseSpeedParam);
cruiseSpeed = speed->rawValue().toDouble();
}
}
......@@ -68,7 +68,6 @@ public:
QString brandImageOutdoor (const Vehicle* vehicle) const override { Q_UNUSED(vehicle); return QStringLiteral("/qmlimages/PX4/BrandImage"); }
bool vehicleYawsToNextWaypointInMission(const Vehicle* vehicle) const override;
QString autoDisarmParameter (Vehicle* vehicle) override { Q_UNUSED(vehicle); return QStringLiteral("COM_DISARM_LAND"); }
void missionFlightSpeedInfo (Vehicle* vehicle, double& hoverSpeed, double& cruiseSpeed) override;
protected:
typedef struct {
......@@ -103,6 +102,9 @@ protected:
QString _followMeFlightMode;
QString _simpleFlightMode;
private slots:
void _mavCommandResult(int vehicleId, int component, int command, int result, bool noReponseFromVehicle);
private:
void _handleAutopilotVersion(Vehicle* vehicle, mavlink_message_t* message);
......
......@@ -38,14 +38,18 @@ QGCView {
property bool activeVehicleJoystickEnabled: _activeVehicle ? _activeVehicle.joystickEnabled : false
property var _activeVehicle: QGroundControl.multiVehicleManager.activeVehicle
property bool _mainIsMap: QGroundControl.videoManager.hasVideo ? QGroundControl.loadBoolGlobalSetting(_mainIsMapKey, true) : true
property bool _isPipVisible: QGroundControl.videoManager.hasVideo ? QGroundControl.loadBoolGlobalSetting(_PIPVisibleKey, true) : false
property real _savedZoomLevel: 0
property real _margins: ScreenTools.defaultFontPixelWidth / 2
property real _pipSize: mainWindow.width * 0.2
property alias _guidedController: guidedActionsController
property alias _altitudeSlider: altitudeSlider
property var _planMasterController: masterController
property var _missionController: _planMasterController.missionController
property var _geoFenceController: _planMasterController.geoFenceController
property var _rallyPointController: _planMasterController.rallyPointController
property var _activeVehicle: QGroundControl.multiVehicleManager.activeVehicle
property bool _mainIsMap: QGroundControl.videoManager.hasVideo ? QGroundControl.loadBoolGlobalSetting(_mainIsMapKey, true) : true
property bool _isPipVisible: QGroundControl.videoManager.hasVideo ? QGroundControl.loadBoolGlobalSetting(_PIPVisibleKey, true) : false
property real _savedZoomLevel: 0
property real _margins: ScreenTools.defaultFontPixelWidth / 2
property real _pipSize: mainWindow.width * 0.2
property alias _guidedController: guidedActionsController
property alias _altitudeSlider: altitudeSlider
readonly property bool isBackgroundDark: _mainIsMap ? (_flightMap ? _flightMap.isSatelliteMap : true) : true
......@@ -92,20 +96,14 @@ QGCView {
}
}
MissionController {
id: flyMissionController
PlanElemementMasterController {
id: masterController
Component.onCompleted: start(false /* editMode */)
onResumeMissionReady: guidedActionsController.confirmAction(guidedActionsController.actionResumeMissionReady)
}
GeoFenceController {
id: flyGeoFenceController
Component.onCompleted: start(false /* editMode */)
}
RallyPointController {
id: flyRallyPointController
Component.onCompleted: start(false /* editMode */)
Connections {
target: _missionController
onResumeMissionReady: guidedActionsController.confirmAction(guidedActionsController.actionResumeMissionReady)
}
MessageDialog {
......@@ -116,7 +114,7 @@ QGCView {
}
Connections {
target: QGroundControl.multiVehicleManager
target: QGroundControl.multiVehicleManager
onActiveVehicleChanged: px4JoystickCheck()
}
......@@ -149,7 +147,7 @@ QGCView {
vehicleWasArmed = true
}
} else {
if (promptForMissionRemove && (flyMissionController.containsItems || flyGeoFenceController.containsItems || flyRallyPointController.containsItems)) {
if (promptForMissionRemove && (_missionController.containsItems || _geoFenceController.containsItems || _rallyPointController.containsItems)) {
root.showDialog(removeMissionDialogComponent, qsTr("Flight complete"), showDialogDefaultWidth, StandardButton.No | StandardButton.Yes)
}
promptForMissionRemove = false
......@@ -169,11 +167,8 @@ QGCView {
message: qsTr("Do you want to remove the mission from the vehicle?")
function accept() {
flyMissionController.removeAllFromVehicle()
flyGeoFenceController.removeAllFromVehicle()
flyRallyPointController.removeAllFromVehicle()
_planMasterController.removeAllFromVehicle()
hideDialog()
}
}
}
......@@ -214,9 +209,7 @@ QGCView {
FlightDisplayViewMap {
id: _flightMap
anchors.fill: parent
missionController: flyMissionController
geoFenceController: flyGeoFenceController
rallyPointController: flyRallyPointController
planMasterController: masterController
guidedActionsController: _guidedController
flightWidgets: flightDisplayViewWidgets
rightPanelWidth: ScreenTools.defaultFontPixelHeight * 9
......@@ -320,7 +313,7 @@ QGCView {
anchors.bottom: parent.bottom
qgcView: root
useLightColors: isBackgroundDark
missionController: _flightMap.missionController
missionController: _missionController
visible: singleVehicleView.checked
}
......@@ -489,11 +482,7 @@ QGCView {
]
onClicked: {
//-- Dismiss any other dialog
rootLoader.sourceComponent = null
guidedActionConfirm.visible = false
guidedActionList.visible = false
altitudeSlider.visible = false
guidedActionsController.closeAll()
var action = model[index].action
if (action === -1) {
if (index == 4) {
......@@ -511,7 +500,7 @@ QGCView {
GuidedActionsController {
id: guidedActionsController
missionController: flyMissionController
missionController: _missionController
confirmDialog: guidedActionConfirm
z: _flightVideoPipControl.z + 1
......@@ -532,6 +521,20 @@ QGCView {
confirmAction(actionResumeMission)
}
}
onShowLandAbortChanged: {
if (showLandAbort) {
confirmAction(actionLandAbort)
}
}
/// Close all dialogs
function closeAll() {
rootLoader.sourceComponent = null
guidedActionConfirm.visible = false
guidedActionList.visible = false
altitudeSlider.visible = false
}
}
GuidedActionConfirm {
......
......@@ -34,9 +34,7 @@ FlightMap {
property alias scaleState: mapScale.state
// The following properties must be set by the consumer
property var missionController
property var geoFenceController
property var rallyPointController
property var planMasterController
property var guidedActionsController
property var flightWidgets
property var rightPanelWidth
......@@ -44,6 +42,10 @@ FlightMap {
property rect centerViewport: Qt.rect(0, 0, width, height)
property var _planMasterController: planMasterController
property var _missionController: _planMasterController.missionController
property var _geoFenceController: _planMasterController.geoFenceController
property var _rallyPointController: _planMasterController.rallyPointController
property var _activeVehicle: QGroundControl.multiVehicleManager.activeVehicle
property var _activeVehicleCoordinate: _activeVehicle ? _activeVehicle.coordinate : QtPositioning.coordinate()
property var _gotoHereCoordinate: QtPositioning.coordinate()
......@@ -58,8 +60,12 @@ FlightMap {
// When the user pans the map we stop responding to vehicle coordinate updates until the panRecenterTimer fires
onUserPannedChanged: {
_disableVehicleTracking = true
panRecenterTimer.start()
if (userPanned) {
console.log("user panned")
userPanned = false
_disableVehicleTracking = true
panRecenterTimer.restart()
}
}
function pointInRect(point, rect) {
......@@ -132,10 +138,10 @@ FlightMap {
QGCMapPalette { id: mapPal; lightColors: isSatelliteMap }
Connections {
target: missionController
target: _missionController
onNewItemsFromVehicle: {
var visualItems = missionController.visualItems
var visualItems = _missionController.visualItems
if (visualItems && visualItems.count != 1) {
mapFitFunctions.fitMapViewportToMissionItems()
firstVehiclePositionReceived = true
......@@ -151,9 +157,7 @@ FlightMap {
id: mapFitFunctions
map: _flightMap
usePlannedHomePosition: false
mapMissionController: missionController
mapGeoFenceController: geoFenceController
mapRallyPointController: rallyPointController
planMasterController: _planMasterController
property real leftToolWidth: toolStrip.x + toolStrip.width
}
......@@ -188,7 +192,7 @@ FlightMap {
// Add the mission item visuals to the map
Repeater {
model: _mainIsMap ? missionController.visualItems : 0
model: _mainIsMap ? _missionController.visualItems : 0
delegate: MissionItemMapVisual {
map: flightMap
......@@ -198,12 +202,12 @@ FlightMap {
// Add lines between waypoints
MissionLineView {
model: _mainIsMap ? missionController.waypointLines : 0
model: _mainIsMap ? _missionController.waypointLines : 0
}
GeoFenceMapVisuals {
map: flightMap
myGeoFenceController: geoFenceController
myGeoFenceController: _geoFenceController
interactive: false
planView: false
homePosition: _activeVehicle && _activeVehicle.homePosition.isValid ? _activeVehicle.homePosition : undefined
......@@ -211,7 +215,7 @@ FlightMap {
// Rally points on map
MapItemView {
model: rallyPointController.points
model: _rallyPointController.points
delegate: MapQuickItem {
id: itemIndicator
......@@ -241,9 +245,9 @@ FlightMap {
}
}
// Camera points
// Camera trigger points
MapItemView {
model: missionController.cameraPoints
model: _activeVehicle ? _activeVehicle.cameraTriggerPoints : 0
delegate: CameraTriggerIndicator {
coordinate: object.coordinate
......
......@@ -50,10 +50,10 @@ Item {
readonly property string disarmMessage: qsTr("Disarm the vehicle")
readonly property string emergencyStopMessage: qsTr("WARNING: This still stop all motors. If vehicle is currently in air it will crash.")
readonly property string takeoffMessage: qsTr("Takeoff from ground and hold position.")
readonly property string startMissionMessage: qsTr("Start the mission which is currently displayed above. If the vehicle is on the ground it will takeoff.")
readonly property string startMissionMessage: qsTr("Takeoff from ground and start the current mission.")
readonly property string continueMissionMessage: qsTr("Continue the mission from the current waypoint.")
property string resumeMissionMessage: qsTr("Resume the mission which is displayed above. This will re-generate the mission from waypoint %1, takeoff and continue the mission.").arg(_resumeMissionIndex)
readonly property string resumeMissionReadyMessage: qsTr("Review the modified mission above. Confirm if you want to takeoff and begin mission.")
property string resumeMissionMessage: qsTr("Resume the current mission. This will re-generate the mission from waypoint %1, takeoff and continue the mission.").arg(_resumeMissionIndex)
readonly property string resumeMissionReadyMessage: qsTr("Review the modified mission. Confirm if you want to takeoff and begin mission.")
readonly property string landMessage: qsTr("Land the vehicle at the current position.")
readonly property string rtlMessage: qsTr("Return to the home position of the vehicle.")
readonly property string changeAltMessage: qsTr("Change the altitude of the vehicle up or down.")
......@@ -87,12 +87,12 @@ Item {
property bool showTakeoff: _activeVehicle && _activeVehicle.guidedModeSupported && !_vehicleFlying && !_activeVehicle.fixedWing
property bool showLand: _activeVehicle && _activeVehicle.guidedModeSupported && _vehicleArmed && !_activeVehicle.fixedWing && !_vehicleInLandMode
property bool showStartMission: _activeVehicle && _missionAvailable && !_missionActive && !_vehicleFlying
property bool showContinueMission: _activeVehicle && _missionAvailable && !_missionActive && _vehicleFlying
property bool showResumeMission: _activeVehicle && !_vehicleFlying && _missionAvailable && _resumeMissionIndex > 0
property bool showContinueMission: _activeVehicle && _missionAvailable && !_missionActive && _vehicleFlying && (_currentMissionIndex < missionController.visualItems.count - 1)
property bool showResumeMission: _activeVehicle && !_vehicleFlying && _missionAvailable && _resumeMissionIndex > 0 && (_resumeMissionIndex < missionController.visualItems.count - 2)
property bool showPause: _activeVehicle && _vehicleArmed && _activeVehicle.pauseVehicleSupported && _vehicleFlying && !_vehiclePaused
property bool showChangeAlt: (_activeVehicle && _vehicleFlying) && _activeVehicle.guidedModeSupported && _vehicleArmed && !_missionActive
property bool showOrbit: !_hideOrbit && _activeVehicle && _vehicleFlying && _activeVehicle.orbitModeSupported && _vehicleArmed && !_missionActive
property bool showLandAbort: _activeVehicle && _vehicleFlying && _activeVehicle.fixedWing
property bool showLandAbort: _activeVehicle && _vehicleFlying && _activeVehicle.fixedWing && _vehicleLanding
property bool showGotoLocation: _activeVehicle && _activeVehicle.guidedMode && _vehicleFlying
property var _activeVehicle: QGroundControl.multiVehicleManager.activeVehicle
......@@ -101,15 +101,19 @@ Item {
property bool _missionActive: _activeVehicle ? _vehicleArmed && (_vehicleInLandMode || _vehicleInRTLMode || _vehicleInMissionMode) : false
property bool _vehicleArmed: _activeVehicle ? _activeVehicle.armed : false
property bool _vehicleFlying: _activeVehicle ? _activeVehicle.flying : false
property bool _vehicleLanding: _activeVehicle ? _activeVehicle.landing : false
property bool _vehiclePaused: false
property bool _vehicleInMissionMode: false
property bool _vehicleInRTLMode: false
property bool _vehicleInLandMode: false
property int _currentMissionIndex: missionController.currentMissionIndex
property int _resumeMissionIndex: missionController.resumeMissionIndex
property bool _hideEmergenyStop: !QGroundControl.corePlugin.options.guidedBarShowEmergencyStop
property bool _hideOrbit: !QGroundControl.corePlugin.options.guidedBarShowOrbit
property var _actionData
on_CurrentMissionIndexChanged: console.log("_currentMissionIndex", _currentMissionIndex)
on_FlightModeChanged: {
_vehiclePaused = _flightMode === _activeVehicle.pauseFlightMode
_vehicleInRTLMode = _flightMode === _activeVehicle.rtlFlightMode
......@@ -119,6 +123,7 @@ Item {
// Called when an action is about to be executed in order to confirm
function confirmAction(actionCode, actionData) {
closeAll()
confirmDialog.action = actionCode
confirmDialog.actionData = actionData
_actionData = actionData
......
......@@ -57,6 +57,9 @@ VideoManager::setToolbox(QGCToolbox *toolbox)
_videoSettings = toolbox->settingsManager()->videoSettings();
QString videoSource = _videoSettings->videoSource()->rawValue().toString();
connect(_videoSettings->videoSource(), &Fact::rawValueChanged, this, &VideoManager::_videoSourceChanged);
connect(_videoSettings->udpPort(), &Fact::rawValueChanged, this, &VideoManager::_udpPortChanged);
connect(_videoSettings->rtspUrl(), &Fact::rawValueChanged, this, &VideoManager::_rtspUrlChanged);
#if defined(QGC_GST_STREAMING)
#ifndef QGC_DISABLE_UVC
......@@ -96,6 +99,17 @@ void VideoManager::_videoSourceChanged(void)
{
emit hasVideoChanged();
emit isGStreamerChanged();
_restartVideo();
}
void VideoManager::_udpPortChanged(void)
{
_restartVideo();
}
void VideoManager::_rtspUrlChanged(void)
{
_restartVideo();
}
//-----------------------------------------------------------------------------
......@@ -170,6 +184,18 @@ void VideoManager::_updateTimer()
#endif
}
//-----------------------------------------------------------------------------
void VideoManager::_updateSettings()
{
if(!_videoSettings || !_videoReceiver)
return;
if (_videoSettings->videoSource()->rawValue().toString() == VideoSettings::videoSourceUDP)
_videoReceiver->setUri(QStringLiteral("udp://0.0.0.0:%1").arg(_videoSettings->udpPort()->rawValue().toInt()));
else
_videoReceiver->setUri(_videoSettings->rtspUrl()->rawValue().toString());
}
//-----------------------------------------------------------------------------
void VideoManager::_updateVideo()
{
......@@ -182,12 +208,20 @@ void VideoManager::_updateVideo()
_videoReceiver = new VideoReceiver(this);
#if defined(QGC_GST_STREAMING)
_videoReceiver->setVideoSink(_videoSurface->videoSink());
QString videoSource = _videoSettings->videoSource()->rawValue().toString();
if (_videoSettings->videoSource()->rawValue().toString() == VideoSettings::videoSourceUDP)
_videoReceiver->setUri(QStringLiteral("udp://0.0.0.0:%1").arg(_videoSettings->udpPort()->rawValue().toInt()));
else
_videoReceiver->setUri(_videoSettings->rtspUrl()->rawValue().toString());
_updateSettings();
#endif
_videoReceiver->start();
}
}
//-----------------------------------------------------------------------------
void VideoManager::_restartVideo()
{
if(!_videoReceiver)
return;
#if defined(QGC_GST_STREAMING)
_videoReceiver->stop();
_updateSettings();
_videoReceiver->start();
#endif
}
......@@ -69,10 +69,16 @@ signals:
private slots:
void _videoSourceChanged(void);
void _udpPortChanged(void);
void _rtspUrlChanged(void);
private:
void _updateTimer ();
void _updateSettings ();
void _updateVideo ();
void _restartVideo ();
VideoSurface* _videoSurface;
VideoReceiver* _videoReceiver;
......
......@@ -200,11 +200,11 @@ DropButton {
QGCButton {
text: qsTr("Current Location")
Layout.fillWidth: true
enabled: mainWindow.gcsPosition && mainWindow.gcsPosition.isValid && !followVehicleCheckBox.checked
enabled: map.gcsPosition ? map.gcsPosition.isValid && !followVehicleCheckBox.checked : false
onClicked: {
dropButton.hideDropDown()
map.center = mainWindow.gcsPosition
map.center = map.gcsPosition
}
}
......
......@@ -16,9 +16,11 @@ import QGroundControl 1.0
Item {
property var map
property bool usePlannedHomePosition ///< true: planned home position used for calculations, false: vehicle home position use for calculations
property var mapGeoFenceController
property var mapMissionController
property var mapRallyPointController
property var planMasterController
property var _missionController: planMasterController.missionController
property var _geoFenceController: planMasterController.geoFenceController
property var _rallyPointController: planMasterController.rallyPointController
property var _activeVehicle: QGroundControl.multiVehicleManager.activeVehicle
......@@ -26,7 +28,7 @@ Item {
var homePosition = QtPositioning.coordinate()
var activeVehicle = QGroundControl.multiVehicleManager.activeVehicle
if (usePlannedHomePosition) {
homePosition = mapMissionController.visualItems.get(0).coordinate
homePosition = _missionController.visualItems.get(0).coordinate
} else if (activeVehicle) {
homePosition = activeVehicle.homePosition
}
......@@ -92,8 +94,8 @@ Item {
if (homePosition.isValid) {
coordList.push(homePosition)
}
for (var i=1; i<mapMissionController.visualItems.count; i++) {
var missionItem = mapMissionController.visualItems.get(i)
for (var i=1; i<_missionController.visualItems.count; i++) {
var missionItem = _missionController.visualItems.get(i)
if (missionItem.specifiesCoordinate && !missionItem.isStandaloneCoordinate) {
coordList.push(missionItem.coordinate)
}
......@@ -101,7 +103,7 @@ Item {
}
function fitMapViewportToMissionItems() {
if (!mapMissionController.visualItems) {
if (!_missionController.visualItems) {
// Being called prior to controller.start
return
}
......@@ -112,16 +114,16 @@ Item {
function addFenceItemCoordsForFit(coordList) {
var homePosition = fitHomePosition()
if (homePosition.isValid && mapGeoFenceController.circleEnabled) {
if (homePosition.isValid && _geoFenceController.circleEnabled) {
var azimuthList = [ 0, 180, 90, 270 ]
for (var i=0; i<azimuthList.length; i++) {
var edgeCoordinate = homePosition.atDistanceAndAzimuth(mapGeoFenceController.circleRadius, azimuthList[i])
var edgeCoordinate = homePosition.atDistanceAndAzimuth(_geoFenceController.circleRadius, azimuthList[i])
coordList.push(edgeCoordinate)
}
}
if (mapGeoFenceController.polygonEnabled && mapGeoFenceController.mapPolygon.path.count > 2) {
for (var i=0; i<mapGeoFenceController.mapPolygon.path.count; i++) {
coordList.push(mapGeoFenceController.mapPolygon.path[i])
if (_geoFenceController.polygonEnabled && _geoFenceController.mapPolygon.path.count > 2) {
for (var i=0; i<_geoFenceController.mapPolygon.path.count; i++) {
coordList.push(_geoFenceController.mapPolygon.path[i])
}
}
}
......@@ -133,8 +135,8 @@ Item {
}
function addRallyItemCoordsForFit(coordList) {
for (var i=0; i<mapRallyPointController.points.count; i++) {
coordList.push(mapRallyPointController.points.get(i).coordinate)
for (var i=0; i<_rallyPointController.points.count; i++) {
coordList.push(_rallyPointController.points.get(i).coordinate)
}
}
......@@ -145,7 +147,7 @@ Item {
}
function fitMapViewportToAllItems() {
if (!mapMissionController.visualItems) {
if (!_missionController.visualItems) {
// Being called prior to controller.start
return
}
......
......@@ -9,6 +9,8 @@
#include "ValuesWidgetController.h"
#include "QGCApplication.h"
#include "QGCCorePlugin.h"
#include <QSettings>
......@@ -19,13 +21,14 @@ const char* ValuesWidgetController::_smallValuesKey = "small";
ValuesWidgetController::ValuesWidgetController(void)
{
QSettings settings;
QStringList largeDefaults;
settings.beginGroup(_groupKey);
largeDefaults << "Vehicle.altitudeRelative" << "Vehicle.groundSpeed";
QStringList largeDefaults, smallDefaults;
qgcApp()->toolbox()->corePlugin()->valuesWidgetDefaultSettings(largeDefaults, smallDefaults);
_largeValues = settings.value(_largeValuesKey, largeDefaults).toStringList();
_smallValues = settings.value(_smallValuesKey, QStringList()).toStringList();
_smallValues = settings.value(_smallValuesKey, smallDefaults).toStringList();
_altitudeProperties << "altitudeRelative" << "altitudeAMSL";
......
......@@ -28,8 +28,6 @@ GPSManager::~GPSManager()
void GPSManager::connectGPS(const QString& device)
{
Q_ASSERT(_toolbox);
RTKSettings* rtkSettings = qgcApp()->toolbox()->settingsManager()->rtkSettings();
cleanup();
......
......@@ -102,6 +102,10 @@ bool JsonHelper::validateKeyTypes(const QJsonObject& jsonObject, const QStringLi
QString valueKey = keys[i];
if (jsonObject.contains(valueKey)) {
const QJsonValue& jsonValue = jsonObject[valueKey];
if (types[i] == QJsonValue::Null && jsonValue.type() == QJsonValue::Double) {
// Null type signals a NaN on a double value
continue;
}
if (jsonValue.type() != types[i]) {
errorString = QObject::tr("Incorrect value type - key:type:expected %1:%2:%3").arg(valueKey).arg(_jsonValueTypeToString(jsonValue.type())).arg(_jsonValueTypeToString(types[i]));
return false;
......@@ -125,21 +129,18 @@ bool JsonHelper::parseEnum(const QJsonObject& jsonObject, QStringList& enumStrin
return true;
}
bool JsonHelper::isJsonFile(const QByteArray& bytes, QJsonDocument& jsonDoc)
bool JsonHelper::isJsonFile(const QByteArray& bytes, QJsonDocument& jsonDoc, QString& errorString)
{
QJsonParseError error;
QJsonParseError parseError;
jsonDoc = QJsonDocument::fromJson(bytes, &error);
jsonDoc = QJsonDocument::fromJson(bytes, &parseError);
if (error.error == QJsonParseError::NoError) {
if (parseError.error == QJsonParseError::NoError) {
return true;
}
if (error.error == QJsonParseError::MissingObject && error.offset == 0) {
} else {
errorString = parseError.errorString();
return false;
}
return true;
}
bool JsonHelper::validateQGCJsonFile(const QJsonObject& jsonObject,
......@@ -192,6 +193,15 @@ bool JsonHelper::validateQGCJsonFile(const QJsonObject& jsonObject,
return true;
}
void JsonHelper::saveQGCJsonFileHeader(QJsonObject& jsonObject,
const QString& fileType,
int version)
{
jsonObject[jsonGroundStationKey] = jsonGroundStationValue;
jsonObject[jsonFileTypeKey] = fileType;
jsonObject[jsonVersionKey] = version;
}
bool JsonHelper::loadGeoCoordinateArray(const QJsonValue& jsonValue,
bool altitudeRequired,
QVariantList& rgVarPoints,
......@@ -336,3 +346,12 @@ void JsonHelper::savePolygon(QmlObjectListModel& list, QJsonArray& polygonArray)
polygonArray.append(jsonValue);
}
}
double JsonHelper::possibleNaNJsonValue(const QJsonValue& value)
{
if (value.type() == QJsonValue::Null) {
return std::numeric_limits<double>::quiet_NaN();
} else {
return value.toDouble();
}
}
......@@ -20,28 +20,44 @@ class JsonHelper
{
public:
/// Determines is the specified data is a json file
/// @param jsonDoc Returned json document if json file
/// @return true: file is json, false: file is not json
static bool isJsonFile(const QByteArray& bytes, QJsonDocument& jsonDoc);
static bool isJsonFile(const QByteArray& bytes, ///< json bytes
QJsonDocument& jsonDoc, ///< returned json document
QString& errorString); ///< error on parse failure
/// Saves the standard file header the json object
static void saveQGCJsonFileHeader(QJsonObject& jsonObject, ///< root json object
const QString& fileType, ///< file type for file
int version); ///< version number for file
/// Validates the standard parts of a QGC json file:
/// jsonFileTypeKey - Required and checked to be equal to expectedFileType
/// jsonVersionKey - Required and checked to be below supportedMajorVersion, supportedMinorVersion
/// jsonGroundStationKey - Required and checked to be string type
/// @return false: validation failed
static bool validateQGCJsonFile(const QJsonObject& jsonObject, ///< root json object
/// @return false: validation failed, errorString set
static bool validateQGCJsonFile(const QJsonObject& jsonObject, ///< json object to validate
const QString& expectedFileType, ///< correct file type for file
int minSupportedVersion, ///< minimum supported version
int maxSupportedVersion, ///< maximum supported major version
int &version, ///< returned file version
QString& errorString); ///< returned error string if validation fails
static bool validateRequiredKeys(const QJsonObject& jsonObject, const QStringList& keys, QString& errorString);
static bool validateKeyTypes(const QJsonObject& jsonObject, const QStringList& keys, const QList<QJsonValue::Type>& types, QString& errorString);
/// Validates that the specified keys are in the object
/// @return false: validation failed, errorString set
static bool validateRequiredKeys(const QJsonObject& jsonObject, ///< json object to validate
const QStringList& keys, ///< keys which are required to be present
QString& errorString); ///< returned error string if validation fails
/// Validates the types of specified keys are in the object
/// @return false: validation failed, errorString set
static bool validateKeyTypes(const QJsonObject& jsonObject, ///< json object to validate
const QStringList& keys, ///< keys to validate
const QList<QJsonValue::Type>& types, ///< required type for each key, QJsonValue::Null specifies double with possible NaN
QString& errorString); ///< returned error string if validation fails
typedef struct {
const char* key; ///< json key name
QJsonValue::Type type; ///< type of key
QJsonValue::Type type; ///< required type for key, QJsonValue::Null specifies double with possible NaN
bool required; ///< true: key must be present
} KeyValidateInfo;
......@@ -90,6 +106,8 @@ public:
static bool parseEnum(const QJsonObject& jsonObject, QStringList& enumStrings, QStringList& enumValues, QString& errorString);
/// Returns NaN if the value is null, or it not the double value
static double possibleNaNJsonValue(const QJsonValue& value);
static const char* jsonVersionKey;
static const char* jsonGroundStationKey;
......
......@@ -29,7 +29,7 @@
"name": "GimbalPitch",
"shortDescription": "Gimbal pitch rotation.",
"type": "double",
"units": "deg",
"units": "gimbal-degrees",
"min": -90,
"max": 0,
"decimalPlaces": 0,
......@@ -40,8 +40,8 @@
"shortDescription": "Gimbal yaw rotation.",
"type": "double",
"units": "deg",
"min": 0.0,
"max": 360.0,
"min": -180.0,
"max": 180.0,
"decimalPlaces": 0,
"defaultValue": 0
}
......
......@@ -90,6 +90,9 @@ FixedWingLandingComplexItem::FixedWingLandingComplexItem(Vehicle* vehicle, QObje
connect(this, &FixedWingLandingComplexItem::loiterClockwiseChanged, this, &FixedWingLandingComplexItem::_setDirty);
connect(this, &FixedWingLandingComplexItem::loiterAltitudeRelativeChanged, this, &FixedWingLandingComplexItem::_setDirty);
connect(this, &FixedWingLandingComplexItem::landingAltitudeRelativeChanged, this, &FixedWingLandingComplexItem::_setDirty);
connect(this, &FixedWingLandingComplexItem::loiterAltitudeRelativeChanged, this, &FixedWingLandingComplexItem::coordinateHasRelativeAltitudeChanged);
connect(this, &FixedWingLandingComplexItem::landingAltitudeRelativeChanged, this, &FixedWingLandingComplexItem::exitCoordinateHasRelativeAltitudeChanged);
}
int FixedWingLandingComplexItem::lastSequenceNumber(void) const
......@@ -409,6 +412,7 @@ void FixedWingLandingComplexItem::_recalcFromRadiusChange(void)
double angleLoiterToTangent = qRadiansToDegrees(qAsin(radius/landToLoiterDistance)) * (_loiterClockwise ? -1 : 1);
_loiterCoordinate = _landingCoordinate.atDistanceAndAzimuth(landToLoiterDistance, heading + 180 + angleLoiterToTangent);
_loiterCoordinate.setAltitude(_loiterAltitudeFact.rawValue().toDouble());
_ignoreRecalcSignals = true;
emit loiterCoordinateChanged(_loiterCoordinate);
......@@ -446,6 +450,7 @@ void FixedWingLandingComplexItem::_recalcFromHeadingAndDistanceChange(void)
// Use those values to get the new loiter point which takes heading into acount
_loiterCoordinate = _landingCoordinate.atDistanceAndAzimuth(loiterDistance, heading + 180 + loiterAzimuth);
_loiterCoordinate.setAltitude(_loiterAltitudeFact.rawValue().toDouble());
_ignoreRecalcSignals = true;
emit loiterTangentCoordinateChanged(_loiterTangentCoordinate);
......@@ -509,11 +514,14 @@ void FixedWingLandingComplexItem::_recalcFromCoordinateChange(void)
void FixedWingLandingComplexItem::_updateLoiterCoodinateAltitudeFromFact(void)
{
_loiterCoordinate.setAltitude(_loiterAltitudeFact.rawValue().toDouble());
emit loiterCoordinateChanged(_loiterCoordinate);
emit coordinateChanged(_loiterCoordinate);
}
void FixedWingLandingComplexItem::_updateLandingCoodinateAltitudeFromFact(void)
{
_landingCoordinate.setAltitude(_landingAltitudeFact.rawValue().toDouble());
emit landingCoordinateChanged(_landingCoordinate);
}
void FixedWingLandingComplexItem::_setDirty(void)
......
......@@ -78,9 +78,9 @@ public:
void appendMissionItems (QList<MissionItem*>& items, QObject* missionItemParent) final;
void applyNewAltitude (double newAltitude) final;
bool coordinateHasRelativeAltitude (void) const final { return true; }
bool exitCoordinateHasRelativeAltitude (void) const final { return true; }
bool exitCoordinateSameAsEntry (void) const final { return true; }
bool coordinateHasRelativeAltitude (void) const final { return _loiterAltitudeRelative; }
bool exitCoordinateHasRelativeAltitude (void) const final { return _landingAltitudeRelative; }
bool exitCoordinateSameAsEntry (void) const final { return false; }
void setDirty (bool dirty) final;
void setCoordinate (const QGeoCoordinate& coordinate) final { setLoiterCoordinate(coordinate); }
......
This diff is collapsed.
......@@ -26,7 +26,7 @@ class GeoFenceController : public PlanElementController
Q_OBJECT
public:
GeoFenceController(QObject* parent = NULL);
GeoFenceController(PlanMasterController* masterController, QObject* parent = NULL);
~GeoFenceController();
Q_PROPERTY(QGCMapPolygon* mapPolygon READ mapPolygon CONSTANT)
......@@ -45,19 +45,18 @@ public:
Q_INVOKABLE void removePolygon (void) { _mapPolygon.clear(); }
void start (bool editMode) final;
void startStaticActiveVehicle (Vehicle* vehicle) final;
void save (QJsonObject& json) final;
bool load (const QJsonObject& json, QString& errorString) final;
void loadFromVehicle (void) final;
void sendToVehicle (void) final;
void loadFromFile (const QString& filename) final;
void saveToFile (const QString& filename) final;
void removeAll (void) final;
void removeAllFromVehicle (void) final;
bool syncInProgress (void) const final;
bool dirty (void) const final;
void setDirty (bool dirty) final;
bool containsItems (void) const final;
QString fileExtension(void) const final;
void managerVehicleChanged (Vehicle* managerVehicle) final;
bool showPlanFromManagerVehicle (void) final;
bool circleEnabled (void) const;
Fact* circleRadiusFact (void) const;
......@@ -89,20 +88,20 @@ private slots:
void _setDirty(void);
void _setPolygonFromManager(const QList<QGeoCoordinate>& polygon);
void _setReturnPointFromManager(QGeoCoordinate breachReturnPoint);
void _loadComplete(const QGeoCoordinate& breachReturn, const QList<QGeoCoordinate>& polygon);
void _managerLoadComplete(const QGeoCoordinate& breachReturn, const QList<QGeoCoordinate>& polygon);
void _updateContainsItems(void);
void _managerSendComplete(bool error);
void _managerRemoveAllComplete(bool error);
private:
void _init(void);
void _signalAll(void);
bool _loadJsonFile(QJsonDocument& jsonDoc, QString& errorString);
void _activeVehicleBeingRemoved(void) final;
void _activeVehicleSet(void) final;
bool _dirty;
QGCMapPolygon _mapPolygon;
QGeoCoordinate _breachReturnPoint;
GeoFenceManager* _geoFenceManager;
bool _dirty;
QGCMapPolygon _mapPolygon;
QGeoCoordinate _breachReturnPoint;
bool _itemsRequested;
static const char* _jsonFileTypeValue;
static const char* _jsonBreachReturnKey;
......
......@@ -40,8 +40,15 @@ void GeoFenceManager::loadFromVehicle(void)
void GeoFenceManager::sendToVehicle(const QGeoCoordinate& breachReturn, QmlObjectListModel& polygon)
{
// No geofence support in unknown vehicle
Q_UNUSED(breachReturn);
Q_UNUSED(polygon);
emit sendComplete(false /* error */);
}
void GeoFenceManager::removeAll(void)
{
// No geofence support in unknown vehicle
emit removeAllComplete(false /* error */);
}
......@@ -35,13 +35,16 @@ public:
virtual bool inProgress(void) const { return false; }
/// Load the current settings from the vehicle
/// Signals loadComplete when done
virtual void loadFromVehicle(void);
/// Send the current settings to the vehicle
/// Signals sendComplete when done
virtual void sendToVehicle(const QGeoCoordinate& breachReturn, QmlObjectListModel& polygon);
/// Remove all fence related items from vehicle (does not affect paramters)
virtual void removeAll(void) { }
/// Signals removeAllComplete when done
virtual void removeAll(void);
/// Returns true if this vehicle support polygon fence
/// Signal: polygonSupportedChanged
......@@ -93,6 +96,8 @@ signals:
void polygonSupportedChanged (bool polygonSupported);
void polygonEnabledChanged (bool polygonEnabled);
void breachReturnSupportedChanged (bool breachReturnSupported);
void removeAllComplete (bool error);
void sendComplete (bool error);
protected:
void _sendError(ErrorCode_t errorCode, const QString& errorMsg);
......
......@@ -54,6 +54,7 @@
"label": "Heading",
"units": "radians",
"nanUnchanged": true,
"default": null,
"decimalPlaces": 2
}
},
......@@ -75,6 +76,7 @@
"label": "Heading",
"units": "radians",
"nanUnchanged": true,
"default": null,
"decimalPlaces": 2
}
},
......@@ -101,6 +103,7 @@
"label": "Heading",
"units": "radians",
"nanUnchanged": true,
"default": null,
"decimalPlaces": 2
}
},
......@@ -157,6 +160,7 @@
"label": "Heading",
"units": "radians",
"nanUnchanged": true,
"default": null,
"decimalPlaces": 2
}
},
......@@ -178,6 +182,7 @@
"label": "Heading",
"units": "radians",
"nanUnchanged": true,
"default": null,
"decimalPlaces": 2
}
},
......@@ -316,6 +321,7 @@
"label": "Heading",
"units": "deg",
"nanUnchanged": true,
"default": null,
"decimalPlaces": 2
}
},
......@@ -331,6 +337,7 @@
"label": "Heading",
"units": "deg",
"nanUnchanged": true,
"default": null,
"decimalPlaces": 2
}
},
......
......@@ -334,7 +334,7 @@ bool MissionCommandUIInfo::loadJsonInfo(const QJsonObject& jsonObject, bool requ
// Validate key types
QList<QJsonValue::Type> types;
types << QJsonValue::Double << QJsonValue::Double << QJsonValue::String << QJsonValue::String << QJsonValue::String << QJsonValue::String << QJsonValue::Bool;
types << QJsonValue::Null << QJsonValue::Double << QJsonValue::String << QJsonValue::String << QJsonValue::String << QJsonValue::String << QJsonValue::Bool;
if (!JsonHelper::validateKeyTypes(jsonObject, allParamKeys, types, internalError)) {
errorString = _loadErrorString(internalError);
return false;
......@@ -358,7 +358,15 @@ bool MissionCommandUIInfo::loadJsonInfo(const QJsonObject& jsonObject, bool requ
paramInfo->_nanUnchanged = paramObject.value(_nanUnchangedJsonKey).toBool(false);
if (paramObject.contains(_defaultJsonKey)) {
paramInfo->_defaultValue = paramObject.value(_defaultJsonKey).toDouble(0.0);
if (paramInfo->_nanUnchanged) {
paramInfo->_defaultValue = JsonHelper::possibleNaNJsonValue(paramObject[_defaultJsonKey]);
} else {
if (paramObject[_defaultJsonKey].type() == QJsonValue::Null) {
errorString = QString("Param %1 default value was null/NaN but NaN is not allowed");
return false;
}
paramInfo->_defaultValue = paramObject.value(_defaultJsonKey).toDouble(0.0);
}
} else {
paramInfo->_defaultValue = paramInfo->_nanUnchanged ? std::numeric_limits<double>::quiet_NaN() : 0;
}
......
This diff is collapsed.
......@@ -24,17 +24,19 @@ class VisualMissionItem;
class MissionItem;
class MissionSettingsItem;
class AppSettings;
class MissionManager;
Q_DECLARE_LOGGING_CATEGORY(MissionControllerLog)
typedef QPair<VisualMissionItem*,VisualMissionItem*> VisualItemPair;
typedef QHash<VisualItemPair, CoordinateVector*> CoordVectHashTable;
class MissionController : public PlanElementController
{
Q_OBJECT
public:
MissionController(QObject* parent = NULL);
MissionController(PlanMasterController* masterController, QObject* parent = NULL);
~MissionController();
typedef struct {
......@@ -62,11 +64,13 @@ public:
Q_PROPERTY(QmlObjectListModel* visualItems READ visualItems NOTIFY visualItemsChanged)
Q_PROPERTY(QmlObjectListModel* waypointLines READ waypointLines NOTIFY waypointLinesChanged)
Q_PROPERTY(QmlObjectListModel* cameraPoints READ cameraPoints CONSTANT)
Q_PROPERTY(QStringList complexMissionItemNames READ complexMissionItemNames NOTIFY complexMissionItemNamesChanged)
Q_PROPERTY(QGeoCoordinate plannedHomePosition READ plannedHomePosition NOTIFY plannedHomePositionChanged)
Q_PROPERTY(int resumeMissionIndex READ resumeMissionIndex NOTIFY resumeMissionIndexChanged)
Q_PROPERTY(double progressPct READ progressPct NOTIFY progressPctChanged)
Q_PROPERTY(int currentMissionIndex READ currentMissionIndex NOTIFY currentMissionIndexChanged)
Q_PROPERTY(int resumeMissionIndex READ resumeMissionIndex NOTIFY resumeMissionIndexChanged) ///< Returns the item index two which a mission should be resumed. -1 indicates resume mission not available.
Q_PROPERTY(double missionDistance READ missionDistance NOTIFY missionDistanceChanged)
Q_PROPERTY(double missionTime READ missionTime NOTIFY missionTimeChanged)
......@@ -98,43 +102,36 @@ public:
/// Updates the altitudes of the items in the current mission to the new default altitude
Q_INVOKABLE void applyDefaultMissionAltitude(void);
/// Loads the mission items from the specified file
/// @param[in] vehicle Vehicle we are loading items for
/// @param[in] filename File to load from
/// @param[out] visualItems Visual items loaded, returns NULL if error
/// @return success/fail
static bool loadItemsFromFile(Vehicle* vehicle, const QString& filename, QmlObjectListModel** visualItems);
/// Sends the mission items to the specified vehicle
static void sendItemsToVehicle(Vehicle* vehicle, QmlObjectListModel* visualMissionItems);
Q_INVOKABLE void clearCameraPoints(void);
bool loadJsonFile(QFile& file, QString& errorString);
bool loadTextFile(QFile& file, QString& errorString);
// Overrides from PlanElementController
void start (bool editMode) final;
void startStaticActiveVehicle (Vehicle* vehicle) final;
void save (QJsonObject& json) final;
bool load (const QJsonObject& json, QString& errorString) final;
void loadFromVehicle (void) final;
void sendToVehicle (void) final;
void loadFromFile (const QString& filename) final;
void saveToFile (const QString& filename) final;
void removeAll (void) final;
void removeAllFromVehicle (void) final;
bool syncInProgress (void) const final;
bool dirty (void) const final;
void setDirty (bool dirty) final;
bool containsItems (void) const final;
QString fileExtension(void) const final;
void managerVehicleChanged (Vehicle* managerVehicle) final;
bool showPlanFromManagerVehicle (void) final;
// Property accessors
QmlObjectListModel* visualItems (void) { return _visualItems; }
QmlObjectListModel* waypointLines (void) { return &_waypointLines; }
QmlObjectListModel* cameraPoints (void) { return &_cameraPoints; }
QStringList complexMissionItemNames (void) const;
QGeoCoordinate plannedHomePosition (void) const;
double progressPct (void) const { return _progressPct; }
/// Returns the item index two which a mission should be resumed. -1 indicates resume mission not available.
int currentMissionIndex(void) const;
int resumeMissionIndex(void) const;
double missionDistance (void) const { return _missionFlightStatus.totalDistance; }
......@@ -165,17 +162,22 @@ signals:
void batteryChangePointChanged(int batteryChangePoint);
void batteriesRequiredChanged(int batteriesRequired);
void plannedHomePositionChanged(QGeoCoordinate plannedHomePosition);
void progressPctChanged(double progressPct);
void currentMissionIndexChanged(int currentMissionIndex);
private slots:
void _newMissionItemsAvailableFromVehicle(bool removeAllRequested);
void _itemCommandChanged(void);
void _activeVehicleHomePositionChanged(const QGeoCoordinate& homePosition);
void _managerVehicleHomePositionChanged(const QGeoCoordinate& homePosition);
void _inProgressChanged(bool inProgress);
void _currentMissionIndexChanged(int sequenceNumber);
void _recalcWaypointLines(void);
void _recalcMissionFlightStatus(void);
void _updateContainsItems(void);
void _cameraFeedback(QGeoCoordinate imageCoordinate, int index);
void _progressPctChanged(double progressPct);
void _visualItemsDirtyChanged(bool dirty);
void _managerSendComplete(bool error);
void _managerRemoveAllComplete(bool error);
private:
void _init(void);
......@@ -192,11 +194,11 @@ private:
bool _findPreviousAltitude(int newIndex, double* prevAltitude, MAV_FRAME* prevFrame);
static double _normalizeLat(double lat);
static double _normalizeLon(double lon);
static void _addMissionSettings(Vehicle* vehicle, QmlObjectListModel* visualItems, bool addToCenter);
static bool _loadJsonMissionFile(Vehicle* vehicle, const QByteArray& bytes, QmlObjectListModel* visualItems, QString& errorString);
static bool _loadJsonMissionFileV1(Vehicle* vehicle, const QJsonObject& json, QmlObjectListModel* visualItems, QString& errorString);
static bool _loadJsonMissionFileV2(Vehicle* vehicle, const QJsonObject& json, QmlObjectListModel* visualItems, QString& errorString);
static bool _loadTextMissionFile(Vehicle* vehicle, QTextStream& stream, QmlObjectListModel* visualItems, QString& errorString);
void _addMissionSettings(QmlObjectListModel* visualItems, bool addToCenter);
bool _loadJsonMissionFile(const QByteArray& bytes, QmlObjectListModel* visualItems, QString& errorString);
bool _loadJsonMissionFileV1(const QJsonObject& json, QmlObjectListModel* visualItems, QString& errorString);
bool _loadJsonMissionFileV2(const QJsonObject& json, QmlObjectListModel* visualItems, QString& errorString);
bool _loadTextMissionFile(QTextStream& stream, QmlObjectListModel* visualItems, QString& errorString);
int _nextSequenceNumber(void);
static void _scanForAdditionalSettings(QmlObjectListModel* visualItems, Vehicle* vehicle);
static bool _convertToMissionItems(QmlObjectListModel* visualMissionItems, QList<MissionItem*>& rgMissionItems, QObject* missionItemParent);
......@@ -205,23 +207,22 @@ private:
void _addHoverTime(double hoverTime, double hoverDistance, int waypointIndex);
void _addCruiseTime(double cruiseTime, double cruiseDistance, int wayPointIndex);
void _updateBatteryInfo(int waypointIndex);
// Overrides from PlanElementController
void _activeVehicleBeingRemoved(void) final;
void _activeVehicleSet(void) final;
bool _loadItemsFromJson(const QJsonObject& json, QmlObjectListModel* visualItems, QString& errorString);
void _initLoadedVisualItems(QmlObjectListModel* loadedVisualItems);
private:
MissionManager* _missionManager;
QmlObjectListModel* _visualItems;
MissionSettingsItem* _settingsItem;
QmlObjectListModel _waypointLines;
QmlObjectListModel _cameraPoints;
CoordVectHashTable _linesTable;
bool _firstItemsFromVehicle;
bool _missionItemsRequested;
bool _itemsRequested;
MissionFlightStatus_t _missionFlightStatus;
QString _surveyMissionItemName;
QString _fwLandingMissionItemName;
AppSettings* _appSettings;
double _progressPct;
static const char* _settingsGroup;
......
......@@ -35,9 +35,10 @@ void MissionControllerManagerTest::_initForFirmwareType(MAV_AUTOPILOT firmwareTy
_missionManager = qgcApp()->toolbox()->multiVehicleManager()->activeVehicle()->missionManager();
QVERIFY(_missionManager);
_rgMissionManagerSignals[newMissionItemsAvailableSignalIndex] = SIGNAL(newMissionItemsAvailable(bool));
_rgMissionManagerSignals[inProgressChangedSignalIndex] = SIGNAL(inProgressChanged(bool));
_rgMissionManagerSignals[errorSignalIndex] = SIGNAL(error(int, const QString&));
_rgMissionManagerSignals[newMissionItemsAvailableSignalIndex] = SIGNAL(newMissionItemsAvailable(bool));
_rgMissionManagerSignals[sendCompleteSignalIndex] = SIGNAL(sendComplete(bool));
_rgMissionManagerSignals[inProgressChangedSignalIndex] = SIGNAL(inProgressChanged(bool));
_rgMissionManagerSignals[errorSignalIndex] = SIGNAL(error(int, const QString&));
_multiSpyMissionManager = new MultiSignalSpy();
Q_CHECK_PTR(_multiSpyMissionManager);
......
......@@ -55,6 +55,7 @@ protected:
typedef enum {
newMissionItemsAvailableSignalIndex = 0,
sendCompleteSignalIndex,
inProgressChangedSignalIndex,
errorSignalIndex,
maxSignalIndex
......@@ -62,6 +63,7 @@ protected:
typedef enum {
newMissionItemsAvailableSignalMask = 1 << newMissionItemsAvailableSignalIndex,
sendCompleteSignalMask = 1 << sendCompleteSignalIndex,
inProgressChangedSignalMask = 1 << inProgressChangedSignalIndex,
errorSignalMask = 1 << errorSignalIndex,
} MissionManagerSignalMask_t;
......
......@@ -13,6 +13,9 @@
#include "MultiVehicleManager.h"
#include "SimpleMissionItem.h"
#include "MissionSettingsItem.h"
#include "QGCApplication.h"
#include "SettingsManager.h"
#include "AppSettings.h"
MissionControllerTest::MissionControllerTest(void)
: _multiSpyMissionController(NULL)
......@@ -24,8 +27,8 @@ MissionControllerTest::MissionControllerTest(void)
void MissionControllerTest::cleanup(void)
{
delete _missionController;
_missionController = NULL;
delete _masterController;
_masterController = NULL;
delete _multiSpyMissionController;
_multiSpyMissionController = NULL;
......@@ -38,8 +41,6 @@ void MissionControllerTest::cleanup(void)
void MissionControllerTest::_initForFirmwareType(MAV_AUTOPILOT firmwareType)
{
bool startController = false;
MissionControllerManagerTest::_initForFirmwareType(firmwareType);
// VisualMissionItem signals
......@@ -49,19 +50,16 @@ void MissionControllerTest::_initForFirmwareType(MAV_AUTOPILOT firmwareType)
_rgMissionControllerSignals[visualItemsChangedSignalIndex] = SIGNAL(visualItemsChanged());
_rgMissionControllerSignals[waypointLinesChangedSignalIndex] = SIGNAL(waypointLinesChanged());
if (!_missionController) {
startController = true;
_missionController = new MissionController();
Q_CHECK_PTR(_missionController);
}
// Master controller pulls offline vehicle info from settings
qgcApp()->toolbox()->settingsManager()->appSettings()->offlineEditingFirmwareType()->setRawValue(firmwareType);
_masterController = new PlanMasterController(this);
_missionController = _masterController->missionController();
_multiSpyMissionController = new MultiSignalSpy();
Q_CHECK_PTR(_multiSpyMissionController);
QCOMPARE(_multiSpyMissionController->init(_missionController, _rgMissionControllerSignals, _cMissionControllerSignals), true);
if (startController) {
_missionController->start(true /* editMode */);
}
_masterController->start(true /* editMode */);
// All signals should some through on start
QCOMPARE(_multiSpyMissionController->checkOnlySignalsByMask(visualItemsChangedSignalMask | waypointLinesChangedSignalMask), true);
......@@ -162,6 +160,7 @@ void MissionControllerTest::_testAddWayppointPX4(void)
_testAddWaypointWorker(MAV_AUTOPILOT_PX4);
}
#if 0
void MissionControllerTest::_testOfflineToOnlineWorker(MAV_AUTOPILOT firmwareType)
{
// Start offline and add item
......@@ -191,6 +190,7 @@ void MissionControllerTest::_testOfflineToOnlinePX4(void)
{
_testOfflineToOnlineWorker(MAV_AUTOPILOT_PX4);
}
#endif
void MissionControllerTest::_setupVisualItemSignals(VisualMissionItem* visualItem)
{
......
......@@ -16,6 +16,7 @@
#include "MissionManager.h"
#include "MultiSignalSpy.h"
#include "MissionControllerManagerTest.h"
#include "PlanMasterController.h"
#include "MissionController.h"
#include "SimpleMissionItem.h"
......@@ -38,14 +39,18 @@ private:
void _testEmptyVehiclePX4(void);
void _testAddWayppointAPM(void);
void _testAddWayppointPX4(void);
#if 0
void _testOfflineToOnlineAPM(void);
void _testOfflineToOnlinePX4(void);
#endif
private:
void _initForFirmwareType(MAV_AUTOPILOT firmwareType);
void _testEmptyVehicleWorker(MAV_AUTOPILOT firmwareType);
void _testAddWaypointWorker(MAV_AUTOPILOT firmwareType);
#if 0
void _testOfflineToOnlineWorker(MAV_AUTOPILOT firmwareType);
#endif
void _setupVisualItemSignals(VisualMissionItem* visualItem);
// MissiomItems signals
......@@ -81,7 +86,8 @@ private:
static const size_t _cVisualItemSignals = visualItemMaxSignalIndex;
const char* _rgVisualItemSignals[_cVisualItemSignals];
MissionController* _missionController;
PlanMasterController* _masterController;
MissionController* _missionController;
};
#endif
......@@ -260,6 +260,13 @@ bool MissionItem::load(const QJsonObject& json, int sequenceNumber, QString& err
return false;
}
for (int i=0; i<4; i++) {
if (rgParams[i].type() != QJsonValue::Double && rgParams[i].type() != QJsonValue::Null) {
errorString = tr("Param %1 incorrect type %2, must be double or null").arg(i+1).arg(rgParams[i].type());
return false;
}
}
// Make sure to set these first since they can signal other changes
setFrame((MAV_FRAME)v2Json[_jsonFrameKey].toInt());
setCommand((MAV_CMD)v2Json[_jsonCommandKey].toInt());
......@@ -280,10 +287,10 @@ bool MissionItem::load(const QJsonObject& json, int sequenceNumber, QString& err
setSequenceNumber(sequenceNumber);
setAutoContinue(v2Json[_jsonAutoContinueKey].toBool());
setParam1(rgParams[0].toDouble());
setParam2(rgParams[1].toDouble());
setParam3(rgParams[2].toDouble());
setParam4(rgParams[3].toDouble());
setParam1(JsonHelper::possibleNaNJsonValue(rgParams[0]));
setParam2(JsonHelper::possibleNaNJsonValue(rgParams[1]));
setParam3(JsonHelper::possibleNaNJsonValue(rgParams[2]));
setParam4(JsonHelper::possibleNaNJsonValue(rgParams[3]));
return true;
}
......
This diff is collapsed.
......@@ -43,10 +43,13 @@ public:
/// Last current mission item reported while in Mission flight mode
int lastCurrentIndex(void) const { return _lastCurrentIndex; }
void requestMissionItems(void);
/// Load the mission items from the vehicle
/// Signals newMissionItemsAvailable when done
void loadFromVehicle(void);
/// Writes the specified set of mission items to the vehicle
/// @param missionItems Items to send to vehicle
/// Signals sendComplete when done
void writeMissionItems(const QList<MissionItem*>& missionItems);
/// Writes the specified set mission items to the vehicle as an ArduPilot guided mode mission item.
......@@ -55,6 +58,7 @@ public:
void writeArduPilotGuidedMissionItem(const QGeoCoordinate& gotoCoord, bool altChangeOnly);
/// Removes all mission items from vehicle
/// Signals removeAllComplete when done
void removeAll(void);
/// Generates a new mission which starts from the specified index. It will include all the CMD_DO items
......@@ -84,7 +88,9 @@ signals:
void currentIndexChanged(int currentIndex);
void lastCurrentIndexChanged(int lastCurrentIndex);
void resumeMissionReady(void);
void cameraFeedback(QGeoCoordinate imageCoordinate, int index);
void progressPct(double progressPercentPct);
void removeAllComplete (bool error);
void sendComplete (bool error);
private slots:
void _mavlinkMessageReceived(const mavlink_message_t& message);
......@@ -104,7 +110,7 @@ private:
TransactionNone,
TransactionRead,
TransactionWrite,
TransactionClearAll
TransactionRemoveAll
} TransactionType_t;
void _startAckTimeout(AckType_t ack);
......@@ -115,8 +121,6 @@ private:
void _handleMissionRequest(const mavlink_message_t& message, bool missionItemInt);
void _handleMissionAck(const mavlink_message_t& message);
void _handleMissionCurrent(const mavlink_message_t& message);
void _handleCameraFeedback(const mavlink_message_t& message);
void _handleCameraImageCaptured(const mavlink_message_t& message);
void _requestNextMissionItem(void);
void _clearMissionItems(void);
void _sendError(ErrorCode_t errorCode, const QString& errorMsg);
......@@ -127,6 +131,7 @@ private:
void _writeMissionCount(void);
void _writeMissionItemsWorker(void);
void _clearAndDeleteMissionItems(void);
void _clearAndDeleteWriteMissionItems(void);
QString _lastMissionReqestString(MAV_MISSION_RESULT result);
void _removeAllWorker(void);
......@@ -146,7 +151,8 @@ private:
QMutex _dataMutex;
QList<MissionItem*> _missionItems;
QList<MissionItem*> _missionItems; ///< Set of mission items on vehicle
QList<MissionItem*> _writeMissionItems; ///< Set of mission items currently being written to vehicle
int _currentMissionIndex;
int _lastCurrentIndex;
};
......
......@@ -60,9 +60,8 @@ void MissionManagerTest::_writeItems(MockLinkMissionItemHandler::FailureMode_t f
// writeMissionItems should emit these signals before returning:
// inProgressChanged
// newMissionItemsAvailable
QVERIFY(_missionManager->inProgress());
QCOMPARE(_multiSpyMissionManager->checkSignalByMask(inProgressChangedSignalMask | newMissionItemsAvailableSignalMask), true);
QCOMPARE(_multiSpyMissionManager->checkSignalByMask(inProgressChangedSignalMask), true);
_checkInProgressValues(true);
_multiSpyMissionManager->clearAllSignals();
......@@ -93,8 +92,9 @@ void MissionManagerTest::_writeItems(MockLinkMissionItemHandler::FailureMode_t f
// Wait for write sequence to complete. We should get:
// inProgressChanged(false) signal
_multiSpyMissionManager->waitForSignalByIndex(inProgressChangedSignalIndex, _missionManagerSignalWaitTime);
QCOMPARE(_multiSpyMissionManager->checkOnlySignalByMask(inProgressChangedSignalMask), true);
// sednComplete signal
_multiSpyMissionManager->waitForSignalByIndex(sendCompleteSignalIndex, _missionManagerSignalWaitTime);
QCOMPARE(_multiSpyMissionManager->checkSignalByMask(inProgressChangedSignalMask | sendCompleteSignalMask), true);
// Validate inProgressChanged signal value
_checkInProgressValues(false);
......@@ -120,7 +120,7 @@ void MissionManagerTest::_roundTripItems(MockLinkMissionItemHandler::FailureMode
_mockLink->setMissionItemFailureMode(failureMode);
// Read the items back from the vehicle
_missionManager->requestMissionItems();
_missionManager->loadFromVehicle();
// requestMissionItems should emit inProgressChanged signal before returning so no need to wait for it
QVERIFY(_missionManager->inProgress());
......
......@@ -8,13 +8,17 @@
****************************************************************************/
#include "PlanElementController.h"
#include "PlanMasterController.h"
#include "QGCApplication.h"
#include "MultiVehicleManager.h"
#include "SettingsManager.h"
#include "AppSettings.h"
PlanElementController::PlanElementController(QObject* parent)
PlanElementController::PlanElementController(PlanMasterController* masterController, QObject* parent)
: QObject(parent)
, _multiVehicleMgr(qgcApp()->toolbox()->multiVehicleManager())
, _activeVehicle(_multiVehicleMgr->offlineEditingVehicle())
, _masterController(masterController)
, _controllerVehicle(masterController->controllerVehicle())
, _managerVehicle(masterController->managerVehicle())
, _editMode(false)
{
......@@ -28,32 +32,9 @@ PlanElementController::~PlanElementController()
void PlanElementController::start(bool editMode)
{
_editMode = editMode;
connect(_multiVehicleMgr, &MultiVehicleManager::activeVehicleChanged, this, &PlanElementController::_activeVehicleChanged);
_activeVehicleChanged(_multiVehicleMgr->activeVehicle());
}
void PlanElementController::startStaticActiveVehicle(Vehicle* vehicle)
void PlanElementController::managerVehicleChanged(Vehicle* managerVehicle)
{
_editMode = false;
_activeVehicleChanged(vehicle);
}
void PlanElementController::_activeVehicleChanged(Vehicle* activeVehicle)
{
if (_activeVehicle) {
_activeVehicleBeingRemoved();
_activeVehicle = NULL;
}
if (activeVehicle) {
_activeVehicle = activeVehicle;
} else {
_activeVehicle = _multiVehicleMgr->offlineEditingVehicle();
}
_activeVehicleSet();
// Whenever vehicle changes we need to update syncInProgress
emit syncInProgressChanged(syncInProgress());
emit vehicleChanged(_activeVehicle);
_managerVehicle = managerVehicle;
}
......@@ -15,6 +15,8 @@
#include "Vehicle.h"
#include "MultiVehicleManager.h"
class PlanMasterController;
/// This is the abstract base clas for Plan Element controllers.
/// Examples of plan elements are: missions (MissionController), geofence (GeoFenceController)
class PlanElementController : public QObject
......@@ -22,61 +24,52 @@ class PlanElementController : public QObject
Q_OBJECT
public:
PlanElementController(QObject* parent = NULL);
PlanElementController(PlanMasterController* masterController, QObject* parent = NULL);
~PlanElementController();
Q_PROPERTY(bool containsItems READ containsItems NOTIFY containsItemsChanged) ///< true: Elemement is non-empty
Q_PROPERTY(bool syncInProgress READ syncInProgress NOTIFY syncInProgressChanged) ///< true: information is currently being saved/sent, false: no active save/send in progress
Q_PROPERTY(bool dirty READ dirty WRITE setDirty NOTIFY dirtyChanged) ///< true: unsaved/sent changes are present, false: no changes since last save/send
Q_PROPERTY(QString fileExtension READ fileExtension CONSTANT) ///< Returns the file extention for plan element file type.
Q_PROPERTY(Vehicle* vehicle READ vehicle NOTIFY vehicleChanged)
virtual QString fileExtension(void) const = 0;
Q_PROPERTY(bool containsItems READ containsItems NOTIFY containsItemsChanged) ///< true: Elemement is non-empty
Q_PROPERTY(bool syncInProgress READ syncInProgress NOTIFY syncInProgressChanged) ///< true: information is currently being saved/sent, false: no active save/send in progress
Q_PROPERTY(bool dirty READ dirty WRITE setDirty NOTIFY dirtyChanged) ///< true: unsaved/sent changes are present, false: no changes since last save/send
/// Should be called immediately upon Component.onCompleted.
/// @param editMode true: controller being used in Plan view, false: controller being used in Fly view
Q_INVOKABLE virtual void start(bool editMode);
virtual void start(bool editMode);
/// Starts the controller using a single static active vehicle. Will not track global active vehicle changes.
/// @param editMode true: controller being used in Plan view, false: controller being used in Fly view
Q_INVOKABLE virtual void startStaticActiveVehicle(Vehicle* vehicle);
virtual void save (QJsonObject& json) = 0;
virtual bool load (const QJsonObject& json, QString& errorString) = 0;
virtual void loadFromVehicle (void) = 0;
virtual void removeAll (void) = 0; ///< Removes all from controller only
virtual bool showPlanFromManagerVehicle (void) = 0; /// true: controller is waiting for the current load to complete
Q_INVOKABLE virtual void loadFromVehicle(void) = 0;
Q_INVOKABLE virtual void sendToVehicle(void) = 0;
Q_INVOKABLE virtual void loadFromFile(const QString& filename) = 0;
Q_INVOKABLE virtual void saveToFile(const QString& filename) = 0;
Q_INVOKABLE virtual void removeAll(void) = 0; ///< Removes all from controller only, synce required to remove from vehicle
Q_INVOKABLE virtual void removeAllFromVehicle(void) = 0; ///< Removes all from vehicle and controller
virtual bool containsItems (void) const = 0;
virtual bool syncInProgress (void) const = 0;
virtual bool dirty (void) const = 0;
virtual void setDirty (bool dirty) = 0;
virtual bool containsItems (void) const = 0;
virtual bool syncInProgress (void) const = 0;
virtual bool dirty (void) const = 0;
virtual void setDirty (bool dirty) = 0;
/// Sends the current plan element to the vehicle
/// Signals sendComplete when done
virtual void sendToVehicle(void) = 0;
Vehicle* vehicle(void) { return _activeVehicle; }
/// Removes all from vehicle and controller
/// Signals removeAllComplete when done
virtual void removeAllFromVehicle(void) = 0;
/// Called when a new manager vehicle has been set.
virtual void managerVehicleChanged(Vehicle* managerVehicle) = 0;
signals:
void containsItemsChanged (bool containsItems);
void syncInProgressChanged (bool syncInProgress);
void dirtyChanged (bool dirty);
void vehicleChanged (Vehicle* vehicle);
void sendComplete (void);
void removeAllComplete (void);
protected:
MultiVehicleManager* _multiVehicleMgr;
Vehicle* _activeVehicle; ///< Currently active vehicle, can be disconnected offline editing vehicle
PlanMasterController* _masterController;
Vehicle* _controllerVehicle;
Vehicle* _managerVehicle;
bool _editMode;
/// Called when the current active vehicle is about to be removed. Derived classes should override
/// to implement custom behavior.
virtual void _activeVehicleBeingRemoved(void) = 0;
/// Called when a new active vehicle has been set. Derived classes should override
/// to implement custom behavior.
virtual void _activeVehicleSet(void) = 0;
private slots:
void _activeVehicleChanged(Vehicle* activeVehicle);
};
#endif
This diff is collapsed.
This diff is collapsed.
/****************************************************************************
*
* (c) 2009-2016 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
*
* QGroundControl is licensed according to the terms in the file
* COPYING.md in the root of the source code directory.
*
****************************************************************************/
#include "PlanMasterControllerTest.h"
#include "LinkManager.h"
#include "MultiVehicleManager.h"
#include "SimpleMissionItem.h"
#include "MissionSettingsItem.h"
#include "QGCApplication.h"
#include "SettingsManager.h"
#include "AppSettings.h"
PlanMasterControllerTest::PlanMasterControllerTest(void)
: _masterController(NULL)
{
}
void PlanMasterControllerTest::init(void)
{
UnitTest::init();
_masterController = new PlanMasterController(this);
_masterController->start(true /* editMode */);
}
void PlanMasterControllerTest::cleanup(void)
{
delete _masterController;
_masterController = NULL;
UnitTest::cleanup();
}
void PlanMasterControllerTest::_testMissionFileLoad(void)
{
_masterController->loadFromFile(":/json/unittest/OldFileFormat.mission");
QCOMPARE(_masterController->missionController()->visualItems()->count(), 7);
}
void PlanMasterControllerTest::_testMissionPlannerFileLoad(void)
{
_masterController->loadFromFile(":/json/unittest/MissionPlanner.waypoints");
QCOMPARE(_masterController->missionController()->visualItems()->count(), 6);
}
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -39,6 +39,13 @@ void RallyPointManager::loadFromVehicle(void)
void RallyPointManager::sendToVehicle(const QList<QGeoCoordinate>& rgPoints)
{
// No support in generic vehicle
Q_UNUSED(rgPoints);
emit sendComplete(false /* error */);
}
void RallyPointManager::removeAll(void)
{
// No support in generic vehicle
emit removeAllComplete(false /* error */);
}
This diff is collapsed.
This diff is collapsed.
......@@ -27,14 +27,11 @@ SpeedSection::SpeedSection(Vehicle* vehicle, QObject* parent)
_metaDataMap = FactMetaData::createMapFromJsonFile(QStringLiteral(":/json/SpeedSection.FactMetaData.json"), NULL /* metaDataParent */);
}
double hoverSpeed, cruiseSpeed;
double flightSpeed = 0;
_vehicle->firmwarePlugin()->missionFlightSpeedInfo(_vehicle, hoverSpeed, cruiseSpeed);
if (_vehicle->multiRotor()) {
flightSpeed = hoverSpeed;
} else if (_vehicle->fixedWing()) {
flightSpeed = cruiseSpeed;
flightSpeed = _vehicle->defaultHoverSpeed();
} else {
flightSpeed = _vehicle->defaultCruiseSpeed();
}
_metaDataMap[_flightSpeedName]->setRawDefaultValue(flightSpeed);
......
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