mirror of
https://github.com/betaflight/betaflight-configurator.git
synced 2025-07-17 21:35:33 +03:00
Added new rc rate calculation to rates curve. Removed SUPER_EXPO feature for >= 3.0.
Added support for RC Expo Power setting. fixed titlebar in pid tuning tab request from @mikeller #252 fixed titlebar from pid tuning and accel
This commit is contained in:
parent
158a415bfc
commit
1da5219bf2
8 changed files with 165 additions and 159 deletions
|
@ -850,6 +850,9 @@
|
||||||
"pidTuningRcRate": {
|
"pidTuningRcRate": {
|
||||||
"message": "RC Rate"
|
"message": "RC Rate"
|
||||||
},
|
},
|
||||||
|
"pidTuningMaxVel": {
|
||||||
|
"message": "Max Vel (deg/s)"
|
||||||
|
},
|
||||||
"pidTuningRate": {
|
"pidTuningRate": {
|
||||||
"message": "Rate"
|
"message": "Rate"
|
||||||
},
|
},
|
||||||
|
@ -872,19 +875,10 @@
|
||||||
"message": "Frequency"
|
"message": "Frequency"
|
||||||
},
|
},
|
||||||
"pidTuningRatesCurve": {
|
"pidTuningRatesCurve": {
|
||||||
"message": "Rates"
|
"message": "Rates"
|
||||||
},
|
|
||||||
"pidTuningMaxAngularVelRoll": {
|
|
||||||
"message": "Max roll speed (deg/s):"
|
|
||||||
},
|
|
||||||
"pidTuningMaxAngularVelPitch": {
|
|
||||||
"message": "Max pitch speed (deg/s):"
|
|
||||||
},
|
|
||||||
"pidTuningMaxAngularVelYaw": {
|
|
||||||
"message": "Max yaw speed (deg/s):"
|
|
||||||
},
|
},
|
||||||
"throttle": {
|
"throttle": {
|
||||||
"message": "Throttle"
|
"message": "Throttle"
|
||||||
},
|
},
|
||||||
"pidTuningButtonSave": {
|
"pidTuningButtonSave": {
|
||||||
"message": "Save"
|
"message": "Save"
|
||||||
|
@ -1607,6 +1601,12 @@
|
||||||
"pidTuningYawJumpPreventionHelp": {
|
"pidTuningYawJumpPreventionHelp": {
|
||||||
"message": "Keeps the craft from jumping up at the end of yaws. Higher number gives more damping at the end of yaw moves (works like old yaw D, which was not a real D like on other axis)"
|
"message": "Keeps the craft from jumping up at the end of yaws. Higher number gives more damping at the end of yaw moves (works like old yaw D, which was not a real D like on other axis)"
|
||||||
},
|
},
|
||||||
|
"pidTuningRcExpoPower": {
|
||||||
|
"message": "RC Expo Power"
|
||||||
|
},
|
||||||
|
"pidTuningRcExpoPowerHelp": {
|
||||||
|
"message": "The exponent that is used when calculating RC Expo. In Betaflight versions prior to 3.0, value is fixed at 3."
|
||||||
|
},
|
||||||
"pidTuningLevel": {
|
"pidTuningLevel": {
|
||||||
"message": "Angle/Horizon"
|
"message": "Angle/Horizon"
|
||||||
},
|
},
|
||||||
|
|
|
@ -46,17 +46,26 @@ var Features = function (config) {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (config.flightControllerVersion !== '' && semver.gte(config.flightControllerVersion, "3.0.0")) {
|
if (config.flightControllerVersion !== '') {
|
||||||
features.push(
|
if (semver.gte(config.flightControllerVersion, "2.8.0")) {
|
||||||
{bit: 18, group: 'other', name: 'OSD', haveTip: true}
|
features.push(
|
||||||
);
|
{bit: 22, group: 'other', name: 'AIRMODE'}
|
||||||
}
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (semver.gte(config.flightControllerVersion, "2.8.0") && !semver.gte(config.flightControllerVersion, "3.0.0")) {
|
||||||
|
features.push(
|
||||||
|
{bit: 23, group: 'pidTuning', name: 'SUPEREXPO_RATES'}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (semver.gte(config.flightControllerVersion, "3.0.0")) {
|
||||||
|
features.push(
|
||||||
|
{bit: 18, group: 'other', name: 'OSD', haveTip: true}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
if (config.flightControllerVersion !== '' && semver.gte(config.flightControllerVersion, "2.8.0")) {
|
|
||||||
features.push(
|
|
||||||
{bit: 22, group: 'other', name: 'AIRMODE'},
|
|
||||||
{bit: 23, group: 'pidTuning', name: 'SUPEREXPO_RATES'}
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
self._features = features;
|
self._features = features;
|
||||||
|
|
|
@ -9,18 +9,24 @@ var RateCurve = function (useLegacyCurve) {
|
||||||
|
|
||||||
this.constrain = function (value, min, max) {
|
this.constrain = function (value, min, max) {
|
||||||
return Math.max(min, Math.min(value, max));
|
return Math.max(min, Math.min(value, max));
|
||||||
}
|
};
|
||||||
|
|
||||||
this.rcCommand = function (rcData, rcRate, rcExpo) {
|
this.rcCommand = function (rcData, rcRate) {
|
||||||
var tmp = Math.min(Math.abs(rcData - midRc), 500) / 100;
|
var tmp = Math.min(Math.abs(rcData - midRc), 500);
|
||||||
|
rcRate = rcRate;
|
||||||
|
|
||||||
var result = ((2500 + rcExpo * (tmp * tmp - 25)) * tmp * rcRate / 2500).toFixed(0);
|
if (rcRate > 2) {
|
||||||
if (rcData < midRc) {
|
rcRate = rcRate + (rcRate - 2) * 14.54;
|
||||||
|
}
|
||||||
|
|
||||||
|
var result = tmp * rcRate;
|
||||||
|
|
||||||
|
if (rcData < midRc) {
|
||||||
result = -result;
|
result = -result;
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
};
|
||||||
|
|
||||||
this.drawRateCurve = function (rate, rcRate, rcExpo, superExpoActive, maxAngularVel, context, width, height) {
|
this.drawRateCurve = function (rate, rcRate, rcExpo, superExpoActive, maxAngularVel, context, width, height) {
|
||||||
var canvasHeightScale = height / (2 * maxAngularVel);
|
var canvasHeightScale = height / (2 * maxAngularVel);
|
||||||
|
@ -42,7 +48,7 @@ var RateCurve = function (useLegacyCurve) {
|
||||||
context.stroke();
|
context.stroke();
|
||||||
|
|
||||||
context.restore();
|
context.restore();
|
||||||
}
|
};
|
||||||
|
|
||||||
this.drawLegacyRateCurve = function (rate, rcRate, rcExpo, context, width, height) {
|
this.drawLegacyRateCurve = function (rate, rcRate, rcExpo, context, width, height) {
|
||||||
// math magic by englishman
|
// math magic by englishman
|
||||||
|
@ -55,28 +61,31 @@ var RateCurve = function (useLegacyCurve) {
|
||||||
context.quadraticCurveTo(width * 11 / 20, height - ((rateY / 2) * (1 - rcExpo)), width, height - rateY);
|
context.quadraticCurveTo(width * 11 / 20, height - ((rateY / 2) * (1 - rcExpo)), width, height - rateY);
|
||||||
context.stroke();
|
context.stroke();
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
RateCurve.prototype.rcCommandRawToDegreesPerSecond = function (rcData, rate, rcRate, rcExpo, superExpoActive) {
|
RateCurve.prototype.rcCommandRawToDegreesPerSecond = function (rcData, rate, rcRate, rcExpo, superExpoActive) {
|
||||||
var angleRate;
|
var angleRate;
|
||||||
if (rate !== undefined && rcRate !== undefined && rcExpo !== undefined) {
|
if (rate !== undefined && rcRate !== undefined && rcExpo !== undefined) {
|
||||||
rate = rate * 100;
|
|
||||||
rcRate = rcRate * 100;
|
|
||||||
rcExpo = rcExpo * 100;
|
|
||||||
|
|
||||||
var inputValue = this.rcCommand(rcData, rcRate, rcExpo);
|
var inputValue = this.rcCommand(rcData, rcRate);
|
||||||
|
var maxRc = 500 * rcRate;
|
||||||
|
|
||||||
if (superExpoActive) {
|
if (rcExpo > 0) {
|
||||||
var rcFactor = Math.abs(inputValue) / (500 * rcRate / 100);
|
var absRc = Math.abs(inputValue) / maxRc;
|
||||||
rcFactor = 1 / this.constrain(1 - rcFactor * rate / 100, 0.01, 1);
|
inputValue = inputValue * ((rcExpo * absRc * absRc * absRc) + absRc * (1-rcExpo)); // absRc should be wrapped in function using expo power
|
||||||
|
|
||||||
angleRate = rcFactor * 27 * inputValue / 16;
|
|
||||||
} else {
|
|
||||||
angleRate = (rate + 27) * inputValue / 16;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
angleRate = this.constrain(angleRate, -8190, 8190); // Rate limit protection
|
var rcInput = inputValue / maxRc;
|
||||||
angleRate = angleRate >> 2; // the shift by 2 is to counterbalance the divide by 4 that occurs on the gyro to calculate the error
|
|
||||||
|
if (superExpoActive) {
|
||||||
|
var rcFactor = 1 / this.constrain(1 - Math.abs(rcInput) * rate, 0.01, 1);
|
||||||
|
angleRate = 200 * rcRate * rcInput; // 200 should be variable checked on version (older versions it's 205,9)
|
||||||
|
angleRate = angleRate * rcFactor;
|
||||||
|
} else {
|
||||||
|
angleRate = (((rate * 100) + 27) * inputValue / 16) / 4.1; // Only applies to old versions ?
|
||||||
|
}
|
||||||
|
|
||||||
|
angleRate = this.constrain(angleRate, -1998, 1998); // Rate limit protection
|
||||||
}
|
}
|
||||||
|
|
||||||
return angleRate;
|
return angleRate;
|
||||||
|
@ -89,7 +98,7 @@ RateCurve.prototype.getMaxAngularVel = function (rate, rcRate, rcExpo, superExpo
|
||||||
}
|
}
|
||||||
|
|
||||||
return maxAngularVel;
|
return maxAngularVel;
|
||||||
}
|
};
|
||||||
|
|
||||||
RateCurve.prototype.draw = function (rate, rcRate, rcExpo, superExpoActive, maxAngularVel, context) {
|
RateCurve.prototype.draw = function (rate, rcRate, rcExpo, superExpoActive, maxAngularVel, context) {
|
||||||
if (rate !== undefined && rcRate !== undefined && rcExpo !== undefined) {
|
if (rate !== undefined && rcRate !== undefined && rcExpo !== undefined) {
|
||||||
|
@ -102,4 +111,4 @@ RateCurve.prototype.draw = function (rate, rcRate, rcExpo, superExpoActive, maxA
|
||||||
this.drawRateCurve(rate, rcRate, rcExpo, superExpoActive, maxAngularVel, context, width, height);
|
this.drawRateCurve(rate, rcRate, rcExpo, superExpoActive, maxAngularVel, context, width, height);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
3
js/fc.js
3
js/fc.js
|
@ -112,7 +112,8 @@ var FC = {
|
||||||
throttle_EXPO: 0,
|
throttle_EXPO: 0,
|
||||||
dynamic_THR_breakpoint: 0,
|
dynamic_THR_breakpoint: 0,
|
||||||
RC_YAW_EXPO: 0,
|
RC_YAW_EXPO: 0,
|
||||||
rcYawRate: 0
|
rcYawRate: 0,
|
||||||
|
rcExpoPower: 3
|
||||||
};
|
};
|
||||||
|
|
||||||
AUX_CONFIG = [];
|
AUX_CONFIG = [];
|
||||||
|
|
|
@ -140,6 +140,11 @@ MspHelper.prototype.process_data = function(dataHandler) {
|
||||||
} else {
|
} else {
|
||||||
RC_tuning.RC_YAW_EXPO = 0;
|
RC_tuning.RC_YAW_EXPO = 0;
|
||||||
}
|
}
|
||||||
|
if (semver.gte(CONFIG.apiVersion, "1.20.0")) {
|
||||||
|
RC_tuning.rcExpoPower = data.readU8();
|
||||||
|
} else {
|
||||||
|
RC_tuning.rcExpoPower = 3;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case MSPCodes.MSP_PID:
|
case MSPCodes.MSP_PID:
|
||||||
// PID data arrived, we need to scale it and save to appropriate bank / array
|
// PID data arrived, we need to scale it and save to appropriate bank / array
|
||||||
|
@ -954,6 +959,9 @@ MspHelper.prototype.crunch = function(code) {
|
||||||
buffer.push8(Math.round(RC_tuning.rcYawRate * 100));
|
buffer.push8(Math.round(RC_tuning.rcYawRate * 100));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (semver.gte(CONFIG.apiVersion, "1.20.0")) {
|
||||||
|
buffer.push8(RC_tuning.rcExpoPower);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case MSPCodes.MSP_SET_RX_MAP:
|
case MSPCodes.MSP_SET_RX_MAP:
|
||||||
for (var i = 0; i < RC_MAP.length; i++) {
|
for (var i = 0; i < RC_MAP.length; i++) {
|
||||||
|
|
|
@ -242,13 +242,13 @@
|
||||||
padding: 5px;
|
padding: 5px;
|
||||||
text-align: left;
|
text-align: left;
|
||||||
border-right: 1px solid #ccc;
|
border-right: 1px solid #ccc;
|
||||||
width: 14%;
|
width: 12.5%;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.tab-pid_tuning .pid_titlebar th:first-child {
|
.tab-pid_tuning .pid_titlebar th:first-child {
|
||||||
text-align: left;
|
text-align: left;
|
||||||
width: 14%;
|
width: 12.5%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.tab-pid_tuning .pid_titlebar th:last-child {
|
.tab-pid_tuning .pid_titlebar th:last-child {
|
||||||
|
@ -288,7 +288,7 @@
|
||||||
|
|
||||||
.tab-pid_tuning table td {
|
.tab-pid_tuning table td {
|
||||||
padding: 1px;
|
padding: 1px;
|
||||||
width: 14%;
|
width: 12.5%;
|
||||||
border-right: 1px solid #ccc;
|
border-right: 1px solid #ccc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -370,32 +370,8 @@
|
||||||
border-top-right-radius: 3px;
|
border-top-right-radius: 3px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.tab-pid_tuning .name {
|
.tab-pid_tuning .new_rates {
|
||||||
width: 14%;
|
text-align: left;
|
||||||
}
|
|
||||||
|
|
||||||
.tab-pid_tuning .proportional {
|
|
||||||
width: 14%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tab-pid_tuning .integral {
|
|
||||||
width: 14%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tab-pid_tuning .derivative {
|
|
||||||
width: 14%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tab-pid_tuning .rc_rate {
|
|
||||||
width: 14%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tab-pid_tuning .rate {
|
|
||||||
width: 14%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tab-pid_tuning .rc_expo {
|
|
||||||
width: 14%;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.tab-pid_tuning .tpa {
|
.tab-pid_tuning .tpa {
|
||||||
|
@ -711,7 +687,6 @@ width: 40%;
|
||||||
|
|
||||||
.tab-pid_tuning .rc_curve_bg {
|
.tab-pid_tuning .rc_curve_bg {
|
||||||
float: left;
|
float: left;
|
||||||
padding-bottom: 20px;
|
|
||||||
background: #ddd;
|
background: #ddd;
|
||||||
border-bottom-left-radius: 5px;
|
border-bottom-left-radius: 5px;
|
||||||
border-bottom-right-radius: 5px;
|
border-bottom-right-radius: 5px;
|
||||||
|
@ -757,4 +732,4 @@ width: 40%;
|
||||||
border-bottom-left-radius: 8px;
|
border-bottom-left-radius: 8px;
|
||||||
border-top: 0px solid silver;
|
border-top: 0px solid silver;
|
||||||
background: #f9f9f9;
|
background: #f9f9f9;
|
||||||
}
|
}
|
||||||
|
|
|
@ -72,6 +72,7 @@
|
||||||
<th class="derivative" i18n="pidTuningDerivative"></th>
|
<th class="derivative" i18n="pidTuningDerivative"></th>
|
||||||
<th class="rc_rate" i18n="pidTuningRcRate"></th>
|
<th class="rc_rate" i18n="pidTuningRcRate"></th>
|
||||||
<th class="rate" i18n="pidTuningRate"></th>
|
<th class="rate" i18n="pidTuningRate"></th>
|
||||||
|
<th class="maxVel" i18n="pidTuningMaxVel"></th>
|
||||||
<th class="rc_expo" i18n="pidTuningRcExpo"></th>
|
<th class="rc_expo" i18n="pidTuningRcExpo"></th>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
|
@ -91,11 +92,12 @@
|
||||||
<td class="pid_data"><input type="number" name="i" step="1" min="0" max="255" /></td>
|
<td class="pid_data"><input type="number" name="i" step="1" min="0" max="255" /></td>
|
||||||
<td class="pid_data"><input type="number" name="d" step="1" min="0" max="255" /></td>
|
<td class="pid_data"><input type="number" name="d" step="1" min="0" max="255" /></td>
|
||||||
<td rowspan="2" style="background-color:white;">
|
<td rowspan="2" style="background-color:white;">
|
||||||
<input type="number" name="rc_rate" step="0.01" min="0" max="2.5" />
|
<input type="number" name="rc_rate" step="0.01" min="0" max="2.55" />
|
||||||
<div class="bracket"></div>
|
<div class="bracket"></div>
|
||||||
</td>
|
</td>
|
||||||
<td class="roll_rate"><input type="number" name="roll_rate" step="0.01" min="0" max="1.00" /></td>
|
<td class="roll_rate"><input type="number" name="roll_rate" step="0.01" min="0" max="1.00" /></td>
|
||||||
<td class="roll_pitch_rate" rowspan="2"><input type="number" name="roll_pitch_rate" step="0.01" min="0" max="1.00" /></td>
|
<td class="roll_pitch_rate" rowspan="2"><input type="number" name="roll_pitch_rate" step="0.01" min="0" max="1.00" /></td>
|
||||||
|
<td class="new_rates maxAngularVelRoll"></td>
|
||||||
<td rowspan="2" style="background-color:white;">
|
<td rowspan="2" style="background-color:white;">
|
||||||
<input type="number" name="rc_expo" step="0.01" min="0" max="1" />
|
<input type="number" name="rc_expo" step="0.01" min="0" max="1" />
|
||||||
<div class="bracket"></div>
|
<div class="bracket"></div>
|
||||||
|
@ -108,6 +110,7 @@
|
||||||
<td class="pid_data"><input type="number" name="i" step="1" min="0" max="255" /></td>
|
<td class="pid_data"><input type="number" name="i" step="1" min="0" max="255" /></td>
|
||||||
<td class="pid_data"><input type="number" name="d" step="1" min="0" max="255" /></td>
|
<td class="pid_data"><input type="number" name="d" step="1" min="0" max="255" /></td>
|
||||||
<td class="pitch_rate"><input type="number" name="pitch_rate" step="0.01" min="0" max="1.00" /></td>
|
<td class="pitch_rate"><input type="number" name="pitch_rate" step="0.01" min="0" max="1.00" /></td>
|
||||||
|
<td class="new_rates maxAngularVelPitch"></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr class="YAW">
|
<tr class="YAW">
|
||||||
<!-- 2 -->
|
<!-- 2 -->
|
||||||
|
@ -115,8 +118,9 @@
|
||||||
<td class="pid_data"><input type="number" name="p" step="1" min="0" max="255" /></td>
|
<td class="pid_data"><input type="number" name="p" step="1" min="0" max="255" /></td>
|
||||||
<td class="pid_data"><input type="number" name="i" step="1" min="0" max="255" /></td>
|
<td class="pid_data"><input type="number" name="i" step="1" min="0" max="255" /></td>
|
||||||
<td></td>
|
<td></td>
|
||||||
<td rowspan="1"><input type="number" name="rc_rate_yaw" step="0.01" min="0" max="2.5" /></td>
|
<td rowspan="1"><input type="number" name="rc_rate_yaw" step="0.01" min="0" max="2.55" /></td>
|
||||||
<td><input type="number" name="yaw_rate" step="0.01" min="0" max="2.55" /></td>
|
<td><input type="number" name="yaw_rate" step="0.01" min="0" max="2.55" /></td>
|
||||||
|
<td class="new_rates maxAngularVelYaw"></td>
|
||||||
<td><input type="number" name="rc_yaw_expo" step="0.01" min="0" max="1" /></td>
|
<td><input type="number" name="rc_yaw_expo" step="0.01" min="0" max="1" /></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr class="YAW_JUMP_PREVENTION">
|
<tr class="YAW_JUMP_PREVENTION">
|
||||||
|
@ -127,7 +131,16 @@
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
<td class="pid_data"><input type="number" name="d" step="1" min="0" max="255" /></td>
|
<td class="pid_data"><input type="number" name="d" step="1" min="0" max="255" /></td>
|
||||||
<td colspan=3></td>
|
<td colspan=4></td>
|
||||||
|
</tr>
|
||||||
|
<tr class="RC_EXPO_POWER">
|
||||||
|
<td colspan = 7>
|
||||||
|
<div>
|
||||||
|
<div i18n="pidTuningRcExpoPower" style="float:left;"></div>
|
||||||
|
<div class="helpicon cf_tip" i18n_title="pidTuningRcExpoPowerHelp"></div>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td class="pid_data"><input type="number" name="rcExpoPower" step="1" min="2" max="4"/></td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
|
@ -208,7 +221,7 @@
|
||||||
<div id="pid_accel" class="gui_box grey topspacer pid_tuning">
|
<div id="pid_accel" class="gui_box grey topspacer pid_tuning">
|
||||||
<table class="pid_titlebar">
|
<table class="pid_titlebar">
|
||||||
<tr>
|
<tr>
|
||||||
<th class="third" i18n="pidTuningName" style="width: 17%;"></th>
|
<th class="third" i18n="pidTuningName" style="width: 24%;"></th>
|
||||||
<th class="third" i18n="pidTuningStrength" style="width: 33%;"></th>
|
<th class="third" i18n="pidTuningStrength" style="width: 33%;"></th>
|
||||||
<th class="third" i18n="pidTuningTransition" style="width: 33%;"></th>
|
<th class="third" i18n="pidTuningTransition" style="width: 33%;"></th>
|
||||||
</tr>
|
</tr>
|
||||||
|
@ -371,26 +384,14 @@
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan=2>
|
<td>
|
||||||
<div class="spacer" style="margin-top: 10px; margin-bottom: 10px;">
|
<div class="spacer" style="margin-top: 10px;">
|
||||||
<div class="rate_curve">
|
<div class="rate_curve">
|
||||||
<canvas height="120px" style="width: 100%; height: 100%"></canvas>
|
<canvas height="120px" style="width: 100%; height: 100%"></canvas>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr class="new_rates">
|
|
||||||
<td i18n="pidTuningMaxAngularVelRoll" style="width: 70%"></td>
|
|
||||||
<td class="maxAngularVelRoll"></td>
|
|
||||||
</tr>
|
|
||||||
<tr class="new_rates">
|
|
||||||
<td i18n="pidTuningMaxAngularVelPitch"></td>
|
|
||||||
<td class="maxAngularVelPitch"></td>
|
|
||||||
</tr>
|
|
||||||
<tr class="new_rates">
|
|
||||||
<td i18n="pidTuningMaxAngularVelYaw"></td>
|
|
||||||
<td class="maxAngularVelYaw"></td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -58,28 +58,6 @@ TABS.pid_tuning.initialize = function (callback) {
|
||||||
self.setRateProfile();
|
self.setRateProfile();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (semver.gte(CONFIG.flightControllerVersion, "2.8.1")) {
|
|
||||||
$('input[id="vbatpidcompensation"]').prop('checked', ADVANCED_TUNING.vbatPidCompensation !== 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (semver.gte(CONFIG.flightControllerVersion, "2.8.2")) {
|
|
||||||
$('#pid-tuning .delta select').val(ADVANCED_TUNING.deltaMethod);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (semver.gte(CONFIG.flightControllerVersion, '3.0.0')) {
|
|
||||||
$('select[name="rcInterpolation-select"]').val(RX_CONFIG.rcInterpolation);
|
|
||||||
|
|
||||||
$('input[name="rcInterpolationInterval-number"]').val(RX_CONFIG.rcInterpolationInterval);
|
|
||||||
|
|
||||||
$('input[name="ptermSetpoint-number"]').val(ADVANCED_TUNING.ptermSetpointWeight / 100);
|
|
||||||
$('input[name="ptermSetpoint-range"]').val(ADVANCED_TUNING.ptermSetpointWeight / 100);
|
|
||||||
|
|
||||||
$('input[name="dtermSetpoint-number"]').val(ADVANCED_TUNING.dtermSetpointWeight / 100);
|
|
||||||
$('input[name="dtermSetpoint-range"]').val(ADVANCED_TUNING.dtermSetpointWeight / 100);
|
|
||||||
|
|
||||||
self.updateRcInterpolationParameters();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fill in the data from PIDs array
|
// Fill in the data from PIDs array
|
||||||
var i = 0;
|
var i = 0;
|
||||||
$('.pid_tuning .ROLL input').each(function () {
|
$('.pid_tuning .ROLL input').each(function () {
|
||||||
|
@ -239,6 +217,14 @@ TABS.pid_tuning.initialize = function (callback) {
|
||||||
$('.pid_tuning input[name="rc_expo"]').attr("rowspan", "3");
|
$('.pid_tuning input[name="rc_expo"]').attr("rowspan", "3");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (semver.gte(CONFIG.flightControllerVersion, "2.8.1")) {
|
||||||
|
$('input[id="vbatpidcompensation"]').prop('checked', ADVANCED_TUNING.vbatPidCompensation !== 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (semver.gte(CONFIG.flightControllerVersion, "2.8.2")) {
|
||||||
|
$('#pid-tuning .delta select').val(ADVANCED_TUNING.deltaMethod);
|
||||||
|
}
|
||||||
|
|
||||||
if (semver.gte(CONFIG.flightControllerVersion, '2.9.0')) {
|
if (semver.gte(CONFIG.flightControllerVersion, '2.9.0')) {
|
||||||
$('.pid_tuning input[name="rc_rate_yaw"]').val(RC_tuning.rcYawRate.toFixed(2));
|
$('.pid_tuning input[name="rc_rate_yaw"]').val(RC_tuning.rcYawRate.toFixed(2));
|
||||||
$('.pid_filter input[name="gyroLowpassFrequency"]').val(FILTER_CONFIG.gyro_soft_lpf_hz);
|
$('.pid_filter input[name="gyroLowpassFrequency"]').val(FILTER_CONFIG.gyro_soft_lpf_hz);
|
||||||
|
@ -255,34 +241,28 @@ TABS.pid_tuning.initialize = function (callback) {
|
||||||
$('.pid_filter input[name="gyroNotchCutoff"]').val(FILTER_CONFIG.gyro_soft_notch_cutoff);
|
$('.pid_filter input[name="gyroNotchCutoff"]').val(FILTER_CONFIG.gyro_soft_notch_cutoff);
|
||||||
$('.pid_filter input[name="dTermNotchFrequency"]').val(FILTER_CONFIG.dterm_notch_hz);
|
$('.pid_filter input[name="dTermNotchFrequency"]').val(FILTER_CONFIG.dterm_notch_hz);
|
||||||
$('.pid_filter input[name="dTermNotchCutoff"]').val(FILTER_CONFIG.dterm_notch_cutoff);
|
$('.pid_filter input[name="dTermNotchCutoff"]').val(FILTER_CONFIG.dterm_notch_cutoff);
|
||||||
|
|
||||||
|
$('select[name="rcInterpolation-select"]').val(RX_CONFIG.rcInterpolation);
|
||||||
|
|
||||||
|
$('input[name="rcInterpolationInterval-number"]').val(RX_CONFIG.rcInterpolationInterval);
|
||||||
|
|
||||||
|
$('input[name="ptermSetpoint-number"]').val(ADVANCED_TUNING.ptermSetpointWeight / 100);
|
||||||
|
$('input[name="ptermSetpoint-range"]').val(ADVANCED_TUNING.ptermSetpointWeight / 100);
|
||||||
|
|
||||||
|
$('input[name="dtermSetpoint-number"]').val(ADVANCED_TUNING.dtermSetpointWeight / 100);
|
||||||
|
$('input[name="dtermSetpoint-range"]').val(ADVANCED_TUNING.dtermSetpointWeight / 100);
|
||||||
|
|
||||||
|
self.updateRcInterpolationParameters();
|
||||||
|
|
||||||
|
$('.pid_tuning input[name="rcExpoPower"]').val(RC_tuning.rcExpoPower.toFixed(0)).prop("readonly", false);
|
||||||
} else {
|
} else {
|
||||||
$('.pid_filter .newFilter').hide();
|
$('.pid_filter .newFilter').hide();
|
||||||
|
|
||||||
|
$('.pid_tuning input[name="rcExpoPower"]').val(3).prop("readonly", true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function form_to_pid_and_rc() {
|
function form_to_pid_and_rc() {
|
||||||
if (semver.gte(CONFIG.flightControllerVersion, "2.8.0")) {
|
|
||||||
BF_CONFIG.features.updateData($('input[name="SUPEREXPO_RATES"]'));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (semver.gte(CONFIG.flightControllerVersion, "2.8.1")) {
|
|
||||||
ADVANCED_TUNING.vbatPidCompensation = $('input[id="vbatpidcompensation"]').is(':checked') ? 1 : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (semver.gte(CONFIG.flightControllerVersion, "2.8.2")) {
|
|
||||||
ADVANCED_TUNING.deltaMethod = $('#pid-tuning .delta select').val();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (semver.gte(CONFIG.flightControllerVersion, '3.0.0')) {
|
|
||||||
RX_CONFIG.rcInterpolation = parseInt($('select[name="rcInterpolation-select"]').val());
|
|
||||||
|
|
||||||
RX_CONFIG.rcInterpolationInterval = parseInt($('input[name="rcInterpolationInterval-number"]').val());
|
|
||||||
|
|
||||||
ADVANCED_TUNING.ptermSetpointWeight = parseInt($('input[name="ptermSetpoint-number"]').val() * 100);
|
|
||||||
|
|
||||||
ADVANCED_TUNING.dtermSetpointWeight = parseInt($('input[name="dtermSetpoint-number"]').val() * 100);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fill in the data from PIDs array
|
// Fill in the data from PIDs array
|
||||||
// Catch all the changes and stuff the inside PIDs array
|
// Catch all the changes and stuff the inside PIDs array
|
||||||
var i = 0;
|
var i = 0;
|
||||||
|
@ -360,12 +340,33 @@ TABS.pid_tuning.initialize = function (callback) {
|
||||||
FILTER_CONFIG.dterm_lpf_hz = parseInt($('.pid_filter input[name="dtermLowpassFrequency"]').val());
|
FILTER_CONFIG.dterm_lpf_hz = parseInt($('.pid_filter input[name="dtermLowpassFrequency"]').val());
|
||||||
FILTER_CONFIG.yaw_lpf_hz = parseInt($('.pid_filter input[name="yawLowpassFrequency"]').val());
|
FILTER_CONFIG.yaw_lpf_hz = parseInt($('.pid_filter input[name="yawLowpassFrequency"]').val());
|
||||||
|
|
||||||
|
if (semver.gte(CONFIG.flightControllerVersion, "2.8.0") && !semver.gte(CONFIG.flightControllerVersion, "3.0.0")) {
|
||||||
|
BF_CONFIG.features.updateData($('input[name="SUPEREXPO_RATES"]'));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (semver.gte(CONFIG.flightControllerVersion, "2.8.1")) {
|
||||||
|
ADVANCED_TUNING.vbatPidCompensation = $('input[id="vbatpidcompensation"]').is(':checked') ? 1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (semver.gte(CONFIG.flightControllerVersion, "2.8.2")) {
|
||||||
|
ADVANCED_TUNING.deltaMethod = $('#pid-tuning .delta select').val();
|
||||||
|
}
|
||||||
|
|
||||||
if (semver.gte(CONFIG.flightControllerVersion, '3.0.0')) {
|
if (semver.gte(CONFIG.flightControllerVersion, '3.0.0')) {
|
||||||
|
RX_CONFIG.rcInterpolation = parseInt($('select[name="rcInterpolation-select"]').val());
|
||||||
|
RX_CONFIG.rcInterpolationInterval = parseInt($('input[name="rcInterpolationInterval-number"]').val());
|
||||||
|
|
||||||
|
ADVANCED_TUNING.ptermSetpointWeight = parseInt($('input[name="ptermSetpoint-number"]').val() * 100);
|
||||||
|
ADVANCED_TUNING.dtermSetpointWeight = parseInt($('input[name="dtermSetpoint-number"]').val() * 100);
|
||||||
|
|
||||||
FILTER_CONFIG.gyro_soft_notch_hz = parseInt($('.pid_filter input[name="gyroNotchFrequency"]').val());
|
FILTER_CONFIG.gyro_soft_notch_hz = parseInt($('.pid_filter input[name="gyroNotchFrequency"]').val());
|
||||||
FILTER_CONFIG.gyro_soft_notch_cutoff = parseInt($('.pid_filter input[name="gyroNotchCutoff"]').val());
|
FILTER_CONFIG.gyro_soft_notch_cutoff = parseInt($('.pid_filter input[name="gyroNotchCutoff"]').val());
|
||||||
FILTER_CONFIG.dterm_notch_hz = parseInt($('.pid_filter input[name="dTermNotchFrequency"]').val());
|
FILTER_CONFIG.dterm_notch_hz = parseInt($('.pid_filter input[name="dTermNotchFrequency"]').val());
|
||||||
FILTER_CONFIG.dterm_notch_cutoff = parseInt($('.pid_filter input[name="dTermNotchCutoff"]').val());
|
FILTER_CONFIG.dterm_notch_cutoff = parseInt($('.pid_filter input[name="dTermNotchCutoff"]').val());
|
||||||
|
|
||||||
|
RC_tuning.rcExpoPower = parseInt($('.pid_tuning input[name="rcExpoPower"]').val());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function showAllPids() {
|
function showAllPids() {
|
||||||
|
@ -452,7 +453,7 @@ TABS.pid_tuning.initialize = function (callback) {
|
||||||
self.rateCurve = new RateCurve(useLegacyCurve);
|
self.rateCurve = new RateCurve(useLegacyCurve);
|
||||||
|
|
||||||
function printMaxAngularVel(rate, rcRate, rcExpo, useSuperExpo, maxAngularVelElement) {
|
function printMaxAngularVel(rate, rcRate, rcExpo, useSuperExpo, maxAngularVelElement) {
|
||||||
var maxAngularVel = self.rateCurve.getMaxAngularVel(rate, rcRate, rcExpo, useSuperExpo);
|
var maxAngularVel = self.rateCurve.getMaxAngularVel(rate, rcRate, rcExpo, useSuperExpo).toFixed(0);
|
||||||
maxAngularVelElement.text(maxAngularVel);
|
maxAngularVelElement.text(maxAngularVel);
|
||||||
|
|
||||||
return maxAngularVel;
|
return maxAngularVel;
|
||||||
|
@ -486,15 +487,19 @@ TABS.pid_tuning.initialize = function (callback) {
|
||||||
superexpo: BF_CONFIG.features.isEnabled('SUPEREXPO_RATES')
|
superexpo: BF_CONFIG.features.isEnabled('SUPEREXPO_RATES')
|
||||||
};
|
};
|
||||||
|
|
||||||
if (CONFIG.flightControllerIdentifier !== "BTFL" || semver.lt(CONFIG.flightControllerVersion, "2.8.1")) {
|
|
||||||
self.currentRates.rc_rate_yaw = self.currentRates.rc_rate;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (semver.lt(CONFIG.apiVersion, "1.7.0")) {
|
if (semver.lt(CONFIG.apiVersion, "1.7.0")) {
|
||||||
self.currentRates.roll_rate = RC_tuning.roll_pitch_rate;
|
self.currentRates.roll_rate = RC_tuning.roll_pitch_rate;
|
||||||
self.currentRates.pitch_rate = RC_tuning.roll_pitch_rate;
|
self.currentRates.pitch_rate = RC_tuning.roll_pitch_rate;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (semver.lt(CONFIG.flightControllerVersion, "2.8.1")) {
|
||||||
|
self.currentRates.rc_rate_yaw = self.currentRates.rc_rate;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (semver.gte(CONFIG.flightControllerVersion, "3.0.0")) {
|
||||||
|
self.currentRates.superexpo = true;
|
||||||
|
}
|
||||||
|
|
||||||
$('.tab-pid_tuning .tab_container .pid').on('click', function () {
|
$('.tab-pid_tuning .tab_container .pid').on('click', function () {
|
||||||
$('.tab-pid_tuning .subtab-pid').show();
|
$('.tab-pid_tuning .subtab-pid').show();
|
||||||
$('.tab-pid_tuning .subtab-filter').hide();
|
$('.tab-pid_tuning .subtab-filter').hide();
|
||||||
|
@ -673,9 +678,9 @@ TABS.pid_tuning.initialize = function (callback) {
|
||||||
rcCurveElement.width = 1000;
|
rcCurveElement.width = 1000;
|
||||||
rcCurveElement.height = 1000;
|
rcCurveElement.height = 1000;
|
||||||
|
|
||||||
var maxAngularVelRollElement = $('.rc_curve .maxAngularVelRoll');
|
var maxAngularVelRollElement = $('.pid_tuning .maxAngularVelRoll');
|
||||||
var maxAngularVelPitchElement = $('.rc_curve .maxAngularVelPitch');
|
var maxAngularVelPitchElement = $('.pid_tuning .maxAngularVelPitch');
|
||||||
var maxAngularVelYawElement = $('.rc_curve .maxAngularVelYaw');
|
var maxAngularVelYawElement = $('.pid_tuning .maxAngularVelYaw');
|
||||||
|
|
||||||
var updateNeeded = true;
|
var updateNeeded = true;
|
||||||
|
|
||||||
|
@ -684,13 +689,13 @@ TABS.pid_tuning.initialize = function (callback) {
|
||||||
var targetElement = $(event.target),
|
var targetElement = $(event.target),
|
||||||
targetValue = checkInput(targetElement);
|
targetValue = checkInput(targetElement);
|
||||||
|
|
||||||
if (self.currentRates.hasOwnProperty(targetElement.attr('name')) && targetValue) {
|
if (self.currentRates.hasOwnProperty(targetElement.attr('name')) && targetValue !== undefined) {
|
||||||
self.currentRates[targetElement.attr('name')] = targetValue;
|
self.currentRates[targetElement.attr('name')] = targetValue;
|
||||||
|
|
||||||
updateNeeded = true;
|
updateNeeded = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (targetElement.attr('name') === 'rc_rate' && CONFIG.flightControllerIdentifier !== "BTFL" || semver.lt(CONFIG.flightControllerVersion, "2.8.1")) {
|
if (targetElement.attr('name') === 'rc_rate' && semver.lt(CONFIG.flightControllerVersion, "2.8.1")) {
|
||||||
self.currentRates.rc_rate_yaw = targetValue;
|
self.currentRates.rc_rate_yaw = targetValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -711,7 +716,7 @@ TABS.pid_tuning.initialize = function (callback) {
|
||||||
var curveHeight = rcCurveElement.height;
|
var curveHeight = rcCurveElement.height;
|
||||||
var curveWidth = rcCurveElement.width;
|
var curveWidth = rcCurveElement.width;
|
||||||
|
|
||||||
var maxAngularVel = Math.max(
|
var maxAngularVel = Math.max(
|
||||||
printMaxAngularVel(self.currentRates.roll_rate, self.currentRates.rc_rate, self.currentRates.rc_expo, self.currentRates.superexpo, maxAngularVelRollElement),
|
printMaxAngularVel(self.currentRates.roll_rate, self.currentRates.rc_rate, self.currentRates.rc_expo, self.currentRates.superexpo, maxAngularVelRollElement),
|
||||||
printMaxAngularVel(self.currentRates.pitch_rate, self.currentRates.rc_rate, self.currentRates.rc_expo, self.currentRates.superexpo, maxAngularVelPitchElement),
|
printMaxAngularVel(self.currentRates.pitch_rate, self.currentRates.rc_rate, self.currentRates.rc_expo, self.currentRates.superexpo, maxAngularVelPitchElement),
|
||||||
printMaxAngularVel(self.currentRates.yaw_rate, self.currentRates.rc_rate_yaw, self.currentRates.rc_yaw_expo, self.currentRates.superexpo, maxAngularVelYawElement));
|
printMaxAngularVel(self.currentRates.yaw_rate, self.currentRates.rc_rate_yaw, self.currentRates.rc_yaw_expo, self.currentRates.superexpo, maxAngularVelYawElement));
|
||||||
|
@ -724,11 +729,9 @@ TABS.pid_tuning.initialize = function (callback) {
|
||||||
|
|
||||||
curveContext.lineWidth = 4;
|
curveContext.lineWidth = 4;
|
||||||
|
|
||||||
drawCurve(self.currentRates.roll_rate, self.currentRates.rc_rate, self.currentRates.rc_expo, self.currentRates.superexpo, maxAngularVel, '#ff0000', 0, curveContext);
|
drawCurve(self.currentRates.roll_rate, self.currentRates.rc_rate, self.currentRates.rc_expo, self.currentRates.superexpo, maxAngularVel, '#ff0000', 0, curveContext);
|
||||||
|
drawCurve(self.currentRates.pitch_rate, self.currentRates.rc_rate, self.currentRates.rc_expo, self.currentRates.superexpo, maxAngularVel, '#00ff00', -4, curveContext);
|
||||||
drawCurve(self.currentRates.pitch_rate, self.currentRates.rc_rate, self.currentRates.rc_expo, self.currentRates.superexpo, maxAngularVel, '#00ff00', -4, curveContext);
|
drawCurve(self.currentRates.yaw_rate, self.currentRates.rc_rate_yaw, self.currentRates.rc_yaw_expo, self.currentRates.superexpo, maxAngularVel, '#0000ff', 4, curveContext);
|
||||||
|
|
||||||
drawCurve(self.currentRates.yaw_rate, self.currentRates.rc_rate_yaw, self.currentRates.rc_yaw_expo, self.currentRates.superexpo, maxAngularVel, '#0000ff', 4, curveContext);
|
|
||||||
|
|
||||||
updateNeeded = false;
|
updateNeeded = false;
|
||||||
}
|
}
|
||||||
|
@ -737,8 +740,8 @@ TABS.pid_tuning.initialize = function (callback) {
|
||||||
|
|
||||||
// UI Hooks
|
// UI Hooks
|
||||||
// curves
|
// curves
|
||||||
$('.pid_tuning').on('input change', updateRates);
|
$('input.feature').on('input change', updateRates);
|
||||||
$('input.feature').on('input change', updateRates).trigger('input');
|
$('.pid_tuning').on('input change', updateRates).trigger('input');
|
||||||
|
|
||||||
$('.throttle input').on('input change', function () {
|
$('.throttle input').on('input change', function () {
|
||||||
setTimeout(function () { // let global validation trigger and adjust the values first
|
setTimeout(function () { // let global validation trigger and adjust the values first
|
||||||
|
@ -900,9 +903,9 @@ TABS.pid_tuning.renderModel = function () {
|
||||||
if (RC.channels[0] && RC.channels[1] && RC.channels[2]) {
|
if (RC.channels[0] && RC.channels[1] && RC.channels[2]) {
|
||||||
var delta = this.clock.getDelta();
|
var delta = this.clock.getDelta();
|
||||||
|
|
||||||
var roll = delta * this.rateCurve.rcCommandRawToDegreesPerSecond(RC.channels[0], this.currentRates.roll_rate, this.currentRates.rc_rate, this.currentRates.rc_expo, this.currentRates.super_expo),
|
var roll = delta * this.rateCurve.rcCommandRawToDegreesPerSecond(RC.channels[0], this.currentRates.roll_rate, this.currentRates.rc_rate, this.currentRates.rc_expo, this.currentRates.superexpo),
|
||||||
pitch = delta * this.rateCurve.rcCommandRawToDegreesPerSecond(RC.channels[1], this.currentRates.pitch_rate, this.currentRates.rc_rate, this.currentRates.rc_expo, this.currentRates.super_expo),
|
pitch = delta * this.rateCurve.rcCommandRawToDegreesPerSecond(RC.channels[1], this.currentRates.pitch_rate, this.currentRates.rc_rate, this.currentRates.rc_expo, this.currentRates.superexpo),
|
||||||
yaw = delta * this.rateCurve.rcCommandRawToDegreesPerSecond(RC.channels[2], this.currentRates.yaw_rate, this.currentRates.rc_rate_yaw, this.currentRates.rc_yaw_expo, this.currentRates.super_expo);
|
yaw = delta * this.rateCurve.rcCommandRawToDegreesPerSecond(RC.channels[2], this.currentRates.yaw_rate, this.currentRates.rc_rate_yaw, this.currentRates.rc_yaw_expo, this.currentRates.superexpo);
|
||||||
|
|
||||||
this.model.rotateBy(-degToRad(pitch), -degToRad(yaw), -degToRad(roll));
|
this.model.rotateBy(-degToRad(pitch), -degToRad(yaw), -degToRad(roll));
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue