diff --git a/locales/en/messages.json b/locales/en/messages.json index 69581428..fdb89071 100644 --- a/locales/en/messages.json +++ b/locales/en/messages.json @@ -3222,8 +3222,8 @@ "message": "Sliders to adjust the quad flight characteristics (PID gains)

Master Multiplier: Raises or Lowers all the PID gains (above) holding the proportional difference between the gains.

PD Balance: Adjusts the balance (ratio \\ proportional difference) between the P and D terms ('the spring' [p-term] and 'shock absorber' [d-term]).

PD Gain: Raises or Lowers the P&D gains together - holding the ratio (balance) between the two - for more (or less) PID control authority.

Stick Response Gain: Raises or Lowers the FeedForward gains to control the stick response feel of the quad.", "description": "Overall helpicon message for PID tuning sliders" }, - "pidTuningSliderHighWarning": { - "message": "CAUTION: Pushing sliders this high may cause flyaways, motor damage or unsafe craft behaviour. Please proceed with caution.", + "pidTuningSliderWarning": { + "message": "CAUTION: Current slider positions may cause flyaways, motor damage or unsafe craft behaviour. Please proceed with caution.", "description": "Warning shown when tuning slider are above safe limits" }, "pidTuningSlidersDisabled": { @@ -3234,6 +3234,10 @@ "message": "Enable Sliders", "description": "Button label for enabling sliders" }, + "pidTuningSlidersNonExpertMode": { + "message": "Note: Sliders range is restricted because you are not in expert mode. This range should be suitable for most builds and beginners.", + "description": "Sliders restricted message" + }, "pidTuningSliderLow": { "message": "Low", "description": "Tuning Slider Low header" diff --git a/src/css/tabs-dark/pid_tuning-dark.css b/src/css/tabs-dark/pid_tuning-dark.css index 43a3ee56..fc3633c1 100644 --- a/src/css/tabs-dark/pid_tuning-dark.css +++ b/src/css/tabs-dark/pid_tuning-dark.css @@ -154,7 +154,6 @@ border-bottom: 1px solid #6b6b6b; } -.tab-pid_tuning .slidersHighWarning, -.tab-pid_tuning .slidersFilterHighWarning { +.tab-pid_tuning .slidersWarning { background: #542415; } diff --git a/src/css/tabs/pid_tuning.css b/src/css/tabs/pid_tuning.css index 24d0bf06..df44b278 100644 --- a/src/css/tabs/pid_tuning.css +++ b/src/css/tabs/pid_tuning.css @@ -751,7 +751,7 @@ opacity: 0.8; transition: opacity .2s; margin: 7px; - background: none; + background: var(--boxBackground); } .tab-pid_tuning .tuningSlider:hover { @@ -766,6 +766,13 @@ height: 15px; } +.tab-pid_tuning .nonExpertModeSliders.tuningSlider::-webkit-slider-runnable-track { + background: linear-gradient(90deg, rgb(197, 197, 197) -50%, rgb(241, 241, 241) 50%, rgb(255, 84, 14) 150%); + background-size: 55%; + background-position: 44%; + background-repeat: no-repeat; +} + .tab-pid_tuning .tuningSlider::-webkit-slider-thumb { -webkit-appearance: none; width: 23px; @@ -830,14 +837,19 @@ width: 30px; } -.tab-pid_tuning .slidersHighWarning, -.tab-pid_tuning .slidersFilterHighWarning { - background: #ffb3b3; +.tab-pid_tuning .slidersWarning { + background: #ffa3a3; border: 1px solid red; font-weight: 600; font-size: 12px; } +.tab-pid_tuning .nonExpertModeSlidersNote { + text-align: center; + padding-top: 2px; + padding-bottom: 2px; +} + .tab-pid_tuning .note-button td:nth-child(n) { padding-left: 7px; padding-right: 7px; diff --git a/src/js/TuningSliders.js b/src/js/TuningSliders.js index 9dbc5474..231b1c09 100644 --- a/src/js/TuningSliders.js +++ b/src/js/TuningSliders.js @@ -20,6 +20,8 @@ var TuningSliders = { cachedPidSliderValues: false, cachedGyroSliderValues: false, cachedDTermSliderValues: false, + + expertMode: false, }; TuningSliders.initialize = function() { @@ -27,6 +29,7 @@ TuningSliders.initialize = function() { this.FILTER_DEFAULT = FC.getFilterDefaults(); this.setDMinFeatureEnabled($('#dMinSwitch').is(':checked')); + this.setExpertMode($('input[name="expertModeCheckbox"]').is(':checked')); this.initPidSlidersPosition(); this.initGyroFilterSliderPosition(); @@ -50,6 +53,17 @@ TuningSliders.setDMinFeatureEnabled = function(dMinFeatureEnabled) { } }; +TuningSliders.setExpertMode = function(expertMode) { + this.expertMode = expertMode; + const allTuningSliderElements = $('#tuningMasterSlider, #tuningPDRatioSlider, #tuningPDGainSlider,\ + #tuningResponseSlider, #tuningGyroFilterSlider, #tuningDTermFilterSlider'); + if (this.expertMode) { + allTuningSliderElements.removeClass('nonExpertModeSliders'); + } else { + allTuningSliderElements.addClass('nonExpertModeSliders'); + } +}; + TuningSliders.scaleSliderValue = function(value) { if (value > 1) { return Math.round(((value - 1) * 2 + 1) * 10) / 10; @@ -90,8 +104,8 @@ TuningSliders.initPidSlidersPosition = function() { }; TuningSliders.initGyroFilterSliderPosition = function() { - this.gyroFilterSliderValue = Math.round((FILTER_CONFIG.gyro_lowpass_dyn_min_hz + FILTER_CONFIG.gyro_lowpass2_hz) / - (this.FILTER_DEFAULT.gyro_lowpass_dyn_min_hz + this.FILTER_DEFAULT.gyro_lowpass2_hz) * 100) / 100; + this.gyroFilterSliderValue = Math.round((FILTER_CONFIG.gyro_lowpass_dyn_min_hz + FILTER_CONFIG.gyro_lowpass_dyn_max_hz + FILTER_CONFIG.gyro_lowpass2_hz) / + (this.FILTER_DEFAULT.gyro_lowpass_dyn_min_hz + this.FILTER_DEFAULT.gyro_lowpass_dyn_max_hz + this.FILTER_DEFAULT.gyro_lowpass2_hz) * 100) / 100; $('output[name="tuningGyroFilterSlider-number"]').val(this.gyroFilterSliderValue); $('#tuningGyroFilterSlider').val(this.downscaleSliderValue(this.gyroFilterSliderValue)); }; @@ -139,10 +153,9 @@ TuningSliders.resetDTermFilterSlider = function() { TuningSliders.updatePidSlidersDisplay = function() { // check if pid values changed manually by saving current values, doing the slider based calculation, and comaparing // if values before and after calculation, if all of them are equal the values haven't been changed manually - // and the sliders are shown, otherwise sliders are grayed out and centered - const WARNING_P_GAIN = 110; + const WARNING_P_GAIN = 70; const WARNING_I_GAIN = 120; - const WARNING_DMAX_GAIN = 70; + const WARNING_DMAX_GAIN = 60; const WARNING_DMIN_GAIN = 40; this.pidSlidersUnavailable = false; @@ -172,26 +185,21 @@ TuningSliders.updatePidSlidersDisplay = function() { this.pidSlidersUnavailable = true; } - if (this.pidSlidersUnavailable) { - $('.tuningPIDSliders').hide(); - $('.slidersDisabled').show(); - } else { - $('.tuningPIDSliders').show(); - $('.slidersDisabled').hide(); + if (!this.pidSlidersUnavailable) { this.cachedPidSliderValues = true; } - if ((PIDs[1][0] > WARNING_P_GAIN || PIDs[1][1] > WARNING_I_GAIN || PIDs[1][2] > WARNING_DMAX_GAIN || ADVANCED_TUNING.dMinPitch > WARNING_DMIN_GAIN) && !this.pidSlidersUnavailable) { - $('.slidersHighWarning').show(); - } else { - $('.slidersHighWarning').hide(); - } + $('.tuningPIDSliders').toggle(!this.pidSlidersUnavailable); + $('.subtab-pid .slidersDisabled').toggle(this.pidSlidersUnavailable); + $('.subtab-pid .nonExpertModeSlidersNote').toggle(!this.pidSlidersUnavailable && !this.expertMode); + $('.subtab-pid .slidersWarning').toggle((PIDs[1][0] > WARNING_P_GAIN || PIDs[1][1] > WARNING_I_GAIN || PIDs[1][2] > WARNING_DMAX_GAIN || + ADVANCED_TUNING.dMinPitch > WARNING_DMIN_GAIN) && !this.pidSlidersUnavailable); }; TuningSliders.updateFilterSlidersDisplay = function() { // check if filters changed manually by comapring current value and those based on slider position - // if equal filter slider is shown, otherwise it is grayed out and centered - const WARNING_FILTER_GAIN = 1.4; + const WARNING_FILTER_HIGH_GAIN = 1.4; + const WARNING_FILTER_LOW_GAIN = 0.7; this.filterGyroSliderUnavailable = false; this.filterDTermSliderUnavailable = false; @@ -222,27 +230,22 @@ TuningSliders.updateFilterSlidersDisplay = function() { this.cachedDTermSliderValues = true; } - if (this.filterGyroSliderUnavailable && this.filterDTermSliderUnavailable) { - $('.tuningFilterSliders').hide(); - } else { - $('.tuningFilterSliders').show(); - } - if (this.filterGyroSliderUnavailable || this.filterDTermSliderUnavailable) { - $('.slidersFilterDisabled').show(); - } else { - $('.slidersFilterDisabled').hide(); - } - - if ((this.gyroFilterSliderValue >= WARNING_FILTER_GAIN && !this.filterGyroSliderUnavailable) || (this.dtermFilterSliderValue >= WARNING_FILTER_GAIN && !this.filterDTermSliderUnavailable)) { - $('.slidersFilterHighWarning').show(); - } else { - $('.slidersFilterHighWarning').hide(); - } + $('.tuningFilterSliders').toggle(!(this.filterGyroSliderUnavailable && this.filterDTermSliderUnavailable)); + $('.subtab-filter .slidersDisabled').toggle(this.filterGyroSliderUnavailable || this.filterDTermSliderUnavailable); + $('.subtab-filter .nonExpertModeSlidersNote').toggle((!this.filterGyroSliderUnavailable || !this.filterDTermSliderUnavailable) && !this.expertMode); + $('.subtab-filter .slidersWarning').toggle(((this.gyroFilterSliderValue >= WARNING_FILTER_HIGH_GAIN || + this.gyroFilterSliderValue <= WARNING_FILTER_LOW_GAIN) && !this.filterGyroSliderUnavailable) || + ((this.dtermFilterSliderValue >= WARNING_FILTER_HIGH_GAIN || + this.dtermFilterSliderValue <= WARNING_FILTER_LOW_GAIN) && !this.filterDTermSliderUnavailable)); }; TuningSliders.calculateNewPids = function() { // this is the main calculation for PID sliders, inputs are in form of slider position values // values get set both into forms and their respective variables + const MAX_PID_GAIN = 200; + const MAX_DMIN_GAIN = 100; + const MAX_FF_GAIN = 2000; + if (this.dMinFeatureEnabled) { //dmin ADVANCED_TUNING.dMinRoll = Math.round(this.PID_DEFAULT[3] * this.PDGainSliderValue); @@ -277,16 +280,16 @@ TuningSliders.calculateNewPids = function() { //master slider multiplication, max value 200 for main PID values for (let i = 0; i < 3; i++) { for (let j = 0; j < 3; j++) { - PIDs[j][i] = Math.min(Math.round(PIDs[j][i] * this.MasterSliderValue), 200); + PIDs[j][i] = Math.min(Math.round(PIDs[j][i] * this.MasterSliderValue), MAX_PID_GAIN); } } - ADVANCED_TUNING.feedforwardRoll = Math.round(ADVANCED_TUNING.feedforwardRoll * this.MasterSliderValue); - ADVANCED_TUNING.feedforwardPitch = Math.round(ADVANCED_TUNING.feedforwardPitch * this.MasterSliderValue); - ADVANCED_TUNING.feedforwardYaw = Math.round(ADVANCED_TUNING.feedforwardYaw * this.MasterSliderValue); + ADVANCED_TUNING.feedforwardRoll = Math.min(Math.round(ADVANCED_TUNING.feedforwardRoll * this.MasterSliderValue), MAX_FF_GAIN); + ADVANCED_TUNING.feedforwardPitch = Math.min(Math.round(ADVANCED_TUNING.feedforwardPitch * this.MasterSliderValue), MAX_FF_GAIN); + ADVANCED_TUNING.feedforwardYaw = Math.min(Math.round(ADVANCED_TUNING.feedforwardYaw * this.MasterSliderValue), MAX_FF_GAIN); if (this.dMinFeatureEnabled) { - ADVANCED_TUNING.dMinRoll = Math.round(ADVANCED_TUNING.dMinRoll * this.MasterSliderValue); - ADVANCED_TUNING.dMinPitch = Math.round(ADVANCED_TUNING.dMinPitch * this.MasterSliderValue); - ADVANCED_TUNING.dMinYaw = Math.round(ADVANCED_TUNING.dMinYaw * this.MasterSliderValue); + ADVANCED_TUNING.dMinRoll = Math.min(Math.round(ADVANCED_TUNING.dMinRoll * this.MasterSliderValue), MAX_DMIN_GAIN); + ADVANCED_TUNING.dMinPitch = Math.min(Math.round(ADVANCED_TUNING.dMinPitch * this.MasterSliderValue), MAX_DMIN_GAIN); + ADVANCED_TUNING.dMinYaw = Math.min(Math.round(ADVANCED_TUNING.dMinYaw * this.MasterSliderValue), MAX_DMIN_GAIN); } $('output[name="tuningMasterSlider-number"]').val(this.MasterSliderValue); @@ -341,4 +344,4 @@ TuningSliders.calculateNewDTermFilters = function() { $('.pid_filter select[name="dtermLowpassDynType').val(FILTER_CONFIG.dterm_lowpass_type); $('.pid_filter select[name="dtermLowpass2Type').val(FILTER_CONFIG.dterm_lowpass2_type); $('output[name="tuningDTermFilterSlider-number"]').val(this.dtermFilterSliderValue); -}; \ No newline at end of file +}; diff --git a/src/js/tabs/pid_tuning.js b/src/js/tabs/pid_tuning.js index 05695eee..dfd3b7dc 100644 --- a/src/js/tabs/pid_tuning.js +++ b/src/js/tabs/pid_tuning.js @@ -11,6 +11,7 @@ TABS.pid_tuning = { SETPOINT_WEIGHT_RANGE_HIGH: 20, SETPOINT_WEIGHT_RANGE_LEGACY: 2.54, activeSubtab: 'pid', + analyticsChanges: {}, }; TABS.pid_tuning.initialize = function (callback) { @@ -1434,6 +1435,18 @@ TABS.pid_tuning.initialize = function (callback) { // filter and tuning sliders TuningSliders.initialize(); + self.analyticsChanges = {}; + + // UNSCALED non expert slider constrain values + const NON_EXPERT_SLIDER_MAX = 1.25; + const NON_EXPERT_SLIDER_MIN = 0.7; + + $('input[name="expertModeCheckbox"]').change(function() { + TuningSliders.setExpertMode($(this).is(':checked')); + TuningSliders.updatePidSlidersDisplay(); + TuningSliders.updateFilterSlidersDisplay(); + }); + $('#dMinSwitch').change(function() { TuningSliders.setDMinFeatureEnabled($(this).is(':checked')); // switch dmin and dmax values on dmin on/off if sliders available @@ -1462,6 +1475,13 @@ TABS.pid_tuning.initialize = function (callback) { } else { slider.attr('step', 0.1); } + if (!TuningSliders.expertMode) { + if (slider.val() > NON_EXPERT_SLIDER_MAX) { + slider.val(NON_EXPERT_SLIDER_MAX); + } else if (slider.val() < NON_EXPERT_SLIDER_MIN) { + slider.val(NON_EXPERT_SLIDER_MIN); + } + } const scaledValue = TuningSliders.scaleSliderValue(slider.val()); if (slider.is('#tuningMasterSlider')) { TuningSliders.MasterSliderValue = scaledValue; @@ -1473,6 +1493,7 @@ TABS.pid_tuning.initialize = function (callback) { TuningSliders.ResponseSliderValue = scaledValue; } TuningSliders.calculateNewPids(); + self.analyticsChanges['PidTuningSliders'] = "On"; }); $('#tuningMasterSlider, #tuningPDRatioSlider, #tuningPDGainSlider, #tuningResponseSlider').mousedown(function() { // adjust step for more smoothness above 1x on mousedown @@ -1514,18 +1535,28 @@ TABS.pid_tuning.initialize = function (callback) { if ($('input[id="useIntegratedYaw"]').is(':checked')) { $('input[id="useIntegratedYaw"]').prop('checked', true).click(); } + self.analyticsChanges['PidTuningSliders'] = "On"; }); // filter slider inputs $('#tuningGyroFilterSlider, #tuningDTermFilterSlider').on('input', function() { const slider = $(this); + if (!TuningSliders.expertMode) { + if (slider.val() > NON_EXPERT_SLIDER_MAX) { + slider.val(NON_EXPERT_SLIDER_MAX); + } else if (slider.val() < NON_EXPERT_SLIDER_MIN) { + slider.val(NON_EXPERT_SLIDER_MIN); + } + } const scaledValue = TuningSliders.scaleSliderValue(slider.val()); if (slider.is('#tuningGyroFilterSlider')) { TuningSliders.gyroFilterSliderValue = scaledValue; TuningSliders.calculateNewGyroFilters(); + self.analyticsChanges['GyroFilterTuningSlider'] = "On"; } else if (slider.is('#tuningDTermFilterSlider')) { TuningSliders.dtermFilterSliderValue = scaledValue; TuningSliders.calculateNewDTermFilters(); + self.analyticsChanges['DTermFilterTuningSlider'] = "On"; } }); $('#tuningGyroFilterSlider, #tuningDTermFilterSlider').mouseup(function() { @@ -1552,30 +1583,42 @@ TABS.pid_tuning.initialize = function (callback) { $('input[id="gyroLowpassEnabled"]').prop('checked', true).click(); $('input[id="gyroLowpass2Enabled"]').prop('checked', false).click(); TuningSliders.resetGyroFilterSlider(); + self.analyticsChanges['GyroFilterTuningSlider'] = "On"; } if (TuningSliders.filterDTermSliderUnavailable) { $('input[id="dtermLowpassDynEnabled"]').prop('checked', false).click(); $('input[id="dtermLowpassEnabled"]').prop('checked', true).click(); $('input[id="dtermLowpass2Enabled"]').prop('checked', false).click(); TuningSliders.resetDTermFilterSlider(); + self.analyticsChanges['DTermFilterTuningSlider'] = "On"; } }); // update on pid table inputs - $('#pid_main input').on('input', () => TuningSliders.updatePidSlidersDisplay()); + $('#pid_main input').on('input', function() { + TuningSliders.updatePidSlidersDisplay(); + self.analyticsChanges['PidTuningSliders'] = "Off"; + }); // update on filter value or type changes - $('.pid_filter input, .pid_filter select').on('input', () => TuningSliders.updateFilterSlidersDisplay()); + $('.pid_filter input, .pid_filter select').on('input', function() { + TuningSliders.updateFilterSlidersDisplay(); + if (TuningSliders.filterGyroSliderUnavailable) { + self.analyticsChanges['GyroFilterTuningSlider'] = "Off"; + } + if (TuningSliders.filterDTermSliderUnavailable) { + self.analyticsChanges['DTermFilterTuningSlider'] = "Off"; + } + }); // update on filter switch changes - $('.inputSwitch input').change(() => TuningSliders.updateFilterSlidersDisplay()); + $('.inputSwitch input').change(() => $('.pid_filter input').trigger('input')); $('.tuningHelp').hide(); } else { $('.tuningPIDSliders').hide(); - $('.slidersDisabled').hide(); - $('.slidersHighWarning').hide(); $('.tuningFilterSliders').hide(); - $('.slidersFilterDisabled').hide(); - $('.slidersFilterHighWarning').hide(); + $('.slidersDisabled').hide(); + $('.slidersWarning').hide(); + $('.nonExpertModeSlidersNote').hide(); $('.tuningHelpSliders').hide(); } @@ -1622,6 +1665,9 @@ TABS.pid_tuning.initialize = function (callback) { GUI.log(i18n.getMessage('pidTuningEepromSaved')); }); + + analytics.sendChangeEvents(analytics.EVENT_CATEGORIES.FLIGHT_CONTROLLER, self.analyticsChanges); + self.analyticsChanges = {}; }); // Setup model for rates preview diff --git a/src/tabs/pid_tuning.html b/src/tabs/pid_tuning.html index 5be61a7f..48a5804d 100644 --- a/src/tabs/pid_tuning.html +++ b/src/tabs/pid_tuning.html @@ -71,8 +71,8 @@

-
-

+
+

@@ -166,6 +166,10 @@
+
+

+
+
@@ -825,10 +829,10 @@

-
-

+
+

-
+
@@ -836,6 +840,9 @@
+
+

+