7import QGroundControl.Controls
8import QGroundControl.FactControls
13 property real availableHeight
14 property real availableWidth
18 property var tuningMode
19 property double chartDisplaySec: 8 // number of seconds to display
20 property bool showAutoModeChange: false
21 property bool showAutoTuning: false
23 property real _margins: ScreenTools.defaultFontPixelHeight / 2
24 property int _currentAxis: 0
25 property var _xAxis: xAxis
26 property var _yAxis: yAxis
27 property int _msecs: 0
28 property double _last_t: 0
29 property var _savedTuningParamValues: [ ]
31 readonly property int _tickSeparation: 5
32 readonly property int _maxTickSections: 10
34 function adjustYAxisMin(yAxis, newValue) {
35 var newMin = Math.min(yAxis.min, newValue)
36 if (newMin % 5 != 0) {
38 newMin = Math.floor(newMin / _tickSeparation) * _tickSeparation
43 function adjustYAxisMax(yAxis, newValue) {
44 var newMax = Math.max(yAxis.max, newValue)
45 if (newMax % 5 != 0) {
47 newMax = Math.floor(newMax / _tickSeparation) * _tickSeparation
52 function resetGraphs() {
53 for (var i = 0; i < chart.count; ++i) {
54 chart.series(i).removePoints(0, chart.series(i).count)
64 // Save the current set of tuning values so we can reset to them
65 function saveTuningParamValues() {
66 _savedTuningParamValues = [ ]
67 for (var i=0; i<axis[_currentAxis].params.count; i++) {
68 var currentTuneParam = controller.getParameterFact(-1, axis[_currentAxis].params.get(i).param)
69 _savedTuningParamValues.push(currentTuneParam.valueString)
71 savedRepeater.model = _savedTuningParamValues
74 function resetToSavedTuningParamValues() {
75 for (var i=0; i<axis[_currentAxis].params.count; i++) {
76 var currentTuneParam = controller.getParameterFact(-1,
77 axis[_currentAxis].params.get(i).param)
78 currentTuneParam.value = _savedTuningParamValues[i]
82 function axisIndexChanged() {
83 chart.removeAllSeries()
84 axis[_currentAxis].plot.forEach(function(e) {
85 chart.createSeries(ChartView.SeriesTypeLine, e.name, xAxis, yAxis);
87 var chartTitle = axis[_currentAxis].plotTitle
88 if (chartTitle == null)
89 chartTitle = axis[_currentAxis].name
90 chart.title = chartTitle + " " + title
91 saveTuningParamValues()
95 Component.onCompleted: {
97 globals.activeVehicle.setPIDTuningTelemetryMode(tuningMode)
98 saveTuningParamValues()
101 Component.onDestruction: globals.activeVehicle.setPIDTuningTelemetryMode(Vehicle.ModeDisabled)
102 on_CurrentAxisChanged: axisIndexChanged()
109 titleText: ScreenTools.isShortScreen ? "" : qsTr("sec") // Save space on small screens
110 tickCount: Math.min(Math.max(Math.floor(chart.width / (ScreenTools.defaultFontPixelWidth * 7)), 4), 11)
111 labelsFont.pointSize: ScreenTools.defaultFontPointSize
112 labelsFont.family: ScreenTools.normalFontFamily
113 titleFont.pointSize: ScreenTools.defaultFontPointSize
114 titleFont.family: ScreenTools.normalFontFamily
122 tickCount: Math.min(((max - min) / _tickSeparation), _maxTickSections) + 1
123 labelsFont.pointSize: ScreenTools.defaultFontPointSize
124 labelsFont.family: ScreenTools.normalFontFamily
125 titleFont.pointSize: ScreenTools.defaultFontPointSize
126 titleFont.family: ScreenTools.normalFontFamily
136 _xAxis.max = _msecs / 1000
137 _xAxis.min = _msecs / 1000 - chartDisplaySec
139 var firstPoint = _msecs == 0
141 var len = axis[_currentAxis].plot.length
142 for (var i = 0; i < len; ++i) {
143 var value = axis[_currentAxis].plot[i].value
145 chart.series(i).append(_msecs/1000, value)
150 adjustYAxisMin(_yAxis, value)
151 adjustYAxisMax(_yAxis, value)
154 var minSec = _msecs/1000 - 3*60
155 while (chart.series(i).count > 0 && chart.series(i).at(0).x < minSec) {
156 chart.series(i).remove(0)
161 var t = new Date().getTime() // in ms
167 property int _maxPointCount: 10000 / interval
172 Layout.alignment: Qt.AlignTop
173 spacing: ScreenTools.defaultFontPixelHeight / 4
174 clip: true // chart has redraw problems
178 width: Math.max(_minChartWidth, availableWidth - rightPanel.width - parent.spacing - _margins)
179 height: Math.max(_minChartHeight, availableHeight - leftPanelBottomColumn.height - parent.spacing - _margins)
181 legend.alignment: Qt.AlignBottom
182 legend.font.pointSize: ScreenTools.defaultFontPointSize
183 legend.font.family: ScreenTools.normalFontFamily
184 titleFont.pointSize: ScreenTools.defaultFontPointSize
185 titleFont.family: ScreenTools.normalFontFamily
187 property real _chartMargin: 0
188 property real _minChartWidth: ScreenTools.defaultFontPixelWidth * 40
189 property real _minChartHeight: ScreenTools.defaultFontPixelHeight * 15
191 // enable mouse dragging
193 property var _startPoint: undefined
194 property double _scaling: 0
196 onPressed: (mouse) => {
197 _startPoint = Qt.point(mouse.x, mouse.y)
198 var start = chart.mapToValue(_startPoint)
199 var next = chart.mapToValue(Qt.point(mouse.x+1, mouse.y+1))
200 _scaling = next.x - start.x
202 onWheel: (wheel) => {
203 if (wheel.angleDelta.y > 0)
204 chartDisplaySec /= 1.2
206 chartDisplaySec *= 1.2
207 _xAxis.min = _xAxis.max - chartDisplaySec
209 onPositionChanged: (mouse) => {
210 if(_startPoint != undefined) {
211 dataTimer.running = false
212 var cp = Qt.point(mouse.x, mouse.y)
213 var dx = (cp.x - _startPoint.x) * _scaling
221 _startPoint = undefined
227 id: leftPanelBottomColumn
228 spacing: ScreenTools.defaultFontPixelHeight / 4
235 onClicked: resetGraphs()
239 text: dataTimer.running ? qsTr("Stop") : qsTr("Start")
241 dataTimer.running = !dataTimer.running
243 if (showAutoModeChange && autoModeChange.checked) {
244 globals.activeVehicle.flightMode = dataTimer.running ? globals.activeVehicle.stabilizedFlightMode : globals.activeVehicle.pauseFlightMode
249 target: globals.activeVehicle
251 if (armed && !dataTimer.running) { // start plotting on arming if not already running
252 dataTimer.running = true
260 visible: showAutoModeChange
262 text: qsTr("Automatic Flight Mode Switching")
265 dataTimer.running = false
270 visible: autoModeChange.checked
272 text: qsTr("Switches to 'Stabilized' when you click Start.")
273 font.pointSize: ScreenTools.smallFontPointSize
277 text: qsTr("Switches to '%1' when you click Stop.").arg(globals.activeVehicle.pauseFlightMode)
278 font.pointSize: ScreenTools.smallFontPointSize
286 Layout.alignment: Qt.AlignTop
289 visible: showAutoTuning
292 id: useAutoTuningRadio
293 text: qsTr("Use auto-tuning")
294 checked: useAutoTuning
295 onClicked: useAutoTuning = true
298 id: useManualTuningRadio
299 text: qsTr("Use manual tuning")
300 checked: !useAutoTuning
301 onClicked: useAutoTuning = false
306 visible: showAutoTuning && useAutoTuningRadio.checked
310 visible: !showAutoTuning || useManualTuningRadio.checked
315 visible: axis.length > 1
317 QGCLabel { text: qsTr("Select Tuning:") }
323 checked: index == _currentAxis
324 onClicked: _currentAxis = index
330 // Instantiate all sliders (instead of switching the model), so that
331 // values are not changed unexpectedly if they do not match with a tick value.
336 model: axis[index].params
338 SettingsGroupLayout {
341 headingDescription: description
342 visible: _currentAxis === index
343 Layout.preferredWidth: ScreenTools.defaultFontPixelWidth * 40
346 fact: controller.getParameterFact(-1, param)
349 majorTickStepSize: step
350 Layout.fillWidth: true
357 QGCLabel { text: qsTr("Clipboard Values:") }
360 rows: savedRepeater.model.length
361 flow: GridLayout.TopToBottom
363 columnSpacing: _margins
366 model: axis[_currentAxis].params
368 QGCLabel { text: param }
374 QGCLabel { text: modelData }
383 text: qsTr("Save To Clipboard")
384 onClicked: saveTuningParamValues()
388 text: qsTr("Restore From Clipboard")
389 onClicked: resetToSavedTuningParamValues()