Files
FTCRoadRunnerRobotics/TeamCode/src/main/assets/tuning/drive-encoder-angular-ramp.html
2023-03-06 22:50:07 -08:00

149 lines
3.9 KiB
HTML

<!doctype html>
<html>
<head>
<title>RR Drive Encoder Angular Ramp Regression</title>
<style>
body {
font-family: Arial, Helvetica, sans-serif;
}
.content {
margin: auto;
}
header {
max-width: 600px;
margin: auto;
}
.bar {
display: flex;
justify-content: space-between;
align-items: center;
}
h1 {
margin-bottom: 0;
}
details, a {
display: block;
margin: 1rem 0 1rem 0;
}
</style>
<script src="/tuning/plotly-2.12.1.min.js"></script>
<!-- https://tom-alexander.github.io/regression-js/ -->
<script src="/tuning/regression-2.0.1.min.js"></script>
<!-- <script src="/tuning/common.js"></script> -->
<script src="common.js"></script>
</head>
<body>
<div class="content">
<header>
<h1>RR Drive Encoder Angular Ramp Regression</h1>
<details></details>
<div id="download"></div>
<p>
<button id="latest">Latest</button>
<input id="browse" type="file" accept="application/json">
</p>
</header>
<div id="rampChart"></div>
<div id="trackWidthChart"></div>
</div>
<script>
function loadRegression(data) {
const leftEncVels = data.leftEncVels.map((vs, i) =>
fixVels(vs.times.slice(0, -1), data.leftEncPositions[i].values.slice(0, -1), vs.values.slice(0, -1)));
const rightEncVels = data.rightEncVels.map((vs, i) =>
fixVels(vs.times.slice(0, -1), data.rightEncPositions[i].values.slice(0, -1), vs.values.slice(0, -1)));
newLinearRegressionChart(
document.getElementById('rampChart'),
[
...leftEncVels.flatMap(vs => vs.values.slice(0, -1).map(v => -v)),
...rightEncVels.flatMap(vs => vs.values.slice(0, -1)),
],
[
...data.leftPowers.flatMap(ps => {
const psNew = ps.values.slice(0, -1).map((p, i) => -p * data.voltages.values[i]);
return psNew.slice(1, -1);
}),
...data.rightPowers.flatMap(ps => {
const psNew = ps.values.slice(0, -1).map((p, i) => p * data.voltages.values[i]);
return psNew.slice(1, -1);
}),
],
{title: 'Ramp Regression', slope: 'kV', intercept: 'kS'}
);
const p = data.angVels.reduce((acc, vsArg) => {
const vs = fixAngVels(vsArg.values).map(v => Math.abs(v));
const maxV = vs.reduce((acc, v) => Math.max(acc, v), 0);
const [accMaxV, _] = acc;
if (maxV >= accMaxV) {
return [maxV, vs];
}
return acc;
}, [0, []]);
const angVels = p[1].slice(1, -1);
newLinearRegressionChart(
document.getElementById('trackWidthChart'),
angVels,
angVels.map((_, i) =>
(leftEncVels.reduce((acc, vs) => acc - vs[i], 0) / data.leftEncVels.length
+ rightEncVels.reduce((acc, vs) => acc + vs[i], 0) / data.rightEncVels.length)
* (data.type === 'mecanum' ? 0.5 : 1)
),
{title: 'Track Width Regression', slope: 'track width', noIntercept: true}
);
}
const latestButton = document.getElementById('latest');
latestButton.addEventListener('click', function() {
fetch('/tuning/angular-ramp/latest.json')
.then(res => {
if (res.ok) {
const filename = res.headers.get('X-Filename');
const a = document.createElement('a');
a.innerText = 'Download';
a.href = `/tuning/angular-ramp/${filename}`;
a.download = `angular-ramp-${filename}`;
const download = document.getElementById('download');
download.innerHTML = '';
download.appendChild(a);
return res.json();
} else {
document.getElementById('trackWidthChart').innerText = 'No data files found';
throw new Error();
}
})
.then(loadRegression)
.catch(console.log.bind(console));
});
const browseInput = document.getElementById('browse');
browseInput.addEventListener('change', function(evt) {
const reader = new FileReader();
reader.onload = function() {
loadRegression(JSON.parse(reader.result.trim()));
};
reader.readAsText(browseInput.files[0]);
});
</script>
</body>
</html>