IMU Anzeige verbssert

This commit is contained in:
Eskimue
2026-05-28 16:10:01 +02:00
parent e6ab4d7716
commit a6e256c3d0
2 changed files with 119 additions and 67 deletions
+117 -65
View File
@@ -94,50 +94,76 @@
S: <span id="overlay-distance">0,00</span> m
</div>
<div class="c-xhair">
<svg viewBox="-90 -90 180 180" xmlns="http://www.w3.org/2000/svg" width="180" height="180">
<!-- äußerer rotierender Strichelring -->
<circle class="xh-rot" cx="0" cy="0" r="82" fill="none" stroke="rgba(0,255,145,.2)" stroke-width="1" stroke-dasharray="4 10"/>
<!-- mittlerer Ring, Gegenrichtung -->
<circle class="xh-rot-rev" cx="0" cy="0" r="60" fill="none" stroke="rgba(0,255,145,.15)" stroke-width=".75" stroke-dasharray="2 16"/>
<!-- innerer fester Ring -->
<circle cx="0" cy="0" r="16" fill="none" stroke="rgba(0,255,145,.3)" stroke-width=".75"/>
<!-- Kreuzlinien mit Lücke in der Mitte -->
<line x1="-86" y1="0" x2="-19" y2="0" stroke="rgba(0,255,145,.6)" stroke-width="1"/>
<line x1="19" y1="0" x2="86" y2="0" stroke="rgba(0,255,145,.6)" stroke-width="1"/>
<line x1="0" y1="-86" x2="0" y2="-19" stroke="rgba(0,255,145,.6)" stroke-width="1"/>
<line x1="0" y1="19" x2="0" y2="86" stroke="rgba(0,255,145,.6)" stroke-width="1"/>
<!-- Skalenstriche bei r=60 -->
<line x1="-60" y1="-6" x2="-60" y2="6" stroke="rgba(0,255,145,.45)" stroke-width=".75"/>
<line x1="60" y1="-6" x2="60" y2="6" stroke="rgba(0,255,145,.45)" stroke-width=".75"/>
<line x1="-6" y1="-60" x2="6" y2="-60" stroke="rgba(0,255,145,.45)" stroke-width=".75"/>
<line x1="-6" y1="60" x2="6" y2="60" stroke="rgba(0,255,145,.45)" stroke-width=".75"/>
<!-- Skalenstriche bei r=38 -->
<line x1="-38" y1="-3.5" x2="-38" y2="3.5" stroke="rgba(0,255,145,.3)" stroke-width=".5"/>
<line x1="38" y1="-3.5" x2="38" y2="3.5" stroke="rgba(0,255,145,.3)" stroke-width=".5"/>
<line x1="-3.5" y1="-38" x2="3.5" y2="-38" stroke="rgba(0,255,145,.3)" stroke-width=".5"/>
<line x1="-3.5" y1="38" x2="3.5" y2="38" stroke="rgba(0,255,145,.3)" stroke-width=".5"/>
<!-- Eckklammern -->
<path d="M-74,-58 L-74,-74 L-58,-74" fill="none" stroke="rgba(0,255,145,.75)" stroke-width="1.5"/>
<path d="M58,-74 L74,-74 L74,-58" fill="none" stroke="rgba(0,255,145,.75)" stroke-width="1.5"/>
<path d="M-74,58 L-74,74 L-58,74" fill="none" stroke="rgba(0,255,145,.75)" stroke-width="1.5"/>
<path d="M58,74 L74,74 L74,58" fill="none" stroke="rgba(0,255,145,.75)" stroke-width="1.5"/>
<!-- pulsierender Ring -->
<circle class="xh-pulse" cx="0" cy="0" r="6" fill="none" stroke="rgba(0,255,145,.7)" stroke-width="1"/>
<svg viewBox="-110 -110 220 220" xmlns="http://www.w3.org/2000/svg" width="220" height="220">
<!-- outer rotating dashed ring -->
<circle class="xh-rot" cx="0" cy="0" r="103" fill="none" stroke="rgba(0,255,145,.14)" stroke-width="1" stroke-dasharray="4 13"/>
<!-- roll arc (static) r=96, ±60° from top -->
<path d="M -83.1 -48 A 96 96 0 0 1 83.1 -48" fill="none" stroke="rgba(0,255,145,.32)" stroke-width="1.25"/>
<!-- roll tick marks via rotate() -->
<g transform="rotate(0)"> <line x1="0" y1="-96" x2="0" y2="-84" stroke="rgba(0,255,145,.72)" stroke-width="1.5"/></g>
<g transform="rotate(10)"> <line x1="0" y1="-96" x2="0" y2="-89" stroke="rgba(0,255,145,.38)" stroke-width="1"/></g>
<g transform="rotate(-10)"><line x1="0" y1="-96" x2="0" y2="-89" stroke="rgba(0,255,145,.38)" stroke-width="1"/></g>
<g transform="rotate(20)"> <line x1="0" y1="-96" x2="0" y2="-89" stroke="rgba(0,255,145,.38)" stroke-width="1"/></g>
<g transform="rotate(-20)"><line x1="0" y1="-96" x2="0" y2="-89" stroke="rgba(0,255,145,.38)" stroke-width="1"/></g>
<g transform="rotate(30)"> <line x1="0" y1="-96" x2="0" y2="-86" stroke="rgba(0,255,145,.58)" stroke-width="1.25"/></g>
<g transform="rotate(-30)"><line x1="0" y1="-96" x2="0" y2="-86" stroke="rgba(0,255,145,.58)" stroke-width="1.25"/></g>
<g transform="rotate(45)"> <line x1="0" y1="-96" x2="0" y2="-89" stroke="rgba(0,255,145,.32)" stroke-width="1"/></g>
<g transform="rotate(-45)"><line x1="0" y1="-96" x2="0" y2="-89" stroke="rgba(0,255,145,.32)" stroke-width="1"/></g>
<!-- counter-rotating middle ring -->
<circle class="xh-rot-rev" cx="0" cy="0" r="72" fill="none" stroke="rgba(0,255,145,.12)" stroke-width=".75" stroke-dasharray="2 20"/>
<!-- inner fixed ring -->
<circle cx="0" cy="0" r="20" fill="none" stroke="rgba(0,255,145,.25)" stroke-width=".75"/>
<!-- cross lines with center gap -->
<line x1="-107" y1="0" x2="-23" y2="0" stroke="rgba(0,255,145,.55)" stroke-width="1"/>
<line x1="23" y1="0" x2="107" y2="0" stroke="rgba(0,255,145,.55)" stroke-width="1"/>
<line x1="0" y1="-107" x2="0" y2="-23" stroke="rgba(0,255,145,.55)" stroke-width="1"/>
<line x1="0" y1="23" x2="0" y2="107" stroke="rgba(0,255,145,.55)" stroke-width="1"/>
<!-- scale ticks r=72 -->
<line x1="-72" y1="-7" x2="-72" y2="7" stroke="rgba(0,255,145,.38)" stroke-width=".75"/>
<line x1="72" y1="-7" x2="72" y2="7" stroke="rgba(0,255,145,.38)" stroke-width=".75"/>
<line x1="-7" y1="-72" x2="7" y2="-72" stroke="rgba(0,255,145,.38)" stroke-width=".75"/>
<line x1="-7" y1="72" x2="7" y2="72" stroke="rgba(0,255,145,.38)" stroke-width=".75"/>
<!-- scale ticks r=46 -->
<line x1="-46" y1="-4" x2="-46" y2="4" stroke="rgba(0,255,145,.22)" stroke-width=".5"/>
<line x1="46" y1="-4" x2="46" y2="4" stroke="rgba(0,255,145,.22)" stroke-width=".5"/>
<line x1="-4" y1="-46" x2="4" y2="-46" stroke="rgba(0,255,145,.22)" stroke-width=".5"/>
<line x1="-4" y1="46" x2="4" y2="46" stroke="rgba(0,255,145,.22)" stroke-width=".5"/>
<!-- corner brackets -->
<path d="M-90,-72 L-90,-90 L-72,-90" fill="none" stroke="rgba(0,255,145,.72)" stroke-width="1.5"/>
<path d="M72,-90 L90,-90 L90,-72" fill="none" stroke="rgba(0,255,145,.72)" stroke-width="1.5"/>
<path d="M-90,72 L-90,90 L-72,90" fill="none" stroke="rgba(0,255,145,.72)" stroke-width="1.5"/>
<path d="M72,90 L90,90 L90,72" fill="none" stroke="rgba(0,255,145,.72)" stroke-width="1.5"/>
<!-- pulsing center ring -->
<circle class="xh-pulse" cx="0" cy="0" r="7" fill="none" stroke="rgba(0,255,145,.65)" stroke-width="1"/>
<!-- IMU group -->
<g id="imu-horizon-group" opacity="0">
<g id="imu-horizon-frame">
<line id="imu-horizon-main" x1="-28" y1="0" x2="28" y2="0" stroke="rgba(0,255,145,.82)" stroke-width="1.25"/>
<line x1="-9" y1="-9.9" x2="9" y2="-9.9" stroke="rgba(0,255,145,.36)" stroke-width=".9"/>
<line x1="-13" y1="-19.8" x2="13" y2="-19.8" stroke="rgba(0,255,145,.36)" stroke-width=".9"/>
<line x1="-9" y1="9.9" x2="9" y2="9.9" stroke="rgba(0,255,145,.36)" stroke-width=".9"/>
<line x1="-13" y1="19.8" x2="13" y2="19.8" stroke="rgba(0,255,145,.36)" stroke-width=".9"/>
<!-- roll pointer triangle (only rotates, no pitch offset) -->
<g id="imu-roll-pointer">
<polygon points="0,-90 -5.5,-79 5.5,-79" fill="rgba(0,255,145,.88)"/>
</g>
<text id="imu-heading-text" x="0" y="-48" fill="rgba(0,255,145,.78)" font-size="8.5" text-anchor="middle">HDG 0°</text>
<text id="imu-roll-text" x="-56" y="52" fill="rgba(0,255,145,.78)" font-size="8.5" text-anchor="middle">R +0.0°</text>
<text id="imu-pitch-text" x="56" y="52" fill="rgba(0,255,145,.78)" font-size="8.5" text-anchor="middle">P +0.0°</text>
<!-- horizon + pitch ladder (rotates AND translates with pitch) -->
<g id="imu-horizon-frame">
<line x1="-11" y1="-33" x2="11" y2="-33" stroke="rgba(0,255,145,.28)" stroke-width=".9"/>
<line x1="-11" y1="33" x2="11" y2="33" stroke="rgba(0,255,145,.28)" stroke-width=".9"/>
<line x1="-17" y1="-22" x2="17" y2="-22" stroke="rgba(0,255,145,.44)" stroke-width=".9"/>
<line x1="-17" y1="22" x2="17" y2="22" stroke="rgba(0,255,145,.44)" stroke-width=".9"/>
<line x1="-10" y1="-11" x2="10" y2="-11" stroke="rgba(0,255,145,.3)" stroke-width=".85"/>
<line x1="-10" y1="11" x2="10" y2="11" stroke="rgba(0,255,145,.3)" stroke-width=".85"/>
<line id="imu-horizon-main" x1="-40" y1="0" x2="40" y2="0" stroke="rgba(0,255,145,.92)" stroke-width="1.5"/>
<line x1="-40" y1="0" x2="-32" y2="-5" stroke="rgba(0,255,145,.92)" stroke-width="1.5"/>
<line x1="40" y1="0" x2="32" y2="-5" stroke="rgba(0,255,145,.92)" stroke-width="1.5"/>
</g>
<!-- HDG readout with background box -->
<rect x="-27" y="-70" width="54" height="13" fill="rgba(0,15,8,.58)" rx="1"/>
<line x1="-27" y1="-70" x2="27" y2="-70" stroke="rgba(0,255,145,.28)" stroke-width=".5"/>
<text id="imu-heading-text" x="0" y="-61.5" fill="rgba(0,255,145,.9)" font-size="9" text-anchor="middle" letter-spacing="1">HDG 000°</text>
<!-- roll / pitch readouts -->
<text id="imu-roll-text" x="-73" y="76" fill="rgba(0,255,145,.72)" font-size="7.5" text-anchor="middle">R +0.0°</text>
<text id="imu-pitch-text" x="73" y="76" fill="rgba(0,255,145,.72)" font-size="7.5" text-anchor="middle">P +0.0°</text>
</g>
<!-- Mittelpunkt -->
<circle cx="0" cy="0" r="2.5" fill="rgba(0,255,145,.9)"/>
<circle cx="0" cy="0" r="1" fill="rgba(255,255,255,.7)"/>
<!-- center dot -->
<circle cx="0" cy="0" r="3" fill="rgba(0,255,145,.92)"/>
<circle cx="0" cy="0" r="1.2" fill="rgba(255,255,255,.8)"/>
</svg>
</div>
<div class="c-scanlines"></div>
@@ -336,6 +362,7 @@ function normalizeHeadingDeg(value) {
function updateImuOverlaySvg() {
var group = document.getElementById("imu-horizon-group");
var frame = document.getElementById("imu-horizon-frame");
var rollPointer = document.getElementById("imu-roll-pointer");
var headingText = document.getElementById("imu-heading-text");
var rollText = document.getElementById("imu-roll-text");
var pitchText = document.getElementById("imu-pitch-text");
@@ -350,11 +377,14 @@ function updateImuOverlaySvg() {
var rollDeg = Number(imuOverlayState.rollDeg || 0);
var pitchDeg = Number(imuOverlayState.pitchDeg || 0);
var headingDeg = normalizeHeadingDeg(imuOverlayState.yawDeg);
var pitchOffset = Math.max(-26, Math.min(26, pitchDeg * 1.1));
var pitchOffset = Math.max(-55, Math.min(55, pitchDeg * 2.2));
group.setAttribute("opacity", "1");
frame.setAttribute("transform", "rotate(" + (-rollDeg).toFixed(2) + ") translate(0 " + pitchOffset.toFixed(2) + ")");
headingText.textContent = "HDG " + Math.round(headingDeg) + "°";
if (rollPointer) {
rollPointer.setAttribute("transform", "rotate(" + (-rollDeg).toFixed(2) + ")");
}
headingText.textContent = "HDG " + String(Math.round(headingDeg)).padStart(3, "0") + "°";
rollText.textContent = "R " + formatSignedNumber(rollDeg, 1) + "°";
pitchText.textContent = "P " + formatSignedNumber(pitchDeg, 1) + "°";
}
@@ -1076,44 +1106,66 @@ function drawImuHorizonOverlay(context, canvasWidth, canvasHeight, size) {
var cx = canvasWidth / 2;
var cy = canvasHeight / 2;
var unit = size / 180;
var unit = size / 220;
var rollRad = Number(imuOverlayState.rollDeg || 0) * Math.PI / 180;
var pitchOffsetPx = Math.max(-26, Math.min(26, Number(imuOverlayState.pitchDeg || 0) * 0.9 * unit));
var pitchOffsetPx = Math.max(-55, Math.min(55, Number(imuOverlayState.pitchDeg || 0) * 2.2)) * unit;
var headingDeg = normalizeHeadingDeg(imuOverlayState.yawDeg);
var rollDeg = Number(imuOverlayState.rollDeg || 0);
var pitchDeg = Number(imuOverlayState.pitchDeg || 0);
/* roll pointer triangle (only roll, no pitch) */
context.save();
context.translate(cx, cy);
context.rotate(-rollRad);
context.beginPath();
context.moveTo(0, -90 * unit);
context.lineTo(-5.5 * unit, -79 * unit);
context.lineTo(5.5 * unit, -79 * unit);
context.closePath();
context.fillStyle = "rgba(0,255,145,.88)";
context.fill();
context.restore();
/* horizon + pitch ladder */
context.save();
context.translate(cx, cy);
context.rotate(-rollRad);
context.translate(0, pitchOffsetPx);
context.strokeStyle = "rgba(0,255,145,.82)";
context.lineWidth = 1.25 * unit;
context.beginPath();
context.moveTo(-28 * unit, 0);
context.lineTo(28 * unit, 0);
context.stroke();
context.strokeStyle = "rgba(0,255,145,.36)";
context.lineWidth = 0.9 * unit;
[-18, -9, 9, 18].forEach(function(stepDeg) {
var y = stepDeg * 1.1 * unit;
var span = Math.abs(stepDeg) === 18 ? 13 : 9;
[
{ y: -33, span: 11, op: .28 }, { y: 33, span: 11, op: .28 },
{ y: -22, span: 17, op: .44 }, { y: 22, span: 17, op: .44 },
{ y: -11, span: 10, op: .3 }, { y: 11, span: 10, op: .3 }
].forEach(function(pl) {
context.beginPath();
context.moveTo(-span * unit, y);
context.lineTo(span * unit, y);
context.moveTo(-pl.span * unit, pl.y * unit);
context.lineTo(pl.span * unit, pl.y * unit);
context.strokeStyle = "rgba(0,255,145," + pl.op + ")";
context.lineWidth = 0.9 * unit;
context.stroke();
});
context.strokeStyle = "rgba(0,255,145,.92)";
context.lineWidth = 1.5 * unit;
context.beginPath(); context.moveTo(-40 * unit, 0); context.lineTo(40 * unit, 0); context.stroke();
context.beginPath(); context.moveTo(-40 * unit, 0); context.lineTo(-32 * unit, -5 * unit); context.stroke();
context.beginPath(); context.moveTo(40 * unit, 0); context.lineTo(32 * unit, -5 * unit); context.stroke();
context.restore();
/* HDG box + text labels */
context.save();
context.font = (8.5 * unit) + 'px "IBM Plex Mono", "Roboto Mono", monospace';
context.fillStyle = "rgba(0,255,145,.78)";
var bw = 54 * unit, bh = 13 * unit;
context.fillStyle = "rgba(0,15,8,.58)";
context.fillRect(cx - bw / 2, cy - 70 * unit, bw, bh);
context.font = (9 * unit) + 'px "Consolas","Cascadia Mono",monospace';
context.fillStyle = "rgba(0,255,145,.9)";
context.textAlign = "center";
context.textBaseline = "middle";
context.fillText("HDG " + Math.round(headingDeg) + "°", cx, cy - (48 * unit));
context.fillText("R " + formatSignedNumber(imuOverlayState.rollDeg, 1) + "°", cx - (56 * unit), cy + (52 * unit));
context.fillText("P " + formatSignedNumber(imuOverlayState.pitchDeg, 1) + "°", cx + (56 * unit), cy + (52 * unit));
context.fillText("HDG " + String(Math.round(headingDeg)).padStart(3, "0") + "°", cx, cy - 63.5 * unit);
context.font = (7.5 * unit) + 'px "Consolas","Cascadia Mono",monospace';
context.fillStyle = "rgba(0,255,145,.72)";
context.fillText("R " + formatSignedNumber(rollDeg, 1) + "°", cx - 73 * unit, cy + 76 * unit);
context.fillText("P " + formatSignedNumber(pitchDeg, 1) + "°", cx + 73 * unit, cy + 76 * unit);
context.restore();
}
@@ -1263,7 +1315,7 @@ function drawHudOverlayToCanvas(context, canvasWidth, canvasHeight) {
context.fillText(document.getElementById("cam-live-text").textContent, canvasWidth / 2 + (6 * camScale * scaleToCanvas), padding);
context.restore();
drawCrosshairOverlayToCanvas(context, canvasWidth, canvasHeight, 180 * camScale * scaleToCanvas);
drawCrosshairOverlayToCanvas(context, canvasWidth, canvasHeight, 220 * camScale * scaleToCanvas);
drawVignetteAndScanlines(context, canvasWidth, canvasHeight);
}