spin Marker Callibration
This commit is contained in:
@@ -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();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user