robot.json neue Marker einfügen
This commit is contained in:
@@ -431,11 +431,16 @@ function initBoard() {
|
|||||||
result.innerHTML = `<span style="color:#f87171">❌ ${data.error ?? `HTTP ${r.status}`}</span>`; return;
|
result.innerHTML = `<span style="color:#f87171">❌ ${data.error ?? `HTTP ${r.status}`}</span>`; return;
|
||||||
}
|
}
|
||||||
if (data.numChanged === 0) {
|
if (data.numChanged === 0) {
|
||||||
result.innerHTML = '<span style="color:#555b6e">Keine Marker im Z-Bereich gefunden.</span>'; return;
|
result.innerHTML = '<span style="color:#555b6e">Keine Marker im Z-Bereich gefunden (weder in robot.json noch im letzten 3b-Run).</span>'; return;
|
||||||
}
|
}
|
||||||
const moved = data.changes.filter(c => c.oldLink !== c.newLink).length;
|
const added = data.changes.filter(c => c.action === 'added').length;
|
||||||
result.innerHTML = `<span style="color:#22c55e">✅ ${data.numChanged} Marker geändert` +
|
const moved = data.changes.filter(c => c.action === 'updated' && c.oldLink !== c.newLink).length;
|
||||||
(moved ? `, ${moved} verschoben` : '') + `.</span>` +
|
const updated = data.changes.filter(c => c.action === 'updated').length - moved;
|
||||||
|
const parts = [];
|
||||||
|
if (added) parts.push(`${added} neu hinzugefügt`);
|
||||||
|
if (moved) parts.push(`${moved} verschoben`);
|
||||||
|
if (updated) parts.push(`${updated} aktualisiert`);
|
||||||
|
result.innerHTML = `<span style="color:#22c55e">✅ ${data.numChanged} Marker: ${parts.join(', ')}.</span>` +
|
||||||
` IDs: ${data.changes.map(c => c.markerId).join(', ')}`;
|
` IDs: ${data.changes.map(c => c.markerId).join(', ')}`;
|
||||||
loadBoardTable();
|
loadBoardTable();
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
|||||||
@@ -23,31 +23,32 @@ async function writeRobot(robotPath, data) {
|
|||||||
* Weist allen Markern, deren z-Position (mm) zwischen zMin und zMax liegt,
|
* Weist allen Markern, deren z-Position (mm) zwischen zMin und zMax liegt,
|
||||||
* das angegebene Set und/oder den angegebenen Link zu.
|
* das angegebene Set und/oder den angegebenen Link zu.
|
||||||
*
|
*
|
||||||
* - set (optional): Setzt den set-Wert des Markers.
|
* - set (optional): Setzt den set-Wert des Markers.
|
||||||
* - link (optional): Verschiebt den Marker in diesen Link (wird ggf. angelegt).
|
* - link (optional): Verschiebt den Marker in diesen Link (wird ggf. angelegt).
|
||||||
|
* - extraMarkers (optional): Triangulierte Marker aus aruco_marker_poses.json –
|
||||||
|
* werden als neue Einträge in robot.json hinzugefügt,
|
||||||
|
* wenn sie noch nicht vorhanden sind.
|
||||||
*
|
*
|
||||||
* Gibt { numChanged, changes[] } zurück.
|
* Gibt { numChanged, changes[] } zurück.
|
||||||
* changes[]: { markerId, oldLink, newLink, oldSet, newSet }
|
* changes[]: { markerId, action, oldLink, newLink, oldSet, newSet }
|
||||||
|
* action: 'updated' | 'added'
|
||||||
*/
|
*/
|
||||||
export async function assignByZRange(robotPath, { zMin, zMax, set, link }) {
|
export async function assignByZRange(robotPath, { zMin, zMax, set, link, extraMarkers = [] }) {
|
||||||
const robot = await readRobot(robotPath);
|
const robot = await readRobot(robotPath);
|
||||||
const links = robot.links ?? {};
|
const links = robot.links ?? {};
|
||||||
const changes = [];
|
const changes = [];
|
||||||
|
|
||||||
// Snapshot aller Marker (mit aktuellem Link-Name) – vor der Mutation
|
const zLo = Number(zMin);
|
||||||
|
const zHi = Number(zMax);
|
||||||
|
|
||||||
|
// ── Teil 1: Bestehende robot.json-Marker aktualisieren / verschieben ──────────
|
||||||
const snapshot = [];
|
const snapshot = [];
|
||||||
for (const [linkName, linkData] of Object.entries(links)) {
|
for (const [linkName, linkData] of Object.entries(links)) {
|
||||||
for (const marker of (linkData.markers ?? [])) {
|
for (const marker of (linkData.markers ?? [])) {
|
||||||
if (Array.isArray(marker.position)) {
|
if (Array.isArray(marker.position)) snapshot.push({ id: marker.id, currentLink: linkName });
|
||||||
snapshot.push({ id: marker.id, currentLink: linkName });
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Nur Marker im Z-Fenster bearbeiten
|
|
||||||
const zLo = Number(zMin);
|
|
||||||
const zHi = Number(zMax);
|
|
||||||
|
|
||||||
for (const { id, currentLink } of snapshot) {
|
for (const { id, currentLink } of snapshot) {
|
||||||
const srcLinkData = links[currentLink];
|
const srcLinkData = links[currentLink];
|
||||||
const idx = (srcLinkData?.markers ?? []).findIndex(m => Number(m.id) === id);
|
const idx = (srcLinkData?.markers ?? []).findIndex(m => Number(m.id) === id);
|
||||||
@@ -58,6 +59,7 @@ export async function assignByZRange(robotPath, { zMin, zMax, set, link }) {
|
|||||||
if (z < zLo || z > zHi) continue;
|
if (z < zLo || z > zHi) continue;
|
||||||
|
|
||||||
const change = {
|
const change = {
|
||||||
|
action: 'updated',
|
||||||
markerId: marker.id,
|
markerId: marker.id,
|
||||||
oldLink: currentLink,
|
oldLink: currentLink,
|
||||||
oldSet: marker.set ?? '',
|
oldSet: marker.set ?? '',
|
||||||
@@ -65,20 +67,12 @@ export async function assignByZRange(robotPath, { zMin, zMax, set, link }) {
|
|||||||
newSet: marker.set ?? '',
|
newSet: marker.set ?? '',
|
||||||
};
|
};
|
||||||
|
|
||||||
// Set setzen
|
if (set !== undefined && set !== '') { marker.set = set; change.newSet = set; }
|
||||||
if (set !== undefined && set !== '') {
|
|
||||||
marker.set = set;
|
|
||||||
change.newSet = set;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Link wechseln
|
|
||||||
if (link && link !== currentLink) {
|
if (link && link !== currentLink) {
|
||||||
// Aus altem Link entfernen
|
|
||||||
srcLinkData.markers.splice(idx, 1);
|
srcLinkData.markers.splice(idx, 1);
|
||||||
|
if (!links[link]) links[link] = { markers: [] };
|
||||||
// Ziel-Link anlegen falls noch nicht vorhanden
|
if (!links[link].markers) links[link].markers = [];
|
||||||
if (!links[link]) links[link] = { markers: [] };
|
|
||||||
if (!links[link].markers) links[link].markers = [];
|
|
||||||
links[link].markers.push(marker);
|
links[link].markers.push(marker);
|
||||||
change.newLink = link;
|
change.newLink = link;
|
||||||
}
|
}
|
||||||
@@ -86,6 +80,45 @@ export async function assignByZRange(robotPath, { zMin, zMax, set, link }) {
|
|||||||
changes.push(change);
|
changes.push(change);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ── Teil 2: Neue Marker aus 3b-Triangulation einfügen (noch nicht in robot.json) ──
|
||||||
|
// Diese haben keine Position in robot.json – wir übernehmen die gemessene Position.
|
||||||
|
if (link && extraMarkers.length > 0) {
|
||||||
|
const knownIds = new Set();
|
||||||
|
for (const ld of Object.values(links)) {
|
||||||
|
for (const m of (ld.markers ?? [])) knownIds.add(Number(m.id));
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const em of extraMarkers) {
|
||||||
|
const emId = Number(em.marker_id);
|
||||||
|
const emPos = em.position_mm; // [x_mm, y_mm, z_mm] robot-Koordinaten
|
||||||
|
if (knownIds.has(emId)) continue; // bereits in robot.json (evtl. gerade hinzugefügt)
|
||||||
|
if (!Array.isArray(emPos) || emPos.length < 3) continue;
|
||||||
|
|
||||||
|
const z = Number(emPos[2]);
|
||||||
|
if (z < zLo || z > zHi) continue;
|
||||||
|
|
||||||
|
const newMarker = {
|
||||||
|
id: emId,
|
||||||
|
position: emPos.map(v => Math.round(Number(v) * 100) / 100), // 2 Dezimalstellen
|
||||||
|
};
|
||||||
|
if (set) newMarker.set = set;
|
||||||
|
|
||||||
|
if (!links[link]) links[link] = { markers: [] };
|
||||||
|
if (!links[link].markers) links[link].markers = [];
|
||||||
|
links[link].markers.push(newMarker);
|
||||||
|
knownIds.add(emId);
|
||||||
|
|
||||||
|
changes.push({
|
||||||
|
action: 'added',
|
||||||
|
markerId: emId,
|
||||||
|
oldLink: null,
|
||||||
|
oldSet: '',
|
||||||
|
newLink: link,
|
||||||
|
newSet: set ?? '',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (changes.length > 0) {
|
if (changes.length > 0) {
|
||||||
robot.links = links;
|
robot.links = links;
|
||||||
await writeRobot(robotPath, robot);
|
await writeRobot(robotPath, robot);
|
||||||
|
|||||||
@@ -706,8 +706,23 @@ app.post('/api/robot/assign-by-z', async (req, res) => {
|
|||||||
if (!set && !link) {
|
if (!set && !link) {
|
||||||
return res.status(400).json({ error: 'Mindestens set oder link muss angegeben werden' });
|
return res.status(400).json({ error: 'Mindestens set oder link muss angegeben werden' });
|
||||||
}
|
}
|
||||||
const result = await assignByZRange(ROBOT_JSON, { zMin, zMax, set, link });
|
|
||||||
console.log(`robot/assign-by-z z=[${zMin}..${zMax}] set="${set}" link="${link}" → ${result.numChanged} geändert`);
|
// Triangulierte Marker aus dem letzten Board-Run als Zusatzquelle für
|
||||||
|
// Marker, die noch nicht in robot.json stehen (z.B. neu entdeckte Marker)
|
||||||
|
let extraMarkers = [];
|
||||||
|
try {
|
||||||
|
const latestRun = await findLatestBoardRun();
|
||||||
|
if (latestRun) {
|
||||||
|
const posesPath = path.join(boardDataDir, latestRun, 'aruco_marker_poses.json');
|
||||||
|
const poses = JSON.parse(await fsPromises.readFile(posesPath, 'utf8'));
|
||||||
|
extraMarkers = poses.markers ?? [];
|
||||||
|
}
|
||||||
|
} catch { /* kein 3b-Output vorhanden – nur bestehende robot.json-Marker bearbeiten */ }
|
||||||
|
|
||||||
|
const result = await assignByZRange(ROBOT_JSON, { zMin, zMax, set, link, extraMarkers });
|
||||||
|
const added = result.changes.filter(c => c.action === 'added').length;
|
||||||
|
const updated = result.changes.filter(c => c.action === 'updated').length;
|
||||||
|
console.log(`robot/assign-by-z z=[${zMin}..${zMax}] set="${set}" link="${link}" → ${updated} aktualisiert, ${added} neu (von ${extraMarkers.length} 3b-Markern)`);
|
||||||
return res.json(result);
|
return res.json(result);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error('robot/assign-by-z error:', err);
|
console.error('robot/assign-by-z error:', err);
|
||||||
|
|||||||
Reference in New Issue
Block a user