From 91925f4a9d2cb4fe6d8ca3c854376f2d68438f71 Mon Sep 17 00:00:00 2001 From: ctzsnooze Date: Tue, 27 Sep 2022 12:27:14 +1000 Subject: [PATCH 1/2] Fix heading calc, update graphs, degree symbol, spaces before units, white space --- js/flightlog_fields_presenter.js | 216 ++++++++++++++++--------------- js/graph_config.js | 90 +++++++------ js/imu.js | 93 ++++++------- 3 files changed, 205 insertions(+), 194 deletions(-) diff --git a/js/flightlog_fields_presenter.js b/js/flightlog_fields_presenter.js index 639dc2d8..472e8f5a 100644 --- a/js/flightlog_fields_presenter.js +++ b/js/flightlog_fields_presenter.js @@ -107,7 +107,7 @@ function FlightLogFieldPresenter() { 'rxFlightChannelsValid': 'RX Flight Ch. Valid', 'rssi': 'RSSI', }; - + const DEBUG_FRIENDLY_FIELD_NAMES_INITIAL = { 'NONE' : { 'debug[all]':'Debug [all]', @@ -138,7 +138,7 @@ function FlightLogFieldPresenter() { 'debug[3]':'Not Used', }, 'GYRO_FILTERED' : { - 'debug[all]':'Debug Gyro Filtered', + 'debug[all]':'Debug Gyro Filtered', 'debug[0]':'Gyro Filtered [X]', 'debug[1]':'Gyro Filtered [Y]', 'debug[2]':'Gyro Filtered [Z]', @@ -173,7 +173,7 @@ function FlightLogFieldPresenter() { 'debug[3]':'Not Used', }, 'GYRO_SCALED' : { - 'debug[all]':'Debug Gyro Scaled', + 'debug[all]':'Debug Gyro Scaled', 'debug[0]':'Gyro Scaled [roll]', 'debug[1]':'Gyro Scaled [pitch]', 'debug[2]':'Gyro Scaled [yaw]', @@ -278,35 +278,35 @@ function FlightLogFieldPresenter() { 'debug[3]':'Offset Min', }, 'GYRO_RAW' : { - 'debug[all]':'Debug Gyro Raw', + 'debug[all]':'Debug Gyro Raw', 'debug[0]':'Gyro Raw [X]', 'debug[1]':'Gyro Raw [Y]', 'debug[2]':'Gyro Raw [Z]', 'debug[3]':'Not Used', }, 'DUAL_GYRO' : { - 'debug[all]':'Debug Dual Gyro', + 'debug[all]':'Debug Dual Gyro', 'debug[0]':'Gyro 1 Filtered [roll]', 'debug[1]':'Gyro 1 Filtered [pitch]', 'debug[2]':'Gyro 2 Filtered [roll]', 'debug[3]':'Gyro 2 Filtered [pitch]', }, 'DUAL_GYRO_RAW': { - 'debug[all]':'Debug Dual Gyro Raw', + 'debug[all]':'Debug Dual Gyro Raw', 'debug[0]':'Gyro 1 Raw [roll]', 'debug[1]':'Gyro 1 Raw [pitch]', 'debug[2]':'Gyro 2 Raw [roll]', 'debug[3]':'Gyro 2 Raw [pitch]', }, 'DUAL_GYRO_COMBINED': { - 'debug[all]':'Debug Dual Combined', + 'debug[all]':'Debug Dual Combined', 'debug[0]':'Not Used', 'debug[1]':'Gyro Filtered [roll]', 'debug[2]':'Gyro Filtered [pitch]', 'debug[3]':'Not Used', }, 'DUAL_GYRO_DIFF': { - 'debug[all]':'Debug Dual Gyro Diff', + 'debug[all]':'Debug Dual Gyro Diff', 'debug[0]':'Gyro Diff [roll]', 'debug[1]':'Gyro Diff [pitch]', 'debug[2]':'Gyro Diff [yaw]', @@ -453,14 +453,14 @@ function FlightLogFieldPresenter() { 'debug[3]':'Gyro Pre-Dyn [dbg-axis]', }, 'DSHOT_RPM_TELEMETRY' : { - 'debug[all]':'DShot Telemetry RPM', + 'debug[all]':'DShot Telemetry RPM', 'debug[0]':'Motor 1 - DShot', 'debug[1]':'Motor 2 - DShot', 'debug[2]':'Motor 3 - DShot', 'debug[3]':'Motor 4 - DShot', }, 'RPM_FILTER' : { - 'debug[all]':'RPM Filter', + 'debug[all]':'RPM Filter', 'debug[0]':'Motor 1 - rpmFilter', 'debug[1]':'Motor 2 - rpmFilter', 'debug[2]':'Motor 3 - rpmFilter', @@ -495,63 +495,63 @@ function FlightLogFieldPresenter() { 'debug[3]':'Gyro 2 [pitch]', }, 'DSHOT_RPM_ERRORS' : { - 'debug[all]':'DSHOT RPM Error', + 'debug[all]':'DSHOT RPM Error', 'debug[0]':'DSHOT RPM Error [1]', 'debug[1]':'DSHOT RPM Error [2]', 'debug[2]':'DSHOT RPM Error [3]', 'debug[3]':'DSHOT RPM Error [4]', }, 'CRSF_LINK_STATISTICS_UPLINK' : { - 'debug[all]':'CRSF Stats Uplink', + 'debug[all]':'CRSF Stats Uplink', 'debug[0]':'Uplink RSSI 1', 'debug[1]':'Uplink RSSI 2', 'debug[2]':'Uplink Link Quality', 'debug[3]':'RF Mode', }, 'CRSF_LINK_STATISTICS_PWR' : { - 'debug[all]':'CRSF Stats Power', + 'debug[all]':'CRSF Stats Power', 'debug[0]':'Antenna', 'debug[1]':'SNR', 'debug[2]':'TX Power', 'debug[3]':'Not Used', }, 'CRSF_LINK_STATISTICS_DOWN' : { - 'debug[all]':'CRSF Stats Downlink', + 'debug[all]':'CRSF Stats Downlink', 'debug[0]':'Downlink RSSI', 'debug[1]':'Downlink Link Quality', 'debug[2]':'Downlink SNR', 'debug[3]':'Not Used', }, 'BARO' : { - 'debug[all]':'Debug Barometer', + 'debug[all]':'Debug Barometer', 'debug[0]':'Baro State', 'debug[1]':'Baro Temperature', 'debug[2]':'Baro Pressure', 'debug[3]':'Baro Pressure Sum', }, 'GPS_RESCUE_THROTTLE_PID' : { - 'debug[all]':'GPS Rescue Throttle PID', + 'debug[all]':'GPS Rescue Throttle PID', 'debug[0]':'Throttle P', 'debug[1]':'Throttle I', 'debug[2]':'Throttle D', 'debug[3]':'Z Velocity', }, 'DYN_IDLE' : { - 'debug[all]':'Dyn Idle', + 'debug[all]':'Dyn Idle', 'debug[0]':'Motor Range Min Inc', 'debug[1]':'Target RPS Change Rate', 'debug[2]':'Error', 'debug[3]':'Min RPM', }, 'FF_LIMIT' : { - 'debug[all]':'FF Limit', + 'debug[all]':'FF Limit', 'debug[0]':'FF input [roll]', 'debug[1]':'FF input [pitch]', 'debug[2]':'FF limited [roll]', 'debug[3]':'Not Used', }, 'FF_INTERPOLATED' : { - 'debug[all]':'FF Interpolated [roll]', + 'debug[all]':'FF Interpolated [roll]', 'debug[0]':'Setpoint Delta Impl [roll]', 'debug[1]':'Boost amount [roll]', 'debug[2]':'Boost amount, clipped [roll]', @@ -650,7 +650,7 @@ function FlightLogFieldPresenter() { }, 'GPS_RESCUE_HEADING' : { 'debug[all]':'GPS Rescue Heading', - 'debug[0]':'Ground speed', + 'debug[0]':'Ground Speed', 'debug[1]':'GPS Heading', 'debug[2]':'IMU Attitude', 'debug[3]':'Angle to home', @@ -782,9 +782,9 @@ function FlightLogFieldPresenter() { printedFlag = false, i, result = ""; - + i = 0; - + while (flags > 0) { if ((flags & 1) != 0) { if (printedFlag) { @@ -795,11 +795,11 @@ function FlightLogFieldPresenter() { result += flagNames[i]; } - + flags >>= 1; i++; } - + if (printedFlag) { return result; } else { @@ -816,12 +816,12 @@ function FlightLogFieldPresenter() { if ((1 << i) & (flags ^ lastFlags)) { // State Changed eventState += '|' + flagNames[i] + ' ' + (((1 << i) & flags) ? 'ON' : 'OFF'); found = true; - } + } } if (!found) { eventState += ' | ACRO'; } // Catch the state when all flags are off, which is ACRO of course return eventState; }; - + FlightLogFieldPresenter.presentEnum = function presentEnum(value, enumNames) { if (enumNames[value] === undefined) { return value; @@ -833,7 +833,7 @@ function FlightLogFieldPresenter() { /** * Attempt to decode the given raw logged value into something more human readable, or return an empty string if * no better representation is available. - * + * * @param fieldName Name of the field * @param value Value of the field */ @@ -841,28 +841,28 @@ function FlightLogFieldPresenter() { if (value === undefined) { return ""; } - + const highResolutionScale = (flightLog && flightLog.getSysConfig().blackbox_high_resolution > 0) ? 10 : 1; const highResolutionAddPrecision = (flightLog && flightLog.getSysConfig().blackbox_high_resolution > 0) ? 1 : 0; switch (fieldName) { case 'time': return formatTime(value / 1000, true); - + case 'gyroADC[0]': case 'gyroADC[1]': case 'gyroADC[2]': - return flightLog.gyroRawToDegreesPerSecond(value / highResolutionScale).toFixed(highResolutionAddPrecision) + " deg/s"; - + return flightLog.gyroRawToDegreesPerSecond(value / highResolutionScale).toFixed(highResolutionAddPrecision) + " °/s"; + case 'gyroADCs[0]': case 'gyroADCs[1]': case 'gyroADCs[2]': - return value.toFixed(0) + " deg/s"; + return value.toFixed(0) + " °/s"; case 'axisError[0]': case 'axisError[1]': case 'axisError[2]': - return (value / highResolutionScale).toFixed(highResolutionAddPrecision) + " deg/s"; + return (value / highResolutionScale).toFixed(highResolutionAddPrecision) + " °/s"; case 'rcCommand[0]': case 'rcCommand[1]': @@ -894,7 +894,7 @@ function FlightLogFieldPresenter() { case 'rcCommands[0]': case 'rcCommands[1]': case 'rcCommands[2]': - return (value / highResolutionScale).toFixed(highResolutionAddPrecision) + " deg/s"; + return (value / highResolutionScale).toFixed(highResolutionAddPrecision) + " °/s"; case 'rcCommands[3]': return value.toFixed(1) + "%"; @@ -913,55 +913,55 @@ function FlightLogFieldPresenter() { case 'axisF[0]': case 'axisF[1]': case 'axisF[2]': - return flightLog.getPIDPercentage(value).toFixed(1) + "%"; + return flightLog.getPIDPercentage(value).toFixed(1) + " %"; case 'accSmooth[0]': case 'accSmooth[1]': case 'accSmooth[2]': - return flightLog.accRawToGs(value).toFixed(2 + highResolutionAddPrecision) + "g"; - + return flightLog.accRawToGs(value).toFixed(2 + highResolutionAddPrecision) + " g"; + case 'vbatLatest': if (flightLog.getSysConfig().firmwareType === FIRMWARE_TYPE_BETAFLIGHT && semver.gte(flightLog.getSysConfig().firmwareVersion, '4.0.0')) { - return (value / 100).toFixed(2) + "V" + ", " + (value / 100 / flightLog.getNumCellsEstimate()).toFixed(2) + "V/cell"; + return (value / 100).toFixed(2) + "V" + ", " + (value / 100 / flightLog.getNumCellsEstimate()).toFixed(2) + " V/cell"; } else if ((flightLog.getSysConfig().firmwareType === FIRMWARE_TYPE_BETAFLIGHT && semver.gte(flightLog.getSysConfig().firmwareVersion, '3.1.0')) || (flightLog.getSysConfig().firmwareType === FIRMWARE_TYPE_CLEANFLIGHT && semver.gte(flightLog.getSysConfig().firmwareVersion, '2.0.0'))) { - return (value / 10).toFixed(2) + "V" + ", " + (value / 10 / flightLog.getNumCellsEstimate()).toFixed(2) + "V/cell"; + return (value / 10).toFixed(2) + "V" + ", " + (value / 10 / flightLog.getNumCellsEstimate()).toFixed(2) + " V/cell"; } else { - return (flightLog.vbatADCToMillivolts(value) / 1000).toFixed(2) + "V" + ", " + (flightLog.vbatADCToMillivolts(value) / 1000 / flightLog.getNumCellsEstimate()).toFixed(2) + "V/cell"; + return (flightLog.vbatADCToMillivolts(value) / 1000).toFixed(2) + "V" + ", " + (flightLog.vbatADCToMillivolts(value) / 1000 / flightLog.getNumCellsEstimate()).toFixed(2) + " V/cell"; } case 'amperageLatest': if ((flightLog.getSysConfig().firmwareType == FIRMWARE_TYPE_BETAFLIGHT && semver.gte(flightLog.getSysConfig().firmwareVersion, '3.1.7')) || (flightLog.getSysConfig().firmwareType == FIRMWARE_TYPE_CLEANFLIGHT && semver.gte(flightLog.getSysConfig().firmwareVersion, '2.0.0'))) { - return (value / 100).toFixed(2) + "A" + ", " + (value / 100 / flightLog.getNumMotors()).toFixed(2) + "A/motor"; + return (value / 100).toFixed(2) + "A" + ", " + (value / 100 / flightLog.getNumMotors()).toFixed(2) + " A/motor"; } else if (flightLog.getSysConfig().firmwareType == FIRMWARE_TYPE_BETAFLIGHT && semver.gte(flightLog.getSysConfig().firmwareVersion, '3.1.0')) { - return (value / 100).toFixed(2) + "A" + ", " + (value / 100 / flightLog.getNumMotors()).toFixed(2) + "A/motor"; + return (value / 100).toFixed(2) + "A" + ", " + (value / 100 / flightLog.getNumMotors()).toFixed(2) + " A/motor"; } else { - return (flightLog.amperageADCToMillivolts(value) / 1000).toFixed(2) + "A" + ", " + (flightLog.amperageADCToMillivolts(value) / 1000 / flightLog.getNumMotors()).toFixed(2) + "A/motor"; + return (flightLog.amperageADCToMillivolts(value) / 1000).toFixed(2) + "A" + ", " + (flightLog.amperageADCToMillivolts(value) / 1000 / flightLog.getNumMotors()).toFixed(2) + " A/motor"; } case 'heading[0]': case 'heading[1]': case 'heading[2]': return (value / Math.PI * 180).toFixed(1) + "°"; - + case 'BaroAlt': - return (value / 100).toFixed(1) + "m"; - + return (value / 100).toFixed(1) + " m"; + case 'flightModeFlags': return FlightLogFieldPresenter.presentFlags(value, FLIGHT_LOG_FLIGHT_MODE_NAME); - + case 'stateFlags': return FlightLogFieldPresenter.presentFlags(value, FLIGHT_LOG_FLIGHT_STATE_NAME); - + case 'failsafePhase': return FlightLogFieldPresenter.presentEnum(value, FLIGHT_LOG_FAILSAFE_PHASE_NAME); - + case 'features': - return FlightLogFieldPresenter.presentEnum(value, FLIGHT_LOG_FEATURES); + return FlightLogFieldPresenter.presentEnum(value, FLIGHT_LOG_FEATURES); case 'rssi': - return (value / 1024 * 100).toFixed(2) + "%"; + return (value / 1024 * 100).toFixed(2) + " %"; case 'debug[0]': case 'debug[1]': @@ -973,7 +973,7 @@ function FlightLogFieldPresenter() { return ""; } }; - + FlightLogFieldPresenter.decodeDebugFieldToFriendly = function(flightLog, fieldName, value, currentFlightMode) { if (flightLog) { const debugModeName = DEBUG_MODE[flightLog.getSysConfig().debug_mode]; // convert to recognisable name @@ -986,7 +986,7 @@ function FlightLogFieldPresenter() { case 'CYCLETIME': switch (fieldName) { case 'debug[1]': - return value.toFixed(0) + "%"; + return value.toFixed(0) + " %"; default: return value.toFixed(0) + "\u03BCS"; } @@ -995,20 +995,20 @@ function FlightLogFieldPresenter() { case 'debug[0]': return value.toFixed(0); default: - return (value / 10).toFixed(1) + "V"; + return (value / 10).toFixed(1) + " V"; } case 'ACCELEROMETER': - return flightLog.accRawToGs(value).toFixed(2) + "g"; + return flightLog.accRawToGs(value).toFixed(2) + " g"; case 'MIXER': return Math.round(flightLog.rcCommandRawToThrottle(value)) + " %"; - case 'PIDLOOP': - return value.toFixed(0) + "\u03BCS"; + case 'PIDLOOP': + return value.toFixed(0) + " \u03BCS"; case 'RC_INTERPOLATION': switch (fieldName) { case 'debug[1]': // current RX refresh rate - return value.toFixed(0) + 'ms'; + return value.toFixed(0) + ' ms'; case 'debug[3]': // setpoint [roll] - return value.toFixed(0) + 'deg/s'; + return value.toFixed(0) + " °/s"; default: return value.toFixed(0); } @@ -1020,30 +1020,41 @@ function FlightLogFieldPresenter() { case 'DUAL_GYRO_DIFF': case 'DUAL_GYRO_RAW': case 'NOTCH': - return Math.round(flightLog.gyroRawToDegreesPerSecond(value)) + "deg/s"; + return Math.round(flightLog.gyroRawToDegreesPerSecond(value)) + " °/s"; case 'ANGLERATE': - return value.toFixed(0) + "deg/s"; + return value.toFixed(0) + " °/s"; case 'ESC_SENSOR': switch (fieldName) { case 'debug[3]': - return value.toFixed(0) + "\u03BCS"; + return value.toFixed(0) + " \u03BCS"; default: return value.toFixed(0); } case 'SCHEDULER': - return value.toFixed(0) + "\u03BCS"; + return value.toFixed(0) + " \u03BCS"; case 'STACK': return value.toFixed(0); case 'ESC_SENSOR_RPM': - return value.toFixed(0) + "rpm"; + return value.toFixed(0) + " rpm"; case 'ESC_SENSOR_TMP': - return value.toFixed(0) + "°C"; + return value.toFixed(0) + " °C"; + case 'ALTITUDE': + switch (fieldName) { + case 'debug[0]': // GPS Trust * 100 + value.toFixed(0); + case 'debug[1]': // GPS Altitude cm + case 'debug[2]': // OSD Altitude cm + case 'debug[3]': // Control Altitude + return (value / 100).toFixed(2) + ' m'; + default: + return value.toFixed(0); + } case 'FFT': switch (fieldName) { case 'debug[0]': // gyro pre dyn notch [for gyro debug axis] case 'debug[1]': // gyro post dyn notch [for gyro debug axis] case 'debug[2]': // gyro pre dyn notch, downsampled for FFT [for gyro debug axis] - return Math.round(flightLog.gyroRawToDegreesPerSecond(value)) + " deg/s"; + return Math.round(flightLog.gyroRawToDegreesPerSecond(value)) + " °/s"; // debug 3 = not used default: return value.toFixed(0); @@ -1062,25 +1073,26 @@ function FlightLogFieldPresenter() { case 'FFT_FREQ': switch (fieldName) { case 'debug[3]': // gyro pre dyn notch [for gyro debug axis] - return Math.round(flightLog.gyroRawToDegreesPerSecond(value)) + " deg/s"; + return Math.round(flightLog.gyroRawToDegreesPerSecond(value)) + " °/s"; default: return value.toFixed(0) + " Hz"; } case 'RTH': switch (fieldName) { - case 'debug[0]': // pitch angle +/-4000 means +/- 40 deg - return (value / 100).toFixed(1) + 'deg'; +// temporarily, perhaps +// case 'debug[0]': // pitch angle +/-4000 means +/- 40 deg +// return (value / 100).toFixed(1) + " °"; default: return value.toFixed(0); } case 'ITERM_RELAX': switch (fieldName) { case 'debug[0]': // roll setpoint high-pass filtered - return value.toFixed(0) + 'deg/s'; + return value.toFixed(0) + " °/s"; case 'debug[1]': // roll I-term relax factor - return value.toFixed(0) + '%'; + return value.toFixed(0) + ' %'; case 'debug[3]': // roll absolute control axis error - return (value / 10).toFixed(1) + 'deg'; + return (value / 10).toFixed(1) + " °"; default: return value.toFixed(0); } @@ -1089,7 +1101,7 @@ function FlightLogFieldPresenter() { case 'debug[0]': return (value + 1500).toFixed(0) + " us"; case 'debug[3]': // rx frame rate [us] - return (value / 1000).toFixed(1) + 'ms'; + return (value / 1000).toFixed(1) + ' ms'; default: return value.toFixed(0); } @@ -1097,19 +1109,19 @@ function FlightLogFieldPresenter() { switch (fieldName) { case 'debug[0]': // current frame rate [us] case 'debug[2]': // average frame rate [us] - return (value / 1000).toFixed(2) + 'ms'; + return (value / 1000).toFixed(2) + ' ms'; default: return value.toFixed(0); } case 'DSHOT_RPM_TELEMETRY': - return (value * 200 / flightLog.getSysConfig()['motor_poles']).toFixed(0) + "rpm / " + (value * 3.333 / flightLog.getSysConfig()['motor_poles']).toFixed(0) + 'hz'; + return (value * 200 / flightLog.getSysConfig()['motor_poles']).toFixed(0) + " rpm / " + (value * 3.333 / flightLog.getSysConfig()['motor_poles']).toFixed(0) + ' hz'; case 'RPM_FILTER': - return (value * 60).toFixed(0) + "rpm / " + value.toFixed(0) + "Hz"; + return (value * 60).toFixed(0) + "rpm / " + value.toFixed(0) + " Hz"; case 'D_MIN': switch (fieldName) { case 'debug[0]': // roll gyro factor case 'debug[1]': // roll setpoint Factor - return value.toFixed(0) + '%'; + return value.toFixed(0) + ' %'; case 'debug[2]': // roll actual D case 'debug[3]': // pitch actual D return (value / 10).toFixed(1); @@ -1120,26 +1132,26 @@ function FlightLogFieldPresenter() { switch (fieldName) { case 'debug[0]': // gyro scaled [for selected axis] case 'debug[3]': // pre-dyn notch gyro [for selected axis] - return Math.round(flightLog.gyroRawToDegreesPerSecond(value)) + "deg/s"; + return Math.round(flightLog.gyroRawToDegreesPerSecond(value)) + " °/s"; default: - return value.toFixed(0) + "Hz"; + return value.toFixed(0) + " Hz"; } case 'DYN_IDLE': switch (fieldName) { case 'debug[3]': // minRPS - return (value * 6) + 'rpm / ' + (value / 10).toFixed(0) +'hz'; + return (value * 6) + ' rpm / ' + (value / 10).toFixed(0) +' hz'; default: return value.toFixed(0); } case 'AC_CORRECTION': - return (value / 10).toFixed(1) + 'deg/s'; + return (value / 10).toFixed(1) + " °/s"; case 'AC_ERROR': - return (value / 10).toFixed(1) + 'deg'; + return (value / 10).toFixed(1) + " °"; case 'RX_TIMING': switch (fieldName) { case 'debug[0]': // Frame delta us/10 case 'debug[1]': // Frame age us/10 - return (value / 100).toFixed(2) + 'ms'; + return (value / 100).toFixed(2) + ' ms'; default: return value.toFixed(0); } @@ -1149,7 +1161,7 @@ function FlightLogFieldPresenter() { // debug 1 is unknown frame count 0 to int16_t // debug 2 is RSSI 0 to -128 -> 0 to 128 case 'debug[3]': // LQ 0-100 - return value.toFixed(0) + '%'; + return value.toFixed(0) + ' %'; default: return value.toFixed(0); } @@ -1166,7 +1178,7 @@ function FlightLogFieldPresenter() { case 'debug[0]': // cycle time in us*10 case 'debug[2]': // task delay time in us*10 case 'debug[3]': // task delay time in us*10 - return (value / 10).toFixed(1) + 'us'; + return (value / 10).toFixed(1) + ' us'; // debug 1 is task ID of late task default: return value.toFixed(0); @@ -1174,16 +1186,16 @@ function FlightLogFieldPresenter() { case 'TIMING_ACCURACY': switch (fieldName) { case 'debug[0]': // CPU Busy % - return value.toFixed(1) + '%'; + return value.toFixed(1) + ' %'; case 'debug[2]': // task delay time in us*10 - return (value / 10).toFixed(1) + 'us'; + return (value / 10).toFixed(1) + ' us'; default: return value.toFixed(0); } case 'RX_EXPRESSLRS_SPI': switch (fieldName) { case 'debug[3]': // uplink LQ % - return value.toFixed(1) + '%'; + return value.toFixed(1) + ' %'; // debug 0 = Lost connection count // debug 1 = RSSI // debug 2 = SNR @@ -1193,21 +1205,21 @@ function FlightLogFieldPresenter() { case 'RX_EXPRESSLRS_PHASELOCK': switch (fieldName) { case 'debug[2]': // Frequency offset in ticks - return value.toFixed(0) + 'ticks'; + return value.toFixed(0) + ' ticks'; // debug 0 = Phase offset us // debug 1 = Filtered phase offset us // debug 3 = Pphase shift in us default: - return value.toFixed(0) + 'us'; + return value.toFixed(0) + ' us'; } case 'GPS_RESCUE_THROTTLE_PID': switch (fieldName) { case 'debug[0]': // Throttle P added uS case 'debug[1]': // Throttle D added * uS - return value.toFixed(0) + 'uS'; + return value.toFixed(0) + ' uS'; case 'debug[2]': // current altitude in m case 'debug[3]': // TARGET altitude in m - return (value / 100).toFixed(1) + 'm'; + return (value / 100).toFixed(1) + ' m'; default: return value.toFixed(0); } @@ -1215,21 +1227,21 @@ function FlightLogFieldPresenter() { switch (fieldName) { case 'debug[0]': // Pitch P degrees * 100 case 'debug[1]': // Pitch D degrees * 100 - return (value / 100).toFixed(1) + 'deg'; + return (value / 100).toFixed(1) + " °"; case 'debug[2]': // velocity to home cm/s case 'debug[3]': // velocity target cm/s - return (value / 100).toFixed(1) + 'm/s'; + return (value / 100).toFixed(1) + ' m/s'; default: return value.toFixed(0); } case 'GPS_RESCUE_HEADING': switch (fieldName) { - case 'debug[0]': // Ground speed cm/s - return (value / 100).toFixed(2) + 'm/s'; + case 'debug[0]': // Ground speed cm/s + return (value / 100).toFixed(2) + ' m/s'; case 'debug[1]': // GPS Ground course degrees * 10 case 'debug[2]': // Attitude in degrees * 10 case 'debug[3]': // Angle to home in degrees * 10 - return (value / 10).toFixed(1) + 'deg'; + return (value / 10).toFixed(1) + " °"; default: return value.toFixed(0); } @@ -1237,10 +1249,10 @@ function FlightLogFieldPresenter() { switch (fieldName) { case 'debug[0]': // velocity to home cm/s case 'debug[1]': // velocity target cm/s - return (value / 100).toFixed(1) + 'm/s'; + return (value / 100).toFixed(1) + ' m/s'; case 'debug[2]': // altitude cm case 'debug[3]': // altitude target cm - return (value / 100).toFixed(1) + 'm'; + return (value / 100).toFixed(1) + ' m'; default: return value.toFixed(0); } @@ -1258,7 +1270,7 @@ function FlightLogFieldPresenter() { } return ""; }; - + FlightLogFieldPresenter.fieldNameToFriendly = function(fieldName, debugMode) { if (debugMode) { if (fieldName.includes('debug')) { @@ -1277,12 +1289,12 @@ function FlightLogFieldPresenter() { } return debugFields[fieldName]; - } + } } if (FRIENDLY_FIELD_NAMES[fieldName]) { return FRIENDLY_FIELD_NAMES[fieldName]; } - + return fieldName; }; })(); diff --git a/js/graph_config.js b/js/graph_config.js index 534f03e4..c155a920 100644 --- a/js/graph_config.js +++ b/js/graph_config.js @@ -5,13 +5,13 @@ function GraphConfig(graphConfig) { graphs = graphConfig ? graphConfig : [], listeners = [], that = this; - + function notifyListeners() { for (var i = 0; i < listeners.length; i++) { listeners[i](that); } } - + this.selectedFieldName = null; this.selectedGraphIndex = 0; this.selectedFieldIndex = 0; @@ -22,62 +22,61 @@ function GraphConfig(graphConfig) { this.getGraphs = function() { return graphs; }; - + /** * newGraphs is an array of objects like {label: "graph label", height:, fields:[{name: curve:{offset:, power:, inputRange:, outputRange:, steps:}, color:, }, ...]} */ this.setGraphs = function(newGraphs) { graphs = newGraphs; - + notifyListeners(); }; - + /** * Convert the given graph configs to make them appropriate for the given flight log. */ this.adaptGraphs = function(flightLog, graphs) { - var + var logFieldNames = flightLog.getMainFieldNames(), - + // Make copies of graphs into here so we can modify them without wrecking caller's copy newGraphs = []; - + for (var i = 0; i < graphs.length; i++) { - var + var graph = graphs[i], newGraph = $.extend( // Default values for missing properties: { height: 1, - }, + }, // The old graph - graph, + graph, // New fields to replace the old ones: { fields:[], }, ), colorIndex = 0; - + for (var j = 0; j < graph.fields.length; j++) { var field = graph.fields[j], matches; - + var adaptField = function(field, colorIndexOffset, forceNewCurve) { const defaultCurve = GraphConfig.getDefaultCurveForField(flightLog, field.name); - if (field.curve === undefined || forceNewCurve) { field.curve = defaultCurve; } else { - /* The curve may have been originally created for a craft with different endpoints, so use the + /* The curve may have been originally created for a craft with different endpoints, so use the * recommended offset and input range instead of the provided one. */ field.curve.offset = defaultCurve.offset; field.curve.inputRange = defaultCurve.inputRange; } - + if(colorIndexOffset!=null && field.color != undefined) { // auto offset the actual color (to expand [all] selections) var index; for(index=0; index < GraphConfig.PALETTE.length; index++) @@ -91,20 +90,20 @@ function GraphConfig(graphConfig) { field.color = GraphConfig.PALETTE[colorIndex % GraphConfig.PALETTE.length].color; colorIndex++; } - + if (field.smoothing === undefined) { field.smoothing = GraphConfig.getDefaultSmoothingForField(flightLog, field.name); } - + return field; }; - + if ((matches = field.name.match(/^(.+)\[all\]$/))) { - var + var nameRoot = matches[1], nameRegex = new RegExp("^" + nameRoot + "\[[0-9]+\]$"), colorIndexOffset = 0; - + for (var k = 0; k < logFieldNames.length; k++) { if (logFieldNames[k].match(nameRegex)) { // add special condition for rcCommands and debug as each of the fields requires a different scaling. @@ -120,13 +119,13 @@ function GraphConfig(graphConfig) { } } } - + newGraphs.push(newGraph); } - + this.setGraphs(newGraphs); }; - + this.addListener = function(listener) { listeners.push(listener); }; @@ -153,12 +152,12 @@ GraphConfig.load = function(config) { if (config) { for (var i = 0; i < config.length; i++) { var graph = config[i]; - + for (var j = 0; j < graph.fields.length; j++) { - var + var field = graph.fields[j], matches; - + if ((matches = field.name.match(/^gyroData(.+)$/))) { field.name = "gyroADC" + matches[1]; } @@ -167,7 +166,7 @@ GraphConfig.load = function(config) { } else { config = false; } - + return config; }; @@ -189,7 +188,6 @@ GraphConfig.load = function(config) { } } catch (e) { return 0;} }; - GraphConfig.getDefaultCurveForField = function(flightLog, fieldName) { var @@ -203,19 +201,19 @@ GraphConfig.load = function(config) { sysConfig["rates"][1] * 10.0 * scale, sysConfig["rates"][2] * 10.0 * scale); default: - return Math.max(flightLog.rcCommandRawToDegreesPerSecond(500,0) * scale, - flightLog.rcCommandRawToDegreesPerSecond(500,1) * scale, + return Math.max(flightLog.rcCommandRawToDegreesPerSecond(500,0) * scale, + flightLog.rcCommandRawToDegreesPerSecond(500,1) * scale, flightLog.rcCommandRawToDegreesPerSecond(500,2) * scale); } } - + var getMinMaxForFields = function(/* fieldName1, fieldName2, ... */) { // helper to make a curve scale based on the combined min/max of one or more fields var stats = flightLog.getStats(), min = Number.MAX_VALUE, max = Number.MIN_VALUE; - + for(var i in arguments) { var fieldIndex = flightLog.getMainFieldIndexByName(arguments[i]), @@ -303,7 +301,7 @@ GraphConfig.load = function(config) { return { offset: 0, power: 0.25, /* Make this 1.0 to scale linearly */ - inputRange: maxDegreesSecond(gyroScaleMargin * highResolutionScale), // Maximum grad/s + 20% + inputRange: maxDegreesSecond(gyroScaleMargin * highResolutionScale), // Maximum grad/s + 20% outputRange: 1.0 }; } else if (fieldName.match(/^axis.+\[/)) { @@ -324,7 +322,7 @@ GraphConfig.load = function(config) { return { offset: 0, power: 0.25, - inputRange: 500 * highResolutionScale * gyroScaleMargin, // +20% to let compare in the same scale with the rccommands + inputRange: 500 * highResolutionScale * gyroScaleMargin, // +20% to let compare in the same scale with the rccommands outputRange: 1.0 }; } else if (fieldName == "heading[2]") { @@ -357,7 +355,7 @@ GraphConfig.load = function(config) { }; } else if (fieldName.match(/^debug.*/) && sysConfig.debug_mode!=null) { - var debugModeName = DEBUG_MODE[sysConfig.debug_mode]; + var debugModeName = DEBUG_MODE[sysConfig.debug_mode]; switch (debugModeName) { case 'CYCLETIME': switch (fieldName) { @@ -367,7 +365,7 @@ GraphConfig.load = function(config) { power: 1, inputRange: 50, outputRange: 1.0 - }; + }; default: return { offset: -1000, // zero offset @@ -376,13 +374,13 @@ GraphConfig.load = function(config) { outputRange: 1.0 }; } - case 'PIDLOOP': + case 'PIDLOOP': return { offset: -250, // zero offset power: 1.0, inputRange: 250, // 0-500uS outputRange: 1.0 - }; + }; case 'GYRO': case 'GYRO_FILTERED': case 'GYRO_SCALED': @@ -422,7 +420,7 @@ GraphConfig.load = function(config) { power: 1, inputRange: 2048, outputRange: 1.0 - }; + }; default: return { offset: -130, @@ -445,7 +443,7 @@ GraphConfig.load = function(config) { return { offset: 0, power: 0.25, - inputRange: 500 * gyroScaleMargin, // +20% to let compare in the same scale with the rccommands + inputRange: 500 * gyroScaleMargin, // +20% to let compare in the same scale with the rccommands outputRange: 1.0 }; case 'debug[1]': // raw RC command derivative @@ -521,7 +519,7 @@ GraphConfig.load = function(config) { power: 1.0, inputRange: 100, outputRange: 1.0 - }; + }; case 'ESC_SENSOR_RPM': case 'DSHOT_RPM_TELEMETRY': case 'RPM_FILTER': @@ -695,7 +693,7 @@ GraphConfig.load = function(config) { inputRange: 50, outputRange: 1.0, }; - case 'debug[2]': // total delay in last second + case 'debug[2]': // total delay in last second return { offset: -500, power: 1.0, @@ -788,7 +786,7 @@ GraphConfig.load = function(config) { inputRange: 10000, outputRange: 1.0, }; - case 'debug[1]': // GPS GroundCourse + case 'debug[1]': // GPS GroundCourse case 'debug[2]': // Yaw attitude * 10 case 'debug[3]': // Angle to home * 10 return { @@ -910,10 +908,10 @@ GraphConfig.load = function(config) { }; } }; - + /** * Get an array of suggested graph configurations will be usable for the fields available in the given flightlog. - * + * * Supply an array of strings `graphNames` to only fetch the graph with the given names. */ GraphConfig.getExampleGraphConfigs = function(flightLog, graphNames) { diff --git a/js/imu.js b/js/imu.js index 7580c3f8..2b44ee8b 100644 --- a/js/imu.js +++ b/js/imu.js @@ -8,29 +8,29 @@ function IMU(copyFrom) { // Constants: var RAD = Math.PI / 180.0, - + ROLL = 0, PITCH = 1, YAW = 2, THROTTLE = 3, - + X = 0, Y = 1, Z = 2, - + //Settings that would normally be set by the user in MW config: gyro_cmpf_factor = 600, gyro_cmpfm_factor = 250, accz_lpf_cutoff = 5.0, - magneticDeclination = 2519, - + magneticDeclination = 0, // user to set to local declination in degrees * 10 + //Calculate RC time constant used in the accZ lpf: fc_acc = 0.5 / (Math.PI * accz_lpf_cutoff), - + INV_GYR_CMPF_FACTOR = 1.0 / (gyro_cmpf_factor + 1.0), INV_GYR_CMPFM_FACTOR = 1.0 / (gyro_cmpfm_factor + 1.0); - + // ************************************************** // Simplified IMU based on "Complementary Filter" // Inspired by http://starlino.com/imu_guide.html @@ -44,37 +44,37 @@ function IMU(copyFrom) { // for heading approximation. // // ************************************************** - + function normalizeVector(src, dest) { var length = Math.sqrt(src.X * src.X + src.Y * src.Y + src.Z * src.Z); - + if (length !== 0) { dest.X = src.X / length; dest.Y = src.Y / length; dest.Z = src.Z / length; } } - + function rotateVector(v, delta) { // This does a "proper" matrix rotation using gyro deltas without small-angle approximation - var + var v_tmp = {X:v.X, Y:v.Y, Z:v.Z}, mat = [[0,0,0],[0,0,0],[0,0,0]], cosx, sinx, cosy, siny, cosz, sinz, coszcosx, sinzcosx, coszsinx, sinzsinx; - + cosx = Math.cos(delta[ROLL]); sinx = Math.sin(delta[ROLL]); cosy = Math.cos(delta[PITCH]); siny = Math.sin(delta[PITCH]); cosz = Math.cos(delta[YAW]); sinz = Math.sin(delta[YAW]); - + coszcosx = cosz * cosx; sinzcosx = sinz * cosx; coszsinx = sinx * cosz; sinzsinx = sinx * sinz; - + mat[0][0] = cosz * cosy; mat[0][1] = -cosy * sinz; mat[0][2] = siny; @@ -84,16 +84,16 @@ function IMU(copyFrom) { mat[2][0] = (sinzsinx) - (coszcosx * siny); mat[2][1] = (coszsinx) + (sinzcosx * siny); mat[2][2] = cosy * cosx; - + v.X = v_tmp.X * mat[0][0] + v_tmp.Y * mat[1][0] + v_tmp.Z * mat[2][0]; v.Y = v_tmp.X * mat[0][1] + v_tmp.Y * mat[1][1] + v_tmp.Z * mat[2][1]; v.Z = v_tmp.X * mat[0][2] + v_tmp.Y * mat[1][2] + v_tmp.Z * mat[2][2]; } - + // Rotate the accel values into the earth frame and subtract acceleration due to gravity from the result function calculateAccelerationInEarthFrame(accSmooth, attitude, acc_1G) { - var + var rpy = [ -attitude.roll, -attitude.pitch, @@ -104,61 +104,62 @@ function IMU(copyFrom) { Y: accSmooth[1], Z: accSmooth[2] }; - + rotateVector(result, rpy); - + result.Z -= acc_1G; - + return result; } - - // Use the craft's estimated roll/pitch to compensate for the roll/pitch of the magnetometer reading + + // Use the craft's estimated roll/pitch to compensate for the roll/pitch of the magnetometer reading function calculateHeading(vec, roll, pitch) { - var + var cosineRoll = Math.cos(roll), sineRoll = Math.sin(roll), cosinePitch = Math.cos(pitch), sinePitch = Math.sin(pitch), - + headingX = vec.X * cosinePitch + vec.Y * sineRoll * sinePitch + vec.Z * sinePitch * cosineRoll, headingY = vec.Y * cosineRoll - vec.Z * sineRoll, - heading = Math.atan2(headingY, headingX) + magneticDeclination / 10.0 * RAD; - - if (heading < 0) - heading += 2 * Math.PI; - + heading = Math.atan2(headingY, headingX) + magneticDeclination / 10.0 * RAD; // RAD = pi/180 + + heading += 2 * Math.PI; // positive all the time, we want zero to return pi + if (heading > 2* Math.PI) + heading -= 2* Math.PI; + return heading; } - + /** * Using the given raw data, update the IMU state and return the new estimate for the attitude. */ this.updateEstimatedAttitude = function(gyroADC, accSmooth, currentTime, acc_1G, gyroScale, magADC) { - var + var accMag = 0, deltaTime, - scale, + scale, deltaGyroAngle = [0,0,0]; - + if (this.previousTime === false) { deltaTime = 1; } else { deltaTime = currentTime - this.previousTime; } - + scale = deltaTime * gyroScale; this.previousTime = currentTime; - + // Initialization for (var axis = 0; axis < 3; axis++) { deltaGyroAngle[axis] = gyroADC[axis] * scale; - + accMag += accSmooth[axis] * accSmooth[axis]; } accMag = accMag * 100 / (acc_1G * acc_1G); - + rotateVector(this.estimateGyro, deltaGyroAngle); - + // Apply complimentary filter (Gyro drift correction) // If accel magnitude >1.15G or <0.85G and ACC vector outside of the limit range => we neutralize the effect of accelerometers in the angle estimation. // To do that, we just skip filter, as EstV already rotated by Gyro @@ -167,30 +168,30 @@ function IMU(copyFrom) { this.estimateGyro.Y = (this.estimateGyro.Y * gyro_cmpf_factor + accSmooth[1]) * INV_GYR_CMPF_FACTOR; this.estimateGyro.Z = (this.estimateGyro.Z * gyro_cmpf_factor + accSmooth[2]) * INV_GYR_CMPF_FACTOR; } - - var + + var attitude = { roll: Math.atan2(this.estimateGyro.Y, this.estimateGyro.Z), pitch: Math.atan2(-this.estimateGyro.X, Math.sqrt(this.estimateGyro.Y * this.estimateGyro.Y + this.estimateGyro.Z * this.estimateGyro.Z)) }; - + if (false && magADC) { //TODO temporarily disabled rotateVector(this.estimateMag, deltaGyroAngle); - + this.estimateMag.X = (this.estimateMag.X * gyro_cmpfm_factor + magADC[0]) * INV_GYR_CMPFM_FACTOR; this.estimateMag.Y = (this.estimateMag.Y * gyro_cmpfm_factor + magADC[1]) * INV_GYR_CMPFM_FACTOR; this.estimateMag.Z = (this.estimateMag.Z * gyro_cmpfm_factor + magADC[2]) * INV_GYR_CMPFM_FACTOR; - + attitude.heading = calculateHeading(this.estimateMag, attitude.roll, attitude.pitch); } else { rotateVector(this.EstN, deltaGyroAngle); normalizeVector(this.EstN, this.EstN); attitude.heading = calculateHeading(this.EstN, attitude.roll, attitude.pitch); } - + return attitude; }; - + if (copyFrom) { this.copyStateFrom(copyFrom); } else { @@ -212,7 +213,7 @@ IMU.prototype.copyStateFrom = function(that) { Y: that.estimateGyro.Y, Z: that.estimateGyro.Z }; - + this.estimateMag = { X: that.estimateMag.X, Y: that.estimateMag.Y, From 6944b89f56bbea334a2d5ff090f3e930ee0f546b Mon Sep 17 00:00:00 2001 From: ctzsnooze Date: Wed, 28 Sep 2022 09:20:01 +1000 Subject: [PATCH 2/2] fixes, thanks to @haslinghuis --- js/flightlog_fields_presenter.js | 2 +- js/imu.js | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/js/flightlog_fields_presenter.js b/js/flightlog_fields_presenter.js index 472e8f5a..3bdc8317 100644 --- a/js/flightlog_fields_presenter.js +++ b/js/flightlog_fields_presenter.js @@ -1041,7 +1041,7 @@ function FlightLogFieldPresenter() { case 'ALTITUDE': switch (fieldName) { case 'debug[0]': // GPS Trust * 100 - value.toFixed(0); + return value.toFixed(0); case 'debug[1]': // GPS Altitude cm case 'debug[2]': // OSD Altitude cm case 'debug[3]': // Control Altitude diff --git a/js/imu.js b/js/imu.js index 2b44ee8b..8f52f6b9 100644 --- a/js/imu.js +++ b/js/imu.js @@ -125,8 +125,9 @@ function IMU(copyFrom) { heading = Math.atan2(headingY, headingX) + magneticDeclination / 10.0 * RAD; // RAD = pi/180 heading += 2 * Math.PI; // positive all the time, we want zero to return pi - if (heading > 2* Math.PI) + if (heading > 2* Math.PI) { heading -= 2* Math.PI; + } return heading; }