curves now sending/receiving correctly. Y values are now converted to Int16 values to allow handles to dip below 0
parent
d67cba4c6f
commit
55b2c178e6
|
|
@ -8,6 +8,8 @@ export class CurveEditor {
|
||||||
this.offset = { x: 0, y: 0 };
|
this.offset = { x: 0, y: 0 };
|
||||||
this.pixelsPerSecond = 48;
|
this.pixelsPerSecond = 48;
|
||||||
|
|
||||||
|
this.exportRange = [0, 4095];
|
||||||
|
|
||||||
this.currentTime = timelineLength * this.pixelsPerSecond / 2;
|
this.currentTime = timelineLength * this.pixelsPerSecond / 2;
|
||||||
|
|
||||||
this.motorButtons = {
|
this.motorButtons = {
|
||||||
|
|
@ -40,15 +42,15 @@ export class CurveEditor {
|
||||||
this.panStart = { x: 0, y: 0 };
|
this.panStart = { x: 0, y: 0 };
|
||||||
|
|
||||||
// Default curve
|
// Default curve
|
||||||
// this.setCurves([
|
this.setCurves([
|
||||||
// {
|
{
|
||||||
// startPoint: { x: this.valueToX(0), y: this.valueToY(0) },
|
startPoint: { x: this.valueToX(0), y: this.valueToY(0) },
|
||||||
// startPointHandle: { x: this.valueToX(timelineLength / 2), y: this.valueToY(0.5) },
|
startPointHandle: { x: this.valueToX(timelineLength / 2), y: this.valueToY(0.5) },
|
||||||
// endPointHandle: { x: this.valueToX(timelineLength / 2), y: this.valueToY(-0.5) },
|
endPointHandle: { x: this.valueToX(timelineLength / 2), y: this.valueToY(-0.5) },
|
||||||
// endPoint: { x: this.valueToX(timelineLength), y: this.valueToY(0) }
|
endPoint: { x: this.valueToX(timelineLength), y: this.valueToY(0) }
|
||||||
// }
|
}
|
||||||
// ]);
|
]);
|
||||||
// this.curveSets[this.selectedMotorID] = this.curves;
|
this.curveSets[this.selectedMotorID] = this.curves;
|
||||||
|
|
||||||
// let othercurves = [
|
// let othercurves = [
|
||||||
// {
|
// {
|
||||||
|
|
@ -71,7 +73,7 @@ export class CurveEditor {
|
||||||
// this.curveSets[7] = othercurves;
|
// this.curveSets[7] = othercurves;
|
||||||
|
|
||||||
|
|
||||||
// this.setSelectedMotor(5);
|
this.setSelectedMotor(4);
|
||||||
|
|
||||||
this.initEvents();
|
this.initEvents();
|
||||||
this.draw();
|
this.draw();
|
||||||
|
|
@ -115,10 +117,31 @@ export class CurveEditor {
|
||||||
return (this.canvas.height / 2 - v * (this.canvas.height / 2)) * this.scale + this.offset.y;
|
return (this.canvas.height / 2 - v * (this.canvas.height / 2)) * this.scale + this.offset.y;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Maps pixel value of y axis to -1 to 1 normalised value
|
||||||
yToValue(y) {
|
yToValue(y) {
|
||||||
return ((this.canvas.height / 2 - (y - this.offset.y) / this.scale) / (this.canvas.height / 2));
|
return ((this.canvas.height / 2 - (y - this.offset.y) / this.scale) / (this.canvas.height / 2));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Maps normalised -1 to 1 value to motor range (0, 4095)
|
||||||
|
yToExportRange(y) {
|
||||||
|
const [minOut, maxOut] = this.exportRange;
|
||||||
|
// Normalize y from [-1, 1] to [0, 1]
|
||||||
|
const normalized = (this.yToValue(y) + 1) / 2;
|
||||||
|
// Scale to export range
|
||||||
|
return Math.round(normalized * (maxOut - minOut) + minOut);
|
||||||
|
}
|
||||||
|
|
||||||
|
exportRangeToY(value) {
|
||||||
|
const [minOut, maxOut] = this.exportRange;
|
||||||
|
// Reverse the scaling
|
||||||
|
const normalized = (value - minOut) / (maxOut - minOut);
|
||||||
|
// Convert from [0, 1] back to [-1, 1]
|
||||||
|
const yValue = normalized * 2 - 1;
|
||||||
|
// Apply inverse mapping from value space to editor Y
|
||||||
|
return this.valueToY(yValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
valueToX(t) {
|
valueToX(t) {
|
||||||
return t * this.pixelsPerSecond * this.scale + this.offset.x;
|
return t * this.pixelsPerSecond * this.scale + this.offset.x;
|
||||||
}
|
}
|
||||||
|
|
@ -635,6 +658,8 @@ export class CurveEditor {
|
||||||
curve.startPointHandle.y += deltaY;
|
curve.startPointHandle.y += deltaY;
|
||||||
|
|
||||||
this.dragControlPoint(curve, 'startPointHandle', curve.startPointHandle.x, curve.startPointHandle.y, index);
|
this.dragControlPoint(curve, 'startPointHandle', curve.startPointHandle.x, curve.startPointHandle.y, index);
|
||||||
|
|
||||||
|
console.log(this.yToExportRange(curve.startPoint.y));
|
||||||
} else if (key === 'endPoint') {
|
} else if (key === 'endPoint') {
|
||||||
const oldX = curve.endPoint.x;
|
const oldX = curve.endPoint.x;
|
||||||
const oldY = curve.endPoint.y;
|
const oldY = curve.endPoint.y;
|
||||||
|
|
@ -660,6 +685,7 @@ export class CurveEditor {
|
||||||
this.dragControlPoint(curve, 'endPointHandle', curve.endPointHandle.x, curve.endPointHandle.y, index);
|
this.dragControlPoint(curve, 'endPointHandle', curve.endPointHandle.x, curve.endPointHandle.y, index);
|
||||||
|
|
||||||
const nextCurve = this.curves[index + 1];
|
const nextCurve = this.curves[index + 1];
|
||||||
|
console.log(curve.endPoint.y);
|
||||||
if (nextCurve) {
|
if (nextCurve) {
|
||||||
nextCurve.startPoint.x = curve.endPoint.x;
|
nextCurve.startPoint.x = curve.endPoint.x;
|
||||||
nextCurve.startPoint.y = curve.endPoint.y;
|
nextCurve.startPoint.y = curve.endPoint.y;
|
||||||
|
|
|
||||||
|
|
@ -155,7 +155,7 @@
|
||||||
|
|
||||||
|
|
||||||
<div class="tab-pane fade" id="animation" role="tabpanel" aria-labelledby="animation-tab">
|
<div class="tab-pane fade" id="animation" role="tabpanel" aria-labelledby="animation-tab">
|
||||||
<canvas id="curveCanvas" width="900" height="300"></canvas>
|
<canvas id="curveCanvas" width="900" height="600"></canvas>
|
||||||
<div style="margin-top: 10px; text-align: center;">
|
<div style="margin-top: 10px; text-align: center;">
|
||||||
<input type="range" id="timeSlider" min="0" step="1" style="width: 80%;">
|
<input type="range" id="timeSlider" min="0" step="1" style="width: 80%;">
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
32
script.js
32
script.js
|
|
@ -424,34 +424,34 @@ window.onload = () => {
|
||||||
offset += 1;
|
offset += 1;
|
||||||
const startTime = view.getUint16(offset, true); offset += 2;
|
const startTime = view.getUint16(offset, true); offset += 2;
|
||||||
const endTime = view.getUint16(offset, true); offset += 2;
|
const endTime = view.getUint16(offset, true); offset += 2;
|
||||||
const startPointY = view.getUint16(offset, true); offset += 2;
|
const startPointY = view.getInt16(offset, true); offset += 2;
|
||||||
const startHandleX = view.getUint16(offset, true); offset += 2;
|
const startHandleX = view.getUint16(offset, true); offset += 2;
|
||||||
const startHandleY = view.getUint16(offset, true); offset += 2;
|
const startHandleY = view.getInt16(offset, true); offset += 2;
|
||||||
const endHandleX = view.getUint16(offset, true); offset += 2;
|
const endHandleX = view.getUint16(offset, true); offset += 2;
|
||||||
const endHandleY = view.getUint16(offset, true); offset += 2;
|
const endHandleY = view.getInt16(offset, true); offset += 2;
|
||||||
const endPointY = view.getUint16(offset, true); offset += 2;
|
const endPointY = view.getInt16(offset, true); offset += 2;
|
||||||
|
|
||||||
console.log("RECEIVED VALUES RAW:");
|
console.log("RECEIVED VALUES RAW:");
|
||||||
console.log(startTime, endTime);
|
console.log(startTime, endTime, startPointY, endPointY);
|
||||||
|
|
||||||
const toFloat = v => (v / 65535) * 2 - 1;
|
const toFloat = v => (v / 65535) * 2 - 1;
|
||||||
|
|
||||||
const curve = {
|
const curve = {
|
||||||
startPoint: {
|
startPoint: {
|
||||||
x: startTime,
|
x: startTime,
|
||||||
y: curveEditor.valueToY(toFloat(startPointY))
|
y: curveEditor.exportRangeToY(startPointY)
|
||||||
},
|
},
|
||||||
startPointHandle: {
|
startPointHandle: {
|
||||||
x: startHandleX,
|
x: startHandleX,
|
||||||
y: curveEditor.valueToY(toFloat(startHandleY))
|
y: curveEditor.exportRangeToY(startHandleY)
|
||||||
},
|
},
|
||||||
endPointHandle: {
|
endPointHandle: {
|
||||||
x: endHandleX,
|
x: endHandleX,
|
||||||
y: curveEditor.valueToY(toFloat(endHandleY))
|
y: curveEditor.exportRangeToY(endHandleY)
|
||||||
},
|
},
|
||||||
endPoint: {
|
endPoint: {
|
||||||
x: endTime,
|
x: endTime,
|
||||||
y: curveEditor.valueToY(toFloat(endPointY))
|
y: curveEditor.exportRangeToY(endPointY)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -561,23 +561,27 @@ window.onload = () => {
|
||||||
view.setUint16(offset, curveCount, true); offset += 2;
|
view.setUint16(offset, curveCount, true); offset += 2;
|
||||||
|
|
||||||
// 🔹 Curve segments
|
// 🔹 Curve segments
|
||||||
|
|
||||||
curveSegments.forEach(seg => {
|
curveSegments.forEach(seg => {
|
||||||
view.setUint8(offset++, seg.motorID);
|
view.setUint8(offset++, seg.motorID);
|
||||||
view.setUint16(offset, seg.startTime, true); offset += 2;
|
view.setUint16(offset, seg.startTime, true); offset += 2;
|
||||||
view.setUint16(offset, seg.endTime, true); offset += 2;
|
view.setUint16(offset, seg.endTime, true); offset += 2;
|
||||||
view.setUint16(offset, seg.startPointY, true); offset += 2;
|
view.setInt16(offset, curveEditor.yToExportRange(seg.startPointY), true); offset += 2;
|
||||||
|
|
||||||
|
console.log(curveEditor.yToExportRange(seg.startPointY));
|
||||||
view.setUint16(offset, seg.startHandleX, true); offset += 2;
|
view.setUint16(offset, seg.startHandleX, true); offset += 2;
|
||||||
view.setUint16(offset, seg.startHandleY, true); offset += 2;
|
view.setInt16(offset, curveEditor.yToExportRange(seg.startHandleY), true); offset += 2;
|
||||||
console.log("STARTHANDLEY: " + seg.startHandleY);
|
|
||||||
view.setUint16(offset, seg.endHandleX, true); offset += 2;
|
view.setUint16(offset, seg.endHandleX, true); offset += 2;
|
||||||
view.setUint16(offset, seg.endHandleY, true); offset += 2;
|
view.setInt16(offset, curveEditor.yToExportRange(seg.endHandleY), true); offset += 2;
|
||||||
view.setUint16(offset, seg.endPointY, true); offset += 2;
|
view.setInt16(offset, curveEditor.yToExportRange(seg.endPointY), true); offset += 2;
|
||||||
});
|
});
|
||||||
console.log("🧵 Curve segments packed:", curveSegments.length);
|
console.log("🧵 Curve segments packed:", curveSegments.length);
|
||||||
console.log(curveSegments);
|
console.log(curveSegments);
|
||||||
|
|
||||||
|
|
||||||
// 🔹 Send to ESP32
|
// 🔹 Send to ESP32
|
||||||
const payload = new Uint8Array(buffer);
|
const payload = new Uint8Array(buffer);
|
||||||
|
console.log()
|
||||||
console.log(payload);
|
console.log(payload);
|
||||||
serial.saveFile(payload); // CMD_SAVE_ANIMATION
|
serial.saveFile(payload); // CMD_SAVE_ANIMATION
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue