spin Marker Callibration

This commit is contained in:
chk
2026-06-15 09:23:21 +02:00
parent 375ee4cf69
commit 15d4175fd1
18 changed files with 1191 additions and 239 deletions

View File

@@ -22,6 +22,7 @@ async function loadPanel(tab, src) {
else if (tab === 'board') initBoard();
else if (tab === 'robot-x-axis') initXAxis();
else if (tab === 'arm1') initArm('arm1');
else if (tab === 'marker') initMarker();
} catch (err) {
document.getElementById('tab-' + tab).innerHTML =
@@ -950,3 +951,163 @@ function initBoard() {
}
});
}
// ── Tab: Marker ───────────────────────────────────────────────────────────────
function initMarker() {
const logEl = document.getElementById('log-marker');
const tableWrap = document.getElementById('marker-table-wrap');
const linkSel = document.getElementById('marker-action-link');
const idSel = document.getElementById('marker-action-id');
const spinLabel = document.getElementById('marker-spin-current');
const resultEl = document.getElementById('marker-action-result');
const frameEl = document.getElementById('marker-viewer-frame');
const ARM_LINKS = ['Arm1', 'Ellbow', 'Arm2', 'Hand', 'Palm', 'FingerA', 'FingerB'];
let _robot = null;
function logM(msg) {
const ts = new Date().toLocaleTimeString('de-CH');
logEl.value += `[${ts}] ${msg}\n`;
logEl.scrollTop = logEl.scrollHeight;
}
// ── Marker-Tabelle rendern ────────────────────────────────────────────────
function renderTable(robot) {
if (!tableWrap) return;
const links = robot?.links ?? {};
const th = (a) => `style="text-align:${a};padding:3px 8px;border-bottom:1px solid #2a2d35;white-space:nowrap;background:#1e293b;color:#555b6e;font-weight:normal"`;
const td = (a, x = '') => `style="padding:2px 8px;border-bottom:1px solid #111418;text-align:${a};white-space:nowrap;${x}"`;
let rows = '';
let total = 0;
for (const linkName of ARM_LINKS) {
const markers = links[linkName]?.markers ?? [];
for (const m of markers) {
total++;
const pos = m.position ? m.position.map(v => Number(v).toFixed(1)).join(', ') : '';
const norm = m.normal ? m.normal.map(v => Number(v).toFixed(2)).join(', ') : '';
rows += `<tr>
<td ${td('left', 'color:#4a9eff')}>${linkName}</td>
<td ${td('right')}>${m.id}</td>
<td ${td('left', 'color:#888')}>${m.name ?? ''}</td>
<td ${td('right')}>${pos}</td>
<td ${td('right', 'color:#aaa')}>${norm}</td>
<td ${td('right')}>${m.size ?? ''}</td>
<td ${td('right', 'color:#f0a500;font-weight:bold')}>${m.spin ?? 0}°</td>
</tr>`;
}
}
if (total === 0) {
tableWrap.innerHTML = '<p style="font-size:12px;color:var(--muted)">Keine Arm-Marker in robot.json eingetragen.</p>';
return;
}
tableWrap.innerHTML = `
<p style="font-size:10px;color:#555b6e;margin-bottom:4px">${total} Marker in Arm-Links</p>
<table style="border-collapse:collapse;font-size:11px;font-family:inherit;width:100%">
<thead><tr>
<th ${th('left')}>Link</th>
<th ${th('right')}>ID</th>
<th ${th('left')}>Name</th>
<th ${th('right')}>Position [x,y,z] mm</th>
<th ${th('right')}>Normal [nx,ny,nz]</th>
<th ${th('right')}>Size mm</th>
<th ${th('right')}>Spin</th>
</tr></thead>
<tbody>${rows}</tbody>
</table>`;
}
// ── Marker-Dropdown für gewählten Link befüllen ───────────────────────────
function updateMarkerDropdown() {
if (!idSel || !_robot) return;
const linkName = linkSel?.value;
const markers = _robot.links?.[linkName]?.markers ?? [];
const prev = idSel.value;
idSel.innerHTML = '<option value=""> wählen </option>' +
markers.map(m => `<option value="${m.id}">${m.id}${m.name ? ' ' + m.name : ''}</option>`).join('');
if (markers.some(m => String(m.id) === prev)) idSel.value = prev;
updateSpinLabel();
}
function updateSpinLabel() {
if (!spinLabel || !_robot) { if (spinLabel) spinLabel.textContent = ''; return; }
const linkName = linkSel?.value;
const markerId = idSel?.value;
if (!markerId) { spinLabel.textContent = ''; return; }
const markers = _robot.links?.[linkName]?.markers ?? [];
const m = markers.find(mm => String(mm.id) === String(markerId));
spinLabel.textContent = m ? `Aktuell: spin = ${m.spin ?? 0}°` : '';
}
// ── Robot laden ───────────────────────────────────────────────────────────
async function loadRobot() {
try {
const r = await fetch('/api/robot');
if (!r.ok) throw new Error(`HTTP ${r.status}`);
_robot = await r.json();
renderTable(_robot);
updateMarkerDropdown();
} catch (err) {
if (tableWrap) tableWrap.innerHTML = `<p style="color:#f87171;font-size:12px">Fehler: ${err}</p>`;
logM(`❌ robot.json konnte nicht geladen werden: ${err}`);
}
}
// ── Spin-Aktion ausführen ─────────────────────────────────────────────────
async function applySpin(delta) {
if (!resultEl) return;
const linkName = linkSel?.value;
const markerId = idSel?.value;
if (!markerId) {
resultEl.innerHTML = '<span style="color:#f87171">⚠ Bitte zuerst einen Marker wählen.</span>';
return;
}
const markers = _robot?.links?.[linkName]?.markers ?? [];
const current = markers.find(m => String(m.id) === String(markerId));
const oldSpin = current?.spin ?? 0;
const newSpin = ((oldSpin + delta) % 360 + 360) % 360;
resultEl.innerHTML = '<span style="color:#555b6e">Speichern …</span>';
try {
const r = await fetch('/api/robot/set-arm-marker-spin', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ linkName, markerId: Number(markerId), spin: newSpin }),
});
const data = await r.json();
if (!r.ok || !data.changed) {
resultEl.innerHTML = `<span style="color:#f87171">❌ ${data.error ?? `HTTP ${r.status}`}</span>`;
return;
}
resultEl.innerHTML =
`<span style="color:#22c55e">✅ ${linkName} #${markerId}: spin ${data.oldSpin}° → ${data.newSpin}°</span>`;
logM(`Spin ${linkName}#${markerId}: ${data.oldSpin}° → ${data.newSpin}°`);
// Lokales Modell aktualisieren
if (current) current.spin = data.newSpin;
updateSpinLabel();
renderTable(_robot);
// Viewer neu laden
if (frameEl?.contentWindow) frameEl.contentWindow.postMessage({ type: 'reload' }, '*');
} catch (err) {
resultEl.innerHTML = `<span style="color:#f87171">❌ ${err}</span>`;
}
}
// ── Event-Listener ────────────────────────────────────────────────────────
document.getElementById('btn-marker-reload')?.addEventListener('click', () => loadRobot());
linkSel?.addEventListener('change', () => updateMarkerDropdown());
idSel?.addEventListener('change', () => updateSpinLabel());
document.getElementById('btn-spin-minus90')?.addEventListener('click', () => applySpin(-90));
document.getElementById('btn-spin-plus90')?.addEventListener('click', () => applySpin(+90));
document.getElementById('btn-spin-180')?.addEventListener('click', () => applySpin(+180));
// Init
loadRobot();
}