diff --git a/js/flightlog.js b/js/flightlog.js
index 19544c28..b8e72f6b 100644
--- a/js/flightlog.js
+++ b/js/flightlog.js
@@ -209,7 +209,7 @@ function FlightLog(logData) {
} else
return false;
};
-
+
function buildFieldNames() {
// Make an independent copy
fieldNames = parser.frameDefs.I.name.slice(0);
@@ -239,7 +239,7 @@ function FlightLog(logData) {
if (!that.isFieldDisabled().SETPOINT) {
fieldNames.push("rcCommands[0]", "rcCommands[1]", "rcCommands[2]", "rcCommands[3]"); // Custom calculated scaled rccommand
}
- if (!(that.isFieldDisabled().GYRO || that.isFieldDisabled().PID)) {
+ if (!that.isFieldDisabled().GYRO && !that.isFieldDisabled().PID) {
fieldNames.push("axisError[0]", "axisError[1]", "axisError[2]"); // Custom calculated error field
}
@@ -385,8 +385,8 @@ function FlightLog(logData) {
destFrame,
destFrame_currentIndex;
- // The G frames need to be processed always. They are "invalid" if not H (Home) has been detected
- // before, but if not processed the viewer shows cuts and gaps. This happens if the quad takes off before
+ // The G frames need to be processed always. They are "invalid" if not H (Home) has been detected
+ // before, but if not processed the viewer shows cuts and gaps. This happens if the quad takes off before
// fixing enough satellites.
if (frameValid || (frameType == 'G' && frame)) {
switch (frameType) {
@@ -419,7 +419,7 @@ function FlightLog(logData) {
destFrame[slowFrameIndex + destFrame_currentIndex] = lastSlow[slowFrameIndex] === undefined ? null : lastSlow[slowFrameIndex];
}
destFrame_currentIndex += slowFrameLength;
-
+
// Also merge last seen gps-frame data
for (let gpsFrameIndex = 0; gpsFrameIndex < lastGPSLength; gpsFrameIndex++) {
destFrame[gpsFrameIndex + destFrame_currentIndex] = lastGPS[gpsFrameIndex] === undefined ? null : lastGPS[gpsFrameIndex];
@@ -617,7 +617,7 @@ function FlightLog(logData) {
destFrame = destChunk.frames[i],
fieldIndex = destFrame.length - ADDITIONAL_COMPUTED_FIELD_COUNT;
- if (gyroADC) { //don't calculate attitude if no gyro data
+ if (!that.isFieldDisabled().GYRO) { //don't calculate attitude if no gyro data
attitude = chunkIMU.updateEstimatedAttitude(
[srcFrame[gyroADC[0]], srcFrame[gyroADC[1]], srcFrame[gyroADC[2]]],
[srcFrame[accSmooth[0]], srcFrame[accSmooth[1]], srcFrame[accSmooth[2]]],
@@ -632,7 +632,7 @@ function FlightLog(logData) {
}
// Add the Feedforward PID sum (P+I+D+F)
- if (axisPID) {
+ if (!that.isFieldDisabled().GYRO && !that.isFieldDisabled().PID) {
for (var axis = 0; axis < 3; axis++) {
let pidSum =
(axisPID[axis][0] !== undefined ? srcFrame[axisPID[axis][0]] : 0) +
@@ -647,7 +647,7 @@ function FlightLog(logData) {
}
// Assign value
- destFrame[fieldIndex++] = pidSum;
+ destFrame[fieldIndex++] = pidSum;
}
}
@@ -657,29 +657,31 @@ function FlightLog(logData) {
// Calculate the Scaled rcCommand (setpoint) (in deg/s, % for throttle)
var fieldIndexRcCommands = fieldIndex;
- // Since version 4.0 is not more a virtual field. Copy the real field to the virtual one to maintain the name, workspaces, etc.
- if (sysConfig.firmwareType == FIRMWARE_TYPE_BETAFLIGHT && semver.gte(sysConfig.firmwareVersion, '4.0.0')) {
- // Roll, pitch and yaw
- for (var axis = 0; axis <= AXIS.YAW; axis++) {
- destFrame[fieldIndex++] = srcFrame[setpoint[axis]];
- }
- // Throttle
- destFrame[fieldIndex++] = srcFrame[setpoint[AXIS.YAW + 1]]/10;
+ if (!that.isFieldDisabled().SETPOINT) {
- // Versions earlier to 4.0 we must calculate the expected setpoint
- } else {
- // Roll, pitch and yaw
- for (var axis = 0; axis <= AXIS.YAW; axis++) {
+ // Since version 4.0 is not more a virtual field. Copy the real field to the virtual one to maintain the name, workspaces, etc.
+ if (sysConfig.firmwareType == FIRMWARE_TYPE_BETAFLIGHT && semver.gte(sysConfig.firmwareVersion, '4.0.0')) {
+ // Roll, pitch and yaw
+ for (let axis = 0; axis <= AXIS.YAW; axis++) {
+ destFrame[fieldIndex++] = srcFrame[setpoint[axis]];
+ }
+ // Throttle
+ destFrame[fieldIndex++] = srcFrame[setpoint[AXIS.YAW + 1]]/10;
+
+ // Versions earlier to 4.0 we must calculate the expected setpoint
+ } else {
+ // Roll, pitch and yaw
+ for (let axis = 0; axis <= AXIS.YAW; axis++) {
+ destFrame[fieldIndex++] = rcCommand[axis] !== undefined ? that.rcCommandRawToDegreesPerSecond(srcFrame[rcCommand[axis]], axis, currentFlightMode) : 0;
+ }
+ // Throttle
destFrame[fieldIndex++] =
- (rcCommand[axis] !== undefined ? that.rcCommandRawToDegreesPerSecond(srcFrame[rcCommand[axis]], axis, currentFlightMode) : 0);
- }
- // Throttle
- destFrame[fieldIndex++] =
- (rcCommand[AXIS.YAW + 1] !== undefined ? that.rcCommandRawToThrottle(srcFrame[rcCommand[AXIS.YAW + 1]]) : 0);
+ (rcCommand[AXIS.YAW + 1] !== undefined ? that.rcCommandRawToThrottle(srcFrame[rcCommand[AXIS.YAW + 1]]) : 0);
+ }
}
// Calculate the PID Error
- if (axisPID && gyroADC) {
+ if (!that.isFieldDisabled().GYRO && !that.isFieldDisabled().PID) {
for (var axis = 0; axis < 3; axis++) {
let gyroADCdegrees = (gyroADC[axis] !== undefined ? that.gyroRawToDegreesPerSecond(srcFrame[gyroADC[axis]]) : 0);
destFrame[fieldIndex++] = destFrame[fieldIndexRcCommands + axis] - gyroADCdegrees;
@@ -1131,7 +1133,7 @@ FlightLog.prototype.rcCommandRawToDegreesPerSecond = function(value, axis, curre
}
var rcRate = sysConfig["rc_rates"][axis] / 100.0;
- if (rcRate > 2.0) {
+ if (rcRate > 2.0) {
rcRate += RC_RATE_INCREMENTAL * (rcRate - 2.0);
}
diff --git a/js/flightlog_fields_presenter.js b/js/flightlog_fields_presenter.js
index a8980de9..b40212ac 100644
--- a/js/flightlog_fields_presenter.js
+++ b/js/flightlog_fields_presenter.js
@@ -911,7 +911,7 @@ function FlightLogFieldPresenter() {
'debug[4]':'Minimum Gyro period in 100th of a us',
'debug[5]':'Maximum Gyro period in 100th of a us',
'debug[6]':'Span of Gyro period in 100th of a us',
- 'debug[7]':'Not Used',
+ 'debug[7]':'Gyro cycle deviation in 100th of a us',
},
'TIMING_ACCURACY' : {
'debug[all]':'Timing Accuracy',
@@ -1897,6 +1897,8 @@ function FlightLogFieldPresenter() {
return value.toFixed(0);
case 'DSHOT_TELEMETRY_COUNTS':
return value.toFixed(0);
+ case 'EZLANDING':
+ return `${(value / 100.0).toFixed(2)} %`;
}
return value.toFixed(0);
}
diff --git a/js/graph_config.js b/js/graph_config.js
index 67d1b4b7..a8c938d4 100644
--- a/js/graph_config.js
+++ b/js/graph_config.js
@@ -1274,6 +1274,13 @@ TODO - The stats data have small issues of min-max data !!!!
default:
return getCurveForMinMaxFields(fieldName);
}
+ case 'EZLANDING':
+ return {
+ offset: -5000,
+ power: 1.0,
+ inputRange: 5000,
+ outputRange: 1.0,
+ };
}
}
// if not found above then
diff --git a/js/graph_config_dialog.js b/js/graph_config_dialog.js
index d8b8d100..1d8b9a4a 100644
--- a/js/graph_config_dialog.js
+++ b/js/graph_config_dialog.js
@@ -11,7 +11,6 @@ function GraphConfigurationDialog(dialog, onSave) {
prevCfg = null,
cfgMustBeRestored = false;
-
function chooseColor(currentSelection) {
const selectColor = $('');
for(let i=0; i")
.text(FlightLogFieldPresenter.fieldNameToFriendly(fieldName, activeFlightLog.getSysConfig().debug_mode))
.attr("value", fieldName);
@@ -108,12 +107,12 @@ function GraphConfigurationDialog(dialog, onSave) {
}
}
- /**
+ /*
* Render the element for the "pick a field" dropdown box. Provide "field" from the config in order to set up the
* initial selection.
*/
function renderField(flightLog, field, color) {
- var
+ var
elem = $(
'
'
+ '
'
@@ -146,7 +145,7 @@ function GraphConfigurationDialog(dialog, onSave) {
//Populate the Color Picker
$('select.color-picker', elem).replaceWith(chooseColor(color));
-
+
// Add event when selection changed to retrieve the current smoothing settings.
$('select.form-control', elem).change( function() {
@@ -764,7 +763,7 @@ function GraphConfigurationDialog(dialog, onSave) {
}
function renderGraph(flightLog, index, graph) {
- var
+ var
graphElem = $(
'
'
+ '
'
@@ -844,11 +843,11 @@ function GraphConfigurationDialog(dialog, onSave) {
});
//Populate the Height seletor
- $('select.graph-height', graphElem).replaceWith(chooseHeight(graph.height?(graph.height):1));
+ $('select.graph-height', graphElem).replaceWith(chooseHeight(graph.height?(graph.height):1));
// Add Field List
for (var i = 0; i < graph.fields.length; i++) {
- var
+ var
field = graph.fields[i],
fieldElem = renderField(flightLog, field, field.color?(field.color):(GraphConfig.PALETTE[i].color));
@@ -858,9 +857,9 @@ function GraphConfigurationDialog(dialog, onSave) {
fieldList.on('click', 'button', function(e) {
var
parentGraph = $(this).parents('.config-graph');
-
+
$(this).parents('.config-graph-field').remove();
-
+
// Remove the graph upon removal of the last field
if ($(".config-graph-field", parentGraph).length === 0) {
parentGraph.remove();
@@ -874,7 +873,7 @@ function GraphConfigurationDialog(dialog, onSave) {
return graphElem;
}
-
+
function renderGraphs(flightLog, graphs) {
var
graphList = $(".config-graphs-list", dialog);
@@ -889,7 +888,7 @@ function GraphConfigurationDialog(dialog, onSave) {
function populateExampleGraphs(flightLog, menu) {
var
i;
-
+
menu.empty();
exampleGraphs = GraphConfig.getExampleGraphConfigs(flightLog);
@@ -899,18 +898,18 @@ function GraphConfigurationDialog(dialog, onSave) {
fields: [{name:""}],
dividerAfter: true
});
-
+
for (i = 0; i < exampleGraphs.length; i++) {
- var
+ var
graph = exampleGraphs[i],
li = $('
');
-
+
$('a', li)
.text(graph.label)
.data('graphIndex', i);
menu.append(li);
-
+
if (graph.dividerAfter) {
menu.append('');
}
@@ -918,7 +917,7 @@ function GraphConfigurationDialog(dialog, onSave) {
}
function convertUIToGraphConfig() {
- var
+ var
graphs = [],
graph,
field;
@@ -983,7 +982,7 @@ function GraphConfigurationDialog(dialog, onSave) {
for (i = 0; i < fieldNames.length; i++) {
// For fields with multiple bracketed x[0], x[1] versions, add an "[all]" option
- var
+ var
fieldName = fieldNames[i],
matches = fieldName.match(/^(.+)\[[0-9]+\]$/);
@@ -993,7 +992,7 @@ function GraphConfigurationDialog(dialog, onSave) {
if (matches) {
if (matches[1] != lastRoot) {
lastRoot = matches[1];
-
+
offeredFieldNames.push(lastRoot + "[all]");
fieldsSeen[lastRoot + "[all]"] = true;
}
@@ -1011,13 +1010,13 @@ function GraphConfigurationDialog(dialog, onSave) {
* keep that tail servo in the config when we're viewing a quadcopter).
*/
for (i = 0; i < config.length; i++) {
- var
+ var
graph = config[i];
-
+
for (j = 0; j < graph.fields.length; j++) {
- var
+ var
field = graph.fields[j];
-
+
if (!fieldsSeen[field.name]) {
offeredFieldNames.push(field.name);
}
@@ -1043,7 +1042,7 @@ function GraphConfigurationDialog(dialog, onSave) {
if (cfgMustBeRestored)
onSave(prevCfg);
});
-
+
$(".graph-configuration-dialog-save").click(function() {
cfgMustBeRestored = false;
onSave(convertUIToGraphConfig());
@@ -1075,16 +1074,16 @@ function GraphConfigurationDialog(dialog, onSave) {
exampleGraphsButton.dropdown();
exampleGraphsMenu.on("click", "a", function(e) {
- var
+ var
graph = exampleGraphs[$(this).data("graphIndex")],
graphElem = renderGraph(activeFlightLog, $(".config-graph", dialog).length, graph);
-
+
$(configGraphsList, dialog).append(graphElem);
updateRemoveAllButton();
-
+
// Dismiss the dropdown button
exampleGraphsButton.dropdown("toggle");
-
+
e.preventDefault();
});
diff --git a/js/graph_spectrum.js b/js/graph_spectrum.js
index dc80996e..59a88a92 100644
--- a/js/graph_spectrum.js
+++ b/js/graph_spectrum.js
@@ -8,7 +8,7 @@ const
ANALYSER_LARGE_HEIGHT_MARGIN = 20,
ANALYSER_LARGE_WIDTH_MARGIN = 20;
-var
+var
that = this,
analyserZoomX = 1.0, /* 100% */
@@ -31,9 +31,9 @@ var
var isFullscreen = false;
var sysConfig = flightLog.getSysConfig();
- GraphSpectrumCalc.initialize(flightLog, sysConfig);
+ const logRateInfo = GraphSpectrumCalc.initialize(flightLog, sysConfig);
GraphSpectrumPlot.initialize(analyserCanvas, sysConfig);
-
+ GraphSpectrumPlot.setLogRateWarningInfo(logRateInfo);
var analyserZoomXElem = $("#analyserZoomX");
var analyserZoomYElem = $("#analyserZoomY");
@@ -75,7 +75,7 @@ var
}
};
- this.resize = function() {
+ this.resize = function() {
var newSize = getSize();
@@ -125,13 +125,12 @@ var
fftData = GraphSpectrumCalc.dataLoadFrequency();
break;
}
-
};
/* This function is called from the canvas drawing routines within grapher.js
- It is only used to record the current curve positions, collect the data and draw the
+ It is only used to record the current curve positions, collect the data and draw the
analyser on screen*/
- this.plotSpectrum = function (fieldIndex, curve, fieldName) {
+ this.plotSpectrum = function (fieldIndex, curve, fieldName) {
// Store the data pointers
dataBuffer = {
fieldIndex: fieldIndex,
@@ -142,7 +141,7 @@ var
// Detect change of selected field.... reload and redraw required.
if ((fftData == null) || (fieldIndex != fftData.fieldIndex) || dataReload) {
dataReload = false;
- dataLoad();
+ dataLoad();
GraphSpectrumPlot.setData(fftData, userSettings.spectrumType);
}
@@ -231,7 +230,7 @@ var
// track frequency under mouse
var lastMouseX = 0,
lastMouseY = 0;
-
+
function trackFrequency(e, analyser) {
if(e.shiftKey) {
diff --git a/js/graph_spectrum_calc.js b/js/graph_spectrum_calc.js
index 65adbcf9..c772319e 100644
--- a/js/graph_spectrum_calc.js
+++ b/js/graph_spectrum_calc.js
@@ -6,10 +6,12 @@ const
FREQ_VS_THR_CHUNK_TIME_MS = 300,
FREQ_VS_THR_WINDOW_DIVISOR = 6,
MAX_ANALYSER_LENGTH = 300 * 1000 * 1000, // 5min
- NUM_VS_BINS = 100;
+ NUM_VS_BINS = 100,
+ WARNING_RATE_DIFFERENCE = 0.05,
+ MAX_RPM_VALUE = 10000;
var GraphSpectrumCalc = GraphSpectrumCalc || {
- _analyserTimeRange : {
+ _analyserTimeRange : {
in: 0,
out: MAX_ANALYSER_LENGTH
},
@@ -25,7 +27,7 @@ var GraphSpectrumCalc = GraphSpectrumCalc || {
GraphSpectrumCalc.initialize = function(flightLog, sysConfig) {
- this._flightLog = flightLog;
+ this._flightLog = flightLog;
this._sysConfig = sysConfig;
var gyroRate = (1000000 / this._sysConfig['looptime']).toFixed(0);
@@ -33,6 +35,29 @@ GraphSpectrumCalc.initialize = function(flightLog, sysConfig) {
if (this._sysConfig.pid_process_denom != null) {
this._blackBoxRate = this._blackBoxRate / this._sysConfig.pid_process_denom;
}
+ this._BetaflightRate = this._blackBoxRate;
+
+ let minTime = this._flightLog.getMinTime(),
+ maxTime = this._flightLog.getMaxTime();
+ let timeRange = maxTime - minTime;
+ if (timeRange > MAX_ANALYSER_LENGTH) {
+ maxTime = minTime + MAX_ANALYSER_LENGTH;
+ timeRange = MAX_ANALYSER_LENGTH;
+ }
+ const allChunks = this._flightLog.getChunksInTimeRange(minTime, maxTime);
+ const length = allChunks.reduce((acc, chunk) => acc + chunk.frames.length, 0);
+ this._actualeRate = 1e6 * length / timeRange;
+
+ if (Math.abs(this._BetaflightRate - this._actualeRate) / this._actualeRate > WARNING_RATE_DIFFERENCE)
+ this._blackBoxRate = Math.round(this._actualeRate);
+
+ if (this._BetaflightRate !== this._blackBoxRate) {
+ return {
+ actualRate: this._actualeRate,
+ betaflightRate: this._BetaflightRate,
+ };
+ }
+ return undefined;
};
GraphSpectrumCalc.setInTime = function(time) {
@@ -51,6 +76,7 @@ GraphSpectrumCalc.setOutTime = function(time) {
GraphSpectrumCalc.setDataBuffer = function(dataBuffer) {
this._dataBuffer = dataBuffer;
+ return undefined;
};
GraphSpectrumCalc.dataLoadFrequency = function() {
@@ -75,8 +101,8 @@ GraphSpectrumCalc._dataLoadFrequencyVsX = function(vsFieldNames, minValue = Infi
let flightSamples = this._getFlightSamplesFreqVsX(vsFieldNames, minValue, maxValue);
- // We divide it into FREQ_VS_THR_CHUNK_TIME_MS FFT chunks, we calculate the average throttle
- // for each chunk. We use a moving window to get more chunks available.
+ // We divide it into FREQ_VS_THR_CHUNK_TIME_MS FFT chunks, we calculate the average throttle
+ // for each chunk. We use a moving window to get more chunks available.
var fftChunkLength = this._blackBoxRate * FREQ_VS_THR_CHUNK_TIME_MS / 1000;
var fftChunkWindow = Math.round(fftChunkLength / FREQ_VS_THR_WINDOW_DIVISOR);
@@ -88,10 +114,10 @@ GraphSpectrumCalc._dataLoadFrequencyVsX = function(vsFieldNames, minValue = Infi
var fft = new FFT.complex(fftChunkLength, false);
for (var fftChunkIndex = 0; fftChunkIndex + fftChunkLength < flightSamples.samples.length; fftChunkIndex += fftChunkWindow) {
-
+
let fftInput = flightSamples.samples.slice(fftChunkIndex, fftChunkIndex + fftChunkLength);
let fftOutput = new Float64Array(fftChunkLength * 2);
-
+
// Hanning window applied to input data
if(userSettings.analyserHanning) {
this._hanningWindow(fftInput, fftChunkLength);
@@ -137,8 +163,8 @@ GraphSpectrumCalc._dataLoadFrequencyVsX = function(vsFieldNames, minValue = Infi
}
}
- // The output data needs to be smoothed, the sampling is not perfect
- // but after some tests we let the data as is, an we prefer to apply a
+ // The output data needs to be smoothed, the sampling is not perfect
+ // but after some tests we let the data as is, an we prefer to apply a
// blur algorithm to the heat map image
var fftData = {
@@ -231,13 +257,13 @@ GraphSpectrumCalc._getFlightChunks = function() {
logStart = this._analyserTimeRange.in;
} else {
logStart = this._flightLog.getMinTime();
- }
+ }
- var logEnd = 0;
+ var logEnd = 0;
if(this._analyserTimeRange.out) {
logEnd = this._analyserTimeRange.out;
} else {
- logEnd = this._flightLog.getMaxTime();
+ logEnd = this._flightLog.getMaxTime();
}
// Limit size
@@ -289,6 +315,7 @@ GraphSpectrumCalc._getFlightSamplesFreqVsX = function(vsFieldNames, minValue = I
let vsValues = new Array(vsIndexes.length).fill(null).map(() => new Float64Array(MAX_ANALYSER_LENGTH / (1000 * 1000) * this._blackBoxRate));
var samplesCount = 0;
+ let lastRPM = 0;
for (var chunkIndex = 0; chunkIndex < allChunks.length; chunkIndex++) {
var chunk = allChunks[chunkIndex];
for (var frameIndex = 0; frameIndex < chunk.frames.length; frameIndex++) {
@@ -297,6 +324,11 @@ GraphSpectrumCalc._getFlightSamplesFreqVsX = function(vsFieldNames, minValue = I
for (let i = 0; i < vsIndexes.length; i++) {
let vsFieldIx = vsIndexes[i];
let value = chunk.frames[frameIndex][vsFieldIx];
+ if (vsFieldNames == FIELD_RPM_NAMES) {
+ if (value > MAX_RPM_VALUE || value < 0)
+ value = lastRPM;
+ lastRPM = value;
+ }
maxValue = Math.max(maxValue, value);
minValue = Math.min(minValue, value);
vsValues[i][samplesCount] = value;
@@ -405,7 +437,7 @@ GraphSpectrumCalc._normalizeFft = function(fftOutput, fftLength) {
var noiseLowEndIdx = 100 / maxFrequency * fftLength;
var maxNoiseIdx = 0;
var maxNoise = 0;
-
+
for (var i = 0; i < fftLength; i++) {
fftOutput[i] = Math.abs(fftOutput[i]);
if (i > noiseLowEndIdx && fftOutput[i] > maxNoise) {
diff --git a/js/graph_spectrum_plot.js b/js/graph_spectrum_plot.js
index 2bea4faa..da411f86 100644
--- a/js/graph_spectrum_plot.js
+++ b/js/graph_spectrum_plot.js
@@ -53,6 +53,7 @@ GraphSpectrumPlot.initialize = function(canvas, sysConfig) {
this._sysConfig = sysConfig;
this._invalidateCache();
this._invalidateDataCache();
+ this._logRateWarning = undefined;
};
GraphSpectrumPlot.setZoom = function(zoomX, zoomY) {
@@ -462,6 +463,8 @@ GraphSpectrumPlot._drawFiltersAndMarkers = function(canvasCtx) {
offset++;
}
+ this._drawRateWarning(canvasCtx);
+
};
GraphSpectrumPlot._drawNotCachedElements = function() {
@@ -855,3 +858,29 @@ GraphSpectrumPlot._invalidateCache = function() {
GraphSpectrumPlot._invalidateDataCache = function() {
this._cachedDataCanvas = null;
};
+
+GraphSpectrumPlot.setLogRateWarningInfo = function(logRateInfo) {
+ this._logRateWarning = logRateInfo;
+};
+
+GraphSpectrumPlot._drawRateWarning = function(canvasCtx) {
+ if (this._logRateWarning != undefined) {
+ canvasCtx.save();
+
+ canvasCtx.font = `${((this._isFullScreen)? this._drawingParams.fontSizeFrameLabelFullscreen : this._drawingParams.fontSizeFrameLabel)}pt ${DEFAULT_FONT_FACE}`;
+ canvasCtx.fillStyle = 'orange';
+ canvasCtx.textAlign = 'center';
+ canvasCtx.shadowColor = 'black';
+ canvasCtx.strokeStyle = 'black';
+
+ const actualRate = this._logRateWarning.actualRate.toFixed(0),
+ betaflightRate = this._logRateWarning.betaflightRate.toFixed(0);
+ const WarningText = "THE ACTUAL AND CONFIG LOG DATA RATE DIFFERENCE: " + actualRate + " : " + betaflightRate;
+ const X = canvasCtx.canvas.width/2,
+ Y = canvasCtx.canvas.height/12;
+ canvasCtx.strokeText(WarningText, X, Y);
+ canvasCtx.fillText(WarningText, X, Y);
+
+ canvasCtx.restore();
+ }
+};
diff --git a/js/header_dialog.js b/js/header_dialog.js
index 3a9e73ef..88e96eeb 100644
--- a/js/header_dialog.js
+++ b/js/header_dialog.js
@@ -465,7 +465,7 @@ function HeaderDialog(dialog, onSave) {
{name: 'Unfiltered Gyroscope', description: 'Unfiltered gyro data'},
];
- const fieldsList_e = $('.fields_list');
+ const fieldsList_e = $('.fields_list').empty();
for (let i = 0; i < fields.length; i++) {
const row_e = $(`