Browse Source

Mission Editor usability changes

QGC4.4
Don Gagne 10 years ago
parent
commit
0adf8caad5
  1. 1
      qgroundcontrol.qrc
  2. 48
      src/FlightDisplay/FlightDisplayView.qml
  3. 18
      src/FlightMap/FlightMap.qml
  4. 1059
      src/MissionEditor/MissionEditor.qml
  5. 5
      src/MissionEditor/MissionEditorController.cc
  6. 233
      src/MissionItem.cc
  7. 42
      src/MissionItem.h
  8. 2
      src/QmlControls/DropButton.qml
  9. 75
      src/QmlControls/MissionItemEditor.qml
  10. 3
      src/QmlControls/MissionItemIndexLabel.qml

1
qgroundcontrol.qrc

@ -70,6 +70,7 @@ @@ -70,6 +70,7 @@
<file alias="Help.svg">src/FlightMap/Images/Help.svg</file>
<file alias="MapCenter.svg">src/FlightMap/Images/MapCenter.svg</file>
<file alias="MapSync.svg">src/FlightMap/Images/MapSync.svg</file>
<file alias="MapSyncChanged.svg">src/FlightMap/Images/MapSyncChanged.svg</file>
<file alias="MapType.svg">src/FlightMap/Images/MapType.svg</file>
<file alias="MapHome.svg">src/FlightMap/Images/MapHome.svg</file>
<file alias="MapAddMission.svg">src/FlightMap/Images/MapAddMission.svg</file>

48
src/FlightDisplay/FlightDisplayView.qml

