Skip to content

Commit

Permalink
Merge pull request #266 from mikeller/add_deadband_to_curves_and_model
Browse files Browse the repository at this point in the history
Added deadband to curves and model calculations. Also fixed rates curve bug in pre 2.8.
  • Loading branch information
borisbstyle authored Sep 7, 2016
2 parents f9ea2c8 + edad524 commit 6d92789
Show file tree
Hide file tree
Showing 4 changed files with 58 additions and 34 deletions.
25 changes: 13 additions & 12 deletions js/RateCurve.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ var RateCurve = function (useLegacyCurve) {
return Math.max(min, Math.min(value, max));
};

this.rcCommand = function (rcData, rcRate) {
var tmp = Math.min(Math.abs(rcData - midRc), 500);
this.rcCommand = function (rcData, rcRate, deadband) {
var tmp = Math.min(Math.max(Math.abs(rcData - midRc) - deadband, 0), 500);

var result = tmp * rcRate;

Expand All @@ -23,7 +23,7 @@ var RateCurve = function (useLegacyCurve) {
return result;
};

this.drawRateCurve = function (rate, rcRate, rcExpo, superExpoActive, maxAngularVel, context, width, height) {
this.drawRateCurve = function (rate, rcRate, rcExpo, superExpoActive, deadband, maxAngularVel, context, width, height) {
var canvasHeightScale = height / (2 * maxAngularVel);

var stepWidth = context.lineWidth;
Expand All @@ -33,10 +33,10 @@ var RateCurve = function (useLegacyCurve) {

context.beginPath();
var rcData = minRc;
context.moveTo(-500, -canvasHeightScale * this.rcCommandRawToDegreesPerSecond(rcData, rate, rcRate, rcExpo, superExpoActive));
context.moveTo(-500, -canvasHeightScale * this.rcCommandRawToDegreesPerSecond(rcData, rate, rcRate, rcExpo, superExpoActive, deadband));
rcData = rcData + stepWidth;
while (rcData <= maxRc) {
context.lineTo(rcData - midRc, -canvasHeightScale * this.rcCommandRawToDegreesPerSecond(rcData, rate, rcRate, rcExpo, superExpoActive));
context.lineTo(rcData - midRc, -canvasHeightScale * this.rcCommandRawToDegreesPerSecond(rcData, rate, rcRate, rcExpo, superExpoActive, deadband));

rcData = rcData + stepWidth;
}
Expand All @@ -48,7 +48,7 @@ var RateCurve = function (useLegacyCurve) {
this.drawLegacyRateCurve = function (rate, rcRate, rcExpo, context, width, height) {
// math magic by englishman
var rateY = height * rcRate;
rateY = rateY + (1 / (1 - ((rateY / height) * rate)))
rateY = rateY + (1 / (1 - ((rateY / height) * rate)));

// draw
context.beginPath();
Expand All @@ -58,13 +58,14 @@ var RateCurve = function (useLegacyCurve) {
}
};

RateCurve.prototype.rcCommandRawToDegreesPerSecond = function (rcData, rate, rcRate, rcExpo, superExpoActive) {
RateCurve.prototype.rcCommandRawToDegreesPerSecond = function (rcData, rate, rcRate, rcExpo, superExpoActive, deadband) {
var angleRate;
if (rate !== undefined && rcRate !== undefined && rcExpo !== undefined) {
if (rcRate > 2) {
rcRate = rcRate + (rcRate - 2) * 14.54;
}
var inputValue = this.rcCommand(rcData, rcRate);

var inputValue = this.rcCommand(rcData, rcRate, deadband);
var maxRc = 500 * rcRate;

var expoPower;
Expand Down Expand Up @@ -98,24 +99,24 @@ RateCurve.prototype.rcCommandRawToDegreesPerSecond = function (rcData, rate, rcR
return angleRate;
};

RateCurve.prototype.getMaxAngularVel = function (rate, rcRate, rcExpo, superExpoActive) {
RateCurve.prototype.getMaxAngularVel = function (rate, rcRate, rcExpo, superExpoActive, deadband) {
var maxAngularVel;
if (!this.useLegacyCurve) {
maxAngularVel = this.rcCommandRawToDegreesPerSecond(maxRc, rate, rcRate, rcExpo, superExpoActive);
maxAngularVel = this.rcCommandRawToDegreesPerSecond(maxRc, rate, rcRate, rcExpo, superExpoActive, deadband);
}

return maxAngularVel;
};

RateCurve.prototype.draw = function (rate, rcRate, rcExpo, superExpoActive, maxAngularVel, context) {
RateCurve.prototype.draw = function (rate, rcRate, rcExpo, superExpoActive, deadband, maxAngularVel, context) {
if (rate !== undefined && rcRate !== undefined && rcExpo !== undefined) {
var height = context.canvas.height;
var width = context.canvas.width;

if (this.useLegacyCurve) {
this.drawLegacyRateCurve(rate, rcRate, rcExpo, context, width, height);
} else {
this.drawRateCurve(rate, rcRate, rcExpo, superExpoActive, maxAngularVel, context, width, height);
this.drawRateCurve(rate, rcRate, rcExpo, superExpoActive, deadband, maxAngularVel, context, width, height);
}
}
};
2 changes: 1 addition & 1 deletion tabs/pid_tuning.html
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@
<th class="derivative" i18n="pidTuningDerivative"></th>
<th class="rc_rate" i18n="pidTuningRcRate"></th>
<th class="rate" i18n="pidTuningRate"></th>
<th class="maxVel" i18n="pidTuningMaxVel"></th>
<th class="new_rates maxVel" i18n="pidTuningMaxVel"></th>
<th class="rc_expo" i18n="pidTuningRcExpo"></th>
</tr>
</table>
Expand Down
44 changes: 28 additions & 16 deletions tabs/pid_tuning.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,13 @@ TABS.pid_tuning.initialize = function (callback) {
promise = MSP.promise(MSPCodes.MSP_BF_CONFIG);
}

return promise;
}).then(function() {
var promise = true;
if (semver.gte(CONFIG.apiVersion, "1.15.0")) {
promise = MSP.promise(MSPCodes.MSP_RC_DEADBAND);
}

return promise;
}).then(function() {
$('#content').load("./tabs/pid_tuning.html", process_html);
Expand Down Expand Up @@ -453,18 +460,18 @@ TABS.pid_tuning.initialize = function (callback) {

self.rateCurve = new RateCurve(useLegacyCurve);

function printMaxAngularVel(rate, rcRate, rcExpo, useSuperExpo, maxAngularVelElement) {
var maxAngularVel = self.rateCurve.getMaxAngularVel(rate, rcRate, rcExpo, useSuperExpo).toFixed(0);
function printMaxAngularVel(rate, rcRate, rcExpo, useSuperExpo, deadband, maxAngularVelElement) {
var maxAngularVel = self.rateCurve.getMaxAngularVel(rate, rcRate, rcExpo, useSuperExpo, deadband).toFixed(0);
maxAngularVelElement.text(maxAngularVel);

return maxAngularVel;
}

function drawCurve(rate, rcRate, rcExpo, useSuperExpo, maxAngularVel, colour, yOffset, context) {
function drawCurve(rate, rcRate, rcExpo, useSuperExpo, maxAngularVel, deadband, colour, yOffset, context) {
context.save();
context.strokeStyle = colour;
context.translate(0, yOffset);
self.rateCurve.draw(rate, rcRate, rcExpo, useSuperExpo, maxAngularVel, context);
self.rateCurve.draw(rate, rcRate, rcExpo, useSuperExpo, maxAngularVel, deadband, context);
context.restore();
}

Expand All @@ -485,7 +492,9 @@ TABS.pid_tuning.initialize = function (callback) {
rc_rate_yaw: RC_tuning.rcYawRate,
rc_expo: RC_tuning.RC_EXPO,
rc_yaw_expo: RC_tuning.RC_YAW_EXPO,
superexpo: BF_CONFIG.features.isEnabled('SUPEREXPO_RATES')
superexpo: BF_CONFIG.features.isEnabled('SUPEREXPO_RATES'),
deadband: RC_deadband.deadband,
yawDeadband: RC_deadband.yaw_deadband
};

if (semver.lt(CONFIG.apiVersion, "1.7.0")) {
Expand Down Expand Up @@ -717,22 +726,25 @@ TABS.pid_tuning.initialize = function (callback) {
var curveHeight = rcCurveElement.height;
var curveWidth = rcCurveElement.width;

var maxAngularVel = Math.max(
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.yaw_rate, self.currentRates.rc_rate_yaw, self.currentRates.rc_yaw_expo, self.currentRates.superexpo, maxAngularVelYawElement));

curveContext.clearRect(0, 0, curveWidth, curveHeight);

var maxAngularVel;
if (!useLegacyCurve) {
maxAngularVel = Math.max(
printMaxAngularVel(self.currentRates.roll_rate, self.currentRates.rc_rate, self.currentRates.rc_expo, self.currentRates.superexpo, self.currentRates.deadband, maxAngularVelRollElement),
printMaxAngularVel(self.currentRates.pitch_rate, self.currentRates.rc_rate, self.currentRates.rc_expo, self.currentRates.superexpo, self.currentRates.deadband, maxAngularVelPitchElement),
printMaxAngularVel(self.currentRates.yaw_rate, self.currentRates.rc_rate_yaw, self.currentRates.rc_yaw_expo, self.currentRates.superexpo, self.currentRates.yawDeadband, maxAngularVelYawElement));

drawAxes(curveContext, curveWidth, curveHeight, (curveHeight / 2) / maxAngularVel * 360);
} else {
maxAngularVel = 0;
}

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.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.roll_rate, self.currentRates.rc_rate, self.currentRates.rc_expo, self.currentRates.superexpo, self.currentRates.deadband, maxAngularVel, '#ff0000', 0, curveContext);
drawCurve(self.currentRates.pitch_rate, self.currentRates.rc_rate, self.currentRates.rc_expo, self.currentRates.superexpo, self.currentRates.deadband, maxAngularVel, '#00ff00', -4, curveContext);
drawCurve(self.currentRates.yaw_rate, self.currentRates.rc_rate_yaw, self.currentRates.rc_yaw_expo, self.currentRates.superexpo, self.currentRates.yawDeadband, maxAngularVel, '#0000ff', 4, curveContext);

updateNeeded = false;
}
Expand Down Expand Up @@ -904,9 +916,9 @@ TABS.pid_tuning.renderModel = function () {
if (RC.channels[0] && RC.channels[1] && RC.channels[2]) {
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.superexpo),
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.superexpo);
var roll = delta * this.rateCurve.rcCommandRawToDegreesPerSecond(RC.channels[0], this.currentRates.roll_rate, this.currentRates.rc_rate, this.currentRates.rc_expo, this.currentRates.superexpo, this.currentRates.deadband),
pitch = delta * this.rateCurve.rcCommandRawToDegreesPerSecond(RC.channels[1], this.currentRates.pitch_rate, this.currentRates.rc_rate, this.currentRates.rc_expo, this.currentRates.superexpo, this.currentRates.deadband),
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.currentRates.yawDeadband);

this.model.rotateBy(-degToRad(pitch), -degToRad(yaw), -degToRad(roll));
}
Expand Down
21 changes: 16 additions & 5 deletions tabs/receiver.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
'use strict';

TABS.receiver = {
rateChartHeight: 117
rateChartHeight: 117,
useSuperExpo: false,
deadband: 0,
yawDeadband: 0
};

TABS.receiver.initialize = function (callback) {
Expand Down Expand Up @@ -64,6 +67,14 @@ TABS.receiver.initialize = function (callback) {
} else {
$('.deadband input[name="yaw_deadband"]').val(RC_deadband.yaw_deadband);
$('.deadband input[name="deadband"]').val(RC_deadband.deadband);

$('.deadband input[name="deadband"]').change(function () {
this.deadband = parseInt($(this).val());
}).change();
$('.deadband input[name="yaw_deadband"]').change(function () {
this.yawDeadband = parseInt($(this).val());
}).change();

}

// generate bars
Expand Down Expand Up @@ -400,7 +411,7 @@ TABS.receiver.initModelPreview = function () {
this.model = new Model($('.model_preview'), $('.model_preview canvas'));

this.useSuperExpo = false;
if (CONFIG.flightControllerIdentifier === 'BTFL' && semver.gte(CONFIG.flightControllerVersion, '2.8.0')) {
if (semver.gte(CONFIG.flightControllerVersion, '2.8.0')) {
this.useSuperExpo = BF_CONFIG.features.isEnabled('SUPEREXPO_RATES');
}

Expand All @@ -417,9 +428,9 @@ TABS.receiver.renderModel = function () {
if (RC.channels[0] && RC.channels[1] && RC.channels[2]) {
var delta = this.clock.getDelta();

var roll = delta * this.rateCurve.rcCommandRawToDegreesPerSecond(RC.channels[0], RC_tuning.roll_rate, RC_tuning.RC_RATE, RC_tuning.RC_EXPO, this.useSuperExpo),
pitch = delta * this.rateCurve.rcCommandRawToDegreesPerSecond(RC.channels[1], RC_tuning.pitch_rate, RC_tuning.RC_RATE, RC_tuning.RC_EXPO, this.useSuperExpo),
yaw = delta * this.rateCurve.rcCommandRawToDegreesPerSecond(RC.channels[2], RC_tuning.yaw_rate, RC_tuning.rcYawRate, RC_tuning.RC_YAW_EXPO, this.useSuperExpo);
var roll = delta * this.rateCurve.rcCommandRawToDegreesPerSecond(RC.channels[0], RC_tuning.roll_rate, RC_tuning.RC_RATE, RC_tuning.RC_EXPO, this.useSuperExpo, this.deadband),
pitch = delta * this.rateCurve.rcCommandRawToDegreesPerSecond(RC.channels[1], RC_tuning.pitch_rate, RC_tuning.RC_RATE, RC_tuning.RC_EXPO, this.useSuperExpo, this.deadband),
yaw = delta * this.rateCurve.rcCommandRawToDegreesPerSecond(RC.channels[2], RC_tuning.yaw_rate, RC_tuning.rcYawRate, RC_tuning.RC_YAW_EXPO, this.useSuperExpo, this.yawDeadband);

this.model.rotateBy(-degToRad(pitch), -degToRad(yaw), -degToRad(roll));
}
Expand Down

0 comments on commit 6d92789

Please sign in to comment.