Commit 33082ffc authored by Andreas Bircher's avatar Andreas Bircher
Browse files

Merge branch 'pull_upstream' into feature/offlineElevationData

Conflicts:
	src/Terrain.cc
parents 6f474c99 2676fe2c
Subproject commit 3ddcbdfcd360c846246d8905d877add3488c8363
Subproject commit 37d14af47d783eb516959cc10e4cf70d66e927c0
......@@ -18,8 +18,8 @@
AudioOutput::AudioOutput(QGCApplication* app, QGCToolbox* toolbox)
: QGCTool(app, toolbox)
, _tts(new QTextToSpeech(this))
{
_tts = new QTextToSpeech(this);
connect(_tts, &QTextToSpeech::stateChanged, this, &AudioOutput::_stateChanged);
}
......
......@@ -4189,7 +4189,7 @@ default 1.5 turns per second</short_desc>
<boolean />
<scope>modules/mc_att_control</scope>
</parameter>
<parameter default="0." name="MC_DTERM_CUTOFF" type="FLOAT">
<parameter default="30." name="MC_DTERM_CUTOFF" type="FLOAT">
<short_desc>Cutoff frequency for the low pass filter on the D-term in the rate controller</short_desc>
<long_desc>The D-term uses the derivative of the rate and thus is the most susceptible to noise. Therefore, using a D-term filter allows to decrease the driver-level filtering, which leads to reduced control latency and permits to increase the P gains. A value of 0 disables the filter.</long_desc>
<min>0</min>
......@@ -8113,7 +8113,7 @@ This is used for gathering replay logs for the ekf2 module</short_desc>
<reboot_required>true</reboot_required>
<scope>modules/sensors</scope>
</parameter>
<parameter default="30.0" name="IMU_GYRO_CUTOFF" type="FLOAT">
<parameter default="80.0" name="IMU_GYRO_CUTOFF" type="FLOAT">
<short_desc>Driver level cutoff frequency for gyro</short_desc>
<long_desc>The cutoff frequency for the 2nd order butterworth filter on the gyro driver. This features is currently supported by the mpu6000 and mpu9250. This only affects the signal sent to the controllers, not the estimators. 0 disables the filter.</long_desc>
<min>0</min>
......@@ -9240,15 +9240,16 @@ This is used for gathering replay logs for the ekf2 module</short_desc>
</parameter>
<parameter default="0" name="UAVCAN_ENABLE" type="INT32">
<short_desc>UAVCAN mode</short_desc>
<long_desc>0 - UAVCAN disabled. 1 - Basic support for UAVCAN actuators and sensors. 2 - Full support for dynamic node ID allocation and firmware update. 3 - Sets the motor control outputs to UAVCAN and enables support for dynamic node ID allocation and firmware update.</long_desc>
<long_desc>0 - UAVCAN disabled. 1 - Enables support for UAVCAN sensors without dynamic node ID allocation and firmware update. 2 - Enables support for UAVCAN sensors with dynamic node ID allocation and firmware update. 3 - Enables support for UAVCAN sensors and actuators with dynamic node ID allocation and firmware update. Also sets the motor control outputs to UAVCAN.</long_desc>
<min>0</min>
<max>3</max>
<reboot_required>true</reboot_required>
<scope>modules/uavcan</scope>
<values>
<value code="0">Disabled</value>
<value code="2">Only Sensors</value>
<value code="3">Sensors and Motors</value>
<value code="1">Sensors Manual Config</value>
<value code="2">Sensors Automatic Config</value>
<value code="3">Sensors and Actuators (ESCs) Automatic Config</value>
</values>
</parameter>
<parameter default="1" name="UAVCAN_ESC_IDLT" type="INT32">
......
......@@ -155,7 +155,7 @@ FlightMap {
}
MapFitFunctions {
id: mapFitFunctions
id: mapFitFunctions // The name for this id cannot be changed without breaking references outside of this code. Beware!
map: _flightMap
usePlannedHomePosition: false
planMasterController: _planMasterController
......
......@@ -90,10 +90,6 @@ Item {
}
function addMissionItemCoordsForFit(coordList) {
var homePosition = fitHomePosition()
if (homePosition.isValid) {
coordList.push(homePosition)
}
for (var i=1; i<_missionController.visualItems.count; i++) {
var missionItem = _missionController.visualItems.get(i)
if (missionItem.specifiesCoordinate && !missionItem.isStandaloneCoordinate) {
......
......@@ -25,6 +25,7 @@ const char* Joystick::_throttleModeSettingsKey = "ThrottleMode";
const char* Joystick::_exponentialSettingsKey = "Exponential";
const char* Joystick::_accumulatorSettingsKey = "Accumulator";
const char* Joystick::_deadbandSettingsKey = "Deadband";
const char* Joystick::_circleCorrectionSettingsKey = "Circle_Correction";
const char* Joystick::_txModeSettingsKey = NULL;
const char* Joystick::_fixedWingTXModeSettingsKey = "TXMode_FixedWing";
const char* Joystick::_multiRotorTXModeSettingsKey = "TXMode_MultiRotor";
......@@ -64,6 +65,7 @@ Joystick::Joystick(const QString& name, int axisCount, int buttonCount, int hatC
, _exponential(0)
, _accumulator(false)
, _deadband(false)
, _circleCorrection(false)
, _activeVehicle(NULL)
, _pollingStartedForCalibration(false)
, _multiVehicleManager(multiVehicleManager)
......@@ -124,6 +126,7 @@ void Joystick::_setDefaultCalibration(void) {
_exponential = 0;
_accumulator = false;
_deadband = false;
_circleCorrection = false;
_throttleMode = ThrottleModeCenterZero;
_calibrated = true;
......@@ -188,6 +191,7 @@ void Joystick::_loadSettings(void)
_exponential = settings.value(_exponentialSettingsKey, 0).toFloat();
_accumulator = settings.value(_accumulatorSettingsKey, false).toBool();
_deadband = settings.value(_deadbandSettingsKey, false).toBool();
_circleCorrection = settings.value(_circleCorrectionSettingsKey, false).toBool();
_throttleMode = (ThrottleMode_t)settings.value(_throttleModeSettingsKey, ThrottleModeCenterZero).toInt(&convertOk);
badSettings |= !convertOk;
......@@ -264,9 +268,10 @@ void Joystick::_saveSettings(void)
settings.setValue(_exponentialSettingsKey, _exponential);
settings.setValue(_accumulatorSettingsKey, _accumulator);
settings.setValue(_deadbandSettingsKey, _deadband);
settings.setValue(_circleCorrectionSettingsKey, _circleCorrection);
settings.setValue(_throttleModeSettingsKey, _throttleMode);
qCDebug(JoystickLog) << "_saveSettings calibrated:throttlemode:deadband:txmode" << _calibrated << _throttleMode << _deadband << _transmitterMode;
qCDebug(JoystickLog) << "_saveSettings calibrated:throttlemode:deadband:txmode" << _calibrated << _throttleMode << _deadband << _circleCorrection << _transmitterMode;
QString minTpl ("Axis%1Min");
QString maxTpl ("Axis%1Max");
......@@ -462,17 +467,19 @@ void Joystick::run(void)
throttle = throttle_accu;
}
float roll_limited = std::max(static_cast<float>(-M_PI_4), std::min(roll, static_cast<float>(M_PI_4)));
float pitch_limited = std::max(static_cast<float>(-M_PI_4), std::min(pitch, static_cast<float>(M_PI_4)));
float yaw_limited = std::max(static_cast<float>(-M_PI_4), std::min(yaw, static_cast<float>(M_PI_4)));
float throttle_limited = std::max(static_cast<float>(-M_PI_4), std::min(throttle, static_cast<float>(M_PI_4)));
// Map from unit circle to linear range and limit
roll = std::max(-1.0f, std::min(tanf(asinf(roll_limited)), 1.0f));
pitch = std::max(-1.0f, std::min(tanf(asinf(pitch_limited)), 1.0f));
yaw = std::max(-1.0f, std::min(tanf(asinf(yaw_limited)), 1.0f));
throttle = std::max(-1.0f, std::min(tanf(asinf(throttle_limited)), 1.0f));
if ( _circleCorrection ) {
float roll_limited = std::max(static_cast<float>(-M_PI_4), std::min(roll, static_cast<float>(M_PI_4)));
float pitch_limited = std::max(static_cast<float>(-M_PI_4), std::min(pitch, static_cast<float>(M_PI_4)));
float yaw_limited = std::max(static_cast<float>(-M_PI_4), std::min(yaw, static_cast<float>(M_PI_4)));
float throttle_limited = std::max(static_cast<float>(-M_PI_4), std::min(throttle, static_cast<float>(M_PI_4)));
// Map from unit circle to linear range and limit
roll = std::max(-1.0f, std::min(tanf(asinf(roll_limited)), 1.0f));
pitch = std::max(-1.0f, std::min(tanf(asinf(pitch_limited)), 1.0f));
yaw = std::max(-1.0f, std::min(tanf(asinf(yaw_limited)), 1.0f));
throttle = std::max(-1.0f, std::min(tanf(asinf(throttle_limited)), 1.0f));
}
if ( _exponential != 0 ) {
// Exponential (0% to -50% range like most RC radios)
//_exponential is set by a slider in joystickConfig.qml
......@@ -767,6 +774,19 @@ void Joystick::setDeadband(bool deadband)
_saveSettings();
}
bool Joystick::circleCorrection(void)
{
return _circleCorrection;
}
void Joystick::setCircleCorrection(bool circleCorrection)
{
_circleCorrection = circleCorrection;
_saveSettings();
emit circleCorrectionChanged(_circleCorrection);
}
void Joystick::setCalibrationMode(bool calibrating)
{
_calibrationMode = calibrating;
......
......@@ -76,8 +76,9 @@ public:
Q_PROPERTY(bool negativeThrust READ negativeThrust WRITE setNegativeThrust NOTIFY negativeThrustChanged)
Q_PROPERTY(float exponential READ exponential WRITE setExponential NOTIFY exponentialChanged)
Q_PROPERTY(bool accumulator READ accumulator WRITE setAccumulator NOTIFY accumulatorChanged)
Q_PROPERTY(bool requiresCalibration READ requiresCalibration CONSTANT)
Q_PROPERTY(bool requiresCalibration READ requiresCalibration CONSTANT)
Q_PROPERTY(bool circleCorrection READ circleCorrection WRITE setCircleCorrection NOTIFY circleCorrectionChanged)
// Property accessors
int axisCount(void) { return _axisCount; }
......@@ -120,6 +121,9 @@ public:
bool deadband(void);
void setDeadband(bool accu);
bool circleCorrection(void);
void setCircleCorrection(bool circleCorrection);
void setTXMode(int mode);
int getTXMode(void) { return _transmitterMode; }
......@@ -147,6 +151,8 @@ signals:
void enabledChanged(bool enabled);
void circleCorrectionChanged(bool circleCorrection);
/// Signal containing new joystick information
/// @param roll Range is -1:1, negative meaning roll left, positive meaning roll right
/// @param pitch Range i -1:1, negative meaning pitch down, positive meaning pitch up
......@@ -213,6 +219,7 @@ protected:
float _exponential;
bool _accumulator;
bool _deadband;
bool _circleCorrection;
Vehicle* _activeVehicle;
bool _pollingStartedForCalibration;
......@@ -229,6 +236,7 @@ private:
static const char* _exponentialSettingsKey;
static const char* _accumulatorSettingsKey;
static const char* _deadbandSettingsKey;
static const char* _circleCorrectionSettingsKey;
static const char* _txModeSettingsKey;
static const char* _fixedWingTXModeSettingsKey;
static const char* _multiRotorTXModeSettingsKey;
......
......@@ -97,7 +97,7 @@ 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) {
if (jsonValue.type() == QJsonValue::Null && types[i] == QJsonValue::Double) {
// Null type signals a NaN on a double value
continue;
}
......
......@@ -106,7 +106,7 @@ public:
static bool parseEnum(const QJsonObject& jsonObject, QStringList& enumStrings, QStringList& enumValues, QString& errorString, QString valueName = QString());
/// Returns NaN if the value is null, or it not the double value
/// Returns NaN if the value is null, or if not, the double value
static double possibleNaNJsonValue(const QJsonValue& value);
static const char* jsonVersionKey;
......
......@@ -343,13 +343,13 @@ int MissionController::insertSimpleMissionItem(QGeoCoordinate coordinate, int i)
}
}
newItem->setDefaultsForCommand();
if ((MAV_CMD)newItem->command() == MAV_CMD_NAV_WAYPOINT) {
double prevAltitude;
MAV_FRAME prevFrame;
if (newItem->specifiesAltitude()) {
double prevAltitude;
int prevAltitudeMode;
if (_findPreviousAltitude(i, &prevAltitude, &prevFrame)) {
newItem->missionItem().setFrame(prevFrame);
newItem->missionItem().setParam7(prevAltitude);
if (_findPreviousAltitude(i, &prevAltitude, &prevAltitudeMode)) {
newItem->altitude()->setRawValue(prevAltitude);
newItem->setAltitudeMode((SimpleMissionItem::AltitudeMode)prevAltitudeMode);
}
}
newItem->setMissionFlightStatus(_missionFlightStatus);
......@@ -372,12 +372,12 @@ int MissionController::insertROIMissionItem(QGeoCoordinate coordinate, int i)
newItem->setDefaultsForCommand();
newItem->setCoordinate(coordinate);
double prevAltitude;
MAV_FRAME prevFrame;
double prevAltitude;
int prevAltitudeMode;
if (_findPreviousAltitude(i, &prevAltitude, &prevFrame)) {
newItem->missionItem().setFrame(prevFrame);
newItem->missionItem().setParam7(prevAltitude);
if (_findPreviousAltitude(i, &prevAltitude, &prevAltitudeMode)) {
newItem->altitude()->setRawValue(prevAltitude);
newItem->setAltitudeMode((SimpleMissionItem::AltitudeMode)prevAltitudeMode);
}
_visualItems->insert(i, newItem);
......@@ -924,6 +924,18 @@ bool MissionController::loadTextFile(QFile& file, QString& errorString)
return true;
}
bool MissionController::readyForSaveSend(void) const
{
for (int i=0; i<_visualItems->count(); i++) {
VisualMissionItem* visualItem = qobject_cast<VisualMissionItem*>(_visualItems->get(i));
if (!visualItem->readyForSave()) {
return false;
}
}
return true;
}
void MissionController::save(QJsonObject& json)
{
json[JsonHelper::jsonVersionKey] = _missionFileVersion;
......@@ -1284,7 +1296,7 @@ void MissionController::_recalcMissionFlightStatus()
}
// Link back to home if first item is takeoff and we have home position
if (firstCoordinateItem && simpleItem && simpleItem->command() == MavlinkQmlSingleton::MAV_CMD_NAV_TAKEOFF) {
if (firstCoordinateItem && simpleItem && (simpleItem->command() == MavlinkQmlSingleton::MAV_CMD_NAV_TAKEOFF || simpleItem->command() == MavlinkQmlSingleton::MAV_CMD_NAV_VTOL_TAKEOFF)) {
if (showHomePosition) {
linkStartToHome = true;
if (_controllerVehicle->multiRotor() || _controllerVehicle->vtol()) {
......@@ -1303,9 +1315,15 @@ void MissionController::_recalcMissionFlightStatus()
case MavlinkQmlSingleton::MAV_CMD_NAV_TAKEOFF:
vtolInHover = false;
break;
case MavlinkQmlSingleton::MAV_CMD_NAV_VTOL_TAKEOFF:
vtolInHover = true;
break;
case MavlinkQmlSingleton::MAV_CMD_NAV_LAND:
vtolInHover = false;
break;
case MavlinkQmlSingleton::MAV_CMD_NAV_VTOL_LAND:
vtolInHover = true;
break;
case MavlinkQmlSingleton::MAV_CMD_DO_VTOL_TRANSITION:
{
int transitionState = simpleItem->missionItem().param1();
......@@ -1648,11 +1666,11 @@ void MissionController::_inProgressChanged(bool inProgress)
emit syncInProgressChanged(inProgress);
}
bool MissionController::_findPreviousAltitude(int newIndex, double* prevAltitude, MAV_FRAME* prevFrame)
bool MissionController::_findPreviousAltitude(int newIndex, double* prevAltitude, int* prevAltitudeMode)
{
bool found = false;
double foundAltitude;
MAV_FRAME foundFrame;
int foundAltitudeMode;
if (newIndex > _visualItems->count()) {
return false;
......@@ -1665,9 +1683,9 @@ bool MissionController::_findPreviousAltitude(int newIndex, double* prevAltitude
if (visualItem->specifiesCoordinate() && !visualItem->isStandaloneCoordinate()) {
if (visualItem->isSimpleItem()) {
SimpleMissionItem* simpleItem = qobject_cast<SimpleMissionItem*>(visualItem);
if ((MAV_CMD)simpleItem->command() == MAV_CMD_NAV_WAYPOINT) {
foundAltitude = simpleItem->exitCoordinate().altitude();
foundFrame = simpleItem->missionItem().frame();
if (simpleItem->specifiesAltitude()) {
foundAltitude = simpleItem->altitude()->rawValue().toDouble();
foundAltitudeMode = simpleItem->altitudeMode();
found = true;
break;
}
......@@ -1677,7 +1695,7 @@ bool MissionController::_findPreviousAltitude(int newIndex, double* prevAltitude
if (found) {
*prevAltitude = foundAltitude;
*prevFrame = foundFrame;
*prevAltitudeMode = foundAltitudeMode;
}
return found;
......
......@@ -118,6 +118,10 @@ public:
/// @param sequenceNumber - index for new item, -1 to clear current item
Q_INVOKABLE void setCurrentPlanViewIndex(int sequenceNumber, bool force);
/// Determines if the mission has all data needed to be saved or sent to the vehicle. Currently the only case where this
/// would return false is when it is still waiting on terrain data to determine correct altitudes.
bool readyForSaveSend(void) const;
/// Sends the mission items to the specified vehicle
static void sendItemsToVehicle(Vehicle* vehicle, QmlObjectListModel* visualMissionItems);
......@@ -218,7 +222,7 @@ private:
void _setupActiveVehicle(Vehicle* activeVehicle, bool forceLoadFromVehicle);
void _calcPrevWaypointValues(double homeAlt, VisualMissionItem* currentItem, VisualMissionItem* prevItem, double* azimuth, double* distance, double* altDifference);
static double _calcDistanceToHome(VisualMissionItem* currentItem, VisualMissionItem* homeItem);
bool _findPreviousAltitude(int newIndex, double* prevAltitude, MAV_FRAME* prevFrame);
bool _findPreviousAltitude(int newIndex, double* prevAltitude, int* prevAltitudeMode);
static double _normalizeLat(double lat);
static double _normalizeLon(double lon);
void _addMissionSettings(QmlObjectListModel* visualItems, bool addToCenter);
......
......@@ -38,10 +38,6 @@ public:
/// from mission start to resumeIndex in the generate mission.
void generateResumeMission(int resumeIndex);
signals:
void currentIndexChanged (int currentIndex);
void lastCurrentIndexChanged (int lastCurrentIndex);
private slots:
void _mavlinkMessageReceived(const mavlink_message_t& message);
......
......@@ -47,10 +47,14 @@ public:
/// 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);
Q_INVOKABLE void start(bool editMode);
/// Starts the controller using a single static active vehicle. Will not track global active vehicle changes.
Q_INVOKABLE virtual void startStaticActiveVehicle(Vehicle* vehicle);
Q_INVOKABLE void startStaticActiveVehicle(Vehicle* vehicle);
/// Determines if the plan has all data needed to be saved or sent to the vehicle. Currently the only case where this
/// would return false is when it is still waiting on terrain data to determine correct altitudes.
Q_INVOKABLE bool readyForSaveSend(void) const { return _missionController.readyForSaveSend(); }
/// Sends a plan to the specified file
/// @param[in] vehicle Vehicle we are sending a plan to
......
......@@ -258,6 +258,19 @@ void QGCMapPolygon::appendVertex(const QGeoCoordinate& coordinate)
emit pathChanged();
}
void QGCMapPolygon::appendVertices(const QList<QGeoCoordinate>& coordinates)
{
QList<QObject*> objects;
foreach (const QGeoCoordinate& coordinate, coordinates) {
objects.append(new QGCQGeoCoordinate(coordinate, this));
_polygonPath.append(QVariant::fromValue(coordinate));
}
_polygonModel.append(objects);
emit pathChanged();
}
void QGCMapPolygon::_polygonModelDirtyChanged(bool dirty)
{
if (dirty) {
......@@ -509,9 +522,7 @@ bool QGCMapPolygon::loadKMLFile(const QString& kmlFile)
}
clear();
for (int i=0; i<rgCoords.count(); i++) {
appendVertex(rgCoords[i]);
}
appendVertices(rgCoords);
return true;
}
......
......@@ -40,6 +40,7 @@ public:
Q_INVOKABLE void clear(void);
Q_INVOKABLE void appendVertex(const QGeoCoordinate& coordinate);
Q_INVOKABLE void removeVertex(int vertexIndex);
Q_INVOKABLE void appendVertices(const QList<QGeoCoordinate>& coordinates);
/// Adjust the value for the specified coordinate
/// @param vertexIndex Polygon point index to modify (0-based)
......
......@@ -32,6 +32,7 @@ Item {
property int borderWidth: 0
property color borderColor: "black"
property var _gqcView: ggcView
property var _polygonComponent
property var _dragHandlesComponent
property var _splitHandlesComponent
......@@ -172,14 +173,16 @@ Item {
QGCFileDialog {
id: kmlLoadDialog
qgcView: _root.qgcView
qgcView: _qgcView
folder: QGroundControl.settingsManager.appSettings.missionSavePath
title: qsTr("Select KML File")
selectExisting: true
nameFilters: [ qsTr("KML files (*.kml)") ]
fileExtension: "kml"
fileExtension: QGroundControl.settingsManager.appSettings.kmlFileExtension
onAcceptedForLoad: {
mapPolygon.loadKMLFile(file)
mapFitFunctions.fitMapViewportToMissionItems()
close()
}
}
......
This diff is collapsed.
......@@ -29,12 +29,21 @@ public:
~SimpleMissionItem();
const SimpleMissionItem& operator=(const SimpleMissionItem& other);
enum AltitudeMode {
AltitudeRelative,
AltitudeAMSL,
AltitudeAboveTerrain
};
Q_ENUM(AltitudeMode)
Q_PROPERTY(QString category READ category NOTIFY commandChanged)
Q_PROPERTY(bool friendlyEditAllowed READ friendlyEditAllowed NOTIFY friendlyEditAllowedChanged)
Q_PROPERTY(bool rawEdit READ rawEdit WRITE setRawEdit NOTIFY rawEditChanged) ///< true: raw item editing with all params
Q_PROPERTY(bool relativeAltitude READ relativeAltitude NOTIFY frameChanged)
Q_PROPERTY(bool specifiesAltitude READ specifiesAltitude NOTIFY commandChanged)
Q_PROPERTY(Fact* altitude READ altitude CONSTANT) ///< Altitude as specified by altitudeMode. Not necessarily true mission item altitude
Q_PROPERTY(AltitudeMode altitudeMode READ altitudeMode WRITE setAltitudeMode NOTIFY altitudeModeChanged)
Q_PROPERTY(Fact* amslAltAboveTerrain READ amslAltAboveTerrain CONSTANT) ///< Actual AMSL altitude for item if altitudeMode == AltitudeAboveTerrain
Q_PROPERTY(MavlinkQmlSingleton::Qml_MAV_CMD command READ command WRITE setCommand NOTIFY commandChanged)
/// Optional sections
......@@ -42,7 +51,6 @@ public:
Q_PROPERTY(QObject* cameraSection READ cameraSection NOTIFY cameraSectionChanged)
// These properties are used to display the editing ui
Q_PROPERTY(QmlObjectListModel* checkboxFacts READ checkboxFacts CONSTANT)
Q_PROPERTY(QmlObjectListModel* comboboxFacts READ comboboxFacts CONSTANT)
Q_PROPERTY(QmlObjectListModel* textFieldFacts READ textFieldFacts CONSTANT)
Q_PROPERTY(QmlObjectListModel* nanFacts READ nanFacts CONSTANT)
......@@ -60,15 +68,20 @@ public:
MavlinkQmlSingleton::Qml_MAV_CMD command(void) const { return (MavlinkQmlSingleton::Qml_MAV_CMD)_missionItem._commandFact.cookedValue().toInt(); }
bool friendlyEditAllowed (void) const;
bool rawEdit (void) const;
bool specifiesAltitude (void) const;
AltitudeMode altitudeMode (void) const { return _altitudeMode; }
Fact* altitude (void) { return &_altitudeFact; }
Fact* amslAltAboveTerrain (void) { return &_amslAltAboveTerrainFact; }
CameraSection* cameraSection (void) { return _cameraSection; }
SpeedSection* speedSection (void) { return _speedSection; }
QmlObjectListModel* textFieldFacts (void) { return &_textFieldFacts; }
QmlObjectListModel* nanFacts (void) { return &_nanFacts; }
QmlObjectListModel* checkboxFacts (void) { return &_checkboxFacts; }
QmlObjectListModel* comboboxFacts (void) { return &_comboboxFacts; }
void setRawEdit(bool rawEdit);
void setAltitudeMode(AltitudeMode altitudeMode);
void setCommandByIndex(int index);
......@@ -82,8 +95,6 @@ public:
bool load(QTextStream &loadStream);
bool load(const QJsonObject& json, int sequenceNumber, QString& errorString);
bool relativeAltitude(void) { return _missionItem.frame() == MAV_FRAME_GLOBAL_RELATIVE_ALT; }
MissionItem& missionItem(void) { return _missionItem; }
const MissionItem& missionItem(void) const { return _missionItem; }
......@@ -107,6 +118,7 @@ public:
void appendMissionItems (QList<MissionItem*>& items, QObject* missionItemParent) final;
void applyNewAltitude (double newAltitude) final;
void setMissionFlightStatus (MissionController::MissionFlightStatus_t& missionFlightStatus) final;
bool readyForSave (void) const final;
bool coordinateHasRelativeAltitude (void) const final { return _missionItem.relativeAltitude(); }
bool exitCoordinateHasRelativeAltitude (void) const final { return coordinateHasRelativeAltitude(); }
......@@ -123,51 +135,51 @@ public slots:
signals:
void commandChanged (int command);
void frameChanged (int frame);
void friendlyEditAllowedChanged (bool friendlyEditAllowed);
void headingDegreesChanged (double heading);
void rawEditChanged (bool rawEdit);
void cameraSectionChanged (QObject* cameraSection);
void speedSectionChanged (QObject* cameraSection);
void altitudeModeChanged (void);
private slots:
void _setDirtyFromSignal (void);
void _sectionDirtyChanged (bool dirty);
void _sendCommandChanged (void);
void _sendCoordinateChanged (void);
void _sendFrameChanged (void);
void _sendFriendlyEditAllowedChanged (void);
void _syncAltitudeRelativeToHomeToFrame (const QVariant& value);
void _syncFrameToAltitudeRelativeToHome (void);
void _updateLastSequenceNumber (void);
void _rebuildFacts (void);
void _setDirty (void);
void _sectionDirtyChanged (bool dirty);
void _sendCommandChanged (void);
void _sendCoordinateChanged (void);
void _sendFriendlyEditAllowedChanged(void);
void _altitudeChanged (void);
void _altitudeModeChanged (void);
void _terrainAltChanged (void);
void _updateLastSequenceNumber (void);
void _rebuildFacts (void);
void _rebuildTextFieldFacts (void);
private:
void _connectSignals (void);
void _setupMetaData (void);
void _updateOptionalSections(void);
void _rebuildTextFieldFacts (void);
void _rebuildNaNFacts (void);
void _rebuildCheckboxFacts (void);
void _rebuildComboBoxFacts (void);
MissionItem _missionItem;
bool _rawEdit;
bool _dirty;
bool _ignoreDirtyChangeSignals;
MissionItem _missionItem;
bool _rawEdit;
bool _dirty;
bool _ignoreDirtyChangeSignals;
SpeedSection* _speedSection;
CameraSection* _cameraSection;
MissionCommandTree* _commandTree;
Fact _altitudeRelativeToHomeFact;
Fact _supportedCommandFact;
Fact _supportedCommandFact;
AltitudeMode _altitudeMode;
Fact _altitudeFact;
Fact _amslAltAboveTerrainFact;
QmlObjectListModel _textFieldFacts;
QmlObjectListModel _nanFacts;
QmlObjectListModel _checkboxFacts;
QmlObjectListModel _comboboxFacts;
static FactMetaData* _altitudeMetaData;
......@@ -185,8 +197,11 @@ private:
FactMetaData _param6MetaData;
FactMetaData _param7MetaData;
bool _syncingAltitudeRelativeToHomeAndFrame; ///< true: already in a sync signal, prevents signal loop
bool _syncingHeadingDegreesAndParam4; ///< true: already in a sync signal, prevents signal loop
bool _syncingHeadingDegreesAndParam4; ///< true: already in a sync signal, prevents signal loop
static const char* _jsonAltitudeModeKey;
static const char* _jsonAltitudeKey;
static const char* _jsonAMSLAltAboveTerrainKey;
};
#endif
......@@ -15,43 +15,37 @@
const SimpleMissionItemTest::ItemInfo_t SimpleMissionItemTest::_rgItemInfo[] = {
{ MAV_CMD_NAV_WAYPOINT, MAV_FRAME_GLOBAL_RELATIVE_ALT },
{ MAV_CMD_NAV_LOITER_UNLIM, MAV_FRAME_GLOBAL_RELATIVE_ALT },
{ MAV_CMD_NAV_LOITER_UNLIM, MAV_FRAME_GLOBAL },
{ MAV_CMD_NAV_LOITER_TURNS, MAV_FRAME_GLOBAL_RELATIVE_ALT },
{ MAV_CMD_NAV_LOITER_TIME, MAV_FRAME_GLOBAL_RELATIVE_ALT },
{ MAV_CMD_NAV_LOITER_TIME, MAV_FRAME_GLOBAL },
{ MAV_CMD_NAV_LAND, MAV_FRAME_GLOBAL_RELATIVE_ALT },
{ MAV_CMD_NAV_TAKEOFF, MAV_FRAME_GLOBAL_RELATIVE_ALT },
{ MAV_CMD_NAV_TAKEOFF, MAV_FRAME_GLOBAL },
{ MAV_CMD_DO_JUMP, MAV_FRAME_MISSION },
};
const SimpleMissionItemTest::FactValue_t SimpleMissionItemTest::_rgFactValuesWaypoint[] = {
{ "Altitude", 70.1234567 },
{ "Hold", 10.1234567 },
};
const SimpleMissionItemTest::FactValue_t SimpleMissionItemTest::_rgFactValuesLoiterUnlim[] = {
{ "Altitude", 70.1234567 },
{ "Radius", 30.1234567 },
};
const SimpleMissionItemTest::FactValue_t SimpleMissionItemTest::_rgFactValuesLoiterTurns[] = {
{ "Altitude", 70.1234567 },
{ "Radius", 30.1234567 },
{ "Turns", 10.1234567 },
};
const SimpleMissionItemTest::FactValue_t SimpleMissionItemTest::_rgFactValuesLoiterTime[] = {
{ "Altitude", 70.1234567 },
{ "Radius", 30.1234567 },
{ "Hold", 10.1234567 },
};
const SimpleMissionItemTest::FactValue_t SimpleMissionItemTest::_rgFactValuesLand[] = {
{ "Altitude", 70.1234567 },
};
const SimpleMissionItemTest::FactValue_t SimpleMissionItemTest::_rgFactValuesTakeoff[] = {
{ "Pitch", 10.1234567 },
{ "Altitude", 70.1234567 },
};
const SimpleMissionItemTest::FactValue_t SimpleMissionItemTest::_rgFactValuesDoJump[] = {
......@@ -60,13 +54,14 @@ const SimpleMissionItemTest::FactValue_t SimpleMissionItemTest::_rgFactValuesDoJ
};
const SimpleMissionItemTest::ItemExpected_t SimpleMissionItemTest::_rgItemExpected[] = {
{ sizeof(SimpleMissionItemTest::_rgFactValuesWaypoint)/sizeof(SimpleMissionItemTest::_rgFactValuesWaypoint[0]), SimpleMissionItemTest::_rgFactValuesWaypoint, true },
{ sizeof(SimpleMissionItemTest::_rgFactValuesLoiterUnlim)/sizeof(SimpleMissionItemTest::_rgFactValuesLoiterUnlim[0]), SimpleMissionItemTest::_rgFactValuesLoiterUnlim, true },
{ sizeof(SimpleMissionItemTest::_rgFactValuesLoiterTurns)/sizeof(SimpleMissionItemTest::_rgFactValuesLoiterTurns[0]), SimpleMissionItemTest::_rgFactValuesLoiterTurns, true },
{ sizeof(SimpleMissionItemTest::_rgFactValuesLoiterTime)/sizeof(SimpleMissionItemTest::_rgFactValuesLoiterTime[0]), SimpleMissionItemTest::_rgFactValuesLoiterTime, true },
{ sizeof(SimpleMissionItemTest::_rgFactValuesLand)/sizeof(SimpleMissionItemTest::_rgFactValuesLand[0]), SimpleMissionItemTest::_rgFactValuesLand, true },
{ sizeof(SimpleMissionItemTest::_rgFactValuesTakeoff)/sizeof(SimpleMissionItemTest::_rgFactValuesTakeoff[0]), SimpleMissionItemTest::_rgFactValuesTakeoff, true },
{ sizeof(SimpleMissionItemTest::_rgFactValuesDoJump)/sizeof(SimpleMissionItemTest::_rgFactValuesDoJump[0]), SimpleMissionItemTest::_rgFactValuesDoJump, false },
// Text field facts count Fact Values Altitude Altitude Mode
{ sizeof(SimpleMissionItemTest::_rgFactValuesWaypoint)/sizeof(SimpleMissionItemTest::_rgFactValuesWaypoint[0]), SimpleMissionItemTest::_rgFactValuesWaypoint, 70.1234567, SimpleMissionItem::AltitudeRelative },
{ sizeof(SimpleMissionItemTest::_rgFactValuesLoiterUnlim)/sizeof(SimpleMissionItemTest::_rgFactValuesLoiterUnlim[0]), SimpleMissionItemTest::_rgFactValuesLoiterUnlim, 70.1234567, SimpleMissionItem::AltitudeAMSL },
{ sizeof(SimpleMissionItemTest::_rgFactValuesLoiterTurns)/sizeof(SimpleMissionItemTest::_rgFactValuesLoiterTurns[0]), SimpleMissionItemTest::_rgFactValuesLoiterTurns, 70.1234567, SimpleMissionItem::AltitudeRelative },
{ sizeof(SimpleMissionItemTest::_rgFactValuesLoiterTime)/sizeof(SimpleMissionItemTest::_rgFactValuesLoiterTime[0]), SimpleMissionItemTest::_rgFactValuesLoiterTime, 70.1234567, SimpleMissionItem::AltitudeAMSL },
{ sizeof(SimpleMissionItemTest::_rgFactValuesLand)/sizeof(SimpleMissionItemTest::_rgFactValuesLand[0]), SimpleMissionItemTest::_rgFactValuesLand, 70.1234567, SimpleMissionItem::AltitudeRelative },
{ sizeof(SimpleMissionItemTest::_rgFactValuesTakeoff)/sizeof(SimpleMissionItemTest::_rgFactValuesTakeoff[0]), SimpleMissionItemTest::_rgFactValuesTakeoff, 70.1234567, SimpleMissionItem::AltitudeAMSL },
{ sizeof(SimpleMissionItemTest::_rgFactValuesDoJump)/sizeof(SimpleMissionItemTest::_rgFactValuesDoJump[0]), SimpleMissionItemTest::_rgFactValuesDoJump, qQNaN(), SimpleMissionItem::AltitudeRelative },
};
SimpleMissionItemTest::SimpleMissionItemTest(void)
......@@ -80,12 +75,12 @@ void SimpleMissionItemTest::init(void)
VisualMissionItemTest::init();
rgSimpleItemSignals[commandChangedIndex] = SIGNAL(commandChanged(int));
rgSimpleItemSignals[frameChangedIndex] = SIGNAL(frameChanged(int));
rgSimpleItemSignals[altitudeModeChangedIndex] = SIGNAL(altitudeModeChanged());
rgSimpleItemSignals[friendlyEditAllowedChangedIndex] = SIGNAL(friendlyEditAllowedChanged(bool));
rgSimpleItemSignals[headingDegreesChangedIndex] = SIGNAL(headingDegreesChanged(double));
rgSimpleItemSignals[rawEditChangedIndex] = SIGNAL(rawEditChanged(bool));
rgSimpleItemSignals[cameraSectionChangedIndex] = SIGNAL(rawEditChanged(bool));
rgSimpleItemSignals[speedSectionChangedIndex] = SIGNAL(rawEditChanged(bool));
rgSimpleItemSignals[cameraSectionChangedIndex] = SIGNAL(cameraSectionChanged(QObject*));
rgSimpleItemSignals[speedSectionChangedIndex] = SIGNAL(speedSectionChanged(QObject*));
rgSimpleItemSignals[coordinateHasRelativeAltitudeChangedIndex] = SIGNAL(coordinateHasRelativeAltitudeChanged(bool));
MissionItem missionItem(1, // sequence number
......@@ -164,8 +159,10 @@ void SimpleMissionItemTest::_testEditorFacts(void)
}
QCOMPARE(factCount, expected->cFactValues);
int expectedCount = expected->relativeAltCheckbox ? 1 : 0;
QCOMPARE(simpleMissionItem.checkboxFacts()->count(), expectedCount);
if (!qIsNaN(expected->altValue)) {
QCOMPARE(simpleMissionItem.altitudeMode(), expected->altMode);
QCOMPARE(simpleMissionItem.altitude()->rawValue().toDouble(), expected->altValue);
}
}
delete vehicle;
......@@ -228,18 +225,8 @@ void SimpleMissionItemTest::_testSignals(void)
QVERIFY(_spyVisualItem->checkOnlySignalByMask(dirtyChangedMask));
_spyVisualItem->clearAllSignals();
// Check frameChanged signalling. Calling setFrame should signal:
// frameChanged
// dirtyChanged
// friendlyEditAllowedChanged - this signal is not very smart on when it gets sent
// coordinateHasRelativeAltitudeChanged
missionItem.setFrame(MAV_FRAME_GLOBAL_RELATIVE_ALT);
QVERIFY(_spyVisualItem->checkNoSignals());
QVERIFY(_spySimpleItem->checkNoSignals());
missionItem.setFrame(MAV_FRAME_GLOBAL);
QVERIFY(_spySimpleItem->checkOnlySignalByMask(frameChangedMask | dirtyChangedMask | friendlyEditAllowedChangedMask | coordinateHasRelativeAltitudeChangedMask));
_simpleItem->setAltitudeMode(_simpleItem->altitudeMode() == SimpleMissionItem::AltitudeRelative ? SimpleMissionItem::AltitudeAMSL : SimpleMissionItem::AltitudeRelative);
QVERIFY(_spySimpleItem->checkOnlySignalByMask(dirtyChangedMask | friendlyEditAllowedChangedMask | altitudeModeChangedMask | coordinateHasRelativeAltitudeChangedMask));
_spySimpleItem->clearAllSignals();
_spyVisualItem->clearAllSignals();
......@@ -320,3 +307,18 @@ void SimpleMissionItemTest::_testSpeedSection(void)
QCOMPARE(_spyVisualItem->checkSignalsByMask(specifiedFlightSpeedChangedMask), true);
QCOMPARE(_simpleItem->dirty(), true);
}
void SimpleMissionItemTest::_testAltitudePropogation(void)
{
// Make sure that changes to altitude propogate to param 7 of the mission item
_simpleItem->setAltitudeMode(SimpleMissionItem::AltitudeRelative);
_simpleItem->altitude()->setRawValue(_simpleItem->altitude()->rawValue().toDouble() + 1);
QCOMPARE(_simpleItem->altitude()->rawValue().toDouble(), _simpleItem->missionItem().param7());
QCOMPARE(_simpleItem->missionItem().frame(), MAV_FRAME_GLOBAL_RELATIVE_ALT);
_simpleItem->setAltitudeMode(SimpleMissionItem::AltitudeAMSL);
_simpleItem->altitude()->setRawValue(_simpleItem->altitude()->rawValue().toDouble() + 1);
QCOMPARE(_simpleItem->altitude()->rawValue().toDouble(), _simpleItem->missionItem().param7());
QCOMPARE(_simpleItem->missionItem().frame(), MAV_FRAME_GLOBAL);
}
......@@ -31,11 +31,12 @@ private slots:
void _testSpeedSectionDirty(void);
void _testCameraSection(void);
void _testSpeedSection(void);
void _testAltitudePropogation(void);
private:
enum {
commandChangedIndex = 0,
frameChangedIndex,
altitudeModeChangedIndex,
friendlyEditAllowedChangedIndex,
headingDegreesChangedIndex,
rawEditChangedIndex,
......@@ -47,7 +48,7 @@ private:
enum {
commandChangedMask = 1 << commandChangedIndex,
frameChangedMask = 1 << frameChangedIndex,
altitudeModeChangedMask = 1 << altitudeModeChangedIndex,
friendlyEditAllowedChangedMask = 1 << friendlyEditAllowedChangedIndex,
headingDegreesChangedMask = 1 << headingDegreesChangedIndex,
rawEditChangedMask = 1 << rawEditChangedIndex,
......@@ -70,9 +71,10 @@ private:
} FactValue_t;
typedef struct {
size_t cFactValues;
const FactValue_t* rgFactValues;
bool relativeAltCheckbox;
size_t cFactValues;
const FactValue_t* rgFactValues;
double altValue;
SimpleMissionItem::AltitudeMode altMode;
} ItemExpected_t;
SimpleMissionItem* _simpleItem;
......
Supports Markdown
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