@ -55,15 +55,14 @@ Item { @@ -55,15 +55,14 @@ Item {
property var _activeVehicle: multiVehicleManager.activeVehicle
readonly property real _defaultLatitude: 37.803784
readonly property real _defaultLongitude: -122.462276
readonly property real _defaultRoll: 0
readonly property real _defaultPitch: 0
readonly property real _defaultHeading: 0
readonly property real _defaultAltitudeWGS84: 0
readonly property real _defaultGroundSpeed: 0
readonly property real _defaultAirSpeed: 0
readonly property real _defaultClimbRate: 0
readonly property var _defaultVehicleCoordinate: QtPositioning.coordinate(37.803784, -122.462276)
readonly property real _defaultRoll: 0
readonly property real _defaultPitch: 0
readonly property real _defaultHeading: 0
readonly property real _defaultAltitudeWGS84: 0
readonly property real _defaultGroundSpeed: 0
readonly property real _defaultAirSpeed: 0
readonly property real _defaultClimbRate: 0
readonly property string _mapName: "FlightDisplayView"
readonly property string _showMapBackgroundKey: "/showMapBackground"
@ -72,8 +71,7 @@ Item { @@ -72,8 +71,7 @@ Item {
property real _pitch: _activeVehicle ? (isNaN(_activeVehicle.pitch) ? _defaultPitch : _activeVehicle.pitch) : _defaultPitch
property real _heading: _activeVehicle ? (isNaN(_activeVehicle.heading) ? _defaultHeading : _activeVehicle.heading) : _defaultHeading
property real _latitude: _activeVehicle ? ((_activeVehicle.latitude === 0) ? _defaultLatitude : _activeVehicle.latitude) : _defaultLatitude
property real _longitude: _activeVehicle ? ((_activeVehicle.longitude === 0) ? _defaultLongitude : _activeVehicle.longitude) : _defaultLongitude
property var _vehicleCoordinate: _activeVehicle ? _activeVehicle.coordinate : _defaultVehicleCoordinate
property real _altitudeWGS84: _activeVehicle ? _activeVehicle.altitudeWGS84 : _defaultAltitudeWGS84
property real _groundSpeed: _activeVehicle ? _activeVehicle.groundSpeed : _defaultGroundSpeed
@ -82,14 +80,20 @@ Item { @@ -82,14 +80,20 @@ Item {
property bool _showMap: getBool(QGroundControl.flightMapSettings.loadMapSetting(flightMap.mapName, _showMapBackgroundKey, "1"))
FlightDisplayViewController { id: _controller; }
FlightDisplayViewController { id: _controller }
ExclusiveGroup {
id: _dropButtonsExclusiveGroup
}
// Validate _showMap setting
Component.onCompleted: _setShowMap(_showMap)
Component.onCompleted: {
// We have to be careful to not reference root properties in a function which is in a subcomponent
// until the root component has completed loading. Otherwise you get undefined references.
flightMap.rootLoadCompleted = true
flightMap.updateMapPosition(true /* force */)
_setShowMap(_showMap)
}
function getBool(value) {
return value === '0' ? false : true;
@ -104,24 +108,24 @@ Item { @@ -104,24 +108,24 @@ Item {
QGroundControl.flightMapSettings.saveMapSetting(flightMap.mapName, _showMapBackgroundKey, setBool(_showMap))
}
FlightMap {
id: flightMap
anchors.fill: parent
mapName: _mapName
visible: _showMap
latitude: root._defaultCoordinate.latitude
longitude: root._defaultCoordinate.longitude
property real rootLatitude: root._latitude
property real rootLongitude: root._longitude
Component.onCompleted: updateMapPosition(true /* force */)
property var rootVehicleCoordinate: _vehicleCoordinate
property bool rootLoadCompleted: false
onRootLatitudeChanged: updateMapPosition(false /* force */)
onRootLongitudeChanged: updateMapPosition(false /* force */)
onRootVehicleCoordinateChanged: updateMapPosition(false /* force */)
function updateMapPosition(force) {
if (_followVehicle || force) {
latitude = root._latitude
longitude = root._longitude
if ((_followVehicle || force) && rootLoadCompleted) {
flightMap.latitude = root._vehicleCoordinate.latitude
flightMap.longitude = root._vehicleCoordinate.longitude
}
}

18
src/FlightMap/FlightMap.qml

@ -59,10 +59,13 @@ Map { @@ -59,10 +59,13 @@ Map {
readonly property real zOrderWidgets: 100 ///< z order value to widgets, for example: zoom controls, hud widgetss
readonly property real zOrderMapItems: 50 ///< z order value for map items, for example: mission item indicators
zoomLevel: 18
center: QtPositioning.coordinate(lat, lon)
gesture.flickDeceleration: 3000
gesture.enabled: interactive
readonly property real maxZoomLevel: 20
zoomLevel: 18
center: QtPositioning.coordinate(lat, lon)
gesture.flickDeceleration: 3000
gesture.enabled: interactive
gesture.activeGestures: MapGestureArea.ZoomGesture | MapGestureArea.PanGesture | MapGestureArea.FlickGesture
plugin: Plugin { name: "QGroundControl" }
@ -295,11 +298,4 @@ Map { @@ -295,11 +298,4 @@ Map {
}
}
*/
MouseArea {
//-- TODO: Check if this is still needed when we switch to 5.5.1
//-- Workaround for QTBUG-46388 (Pinch zoom doesn't work without it on mobile)
anchors.fill: parent
}
} // Map

1059
src/MissionEditor/MissionEditor.qml

File diff suppressed because it is too large Load Diff

5
src/MissionEditor/MissionEditorController.cc

@ -103,14 +103,15 @@ int MissionEditorController::addMissionItem(QGeoCoordinate coordinate) @@ -103,14 +103,15 @@ int MissionEditorController::addMissionItem(QGeoCoordinate coordinate)
if (!_canEdit) {
qWarning() << "addMissionItem called with _canEdit == false";
}
// Coordinate will come through without altitude
coordinate.setAltitude(MissionItem::defaultAltitude);
MissionItem * newItem = new MissionItem(this, _missionItems->count(), coordinate, MAV_CMD_NAV_WAYPOINT);
_initMissionItem(newItem);
newItem->setAltitude(30);
if (_missionItems->count() == 1) {
newItem->setCommand(MavlinkQmlSingleton::MAV_CMD_NAV_TAKEOFF);
}
qDebug() << "MissionItem" << newItem->coordinate();
_missionItems->append(newItem);
_recalcAll();

233
src/MissionItem.cc

@ -36,6 +36,13 @@ This file is part of the QGROUNDCONTROL project @@ -36,6 +36,13 @@ This file is part of the QGROUNDCONTROL project
QGC_LOGGING_CATEGORY(MissionItemLog, "MissionItemLog")
const double MissionItem::defaultPitch = 15.0;
const double MissionItem::defaultHeading = 0.0;
const double MissionItem::defaultAltitude = 25.0;
const double MissionItem::defaultAcceptanceRadius = 3.0;
const double MissionItem::defaultLoiterOrbitRadius = 10.0;
const double MissionItem::defaultLoiterTurns = 1.0;
QDebug operator<<(QDebug dbg, const MissionItem& missionItem)
{
QDebugStateSaver saver(dbg);
@ -82,14 +89,14 @@ MissionItem::MissionItem(QObject* parent, @@ -82,14 +89,14 @@ MissionItem::MissionItem(QObject* parent,
, _autocontinue(autocontinue)
, _isCurrentItem(isCurrentItem)
, _reachedTime(0)
, _yawRadiansFact(NULL)
, _headingDegreesFact(NULL)
,_dirty(false)
, _homePositionSpecialCase(false)
{
_latitudeFact = new Fact(0, "Latitude:", FactMetaData::valueTypeDouble, this);
_longitudeFact = new Fact(0, "Longitude:", FactMetaData::valueTypeDouble, this);
_altitudeFact = new Fact(0, "Altitude:", FactMetaData::valueTypeDouble, this);
_yawRadiansFact = new Fact(0, "Heading:", FactMetaData::valueTypeDouble, this);
_headingDegreesFact = new Fact(0, "Heading:", FactMetaData::valueTypeDouble, this);
_loiterOrbitRadiusFact = new Fact(0, "Radius:", FactMetaData::valueTypeDouble, this);
_param1Fact = new Fact(0, QString(), FactMetaData::valueTypeDouble, this);
_param2Fact = new Fact(0, QString(), FactMetaData::valueTypeDouble, this);
@ -100,7 +107,7 @@ MissionItem::MissionItem(QObject* parent, @@ -100,7 +107,7 @@ MissionItem::MissionItem(QObject* parent,
setCoordinate(coordinate);
setParam1(param1);
setParam2(param2);
setYawRadians(param4);
_setYawRadians(param4);
setLoiterOrbitRadius(param3);
// FIXME: Need to fill out more meta data
@ -114,8 +121,8 @@ MissionItem::MissionItem(QObject* parent, @@ -114,8 +121,8 @@ MissionItem::MissionItem(QObject* parent,
FactMetaData* altitudeMetaData = new FactMetaData(FactMetaData::valueTypeDouble, _altitudeFact);
altitudeMetaData->setUnits("meters");
FactMetaData* yawMetaData = new FactMetaData(FactMetaData::valueTypeDouble, _yawRadiansFact);
yawMetaData->setUnits("deg");
FactMetaData* headingMetaData = new FactMetaData(FactMetaData::valueTypeDouble, _headingDegreesFact);
headingMetaData->setUnits("deg");
_pitchMetaData = new FactMetaData(FactMetaData::valueTypeDouble, this);
_pitchMetaData->setUnits("deg");
@ -147,23 +154,10 @@ MissionItem::MissionItem(QObject* parent, @@ -147,23 +154,10 @@ MissionItem::MissionItem(QObject* parent,
_latitudeFact->setMetaData(latitudeMetaData);
_longitudeFact->setMetaData(longitudeMetaData);
_altitudeFact->setMetaData(altitudeMetaData);
_yawRadiansFact->setMetaData(yawMetaData);
_headingDegreesFact->setMetaData(headingMetaData);
_loiterOrbitRadiusFact->setMetaData(loiterOrbitRadiusMetaData);
// Connect to valueChanged to track dirty state
connect(_latitudeFact, &Fact::valueChanged, this, &MissionItem::_factValueChanged);
connect(_longitudeFact, &Fact::valueChanged, this, &MissionItem::_factValueChanged);
connect(_altitudeFact, &Fact::valueChanged, this, &MissionItem::_factValueChanged);
connect(_yawRadiansFact, &Fact::valueChanged, this, &MissionItem::_factValueChanged);
connect(_loiterOrbitRadiusFact, &Fact::valueChanged, this, &MissionItem::_factValueChanged);
connect(_param1Fact, &Fact::valueChanged, this, &MissionItem::_factValueChanged);
connect(_param2Fact, &Fact::valueChanged, this, &MissionItem::_factValueChanged);
connect(_altitudeRelativeToHomeFact, &Fact::valueChanged, this, &MissionItem::_factValueChanged);
// Connect valueChanged signals so we can output coordinateChanged signal
connect(_latitudeFact, &Fact::valueChanged, this, &MissionItem::_coordinateFactChanged);
connect(_longitudeFact, &Fact::valueChanged, this, &MissionItem::_coordinateFactChanged);
connect(_altitudeFact, &Fact::valueChanged, this, &MissionItem::_coordinateFactChanged);
_connectSignals();
}
MissionItem::MissionItem(const MissionItem& other, QObject* parent)
@ -172,7 +166,7 @@ MissionItem::MissionItem(const MissionItem& other, QObject* parent) @@ -172,7 +166,7 @@ MissionItem::MissionItem(const MissionItem& other, QObject* parent)
_latitudeFact = new Fact(this);
_longitudeFact = new Fact(this);
_altitudeFact = new Fact(this);
_yawRadiansFact = new Fact(this);
_headingDegreesFact = new Fact(this);
_loiterOrbitRadiusFact = new Fact(this);
_param1Fact = new Fact(this);
_param2Fact = new Fact(this);
@ -188,26 +182,9 @@ MissionItem::MissionItem(const MissionItem& other, QObject* parent) @@ -188,26 +182,9 @@ MissionItem::MissionItem(const MissionItem& other, QObject* parent)
_jumpSequenceMetaData = new FactMetaData(this);
_jumpRepeatMetaData = new FactMetaData(this);
// Connect to valueChanged to track dirty state
connect(_latitudeFact, &Fact::valueChanged, this, &MissionItem::_factValueChanged);
connect(_longitudeFact, &Fact::valueChanged, this, &MissionItem::_factValueChanged);
connect(_altitudeFact, &Fact::valueChanged, this, &MissionItem::_factValueChanged);
connect(_yawRadiansFact, &Fact::valueChanged, this, &MissionItem::_factValueChanged);
connect(_loiterOrbitRadiusFact, &Fact::valueChanged, this, &MissionItem::_factValueChanged);
connect(_param1Fact, &Fact::valueChanged, this, &MissionItem::_factValueChanged);
connect(_param2Fact, &Fact::valueChanged, this, &MissionItem::_factValueChanged);
connect(_altitudeRelativeToHomeFact, &Fact::valueChanged, this, &MissionItem::_factValueChanged);
// Connect valueChanged signals so we can output coordinateChanged signal
connect(_latitudeFact, &Fact::valueChanged, this, &MissionItem::_coordinateFactChanged);
connect(_longitudeFact, &Fact::valueChanged, this, &MissionItem::_coordinateFactChanged);
connect(_altitudeFact, &Fact::valueChanged, this, &MissionItem::_coordinateFactChanged);
*this = other;
}
_connectSignals();
MissionItem::~MissionItem()
{
*this = other;
}
const MissionItem& MissionItem::operator=(const MissionItem& other)
@ -221,15 +198,15 @@ const MissionItem& MissionItem::operator=(const MissionItem& other) @@ -221,15 +198,15 @@ const MissionItem& MissionItem::operator=(const MissionItem& other)
_altitudeRelativeToHomeFact = other._altitudeRelativeToHomeFact;
_dirty = other._dirty;
_homePositionSpecialCase = other._homePositionSpecialCase;
*_latitudeFact = *other._latitudeFact;
*_longitudeFact = *other._longitudeFact;
*_altitudeFact = *other._altitudeFact;
*_yawRadiansFact = *other._yawRadiansFact;
*_headingDegreesFact = *other._headingDegreesFact;
*_loiterOrbitRadiusFact = *other._loiterOrbitRadiusFact;
*_param1Fact = *other._param1Fact;
*_param2Fact = *other._param2Fact;
*_pitchMetaData = *other._pitchMetaData;
*_acceptanceRadiusMetaData = *other._acceptanceRadiusMetaData;
*_holdTimeMetaData = *other._holdTimeMetaData;
@ -238,10 +215,34 @@ const MissionItem& MissionItem::operator=(const MissionItem& other) @@ -238,10 +215,34 @@ const MissionItem& MissionItem::operator=(const MissionItem& other)
*_delaySecondsMetaData = *other._delaySecondsMetaData;
*_jumpSequenceMetaData = *other._jumpSequenceMetaData;
*_jumpRepeatMetaData = *other._jumpRepeatMetaData;
return *this;
}
void MissionItem::_connectSignals(void)
{
// Connect to valueChanged to track dirty state
connect(_latitudeFact, &Fact::valueChanged, this, &MissionItem::_factValueChanged);
connect(_longitudeFact, &Fact::valueChanged, this, &MissionItem::_factValueChanged);
connect(_altitudeFact, &Fact::valueChanged, this, &MissionItem::_factValueChanged);
connect(_headingDegreesFact, &Fact::valueChanged, this, &MissionItem::_factValueChanged);
connect(_loiterOrbitRadiusFact, &Fact::valueChanged, this, &MissionItem::_factValueChanged);
connect(_param1Fact, &Fact::valueChanged, this, &MissionItem::_factValueChanged);
connect(_param2Fact, &Fact::valueChanged, this, &MissionItem::_factValueChanged);
connect(_altitudeRelativeToHomeFact, &Fact::valueChanged, this, &MissionItem::_factValueChanged);
// Connect valueChanged signals so we can output coordinateChanged signal
connect(_latitudeFact, &Fact::valueChanged, this, &MissionItem::_coordinateFactChanged);
connect(_longitudeFact, &Fact::valueChanged, this, &MissionItem::_coordinateFactChanged);
connect(_altitudeFact, &Fact::valueChanged, this, &MissionItem::_coordinateFactChanged);
connect(_headingDegreesFact, &Fact::valueChanged, this, &MissionItem::_headingDegreesFactChanged);
}
MissionItem::~MissionItem()
{
}
bool MissionItem::isNavigationType()
{
return (_command < MavlinkQmlSingleton::MAV_CMD_NAV_LAST);
@ -254,7 +255,7 @@ void MissionItem::save(QTextStream &saveStream) @@ -254,7 +255,7 @@ void MissionItem::save(QTextStream &saveStream)
position = position.arg(y(), 0, 'g', 18);
position = position.arg(z(), 0, 'g', 18);
QString parameters("%1\t%2\t%3\t%4");
parameters = parameters.arg(param1(), 0, 'g', 18).arg(param2(), 0, 'g', 18).arg(loiterOrbitRadius(), 0, 'g', 18).arg(yawRadians(), 0, 'g', 18);
parameters = parameters.arg(param1(), 0, 'g', 18).arg(param2(), 0, 'g', 18).arg(loiterOrbitRadius(), 0, 'g', 18).arg(_yawRadians(), 0, 'g', 18);
// FORMAT: <INDEX> <CURRENT WP> <COORD FRAME> <COMMAND> <PARAM1> <PARAM2> <PARAM3> <PARAM4> <PARAM5/X/LONGITUDE> <PARAM6/Y/LATITUDE> <PARAM7/Z/ALTITUDE> <AUTOCONTINUE> <DESCRIPTION>
// as documented here: http://qgroundcontrol.org/waypoint_protocol
saveStream << this->sequenceNumber() << "\t" << this->isCurrentItem() << "\t" << this->frame() << "\t" << this->command() << "\t" << parameters << "\t" << position << "\t" << this->autoContinue() << "\r\n"; //"\t" << this->getDescription() << "\r\n";
@ -271,7 +272,7 @@ bool MissionItem::load(QTextStream &loadStream) @@ -271,7 +272,7 @@ bool MissionItem::load(QTextStream &loadStream)
setParam1(wpParams[4].toDouble());
setParam2(wpParams[5].toDouble());
setLoiterOrbitRadius(wpParams[6].toDouble());
setYawRadians(wpParams[7].toDouble());
_setYawRadians(wpParams[7].toDouble());
setLatitude(wpParams[8].toDouble());
setLongitude(wpParams[9].toDouble());
setAltitude(wpParams[10].toDouble());
@ -351,11 +352,27 @@ void MissionItem::setAction(int /*MAV_CMD*/ action) @@ -351,11 +352,27 @@ void MissionItem::setAction(int /*MAV_CMD*/ action)
// Fix defaults according to WP type
if (_command == MavlinkQmlSingleton::MAV_CMD_NAV_TAKEOFF) {
// We default to 15 degrees minimum takeoff pitch
setParam1(15.0);
switch (_command) {
case MavlinkQmlSingleton::MAV_CMD_NAV_TAKEOFF:
setParam1(defaultPitch);
break;
case MavlinkQmlSingleton::MAV_CMD_NAV_WAYPOINT:
setAcceptanceRadius(defaultAcceptanceRadius);
break;
case MavlinkQmlSingleton::MAV_CMD_NAV_LOITER_UNLIM:
case MavlinkQmlSingleton::MAV_CMD_NAV_LOITER_TIME:
setLoiterOrbitRadius(defaultLoiterOrbitRadius);
break;
case MavlinkQmlSingleton::MAV_CMD_NAV_LOITER_TURNS:
setLoiterOrbitRadius(defaultLoiterOrbitRadius);
setParam1(defaultLoiterTurns);
break;
default:
break;
}
setHeadingDegrees(defaultHeading);
setAltitude(defaultAltitude);
if (specifiesCoordinate()) {
if (_frame != MAV_FRAME_GLOBAL && _frame != MAV_FRAME_GLOBAL_RELATIVE_ALT) {
setFrame(MAV_FRAME_GLOBAL_RELATIVE_ALT);
@ -438,7 +455,7 @@ void MissionItem::setParam3(double param3) @@ -438,7 +455,7 @@ void MissionItem::setParam3(double param3)
void MissionItem::setParam4(double param4)
{
setYawRadians(param4);
_setYawRadians(param4);
}
void MissionItem::setParam5(double param5)
@ -526,6 +543,46 @@ QString MissionItem::commandName(void) @@ -526,6 +543,46 @@ QString MissionItem::commandName(void)
return type;
}
QString MissionItem::commandDescription(void)
{
QString description;
switch (_command) {
case MAV_CMD_NAV_WAYPOINT:
description = "Travel to a position in 3D space.";
break;
case MAV_CMD_NAV_LOITER_UNLIM:
description = "Travel to a position and Loiter around the specified radius indefinitely.";
break;
case MAV_CMD_NAV_LOITER_TURNS:
description = "Travel to a position and Loiter around the specified radius for a number of turns.";
break;
case MAV_CMD_NAV_LOITER_TIME:
description = "Travel to a position and Loiter around the specified radius for an amount of time.";
break;
case MAV_CMD_NAV_RETURN_TO_LAUNCH:
description = "Send the vehicle back to the home position set when armed.";
break;
case MAV_CMD_NAV_LAND:
description = "Land vehicle at the current location.";
break;
case MAV_CMD_NAV_TAKEOFF:
description = "Lift off from the ground and travel to the specified position.";
break;
case MAV_CMD_CONDITION_DELAY:
description = "Delay";
break;
case MAV_CMD_DO_JUMP:
description = "Jump To Command";
break;
default:
description = QString("Unknown (%1)").arg(_command);
break;
}
return description;
}
QStringList MissionItem::valueLabels(void)
{
QStringList labels;
@ -590,24 +647,24 @@ QStringList MissionItem::valueStrings(void) @@ -590,24 +647,24 @@ QStringList MissionItem::valueStrings(void)
switch (_command) {
case MAV_CMD_NAV_WAYPOINT:
list << _oneDecimalString(_altitudeFact->value().toDouble()) << _oneDecimalString(yawDegrees()) << _oneDecimalString(param2()) << _oneDecimalString(param1());
list << _oneDecimalString(_altitudeFact->value().toDouble()) << _oneDecimalString(headingDegrees()) << _oneDecimalString(param2()) << _oneDecimalString(param1());
break;
case MAV_CMD_NAV_LOITER_UNLIM:
list << _oneDecimalString(yawRadians() * (180.0 / M_PI)) << _oneDecimalString(loiterOrbitRadius());
list << _oneDecimalString(headingDegrees()) << _oneDecimalString(loiterOrbitRadius());
break;
case MAV_CMD_NAV_LOITER_TURNS:
list << _oneDecimalString(yawRadians() * (180.0 / M_PI)) << _oneDecimalString(loiterOrbitRadius()) << _oneDecimalString(param1());
list << _oneDecimalString(headingDegrees()) << _oneDecimalString(loiterOrbitRadius()) << _oneDecimalString(param1());
break;
case MAV_CMD_NAV_LOITER_TIME:
list << _oneDecimalString(yawRadians() * (180.0 / M_PI)) << _oneDecimalString(loiterOrbitRadius()) << _oneDecimalString(param1());
list << _oneDecimalString(headingDegrees()) << _oneDecimalString(loiterOrbitRadius()) << _oneDecimalString(param1());
break;
case MAV_CMD_NAV_RETURN_TO_LAUNCH:
break;
case MAV_CMD_NAV_LAND:
list << _oneDecimalString(_altitudeFact->value().toDouble()) << _oneDecimalString(yawRadians() * (180.0 / M_PI));
list << _oneDecimalString(_altitudeFact->value().toDouble()) << _oneDecimalString(headingDegrees());
break;
case MAV_CMD_NAV_TAKEOFF:
list << _oneDecimalString(_altitudeFact->value().toDouble()) << _oneDecimalString(yawRadians() * (180.0 / M_PI)) << _oneDecimalString(param1());
list << _oneDecimalString(_altitudeFact->value().toDouble()) << _oneDecimalString(headingDegrees()) << _oneDecimalString(param1());
break;
case MAV_CMD_CONDITION_DELAY:
list << _oneDecimalString(param1());
@ -659,59 +716,38 @@ QmlObjectListModel* MissionItem::textFieldFacts(void) @@ -659,59 +716,38 @@ QmlObjectListModel* MissionItem::textFieldFacts(void)
switch ((MAV_CMD)_command) {
case MAV_CMD_NAV_WAYPOINT:
_param2Fact->_setName("Radius:");
_param2Fact->setMetaData(_acceptanceRadiusMetaData);
_param1Fact->_setName("Hold:");
_param1Fact->setMetaData(_holdTimeMetaData);
model->append(_latitudeFact);
model->append(_longitudeFact);
model->append(_altitudeFact);
if (!_homePositionSpecialCase) {
model->append(_yawRadiansFact);
model->append(_param2Fact);
model->append(_param1Fact);
}
break;
case MAV_CMD_NAV_LOITER_UNLIM:
model->append(_latitudeFact);
model->append(_longitudeFact);
model->append(_altitudeFact);
model->append(_yawRadiansFact);
model->append(_loiterOrbitRadiusFact);
break;
case MAV_CMD_NAV_LOITER_TURNS:
_param1Fact->_setName("Turns:");
_param1Fact->setMetaData(_loiterTurnsMetaData);
model->append(_latitudeFact);
model->append(_longitudeFact);
model->append(_altitudeFact);
model->append(_yawRadiansFact);
model->append(_loiterOrbitRadiusFact);
model->append(_param1Fact);
break;
case MAV_CMD_NAV_LOITER_TIME:
_param1Fact->_setName("Seconds:");
_param1Fact->setMetaData(_loiterSecondsMetaData);
model->append(_latitudeFact);
model->append(_longitudeFact);
model->append(_altitudeFact);
model->append(_yawRadiansFact);
model->append(_loiterOrbitRadiusFact);
model->append(_param1Fact);
break;
case MAV_CMD_NAV_LAND:
model->append(_latitudeFact);
model->append(_longitudeFact);
model->append(_altitudeFact);
model->append(_yawRadiansFact);
break;
case MAV_CMD_NAV_TAKEOFF:
_param1Fact->_setName("Pitch:");
_param1Fact->setMetaData(_pitchMetaData);
model->append(_latitudeFact);
model->append(_longitudeFact);
model->append(_altitudeFact);
model->append(_yawRadiansFact);
model->append(_param1Fact);
break;
case MAV_CMD_CONDITION_DELAY:
@ -730,6 +766,11 @@ QmlObjectListModel* MissionItem::textFieldFacts(void) @@ -730,6 +766,11 @@ QmlObjectListModel* MissionItem::textFieldFacts(void)
default:
break;
}
if (specifiesHeading()) {
model->append(_headingDegreesFact);
}
return model;
}
@ -768,30 +809,30 @@ QmlObjectListModel* MissionItem::checkboxFacts(void) @@ -768,30 +809,30 @@ QmlObjectListModel* MissionItem::checkboxFacts(void)
return model;
}
double MissionItem::yawRadians(void) const
double MissionItem::headingDegrees(void) const
{
return _yawRadiansFact->value().toDouble();
return _headingDegreesFact->value().toDouble();
}
void MissionItem::setYawRadians(double yaw)
void MissionItem::setHeadingDegrees(double headingDegrees)
{
if (yawRadians() != yaw)
{
_yawRadiansFact->setValue(yaw);
if (_headingDegreesFact->value().toDouble() != headingDegrees) {
_headingDegreesFact->setValue(headingDegrees);
emit changed(this);
emit valueStringsChanged(valueStrings());
emit headingDegreesChanged(headingDegrees);
}
}
double MissionItem::yawDegrees(void) const
double MissionItem::_yawRadians(void) const
{
return yawRadians() * (180.0 / M_PI);
return _headingDegreesFact->value().toDouble() * (M_PI / 180.0);
}
void MissionItem::setYawDegrees(double yaw)
void MissionItem::_setYawRadians(double yawRadians)
{
setYawRadians(yaw * (M_PI / 180.0));
setHeadingDegrees(yawRadians * (180 / M_PI));
}
QGeoCoordinate MissionItem::coordinate(void) const
@ -854,3 +895,19 @@ void MissionItem::_coordinateFactChanged(QVariant value) @@ -854,3 +895,19 @@ void MissionItem::_coordinateFactChanged(QVariant value)
Q_UNUSED(value);
emit coordinateChanged(coordinate());
}
bool MissionItem::specifiesHeading(void) const
{
switch ((MAV_CMD)_command) {
case MAV_CMD_NAV_LAND:
case MAV_CMD_NAV_TAKEOFF:
return true;
default:
return false;
}
}
void MissionItem::_headingDegreesFactChanged(QVariant value)
{
emit headingDegreesChanged(value.toDouble());
}

42
src/MissionItem.h

@ -50,9 +50,9 @@ public: @@ -50,9 +50,9 @@ public:
QGeoCoordinate coordiante = QGeoCoordinate(),
int action = MAV_CMD_NAV_WAYPOINT,
double param1 = 0.0,
double param2 = 0.0,
double param3 = 0.0,
double param4 = 0.0,
double param2 = defaultAcceptanceRadius,
double param3 = defaultLoiterOrbitRadius,
double param4 = defaultHeading,
bool autocontinue = true,
bool isCurrentItem = false,
int frame = MAV_FRAME_GLOBAL_RELATIVE_ALT);
@ -67,10 +67,16 @@ public: @@ -67,10 +67,16 @@ public:
Q_PROPERTY(int sequenceNumber READ sequenceNumber WRITE setSequenceNumber NOTIFY sequenceNumberChanged)
Q_PROPERTY(bool isCurrentItem READ isCurrentItem WRITE setIsCurrentItem NOTIFY isCurrentItemChanged)
Q_PROPERTY(bool specifiesCoordinate READ specifiesCoordinate NOTIFY commandChanged)
Q_PROPERTY(QGeoCoordinate coordinate READ coordinate WRITE setCoordinate NOTIFY coordinateChanged)
Q_PROPERTY(bool specifiesHeading READ specifiesHeading NOTIFY commandChanged)
Q_PROPERTY(double heading READ headingDegrees WRITE setHeadingDegrees NOTIFY headingDegreesChanged)
Q_PROPERTY(QStringList commandNames READ commandNames CONSTANT)
Q_PROPERTY(QString commandName READ commandName NOTIFY commandChanged)
Q_PROPERTY(QString commandDescription READ commandDescription NOTIFY commandChanged)
Q_PROPERTY(QStringList valueLabels READ valueLabels NOTIFY commandChanged)
Q_PROPERTY(QStringList valueStrings READ valueStrings NOTIFY valueStringsChanged)
Q_PROPERTY(int commandByIndex READ commandByIndex WRITE setCommandByIndex NOTIFY commandChanged)
@ -88,12 +94,16 @@ public: @@ -88,12 +94,16 @@ public:
void setIsCurrentItem(bool isCurrentItem);
bool specifiesCoordinate(void) const;
QGeoCoordinate coordinate(void) const;
void setCoordinate(const QGeoCoordinate& coordinate);
bool specifiesHeading(void) const;
double headingDegrees(void) const;
void setHeadingDegrees(double headingDegrees);
QStringList commandNames(void);
QString commandName(void);
QString commandDescription(void);
int commandByIndex(void);
void setCommandByIndex(int index);
@ -107,9 +117,6 @@ public: @@ -107,9 +117,6 @@ public:
QmlObjectListModel* textFieldFacts(void);
QmlObjectListModel* checkboxFacts(void);
double yawDegrees(void) const;
void setYawDegrees(double yaw);
bool dirty(void) { return _dirty; }
void setDirty(bool dirty);
@ -136,9 +143,6 @@ public: @@ -136,9 +143,6 @@ public:
void setY(double y);
void setZ(double z);
double yawRadians(void) const;
void setYawRadians(double yaw);
bool autoContinue() const {
return _autocontinue;
}
@ -161,7 +165,7 @@ public: @@ -161,7 +165,7 @@ public:
return loiterOrbitRadius();
}
double param4() const {
return yawRadians();
return _yawRadians();
}
double param5() const {
return latitude();
@ -189,11 +193,19 @@ public: @@ -189,11 +193,19 @@ public:
bool load(QTextStream &loadStream);
void setHomePositionSpecialCase(bool homePositionSpecialCase) { _homePositionSpecialCase = homePositionSpecialCase; }
static const double defaultPitch;
static const double defaultHeading;
static const double defaultAltitude;
static const double defaultAcceptanceRadius;
static const double defaultLoiterOrbitRadius;
static const double defaultLoiterTurns;
signals:
void sequenceNumberChanged(int sequenceNumber);
void isCurrentItemChanged(bool isCurrentItem);
void coordinateChanged(const QGeoCoordinate& coordinate);
void headingDegreesChanged(double heading);
void dirtyChanged(bool dirty);
/** @brief Announces a change to the waypoint data */
@ -234,9 +246,13 @@ public: @@ -234,9 +246,13 @@ public:
private slots:
void _factValueChanged(QVariant value);
void _coordinateFactChanged(QVariant value);
void _headingDegreesFactChanged(QVariant value);
private:
QString _oneDecimalString(double value);
void _connectSignals(void);
double _yawRadians(void) const;
void _setYawRadians(double yawRadians);
private:
typedef struct {
@ -254,7 +270,7 @@ private: @@ -254,7 +270,7 @@ private:
Fact* _latitudeFact;
Fact* _longitudeFact;
Fact* _altitudeFact;
Fact* _yawRadiansFact;
Fact* _headingDegreesFact;
Fact* _loiterOrbitRadiusFact;
Fact* _param1Fact;
Fact* _param2Fact;

2
src/QmlControls/DropButton.qml

@ -224,7 +224,7 @@ Item { @@ -224,7 +224,7 @@ Item {
context.lineTo(dropItemHolderRect.x, dropItemHolderRect.y)
context.closePath()
context.fillStyle = qgcPal.button
context.fillStyle = qgcPal.windowShade
context.fill()
}
} // Canvas - arrowCanvas

75
src/QmlControls/MissionItemEditor.qml

@ -19,34 +19,26 @@ Rectangle { @@ -19,34 +19,26 @@ Rectangle {
signal clicked
signal remove
height: missionItem.isCurrentItem ?
(missionItem.textFieldFacts.count * (measureTextField.height + _margin)) +
(missionItem.checkboxFacts.count * (measureCheckbox.height + _margin)) +
commandPicker.height + (deleteButton.visible ? deleteButton.height : 0) + (_margin * 9) :
commandPicker.height + (_margin * 2)
height: innerItem.height + (_margin * 2)
color: missionItem.isCurrentItem ? qgcPal.buttonHighlight : qgcPal.windowShade
radius: _radius
readonly property real _editFieldWidth: ScreenTools.defaultFontPixelWidth * 16
readonly property real _margin: ScreenTools.defaultFontPixelWidth / 3
readonly property real _margin: ScreenTools.defaultFontPixelWidth / 2
readonly property real _radius: ScreenTools.defaultFontPixelWidth / 2
QGCPalette {
id: qgcPal
colorGroupEnabled: enabled
}
QGCTextField {
id: measureTextField
visible: false
}
QGCCheckBox {
id: measureCheckbox
visible: false
}
Item {
id: innerItem
anchors.margins: _margin
anchors.fill: parent
anchors.top: parent.top
anchors.left: parent.left
anchors.right: parent.right
height: valuesRect.visible ? valuesRect.y + valuesRect.height : valuesRect.y
MissionItemIndexLabel {
id: label
@ -69,7 +61,7 @@ Rectangle { @@ -69,7 +61,7 @@ Rectangle {
anchors.right: parent.right
currentIndex: missionItem.commandByIndex
model: missionItem.commandNames
visible: missionItem.sequenceNumber != 0 // Item 0 is home position, can't change item type
visible: missionItem.sequenceNumber != 0 && missionItem.isCurrentItem
onActivated: missionItem.commandByIndex = index
}
@ -77,30 +69,36 @@ Rectangle { @@ -77,30 +69,36 @@ Rectangle {
Rectangle {
anchors.fill: commandPicker
color: qgcPal.button
visible: missionItem.sequenceNumber == 0 // Item 0 is home position, can't change item type
visible: !commandPicker.visible
QGCLabel {
id: homeLabel
anchors.leftMargin: ScreenTools.defaultFontPixelWidth
anchors.fill: parent
verticalAlignment: Text.AlignVCenter
text: "Home"
text: missionItem.sequenceNumber == 0 ? "Home" : missionItem.commandName
color: qgcPal.buttonText
}
}
Rectangle {
id: valuesRect
anchors.topMargin: _margin
anchors.top: commandPicker.bottom
anchors.bottom: parent.bottom
anchors.left: parent.left
anchors.right: parent.right
height: valuesItem.height
color: qgcPal.windowShadeDark
visible: missionItem.isCurrentItem
radius: _radius
Item {
id: valuesItem
anchors.margins: _margin
anchors.fill: parent
anchors.left: parent.left
anchors.right: parent.right
anchors.top: parent.top
height: valuesColumn.height + _margin
Column {
id: valuesColumn
@ -109,6 +107,12 @@ Rectangle { @@ -109,6 +107,12 @@ Rectangle {
anchors.top: parent.top
spacing: _margin
QGCLabel {
width: parent.width
wrapMode: Text.WordWrap
text: missionItem.commandDescription
}
Repeater {
model: missionItem.textFieldFacts
@ -140,11 +144,6 @@ Rectangle { @@ -140,11 +144,6 @@ Rectangle {
}
}
Item {
width: 10
height: missionItem.textFieldFacts.count ? _margin : 0
}
Repeater {
model: missionItem.checkboxFacts
@ -154,28 +153,6 @@ Rectangle { @@ -154,28 +153,6 @@ Rectangle {
fact: object
}
}
Item {
width: 10
height: missionItem.checkboxFacts.count ? _margin : 0
}
Row {
width: parent.width
spacing: _margin
readonly property real buttonWidth: (width - (_margin * 2)) / 3
QGCButton {
id: deleteButton
width: parent.buttonWidth
text: "Delete"
visible: !readOnly
onClicked: _root.remove()
}
}
} // Column
} // Item
} // Rectangle

3
src/QmlControls/MissionItemIndexLabel.qml

@ -13,7 +13,7 @@ Rectangle { @@ -13,7 +13,7 @@ Rectangle {
QGCPalette { id: qgcPal }
width: ScreenTools.defaultFontPixelHeight * 1.5
width: ScreenTools.mediumFontPixelSize * 1.5
height: width
radius: width / 2
border.width: 2
@ -32,5 +32,6 @@ Rectangle { @@ -32,5 +32,6 @@ Rectangle {
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
color: "white"
font.pixelSize: ScreenTools.mediumFontPixelSize
}
}

Loading…
Cancel
Save