地面站终端 App
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

529 lines
24 KiB

/*=====================================================================
QGroundControl Open Source Ground Control Station
(c) 2009 - 2015 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
This file is part of the QGROUNDCONTROL project
QGROUNDCONTROL is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
QGROUNDCONTROL is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with QGROUNDCONTROL. If not, see <http://www.gnu.org/licenses/>.
======================================================================*/
import QtQuick 2.2
import QtQuick.Controls 1.2
import QtQuick.Controls.Styles 1.2
import QtQuick.Dialogs 1.2
import QGroundControl.FactSystem 1.0
import QGroundControl.FactControls 1.0
import QGroundControl.Palette 1.0
import QGroundControl.Controls 1.0
import QGroundControl.ScreenTools 1.0
import QGroundControl.Controllers 1.0
QGCView {
id: qgcView
viewPanel: panel
// Help text which is shown both in the status text area prior to pressing a cal button and in the
// pre-calibration dialog.
readonly property string orientationHelp: "If the orientation is in the direction of flight, select None."
readonly property string boardRotationText: "If the autopilot is mounted in flight direction, leave the default value (None)"
readonly property string compassRotationText: "If the compass or GPS module is mounted in flight direction, leave the default value (None)"
readonly property string compassHelp: "For Compass calibration you will need to rotate your vehicle through a number of positions. Most users prefer to do this wirelessly with the telemetry link."
readonly property string gyroHelp: "For Gyroscope calibration you will need to place your vehicle on a surface and leave it still."
readonly property string accelHelp: "For Accelerometer calibration you will need to place your vehicle on all six sides on a perfectly level surface and hold it still in each orientation for a few seconds."
readonly property string levelHelp: "To level the horizon you need to place the vehicle in its level flight position and press OK."
readonly property string airspeedHelp: "For Airspeed calibration you will need to keep your airspeed sensor out of any wind and then blow across the sensor."
readonly property string statusTextAreaDefaultText: "Start the individual calibration steps by clicking one of the buttons above."
// Used to pass what type of calibration is being performed to the preCalibrationDialog
property string preCalibrationDialogType
// Used to pass help text to the preCalibrationDialog dialog
property string preCalibrationDialogHelp
property string _postCalibrationDialogText
property var _postCalibrationDialogParams
readonly property string _badCompassCalText: "The calibration for Compass %1 appears to be poor. " +
"Check the compass position within your vehicle and re-do the calibration."
readonly property int sideBarH1PointSize: ScreenTools.mediumFontPointSize
readonly property int mainTextH1PointSize: ScreenTools.mediumFontPointSize // Seems to be unused
readonly property int rotationColumnWidth: 250
property Fact compass1Id: controller.getParameterFact(-1, "COMPASS_DEV_ID")
property Fact compass2Id: controller.getParameterFact(-1, "COMPASS_DEV_ID2")
property Fact compass3Id: controller.getParameterFact(-1, "COMPASS_DEV_ID3")
property Fact compass1ExternalFact: controller.getParameterFact(-1, "COMPASS_EXTERNAL")
property Fact compass1Rot: controller.getParameterFact(-1, "COMPASS_ORIENT")
property Fact boardRot: controller.getParameterFact(-1, "AHRS_ORIENTATION")
property bool accelCalNeeded: controller.accelSetupNeeded
property bool compassCalNeeded: controller.compassSetupNeeded
// The following parameters are not available in olders firmwares
property bool compass2ExternalParamAvailable: controller.parameterExists(-1, "COMPASS_EXTERN2")
property bool compass3ExternalParamAvailable: controller.parameterExists(-1, "COMPASS_EXTERN3")
property bool compass2RotParamAvailable: controller.parameterExists(-1, "COMPASS_ORIENT2")
property bool compass3RotParamAvailable: controller.parameterExists(-1, "COMPASS_ORIENT3")
property bool compass1UseParamAvailable: controller.parameterExists(-1, "COMPASS_USE")
property bool compass2UseParamAvailable: controller.parameterExists(-1, "COMPASS_USE2")
property bool compass3UseParamAvailable: controller.parameterExists(-1, "COMPASS_USE3")
property Fact noFact: Fact { }
property Fact compass2ExternalFact: compass2ExternalParamAvailable ? controller.getParameterFact(-1, "COMPASS_EXTERN2") : noFact
property Fact compass3ExternalFact: compass3ExternalParamAvailable ? controller.getParameterFact(-1, "COMPASS_EXTERN3") : noFact
property Fact compass2Rot: compass2RotParamAvailable ? controller.getParameterFact(-1, "COMPASS_ORIENT2") : noFact
property Fact compass3Rot: compass3RotParamAvailable ? controller.getParameterFact(-1, "COMPASS_ORIENT3") : noFact
property Fact compass1UseFact: compass1UseParamAvailable ? controller.getParameterFact(-1, "COMPASS_USE") : noFact
property Fact compass2UseFact: compass2UseParamAvailable ? controller.getParameterFact(-1, "COMPASS_USE2") : noFact
property Fact compass3UseFact: compass3UseParamAvailable ? controller.getParameterFact(-1, "COMPASS_USE3") : noFact
// We track these values by binding through a separate property so we can handle missing params
property bool compass1External: compass1ExternalFact.value
property bool compass2External: compass2ExternalParamAvailable ? compass2ExternalFact.value : false // false: Simulate internal so we don't show rotation combos
property bool compass3External: compass3ExternalParamAvailable ? compass3ExternalFact.value : false // false: Simulate internal so we don't show rotation combos
property bool compass1Use: compass1UseParamAvailable ? compass1UseFact.value : true
property bool compass2Use: compass2UseParamAvailable ? compass2UseFact.value : true
property bool compass3Use: compass3UseParamAvailable ? compass3UseFact.value : true
// Id > = signals compass available, rot < 0 signals internal compass
property bool showCompass1Rot: compass1Id.value > 0 && compass1External && compass1Use
property bool showCompass2Rot: compass2Id.value > 0 && compass2External && compass2Use
property bool showCompass3Rot: compass3Id.value > 0 && compass3External && compass3Use
function validCompassOffsets(compassParamPrefix) {
var ofsX = controller.getParameterFact(-1, compassParamPrefix + "X")
var ofsY = controller.getParameterFact(-1, compassParamPrefix + "Y")
var ofsZ = controller.getParameterFact(-1, compassParamPrefix + "Z")
return Math.sqrt(ofsX.value^2 + ofsY.value^2 + ofsZ.value^2) < 600
}
APMSensorsComponentController {
id: controller
factPanel: panel
statusLog: statusTextArea
progressBar: progressBar
compassButton: compassButton
accelButton: accelButton
nextButton: nextButton
cancelButton: cancelButton
orientationCalAreaHelpText: orientationCalAreaHelpText
onResetStatusTextArea: statusLog.text = statusTextAreaDefaultText
onWaitingForCancelChanged: {
if (controller.waitingForCancel) {
showMessage(qsTr("Calibration Cancel"), qsTr("Waiting for Vehicle to response to Cancel. This may take a few seconds."), 0)
} else {
hideDialog()
}
}
onCalibrationComplete: {
if (preCalibrationDialogType == "accel") {
_postCalibrationDialogText = qsTr("Accelerometer calibration complete.")
_postCalibrationDialogParams = [ "INS_ACCSCAL_X", "INS_ACCSCAL_Y", "INS_ACCSCAL_Z",
"INS_ACC2SCAL_X", "INS_ACC2SCAL_Y", "INS_ACC2SCAL_Z",
"INS_ACC3SCAL_X", "INS_ACC3SCAL_Y", "INS_ACC3SCAL_Z",
"INS_GYROFFS_X", "INS_GYROFFS_Y", "INS_GYROFFS_Z",
"INS_GYR2OFFS_X", "INS_GYR2OFFS_Y", "INS_GYR2OFFS_Z",
"INS_GYR3OFFS_X", "INS_GYR3OFFS_Y", "INS_GYR3OFFS_Z" ]
} else if (preCalibrationDialogType == "compass") {
_postCalibrationDialogText = qsTr("Compass calibration complete. ")
_postCalibrationDialogParams = [];
if (compass1Id.value > 0) {
if (!validCompassOffsets("COMPASS_OFS_")) {
_postCalibrationDialogText += _badCompassCalText.replace("%1", 1)
}
_postCalibrationDialogParams.push("COMPASS_OFS_X")
_postCalibrationDialogParams.push("COMPASS_OFS_Y")
_postCalibrationDialogParams.push("COMPASS_OFS_Z")
}
if (compass2Id.value > 0) {
if (!validCompassOffsets("COMPASS_OFS_")) {
_postCalibrationDialogText += _badCompassCalText.replace("%1", 2)
}
_postCalibrationDialogParams.push("COMPASS_OFS2_X")
_postCalibrationDialogParams.push("COMPASS_OFS2_Y")
_postCalibrationDialogParams.push("COMPASS_OFS2_Z")
}
if (compass3Id.value > 0) {
if (!validCompassOffsets("COMPASS_OFS_")) {
_postCalibrationDialogText += _badCompassCalText.replace("%1", 3)
}
_postCalibrationDialogParams.push("COMPASS_OFS3_X")
_postCalibrationDialogParams.push("COMPASS_OFS3_Y")
_postCalibrationDialogParams.push("COMPASS_OFS3_Z")
}
}
showDialog(postCalibrationDialogComponent, qsTr("Calibration complete"), qgcView.showDialogDefaultWidth, StandardButton.Ok)
}
}
QGCPalette { id: qgcPal; colorGroupEnabled: panel.enabled }
Component {
id: preCalibrationDialogComponent
QGCViewDialog {
id: preCalibrationDialog
function accept() {
if (preCalibrationDialogType == "accel") {
controller.calibrateAccel()
} else if (preCalibrationDialogType == "compass") {
controller.calibrateCompass()
}
preCalibrationDialog.hideDialog()
}
QGCLabel {
id: label
anchors.left: parent.left
anchors.right: parent.right
wrapMode: Text.WordWrap
text: qsTr("Before calibrating make sure orientation settings are correct.")
}
Loader {
id: rotationsLoader
anchors.topMargin: ScreenTools.defaultFontPixelHeight
anchors.top: label.bottom
anchors.left: parent.left
anchors.right: parent.right
sourceComponent: rotationCombosComponent
property bool showCompassRotations: preCalibrationDialogType == "accel" ? false : true
}
}
}
Component {
id: postCalibrationDialogComponent
QGCViewDialog {
QGCLabel {
id: textLabel
anchors.left: parent.left
anchors.right: parent.right
wrapMode: Text.WordWrap
text: _postCalibrationDialogText
}
QGCCheckBox {
id: showValues
anchors.topMargin: ScreenTools.defaultFontPixelHeight
anchors.top: textLabel.bottom
text: qsTr("Show values")
}
QGCFlickable {
anchors.topMargin: ScreenTools.defaultFontPixelHeight
anchors.top: showValues.bottom
anchors.bottom: parent.bottom
contentHeight: valueColumn.height
flickableDirection: Flickable.VerticalFlick
visible: showValues.checked
Column {
id: valueColumn
Repeater {
model: _postCalibrationDialogParams
QGCLabel {
text: fact.name +": " + fact.valueString
property Fact fact: controller.getParameterFact(-1, modelData)
}
}
}
}
}
}
Component {
id: rotationCombosComponent
Column {
QGCLabel {
font.pointSize: sideBarH1PointSize
text: qsTr("Set Orientations")
}
Item {
width: 1
height: ScreenTools.defaultFontPixelHeight
}
QGCLabel {
width: parent.width
wrapMode: Text.WordWrap
text: orientationHelp
}
Item {
width: 1
height: ScreenTools.defaultFontPixelHeight
}
// Board rotation
QGCLabel {
text: qsTr("Autopilot Orientation")
}
FactComboBox {
id: boardRotationCombo
width: parent.width
fact: boardRot
indexModel: false
}
Item {
width: 1
height: ScreenTools.defaultFontPixelHeight
}
// Compass 1 rotation
QGCLabel {
text: qsTr("Compass 1 Orientation")
visible: showCompassRotations && showCompass1Rot
}
FactComboBox {
width: parent.width
fact: compass1Rot
indexModel: false
visible: showCompassRotations && showCompass1Rot
}
Item {
width: 1
height: ScreenTools.defaultFontPixelHeight
}
// Compass 2 rotation
QGCLabel {
text: qsTr("Compass 2 Orientation")
visible: showCompassRotations && showCompass2Rot
}
FactComboBox {
width: parent.width
fact: compass2Rot
indexModel: false
visible: showCompassRotations && showCompass2Rot
}
Item {
width: 1
height: ScreenTools.defaultFontPixelHeight
}
// Compass 3 rotation
QGCLabel {
text: qsTr("Compass 3 Orientation")
visible: showCompassRotations && showCompass3Rot
}
FactComboBox {
width: parent.width
fact: compass3Rot
indexModel: false
visible: showCompassRotations && showCompass3Rot
}
} // Column
} // Component - Rotation combos
QGCViewPanel {
id: panel
anchors.fill: parent
Row {
id: buttonsRow
spacing: ScreenTools.defaultFontPixelWidth
readonly property int buttonWidth: ScreenTools.defaultFontPixelWidth * 15
QGCLabel { text: qsTr("Calibrate:"); anchors.baseline: compassButton.baseline }
IndicatorButton {
id: accelButton
width: parent.buttonWidth
text: qsTr("Accelerometer")
indicatorGreen: !accelCalNeeded
onClicked: {
preCalibrationDialogType = "accel"
preCalibrationDialogHelp = accelHelp
showDialog(preCalibrationDialogComponent, qsTr("Calibrate Accelerometer"), qgcView.showDialogDefaultWidth, StandardButton.Cancel | StandardButton.Ok)
}
}
IndicatorButton {
id: compassButton
width: parent.buttonWidth
text: qsTr("Compass")
indicatorGreen: !compassCalNeeded
onClicked: {
if (controller.accelSetupNeeded) {
showMessage(qsTr("Calibrate Compass"), qsTr("Accelerometer must be calibrated prior to Compass."), StandardButton.Ok)
} else {
preCalibrationDialogType = "compass"
preCalibrationDialogHelp = compassHelp
showDialog(preCalibrationDialogComponent, qsTr("Calibrate Compass"), qgcView.showDialogDefaultWidth, StandardButton.Cancel | StandardButton.Ok)
}
}
}
QGCButton {
id: nextButton
text: qsTr("Next")
enabled: false
onClicked: controller.nextClicked()
}
QGCButton {
id: cancelButton
text: qsTr("Cancel")
enabled: false
onClicked: controller.cancelCalibration()
}
} // Row - Cal buttons
ProgressBar {
id: progressBar
anchors.topMargin: ScreenTools.defaultFontPixelHeight
anchors.top: buttonsRow.bottom
anchors.left: parent.left
anchors.right: centerPanel.right
}
Item {
id: centerPanel
anchors.topMargin: ScreenTools.defaultFontPixelHeight
anchors.rightMargin: ScreenTools.defaultFontPixelHeight
anchors.top: progressBar.bottom
anchors.bottom: parent.bottom
anchors.left: parent.left
anchors.right: rotationsLoader.left
TextArea {
id: statusTextArea
anchors.fill: parent
readOnly: true
frameVisible: false
text: statusTextAreaDefaultText
style: TextAreaStyle {
textColor: qgcPal.text
backgroundColor: qgcPal.windowShade
}
}
Rectangle {
id: orientationCalArea
anchors.fill: parent
visible: controller.showOrientationCalArea
color: qgcPal.windowShade
QGCLabel {
id: orientationCalAreaHelpText
anchors.margins: ScreenTools.defaultFontPixelWidth
anchors.top: orientationCalArea.top
anchors.left: orientationCalArea.left
width: parent.width
wrapMode: Text.WordWrap
font.pointSize: ScreenTools.mediumFontPointSize
}
Flow {
anchors.topMargin: ScreenTools.defaultFontPixelWidth
anchors.top: orientationCalAreaHelpText.bottom
anchors.left: orientationCalAreaHelpText.left
width: parent.width
height: parent.height - orientationCalAreaHelpText.implicitHeight
spacing: ScreenTools.defaultFontPixelWidth
VehicleRotationCal {
visible: controller.orientationCalDownSideVisible
calValid: controller.orientationCalDownSideDone
calInProgress: controller.orientationCalDownSideInProgress
calInProgressText: controller.orientationCalDownSideRotate ? qsTr("Rotate") : qsTr("Hold Still")
imageSource: controller.orientationCalDownSideRotate ? "qrc:///qmlimages/VehicleDownRotate.png" : "qrc:///qmlimages/VehicleDown.png"
}
VehicleRotationCal {
visible: controller.orientationCalUpsideDownSideVisible
calValid: controller.orientationCalUpsideDownSideDone
calInProgress: controller.orientationCalUpsideDownSideInProgress
calInProgressText: controller.orientationCalUpsideDownSideRotate ? qsTr("Rotate") : qsTr("Hold Still")
imageSource: controller.orientationCalUpsideDownSideRotate ? "qrc:///qmlimages/VehicleUpsideDownRotate.png" : "qrc:///qmlimages/VehicleUpsideDown.png"
}
VehicleRotationCal {
visible: controller.orientationCalNoseDownSideVisible
calValid: controller.orientationCalNoseDownSideDone
calInProgress: controller.orientationCalNoseDownSideInProgress
calInProgressText: controller.orientationCalNoseDownSideRotate ? qsTr("Rotate") : qsTr("Hold Still")
imageSource: controller.orientationCalNoseDownSideRotate ? "qrc:///qmlimages/VehicleNoseDownRotate.png" : "qrc:///qmlimages/VehicleNoseDown.png"
}
VehicleRotationCal {
visible: controller.orientationCalTailDownSideVisible
calValid: controller.orientationCalTailDownSideDone
calInProgress: controller.orientationCalTailDownSideInProgress
calInProgressText: controller.orientationCalTailDownSideRotate ? qsTr("Rotate") : qsTr("Hold Still")
imageSource: controller.orientationCalTailDownSideRotate ? "qrc:///qmlimages/VehicleTailDownRotate.png" : "qrc:///qmlimages/VehicleTailDown.png"
}
VehicleRotationCal {
visible: controller.orientationCalLeftSideVisible
calValid: controller.orientationCalLeftSideDone
calInProgress: controller.orientationCalLeftSideInProgress
calInProgressText: controller.orientationCalLeftSideRotate ? qsTr("Rotate") : qsTr("Hold Still")
imageSource: controller.orientationCalLeftSideRotate ? "qrc:///qmlimages/VehicleLeftRotate.png" : "qrc:///qmlimages/VehicleLeft.png"
}
VehicleRotationCal {
visible: controller.orientationCalRightSideVisible
calValid: controller.orientationCalRightSideDone
calInProgress: controller.orientationCalRightSideInProgress
calInProgressText: controller.orientationCalRightSideRotate ? qsTr("Rotate") : qsTr("Hold Still")
imageSource: controller.orientationCalRightSideRotate ? "qrc:///qmlimages/VehicleRightRotate.png" : "qrc:///qmlimages/VehicleRight.png"
}
}
}
} // Item - Cal display area
Loader {
id: rotationsLoader
anchors.top: centerPanel.top
anchors.bottom: parent.bottom
anchors.right: parent.right
width: rotationColumnWidth
sourceComponent: rotationCombosComponent
property bool showCompassRotations: true
}
} // QGCViewPanel
} // QGCView